mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
fix(client): restore localStorage shadowed by Node 26 in jsdom tests
Node 26 defines localStorage as a native global accessor returning undefined unless started with --localstorage-file. Vitest's jsdom environment sets window === globalThis, so that accessor shadows jsdom's own, breaking all 20 test files that touch localStorage (479 tests). sessionStorage is unaffected. Install an in-memory Storage in a setup file when the global is missing. Not using --localstorage-file: it is file-backed and shared across vitest's parallel workers, which would leak state between test files. Suite: 3572/3572 passing (was 3093/3572). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// Vitest global setup for the jsdom suite.
|
||||
//
|
||||
// Why this exists: Node 26 defines `localStorage` as a native global accessor
|
||||
// that returns `undefined` unless the process was started with
|
||||
// `--localstorage-file`. Vitest's jsdom environment makes `window === globalThis`,
|
||||
// so that native accessor shadows the one jsdom would otherwise install, and
|
||||
// every test touching `localStorage` throws. `sessionStorage` is unaffected —
|
||||
// jsdom's implementation still wins there.
|
||||
//
|
||||
// We deliberately do NOT pass `--localstorage-file`: it is file-backed and would
|
||||
// be shared by vitest's parallel workers, leaking state between test files.
|
||||
|
||||
/**
|
||||
* Minimal in-memory Web Storage implementation used to replace the shadowed
|
||||
* `localStorage` global.
|
||||
*
|
||||
* Matches the spec on the three points app code depends on: `getItem` returns
|
||||
* `null` (not `undefined`) for absent keys, `setItem` coerces values to strings,
|
||||
* and `key(i)` enumerates in insertion order — src/lib/themes.ts:30 and
|
||||
* src/components/settings/AdvancedTab.ts:351 both sweep storage via `key(i)`
|
||||
* over `length`, so ordering is load-bearing.
|
||||
*/
|
||||
function createMemoryStorage(): Storage {
|
||||
const store = new Map<string, string>();
|
||||
|
||||
return {
|
||||
get length(): number {
|
||||
return store.size;
|
||||
},
|
||||
key(index: number): string | null {
|
||||
return [...store.keys()][index] ?? null;
|
||||
},
|
||||
getItem(key: string): string | null {
|
||||
return store.get(String(key)) ?? null;
|
||||
},
|
||||
setItem(key: string, value: string): void {
|
||||
store.set(String(key), String(value));
|
||||
},
|
||||
removeItem(key: string): void {
|
||||
store.delete(String(key));
|
||||
},
|
||||
clear(): void {
|
||||
store.clear();
|
||||
},
|
||||
} satisfies Storage;
|
||||
}
|
||||
|
||||
if (typeof globalThis.localStorage === "undefined") {
|
||||
Object.defineProperty(globalThis, "localStorage", {
|
||||
value: createMemoryStorage(),
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
@@ -13,6 +13,8 @@ export default defineConfig({
|
||||
},
|
||||
test: {
|
||||
environment: "jsdom",
|
||||
// Restores `localStorage`, which Node 26 shadows out of the jsdom global.
|
||||
setupFiles: ["./tests/setup.ts"],
|
||||
// Both the `tests/**/*.test.ts` suite and component-local
|
||||
// `src/**/*.test.ts` files are picked up.
|
||||
include: ["tests/**/*.test.ts", "src/**/*.test.ts"],
|
||||
|
||||
Reference in New Issue
Block a user