Search code examples
javascriptjqueryunit-testingqunitsinon

QUnit/Sinon: testing a function which checks if cookies are enabled


I have the following (simplified) javascript module which uses jQuery Cookie plugin to check if cookies are enabled. If cookies are disabled it warns the user:

var cookiePolicy = (function () {
    var cookiesEnabled = function () {
        return $.cookie('check', 'valid', { expires: 1 }) && $.cookie('check') == 'valid';
    };

    return {
        updateCookiePolicy: function () {
            if (!cookiesEnabled()) {
                $("#cookie-policy").append('<p id="cookie-warning">Cookies are disabled. Some features of this site may not work correctly.</p>');
            }
        }
    };
})();

I have the following unit test:

QUnit.test("When cookies are enabled the cookie policy text remains unchanged", function (assert) {
    sinon.mock($).expects("cookie").once().withExactArgs("check", "valid", { expires: 1 });
    sinon.mock($).expects("cookie").once().withExactArgs("check").returns("valid");

    cookiePolicy.updateCookiePolicy();

    assert.equal(0, $('#cookie-warning').length, "Failed!");
});

The test fails because "cookie is already wrapped". I assume this is because I am mocking $.cookie for both set and read. How can I mock the call to $.cookie for both setting and reading in this test?


Solution

  • Your assumption is correct. Depending on the version of Sinon you're using, you could do something like this:

    // UUT
    var foo = {
        bar: function() {}
    };
    
    // Test setup
    var mock = sinon.mock(foo);
    var expectation = mock.expects('bar').twice();
    expectation.onFirstCall().stub.calledWithExactly('baz');
    expectation.onSecondCall().stub.calledWithExactly('qux');
    
    // Test
    foo.bar('baz');
    foo.bar('qux');
    mock.verify();
    

    BTW, it's strange to use Sinon mocks without using .verify(). Maybe stubs would be a better fit?