-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
flush-microtasks.js
66 lines (62 loc) · 2.28 KB
/
flush-microtasks.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* istanbul ignore file */
// the part of this file that we need tested is definitely being run
// and the part that is not cannot easily have useful tests written
// anyway. So we're just going to ignore coverage for this file
/**
* copied and modified from React's enqueueTask.js
*/
function getIsUsingFakeTimers() {
return (
typeof jest !== 'undefined' &&
typeof setTimeout !== 'undefined' &&
(setTimeout.hasOwnProperty('_isMockFunction') ||
setTimeout.hasOwnProperty('clock'))
)
}
let didWarnAboutMessageChannel = false
let enqueueTask
try {
// read require off the module object to get around the bundlers.
// we don't want them to detect a require and bundle a Node polyfill.
const requireString = `require${Math.random()}`.slice(0, 7)
const nodeRequire = module && module[requireString]
// assuming we're in node, let's try to get node's
// version of setImmediate, bypassing fake timers if any.
enqueueTask = nodeRequire.call(module, 'timers').setImmediate
} catch (_err) {
// we're in a browser
// we can't use regular timers because they may still be faked
// so we try MessageChannel+postMessage instead
enqueueTask = callback => {
const supportsMessageChannel = typeof MessageChannel === 'function'
if (supportsMessageChannel) {
const channel = new MessageChannel()
channel.port1.onmessage = callback
channel.port2.postMessage(undefined)
} else if (didWarnAboutMessageChannel === false) {
didWarnAboutMessageChannel = true
// eslint-disable-next-line no-console
console.error(
'This browser does not have a MessageChannel implementation, ' +
'so enqueuing tasks via await act(async () => ...) will fail. ' +
'Please file an issue at https://github.com/facebook/react/issues ' +
'if you encounter this warning.',
)
}
}
}
export default function flushMicroTasks() {
return {
then(resolve) {
if (getIsUsingFakeTimers()) {
// without this, a test using fake timers would never get microtasks
// actually flushed. I spent several days on this... Really hard to
// reproduce the problem, so there's no test for it. But it works!
jest.advanceTimersByTime(0)
resolve()
} else {
enqueueTask(resolve)
}
},
}
}