Skip to content

Commit f5ac361

Browse files
authored
Fix missing act warnings issued from focus and blur calls (#3253)
1 parent 922c56e commit f5ac361

File tree

1 file changed

+40
-27
lines changed

1 file changed

+40
-27
lines changed

packages/@headlessui-react/src/test-utils/interactions.ts

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,10 @@ export async function rawClick(
254254
let next: HTMLElement | null = element as HTMLElement | null
255255
while (next !== null) {
256256
if (next.matches(focusableSelector)) {
257-
next.focus()
257+
act(() => {
258+
// act scopes are called immediately. `next` should keep its type refinements.
259+
next!.focus()
260+
})
258261
break
259262
}
260263
next = next.parentElement
@@ -288,37 +291,40 @@ export async function rawClick(
288291
}
289292

290293
export async function focus(element: Document | Element | Window | Node | null) {
291-
try {
292-
if (element === null) return expect(element).not.toBe(null)
294+
await act(async () => {
295+
try {
296+
if (element === null) return expect(element).not.toBe(null)
297+
if (element instanceof HTMLElement) {
298+
element.focus()
299+
} else {
300+
fireEvent.focus(element)
301+
}
293302

294-
if (element instanceof HTMLElement) {
295-
element.focus()
296-
} else {
297-
fireEvent.focus(element)
303+
await new Promise(nextFrame)
304+
} catch (err) {
305+
if (err instanceof Error) Error.captureStackTrace(err, focus)
306+
throw err
298307
}
299-
300-
await new Promise(nextFrame)
301-
} catch (err) {
302-
if (err instanceof Error) Error.captureStackTrace(err, focus)
303-
throw err
304-
}
308+
})
305309
}
306310

307311
export async function blur(element: Document | Element | Window | Node | null) {
308-
try {
309-
if (element === null) return expect(element).not.toBe(null)
312+
await act(async () => {
313+
try {
314+
if (element === null) return expect(element).not.toBe(null)
315+
316+
if (element instanceof HTMLElement) {
317+
element.blur()
318+
} else {
319+
fireEvent.blur(element)
320+
}
310321

311-
if (element instanceof HTMLElement) {
312-
element.blur()
313-
} else {
314-
fireEvent.blur(element)
322+
await new Promise(nextFrame)
323+
} catch (err) {
324+
if (err instanceof Error) Error.captureStackTrace(err, blur)
325+
throw err
315326
}
316-
317-
await new Promise(nextFrame)
318-
} catch (err) {
319-
if (err instanceof Error) Error.captureStackTrace(err, blur)
320-
throw err
321-
}
327+
})
322328
}
323329

324330
export async function mouseEnter(element: Document | Element | Window | null) {
@@ -401,7 +407,10 @@ export async function mouseDrag(
401407
let next: HTMLElement | null = startingElement as HTMLElement | null
402408
while (next !== null) {
403409
if (next.matches(focusableSelector)) {
404-
next.focus()
410+
act(() => {
411+
// act scopes are called immediately. `next` should keep its type refinements.
412+
next!.focus()
413+
})
405414
break
406415
}
407416
next = next.parentElement
@@ -455,7 +464,11 @@ function focusNext(event: Partial<KeyboardEvent>) {
455464
let currentIdx = focusableElements.indexOf(document.activeElement as HTMLElement)
456465
let next = focusableElements[(currentIdx + total + direction + offset) % total] as HTMLElement
457466

458-
if (next) next?.focus({ preventScroll: true })
467+
if (next) {
468+
act(() => {
469+
next?.focus({ preventScroll: true })
470+
})
471+
}
459472

460473
if (next !== document.activeElement) return innerFocusNext(offset + direction)
461474
return next

0 commit comments

Comments
 (0)