Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsdom: window.document.defaultView !== window #2648

Closed
6 tasks done
molily opened this issue Jan 12, 2023 · 1 comment · Fixed by #2649
Closed
6 tasks done

jsdom: window.document.defaultView !== window #2648

molily opened this issue Jan 12, 2023 · 1 comment · Fixed by #2649

Comments

@molily
Copy link

molily commented Jan 12, 2023

Describe the bug

I'm migrating tests from Jest to Vitest (both using jsdom) and stumbled upon this subtle difference between Jest and Vitest:

it("works", () => {
  console.log(
    "document.defaultView === window",
    document.defaultView === window
  );

  const element = document.createElement("div");
  document.body.appendChild(element);
  console.log(
    "element.ownerDocument.defaultView === window",
    element.ownerDocument.defaultView === window
  );
});

See https://github.com/molily/vitest-test2/blob/main/first.test.js

Output in vitest:

document.defaultView === window false
element.ownerDocument.defaultView === window false

Output in jest:

document.defaultView === window true 
element.ownerDocument.defaultView === window true

In Vitest, window and document.defaultView are two different Window instances. I would expect both to point to the same object.


Why is this relevant? In my tests, I mock objects on window and expect that it affects all elements in the document.

My concrete test uses @testing-library/dom to fire an event on an element: https://github.com/molily/vitest-test2/blob/main/dom.test.js

I'm mocking window.PointerEvent since jsdom does not support it:

window.PointerEvent = PointerEventFake;

Then I use fireEvent from @testing-library/dom to dispatch an event. fireEvent uses element.ownerDocument.defaultView to get the associated Window object (source 1). It then creates an event using the constructor on this obtained Window instance (source 2). In Vitest, defaultView yields a different object than window, so @testing-library/dom does not find my PointerEvent mock.

A workaround would be to assign the mock on document.defaultView:

document.defaultView.PointerEvent = PointerEvent;

But this is obscure and most developers don't know what defaultView is (they shouldn't for this use case IMHO).

Is there a particular reason why [DOM node].defaultView isn't identical to window? Or am I doing anything wrong?

Reproduction

Example repo: https://github.com/molily/vitest-test2

npm run vitest

yields

stdout | first.test.js > works
document.defaultView === window false
element.ownerDocument.defaultView === window false

 ✓ first.test.js (1)
 ❯ dom.test.js (1)
   × works

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  dom.test.js > works
AssertionError: expected false to be true // Object.is equality
 ❯ dom.test.js:37:18
     35|   document.body.appendChild(element);
     36|   fireEvent.pointerDown(element, { pointerType: "mouse" });
     37|   expect(called).toBe(true);
       |                  ^
     38| });
     39|

  - Expected   "true"
  + Received   "false"

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

 Test Files  1 failed | 1 passed (2)
      Tests  1 failed | 1 passed (2)
   Start at  10:07:22
   Duration  691ms (transform 218ms, setup 0ms, collect 61ms, tests 11ms)

whereas

npm run jest

yields

 PASS  ./dom.test.js
  ● Console

    console.log
      mouse click!
      at HTMLDivElement.log (dom.test.js:31:15)

 PASS  ./first.test.js
  ● Console

    console.log
      document.defaultView === window true
      at Object.log (first.test.js:2:11)

    console.log
      element.ownerDocument.defaultView === window true
      at Object.log (first.test.js:9:11)


Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.482 s, estimated 1 s
Ran all test suites.

System Info

Node: 18.13.0
vitest: 0.27.1

Used Package Manager

npm

Validations

@molily
Copy link
Author

molily commented Jan 12, 2023

Thank you very much! 😻

@github-actions github-actions bot locked and limited conversation to collaborators Jun 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants