test: stop restoring window as an undefined global

Assigning globalThis.window = undefined creates an own property. On Ubuntu
that shadows the host window, so later editor tests throw when ProseMirror
reads window.MutationObserver.
This commit is contained in:
tianma-if committed 2026-09-30 21:52:02 +08:00
1 parent d4d212878f
commit f697ffb7dc
13 files changed
+78 -27

No files matched your search

@@ -9,7 +9,8 @@ import {
const originalWindow = globalThis.window;
afterEach(() => {
globalThis.window = originalWindow;
if (originalWindow === undefined) delete globalThis.window;
else globalThis.window = originalWindow;
});
const installWindow = () => {
@@ -9,7 +9,8 @@ import {
const originalWindow = globalThis.window;
afterEach(() => {
globalThis.window = originalWindow;
if (originalWindow === undefined) delete globalThis.window;
else globalThis.window = originalWindow;
});
const installWindow = () => {
+2 -1
View File
@@ -61,7 +61,8 @@ const installLocalStorage = (initialValue = null) => {
};
afterEach(() => {
globalThis.window = originalWindow;
if (originalWindow === undefined) delete globalThis.window;
else globalThis.window = originalWindow;
});
describe("search shortcut scope", () => {
@@ -5,8 +5,10 @@ const originalWindow = globalThis.window;
const originalDocument = globalThis.document;
afterEach(() => {
globalThis.window = originalWindow;
globalThis.document = originalDocument;
if (originalWindow === undefined) delete globalThis.window;
else globalThis.window = originalWindow;
if (originalDocument === undefined) delete globalThis.document;
else globalThis.document = originalDocument;
});
describe("desktop renderer readiness", () => {
+2 -1
View File
@@ -38,7 +38,8 @@ describe("desktop staged resource sync", () => {
release();
expect(events.filter((event) => event === "edgeever:sync-queue-changed")).toHaveLength(1);
} finally {
globalThis.window = originalWindow;
if (originalWindow === undefined) delete globalThis.window;
else globalThis.window = originalWindow;
}
});
@@ -46,7 +46,8 @@ describe("desktop workspace restore", () => {
try {
expect(shouldRestoreDesktopWorkspace()).toBe(true);
} finally {
globalThis.window = previous;
if (previous === undefined) delete globalThis.window;
else globalThis.window = previous;
}
});
});
@@ -1,10 +1,11 @@
import { afterAll, expect, test } from "bun:test";
import { restoreTestGlobal } from "../restore-test-global.mjs";
const originalWindow = globalThis.window;
const originalDocument = globalThis.document;
const originalMutationObserver = globalThis.MutationObserver;
const values = new Map();
globalThis.window = {
const stubWindow = {
location: { href: "https://example.test" },
localStorage: {
getItem: (key) => values.get(key) ?? null,
@@ -16,7 +17,8 @@ globalThis.window = {
addEventListener() {},
removeEventListener() {},
};
globalThis.document = {
globalThis.window = stubWindow;
const stubDocument = {
documentElement: {
classList: { contains: () => false },
dataset: {},
@@ -24,14 +26,16 @@ globalThis.document = {
removeAttribute() {},
},
};
globalThis.MutationObserver = class { observe() {} disconnect() {} };
globalThis.document = stubDocument;
const StubMutationObserver = class { observe() {} disconnect() {} };
globalThis.MutationObserver = StubMutationObserver;
const { EdgeEverPluginHost } = await import("./plugin-host.ts");
afterAll(() => {
globalThis.window = originalWindow;
globalThis.document = originalDocument;
globalThis.MutationObserver = originalMutationObserver;
restoreTestGlobal("window", originalWindow, stubWindow);
restoreTestGlobal("document", originalDocument, stubDocument);
restoreTestGlobal("MutationObserver", originalMutationObserver, StubMutationObserver);
});
const secretStorage = { get: async () => null, set: async () => {}, remove: async () => {}, clearNamespace: async () => {} };
+10 -6
View File
@@ -1,4 +1,5 @@
import { afterAll, beforeEach, describe, expect, test } from "bun:test";
import { restoreTestGlobal } from "../restore-test-global.mjs";
const originalWindow = globalThis.window;
const originalDocument = globalThis.document;
@@ -8,7 +9,7 @@ const values = new Map();
const styles = new Map();
const eventListeners = new Map();
globalThis.window = {
const stubWindow = {
location: { href: "https://edgeever.example/settings" },
localStorage: {
getItem: (key) => values.get(key) ?? null,
@@ -20,8 +21,9 @@ globalThis.window = {
addEventListener: (name, listener) => eventListeners.set(name, listener),
removeEventListener: (name) => eventListeners.delete(name),
};
globalThis.window = stubWindow;
globalThis.document = {
const stubDocument = {
documentElement: {
classList: { contains: () => false },
dataset: {},
@@ -34,11 +36,13 @@ globalThis.document = {
},
},
};
globalThis.document = stubDocument;
globalThis.MutationObserver = class {
const StubMutationObserver = class {
observe() {}
disconnect() {}
};
globalThis.MutationObserver = StubMutationObserver;
const { EdgeEverPluginHost, applyPluginMarkdownEdits } = await import("./plugin-host.ts");
const { sha256Hex } = await import("./github-plugin-distribution.ts");
@@ -46,9 +50,9 @@ const { withRepositoryMutationEvents } = await import("../repository-events.ts")
const { results: capabilityResults } = await import('./plugin-capabilities.fixture.mjs');
afterAll(() => {
globalThis.window = originalWindow;
globalThis.document = originalDocument;
globalThis.MutationObserver = originalMutationObserver;
restoreTestGlobal("window", originalWindow, stubWindow);
restoreTestGlobal("document", originalDocument, stubDocument);
restoreTestGlobal("MutationObserver", originalMutationObserver, StubMutationObserver);
});
const repository = {
@@ -1,16 +1,20 @@
import { afterAll, expect, test } from 'bun:test';
import { restoreTestGlobal } from '../restore-test-global.mjs';
const originalWindow = globalThis.window;
const originalDocument = globalThis.document;
const originalMutationObserver = globalThis.MutationObserver;
const values = new Map();
globalThis.window = { location: { href: 'https://example.test' }, localStorage: { getItem: key => values.get(key) ?? null, setItem: (key, value) => values.set(key, String(value)), removeItem: key => values.delete(key) }, addEventListener() {}, removeEventListener() {} };
globalThis.document = { documentElement: { classList: { contains: () => false }, dataset: {}, style: { setProperty() {}, removeProperty() {} }, removeAttribute() {} } };
globalThis.MutationObserver = class { observe() {} disconnect() {} };
const stubWindow = { location: { href: 'https://example.test' }, localStorage: { getItem: key => values.get(key) ?? null, setItem: (key, value) => values.set(key, String(value)), removeItem: key => values.delete(key) }, addEventListener() {}, removeEventListener() {} };
const stubDocument = { documentElement: { classList: { contains: () => false }, dataset: {}, style: { setProperty() {}, removeProperty() {} }, removeAttribute() {} } };
const StubMutationObserver = class { observe() {} disconnect() {} };
globalThis.window = stubWindow;
globalThis.document = stubDocument;
globalThis.MutationObserver = StubMutationObserver;
const { EdgeEverPluginHost } = await import('./plugin-host');
afterAll(() => {
globalThis.window = originalWindow;
globalThis.document = originalDocument;
globalThis.MutationObserver = originalMutationObserver;
restoreTestGlobal('window', originalWindow, stubWindow);
restoreTestGlobal('document', originalDocument, stubDocument);
restoreTestGlobal('MutationObserver', originalMutationObserver, StubMutationObserver);
});
function setup() {
values.clear();
+2 -1
View File
@@ -16,7 +16,8 @@ const installTestWindow = ({ hostname = "localhost" } = {}) => {
location: { hostname, href: `http://${hostname}/` },
});
return () => {
globalThis.window = previousWindow;
if (previousWindow === undefined) delete globalThis.window;
else globalThis.window = previousWindow;
};
};
+7
View File
@@ -0,0 +1,7 @@
const restoreUnconditionally = Symbol("restore-unconditionally");
export const restoreTestGlobal = (key, original, installed = restoreUnconditionally) => {
if (installed !== restoreUnconditionally && globalThis[key] !== installed) return;
if (original === undefined) delete globalThis[key];
else globalThis[key] = original;
};
@@ -0,0 +1,23 @@
import { expect, test } from "bun:test";
import { restoreTestGlobal } from "./restore-test-global.mjs";
test("restoreTestGlobal deletes a missing global instead of shadowing it with undefined", () => {
const descriptor = Object.getOwnPropertyDescriptor(globalThis, "window");
delete globalThis.window;
globalThis.window = { localStorage: {} };
restoreTestGlobal("window", undefined, globalThis.window);
expect(Object.hasOwn(globalThis, "window")).toBe(false);
if (descriptor) Object.defineProperty(globalThis, "window", descriptor);
});
test("restoreTestGlobal leaves a global that another file replaced", () => {
const descriptor = Object.getOwnPropertyDescriptor(globalThis, "document");
const installed = { owned: true };
const replacement = { owned: false };
globalThis.document = installed;
globalThis.document = replacement;
restoreTestGlobal("document", undefined, installed);
expect(globalThis.document).toBe(replacement);
if (descriptor) Object.defineProperty(globalThis, "document", descriptor);
else delete globalThis.document;
});
+2 -1
View File
@@ -21,7 +21,8 @@ const originalWindow = globalThis.window;
const originalLocalStorage = Object.getOwnPropertyDescriptor(globalThis, "localStorage");
afterEach(() => {
globalThis.window = originalWindow;
if (originalWindow === undefined) delete globalThis.window;
else globalThis.window = originalWindow;
if (originalLocalStorage) {
Object.defineProperty(globalThis, "localStorage", originalLocalStorage);
} else {