testing-library / dom-testing-library

🐙 Simple and complete DOM testing utilities that encourage good testing practices.
https://testing-library.com/dom
MIT License
3.25k stars 460 forks source link

Leaking `waitFor` callback against `jasmine` when the `clock` is mocked #1270

Closed KevinBon closed 6 months ago

KevinBon commented 9 months ago

Relevant code or config:

/**
 * For making dom-testing-library compatible with jasmine
 */
function enableFakeJestMode() {
  /**
   * For jestFakeTimersAreEnabled
   * @see https://github.com/testing-library/dom-testing-library/blob/a7b725257e61370675ee043813003d36fae23e9d/src/helpers.ts#L5
   * For usingJestFakeTimers
   * @see https://github.com/testing-library/dom-testing-library/blob/a7b725257e61370675ee043813003d36fae23e9d/src/wait-for.js#L51-L52
   *
   */
  Object.assign(globalThis.setTimeout, { _isMockFunction: true });

  globalThis.jest = {
    /**
     * Use jasmine.clock instead
     */
    advanceTimersByTime: (delay: number) => {
      globalThis.jasmine.clock().tick(delay);
    },
  };
}

describe('jasmine', () => {
  beforeEach(() => {
    enableFakeJestMode();
    jasmine.clock().install();
  });

  afterEach(() => {
    console.log(
      '%c afterEach',
      'color: #f80; font-weight: bold',
      'uninstall:before'
    );
    jasmine.clock().uninstall();
    console.log(
      '%c afterEach',
      'color: #f80; font-weight: bold',
      'uninstall:after'
    );
  });

  it('simulates a timeout', async () => {
    render(<span>Will never be found</span>);

    try {
      await waitFor(
        () => {
          console.log(
            '%c spec',
            'color: lime; font-weight: bold',
            'waitfor:callback'
          );
          // The button shouldn't be found, so it will throw/fail the inner waitFor callback predicate
          screen.getByRole('button');
        },
        { interval: 6000 } // to have less logs
      );
      fail('Should have failed');
    } catch (error) {
      console.log('%c spec', 'color: #f80; font-weight: bold', 'finished ✅');
      expect().nothing();
    }
  });
});

What you did:

I added logs to demonstrate that the waitFor callback has been called even after it has been resolved from a timeout.

What happened:

image

After the waitFor is resolved (see: spec finished: ✅), spec waitfor:callback is still being invoked.

PS: Log points added to surface internal react-testing-library, dom-testing-library and jasmine calls

Reproduction:

Problem description:

The following issue can only be seen when the jasmine.Clock is installed against waitFor.

To prevent any side-effect (e.g: the waitFor callback modifies the global environment), the waitFor callback should never be invoked once it "finishes/resolves"

Suggested solution:

https://github.com/testing-library/dom-testing-library/pull/1271

github-actions[bot] commented 9 months ago

Uh oh! @KevinBon, the image you shared is missing helpful alt text. Check your issue body.

Alt text is an invisible description that helps screen readers describe images to blind or low-vision users. If you are using markdown to display images, add your alt text inside the brackets of the markdown image.

Learn more about alt text at Basic writing and formatting syntax: images on GitHub Docs.

github-actions[bot] commented 9 months ago

Uh oh! @KevinBon, the image you shared is missing helpful alt text. Check your issue body.

Alt text is an invisible description that helps screen readers describe images to blind or low-vision users. If you are using markdown to display images, add your alt text inside the brackets of the markdown image.

Learn more about alt text at Basic writing and formatting syntax: images on GitHub Docs.

github-actions[bot] commented 9 months ago

Uh oh! @KevinBon, the image you shared is missing helpful alt text. Check your issue body.

Alt text is an invisible description that helps screen readers describe images to blind or low-vision users. If you are using markdown to display images, add your alt text inside the brackets of the markdown image.

Learn more about alt text at Basic writing and formatting syntax: images on GitHub Docs.