close

Fake timers

The fake timers may be useful when a piece of code sets a long timeout that we don't want to wait for in a test.

Rstest provides some utility functions to help you fake timers powered by @sinonjs/fake-timers.

rs.useFakeTimers

  • Alias: rstest.useFakeTimers
  • Type: (config?: FakeTimerInstallOpts) => RstestUtilities & Disposable

To enable mocking timers, you need to call this method. It uses @sinonjs/fake-timers under the hood.

rs.useFakeTimers();

You can also pass a configuration object to customize the behavior of the fake timers.

The configuration is forwarded to @sinonjs/fake-timers. For example, toFake and toNotFake control which timer APIs are mocked, now sets the initial fake system time, and shouldAdvanceTime / advanceTimeDelta enable automatic advancement.

Disposable / using syntax

Rstest supports the using syntax to restore real timers automatically when the block exits:

{
  using _timers = rs.useFakeTimers();
  // Fake timers are active in this block.
}

rs.useRealTimers

  • Alias: rstest.useRealTimers
  • Type: () => RstestUtilities

Restores the original timer functions (such as setTimeout, setInterval, etc.), disabling the fake timers.

rs.useRealTimers();

rs.isFakeTimers

  • Alias: rstest.isFakeTimers
  • Type: () => boolean

Returns true if fake timers are currently enabled, otherwise false.

if (rs.isFakeTimers()) {
  // Fake timers are active
}

rs.setSystemTime

  • Alias: rstest.setSystemTime
  • Type: (now?: number | Date | { epochMilliseconds: number }) => RstestUtilities

Sets the current system time used by fake timers. Useful for testing code that depends on the current date or time.

If fake timers are enabled, this simulates the user changing the system clock (affecting date-related APIs like Date and performance.now) without firing any timers. If fake timers are not enabled, this only mocks Date.* calls, so you can pin the clock without calling rs.useFakeTimers first.

The now value can also be a Temporal-like object such as Temporal.Instant or Temporal.ZonedDateTime.

rs.setSystemTime(new Date('2020-01-01T00:00:00Z'));

expect(new Date().toISOString()).toBe('2020-01-01T00:00:00.000Z');

rs.useRealTimers();

rs.getRealSystemTime

  • Alias: rstest.getRealSystemTime
  • Type: () => number

Returns the real system time (as a timestamp), even when fake timers are enabled.

const realTime = rs.getRealSystemTime();

rs.runAllTicks

  • Alias: rstest.runAllTicks
  • Type: () => RstestUtilities

Runs all queued microtasks (e.g., process.nextTick).

rs.runAllTimers

  • Alias: rstest.runAllTimers
  • Type: () => RstestUtilities

Executes all pending timers (both timeouts and intervals).

rs.runAllTimersAsync

  • Alias: rstest.runAllTimersAsync
  • Type: () => Promise<RstestUtilities>

Asynchronously executes all pending timers.

rs.runOnlyPendingTimers

  • Alias: rstest.runOnlyPendingTimers
  • Type: () => RstestUtilities

Runs only the currently pending timers (does not schedule new ones).

rs.runOnlyPendingTimersAsync

  • Alias: rstest.runOnlyPendingTimersAsync
  • Type: () => Promise<RstestUtilities>

Asynchronously runs only the currently pending timers.

rs.advanceTimersByTime

  • Alias: rstest.advanceTimersByTime
  • Type: (ms: number | string | Temporal.Duration) => RstestUtilities

Advances the fake timers by the specified milliseconds, executing any timers scheduled within that time.

String durations use the same format as @sinonjs/fake-timers, for example '00:10' for ten seconds.

rs.advanceTimersByTimeAsync

  • Alias: rstest.advanceTimersByTimeAsync
  • Type: (ms: number | string | Temporal.Duration) => Promise<RstestUtilities>

Asynchronously advances the fake timers by the specified milliseconds.

rs.advanceTimersToNextTimer

  • Alias: rstest.advanceTimersToNextTimer
  • Type: (steps?: number) => RstestUtilities

Advances the timers to the next scheduled timer, optionally for a given number of steps.

rs.advanceTimersToNextTimerAsync

  • Alias: rstest.advanceTimersToNextTimerAsync
  • Type: (steps?: number) => Promise<RstestUtilities>

Asynchronously advances the timers to the next scheduled timer.

rs.advanceTimersToNextFrame

  • Alias: rstest.advanceTimersToNextFrame
  • Type: () => RstestUtilities

Advances the timers to the next animation frame.

rs.jumpTimersByTime

  • Alias: rstest.jumpTimersByTime
  • Type: (ms: number | string | Temporal.Duration) => RstestUtilities

Jumps the fake clock forward by the specified amount of time, firing each affected timer callback at most once. This is useful for simulating a JavaScript engine being suspended and resumed later, where intermediate interval ticks are skipped.

rs.useFakeTimers({ now: 0 });

const cb = rs.fn();
setInterval(cb, 1000);

rs.jumpTimersByTime(5000);

expect(cb).toHaveBeenCalledTimes(1);

rs.setTickMode

  • Alias: rstest.setTickMode
  • Type: (mode: { mode: 'manual' | 'nextAsync' } | { mode: 'interval'; delta?: number }) => RstestUtilities

Configures how fake timers advance automatically.

  • { mode: 'manual' }: timers only advance when you call APIs such as rs.advanceTimersByTime().
  • { mode: 'nextAsync' }: the clock continuously advances to the next scheduled timer and lets promise callbacks run between timers.
  • { mode: 'interval', delta?: number }: advances fake time on an interval, equivalent to shouldAdvanceTime / advanceTimeDelta.
rs.useFakeTimers();
rs.setTickMode({ mode: 'nextAsync' });

await new Promise((resolve) => setTimeout(resolve, 1000));

rs.getTimerCount

  • Alias: rstest.getTimerCount
  • Type: () => number

Returns the number of fake timers still left to run.

const count = rs.getTimerCount();

rs.clearAllTimers

  • Alias: rstest.clearAllTimers
  • Type: () => RstestUtilities

Removes all timers that are scheduled to run.

rs.clearAllTimers();