Skip to content

Commit 3206d74

Browse files
puikinshclaude
andcommitted
Fix flaky localStorage test setup across Node versions
The persistThemeOptions test passed on Node 26 (local) but failed in CI on Node 22: the setup only polyfilled window.localStorage when methods were missing, but Node 22's experimental localStorage exposes methods that silently no-op without --localstorage-file, so writes were dropped and setItem was never observed. Install the in-memory polyfill unconditionally so storage behaves identically everywhere. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0a40aa6 commit 3206d74

1 file changed

Lines changed: 37 additions & 39 deletions

File tree

vitest.setup.js

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,46 +27,44 @@ if (typeof window !== 'undefined' && !window.ResizeObserver) {
2727
};
2828
}
2929

30-
// jsdom's window.localStorage in recent Vitest/jsdom combos can be a Storage
31-
// instance lacking `.clear()`/`.setItem()` — replace it with a spec-shaped
32-
// in-memory polyfill so persistence tests round-trip cleanly.
30+
// localStorage is inconsistent across Node/jsdom/Vitest combos: depending on
31+
// the runtime, `window.localStorage` may lack methods, or expose methods that
32+
// silently no-op (e.g. Node 22's experimental localStorage without
33+
// `--localstorage-file` drops every write). Method-existence checks therefore
34+
// aren't enough — Node 22 has the methods but they don't persist, which made
35+
// the persistence tests pass on Node 26 yet fail in CI on Node 22. Install a
36+
// spec-shaped in-memory polyfill unconditionally so storage behaves
37+
// identically everywhere.
3338
if (typeof window !== 'undefined') {
34-
const hasWorkingStorage =
35-
window.localStorage &&
36-
typeof window.localStorage.clear === 'function' &&
37-
typeof window.localStorage.setItem === 'function';
38-
39-
if (!hasWorkingStorage) {
40-
class MemoryStorage {
41-
constructor() {
42-
this._store = new Map();
43-
}
44-
get length() {
45-
return this._store.size;
46-
}
47-
clear() {
48-
this._store.clear();
49-
}
50-
getItem(key) {
51-
return this._store.has(key) ? this._store.get(key) : null;
52-
}
53-
setItem(key, value) {
54-
this._store.set(String(key), String(value));
55-
}
56-
removeItem(key) {
57-
this._store.delete(key);
58-
}
59-
key(index) {
60-
return Array.from(this._store.keys())[index] ?? null;
61-
}
39+
class MemoryStorage {
40+
constructor() {
41+
this._store = new Map();
42+
}
43+
get length() {
44+
return this._store.size;
45+
}
46+
clear() {
47+
this._store.clear();
48+
}
49+
getItem(key) {
50+
return this._store.has(key) ? this._store.get(key) : null;
51+
}
52+
setItem(key, value) {
53+
this._store.set(String(key), String(value));
54+
}
55+
removeItem(key) {
56+
this._store.delete(key);
57+
}
58+
key(index) {
59+
return Array.from(this._store.keys())[index] ?? null;
6260
}
63-
Object.defineProperty(window, 'localStorage', {
64-
configurable: true,
65-
value: new MemoryStorage(),
66-
});
67-
Object.defineProperty(window, 'sessionStorage', {
68-
configurable: true,
69-
value: new MemoryStorage(),
70-
});
7161
}
62+
Object.defineProperty(window, 'localStorage', {
63+
configurable: true,
64+
value: new MemoryStorage(),
65+
});
66+
Object.defineProperty(window, 'sessionStorage', {
67+
configurable: true,
68+
value: new MemoryStorage(),
69+
});
7270
}

0 commit comments

Comments
 (0)