Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1fc17be

Browse files
authored
fix(wait-for): Don't queue microtasks after condition is met (#1073)
1 parent 2866544 commit 1fc17be

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

‎src/__tests__/wait-for.js‎

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ function deferred() {
1111
return {promise, resolve, reject}
1212
}
1313

14+
let originalConfig
15+
beforeEach(() => {
16+
originalConfig = getConfig()
17+
})
18+
19+
afterEach(() => {
20+
configure(originalConfig)
21+
// restore timers
22+
jest.useRealTimers()
23+
})
24+
1425
test('waits callback to not throw an error', async () => {
1526
const spy = jest.fn()
1627
// we are using random timeout here to simulate a real-time example
@@ -138,7 +149,6 @@ Ignored nodes: comments, <script />, <style />
138149
})
139150

140151
test('should delegate to config.getElementError', async () => {
141-
const originalConfig = getConfig()
142152
const elementError = new Error('Custom element error')
143153
const getElementError = jest.fn().mockImplementation(() => elementError)
144154
configure({getElementError})
@@ -153,7 +163,6 @@ test('should delegate to config.getElementError', async () => {
153163

154164
expect(getElementError).toBeCalledTimes(1)
155165
expect(error.message).toMatchInlineSnapshot(`Custom element error`)
156-
configure(originalConfig)
157166
})
158167

159168
test('when a promise is returned, it does not call the callback again until that promise rejects', async () => {
@@ -255,3 +264,71 @@ test('the real timers => fake timers error shows the original stack trace when c
255264

256265
expect((await waitForError).stack).not.toMatch(__dirname)
257266
})
267+
268+
test('does not work after it resolves', async () => {
269+
jest.useFakeTimers('modern')
270+
let context = 'initial'
271+
configure({
272+
// @testing-library/react usage to ensure `IS_REACT_ACT_ENVIRONMENT` is set when acting.
273+
unstable_advanceTimersWrapper: callback => {
274+
const originalContext = context
275+
context = 'act'
276+
try {
277+
const result = callback()
278+
// eslint-disable-next-line jest/no-if
279+
if (typeof result?.then === 'function') {
280+
const thenable = result
281+
return {
282+
then: (resolve, reject) => {
283+
thenable.then(
284+
returnValue => {
285+
context = originalContext
286+
resolve(returnValue)
287+
},
288+
error => {
289+
context = originalContext
290+
reject(error)
291+
},
292+
)
293+
},
294+
}
295+
} else {
296+
context = originalContext
297+
return undefined
298+
}
299+
} catch {
300+
context = originalContext
301+
return undefined
302+
}
303+
},
304+
asyncWrapper: async callback => {
305+
const originalContext = context
306+
context = 'no-act'
307+
try {
308+
await callback()
309+
} finally {
310+
context = originalContext
311+
}
312+
},
313+
})
314+
315+
let data = null
316+
setTimeout(() => {
317+
data = 'resolved'
318+
}, 100)
319+
320+
await waitFor(
321+
() => {
322+
if (data === null) {
323+
throw new Error('not found')
324+
}
325+
},
326+
{interval: 50},
327+
)
328+
329+
expect(context).toEqual('initial')
330+
331+
await Promise.resolve()
332+
333+
expect(context).toEqual('initial')
334+
})

‎src/wait-for.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ function waitFor(
8282
// an entire day banging my head against a wall on this.
8383
checkCallback()
8484

85+
if (finished) {
86+
break
87+
}
88+
8589
// In this rare case, we *need* to wait for in-flight promises
8690
// to resolve before continuing. We don't need to take advantage
8791
// of parallelization so we're fine.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /