icingaweb2/doc/test/js_tests.md

4.1 KiB

Writing JavaScipt tests

JavaScript tests are executed using mocha as a test framework and should.js as the assertion framework.

Mocking require.js

As we use require.js for asynchronous dependency resolution in JavaScript, this can lead to problems in our node.js environment. In order to avoid requirejs calls to cause issues, it has been mocked in the testlib/asyncmock.js class and should be required in every testcase:

var rjsmock = require("requiremock.js");

rjsmock now makes dependency management comfortable and provides the following most important methods:

    // remove all registered dependencies from the rjsmock cache
    rjsmock.purgeDependencies();

    // register the following objects underneath the following requirejs paths:
    rjsmock.registerDependencies({
        'icinga/container' : {
            updateContainer : function() {},
            createPopupContainer: function() {}
        }
    });
    // in your js code a require(['icinga/container], function(container) {}) would now have the above mock
    // object in the container variable

    requireNew("icinga/util/async.js"); // requires icinga/util/async.js file - and ignores the requirejs cache
    var async = rjsmock.getDefine(); // returns the last define, this way you can retrieve a specific javacript file

Faking async responses

As we currently use the icinga/util/async.js class for all asynchronous requests, it's easy to fake responses. The asyncmock.js class provides functions for this. To use it in your test, you first have to require it:

var asyncMock = require("asyncmock.js");

You now can use asyncMock.setNextAsyncResult((async) asyncManager, (string) resultString, (bool) fails, (object) headers) to let the next request of the passed asyncManager object return resultString as the response, with the headers provided as the last parameter. If fails = true, the error callback of the request will be called.

Example test

The following example describes a complete test, (which tests whether the registerHeaderListener method in the async class works) :

var should = require("should");             //  require should.js for assertions
var rjsmock = require("requiremock.js");    //  use the requiremock described above
var asyncMock = require("asyncmock.js");    //  Helper class to fake async requests

GLOBAL.document = $('body');                //  needed when our test accesses window.document


describe('The async module', function() {   // start the test scenario
    it("Allows to react on specific headers", function(done) {  // Start a test case - when done is called it is finished
        rjsmock.purgeDependencies();        // Remove any dependency previously declared
        rjsmock.registerDependencies({      // Mock icinga/container, as this is a dependency for the following include
            'icinga/container' : {
                updateContainer : function() {},
                createPopupContainer: function() {}
            }
        });

        requireNew("icinga/util/async.js"); // This is the file we want to test, load it and all of it's dependencies
        var async = rjsmock.getDefine();    // Retrieve a reference to the loaded file

        // Use asyncMock.setNextAsyncResult to let the next async request return 'result' without failing and set
        // the response headers 'X-Dont-Care' and 'X-Test-Header'
        asyncMock.setNextAsyncResult(async, "result", false, {
            'X-Dont-Care' : 'Ignore-me',
            'X-Test-Header' : 'Testme123'
        });

        // register a listener for results with the X-Test-Header response
        async.registerHeaderListener("X-Test-Header", function(value, header) {
            // test for the correct header
            should.equal("Testme123", value);
            // call done to mark this test as succeeded
            done();
        },this);
        // run the faked request
        var test = async.createRequest();
    });

});