1

I've been banging my head against the wall and for the life of me, I can't figure out the issue. I am using Jest (ts-jest) and the default JSDOM for testing.

In my tests, I am declaring document content for each test separately. Eg.:

test('imageParentTest', () => {
    document.body.innerHTML = '<div><img class="foo"></div>';
    new HtmlElementsCheck()
    // assertions for checking parent, returns <div>
})

Everything works perfectly ok in the first spec. The method that the constructor calls returns a document.querySelectorAll('.' + this._configuration.className); node list of elements, and I am able to check that list, compare the parents of the image, and do the necessary manipulation. So far so good.

If I now run the following spec (imageParentTest2) separately, it will also work correctly, however, if I run both of the specs that share the test context (so if I run testContext), the imageParentTest2 spec does not work because the document.querySelectorAll('.' + this._configuration.className); keeps returning the list of elements that were inserted in the body by imageParentTest. Eg.

describe('testContext', () => {
        test('imageParentTest', () => {
            document.body.innerHTML = '<div><img class="foo"></div>';
            new HtmlElementsCheck();
            // assertions for checking parent, returns <div>
         });

         test('imageParentTest2', () => {
            document.body.innerHTML = '<picture><img class="foo"></picture>';
            new HtmlElementsCheck();
            // assertions for checking parent, returns <div> when running test via 'testContext',
            // returns <picture> when running test 'imageParentTest2' in isolation
         })
})

I have already tried a solution which supposedly resets the document, as noted in this stack overflow answer by adding a

afterEach(() => {
    document.getElementsByTagName('html')[0].innerHTML = ''; 
});

at the beginning of testContext, however, that, as far as my understanding goes, should not be necessary in my case as I am setting the document.body.innerHTML in every test anyway.

I have also tried adding a jest.resetModules(); in the beforeEach to ensure the class that gets instantiated isn't cached and I've tried running tests with the --no-cache flag.

So, how is it possible that in my second test, the document.querySelectorAll('.' + this._configuration.className); in HtmlElementsCheck class returns the node list of elements that were inserted in the body in the first test?

EDIT: I just verified, the class itself is a new instance in separate tests, regardless of whether I run them separately or both via the context so it is looking more and more as if the body doesn't somehow get overridden when I run both tests in the context

Canta
  • 1,480
  • 1
  • 13
  • 26
l.varga
  • 851
  • 6
  • 14
  • 1
    i've tried to isolate your tests. don't see those duplicates – qballer Aug 21 '18 at 13:01
  • Thanks @qballer, did you try running the entire test context? Because running tests separately in isolation works. It's just when I try to run them via `npm run test` or anything like that, when multiple tests are ran, that they don't work. My project is basically blank, though, so I've no idea what could influence it. – l.varga Aug 21 '18 at 13:08

1 Answers1

-1

Ok, so it seems the problem was not in the document itself being persisted, but rather in a beforeAll which mocked a function that gets executed within my class. As this was mocked, my second test detected that the mock got called with the parameters of the first test.

So the mock was causing the issues actually (even though the second test asserted that that function didn't get called).

Changing the mock to be declared in a beforeEach fixed the issue.

l.varga
  • 851
  • 6
  • 14