Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript - can't get jsdom document in Jest test

I have a module that provides some convenience functions for DOM manipulation that I'm trying to test with Jest and jsdom, but I seem to be doing something wrong in instantiating it.

From reading other questions and answers (such as this one) I understand that Jest's testing environment is automatically set to use jsdom and that you need to replace global.document, but it's not working as I currently have it.

Here's the smallest test case to reproduce the problem:

// domUtils.js

function el(id) {
    return document.getElementById(id);
}

and

// domUtils.test.js

import { JSDOM } from "jsdom";

import * as domUtils from "../src/domUtils";

describe("DOM operations", () => {
    // Workaround for jsdom issue 2304 - needed for later localStorage tests
    const url = "http://localhost";

    const documentHTML = '<!DOCTYPE html><div id="lorem" class="test">Lorem ipsum</div>';

    global.document = new JSDOM(documentHTML, { url });

    test("Get an element from the DOM", () => {
        const loremDiv = domUtils.el("lorem");

        expect(loremDiv.constructor.name).toEqual("HTMLDivElement");
    });
}

This results in TypeError: Cannot read property 'constructor' of null. Replacing the call to domUtils.el() with document.getElementById() results in the same error.

Is it a loading order problem of some sort, or something else?

like image 604
Scott Martin Avatar asked Jan 01 '23 14:01

Scott Martin


1 Answers

OK, the solution was - I totally didn't need to do any of the jsdom setup myself because Jest has already done it. You can set document.body.innerHTML directly in your tests and Bob's your uncle.

I had gotten to Jest's very brief page on DOM testing and skipped over the code example that uses jQuery, because I'm not using jQuery - and got to the paragraph that mentions it provides jsdom. But it didn't explain that, or link to the jsdom docs, so I searched and found them. And they don't mention Jest even once - so I followed the instructions on how to set up jsdom, which turned out to be completely redundant and lead to the error I was getting. Honestly, the one sentence "If you're using Jest, you don't need to instantiate jsdom yourself" would have saved me about two days of pulling my hair out.

like image 57
Scott Martin Avatar answered Jan 04 '23 03:01

Scott Martin