-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathvitest.setup.ts
More file actions
72 lines (59 loc) · 2.16 KB
/
vitest.setup.ts
File metadata and controls
72 lines (59 loc) · 2.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import '@testing-library/jest-dom';
// ---------------------------------------------------------------------------
// Web Storage polyfill — Node.js 22+ ships a stub `localStorage` / `sessionStorage`
// on `globalThis` that has NO methods (setItem, getItem, etc.) unless the process
// was started with `--localstorage-file`. Vitest's jsdom environment sets up proper
// Storage objects on `window`, but in worker threads the Node.js stub can shadow them.
//
// This setup file replaces both globals with a real in-memory implementation so that
// any test code — whether it accesses `localStorage`, `window.localStorage`, or
// `globalThis.localStorage` — gets a fully-functional Storage API.
// ---------------------------------------------------------------------------
class InMemoryStorage implements Storage {
private store: Map<string, string> = new Map();
get length() {
return this.store.size;
}
clear() {
this.store.clear();
}
getItem(key: string): string | null {
return this.store.has(key) ? (this.store.get(key) as string) : null;
}
key(index: number): string | null {
return [...this.store.keys()][index] ?? null;
}
removeItem(key: string) {
this.store.delete(key);
}
setItem(key: string, value: string) {
this.store.set(key, value);
}
}
function hasWorkingStorage(storageName: 'localStorage' | 'sessionStorage'): boolean {
const descriptor = Object.getOwnPropertyDescriptor(globalThis, storageName);
if (!descriptor) {
return false;
}
if ('value' in descriptor) {
return typeof descriptor.value?.setItem === 'function';
}
// Node 22 exposes stub storage globals behind accessors that emit warnings
// when touched without `--localstorage-file`. Replace accessor-backed values
// outright instead of probing them.
return false;
}
if (!hasWorkingStorage('localStorage')) {
Object.defineProperty(globalThis, 'localStorage', {
value: new InMemoryStorage(),
writable: true,
configurable: true,
});
}
if (!hasWorkingStorage('sessionStorage')) {
Object.defineProperty(globalThis, 'sessionStorage', {
value: new InMemoryStorage(),
writable: true,
configurable: true,
});
}