Skip to main content
Time is the usual source of flake in integration tests. ProdBreak gives you deterministic control of it. Today’s MVP lever is collapsing named durations to 0; freeze-in-place mode (the eventual CI default) is on the roadmap.

The pattern

Set the pack’s named durations to 0 in your test setup. The timer queue then drains in order on the triggering call — no waiting on wall-clock:
beforeEach(async () => {
  await sandbox.clock.setDurations({ run_settle: "0s", transcription: "0s" });
});
Now a cascade runs to completion synchronously:
const run = await deck.taskRuns.create({ taskId: "task_rent" });
await sandbox.clock.advance("0s");      // every due event fires, in order, before this returns
const done = await deck.taskRuns.retrieve(run.id);
expect(done.status).toBe("completed");  // no polling, no sleep, no flake

What you get today vs. with freeze mode

Deterministic now (durations→0)

Event ordering, “did the cascade fire?”, and relative timing assertions are fully deterministic. This covers the large majority of integration tests.

Needs freeze mode (roadmap)

Assertions on exact absolute timestamps (created_at == "2025-01-01T00:00:05Z") want freeze-in-place plus a pinned t0, since absolute stamps still track wall-clock until then.
Pin t0 per world when a test is date-sensitive — month-end billing, DST, year rollover — so the canonical start is reproducible regardless of when CI runs:
await sandbox.reset({ t0: "2025-01-31T23:59:00Z" });

Why not just sleep?

A sleep(5000) is slow and flaky — it assumes delivery happens within a window. Collapsing durations removes the window entirely: the work is done by the time advance() returns. Faster suites, zero timing assumptions.