Search code examples
javascriptunit-testingsinonjsdomava

JSDOM + Ava – test function that relies on `document` global


I'm writing some utilities that are related to the document object.

Let's say that I'm writing a that uses document browser object.

// utils.js
export function myFn(callback) {
  document.addEventListener(callback);  
}

My test file is like so:

// utils.test.js
import test from "ava";
import { JSDOM } from "jsdom";
import sinon from "sinon";
import { myFn } from "./utils";

let dom, document;

test.beforeEach(() => {
  dom = new JSDOM();
  document = dom.window.document;
});

test("it calls the callback when document is ready", t => {
  let fakeCb = sinon.spy();
  myFn(fakeCb);
  t.true(fakeCb.called);
});

After running this test I got a ReferenceError telling that "document is not defined", which makes sense.

My question is: what would be a good way to make the document variable from my test be used inside the function under test?

This function works if I pass a document parameter to it, but this is an ugly solution.


Solution

  • Node.js provides access to the global namespace through global.

    Set document on global and it will be available in your code:

    // utils.test.js
    import test from "ava";
    import { JSDOM } from "jsdom";
    import sinon from "sinon";
    import { myFn } from "./utils";
    
    test.beforeEach(() => {
      global.document = new JSDOM().window.document;
    });
    
    test("it calls the callback when document is ready", t => {
      // ...
    });