Skip to content

Commit 9824813

Browse files
committed
Add support for async toWarnDev scope
1 parent 6603afa commit 9824813

File tree

3 files changed

+56
-15
lines changed

3 files changed

+56
-15
lines changed

src/__tests__/render.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ describe('render API', () => {
219219
expect(wrapperComponentMountEffect).toHaveBeenCalledTimes(1)
220220
})
221221

222-
testGateReact18('legacyRoot uses legacy ReactDOM.render', () => {
223-
expect(() => {
224-
render(<div />, {legacyRoot: true})
222+
testGateReact18('legacyRoot uses legacy ReactDOM.render', async () => {
223+
await expect(async () => {
224+
await render(<div />, {legacyRoot: true})
225225
}).toErrorDev(
226226
[
227227
"Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",
@@ -238,12 +238,12 @@ describe('render API', () => {
238238
)
239239
})
240240

241-
testGateReact18('legacyRoot uses legacy ReactDOM.hydrate', () => {
241+
testGateReact18('legacyRoot uses legacy ReactDOM.hydrate', async () => {
242242
const ui = <div />
243243
const container = document.createElement('div')
244244
container.innerHTML = ReactDOMServer.renderToString(ui)
245-
expect(() => {
246-
render(ui, {container, hydrate: true, legacyRoot: true})
245+
await expect(async () => {
246+
await render(ui, {container, hydrate: true, legacyRoot: true})
247247
}).toErrorDev(
248248
[
249249
"Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot",

src/__tests__/renderHook.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ test('allows wrapper components', async () => {
6767
expect(result.current).toEqual('provided')
6868
})
6969

70-
testGateReact18('legacyRoot uses legacy ReactDOM.render', () => {
70+
testGateReact18('legacyRoot uses legacy ReactDOM.render', async () => {
7171
const Context = React.createContext('default')
7272
function Wrapper({children}) {
7373
return <Context.Provider value="provided">{children}</Context.Provider>
7474
}
7575
let result
76-
expect(async () => {
76+
await expect(async () => {
7777
result = (
7878
await renderHook(
7979
() => {

tests/toWarnDev.js

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,7 @@ const createMatcherFor = (consoleMethod, matcherName) =>
181181
// Avoid using Jest's built-in spy since it can't be removed.
182182
console[consoleMethod] = consoleSpy
183183

184-
try {
185-
callback()
186-
} catch (error) {
187-
caughtError = error
188-
} finally {
184+
const onFinally = () => {
189185
// Restore the unspied method so that unexpected errors fail tests.
190186
console[consoleMethod] = originalMethod
191187

@@ -289,11 +285,56 @@ const createMatcherFor = (consoleMethod, matcherName) =>
289285

290286
return {pass: true}
291287
}
288+
289+
let returnPromise = null
290+
try {
291+
const result = callback()
292+
293+
if (
294+
typeof result === 'object' &&
295+
result !== null &&
296+
typeof result.then === 'function'
297+
) {
298+
// `act` returns a thenable that can't be chained.
299+
// Once `act(async () => {}).then(() => {}).then(() => {})` works
300+
// we can just return `result.then(onFinally, error => ...)`
301+
returnPromise = new Promise((resolve, reject) => {
302+
result
303+
.then(
304+
() => {
305+
resolve(onFinally())
306+
},
307+
error => {
308+
caughtError = error
309+
return resolve(onFinally())
310+
},
311+
)
312+
// In case onFinally throws we need to reject from this matcher
313+
.catch(error => {
314+
reject(error)
315+
})
316+
})
317+
}
318+
} catch (error) {
319+
caughtError = error
320+
} finally {
321+
return returnPromise === null ? onFinally() : returnPromise
322+
}
292323
} else {
293324
// Any uncaught errors or warnings should fail tests in production mode.
294-
callback()
325+
const result = callback()
295326

296-
return {pass: true}
327+
if (
328+
typeof result === 'object' &&
329+
result !== null &&
330+
typeof result.then === 'function'
331+
) {
332+
return result.then(() => {
333+
return {pass: true}
334+
})
335+
} else {
336+
return {pass: true}
337+
}
297338
}
298339
}
299340

0 commit comments

Comments
 (0)