Showing posts with label jQuery. Show all posts
Showing posts with label jQuery. Show all posts

Monday, January 30, 2012

Testing a jQuery Plugin with ExpectThat and Mocha

A couple of weeks ago, I announced a CoffeeScript/JavaScript assertion library called ExpectThat. In this post, I'll provide a more real-world example of how ExpectThat can be used. For this example, I'll be using the jQuery plugin and tests from one of Josh Bush's posts entitled "Testing jQuery Plugins with Node.js and Jasmine".

The jQuery plugin

The code that follows is a re-write (in CoffeeScript) of the simple jQuery plugin that Josh provided in his post.

This jQuery plugin provides a basic watermark type of feature for an input box.

The specs

Since Josh has already done the work of writing the specs for this jQuery plugin, all that I need to do is port this to CoffeeScript and add in ExpectThat. To mix things up a bit, I've chosen to use Mocha instead of Jasmine (though ExpectThat works just as well for Jasmine). For simplicity, I've combined the spec files from Josh's post.

Apples to apples 

Here's a quick before and after comparison (with both examples in CoffeeScript):

Before ExpectThat:
    describe "when calling placeholder plugin", ->
      it "should show placeholder value", ->
        expect(input.val()).toEqual("foo")
After ExpectThat:
    describe "when calling placeholder plugin", ->
      expectThat -> input.val().should equal "foo"
Josh's tests are already very readable, but by adding ExpectThat, I'm able to eliminate 1 line from every test and allow each to be self-documenting.

An example of the result of running the specs in the browser is shown below:




Wait, what about Node?

"So", you say, "this is great, but Josh's post was all about using the same code and specs from the browser in Node.js". Ah, yes, thanks for reminding me. It's pretty simple to run these same specs in Node.

Here are the steps:

1. Use NPM to install mocha at a global level (i.e. npm install mocha -g) then install jsdom, jquery, and expectThat.mocha at the local level (i.e. npm install <package name>).

2. Create a file called runspecs.coffee with the code shown below and compile it however you choose (i.e. "coffee --compile --output lib/ specs/").


3. Run the tests with a command such as "mocha 'lib/runspecs.js' --reporter spec" and you should see something like the following:
In future posts, I'll show how to do similar testing with other tools such as Jasmine-Node and Zombie.js. To learn more about ExpectThat, get involved, and/or keep an eye on its progress, go to https://github.com/dmohl/expectThat.

Tuesday, November 15, 2011

A Pinch of CoffeeScript Sugar - Part 1

In this series, I plan to point out and provide a few examples of some cool syntactic sugar provided by CoffeeScript. In this post, I'll talk about destructuring assignment and splats.

I've shown how to write a jQuery plugin in CoffeeScript in a previous post. In the following example, I take that simple jQuery plugin and add a little more sugar.

The above example is based on the recommendations defined in the jQuery Plugins/Authoring documentation. There are a couple of interesting aspects of this code.

Line 10 (i.e. [_, args...] = arguments) is using two cool CoffeeScript features. The first is something called destructuring assignment. This feature allows you to take data from arrays or objects and place that data into something more wieldy. In this case, we are taking the JavaScript arguments object, destructuring it, and assigning all of the arguments except the first one to an array named args. This eliminates the need for me to type Array.prototype.slice.call(arguments, 1). If I had not used a splat (i.e ...), this would have assigned only the second argument to args. Note: Destructuring assignment has been added to JavaScript 1.7.

The second thing of interest on this line (which I've already briefly mentioned) is the use of the splat. The splat allows you to easily work with anything that involves a variable number of arguments. Since line 10 potentially involves more than 2 passed arguments, this is a perfect place to use a splat. As I mentioned before, the use of the splat in this case will generate JavaScript to slice the arguments array i.e. Array.prototype.slice.call(arguments, 1).

Lines 11 and 13 also use a splat, but the reasoning behind its use on these lines is slightly different. While this is still related to a varying number of arguments, it has to do with the passing of those arguments to a function rather than retrieval of the additional argument values. The splat in this case will generate JavaScript that uses the Function.apply method.

A little bit of sugar can make things much sweeter (ug...that was bad). I hope you find this post helpful and that you find lots of uses for the described features.

Tuesday, September 13, 2011

Advantages of CoffeeScript When Working with jQuery Templates

Working with jQuery Templates in CoffeeScript is very similar to working with them in JavaScript. However, there are a couple of CoffeeScript features that can make it even easier.

Here's a simple example (based on an example in the jQuery Template documentation):


As you can see, it's pretty similar to its JavaScript counterpart.

How can CoffeeScript make this better?

Enter Heredoc and String Interpolation...

Heredoc: Heredocs allow you to specify multi-line, formatted text. This can be useful when defining the template markup.

With heredocs, the markup from the previous example changes to this:


String Interpolation: CoffeeScript also provides Ruby style string interpolation. Here's an example of the markup after taking advantage of the string interpolation feature (Note: String interpolation only occurs within double-quoted strings and double-quoted heredocs):


Want to see it in action?

Go to http://tinkerbin.com/w0QoscT9, change the JavaScript Format drop down to CoffeeScript, then click the Run button.

Thursday, September 1, 2011

Unit Testing a jQuery Plugin with CoffeeScript and Pavlov

If you search the web, you'll find a handful of good examples of jQuery plugins written in CoffeeScript, but there seems to be few examples of writing unit tests/specs in CoffeeScript. In this post, I'll show a very simple jQuery plugin with Pavlov specs.

Simple Plugin

This plugin simply wraps the jQuery UI dialog (http://jqueryui.com/demos/dialog/).
do ($ = jQuery) ->
  methods = 
    init: (options) ->
      dialogElement = $(options.dialogSelector)
      dialog = dialogElement.dialog autoOpen: false, modal: true, resizable: false 
      $(options.inputSelector).click -> dialog.dialog 'open'
  
  $.fn.simple = (options) -> 
    settings = dialogSelector:'.dialog', inputSelector:'.input'
    if options 
      $.extend settings, options
    methods.init settings
Pavlov Specs

QUnit is a JavaScript testing framework (learn more about it at http://docs.jquery.com/Qunit) and Pavlov (https://github.com/mmonteleone/pavlov) extends QUnit with several features that promote Behavior-Driven Development (BDD). Here's the example:
pavlov.specify "Simple Plugin", ->
  describe "Given default options", -> 
    before -> $(this).simple()
    describe "when executing a click event", ->
      before -> $('.input').click()
      it "it should open the dialog", ->
        assert($('.dialog').parents('.ui-dialog:visible').length).isTrue()
      after ->
        $('.dialog').dialog('close')
    describe "When the click event has not been executed", ->
      it "it should not have an open dialog", ->
        assert($('.dialog').parents('.ui-dialog:visible').length).isFalse()
      after -> 
        $('.dialog').dialog('close')

  describe "Given all custom options", -> 
    before -> 
      $(this).simple dialogSelector:'.customDialog', inputSelector:'.customInput' 
    describe "when executing a click event", ->
      before -> $('.customInput').click()
      it "it should open the custom dialog", ->
        assert($('.customDialog').parents('.ui-dialog:visible').length).isTrue()
      after ->
        $('.customDialog').dialog('close')

  describe "Given only a custom dialogSelector", -> 
    before -> $(this).simple dialogSelector:'.customDialog'
    describe "when executing a click event", ->
      before -> $('.input').click()
      it "it should open the custom dialog", ->
        assert($('.customDialog').parents('.ui-dialog:visible').length).isTrue()
      after ->
        $('.customDialog').dialog('close')

  describe "Given only a custom inputSelector", -> 
    before -> $(this).simple inputSelector:'.customInput' 
    describe "when executing a click event", ->
      before -> $('.customInput').click()
      it "it should open the dialog", ->
        assert($('.dialog').parents('.ui-dialog:visible').length).isTrue()
      after ->
        $('.dialog').dialog('close')
The Output

Once we have this in place and create a simple test runner page, we end up with the standard QUnit output that looks like the following: