Closed dadamssg closed 5 years ago
Of course I would finally stumble on some clue minutes after I submit an issue but days after trying to figure this out.
Apparently it has something to do with the jest.useFakeTimers()
and promises.
https://stackoverflow.com/a/51132058/728241
After some testing, I've found that I need to advance the timers by an amount greater than 30 ms in an immediately resolving promise. I have no idea why that's the magic number. Or calling jest.runAllTimers()
in the resolving promise also works.
Working test:
describe('Slideshow', () => {
test('slideshow', async () => {
const {getByText} = render(<Slideshow />)
flushEffects()
Promise.resolve().then(() => jest.advanceTimersByTime(30))
// Promise.resolve().then(() => jest.runAllTimers()) <-- also works
await waitForElement(() => getByText('abc'))
})
})
This has nothing to do with react-testing-library
but I feel like this should be documented somewhere. I just don't know where the appropriate place would be.
Bummer. I wonder if you could make it work any better using lolex directly 🤔
Would you like to add this to the FAQ in the README?
Don't you need to wrap the jest.useFakeTimers()
in a promise as well?
I have something like this, and without rapping jest.useFakeTimers()
in a promise, the test timeouts
on the first await (basically nothing gets rendered).
it('hides the error message after sometime', async () => {
Promise.resolve().then(() => jest.useFakeTimers())
const reason = 'there is a special reason'
const { getByText, queryByText, store: { dispatch } } = render(cogitoContract())
dispatch(AppEventsActions.telepathError({ reason }))
await waitForElement(() => getByText(reason))
Promise.resolve().then(() => jest.advanceTimersByTime(3000))
await wait(() => expect(queryByText(reason)).toBeNull())
})
Thanks @marcinczenko!
I'm going to go ahead and close this one.
I think it is fine to close. I have just one remark. I found out that in some cases, you may need to call jest.useFakeTimers()
directly without wrapping it in a promise. So, if something does not work, try both options. Would be nice to further investigate, but as long I can get it to work, it is not the highest priority on my list - fortunately not so many tests need it. It may be related to having async componentDidMount()
and/or calling setState
in it, which always causes second render. In such cases it seems that jest.useFakeTimers()
needs to be wrapped.
I've run into a same issue with testing a component in which a hook sleeps for sometime and then updates the state but no matter what I do I am unable to advance timer
this is what my code looks like, I've given up trying to mock timer in tests of this component but I wonder if my understanding of timers and queues in JS is flawed or if there's something wrong with jest.
const sleep = time =>
new Promise((res, rej) => {
setTimeout(res, time);
});
export default function MyComponent (props) {
...
// my component
...
const spring = useSpring({
to: async (next, cancel) => {
...
await sleep(300);
setSomeState(false);
...
},
// other configurations for animation
});
return <div>MY UI</div>
}
This is an old issue. If you feel like you've found a related issue, then please reproduce the issue using https://kcd.im/rtl-help and file a new issue on the relevant repository.
Thanks!
react-testing-library
version: 5.3.1react
version: react@16.7.0-alpha.2node
version: 8.12.0npm
(oryarn
) version: yarn 1.10.1Relevant code or config:
What you did:
I'm building a slideshow component that will eventually auto-play based on a
setTimeout
. If i calljest.useFakeTimers()
, the test fails. If i remove it, it passes. I've tried usingrerender
,jest.advanctTimersByTime(1)
, andflushEffects()
in various places in conjunction with the previous.What happened:
Reproduction:
You can just copy/paste the above snippet in a project that's using hooks. CodeSandbox doesn't support
jest.useFakeTimers()
.Problem description:
You can see in the screenshot, that the correct data is being logged so hypothetically it should show up in the dom but alas, it is not.
Suggested solution:
???