testing-library/testing-library-docs

Usage with Jest's `test.concurrent.each`

jimmycallin opened this issue · 3 comments

  • @testing-library/dom version: 13.3.0
  • Testing Framework and version: jest@28.1.1
  • DOM Environment: jsdom

Relevant code or config:

/**
 * @jest-environment jsdom
 */

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

// this works fine, since we don't run concurrently
test.each([{ param: 1 }, { param: 2 }])("it works $param", ({ param }) => {
  const { getByTestId } = render(<div data-testid="test-container">Hello</div>);
  expect(getByTestId("test-container")).toBeTruthy();
});

// this won't work though, since it will find multiple DOM nodes with id test-container
test.concurrent.each([{ param: 1 }, { param: 2 }])(
  "it works $param",
  ({ param }) => {
    const { getByTestId } = render(
      <div data-testid="test-container">Hello</div>
    );
    expect(getByTestId("test-container")).toBeTruthy();
  }
);
;

What you did:

I have a set of tests that are relying on jest's test.concurrent feature, and I would like to be able to run these concurrently using test.concurrent.each. Just switching from test.concurrent to test.concurrent.each doesn't seem to work.

What happened:

The render method seems to add these to the same JSDOM document, causing issues with e.g. getByTestId

TestingLibraryElementError: Found multiple elements by: [data-testid="test-container"]

Reproduction:

See code snippet on top, or this repository: https://github.com/jimmycallin/rtl-concurrent-each

Problem description:

test.concurrent.each is a supported feature in jest, and it would be great to be able to run multiple testing-library tests in parallel using this feature.

Suggested solution:

It's expected that it doesn't work in the normal configuration because we render into the global document. But since now two tests are rendering concurrently into the same document, the test queries cannot behave the same way.

You would have to create isolated containers for each test. We should probably add explicit documentation for how to achive that.

Thanks, that make sense!

For reference, how would I create isolated containers for each test?

https://jestjs.io/docs/configuration#testenvironment-string

One approach could be to use a custom environment that creates a new JSDOM global in handleTestEvent. This wouldn't just be useful for concurrent tests, it would also isolate regular serial tests a lot better. But there's probably a pretty large perf cost to doing it.