0
# Fake Timers
1
2
Fake timers allow you to control time-dependent code by mocking JavaScript's timing functions and Date constructor. They're essential for testing timeouts, intervals, animations, and any code that depends on the passage of time.
3
4
## Capabilities
5
6
### Installing Fake Timers
7
8
Replace native timing functions with controllable fake implementations.
9
10
```javascript { .api }
11
/**
12
* Install fake timers to control time-dependent code
13
* @param config - Configuration options for fake timers
14
* @returns Clock object for controlling time
15
*/
16
function useFakeTimers(config?: FakeTimerConfig): SinonClock;
17
18
interface FakeTimerConfig {
19
/** Starting time for the fake clock (default: 0) */
20
now?: number | Date;
21
22
/** Array of global functions to fake */
23
toFake?: ("setTimeout" | "clearTimeout" | "setInterval" | "clearInterval" |
24
"Date" | "setImmediate" | "clearImmediate" | "nextTick" |
25
"requestAnimationFrame" | "cancelAnimationFrame" |
26
"requestIdleCallback" | "cancelIdleCallback")[];
27
28
/** Whether time should advance automatically (default: false) */
29
shouldAdvanceTime?: boolean;
30
31
/** How much time advances per automatic tick in ms (default: 20) */
32
advanceTimeDelta?: number;
33
34
/** Target object to install timers on (default: global) */
35
target?: object;
36
}
37
```
38
39
**Usage Examples:**
40
41
```javascript
42
import { useFakeTimers } from "sinon";
43
44
// Basic fake timers
45
const clock = useFakeTimers();
46
47
// Start from specific time
48
const clock = useFakeTimers({ now: new Date("2023-01-01") });
49
50
// Only fake specific functions
51
const clock = useFakeTimers({
52
toFake: ["setTimeout", "Date"]
53
});
54
55
// Automatic time advancement
56
const clock = useFakeTimers({
57
shouldAdvanceTime: true,
58
advanceTimeDelta: 50 // 50ms per tick
59
});
60
```
61
62
### Clock Control Methods
63
64
Methods for controlling the fake clock and advancing time.
65
66
```javascript { .api }
67
interface SinonClock {
68
/**
69
* Advance the clock by specified milliseconds
70
* @param milliseconds - Time to advance in milliseconds
71
*/
72
tick(milliseconds: number): void;
73
74
/**
75
* Advance to the next scheduled timer
76
*/
77
next(): void;
78
79
/**
80
* Run all pending timers (timeouts and intervals)
81
*/
82
runAll(): void;
83
84
/**
85
* Run timers until there are no more scheduled
86
*/
87
runToLast(): void;
88
89
/**
90
* Advance to the next animation frame
91
*/
92
runToFrame(): void;
93
94
/**
95
* Get the current fake time in milliseconds
96
* @returns Current time
97
*/
98
now(): number;
99
100
/**
101
* Get Date representation of current fake time
102
* @returns Current date
103
*/
104
Date(): Date;
105
106
/**
107
* Restore all native timing functions
108
*/
109
restore(): void;
110
}
111
```
112
113
**Usage Examples:**
114
115
```javascript
116
const clock = sinon.useFakeTimers();
117
118
// Schedule some timers
119
setTimeout(() => console.log("timeout 1"), 100);
120
setTimeout(() => console.log("timeout 2"), 200);
121
setInterval(() => console.log("interval"), 50);
122
123
// Advance time manually
124
clock.tick(50); // Logs: "interval"
125
clock.tick(50); // Logs: "timeout 1", "interval"
126
clock.tick(100); // Logs: "timeout 2", "interval", "interval"
127
128
// Or run all at once
129
clock.runAll(); // Executes all pending timers
130
131
// Clean up
132
clock.restore();
133
```
134
135
### Fake Timer Functions
136
137
The fake implementations of native timing functions available on the clock.
138
139
```javascript { .api }
140
interface SinonClock {
141
/** Fake setTimeout implementation */
142
setTimeout: typeof setTimeout;
143
144
/** Fake clearTimeout implementation */
145
clearTimeout: typeof clearTimeout;
146
147
/** Fake setInterval implementation */
148
setInterval: typeof setInterval;
149
150
/** Fake clearInterval implementation */
151
clearInterval: typeof clearInterval;
152
153
/** Fake setImmediate implementation (Node.js) */
154
setImmediate: typeof setImmediate;
155
156
/** Fake clearImmediate implementation (Node.js) */
157
clearImmediate: typeof clearImmediate;
158
159
/** Fake Date constructor */
160
Date: DateConstructor;
161
162
/** Fake requestAnimationFrame implementation */
163
requestAnimationFrame: typeof requestAnimationFrame;
164
165
/** Fake cancelAnimationFrame implementation */
166
cancelAnimationFrame: typeof cancelAnimationFrame;
167
168
/** Fake performance.now implementation */
169
performance: { now(): number };
170
}
171
```
172
173
### Testing Timeouts
174
175
Common patterns for testing setTimeout-based code.
176
177
**Usage Examples:**
178
179
```javascript
180
// Function that uses timeout
181
function debounce(func, delay) {
182
let timeoutId;
183
return function(...args) {
184
clearTimeout(timeoutId);
185
timeoutId = setTimeout(() => func.apply(this, args), delay);
186
};
187
}
188
189
// Test the debounced function
190
const clock = sinon.useFakeTimers();
191
const spy = sinon.spy();
192
const debouncedSpy = debounce(spy, 100);
193
194
// Call multiple times quickly
195
debouncedSpy("arg1");
196
debouncedSpy("arg2");
197
debouncedSpy("arg3");
198
199
// No calls yet
200
console.log(spy.called); // false
201
202
// Advance past debounce delay
203
clock.tick(100);
204
205
// Now the function is called once with the last arguments
206
console.log(spy.calledOnce); // true
207
console.log(spy.calledWith("arg3")); // true
208
209
clock.restore();
210
```
211
212
### Testing Intervals
213
214
Testing setInterval-based functionality.
215
216
**Usage Examples:**
217
218
```javascript
219
// Function that uses interval
220
function startPolling(callback, interval = 1000) {
221
return setInterval(callback, interval);
222
}
223
224
// Test polling behavior
225
const clock = sinon.useFakeTimers();
226
const callback = sinon.spy();
227
228
const intervalId = startPolling(callback, 500);
229
230
// Advance time to trigger interval
231
clock.tick(500);
232
console.log(callback.calledOnce); // true
233
234
clock.tick(500);
235
console.log(callback.calledTwice); // true
236
237
// Stop and cleanup
238
clearInterval(intervalId);
239
clock.restore();
240
```
241
242
### Testing Date-dependent Code
243
244
Testing code that depends on the current date/time.
245
246
**Usage Examples:**
247
248
```javascript
249
// Function that uses current date
250
function isBusinessDay() {
251
const day = new Date().getDay();
252
return day >= 1 && day <= 5; // Monday-Friday
253
}
254
255
// Test with specific date
256
const clock = sinon.useFakeTimers(new Date("2023-12-25")); // Monday
257
258
console.log(isBusinessDay()); // true (Monday is business day)
259
260
// Change to weekend
261
clock.tick(1000 * 60 * 60 * 24 * 5); // Advance 5 days to Saturday
262
console.log(isBusinessDay()); // false (Saturday is weekend)
263
264
clock.restore();
265
```
266
267
### Testing Promises with Timers
268
269
Combining fake timers with Promise-based code.
270
271
**Usage Examples:**
272
273
```javascript
274
// Function that returns Promise with delay
275
function delayedPromise(value, delay) {
276
return new Promise(resolve => {
277
setTimeout(() => resolve(value), delay);
278
});
279
}
280
281
// Test Promise timing
282
async function testDelayedPromise() {
283
const clock = sinon.useFakeTimers();
284
285
const promise = delayedPromise("result", 1000);
286
287
// Promise is pending
288
let resolved = false;
289
promise.then(value => {
290
resolved = true;
291
console.log(value); // "result"
292
});
293
294
console.log(resolved); // false
295
296
// Advance time to resolve Promise
297
clock.tick(1000);
298
299
// Allow Promise to resolve
300
await Promise.resolve();
301
console.log(resolved); // true
302
303
clock.restore();
304
}
305
```
306
307
### Testing Animation Frames
308
309
Testing requestAnimationFrame-based animations.
310
311
**Usage Examples:**
312
313
```javascript
314
// Animation function
315
function animate() {
316
const start = performance.now();
317
318
function frame(timestamp) {
319
const elapsed = timestamp - start;
320
321
if (elapsed < 1000) {
322
// Continue animation
323
requestAnimationFrame(frame);
324
}
325
326
// Update animation based on elapsed time
327
updateAnimation(elapsed);
328
}
329
330
requestAnimationFrame(frame);
331
}
332
333
// Test animation
334
const clock = sinon.useFakeTimers();
335
const updateSpy = sinon.spy(window, 'updateAnimation');
336
337
animate();
338
339
// Advance through several frames
340
clock.runToFrame(); // First frame
341
clock.tick(16); // ~60fps
342
clock.runToFrame(); // Second frame
343
clock.tick(16);
344
clock.runToFrame(); // Third frame
345
346
console.log(updateSpy.callCount); // 3
347
348
// Jump to end of animation
349
clock.tick(1000);
350
clock.runToFrame();
351
352
clock.restore();
353
updateSpy.restore();
354
```
355
356
### Sandbox Integration
357
358
Using fake timers with sandboxes for automatic cleanup.
359
360
**Usage Examples:**
361
362
```javascript
363
// Automatic fake timer management
364
const sandbox = sinon.createSandbox({
365
useFakeTimers: true
366
});
367
368
// Clock is available on sandbox
369
setTimeout(() => console.log("timeout"), 100);
370
sandbox.clock.tick(100); // Logs: "timeout"
371
372
// Automatic restoration
373
sandbox.restore(); // Restores timers automatically
374
```
375
376
**Manual sandbox integration:**
377
378
```javascript
379
const sandbox = sinon.createSandbox();
380
381
// Install fake timers in sandbox
382
const clock = sandbox.useFakeTimers({ now: Date.now() });
383
384
// Use clock for testing...
385
clock.tick(1000);
386
387
// Restore via sandbox
388
sandbox.restore(); // Also restores timers
389
```
390
391
### Advanced Timer Configuration
392
393
Complex timer setups and configurations.
394
395
**Usage Examples:**
396
397
```javascript
398
// Custom timer configuration
399
const clock = useFakeTimers({
400
now: Date.parse("2023-01-01"),
401
toFake: ["setTimeout", "Date", "performance"],
402
shouldAdvanceTime: false,
403
target: window // Specific target object
404
});
405
406
// Multiple timer operations
407
setTimeout(() => console.log("timeout 1"), 100);
408
setTimeout(() => console.log("timeout 2"), 50);
409
const interval = setInterval(() => console.log("interval"), 25);
410
411
// Selective advancement
412
clock.next(); // Runs next timer (50ms timeout 2)
413
clock.next(); // Runs next timer (25ms interval)
414
clock.next(); // Runs next timer (75ms interval again)
415
clock.next(); // Runs next timer (100ms timeout 1)
416
417
clearInterval(interval);
418
clock.restore();
419
```
420
421
## Types
422
423
```javascript { .api }
424
interface SinonClock {
425
// Time control
426
tick(milliseconds: number): void;
427
next(): void;
428
runAll(): void;
429
runToLast(): void;
430
runToFrame(): void;
431
432
// Current time
433
now(): number;
434
Date(): Date;
435
436
// Fake timer functions
437
setTimeout: typeof setTimeout;
438
clearTimeout: typeof clearTimeout;
439
setInterval: typeof setInterval;
440
clearInterval: typeof clearInterval;
441
setImmediate: typeof setImmediate;
442
clearImmediate: typeof clearImmediate;
443
Date: DateConstructor;
444
requestAnimationFrame: typeof requestAnimationFrame;
445
cancelAnimationFrame: typeof cancelAnimationFrame;
446
performance: { now(): number };
447
448
// Lifecycle
449
restore(): void;
450
}
451
452
interface FakeTimerConfig {
453
now?: number | Date;
454
toFake?: string[];
455
shouldAdvanceTime?: boolean;
456
advanceTimeDelta?: number;
457
target?: object;
458
}
459
```