Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8aac27b

Browse files
authored
feat(fake-timers)!: allow jest.useFakeTimers() and projectConfig.fakeTimers to take an options bag (#12572)
1 parent c7b1538 commit 8aac27b

File tree

68 files changed

+1250
-258
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1250
-258
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- `[jest-circus, jest-jasmine2]` Allowed classes and functions as `describe` and `it`/`test` names ([#12484](https://github.com/facebook/jest/pull/12484))
88
- `[jest-cli, jest-config]` [**BREAKING**] Remove `testURL` config, use `testEnvironmentOptions.url` instead ([#10797](https://github.com/facebook/jest/pull/10797))
99
- `[jest-cli, jest-core]` Add `--shard` parameter for distributed parallel test execution ([#12546](https://github.com/facebook/jest/pull/12546))
10+
- `[jest-cli]` [**BREAKING**] Remove undocumented `--timers` option ([#12572](https://github.com/facebook/jest/pull/12572))
1011
- `[jest-config]` [**BREAKING**] Stop shipping `jest-environment-jsdom` by default ([#12354](https://github.com/facebook/jest/pull/12354))
1112
- `[jest-config]` [**BREAKING**] Stop shipping `jest-jasmine2` by default ([#12355](https://github.com/facebook/jest/pull/12355))
1213
- `[jest-config, @jest/types]` Add `ci` to `GlobalConfig` ([#12378](https://github.com/facebook/jest/pull/12378))
@@ -24,6 +25,8 @@
2425
- `[jest-environment-node]` [**BREAKING**] Second argument `context` to constructor is mandatory ([#12469](https://github.com/facebook/jest/pull/12469))
2526
- `[@jest/expect]` New module which extends `expect` with `jest-snapshot` matchers ([#12404](https://github.com/facebook/jest/pull/12404), [#12410](https://github.com/facebook/jest/pull/12410), [#12418](https://github.com/facebook/jest/pull/12418))
2627
- `[@jest/expect-utils]` New module exporting utils for `expect` ([#12323](https://github.com/facebook/jest/pull/12323))
28+
- `[@jest/fake-timers]` [**BREAKING**] Rename `timers` configuration option to `fakeTimers` ([#12572](https://github.com/facebook/jest/pull/12572))
29+
- `[@jest/fake-timers]` [**BREAKING**] Allow `jest.useFakeTimers()` and `projectConfig.fakeTimers` to take an options bag ([#12572](https://github.com/facebook/jest/pull/12572))
2730
- `[jest-haste-map]` [**BREAKING**] `HasteMap.create` now returns a promise ([#12008](https://github.com/facebook/jest/pull/12008))
2831
- `[jest-haste-map]` Add support for `dependencyExtractor` written in ESM ([#12008](https://github.com/facebook/jest/pull/12008))
2932
- `[jest-mock]` [**BREAKING**] Rename exported utility types `ClassLike`, `FunctionLike`, `ConstructorLikeKeys`, `MethodLikeKeys`, `PropertyLikeKeys`; remove exports of utility types `ArgumentsOf`, `ArgsType`, `ConstructorArgumentsOf` - TS builtin utility types `ConstructorParameters` and `Parameters` should be used instead ([#12435](https://github.com/facebook/jest/pull/12435), [#12489](https://github.com/facebook/jest/pull/12489))

docs/Configuration.md

Lines changed: 102 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,108 @@ Jest's ESM support is still experimental, see [its docs for more details](ECMASc
395395
}
396396
```
397397

398+
### `fakeTimers` \[object]
399+
400+
Default: `{}`
401+
402+
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. For additional details see [Fake Timers guide](TimerMocks.md) and [API documentation](JestObjectAPI.md#fake-timers).
403+
404+
This option provides the default configuration of fake timers for all tests. Calling `jest.useFakeTimers()` in a test file will use these options or will override them if a configuration object is passed. For example, you can tell Jest to keep the original implementation of `process.nextTick()` and adjust the limit of recursive timers that will be run:
405+
406+
```json
407+
{
408+
"fakeTimers": {
409+
"doNotFake": ["nextTick"],
410+
"timerLimit": 1000
411+
}
412+
}
413+
```
414+
415+
```js title="fakeTime.test.js"
416+
// install fake timers for this file using the options from Jest configuration
417+
jest.useFakeTimers();
418+
419+
test('increase the limit of recursive timers for this and following tests', () => {
420+
jest.useFakeTimers({timerLimit: 5000});
421+
// ...
422+
});
423+
```
424+
425+
:::tip
426+
427+
Instead of including `jest.useFakeTimers()` in each test file, you can enable fake timers globally for all tests:
428+
429+
```json
430+
{
431+
"fakeTimers": {
432+
"enableGlobally": true
433+
}
434+
}
435+
```
436+
437+
:::
438+
439+
Configuration options:
440+
441+
```ts
442+
type FakeableAPI =
443+
| 'Date'
444+
| 'hrtime'
445+
| 'nextTick'
446+
| 'performance'
447+
| 'queueMicrotask'
448+
| 'requestAnimationFrame'
449+
| 'cancelAnimationFrame'
450+
| 'requestIdleCallback'
451+
| 'cancelIdleCallback'
452+
| 'setImmediate'
453+
| 'clearImmediate'
454+
| 'setInterval'
455+
| 'clearInterval'
456+
| 'setTimeout'
457+
| 'clearTimeout';
458+
459+
type ModernFakeTimersConfig = {
460+
/**
461+
* If set to `true` all timers will be advanced automatically by 20 milliseconds
462+
* every 20 milliseconds. A custom time delta may be provided by passing a number.
463+
* The default is `false`.
464+
*/
465+
advanceTimers?: boolean | number;
466+
/**
467+
* List of names of APIs that should not be faked. The default is `[]`, meaning
468+
* all APIs are faked.
469+
*/
470+
doNotFake?: Array<FakeableAPI>;
471+
/** Whether fake timers should be enabled for all test files. The default is `false`. */
472+
enableGlobally?: boolean;
473+
/**
474+
* Use the old fake timers implementation instead of one backed by `@sinonjs/fake-timers`.
475+
* The default is `false`.
476+
*/
477+
legacyFakeTimers?: boolean;
478+
/** Sets current system time to be used by fake timers. The default is `Date.now()`. */
479+
now?: number;
480+
/** Maximum number of recursive timers that will be run. The default is `100_000` timers. */
481+
timerLimit?: number;
482+
};
483+
```
484+
485+
:::info Legacy Fake Timers
486+
487+
For some reason you might have to use legacy implementation of fake timers. Here is how to enable it globally (additional options are not supported):
488+
489+
```json
490+
{
491+
"fakeTimers": {
492+
"enableGlobally": true,
493+
"legacyFakeTimers": true
494+
}
495+
}
496+
```
497+
498+
:::
499+
398500
### `forceCoverageMatch` \[array&lt;string&gt;]
399501

400502
Default: `['']`
@@ -1458,14 +1560,6 @@ Default: `5000`
14581560

14591561
Default timeout of a test in milliseconds.
14601562

1461-
### `timers` \[string]
1462-
1463-
Default: `real`
1464-
1465-
Setting this value to `fake` or `modern` enables fake timers for all tests by default. Fake timers are useful when a piece of code sets a long timeout that we don't want to wait for in a test. You can learn more about fake timers [here](JestObjectAPI.md#jestusefaketimersimplementation-modern--legacy).
1466-
1467-
If the value is `legacy`, the old implementation will be used as implementation instead of one backed by [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers).
1468-
14691563
### `transform` \[object&lt;string, pathToTransformer | \[pathToTransformer, object]&gt;]
14701564

14711565
Default: `{"\\.[jt]sx?$": "babel-jest"}`

docs/JestObjectAPI.md

Lines changed: 119 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -628,19 +628,118 @@ test('direct', () => {
628628
});
629629
```
630630

631-
## Mock Timers
631+
## Fake Timers
632632

633-
### `jest.useFakeTimers(implementation?: 'modern' | 'legacy')`
633+
### `jest.useFakeTimers(fakeTimersConfig?)`
634634

635-
Instructs Jest to use fake versions of the standard timer functions (`setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`, `nextTick`, `setImmediate` and `clearImmediate` as well as `Date`).
635+
Instructs Jest to use fake versions of the global date, performance, time and timer APIs. Fake timers implementation is backed by [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers).
636636

637-
If you pass `'legacy'` as an argument, Jest's legacy implementation will be used rather than one based on [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers).
637+
Fake timers will swap out `Date`, `performance.now()`, `queueMicrotask()`, `setImmediate()`, `clearImmediate()`, `setInterval()`, `clearInterval()`, `setTimeout()`, `clearTimeout()` with an implementation that gets its time from the fake clock.
638+
639+
In Node environment `process.hrtime`, `process.nextTick()` and in JSDOM environment `requestAnimationFrame()`, `cancelAnimationFrame()`, `requestIdleCallback()`, `cancelIdleCallback()` will be replaced as well.
640+
641+
Configuration options:
642+
643+
```ts
644+
type FakeableAPI =
645+
| 'Date'
646+
| 'hrtime'
647+
| 'nextTick'
648+
| 'performance'
649+
| 'queueMicrotask'
650+
| 'requestAnimationFrame'
651+
| 'cancelAnimationFrame'
652+
| 'requestIdleCallback'
653+
| 'cancelIdleCallback'
654+
| 'setImmediate'
655+
| 'clearImmediate'
656+
| 'setInterval'
657+
| 'clearInterval'
658+
| 'setTimeout'
659+
| 'clearTimeout';
660+
661+
type FakeTimersConfig = {
662+
/**
663+
* If set to `true` all timers will be advanced automatically by 20 milliseconds
664+
* every 20 milliseconds. A custom time delta may be provided by passing a number.
665+
* The default is `false`.
666+
*/
667+
advanceTimers?: boolean | number;
668+
/**
669+
* List of names of APIs that should not be faked. The default is `[]`, meaning
670+
* all APIs are faked.
671+
*/
672+
doNotFake?: Array<FakeableAPI>;
673+
/**
674+
* Use the old fake timers implementation instead of one backed by `@sinonjs/fake-timers`.
675+
* The default is `false`.
676+
*/
677+
legacyFakeTimers?: boolean;
678+
/** Sets current system time to be used by fake timers. The default is `Date.now()`. */
679+
now?: number | Date;
680+
/**
681+
* The maximum number of recursive timers that will be run when calling `jest.runAllTimers()`.
682+
* The default is `100_000` timers.
683+
*/
684+
timerLimit?: number;
685+
};
686+
```
687+
688+
Calling `jest.useFakeTimers()` will use fake timers for all tests within the file, until original timers are restored with `jest.useRealTimers()`.
689+
690+
You can call `jest.useFakeTimers()` or `jest.useRealTimers()` from anywhere: top level, inside an `test` block, etc. Keep in mind that this is a **global operation** and will affect other tests within the same file. Calling `jest.useFakeTimers()` once again in the same test file would reset the internal state (e.g. timer count) and reinstall fake timers using the provided options:
691+
692+
```js
693+
test('advance the timers automatically', () => {
694+
jest.useFakeTimers({advanceTimers: true});
695+
// ...
696+
});
697+
698+
test('do not advance the timers and do not fake `performance`', () => {
699+
jest.useFakeTimers({doNotFake: ['performance']});
700+
// ...
701+
});
702+
703+
test('uninstall fake timers for the rest of tests in the file', () => {
704+
jest.useRealTimers();
705+
// ...
706+
});
707+
```
708+
709+
:::info Legacy Fake Timers
710+
711+
For some reason you might have to use legacy implementation of fake timers. It can be enabled like this (additional options are not supported):
712+
713+
```js
714+
jest.useFakeTimers({
715+
legacyFakeTimers: true,
716+
});
717+
```
718+
719+
Legacy fake timers will swap out `setImmediate()`, `clearImmediate()`, `setInterval()`, `clearInterval()`, `setTimeout()`, `clearTimeout()` with Jest [mock functions](MockFunctionAPI.md). In Node environment `process.nextTick()` and in JSDOM environment `requestAnimationFrame()`, `cancelAnimationFrame()` will be also replaced.
720+
721+
:::
638722

639723
Returns the `jest` object for chaining.
640724

641725
### `jest.useRealTimers()`
642726

643-
Instructs Jest to use the real versions of the standard timer functions.
727+
Instructs Jest to restore the original implementations of the global date, performance, time and timer APIs. For example, you may call `jest.useRealTimers()` inside `afterEach` hook to restore timers after each test:
728+
729+
```js
730+
afterEach(() => {
731+
jest.useRealTimers();
732+
});
733+
734+
test('do something with fake timers', () => {
735+
jest.useFakeTimers();
736+
// ...
737+
});
738+
739+
test('do something with real timers', () => {
740+
// ...
741+
});
742+
```
644743

645744
Returns the `jest` object for chaining.
646745

@@ -662,7 +761,11 @@ This is often useful for synchronously executing setTimeouts during a test in or
662761

663762
Exhausts all tasks queued by `setImmediate()`.
664763

665-
> Note: This function is not available when using modern fake timers implementation
764+
:::info
765+
766+
This function is only available when using legacy fake timers implementation.
767+
768+
:::
666769

667770
### `jest.advanceTimersByTime(msToRun)`
668771

@@ -696,13 +799,21 @@ Returns the number of fake timers still left to run.
696799

697800
Set the current system time used by fake timers. Simulates a user changing the system clock while your program is running. It affects the current time but it does not in itself cause e.g. timers to fire; they will fire exactly as they would have done without the call to `jest.setSystemTime()`.
698801

699-
> Note: This function is only available when using modern fake timers implementation
802+
:::info
803+
804+
This function is not available when using legacy fake timers implementation.
805+
806+
:::
700807

701808
### `jest.getRealSystemTime()`
702809

703810
When mocking time, `Date.now()` will also be mocked. If you for some reason need access to the real current time, you can invoke this function.
704811

705-
> Note: This function is only available when using modern fake timers implementation
812+
:::info
813+
814+
This function is not available when using legacy fake timers implementation.
815+
816+
:::
706817

707818
## Misc
708819

0 commit comments

Comments
 (0)