Hone logo
Hone
Problems

Jest Timer Mastery: Ensuring a Clean Slate

In JavaScript, setTimeout and setInterval are powerful tools for asynchronous operations. However, in testing environments like Jest, these timers can persist between tests, leading to flaky tests, unexpected behavior, and increased execution times. This challenge focuses on creating a robust clearAllTimers function to ensure a clean state before each test.

Problem Description

Your task is to implement a clearAllTimers function in TypeScript that, when called, will effectively cancel all active timers created by setTimeout and setInterval within the current test environment. This is crucial for preventing timer-related side effects from leaking between tests, ensuring that each test starts with a predictable and unpolluted environment.

Key Requirements:

  • The clearAllTimers function must be able to clear both setTimeout and setInterval timers.
  • It should be a standalone function, not tied to a specific class or object.
  • The function should not throw errors if there are no active timers to clear.

Expected Behavior:

When clearAllTimers is invoked, all timers that have been set and are still pending execution should be canceled. Any callbacks associated with these timers should not be executed.

Edge Cases to Consider:

  • Calling clearAllTimers when no timers have been set.
  • Clearing timers that have already executed.
  • Clearing timers that have already been explicitly cleared by their individual clearTimeout or clearInterval calls.

Examples

Example 1:

// Before clearAllTimers
const timerId1 = setTimeout(() => console.log('Timer 1 fired'), 1000);
const timerId2 = setInterval(() => console.log('Timer 2 fired'), 500);

// Assume clearAllTimers is called here

// After clearAllTimers
// Neither 'Timer 1 fired' nor 'Timer 2 fired' should be logged.

Explanation:

In this scenario, clearAllTimers is expected to cancel both the setTimeout and setInterval timers, preventing their respective console logs from appearing.

Example 2:

// Before clearAllTimers
let counter = 0;
const intervalId = setInterval(() => {
  counter++;
  console.log('Interval tick');
}, 200);

// Assume clearAllTimers is called after 3 ticks but before the 4th tick.

// After clearAllTimers
// The console should show 'Interval tick' 3 times.
// The 4th tick and subsequent ticks should not occur.
// The final value of 'counter' should be 3.

Explanation:

This example demonstrates clearing an interval after it has started but before it has completed its intended runs. The counter should reflect the number of ticks that occurred before clearAllTimers was called.

Example 3: (Edge Case)

// Before clearAllTimers
const timerId1 = setTimeout(() => console.log('Timer 1 fired'), 100);
clearTimeout(timerId1); // Timer is explicitly cleared.

const timerId2 = setInterval(() => console.log('Timer 2 fired'), 200);
clearInterval(timerId2); // Interval is explicitly cleared.

// Assume clearAllTimers is called after both have been explicitly cleared.

// After clearAllTimers
// No errors should be thrown.
// No logs should appear from these timers.

Explanation:

This example tests the robustness of clearAllTimers when timers have already been manually cleared. The function should handle this gracefully without errors and ensure no unexpected behavior.

Constraints

  • The clearAllTimers function should be implemented to work within a standard Node.js environment where Jest is typically run.
  • Your solution should be written in TypeScript.
  • The solution should aim for efficiency, though for this problem, direct manipulation of timer handles is acceptable and likely the most straightforward approach.

Notes

Jest provides built-in utilities for managing timers, such as jest.useFakeTimers() and jest.advanceTimersByTime(). While these are valuable for controlling time in tests, this challenge specifically asks you to implement a function that clears all active timers. You might need to consider how to access or track the timers that are currently active in the JavaScript runtime. Think about how setTimeout and setInterval return unique identifiers.

Loading editor...
typescript