From 108922a8b7c49b1bc3507b9558c81b055d5f58e8 Mon Sep 17 00:00:00 2001 From: JUN Date: Mon, 9 Nov 2026 02:10:06 +0900 Subject: [PATCH 1/4] test(gui): restore Overview account-label test globals exactly Closes #8344 --- .../provider-overview-account-label.test.tsx | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/gui/tests/provider-overview-account-label.test.tsx b/gui/tests/provider-overview-account-label.test.tsx index 57e5f3392df..71c3b0b16c5 100644 --- a/gui/tests/provider-overview-account-label.test.tsx +++ b/gui/tests/provider-overview-account-label.test.tsx @@ -14,12 +14,11 @@ import type { WorkspaceItem } from "../src/provider-workspace/catalog"; */ const globals = ["document", "window", "navigator", "localStorage", "IS_REACT_ACT_ENVIRONMENT"] as const; -const WINDOW_EVENT_STUB: { event: undefined } = { event: undefined }; -let previous: Record<(typeof globals)[number], unknown>; +let previous: Record<(typeof globals)[number], PropertyDescriptor | undefined>; let win: Window; let host: HTMLElement; let root: Root | null = null; -let originalFetch: typeof globalThis.fetch; +let originalFetch: PropertyDescriptor | undefined; const POOL_A = { name: "anthropic", adapter: "anthropic", baseUrl: "https://api.anthropic.com", authMode: "oauth" } as unknown as WorkspaceItem; const POOL_B = { ...POOL_A, name: "anthropic2", anthropicOAuthInstance: "anthropic2" } as unknown as WorkspaceItem; @@ -33,9 +32,13 @@ function rows(pool: string, active: Partial): OAuthAccountRow[] ] as OAuthAccountRow[]; } +const originalDescriptors = new Map( + [...globals, "fetch"].map((k) => [k, Object.getOwnPropertyDescriptor(globalThis, k)]), +); + beforeEach(() => { - previous = Object.fromEntries(globals.map((k) => [k, Reflect.get(globalThis, k)])) as typeof previous; - originalFetch = globalThis.fetch; + previous = Object.fromEntries(globals.map((k) => [k, Object.getOwnPropertyDescriptor(globalThis, k)])) as typeof previous; + originalFetch = Object.getOwnPropertyDescriptor(globalThis, "fetch"); win = new Window({ url: "http://localhost/" }); Object.defineProperty(win.navigator, "language", { configurable: true, value: "en-US" }); Object.defineProperty(win, "event", { configurable: true, writable: true, value: undefined }); @@ -52,9 +55,15 @@ beforeEach(() => { }); host = win.document.createElement("div") as unknown as HTMLElement; win.document.body.appendChild(host as never); + domIsSetup = true; }); -afterEach(async () => { +let domIsSetup = false; +afterEach(teardownDom); + +async function teardownDom(): Promise { + if (!domIsSetup) return; + domIsSetup = false; if (root) { const current = root; await act(async () => { current.unmount(); }); @@ -66,23 +75,15 @@ afterEach(async () => { await Promise.resolve(); } }); - for (const key of globals) { - let value = previous[key]; - if (key === "window") { - if (value == null || typeof value !== "object") { - value = WINDOW_EVENT_STUB; - } else if (!Object.prototype.hasOwnProperty.call(value, "event")) { - try { - Object.defineProperty(value, "event", { configurable: true, writable: true, value: undefined }); - } catch { - value = WINDOW_EVENT_STUB; - } - } - } - Object.defineProperty(globalThis, key, { configurable: true, value }); - } - Object.defineProperty(globalThis, "fetch", { configurable: true, value: originalFetch }); -}); + // Restore the exact descriptors; a global that was absent is deleted, never stubbed (#8344). + for (const key of globals) restoreOwnProperty(globalThis, key, previous[key]); + restoreOwnProperty(globalThis, "fetch", originalFetch); +} + +function restoreOwnProperty(target: object, key: PropertyKey, descriptor: PropertyDescriptor | undefined): void { + if (descriptor) Object.defineProperty(target, key, descriptor); + else Reflect.deleteProperty(target, key); +} /** Mounts ProviderDetails on its default Overview tab and returns the rendered text. */ async function overviewText( @@ -195,3 +196,11 @@ test("other OAuth providers keep the login identity in the Overview", async () = expect(text).toContain("Logged in as s***d@xai.test"); expect(currentAccount()).toBeUndefined(); }); + +/** #8344: teardown must leave every global exactly as it found it, absent ones included. */ +test("teardown restores the original global property descriptors exactly", async () => { + const keys = [...globals, "fetch"] as const; + const expected = new Map(keys.map((k) => [k, originalDescriptors.get(k)])); + await teardownDom(); + for (const k of keys) expect(Object.getOwnPropertyDescriptor(globalThis, k)).toEqual(expected.get(k)); +}); From da8c21a0806d34a3640df8302bf9e9e3d33bbc48 Mon Sep 17 00:00:00 2001 From: JUN Date: Mon, 9 Nov 2026 03:07:15 +0900 Subject: [PATCH 2/4] ci: re-run checks on the fixed dev base From e202dcbb59c1717add5c9b5930fce0d46f5c20f3 Mon Sep 17 00:00:00 2001 From: JUN Date: Mon, 9 Nov 2026 03:48:48 +0900 Subject: [PATCH 3/4] test(gui): arm teardown before setup mutates globals and pin a pre-existing window --- .../provider-overview-account-label.test.tsx | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/gui/tests/provider-overview-account-label.test.tsx b/gui/tests/provider-overview-account-label.test.tsx index 71c3b0b16c5..72f772895fd 100644 --- a/gui/tests/provider-overview-account-label.test.tsx +++ b/gui/tests/provider-overview-account-label.test.tsx @@ -19,6 +19,7 @@ let win: Window; let host: HTMLElement; let root: Root | null = null; let originalFetch: PropertyDescriptor | undefined; +let domIsSetup = false; const POOL_A = { name: "anthropic", adapter: "anthropic", baseUrl: "https://api.anthropic.com", authMode: "oauth" } as unknown as WorkspaceItem; const POOL_B = { ...POOL_A, name: "anthropic2", anthropicOAuthInstance: "anthropic2" } as unknown as WorkspaceItem; @@ -36,9 +37,13 @@ const originalDescriptors = new Map( [...globals, "fetch"].map((k) => [k, Object.getOwnPropertyDescriptor(globalThis, k)]), ); -beforeEach(() => { +beforeEach(setupDom); + +function setupDom(): void { previous = Object.fromEntries(globals.map((k) => [k, Object.getOwnPropertyDescriptor(globalThis, k)])) as typeof previous; originalFetch = Object.getOwnPropertyDescriptor(globalThis, "fetch"); + // Armed before the first mutation, so a setup failure still restores what it changed. + domIsSetup = true; win = new Window({ url: "http://localhost/" }); Object.defineProperty(win.navigator, "language", { configurable: true, value: "en-US" }); Object.defineProperty(win, "event", { configurable: true, writable: true, value: undefined }); @@ -55,10 +60,8 @@ beforeEach(() => { }); host = win.document.createElement("div") as unknown as HTMLElement; win.document.body.appendChild(host as never); - domIsSetup = true; -}); +} -let domIsSetup = false; afterEach(teardownDom); async function teardownDom(): Promise { @@ -204,3 +207,18 @@ test("teardown restores the original global property descriptors exactly", async await teardownDom(); for (const k of keys) expect(Object.getOwnPropertyDescriptor(globalThis, k)).toEqual(expected.get(k)); }); + +/** #8344: a window that already existed comes back as the same object, without an added `event`. */ +test("teardown leaves a pre-existing window object untouched", async () => { + await teardownDom(); + const existing = { marker: "pre-existing" }; + Object.defineProperty(globalThis, "window", { configurable: true, writable: true, value: existing }); + try { + setupDom(); + await teardownDom(); + expect(Reflect.get(globalThis, "window")).toBe(existing); + expect(Object.getOwnPropertyNames(existing)).toEqual(["marker"]); + } finally { + Reflect.deleteProperty(globalThis, "window"); + } +}); From 12556a11f2b3d15e01e16af43b5fd64da9c54bcd Mon Sep 17 00:00:00 2001 From: JUN Date: Mon, 9 Nov 2026 04:04:31 +0900 Subject: [PATCH 4/4] test(gui): restore a prior window after the pre-existing-window check --- gui/tests/provider-overview-account-label.test.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gui/tests/provider-overview-account-label.test.tsx b/gui/tests/provider-overview-account-label.test.tsx index 72f772895fd..78c9722997c 100644 --- a/gui/tests/provider-overview-account-label.test.tsx +++ b/gui/tests/provider-overview-account-label.test.tsx @@ -211,14 +211,15 @@ test("teardown restores the original global property descriptors exactly", async /** #8344: a window that already existed comes back as the same object, without an added `event`. */ test("teardown leaves a pre-existing window object untouched", async () => { await teardownDom(); + const priorWindow = Object.getOwnPropertyDescriptor(globalThis, "window"); const existing = { marker: "pre-existing" }; Object.defineProperty(globalThis, "window", { configurable: true, writable: true, value: existing }); try { setupDom(); await teardownDom(); - expect(Reflect.get(globalThis, "window")).toBe(existing); + expect((globalThis as { window?: unknown }).window).toBe(existing); expect(Object.getOwnPropertyNames(existing)).toEqual(["marker"]); } finally { - Reflect.deleteProperty(globalThis, "window"); + restoreOwnProperty(globalThis, "window", priorWindow); } });