Skip to content

Commit f5fb9f7

Browse files
committed
Test reference impl
1 parent a629609 commit f5fb9f7

File tree

2 files changed

+154
-12
lines changed

2 files changed

+154
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`waitFor DOM reference implementation using fake legacy timers timeout 1`] = `
4+
Not done
5+
6+
Document {
7+
"location": Location {
8+
"assign": [Function assign],
9+
"hash": "",
10+
"host": "localhost",
11+
"hostname": "localhost",
12+
"href": "http://localhost/",
13+
"origin": "http://localhost",
14+
"pathname": "/",
15+
"port": "",
16+
"protocol": "http:",
17+
"reload": [Function reload],
18+
"replace": [Function replace],
19+
"search": "",
20+
"toString": [Function toString],
21+
},
22+
}
23+
`;
24+
25+
exports[`waitFor DOM reference implementation using fake modern timers timeout 1`] = `
26+
Not done
27+
28+
Document {
29+
"location": Location {
30+
"assign": [Function assign],
31+
"hash": "",
32+
"host": "localhost",
33+
"hostname": "localhost",
34+
"href": "http://localhost/",
35+
"origin": "http://localhost",
36+
"pathname": "/",
37+
"port": "",
38+
"protocol": "http:",
39+
"reload": [Function reload],
40+
"replace": [Function replace],
41+
"search": "",
42+
"toString": [Function toString],
43+
},
44+
}
45+
`;
46+
47+
exports[`waitFor DOM reference implementation using real timers timeout 1`] = `
48+
Not done
49+
50+
Document {
51+
"location": Location {
52+
"assign": [Function assign],
53+
"hash": "",
54+
"host": "localhost",
55+
"hostname": "localhost",
56+
"href": "http://localhost/",
57+
"origin": "http://localhost",
58+
"pathname": "/",
59+
"port": "",
60+
"protocol": "http:",
61+
"reload": [Function reload],
62+
"replace": [Function replace],
63+
"search": "",
64+
"toString": [Function toString],
65+
},
66+
}
67+
`;

src/__tests__/waitForDOM.test.js

+87-12
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function waitFor(
5252
} = {},
5353
) {
5454
function getElementError(message) {
55-
const prettifiedDOM = prettyFormat(container)
55+
const prettifiedDOM = prettyFormat.format(container)
5656
const error = new Error(
5757
[message, prettifiedDOM].filter(Boolean).join('\n\n'),
5858
)
@@ -126,6 +126,22 @@ function waitFor(
126126
return result
127127
}
128128

129+
const {MutationObserver} = getWindowFromNode(container)
130+
const observer = new MutationObserver(() => {
131+
const result = checkCallbackWithExpensiveErrorDiagnosticsDisabled()
132+
if (typeof result?.then === 'function') {
133+
result.then(resolvedValue => {
134+
onDone(null, resolvedValue)
135+
})
136+
} else {
137+
onDone(null, result)
138+
}
139+
})
140+
observer.observe(container, mutationObserverOptions)
141+
controller.signal.addEventListener('abort', () => {
142+
observer.disconnect()
143+
})
144+
129145
waitForWeb(checkCallbackWithExpensiveErrorDiagnosticsDisabled, {
130146
clock,
131147
interval,
@@ -147,18 +163,77 @@ function waitFor(
147163
}
148164
},
149165
)
150-
151-
const {MutationObserver} = getWindowFromNode(container)
152-
const observer = new MutationObserver(
153-
checkCallbackWithExpensiveErrorDiagnosticsDisabled,
154-
)
155-
observer.observe(container, mutationObserverOptions)
156-
controller.signal.addEventListener('abort', () => {
157-
observer.disconnect()
158-
})
159166
})
160167
}
161168

162-
test('runs', async () => {
163-
await expect(waitFor(() => {})).resolves.toBeUndefined()
169+
describe.each([
170+
['real timers', () => jest.useRealTimers()],
171+
['fake legacy timers', () => jest.useFakeTimers('legacy')],
172+
['fake modern timers', () => jest.useFakeTimers('modern')],
173+
])('waitFor DOM reference implementation using %s', (label, useTimers) => {
174+
beforeEach(() => {
175+
useTimers()
176+
})
177+
178+
afterEach(() => {
179+
jest.useRealTimers()
180+
})
181+
182+
test('void callback', async () => {
183+
await expect(waitFor(() => {})).resolves.toBeUndefined()
184+
})
185+
186+
test('callback passes after timeout', async () => {
187+
let state = 'pending'
188+
setTimeout(() => {
189+
state = 'done'
190+
}, 10)
191+
192+
await expect(
193+
waitFor(
194+
() => {
195+
if (state !== 'done') {
196+
throw new Error('Not done')
197+
}
198+
},
199+
{interval: 5},
200+
),
201+
).resolves.toBeUndefined()
202+
})
203+
204+
test('timeout', async () => {
205+
const state = 'pending'
206+
207+
await expect(
208+
waitFor(
209+
() => {
210+
if (state !== 'done') {
211+
throw new Error('Not done')
212+
}
213+
},
214+
{timeout: 10},
215+
),
216+
).rejects.toThrowErrorMatchingSnapshot()
217+
})
218+
219+
test('can resolve early due to mutations', async () => {
220+
const container = document.createElement('div')
221+
222+
setTimeout(() => {
223+
container.appendChild(document.createTextNode('Done'))
224+
}, 50)
225+
226+
const p = waitFor(
227+
() => {
228+
if (container.textContent !== 'Done') {
229+
throw new Error('Not done')
230+
}
231+
return container.textContent
232+
},
233+
// this would never resolve with real timers without using a MutationObserver
234+
{container, interval: 200, timeout: 200},
235+
)
236+
237+
await expect(p).resolves.toBe('Done')
238+
})
164239
})

0 commit comments

Comments
 (0)