views:

265

answers:

3

Hi all:

Just a quick question... I currently have the following jQuery code with a selector in it.

var ID = "idControl"
function doesTreeViewExist()
{
    if($('#' + ID).length == 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

I was wondering how do I write the test to test the selector using QUnit? More specifically, I'm having trouble coming up with the syntax/code.

EDIT:

Ok, suppose now I want to mock the selector call instead because I cannot get access to the actual website. I'm using JsTestDriver as my testing tool, which means I cannot touch the browser the tests are running in (else the test runs will stop). What about in such situation? How can I possibly test the code?

Thanks.

+4  A: 

The function you post, can be heavily simplified:

var ID = "idControl";
function doesTreeViewExist() {
  return !!$('#' + ID).length;
}

Using the !! construct (double bitwise NOT), to convert the length property to Boolean, it will return false only when length is zero.

Speaking about qUnit, you can easily setup a simple test like this:

test("Your selector test", function() {
  ok($('#idControl').length > 0, "idControl exists");
  // or simply
  ok($('#idControl').length, "idControl exists");
});

The ok function does a boolean assertion, equivalent to JUnit's assertTrue.

CMS
+1  A: 

I test selectors manually, then pass them to code that uses them. I can then unit test the code that uses them. If you want to just test a selector, you need access to the HTML it affects. Your test could include HTML to target, something like:

test("selector works", function() {
    var html = $('<input type="select"><option value=0/></input');

    var result = $('option', html);

    ok(result.count() == 1);
});

But I don't do that... I put my selectors at the edge of the code so I can get to them quickly and step through them under the debugger. I'll have a simple class whose properties are those selectors. Then I'll mock/stub that simple class, so I can write code for everything dependent on those selectors. The reason I don't test my selectors is because the HTML they target is generated by ASP.NET code, and hard to get to from a javascript test. But I can wrap them in a Humble Object ("http://xunitpatterns.com/Humble Object.html") then test code that depends on that humble object. Here's a simple wrapper class that I can replace with test doubles:

var createSelectWidget = function(rootSelector)
{
    return {
        userText : $('span', rootSelector),
        inputList : $('option', rootSelector),
    };
}

Whatever dependency injection pattern you use, you can then stub it like below. Suppose my widget has a select input to read the value of, and a span I want to write some results to:

var createSelectWidgetStub = function()
{
    return {
        userText : { text = function() {}},
        inputList : { val = function() {}},
    };
}

I can then pass around this stub in tests where I want to isolate the dependency but don't care about interactions with that dependency. When I want to verify interactions with the dependency, I can mock it with JSMock. Suppose I want to verify interactions with the input list, I would prepare a stub with the one element mock'd:

var selectMock = createSelectWidgetStub();
selectMock.inputList = mc.createMock(selectMock.inputList);
Frank Schwieterman
`<input type="select" />` is not valid, you should use a `<select>` element, also on your first example `count()` is not defined, I think you want to use `size()` but I would recommend you to simply use the `length` property.
CMS
This is a nice idea. But it sounds like something that a framework would handle it for me instead of me doing it manually. But if the use of other framework is not allowed, this would definitely be an approach.
BeraCim
CMS- yeah I was just hypothesizing some HTML. That wasn't the point of the question.
Frank Schwieterman
BeraCim- If you find a framework that helps this along let me know. I use the QUnit test framework and the JSMock library, so I am using existing tools where available.
Frank Schwieterman
+1  A: 

I used Jack and successfully mocked the jquery call and returned a custom length and expected result.

Something like:

jack (function() {
    jack.expect("$").exactly("1").withArguments("#" + ID).returnValue( {length:0} );
    doesTreeViewExist()
    assertEquals(false, result);
});

I have also managed to supply a DOM structure to satisfy the jquery call, as I'm using one of JsTestDriver's built-in function HtmlDoc. Something like:

/*:DOC += <span id="idControl"></span> */

or simply create a DOM sturcture without the specified id to get the false statement.

HTH.

BeraCim