vydimitrov / react-countdown-circle-timer

Lightweight React/React Native countdown timer component with color and progress animation based on SVG

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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);
});