Cannot run countdown in a test (vitest)
AldeonMoriak opened this issue · comments
Hello, these few days I've been trying to test a component which in it I have a countdown but I couldn't make countdown run in it.
First I noticed it was a problem with not letting vitest
know DOM
has been updated so I added act
to let it know. And I tested it by using a setInterval
in a test component. But still countdown
doesn't work in a test.
I've created a minimal reproduction of the issue in here.
The component:
import React, { useEffect, useState } from 'react';
import { CountdownCircleTimer } from 'react-countdown-circle-timer';
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
setInterval(() => {
setCount((v) => v + 3);
}, 1000);
}, []);
return (
<>
<div>{count}</div>
<CountdownCircleTimer
isPlaying
duration={7}
colors={['#004777', '#F7B801', '#A30000', '#A30000']}
colorsTime={[7, 5, 2, 0]}
>
{({ remainingTime }) => remainingTime}
</CountdownCircleTimer>
</>
);
}
the test:
test('should render correctly', () => {
vi.useFakeTimers();
render(<App />);
act(() => {
vi.advanceTimersByTime(2000);
});
expect(screen.getByText('2')).toBeDefined();
});
In this test count
value gets updated but the countdown
doesn't.
Hey, the timer is using requestAnimationFrame internally to measure the time and it seems useFakeTimers is not mocking that. You will need to find other way to test it.
Thank you. I was able to find a solution for that:
let count = 0;
vi.spyOn(window, "requestAnimationFrame").mockImplementation((cb) =>
setTimeout(() => cb(1000 * ++count), 100)
);
act(() => {
vi.advanceTimersByTime(6100);
});