fix(test): shared-worker files inherit document focus after jsdom 30.1.1

jsdom 30.1.1 (#162575) implements the HTML unfocusing steps: blur() now
focuses the document viewport, so document.hasFocus() stays true. The
non-isolated runner's between-file reset focuses and blurs body to clear
stale shadow focus, which therefore left every later file with
hasFocus() === true instead of a fresh document's false. The runner's
composite test (10-focus observers) failed on main, and UI code that gates
on document.hasFocus() (usage refresh policy) could behave differently in a
shared worker than in an isolated file.

jsdom-compat already owns the jsdom internal bindings; clear the
viewport-only focus there after the reset, restoring the fresh-document
state. Element focus is untouched.
This commit is contained in:
Peter Steinberger 2026-10-01 06:22:55 -07:00
parent 0636d7e772
commit c3425e1d7b
2 changed files with 15 additions and 0 deletions

View file

@ -42,6 +42,19 @@ function bindings() {
return { utils, eventTarget, blob, formData, registry };
}
// jsdom 30.1.1 follows the unfocusing steps: blur() focuses the document viewport, so
// hasFocus() stays true. A fresh document has no focused area; restore that state.
export function clearJsdomViewportFocus(document: Document): void {
const impl = bindings().utils.implForWrapper(document) as {
_lastFocusedElement?: unknown;
_clearDOMSelector?: () => void;
} | null;
if (impl && impl._lastFocusedElement === impl) {
impl._lastFocusedElement = null;
impl._clearDOMSelector?.();
}
}
export function jsdomCustomElementDefinitions(registry: object) {
const native = bindings().registry;
return native.is(registry)

View file

@ -22,6 +22,7 @@ import {
resetGatewayWorkAdmission,
} from "../src/process/gateway-work-admission.js";
import { hasOpenClawAgentDatabaseAsyncResources } from "../src/state/openclaw-agent-db-resources.js";
import { clearJsdomViewportFocus } from "./jsdom-compat.mts";
import {
type CustomElementTracking,
dropRepoOwnedCustomElements,
@ -223,6 +224,7 @@ function resetSharedDocumentBody(): void {
body.focus();
body.blur();
body.removeAttribute("tabindex");
clearJsdomViewportFocus(body.ownerDocument);
}
function restoreRealTimers(): void {