Andrew Jones
Andrew Jones

Reputation: 1001

Using jsdom and Jest

I'm experimenting with Jest to unit test an angular application. In order to test the angular bindings I'm trying to use jsdom (N.B. I'm using v3.1.2 as I'm using node not IO). When I need to load a script with the html the test seems to complete before the script is loaded.

I've simplified my test case to use an example from jsdom:

it('updates the view without error', function(){
    var jsdom = require('../../../../node_modules/jsdom/lib/jsdom');

    jsdom.env(
      '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>',
      ["http://code.jquery.com/jquery.js"],
      function (errors, window) {
        //console.log("contents of a.the-link:", window.$("a.the-link").text());
        console.log("Completed");
        expect(errors).toBeNull();
      }
    );

    console.log('exiting...');
});

If I run this test, the test will pass but the "Completed" log message will not be printed, I can also replace the expect with something that should obviously fail, like expect(false).toBeTruthy() and the test will still "pass". If I remove the injection of jquery then all works as expected.

How should I make sure that the script is loaded before I exit the test? And more generally, using jsdom explicitly with Jest feels a bit wrong. Is there a better way?

Upvotes: 2

Views: 5918

Answers (2)

Giorgio Tempesta
Giorgio Tempesta

Reputation: 2059

I think the best way to test asynchronous code is to pass the 'done' callback as explained in the docs. Your code would then become:

it('updates the view without error', function(done){
    var jsdom = require('../../../../node_modules/jsdom/lib/jsdom');

    jsdom.env(
      '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>',
      ["http://code.jquery.com/jquery.js"],
      function (errors, window) {
        //console.log("contents of a.the-link:", window.$("a.the-link").text());
        console.log("Completed");
        expect(errors).toBeNull();
        done();
      }
    );

    console.log('exiting...');
});

Upvotes: 1

Felix Kling
Felix Kling

Reputation: 816282

Because .env is probably asynchronous, the test will always exist before the callback is called.

According to the jest tutorial, you can simply assign the HTML to document.body.innerHTML:

// Set up our document body
document.body.innerHTML =
    '<div>' +
    ' <span id="username" />' +
    ' <button id="button" />' +
    '</div>';
var $ = require('jquery');

Alternatively you could use pit instead of it and return a promise from the function.

Upvotes: 5

Related Questions