-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fake promises for fake timers #6876
Changes from 10 commits
c8334fd
a2fe3f1
34e06e1
75caae7
b67bdc6
ff9a55a
5709e02
8792dc9
05e705e
afb2b5b
bf04905
6ddadb3
6a64998
bc7c78e
233be98
5da3111
d9d8055
cc4601b
f78f243
3c0917c
18c87e1
4060a7c
e6d30c6
6bf8ffe
2c9f3a6
7879ece
c6ebf8d
932d76f
0cc3b74
e4b91e3
faee4f9
954a164
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -467,6 +467,12 @@ The projects feature can also be used to run multiple configurations or multiple | |
|
||
_Note: When using multi project runner, it's recommended to add a `displayName` for each project. This will show the `displayName` of a project next to its tests._ | ||
|
||
### `promises` [string] | ||
|
||
Default: `real` | ||
|
||
Setting this value to `fake` allows the use of fake promises to replace the `Promise` class introduced in ecma-script2015 specification. Fake promises are useful for synchronizing promises, or for use with jest's fake timers feature. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Jest's" |
||
|
||
### `reporters` [array<moduleName | [moduleName, options]>] | ||
|
||
Default: `undefined` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,13 +22,16 @@ The `jest` object is automatically in scope within every test file. The methods | |
- [`jest.restoreAllMocks()`](#jestrestoreallmocks) | ||
- [`jest.resetModules()`](#jestresetmodules) | ||
- [`jest.retryTimes()`](#jestretrytimes) | ||
- [`jest.runAllPromises(runAllTicks)`](#jestrunallpromises) | ||
- [`jest.runAllTicks()`](#jestrunallticks) | ||
- [`jest.runAllTimers()`](#jestrunalltimers) | ||
- [`jest.advanceTimersByTime(msToRun)`](#jestadvancetimersbytimemstorun) | ||
- [`jest.runOnlyPendingTimers()`](#jestrunonlypendingtimers) | ||
- [`jest.setMock(moduleName, moduleExports)`](#jestsetmockmodulename-moduleexports) | ||
- [`jest.setTimeout(timeout)`](#jestsettimeouttimeout) | ||
- [`jest.useFakePromises()`](#jestusefakepromises) | ||
- [`jest.useFakeTimers()`](#jestusefaketimers) | ||
- [`jest.useRealPromises()`](#jestuserealpromises) | ||
- [`jest.useRealTimers()`](#jestuserealtimers) | ||
- [`jest.spyOn(object, methodName)`](#jestspyonobject-methodname) | ||
- [`jest.spyOn(object, methodName, accessType?)`](#jestspyonobject-methodname-accesstype) | ||
|
@@ -344,11 +347,19 @@ module.exports = { | |
|
||
Returns the `jest` object for chaining. | ||
|
||
### `jest.runAllPromises(runAllTicks)` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find it a bit odd to pass in a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe drop it and document that people should call Potentially Oooor make |
||
|
||
Exhausts the **micro**-task queue (`process.nextTick` callbacks and promises scheduled via the `Promise` class). | ||
|
||
Uses the provided `runAllTicks` callback to exhaust all ticks that are currently queued. Fake promises should be in use (by calling `jest.useFakePromises` ) before calling this method. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. space between ` and ) |
||
|
||
This is useful for synchronously executing scheduled promises and ticks in the order in their natural run order in node. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That reads a bit weird, mind rephrasing? Also, "Node.js" |
||
|
||
### `jest.runAllTicks()` | ||
|
||
Exhausts the **micro**-task queue (usually interfaced in node via `process.nextTick`). | ||
Exhausts all scheduled next tick callbacks (usually interfaced in node via `process.nextTick`). | ||
|
||
When this API is called, all pending micro-tasks that have been queued via `process.nextTick` will be executed. Additionally, if those micro-tasks themselves schedule new micro-tasks, those will be continually exhausted until there are no more micro-tasks remaining in the queue. | ||
When this API is called, all pending next tick callbacks that have been queued via `process.nextTick` will be executed. Additionally, if those micro-tasks themselves schedule new micro-tasks, those will be continually exhausted until there are no more micro-tasks remaining in the queue. See the (Promise Mocks)(PromiseMocks.md) doc for more information. | ||
|
||
### `jest.runAllTimers()` | ||
|
||
|
@@ -404,12 +415,24 @@ Example: | |
jest.setTimeout(1000); // 1 second | ||
``` | ||
|
||
### `jest.useFakePromises()` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should note that |
||
|
||
Instructs Jest to use fake versions of the standard Promise API (`Promise.resolve`, `Promise.reject`, `Promise.all`, `Promise.race`, `[Promise].then`, `[Promise].catch`, and `[Promise].finally`). | ||
|
||
Returns the `jest` object for chaining. | ||
|
||
### `jest.useFakeTimers()` | ||
|
||
Instructs Jest to use fake versions of the standard timer functions (`setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`, `nextTick`, `setImmediate` and `clearImmediate`). | ||
|
||
Returns the `jest` object for chaining. | ||
|
||
### `jest.useRealPromises()` | ||
|
||
Instructs Jest to use the real versions of the standard Promise API. | ||
|
||
Returns the `jest` object for chaining. | ||
|
||
### `jest.useRealTimers()` | ||
|
||
Instructs Jest to use the real versions of the standard timer functions. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
--- | ||
id: promise-mocks | ||
title: Promise Mocks | ||
--- | ||
|
||
Can be used to supplement the [timer mocks](TimerMocks.md). Timer mocks work by running timer callbacks synchronously, in the same order they normally would, but without waiting. Promise mocks can be used with timer mocks to skip wait times and still run node micro-tasks and macro-tasks in the order they normally would. | ||
|
||
```javascript | ||
// promiseGame.js | ||
'use strict'; | ||
|
||
function promiseGame(callback) { | ||
console.log('Ready....go!'); | ||
Promise.resolve(0).then(() => { | ||
console.log('Promise is fulfilled -- stop!'); | ||
callback && callback(); | ||
}); | ||
} | ||
|
||
module.exports = promiseGame; | ||
``` | ||
|
||
```javascript | ||
// __tests__/promiseGame.js | ||
'use strict'; | ||
|
||
jest.useFakePromises(); | ||
|
||
test('runs all queued promises', () => { | ||
const promiseGame = require('../promiseGame'); | ||
const callback = jest.fn(); | ||
const runAllTicks = jest.fn(); | ||
|
||
promiseGame(callback); | ||
|
||
// At this point, the promise callback should not have been called yet | ||
expect(callback).not.toBeCalled(); | ||
|
||
// Fast-forward until all promises are completed | ||
jest.runAllPromises(runAllTicks); | ||
|
||
// Now our callback should have been called! | ||
expect(callback).toBeCalled(); | ||
expect(callback).toHaveBeenCalledTimes(1); | ||
|
||
// Check that all ticks have been run | ||
expect(runAllTicks).toBeCalled(); | ||
expect(runAllTicks).toHaveBeenCalledTimes(1); | ||
}); | ||
``` | ||
|
||
Here we enable fake promises by calling `jest.useFakePromises();`. This mocks out the Promise class and its entire API. `jest.runAllPromises();` is used to synchronously run all queued promises | ||
|
||
The timer mock API uses a promise mock delegate to run all queued promises and nextTick callbacks if fake promises are being used. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"presets": ["env"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
'use strict'; | ||
|
||
jest.useFakePromises(); | ||
|
||
describe('promiseGame', () => { | ||
it('runs all queued promises', () => { | ||
const promiseGame = require('../promiseGame'); | ||
const callback = jest.fn(); | ||
const runAllTicks = jest.fn(); | ||
|
||
promiseGame(callback); | ||
|
||
// At this point, the promise callback should not have been called yet | ||
expect(callback).not.toBeCalled(); | ||
|
||
// Fast-forward until all promises are completed | ||
jest.runAllPromises(runAllTicks); | ||
|
||
// Now our callback should have been called! | ||
expect(callback).toBeCalled(); | ||
expect(callback.mock.calls.length).toBe(1); | ||
|
||
// Check that all ticks have been run | ||
expect(runAllTicks).toBeCalled(); | ||
expect(runAllTicks.mock.calls.length).toBeGreaterThan(0); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"private": true, | ||
"version": "0.0.0", | ||
"name": "example-promise", | ||
"devDependencies": { | ||
"babel-preset-env": "*", | ||
"jest": "*" | ||
}, | ||
"scripts": { | ||
"test": "jest" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
function promiseGame(callback) { | ||
console.log('Ready....go!'); | ||
Promise.resolve(0).then(() => { | ||
console.log('Promise is fulfilled -- stop!'); | ||
callback && callback(); | ||
}); | ||
} | ||
|
||
module.exports = promiseGame; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the number should include
#
(same with the docs one)