Skip to content

waitFor errors with a weird error if a test using fake timers stops (because of an error for example) while it's waiting #830

Closed
@julienw

Description

@julienw
  • @testing-library/dom version: 7.26.3 (but I also reproduce in 7.27.0)
  • Testing Framework and version: Jest 26.6.3
  • DOM Environment: jsdom 16.4.0
  • node 12.18

Relevant code or config:

See below.

What you did:

Simply using findByText in some promise-based code while using fake timers, working on a new test.

What happened:

This is the error I get:

  ●  Cannot log after tests are done. Did you forget to wait for something async in your test?
    Attempted to log "A function to advance timers was called but the timers API is not mocked with fake timers. Call `jest.useFakeTimers()` in this test or enable fake timers globally by setting `"timers": "fake"` in the configuration file. This warning is likely a result of a default configuration change in Jest 15.

    Release Blog Post: https://jestjs.io/blog/2016/09/01/jest-15.html
    Stack Trace:

          Error: 
          at FakeTimers._checkFakeTimers (node_modules/@jest/fake-timers/build/legacyFakeTimers.js:436:13)
          at FakeTimers.advanceTimersByTime (node_modules/@jest/fake-timers/build/legacyFakeTimers.js:263:10)
          at node_modules/@testing-library/dom/dist/wait-for.js:60:14".

      at BufferedConsole.warn (node_modules/@jest/console/build/BufferedConsole.js:242:10)
      at FakeTimers._checkFakeTimers (node_modules/@jest/fake-timers/build/legacyFakeTimers.js:426:28)
      at FakeTimers.advanceTimersByTime (node_modules/@jest/fake-timers/build/legacyFakeTimers.js:263:10)
      at node_modules/@testing-library/dom/dist/wait-for.js:60:14

One main issue is that the error is repeated indefinitely, I have to ctrl-c to stop the runner. It also obscures the real error happening before.

Reproduction:

This is the simplest code showing the problem:

  beforeEach(() => {
    jest.useFakeTimers();
  });
  afterEach(() => {
    jest.useRealTimers();
  });
  it('errors with a weird error', () => {
    // wait forever
    waitFor(() => {
      throw Error();
    });
  });

Obviously in this code I forgot to "await" waitFor, as a result the test stops before waitFor ends.

An example closer to the real life is this:

  beforeEach(() => {
    jest.useFakeTimers();
  });
  afterEach(() => {
    jest.useRealTimers();
  });
  it('errors with a weird error', async () => {
    Promise.resolve().then(() => {
      throw Error('oops, error');
    });

    // wait forever
    await waitFor(() => {
      throw Error();
    });
  });

The problem is that the test errors before waitFor finishes, fake timers are torn down automatically, but the code in waitFor still wants to use the fake timers.

I couldn't make it fail on codesandbox, I believe because setImmediate is aliased to setTimeout in browsers, but here is a repository where I reproduce locally: https://github.com/julienw/jest-dom-library-issue

git clone https://github.com/julienw/jest-dom-library-issue
cd jest-dom-library-issue
yarn
yarn test

Suggested solution:

I believe that the most important issue is that this never stops. The timeout should set finished to false... but I think that the timeout never runs because the loop is too "tight" (it's using setImmediate, maybe it's using a microtask, but couldn't find anything conclusive about that -- but probably it has precedence over setTimeout).

Note: I could live with one such log that would let me see easily the real error.

Other ideas:

  1. waitFor should know that the test stopped and stop right away. Is it possible to get notified about that? Should we register an beforeEach and afterEach callbacks to get notified of when a test starts and stops?
  2. we check if fake timers are enabled in https://github.com/testing-library/dom-testing-library/blob/master/src/wait-for.js#L54, and then use it all the time in https://github.com/testing-library/dom-testing-library/blob/master/src/wait-for.js#L68, maybe we should check it again at each loop and bail out if this changed? Would that be a perf problem?

But again I could live with these 2 problems if this wasn't looping forever.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requestedreleased

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions