lpetrucci
lpetrucci

Reputation: 1679

Jest + React Testing Library: Portals are not being cleaned up

As far as I understand it, React Testing Library cleans up your DOM after every test automatically (at least when you're using Jest).

This works for whatever is rendered inside my root node, but anything that's been rendered outside root with Portals is not getting cleaned up and being persisted across tests.

Unfortunately some of my components depend on a modal component that renders with a portal, so once this component has been opened, I have no way to remove it from the DOM in subsequent tests.

How do I get around this issue?

Upvotes: 2

Views: 3255

Answers (1)

Bruce Sun
Bruce Sun

Reputation: 661

I have the exact same issue with ant-design, I found 2 solutions.

Solution #1, add an additional option container: document.body when calling render (works with warnings, NOT encouraged by testing-library)

render(<CreateOrEditAvailability isEdit={false} />, { initialState, container: document.body });

Warnings:

  • No. 1
Warning: render(...): Replacing React-rendered children with a new root component. If you intended to update the children of this node, you should instead have the existing children update their state and render the new components instead of calling ReactDOM.render.

      at printWarning (node_modules/react-dom/cjs/react-dom.development.js:88:30)
      at error (node_modules/react-dom/cjs/react-dom.development.js:60:5)
      at topLevelUpdateWarnings (node_modules/react-dom/cjs/react-dom.development.js:24664:7)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:24733:5)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:24840:10)
      at node_modules/@testing-library/react/dist/pure.js:99:25
      at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:21856:12)
  • No. 2
Warning: render(): Rendering components directly into document.body is discouraged, since its children are often manipulated by third-party scripts and browser extensions. This may lead to subtle reconciliation issues. Try rendering into a container element created for your app.

      at printWarning (node_modules/react-dom/cjs/react-dom.development.js:88:30)
      at error (node_modules/react-dom/cjs/react-dom.development.js:60:5)
      at topLevelUpdateWarnings (node_modules/react-dom/cjs/react-dom.development.js:24668:7)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:24733:5)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:24840:10)
      at node_modules/@testing-library/react/dist/pure.js:99:25
      at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:21856:12)

Solution #2, remove modals manually with removeChild in afterEach

afterEach(() => {
    const modals = document.querySelectorAll('.ant-modal-wrap');
    modals.forEach((modal) => modal.parentNode.removeChild(modal));
});

test('blah blah', () => {
    render(<CreateOrEditAvailability isEdit={false} />, { initialState });
    ...
});

Upvotes: 2

Related Questions