-
Notifications
You must be signed in to change notification settings - Fork 470
/
Copy pathfake-timers.js
131 lines (112 loc) · 3.38 KB
/
fake-timers.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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import {configure, getConfig, waitFor, waitForElementToBeRemoved} from '..'
import {render} from './helpers/test-utils'
async function runWaitFor({time = 300} = {}, options) {
const response = 'data'
const doAsyncThing = () =>
new Promise(r => setTimeout(() => r(response), time))
let result
doAsyncThing().then(r => (result = r))
await waitFor(() => expect(result).toBe(response), options)
}
let originalConfig
beforeAll(() => {
originalConfig = getConfig()
})
afterEach(() => {
jest.useRealTimers()
configure(originalConfig)
})
test('real timers', async () => {
// the only difference when not using fake timers is this test will
// have to wait the full length of the timeout
await runWaitFor()
})
test('legacy', async () => {
jest.useFakeTimers('legacy')
await runWaitFor()
})
test('modern', async () => {
jest.useFakeTimers()
await runWaitFor()
})
test('fake timer timeout', async () => {
jest.useFakeTimers()
await expect(
waitFor(
() => {
throw new Error('always throws')
},
{timeout: 10, onTimeout: e => e},
),
).rejects.toMatchInlineSnapshot(`[Error: always throws]`)
})
test('fake timer timeout uses default ontimeout', async () => {
configure({
defaultOnTimeout: _ => {
return Error('Test Error')
},
})
jest.useFakeTimers()
await expect(
waitFor(
() => {
throw new Error('always throws')
},
{timeout: 10},
),
).rejects.toMatchInlineSnapshot(`[Error: Test Error]`)
})
test('times out after 1000ms by default', async () => {
const startReal = performance.now()
jest.useFakeTimers()
const {container} = render(`<div></div>`)
const startFake = performance.now()
// there's a bug with this rule here...
// eslint-disable-next-line jest/valid-expect
await expect(
waitForElementToBeRemoved(() => container, {onTimeout: e => e}),
).rejects.toThrowErrorMatchingInlineSnapshot(
`Timed out in waitForElementToBeRemoved.`,
)
// NOTE: this assertion ensures that the timeout runs in the declared (fake) clock.
expect(performance.now() - startFake).toBeGreaterThanOrEqual(1000)
jest.useRealTimers()
// NOTE: this assertion ensures that the timeout runs in the declared (fake) clock
// while in real time the time was only a fraction since the real clock is only bound by the CPU.
// So 20ms is really just an approximation on how long the CPU needs to execute our code.
// If people want to timeout in real time they should rely on their test runners.
expect(performance.now() - startReal).toBeLessThanOrEqual(20)
})
test('recursive timers do not cause issues', async () => {
jest.useFakeTimers()
let recurse = true
function startTimer() {
setTimeout(() => {
// eslint-disable-next-line jest/no-conditional-in-test -- false-positive
if (recurse) startTimer()
}, 1)
}
startTimer()
await runWaitFor({time: 800}, {timeout: 900})
recurse = false
})
test('legacy fake timers do waitFor requestAnimationFrame', async () => {
jest.useFakeTimers('legacy')
let exited = false
requestAnimationFrame(() => {
exited = true
})
await waitFor(() => {
expect(exited).toBe(true)
})
})
test('modern fake timers do waitFor requestAnimationFrame', async () => {
jest.useFakeTimers('modern')
let exited = false
requestAnimationFrame(() => {
exited = true
})
await waitFor(() => {
expect(exited).toBe(true)
})
})