Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock window/document with mocha/chai

When I try to unit test the getElement function

class BarFoo {
    getElement() {
        return document.querySelector('#barfoo');
    }
}

mocha doesn't know anything about document, so I figured that you might do something like this:

beforeEach(() => {
    global.document = {
        querySelector: () => { ... }
    }
}

Although this works, I'm wondering if this is the correct approach and maybe there is a package available to solve this issue, because my approach can get laborious if more browser API's are used ?

like image 624
Jeanluca Scaljeri Avatar asked Apr 08 '16 13:04

Jeanluca Scaljeri


People also ask

Does Mocha use Jsdom?

mocha-jsdom is a simple glue to integrate jsdom to mocha. Invoking jsdom() will inject before and after handlers to the current mocha suite which will setup and teardown jsdom.

Which is better jest or Mocha?

Jest is also faster than Mocha. It has built-in support for snapshot testing, which means tests are run automatically on each change to the code. This makes it easy to keep your tests up to date as you work. Mocha has more features out of the box since it is a more mature tool with a larger community of contributors.

What is Mocha and chai?

Mocha is a JavaScript test framework running on Node. js and in the browser. Mocha allows asynchronous testing, test coverage reports, and use of any assertion library. Chai is a BDD / TDD assertion library for NodeJS and the browser that can be delightfully paired with any javascript testing framework.


Video Answer


2 Answers

There are a few options available to you:

Option 1: Use JSDOM

By adding a DOM to your code, you can unit test much of your client-side code within node.js

Option 2: Use MOCHA on the client

Mocha does run inside the client and you can use separate client-side unit tests. This tends to be my preferred approach as I can test against specific browsers and not a specific JS implantation.

Option 3: Use PhantomJS

PhantomJS allows you to control a headless browser within your testing environment.

Option 4: Headless Chrome

Now that Headless Chrome is out, the PhantomJS maintainer has retired.

like image 181
Jeremy J Starcher Avatar answered Oct 17 '22 04:10

Jeremy J Starcher


I have been writing tests similar to what you proposed when I just needed to mock a certain function on window:

it('html test', function () {
    const windowRef = global.window;
    global.window = {document: {querySelector: () => null}};
    const lib = require('lib-that-uses-queryselector');
    assert(true);
    global.window = windowRef;
});

I have been using mock-browser in other tests when I wanted a more complete window object:

it('html test', function () {
     const windowRef = global.window;
     const MockBrowser = require('mock-browser').mocks.MockBrowser;
     global.window = new MockBrowser().getWindow();
     const lib = require('lib-that-uses-window');
     assert(true);
     global.window = windowRef;
});

Note that you probably want to restore the window object (global.window = windowRef; above) after messing with globals.

like image 42
Simon Bengtsson Avatar answered Oct 17 '22 02:10

Simon Bengtsson