Description
- Fresh project generated by create-react-app@4:
@testing-library/dom
version: 5.11.4- Testing Framework and version:
- jest@26.6.0
- DOM Environment:
- jest-environment-jsdom@26.6.2
- jsdom@16.4.0
Relevant code or config:
Same code is available in codesandbox below. The real use case is a bit different but I was able to reproduce the issue with this example:
import React, { useReducer } from "react";
import Modal from "react-modal";
import userEvent from "@testing-library/user-event";
import {
render,
waitForElementToBeRemoved,
screen,
} from "@testing-library/react";
beforeAll(() => {
const root = document.createElement("div");
root.id = "app-root";
document.body.appendChild(root);
Modal.setAppElement("#app-root");
});
function Component() {
const [isOpen, toggle] = useReducer((s) => !s, false);
return (
<>
<button onClick={toggle}>Open</button>
<Modal isOpen={isOpen}>
<button onClick={toggle}>Close</button>
{isOpen && <div>Content</div>}
</Modal>
</>
);
}
test("poc", async () => {
render(<Component />);
userEvent.click(screen.getByText("Open"));
const content = await screen.findByText("Content");
userEvent.click(screen.getByText("Close"));
await waitForElementToBeRemoved(content);
});
What you did:
Queried element rendered inside react-modal
. Closed the modal and waited for the content to disappear. The modal seems to do some direct DOM manipulation, https://github.com/reactjs/react-modal/blob/master/src/components/Modal.js.
What happened:
TypeError: Cannot read property 'parentElement' of null
37 |
38 | userEvent.click(screen.getByText("Close"));
> 39 | await waitForElementToBeRemoved(content);
| ^
40 | });
41 |
at node_modules/@testing-library/dom/dist/wait-for-element-to-be-removed.js:30:21
at Array.map (<anonymous>)
at waitForElementToBeRemoved (node_modules/@testing-library/dom/dist/wait-for-element-to-be-removed.js:27:43)
at Object.<anonymous> (src/App.test.js:39:11)
dom-testing-library/src/wait-for-element-to-be-removed.js
Lines 21 to 25 in cb70902
Reproduction:
https://codesandbox.io/s/amazing-brook-7xssv?file=/src/App.test.js
Problem description:
react-modal
is removing the parentElement of the queried element. The queried element is given to waitForElementToBeRemoved
which crashes while accessing the parentElement.
I'm sure there are work-arounds which can be used to avoid the crash caused by this minimal example. This is still a valid bug in the waitForElementToBeRemoved
utility.
Suggested solution:
waitForElementToBeRemoved
should not crash if given element has no .parentElement
available. It should resolve successfully once missing parentElement is detected.
Debug information:
const getRemainingElements = elements.map(element => {
let parent = element.parentElement;
debugger
// element.outerHTML -> '<div>Content</div>'
// element.parentElement -> null
while (parent.parentElement) parent = parent.parentElement;