This repository was archived by the owner on Jan 10, 2025. It is now read-only.
This repository was archived by the owner on Jan 10, 2025. It is now read-only.
react-testing: Introduce a waitFor helper #2536
Open
Description
Overview
Relates to: https://github.com/Shopify/pos-channel/issues/9692
It looks like there is no clean way to test certain use cases that involve some state update scenarios within useEffect
. Here is a minimal example.
const Component = () => {
const [counter, setCounter] = useState(0);
useEffect(() => {
setTimeout(() => {
setCounter((counter) => counter + 1);
}, 0);
}, []);
return <p>{counter}</p>;
};
describe('waitFor', () => {
it('failure', async () => {
const root = await mount(<Component />);
expect(root).toContainReactText('0'); // pass
await root.act(() => {}); // ???
expect(root).toContainReactText('1'); // fail
});
});
react-testing-library
offers a waitFor
method for cases like these. Here is a naive implementation that takes us a bit further.
const waitFor = async (expectation) => {
const timeout = 4500;
const interval = 50;
const maxTries = Math.ceil(timeout / interval);
let tries = 0;
return new Promise<void>((resolve, reject) => {
const rejectOrRerun = (error: Error) => {
if (tries > maxTries) {
reject(error);
return;
}
setTimeout(runExpectation, interval);
};
function runExpectation() {
tries += 1;
try {
Promise.resolve(expectation())
.then(() => resolve())
.catch(rejectOrRerun);
} catch (error) {
rejectOrRerun(error);
}
}
setTimeout(runExpectation, 0);
});
};
And the same test using the above helper
it('success', async () => {
const root = await mount(<Component />);
expect(root).toContainReactText('0'); // pass
await waitFor(() => {
expect(root).toContainReactText('1'); // fail
});
});
The above test passes, but it still feels a bit dirty considering React fires act
warnings:
Warning: An update to Component inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
Would appreciate some insights on how we could best support this.
References:
- DOM Testing Library's implementation
- wait-for-expect
- Slack discussion
- Workplace discussion
Type
- New feature
- Changes to existing features
Motivation
What inspired this feature request? What problems were you facing,
or what else makes you think this should be inquilt
?
...
Area
- Add any relevant
Area: <area>
labels to this issue
Scope
-
Is this issue related to a specific package?
- Tag it with the
Package: <package_name>
label.
- Tag it with the
-
Is it related to a new package?
- Tag it with the
New package
Label
- Tag it with the
Checklist
- Please delete the labels section before submitting your issue
- I have described this issue in a way that is actionable (if possible)