0

I've created a Countdown timer component and am writing out tests. I want to test that the setInterval gets cleared when the distance is less than 0.

I've set up a test as follows using vi.spyOn(global, 'clearInterval'):

test('should clear the interval when the distance is less than 0', () => {
        const date = setDate(SECOND);
        vi.spyOn(global, 'clearInterval');

        render(<CountdownClock endDate={date} etc.../>)

        act(() => {
            vi.runOnlyPendingTimers();
            vi.runOnlyPendingTimers();
            vi.clearAllMocks();
        });

        // expect assertions ...
    });

The code itself handles the timer inside of a useEffect:

 useEffect(() => {
        // Start straight away (ie before first second elapses in setInterval)
        if (distance() > 0) {
            runTimer();
        }

        const interval = setInterval(() => {
            if (distance() < 0) {
                // Stop Timer
                endTimer();
                clearInterval(interval);
            } else {
                runTimer();
            }
        }, 1000);

        return () => {
            clearInterval(interval);
        };
    }, []);

The above test sets the date to 1 second in the future and then I run setInterval twice more using vi.runOnlyPendingTimers(). This pushes the distance into negative which stops the timer and clears the interval.

I've logged this out and I can see that the spy works in this part of the code - I can see callCount of 1 after clearInterval has run.

The issue I get is that it then runs the useEffect return statement to clear up. At this point I get the error:

ReferenceError: clearInterval is not defined
 ❯ src/components/CountdownClock/CountdownClockContainer.tsx:94:12
     92| 
     93|         return () => {
     94|             clearInterval(interval);
       |            ^
     95|         };

I can't work out why clearInterval is undefined at this stage. My understanding is that spyOn doesn't create a mock and is rather 'spying' on the method so I can't figure out why clearInterval becomes undefined.

If anyone has any suggestions as to what might be the issue that would be great.

  • Does calling clearInterval trigger any UI change that you can detect? Do you really care that clearInterval is called or that something happen when it is called? – Letincel Nov 14 '22 at 15:53
  • There is a UI change but not directly from calling clearInterval(), it's a state change in the same `if` block. But yeah, it's not testing a UI change. All this is testing really is that there isn't a memory leak that could happen if `clearInterval` doesn't get called. – Matt Wendzina Nov 14 '22 at 16:28

0 Answers0