import { test } from 'node:test'; import assert from 'node:assert/strict'; import { createStore } from 'jotai'; import { getLocalStorageItem, setLocalStorageItem, atomWithLocalStorage, } from './atomWithLocalStorage'; // These helpers read/write the real `localStorage` global, which node lacks, so // we install a small in-memory mock before each case. `atomWithLocalStorage` // also registers a `window` storage listener via `onMount`; we only drive the // pure read/write path through a jotai store (no onMount), so `window` is not // required here. const installStorage = (): Map => { const map = new Map(); (globalThis as { localStorage?: unknown }).localStorage = { getItem: (k: string) => (map.has(k) ? map.get(k)! : null), setItem: (k: string, v: string) => { map.set(k, v); }, removeItem: (k: string) => { map.delete(k); }, }; return map; }; test('getLocalStorageItem returns the default when the key is absent', () => { installStorage(); assert.deepEqual(getLocalStorageItem('missing', { a: 1 }), { a: 1 }); assert.equal(getLocalStorageItem('missing', 7), 7); }); test('getLocalStorageItem maps the literal string "undefined" to undefined', () => { const store = installStorage(); store.set('k', 'undefined'); assert.equal(getLocalStorageItem('k', 'fallback'), undefined); }); test('getLocalStorageItem parses stored JSON', () => { const store = installStorage(); store.set('k', JSON.stringify({ nested: [1, 2, 3] })); assert.deepEqual(getLocalStorageItem('k', null), { nested: [1, 2, 3] }); }); test('getLocalStorageItem returns the default on malformed JSON', () => { const store = installStorage(); store.set('k', '{ not valid json'); assert.equal(getLocalStorageItem('k', 'fallback'), 'fallback'); }); test('setLocalStorageItem writes the JSON-serialized value', () => { const store = installStorage(); setLocalStorageItem('k', { hello: 'world' }); assert.equal(store.get('k'), JSON.stringify({ hello: 'world' })); }); test('round-trips a value through set + get', () => { installStorage(); setLocalStorageItem('k', [1, 'two', { three: true }]); assert.deepEqual(getLocalStorageItem('k', null), [1, 'two', { three: true }]); }); test('atomWithLocalStorage seeds the atom from getItem on creation', () => { installStorage(); const seeded = atomWithLocalStorage( 'k', () => 42, () => undefined, ); const store = createStore(); assert.equal(store.get(seeded), 42); }); test('atomWithLocalStorage write-through updates BOTH the atom and storage', () => { installStorage(); const writes: Array<[string, number]> = []; const theAtom = atomWithLocalStorage( 'k', () => 0, (key, value) => { writes.push([key, value]); }, ); const store = createStore(); store.set(theAtom, 5); // Atom value reflects the write... assert.equal(store.get(theAtom), 5); // ...and setItem was invoked with the key + new value. assert.deepEqual(writes, [['k', 5]]); }); test('atomWithLocalStorage persists through the real setLocalStorageItem helper', () => { const backing = installStorage(); const theAtom = atomWithLocalStorage<{ count: number }>( 'k', (key) => getLocalStorageItem(key, { count: 0 }), (key, value) => setLocalStorageItem(key, value), ); const store = createStore(); store.set(theAtom, { count: 9 }); assert.equal(backing.get('k'), JSON.stringify({ count: 9 })); assert.deepEqual(store.get(theAtom), { count: 9 }); });