infinite loop when DOM mutation happens in waitFor callback
See original GitHub issueJest hangs on the following sample test:
const { waitFor } = require("@testing-library/dom");
describe("test", () => {
it("test", async () => {
let value = 1;
setTimeout(() => {
value = 2;
});
await waitFor(() => {
// both these lines are important: it's necessary to do a mutation and to fail in the first iteration
// It works normally, if we comment one of these lines
document.body.setAttribute("data-something", 'whatever');
expect(value).toEqual(2);
});
console.log("execution never comes here");
});
});
Two conditions have to be met:
- there should be a DOM mutation in waitFor callback
- first execution of waitFor callback should fail
Expected result: waitFor should resolve the promise after a successful iteration regardless whether there were DOM mutations or not
Current result: waitFor calls the callback infinitely even if subsequent iterations don’t throw any exception.
Environment: @testing-library/dom@7.26.4 jest@26.6.2
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:18 (14 by maintainers)
Top Results From Across the Web
Common mistakes with React Testing Library - Kent C. Dodds
Performing side-effects in waitFor Because of this, the callback can be called (or checked for errors) a non-deterministic number of times and ...
Read more >Infinite loop in useEffect - reactjs - Stack Overflow
Passing an empty array as the second argument to useEffect makes it only run on mount and unmount, thus stopping any infinite loops....
Read more >Async Methods - Testing Library
waitFor may run the callback a number of times until the timeout is reached. Note that the number of calls is constrained by...
Read more >testing library: side-effects and `waitfor` - code-comments
When any of those changes occur, it will re-run the callback. I believe this is where I ran into trouble and created a...
Read more >Getting To Know The MutationObserver API
Monitoring for changes to the DOM is sometimes needed in complex web ... let observer = new MutationObserver(callback); function callback ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
The very first step of waitFor with or without fake timers is to check the callback. (https://github.com/testing-library/dom-testing-library/blob/master/src/wait-for.js#L56 or https://github.com/testing-library/dom-testing-library/blob/master/src/wait-for.js#L96) waitFor doesn’t consider booleans, its either callback throws (try again) or doesn’t throw (success). (https://github.com/testing-library/dom-testing-library/blob/master/src/wait-for.js#L146) If you need to verify against boolean then your callback should use
toBeTruthy()
eg.I do not really understand how
await waitFor(() => false); console.log('Foo')
work. In my case waitFor waits for nothing. No matter if the result of the callback is true or false, the promise (waitFor) will always be resolved andFoo
is logged. Have I understood something wrong here?some env infos: