javascriptunit-testingsinonqunit

Testing function which checks if cookies are enabled with Qunit


I have the following function which checks if cookies are enabled in a user's browser:

CookiesEnabled: function() {
    var cookieEnabled = navigator.cookieEnabled;
    if (!cookieEnabled) {
        document.cookie = "test_cookie";
        cookieEnabled = document.cookie.indexOf("test_cookie") != -1;
    }

    return cookieEnabled;
},

I want to unit test that this works using Sinon/Qunit but am unsure of how to approach this properly as I am not very experienced using Sinon or QUnit. Here is my attempt at putting together a test:

QUnit.test("CookiesEnabled - returns true if user has enabled cookies in their browser", function (assert) {
    sinon.stub(CookieHelper, "CookiesEnabled")
         .callsFake(function () {});

    var result = CookieHelper.CookiesEnabled();

    Assert.Equal(result, true);

    CookieHelper.CookiesEnabled.restore();
});

Please can anyone point me in the right direction for unit testing this method using Qunit and Sinon? Thank you.

UPDATED ATTEMPT:

QUnit.test("CookiesEnabled - returns true if user has enabled cookies in their browser", function (assert) {
    sinon.stub(navigator, "cookieEnabled").callsFake(function () {
        return true;
    });

    var result = CookieHelper.CookiesEnabled();

    assert.equal(result, true);

});

Solution

  • As mentioned, window.navigator is readonly. There are some things you could try to fake out the browser, but really, you should just inject the properties you're interested in for the function to use. This way you can override the browser setting or test it! Notice the addition of two arguments (since you also need to bypass your double-checking of cookie setting).

    The additional flag argument is a boolean that essentially tells the function what the value of cookieEnabled should be (versus using navigator.cookieEnabled). However, if that parameter is missing, the code will use the browser setting. In other words, it's a way to "inject" the value you want, very useful in testing. This isn't ideal, but not much else you can without a lot more work and mocking (using a headless browser with cookies disabled).

    Here's a jsfiddle of this working: https://jsfiddle.net/e5mtpboy/

    CookiesEnabled: function(flag, bypassTest) {
        var cookieEnabled = typeof(flag) === 'boolean' ? flag : navigator.cookieEnabled;
        if (!cookieEnabled && !bypassTest) {
            document.cookie = "test_cookie";
            cookieEnabled = document.cookie.indexOf("test_cookie") != -1;
        }
    
        return cookieEnabled;
    }
    

    Then in your tests:

    QUnit.test("CookiesEnabled - returns true if user has enabled cookies in their browser", function (assert) {
        var result = CookieHelper.CookiesEnabled(true);
        assert.equal(result, true);
    });
    
    QUnit.test("CookiesEnabled - returns true if user has disabled cookies, but we can still set one", function (assert) {
        var result = CookieHelper.CookiesEnabled(false);
        assert.equal(result, true);
    });
    
    QUnit.test("CookiesEnabled - returns false if browser does not support cookies", function (assert) {
        var result = CookieHelper.CookiesEnabled(false, true);
        assert.equal(result, false);
    });