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

TypeError: Cannot read properties of null (reading 'createEvent') #1027

Closed
Zylphrex opened this issue Mar 21, 2022 · 5 comments
Closed

TypeError: Cannot read properties of null (reading 'createEvent') #1027

Zylphrex opened this issue Mar 21, 2022 · 5 comments

Comments

@Zylphrex
Copy link

Zylphrex commented Mar 21, 2022

Relevant code or config:

import React, {useEffect} from "react";
import { render } from "@testing-library/react";

function Component() {
  useEffect(() => () => {}, []); // make sure to return a cleanup 
  return <>x</>;
}

it("it", function () {
  const {findByText} = render(<Component />);
  return findByText("x").then(() => {
  // the test should have timed out at this point
    return findByText("x");
  });
}, 1); // force a timeout of 1ms so that by the time the second `findByText` is called, the test should've failed

What you did:

You can see the original failure in this github action. The original test is attached below from this pull request

it('allows adding up to GROUP_BY_LIMIT fields', async function () {
  renderTestComponent({
    query: {displayType: 'line'},
    orgFeatures: [...defaultOrgFeatures, 'new-widget-builder-experience-design'],
  });

  await screen.findByText('Group your results');

  // this block is synchronous and causes the test to timeout
  for (let i = 0; i < 19; i++) {
    userEvent.click(screen.getByText('Add Group'));
  }

  // this findAllByText executes after the test times out and is the source of the error
  expect(await screen.findAllByText('Select group')).toHaveLength(20);
  expect(screen.queryByText('Add Group')).not.toBeInTheDocument();
});

I've stripped down the component and test to a minimal case, hence why the test may seem a little strange.

I had a test that did 2 asynchronous findByText calls with some the synchronous calls in between that was causing the test to timeout.

What happened:

I was expecting a timeout error pointing at the specific test that had failed. Instead, my tests crashed with the following stacktrace.

/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom.development.js:3905
      var evt = document.createEvent('Event');
                         ^
TypeError: Cannot read properties of null (reading 'createEvent')
    at Object.invokeGuardedCallbackDev (/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom.development.js:3905:26)
    at invokeGuardedCallback (/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom.development.js:4056:31)
    at flushPassiveEffectsImpl (/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom.development.js:23543:11)
    at unstable_runWithPriority (/home/runner/work/sentry/sentry/node_modules/scheduler/cjs/scheduler.development.js:468:12)
    at runWithPriority$1 (/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom.development.js:11276:10)
    at flushPassiveEffects (/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom.development.js:23447:14)
    at Object.<anonymous>.flushWork (/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom-test-utils.development.js:992:10)
    at Immediate.<anonymous> (/home/runner/work/sentry/sentry/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1003:11)
    at processImmediate (node:internal/timers:464:21)

Reproduction:

You can find a repro in https://github.com/Zylphrex/react-testing-library-error-repro

Problem description:

This error was causing an error without any indication which test was the culprit. This should be failing the test with a timeout, and the test that timed out should obvious.

Suggested solution:

@MatanBobi
Copy link
Member

Hi @Zylphrex, thanks for taking the time to open this one.
If I get the scenario correctly, the test is taking too long (because you're dispatching 20 clicks on elements) so it times out (the jest default timeout is 10 seconds IIRC).
After the test is already cleared, it's reasonable that document won't be available as it's not something available outside of your test (it's only available through JSDOM in your test).

I'd recommend increasing the default timeout for this specific test as it might take time in lower CPU machines.
I don't think there's any issue with testing-library here so I'm closing this one, feel free to comment here and I'll re-open if you think otherwise :)

@Zylphrex
Copy link
Author

I understand that the problem was that my test was timing out and that needs to be addressed. But the problem with testing-library here is that the error itself was not helpful in any way in tracking down the failure.

For example, if I changed the test to something like

import { render } from "@testing-library/react";

function Component() {
  useEffect(() => {}, []); // make sure to return a cleanup
  return <>x</>;
}

it("it", function () {
  const {findByText} = render(<Component />);
  return findByText("x").then(() => {
  // the test should have timed out at this point
    return findByText("x");
  });
}, 1); // force a timeout of 1ms so that by the time the second `findByText` is called, the test should've failed

I simply removed the cleanup in the useEffect, it fails with a timeout error which is what I was hoping. for in the case above.

  ✕ it (36 ms)

  ● it

    thrown: "Exceeded timeout of 1 ms for a test.
    Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

       7 | }
       8 |
    >  9 | it("it", function () {
         | ^
      10 |   const {findByText} = render(<Component />);
      11 |   return findByText("x").then(() => {
      12 |   // the test should have timed out at this point

      at Object.<anonymous> (test.js:9:1)
      at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (node_modules/@jest/core/build/runJest.js:404:19)
      at _run10000 (node_modules/@jest/core/build/cli/index.js:320:7)
      at runCLI (node_modules/@jest/core/build/cli/index.js:173:3)

@MatanBobi
Copy link
Member

MatanBobi commented Mar 21, 2022

Hmm, I get your point, but looking at this the other way around, it will be hard for us to write specific catch for all framework exceptions that might come along the way.

The reason you're seeing the timeout without interacting with anything is that we're probably already rendering and just waiting for the side effect to finish so no error is thrown from React there. The reason you see a React error afterwards is since we're still in progress of running the test but jest has already cleared all of the resources that test was using.

I'll re-open this one, maybe other maintainers will have different insights :)

@eps1lon
Copy link
Member

eps1lon commented Apr 13, 2022

Thank you very much for the repro! Unfortunately, this looks like an issue with Jest: jestjs/jest#9056. Closing in favor of jestjs/jest#12670 until there's something actionable for us.

@mskashef
Copy link

mskashef commented May 9, 2022

I was receiving the same error and I was able to solve it by using getByText instead of findByText

vmarta added a commit to SalesforceCommerceCloud/pwa-kit that referenced this issue Apr 3, 2023
My guess of why there was an error is that there's nothing left to wait for. Perhaps jest already shuts down the test, while react-testing-library is waiting to see more.

Other people out there have experienced the same error: testing-library/react-testing-library#1027 (comment)
vmarta added a commit to SalesforceCommerceCloud/pwa-kit that referenced this issue Apr 11, 2023
* Upgrade msw to latest

* Bring back `server.close`

* Fix one of the failing tests

My guess of why there was an error is that there's nothing left to wait for. Perhaps jest already shuts down the test, while react-testing-library is waiting to see more.

Other people out there have experienced the same error: testing-library/react-testing-library#1027 (comment)

* Fix another test with similar strategy

* Simplify the test so that it passes consistently

Not sure why it seems to be timing out. And different results when only that single test is run vs running the whole test file.

* Skip these tests for now

* Fix AppConfig test

* Fix the remaining checkout tests

* Fix one of the cart tests

* Tweak these cart tests

* Try a different kind of query

* Attempt at fixing this flaky test

* Skip this test for now

* Another attempt at fixing this flaky test

* Try moving it out of the catch block

* Update package-lock.json

* Try moving it out of the catch block

* Try moving it out of the catch block

* Revert and exit early if we detect this test being flaky

* Update comment

* Skip this test only in CI

* Mock response from additional endpoint

* Trigger another round of tests

* Update package lock

* No longer run this test conditionally

* Update package-lock.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants