Matthew Roach

Basic jQuery testing with Jasmine – Spies – Part 2

In my previous jQuery testing with Jasmine I went over the basic’s of getting everything set up and even getting a few tests running, and as these couple of post’s are about testing a jQuery plug-in rather than standard JavaScript we are using jasmine-jquery. Couple of reason I am using jasmine-jquery is mainly I am testing a jQuery plug-in, so that makes sense, and as my plug-in has click events in it we can test these events.

The examples in the post relate to the testing of my simple jQuery tabs plug-in (fluabs) which is available on GitHub with all the test’s.

Following on from the previous post, we tested the plug-in was set up and initatied on the fixture we loaded, and the default actions of the plug-in had happened. In this case only the one content area should be shown.

Now we know the plug-in can do more than that, and it should do more than that. We need to know test against the click events that the plug-in should of bound to the element to hide/show the relevant tabs.

For me I set up another describe block for testing events, happily name fluabs events:

describe('fluabs events', function() { });

In here I will test the plug-ins events for clicking on the tabs.

Test One

The first test I preform is to check if any of the tabs have a click event bound to them. As the plug-in does the event binding we can test if the event has been bound properly.

My test looks like:

  it("click tab", function() {
    var spyEvent = spyOnEvent('#tabs li a', 'click' );
    $('#tabs li a').click();
    expect( 'click' ).toHaveBeenTriggeredOn( '#tabs li a' );
    expect( spyEvent ).toHaveBeenTriggered();

Ok, so let’s take a look at what this test is doing. This test is the basic example that is shown on the jasmine-jquery readme on their github page. I have modified it to work with the fluabs plug-in.

First we are assigned a spyOnEvent() function that has the element I want to perform the event on and the type of event I want to perform, to the variable spyEvent, we then trigger the event using the jQuery trigger function.
The next two lines are the test’s check a click event has happened on the element we have specified. So we expect a click to happen on the a inside the li under the #tabs element, and the second expect is to check that our spyOnEvent has been triggered

This first test is a bit open ended as all its checking is if a click event has been fired, so the plug-in could be binding the click event to the correct element but does not me the click event is working properly, we will do that next. But this is a good test to ensure we have go our event bound properly.

Test Two

The second test I preform is to check if the click event we bind in the plug-in are bound properly and do what they are supposed to do.

My test for this looks like:

it("click tab 2 - hide all tabs except tab 2, tab 2 to have class current", function() {
   var spyEvent = spyOnEvent('#tabs li a[href=#two]', 'click');
    $('#tabs li a[href=#two]').click();
    expect( 'click' ).toHaveBeenTriggeredOn( '#tabs li a[href=#two]' );
    expect( spyEvent ).toHaveBeenTriggered();
    expect( $('[data-tab="#two"]') ).toBe( ':visible' );
    expect( $('#tabs li a[href=#two]') ).toHaveClass( 'current' );
    expect( $('[data-tab="#one"]') ).not.toBe( ':visible' );
    expect( $('[data-tab="#three"]') ).not.toBe( ':visible' );

You will see some similarities to the first test, as we are again testing the click event, but this time we are not testing just for a click event to happen, we are testing the click event on a certain element and if it has performed the click events functions as the plug-in should be set up to do.

This means with the spyOnEvent() function will have to be more specific on the element we wish to target the click event on, so that the actual plug-in click event happens.

As this a tabs plug-in, and the way I have wrote it is, that the href part of the tabs unordered list elements is used to target the div within the .tabcontent div. The tabs list looks like:

  <ul id="tabs">
    <li><a href="#one" class="current">Tab One</a></li>
    <li><a href="#two">Tab Two</a></li>
    <li><a href="#three">Tab Three</a></li>

and my tabs content div looks like:

  <div class="tabcontent">
    <div class="tab" data-tab="#one">
        This is some sample tab content in <strong>Tab One</strong>
    <div class="tab" data-tab="#three">
        This is some sample tab content in <strong>Tab Three</strong>
    <div class="tab"data-tab="#two">
        This is some sample tab content in <strong>Tab Two</strong>

So the href part corresponds with the data-tab attribute of a div with the .tabcontent div

With that all sorted, back to the test. We have set up the click event to happen on the second tab like so :

$('#tabs li a[href=#two]').click();

Then the follow expects check that the element has been triggered on, and the spyEvent was triggered, then we check to make sure the elements on the page have changed based on what the plug-in is supposed to do.

We expected the data-tab=”#two” to be visible as we click the link with href of #two, and the plug-in adds a class of current to the a element, so we check to ensure this has happened.

Now we have checked the relevant tab is visible and the link we triggered the event on has the right class, we need to check to make sure none of the other tabcontent div’s are showing we check them to make sure they are not visible.