Skip to content

Commit cb57f99

Browse files
authored
Merge branch 'main' into alpha
2 parents 37ccada + bd04cf9 commit cb57f99

File tree

4 files changed

+120
-20
lines changed

4 files changed

+120
-20
lines changed

.all-contributorsrc

+10
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,16 @@
16261626
"code",
16271627
"bug"
16281628
]
1629+
},
1630+
{
1631+
"login": "KevinBon",
1632+
"name": "Kevin BON",
1633+
"avatar_url": "https://avatars.githubusercontent.com/u/1910927?v=4",
1634+
"profile": "https://github.com/KevinBon",
1635+
"contributions": [
1636+
"code",
1637+
"bug"
1638+
]
16291639
}
16301640
],
16311641
"repoHost": "https://github.com",

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ Thanks goes to these people ([emoji key][emojis]):
346346
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jlp-craigmorten"><img src="https://avatars.githubusercontent.com/u/124147726?v=4?s=100" width="100px;" alt="Craig Morten"/><br /><sub><b>Craig Morten</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=jlp-craigmorten" title="Code">💻</a></td>
347347
<td align="center" valign="top" width="14.28%"><a href="https://naor.dev"><img src="https://avatars.githubusercontent.com/u/6171622?v=4?s=100" width="100px;" alt="Naor Peled"/><br /><sub><b>Naor Peled</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=naorpeled" title="Code">💻</a></td>
348348
<td align="center" valign="top" width="14.28%"><a href="http://everlong.org/"><img src="https://avatars.githubusercontent.com/u/454175?v=4?s=100" width="100px;" alt="Julien Wajsberg"/><br /><sub><b>Julien Wajsberg</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=julienw" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3Ajulienw" title="Bug reports">🐛</a></td>
349+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KevinBon"><img src="https://avatars.githubusercontent.com/u/1910927?v=4?s=100" width="100px;" alt="Kevin BON"/><br /><sub><b>Kevin BON</b></sub></a><br /><a href="https://github.com/testing-library/dom-testing-library/commits?author=KevinBon" title="Code">💻</a> <a href="https://github.com/testing-library/dom-testing-library/issues?q=author%3AKevinBon" title="Bug reports">🐛</a></td>
349350
</tr>
350351
</tbody>
351352
</table>

src/__tests__/wait-for.js

+105-16
Original file line numberDiff line numberDiff line change
@@ -292,12 +292,11 @@ test('the real timers => fake timers error shows the original stack trace when c
292292

293293
test('does not work after it resolves', async () => {
294294
jest.useFakeTimers('modern')
295-
let context = 'initial'
295+
const contextStack = []
296296
configure({
297297
// @testing-library/react usage to ensure `IS_REACT_ACT_ENVIRONMENT` is set when acting.
298298
unstable_advanceTimersWrapper: callback => {
299-
const originalContext = context
300-
context = 'act'
299+
contextStack.push('act:start')
301300
try {
302301
const result = callback()
303302
// eslint-disable-next-line jest/no-if, jest/no-conditional-in-test -- false-positive
@@ -307,54 +306,144 @@ test('does not work after it resolves', async () => {
307306
then: (resolve, reject) => {
308307
thenable.then(
309308
returnValue => {
310-
context = originalContext
309+
contextStack.push('act:end')
311310
resolve(returnValue)
312311
},
313312
error => {
314-
context = originalContext
313+
contextStack.push('act:end')
315314
reject(error)
316315
},
317316
)
318317
},
319318
}
320319
} else {
321-
context = originalContext
320+
contextStack.push('act:end')
322321
return undefined
323322
}
324323
} catch {
325-
context = originalContext
324+
contextStack.push('act:end')
326325
return undefined
327326
}
328327
},
329328
asyncWrapper: async callback => {
330-
const originalContext = context
331-
context = 'no-act'
329+
contextStack.push('no-act:start')
332330
try {
333331
await callback()
334332
} finally {
335-
context = originalContext
333+
contextStack.push('no-act:end')
336334
}
337335
},
338336
})
339337

340-
let data = null
338+
let timeoutResolved = false
341339
setTimeout(() => {
342-
data = 'resolved'
340+
contextStack.push('timeout')
341+
timeoutResolved = true
343342
}, 100)
344343

344+
contextStack.push('waitFor:start')
345345
await waitFor(
346346
() => {
347+
contextStack.push('callback')
347348
// eslint-disable-next-line jest/no-conditional-in-test -- false-positive
348-
if (data === null) {
349+
if (!timeoutResolved) {
349350
throw new Error('not found')
350351
}
351352
},
352353
{interval: 50},
353354
)
354-
355-
expect(context).toEqual('initial')
355+
contextStack.push('waitFor:end')
356+
357+
expect(contextStack).toMatchInlineSnapshot(`
358+
[
359+
waitFor:start,
360+
no-act:start,
361+
callback,
362+
act:start,
363+
act:end,
364+
callback,
365+
act:start,
366+
timeout,
367+
act:end,
368+
callback,
369+
no-act:end,
370+
waitFor:end,
371+
]
372+
`)
356373

357374
await Promise.resolve()
358375

359-
expect(context).toEqual('initial')
376+
// The context call stack should not change
377+
expect(contextStack).toMatchInlineSnapshot(`
378+
[
379+
waitFor:start,
380+
no-act:start,
381+
callback,
382+
act:start,
383+
act:end,
384+
callback,
385+
act:start,
386+
timeout,
387+
act:end,
388+
callback,
389+
no-act:end,
390+
waitFor:end,
391+
]
392+
`)
393+
})
394+
395+
test(`when fake timer is installed, on waitFor timeout, it doesn't call the callback afterward`, async () => {
396+
jest.useFakeTimers('modern')
397+
398+
configure({
399+
// @testing-library/react usage to ensure `IS_REACT_ACT_ENVIRONMENT` is set when acting.
400+
unstable_advanceTimersWrapper: callback => {
401+
try {
402+
const result = callback()
403+
// eslint-disable-next-line jest/no-if, jest/no-conditional-in-test -- false-positive
404+
if (typeof result?.then === 'function') {
405+
const thenable = result
406+
return {
407+
then: (resolve, reject) => {
408+
thenable.then(
409+
returnValue => {
410+
resolve(returnValue)
411+
},
412+
error => {
413+
reject(error)
414+
},
415+
)
416+
},
417+
}
418+
} else {
419+
return undefined
420+
}
421+
} catch {
422+
return undefined
423+
}
424+
},
425+
asyncWrapper: async callback => {
426+
try {
427+
await callback()
428+
} finally {
429+
/* eslint no-empty: "off" */
430+
}
431+
},
432+
})
433+
434+
const callback = jest.fn(() => {
435+
throw new Error('We want to timeout')
436+
})
437+
const interval = 50
438+
439+
await expect(() =>
440+
waitFor(callback, {interval, timeout: 100}),
441+
).rejects.toThrow()
442+
expect(callback).toHaveBeenCalledWith()
443+
444+
callback.mockClear()
445+
446+
await jest.advanceTimersByTimeAsync(interval)
447+
448+
expect(callback).not.toHaveBeenCalledWith()
360449
})

src/wait-for.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,15 @@ function waitFor(
8181
jest.advanceTimersByTime(interval)
8282
})
8383

84+
// Could have timed-out
85+
if (finished) {
86+
break
87+
}
8488
// It's really important that checkCallback is run *before* we flush
8589
// in-flight promises. To be honest, I'm not sure why, and I can't quite
8690
// think of a way to reproduce the problem in a test, but I spent
8791
// an entire day banging my head against a wall on this.
8892
checkCallback()
89-
90-
if (finished) {
91-
break
92-
}
9393
}
9494
} else {
9595
try {

0 commit comments

Comments
 (0)