Friday, March 27, 2009

JavaScript Unit Testing Frameworks

Not only should you have unit tests for your User Interface & Middle Tier code, but you should also consider unit testing your JavaScript code.

There are several different Unit Testing frameworks made for JavaScript that you have to choose from.

Note: In future posts I will show examples of how to use each of these frameworks… as for now, this is just an introduction to the tools I’ll be covering.

Framework Description
YUI Test

YUI Test is a testing framework for browser-based JavaScript solutions. Using YUI Test, you can easily add unit testing to your JavaScript solutions. While not a direct port from any specific xUnit framework, YUI Test does derive some characteristics fromnUnit and JUnit.

JsUnit JsUnit is a Unit Testing framework for client-side (in-browser) JavaScript. It is essentially a port of JUnit to JavaScript. Also included is a platform for automating the execution of tests on multiple browsers and mutiple machines running different OSs. Its development began in January 2001.
QUnit QUnit is the unit testrunner for the jQuery project. It got promoted to a top-level project in May 2008 to make it easier to use in other projects, with focus on jQuery UI. Every plugin developer can leverage the testsuite to unit test their code.
JSSpec JSSpec is a Javascript BDD (Behavior Driven Development) framework.

Do you already use one of these frameworks? If so, which one do you prefer?

Is there another framework that you like that is better than the above listed?

Please leave a comment with your opinion :) Thanks!

Wednesday, March 25, 2009

ASP.NET MVC Html.RadioButtonList Blues

Recently I upgraded our ASP.NET MVC project from Preview 5 to RC2. At first I thought the Html.RadioButtonList extension was removed completely, but then realized that it was no longer in the main MVC assembly, but was moved to the Futures project (although I don't know why).

The Preview 5 version of the Html.RadioButtonList rendered the following output...

However, once I got my code to compile I went to run my application only to find that it rendered two RadioButtons with no labels! Where did the labels go?

I pulled down the source code for the 1.0 release (just to make sure it wasn't fixed in the RTM as opposed to the RC2) and dove into the extension code. Nowhere did I see the labels being applied in the extension.

//C:\...\MVC-RTM\MVC\src\MvcFutures\Mvc\RadioExtensions.cs
private static string[] RadioButtonListInternal(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, bool usedViewData, IDictionary<string, object> htmlAttributes) {
   if (String.IsNullOrEmpty(name)) {
      throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
   }
   if (selectList == null) {
      throw new ArgumentNullException("selectList");
   }

   // If we haven't already used ViewData to get the entire list of items then we need to
   // use the ViewData-supplied value before using the parameter-supplied value.
   if (!usedViewData) {
      object defaultValue = htmlHelper.ViewData.Eval(name);

      if (defaultValue != null) {
         IEnumerable defaultValues = new[] { defaultValue };
         IEnumerable<string> values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture);
         HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
         List<SelectListItem> newSelectList = new List<SelectListItem>();

         foreach (SelectListItem item in selectList) {
            item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
            newSelectList.Add(item);
         }

         selectList = newSelectList;
      }
   }

   IEnumerable<string> radioButtons = selectList.Select<SelectListItem, string>(item => htmlHelper.RadioButton(name, item.Value, item.Selected, htmlAttributes));

   return radioButtons.ToArray();
}

Next I looked at the Unit Tests for the extesion. I was please to see tests for the RadioButtonList, but was shocked to see that the asserts were verifying html that didn't have any labels applied!

//C:\...\MVC-RTM\MVC\test\MvcFuturesTest\Mvc\Test\RadioExtensionsTest.cs
[TestMethod]
public void RadioButtonListItemSelected() {
   // Arrange
   HtmlHelper htmlHelper = TestHelper.GetHtmlHelper(new ViewDataDictionary());

   // Act
   string[] html = htmlHelper.RadioButtonList("FooList", GetRadioButtonListData(true));

   // Assert
   Assert.AreEqual(@"<input id=""FooList"" name=""FooList"" type=""radio"" value=""foo"" />", html[0]);
   Assert.AreEqual(@"<input id=""FooList"" name=""FooList"" type=""radio"" value=""bar"" />", html[1]);
   Assert.AreEqual(@"<input checked=""checked"" id=""FooList"" name=""FooList"" type=""radio"" value=""baz"" />", html[2]);
}

private static SelectList GetRadioButtonListData(bool selectBaz) {
   List<RadioItem> list = new List<RadioItem>();
   list.Add(new RadioItem { Text = "text-foo", Value = "foo" });
   list.Add(new RadioItem { Text = "text-bar", Value = "bar" });
   list.Add(new RadioItem { Text = "text-baz", Value = "baz" });
   return new SelectList(list, "value", "TEXT", selectBaz ? "baz" : "something-else");
}

private class RadioItem {
   public string Text {
      get;
      set;
   }

   public string Value {
      get;
      set;
   }
}  

Where does that leave us? I guess using the Futures Html.RadioButtonList isn't all that helpful after all. So, instead I decided to loop through my DataSource and create individual Html.RadioButton and Label combinations.

<!-- After using and looking at the code for the Html.RadioButtonList in the ASP.NET MVC 1.0 RTM codebase, I'm not sure how it is supposed to be useful. It only outputs the actual input radio button and doesn't render any corresponding labels. To get around this I ended up writing a foreach creating individual Html.RadioButton and labels -->
<% 
var radioButtonList = new SelectList(new List<ListItem> {
   new ListItem { Text = "Current", Value="false", Selected=true }, 
   new ListItem { Text = "Other", Value="true"}}, "Value", "Text", "false");
var htmlAttributes = new Dictionary<string, object> { 
   { "class", "radioButtonList" },
   { "onclick", "if(eval(this.value)) { $('#tblDate').show('slow'); } else { $('#tblDate').hide('slow'); }" }
};
foreach (var radiobutton in radioButtonList) { %>
   <%=Html.RadioButton("rblDate", radiobutton.Value, radiobutton.Selected, htmlAttributes)%>
   <label><%=radiobutton.Text%></label>
<% } %>   

Monday, March 23, 2009

CodeStock 2009 Call for Speakers

CodeStock 2009 is just around the corner.

CodeStock is a .NET developer's conference held in Knoxville, TN on June 26-27, 2009.

This is a great opportunity to hear lots of great speakers and collaborate with other geeks for only $25!

If you are at all interested in speaking at CodeStock then I encourage you to submit your abstracts today!. You have until March 30th to submit yourself as a speaker.

Here is a snippet from their website...

CodeStock 2009 is going to be held on June 26th and 27th. Registration will open on or after March 31st and the cost for CodeStock will stay the same as 2008 - $25.

CodeStock will be held on June 26th and 27th, 2009 in Knoxville, TN. Speaker applications are due March 30th. Speaker selections will be announced on or before May 15th.

Wednesday, March 18, 2009

ASP.NET MVC 1.0 RTM, Source, Docs, Videos, and More

For all of you who've been waiting long and hard, the time has finally come... ASP.NET MVC has been released!

You can download the 1.0 release from the Microsoft Downloads site.

You can also view the documentation for ASP.NET MVC on the MSDN Microsoft Developer Network.

Updated: If you are the curious type or just want to see how something works, then you can download the full source code (including all the tests and the futures project) from codeplex.

For many of you this means you finally might be able to convince your boss to use ASP.NET MVC in one of your production applications :)

Thanks to everyone involved in making ASP.NET MVC a reality!

If you would like a good start on learning the ASP.NET MVC, then I recommend checking out...

Thursday, March 12, 2009

Twitter Stats using Greasemonkey & jQuery

I wrote a simple Greasemonkey script that uses jQuery to read the Following, Followers, and Updates count from your Twitter Home page and displays them in the title of your Firefox tab (as seen in the image to the left).

Since I enjoy using jQuery, I tend to use this script as the starting point for several other of my custom Greasemoney scripts.

You can install the following Greasemonkey script from the userscripts.org website.

// ==UserScript==
// @name           Twitter Stats
// @namespace      http://zi.ma/webdev
// @description    Display your Twitter Stats in the Tab Title
// @include        http://twitter.com/home
// ==/UserScript==

//BEGIN - Load jQueryhttp://is.gd/j6G
var GM_JQ = document.createElement('script');
GM_JQ.src = 'http://jquery.com/src/jquery-latest.js';
GM_JQ.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(GM_JQ);

function GM_wait() {
   if (typeof unsafeWindow.jQuery == 'undefined') { window.setTimeout(GM_wait,100); }
   else { $ = unsafeWindow.jQuery; letsJQuery(); }
}
GM_wait();
//END - Load jQuery http://is.gd/j6G
    
// All your GM code must be inside this function
function letsJQuery() {
   unsafeWindow.console.log('BEGIN letsJQuery'); 

   var followers = $("#follower_count").html();
   var following = $("#following_count").html();
   var updates = $("#update_count").html();
   document.title = 'Twitter / Ing: ' + $.trim(following) + '; Ers: ' + $.trim(followers); 
 
   unsafeWindow.console.log('END letsJQuery');
}

unsafeWindow.alert = function alert(message) {
   //do nothing
}; 

The above script first loads the jQuery framework and then retrieves the Twitter values.

You might notice the use of unsafeWindow.console.log('Your message here...');

I mainly used this to help debug the script.

You can find these messages displayed in your Firebug console.

Once you have installed the script, it could be easily be coupled with the ReloadEvery firefox extension so that you can sit back and watch your stats update to your heart's content :)

Monday, March 09, 2009

Screencast: Dive Into ASP.NET MVC RC2


Dive into ASP.NET MVC RC2 from Elijah Manor on Vimeo.

Last week I gave a presentation at the Compuware Thought Leadership meeting entitled, "Dive Into ASP.NET MVC RC2".

Several people asked me about the presentaiton and were interested in the material. However, the meeting was closed to only Compuware employees. So, I thought I would make a screencast of the talk.

The screencast covers the following:

  1. An quick overview of what is "MVC"
  2. Pros & Cons comparing ASP.NET MVC to ASP.NET WebForms
  3. Answers to questions you might be thinking
  4. Review of new features since the beta release
  5. Demonstration & code review of a demo app using ASP.NET MVC RC2

Note: This is my first screencast, so please be patient with me :)

You can download the sample ASP.NET MVC RC2 application demonstrated in the screencast... PetShop5Rc2.zip