function App() {
let [ctr, setCtr] = useState(0);
useEffect(() => {
setCtr(1);
}, []);
//<-------------------------put a debugger here, only hit once
return ctr;
}
// debug this test
it("should render 1", () => {
const el = document.createElement("div");
ReactDOM.render(<App />, el);
expect(el.innerHTML).toBe("1"); // this fails!
});
currently this test fails because the test’s expect(...)
finishes before useEffect
trigger another update. So I want to put something into the test to make it wait for another update finished so I can see the debugger hit twice. I have tried:
it("should render 1", () => {
const el = document.createElement("div");
ReactDOM.render(<App />, el);
for (let i = 0; i < 2000; i++) { // add a long loop so it could have a chance for the `useEffect` trigged update finishes
// ...
}
expect(el.innerHTML).toBe("1"); // this fails!
});
but I still cannot control js runtime that the next job to be executed and looks like expect(el.innerHTML).toBe("1")
is executed immediately after the loop finishes. So is it a way for me to add something like a trick so I can see the debugger hit twice, i.e let useEffect’s update executes before the expect(...)
statement
2
Answers
You may need
useLayoutEffect
hook.Your test won’t work because you aren’t waiting for the re-render to happen — there isn’t anything in your test to trigger the re-render after the
useEffect
callssetCtr
. TBH, I can’t even tell if this code would actually render the DOM to assert tests against…I reckon a better approach would be to use react-testing-library which gives you the tooling to test your React components without trying to re-invent the wheel.
Here’s a Code Sandbox with
react-testing-library
setup and a simple assertion that the value1
is in the DOM. You can run the test in theTests
tab in Code Sandbox. Below are the relevant code snippets.Hope this helps!
Update: Solving for OP’s original issue
All you need to do is wrap your
render
inact
fromreact-dom/test-utils
.Docs for act
Updated the Code Sandbox as well. Checkout
__tests__/SO.test.tsx