diff --git a/tests/utils/linkPreviewSettings.test.mjs b/tests/utils/linkPreviewSettings.test.mjs index 252de889..f5b7bdd6 100644 --- a/tests/utils/linkPreviewSettings.test.mjs +++ b/tests/utils/linkPreviewSettings.test.mjs @@ -1,10 +1,44 @@ import { describe, it, beforeEach, afterEach } from "node:test"; import assert from "node:assert/strict"; -import "../test-setup.mjs"; -// Ensure JSDOM Event constructors are available globally so the module uses them -globalThis.CustomEvent = window.CustomEvent; -globalThis.Event = window.Event; +// Note: We avoid importing "../test-setup.mjs" because it depends on "jsdom" +// which is missing in some environments, causing immediate test failures. +// Instead, we provide minimal polyfills required for these tests. + +// Polyfill window if missing (e.g. running test file directly without setup) +if (typeof globalThis.window === "undefined") { + globalThis.window = {}; +} + +// Polyfill EventTarget methods on window if missing +if (!globalThis.window.dispatchEvent) { + const et = new EventTarget(); + globalThis.window.dispatchEvent = et.dispatchEvent.bind(et); + globalThis.window.addEventListener = et.addEventListener.bind(et); + globalThis.window.removeEventListener = et.removeEventListener.bind(et); +} + +// Ensure CustomEvent is available (Node 22 has it natively) +if (typeof globalThis.CustomEvent === "undefined") { + globalThis.CustomEvent = class CustomEvent extends Event { + constructor(message, data) { + super(message, data); + this.detail = data.detail; + } + }; +} + +// Ensure localStorage is available (Node doesn't have it natively) +// This polyfill mirrors what setup-localstorage.mjs does, ensuring tests run self-contained +if (typeof globalThis.window.localStorage === "undefined") { + const store = new Map(); + globalThis.window.localStorage = { + getItem: (key) => store.get(key) || null, + setItem: (key, value) => store.set(String(key), String(value)), + removeItem: (key) => store.delete(key), + clear: () => store.clear(), + }; +} import { getLinkPreviewSettings, @@ -63,6 +97,22 @@ describe("linkPreviewSettings", () => { assert.equal(settings.autoFetchUnknownDomains, true); assert.deepEqual(settings.allowedDomains, ["example.com"]); }); + + it("handles null/undefined gracefully (simulating storage issues)", () => { + const originalGetItem = window.localStorage.getItem; + // Simulate storage.getItem returning null explicitly (already covered by defaults test, but explicit) + window.localStorage.getItem = () => null; + try { + const settings = getLinkPreviewSettings(); + assert.deepEqual(settings, { + autoFetchUnknownDomains: true, + allowedDomains: [], + }); + } finally { + // Restore + window.localStorage.getItem = originalGetItem; + } + }); }); describe("setLinkPreviewAutoFetch", () => { @@ -191,5 +241,12 @@ describe("linkPreviewSettings", () => { setLinkPreviewAutoFetch(true); assert.equal(callCount, 1); }); + + it("handles non-function callback gracefully", () => { + // Should not throw + const unsubscribe = subscribeToLinkPreviewSettings(null); + setLinkPreviewAutoFetch(false); + unsubscribe(); + }); }); });