Testland
Browse all skills & agents

sinon-fake-timers-js

Wraps Sinon's standalone @sinonjs/fake-timers library for JS/TS testing: install(), tick() / tickAsync(), setSystemTime(), restore(); covers timers (setTimeout / setInterval / requestAnimationFrame), Date / performance.now() / hrtime, and the toFake option for selective override. Runner-agnostic - drives the clock directly in Mocha, AVA, Jasmine, node:test, or the browser. Use when JS/TS code needs deterministic timer or clock control and the test runner does not already expose this library behind its own built-in fake-timer API.

Install with skills.sh (any agent)

npx skills add testland/qa --skill sinon-fake-timers-js
View source

sinon-fake-timers-js

Overview

@sinonjs/fake-timers drives timers and the clock directly, so it works outside Jest (Jest wraps it per jest-fake-timers). Per github.com/sinonjs/fake-timers (opens in new window).

When to use

  • Mocha / Jasmine / Vitest tests needing fake timers + clock.
  • Testing code that uses setTimeout / setInterval / Date.now / requestAnimationFrame.
  • Async-flow tests where promises must resolve at controlled ticks.

Authoring

Install

npm install --save-dev @sinonjs/fake-timers

Basic install

import FakeTimers from '@sinonjs/fake-timers';

const clock = FakeTimers.install({ now: new Date('2026-05-20T14:30:00Z').getTime() });

// Test code that calls Date.now() / new Date() / setTimeout / etc.
expect(new Date().toISOString()).toBe('2026-05-20T14:30:00.000Z');

clock.uninstall();

Tick forward

clock.tick(1000);                  // Advance 1000ms
expect(new Date().toISOString()).toBe('2026-05-20T14:30:01.000Z');

Async tick (for promise-based timers)

test('debounce fires after 300ms', async () => {
  let fired = false;
  setTimeout(() => { fired = true; }, 300);

  await clock.tickAsync(299);
  expect(fired).toBe(false);

  await clock.tickAsync(1);
  expect(fired).toBe(true);
});

Selective faking, setSystemTime, and DST

The toFake selective-override option, setSystemTime jumps, and DST / timezone setup are in references/advanced-scenarios.md.

Teardown

afterEach(() => clock.uninstall());

Critical - leaked clocks contaminate subsequent tests.

Running

npx mocha
npx vitest run

CI integration

jobs:
  time-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v4
      - run: npm ci && npx vitest run

Anti-patterns

Anti-patternWhy it failsFix
Forget clock.uninstall()Leaked fake clock contaminates next testsafterEach(clock.uninstall)
Mix real + fake timers in same testRace conditionsEither fake everything or fake nothing
Use tick() for promise-resolving timersPromises don't resolve synchronouslyUse tickAsync
Hardcode Unix timestampsBrittle to system tzUse new Date(iso-string)
Test DST without process.env.TZUTC-only; DST tests degenerateSet TZ explicitly
Fake hrtime / performance alwaysLoses real-perf measurement when neededUse toFake option
Long tick(86400 * 365 * 1000) to "advance 1 year"Timers fire one-by-one; slowUse setSystemTime instead

Limitations

  • Doesn't fake monotonic time by default. performance.now() and process.hrtime() aren't faked unless requested.
  • DST handling depends on the JS runtime's tz library. Node uses ICU; browsers vary.
  • No leap-second simulation. See leap-second-reference.
  • Tests must isolate process.env.TZ per test. Setting it globally affects all subsequent tests.

References

  • @sinonjs/fake-timers: github.com/sinonjs/fake-timers (opens in new window).
  • Companion catalogs: dst-transition-reference, iso-8601-vs-rfc-3339-reference.
  • Sibling libraries: jest-fake-timers (Sinon's pattern used by Jest's built-in).
  • Cross-language: libfaketime-c, freezegun-python, timecop-ruby, mockclock-jvm.
  • Test matrix: timezone-test-matrix-builder.

sinon fake-timers advanced scenarios

View source (opens in new window)

sinon fake-timers advanced scenarios

Selective override, absolute clock jumps, and DST/timezone setup extracted from the core skill. Install / tick / tickAsync / teardown usage stays in SKILL.md.

Selectively fake

const clock = FakeTimers.install({
  now: new Date('2026-05-20T14:30:00Z').getTime(),
  toFake: ['setTimeout', 'setInterval', 'Date'],  // not 'performance', 'hrtime'
});

Useful when you want real performance.now() for benchmarking but fake Date.

setSystemTime

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

Jumps the clock without ticking any in-flight timers.

DST tests

@sinonjs/fake-timers fakes UTC time; for local-zone DST behaviour, set process.env.TZ first, then install at the UTC instant of the transition.

process.env.TZ = 'America/New_York';
const clock = FakeTimers.install({
  now: new Date('2026-03-08T06:30:00Z').getTime(),  // 02:30 EDT - invalid local
});
// ... test that scheduling at 02:30 local degrades gracefully

The test verifies behaviour at the transition (see the dst-transition-reference skill); the fake clock makes it reproducible.

Related skills

dotnet-faketime

Wraps .NET's TimeProvider abstraction (System.TimeProvider, introduced .NET 8) and FakeTimeProvider from Microsoft.Extensions.TimeProvider.Testing: SetUtcNow, Advance, AutoAdvanceAmount, CreateTimer, Delay, and the pre-.NET-8 ISystemClock migration path. Use when testing C# or F# code that reads the current time, uses timers, or awaits Task.Delay.

dst-transition-reference

Pure-reference catalog of Daylight Saving Time (DST) transition patterns and their canonical bug classes. Covers the spring-forward (skipped hour: 02:00 → 03:00 local) and fall-back (repeated hour: 02:00 → 01:00 local) transitions, the historical irregularity of DST (different jurisdictions, transitions on different dates, some regions abolish DST or never adopted it), the IANA timezone database (tz / Olson DB) as the canonical source, and the testable behaviors DST creates (duplicate / missing local timestamps, cron jobs that fire 0 or 2 times, billing periods that miss / double-count, recurring meetings on transition days). Per-jurisdiction DST-rule tables and refreshable per-region test-data fixtures live in references/. Use when designing or auditing time-handling code or test cases.

freezegun-python

Wraps freezegun (github.com/spulec/freezegun), the Python time-mocking library: @freeze_time decorator / context manager, freeze_time(...).start() + stop(), tick / move_to / tz_offset, and integration with datetime.now / time.time / time.localtime. Use when testing Python code that calls datetime / time.

iso-8601-vs-rfc-3339-reference

Pure-reference catalog of the ISO 8601 vs RFC 3339 distinction. Covers the relationship (RFC 3339 is a strict subset of ISO 8601 designed for internet protocols), the syntactic differences (RFC 3339 disallows ISO 8601's '+02' offset short-form requires '+02:00'; RFC 3339 mandates a date-time separator T or space; ISO 8601 allows much more), the canonical date-time string format (YYYY-MM-DDTHH:MM:SS[.fff]±HH:MM or Z), per-language parser behaviour (Python isoformat, Java Instant.parse, JS Date.parse non-spec), and serialisation rules for APIs. Use when choosing a wire format, parsing third-party datetimes, or auditing time-string handling.

jest-fake-timers

Wraps Jest's built-in modern fake-timers (built on @sinonjs/fake-timers since Jest 27): jest.useFakeTimers(), jest.setSystemTime(), jest.advanceTimersByTime(), jest.runAllTimers(), and jest.useRealTimers() for selective restoration. Use when testing JS/TS code in Jest where setTimeout / setInterval / Date / Date.now need deterministic control.

leap-second-reference

Pure-reference catalog of leap-second mechanics and the bugs they cause: the 23:59:60 UTC insertion (announced ~6 months ahead by IERS Bulletin C; 27 inserted 1972-2016; abolished by 2035 per CGPM 2022), the Google/AWS leap-smear alternative, and the four bug classes a real insertion exposes - time_t non-monotonicity, negative durations, NTP cascading, and cross-node clock skew - each with a monotonic-clock fix and a freezegun simulation. Use when auditing time-sensitive code (financial timestamping, distributed logs, NTP-driven schedulers) for second-by-second progress assumptions; for the far more common daylight-saving-time transition hazards, use dst-transition-reference instead.

libfaketime-c

Wraps libfaketime (github.com/wolfcw/libfaketime), the LD_PRELOAD library that fakes the clock for any binary by intercepting time() / gettimeofday() / clock_gettime(). Covers absolute-date mode (FAKETIME='2026-12-31 23:59:00'), relative offset (FAKETIME='-1d'), advance-rate (FAKETIME='@2026-12-31 23:59:00 x5' for 5x speed), per-process scope via LD_PRELOAD, and FAKETIME_NO_CACHE for high-resolution mocking. Use when you need to fake time, mock the clock, or freeze time for C/C++ or any native binary that needs deterministic wall-clock time.

mockclock-jvm

Wraps Java's java.time.Clock + InstantSource dependency-injection pattern for testing time-sensitive code. Covers Clock.fixed(instant, zone), Clock.offset(baseClock, duration), Clock.systemDefaultZone() for production, the InstantSource interface (Java 17+), and the recommended dependency-injection pattern (constructor-inject Clock instead of calling Instant.now() directly). Use when you need to wire the clock-injection pattern (Clock.fixed, Clock.offset, MutableClock, InstantSource, Spring @Bean) into JVM (Java / Kotlin / Scala) production or test code. For pure DST transition reference (skipped or repeated hours, IANA DB, cron-double-fire bug classes) without a clock-injection need, use dst-transition-reference instead.

timecop-ruby

Wraps timecop (github.com/travisjeffery/timecop), the Ruby time-mocking gem: Timecop.freeze, Timecop.travel, Timecop.scale (time-speedup), Timecop.return (cleanup), and RSpec-friendly helpers. Use when testing Ruby/Rails code that calls Time / Date / DateTime.

timezone-test-matrix-builder

Builds a timezone, daylight saving time (DST), and leap year / leap second test matrix from wherever a codebase reads or formats dates and times. Finds time-handling code (grep for datetime / Date / Instant / time.time / timezone), sorts each spot into storage, business-logic, display, cron, or billing, picks the edge cases that matter (DST spring-forward / fall-back, ambiguous local time, leap day Feb 29, ISO 8601 / RFC 3339 round-trip, zone-database updates), and emits per-spot test stubs wired to the language's fake-clock (mock-time) library. Use when a codebase needs timezone, DST, and leap-year test coverage derived from its own date/time usage.