import { describe, it, expect, beforeEach } from 'vitest'; import 'fake-indexeddb/auto'; import { SecureStorage } from './secure-storage.js'; describe('SecureStorage', () => { let storage: SecureStorage; beforeEach(async () => { storage = new SecureStorage('com.test.app'); await storage.clear(); }); // ── Basic CRUD ────────────────────────────────── it('set and get', async () => { await storage.set('token', 'abc123'); const val = await storage.get('token'); expect(val).toBe('abc123'); }); it('get returns null for missing key', async () => { const val = await storage.get('nonexistent'); expect(val).toBeNull(); }); it('overwrite existing key', async () => { await storage.set('token', 'first'); await storage.set('token', 'second'); const val = await storage.get('token'); expect(val).toBe('second'); }); it('delete removes value', async () => { await storage.set('token', 'abc'); await storage.delete('token'); const val = await storage.get('token'); expect(val).toBeNull(); }); it('delete non-existent key does not throw', async () => { await expect(storage.delete('nope')).resolves.toBeUndefined(); }); // ── Clear ─────────────────────────────────────── it('clear removes all values', async () => { await storage.set('a', '1'); await storage.set('b', '2'); await storage.clear(); expect(await storage.get('a')).toBeNull(); expect(await storage.get('b')).toBeNull(); }); // ── Has ───────────────────────────────────────── it('has returns true for existing key', async () => { await storage.set('x', 'val'); expect(await storage.has('x')).toBe(true); }); it('has returns false for missing key', async () => { expect(await storage.has('missing')).toBe(false); }); // ── Keys ──────────────────────────────────────── it('keys lists stored keys', async () => { await storage.set('alpha', '1'); await storage.set('beta', '2'); const keys = await storage.keys(); expect(keys.sort()).toEqual(['alpha', 'beta']); }); it('keys returns empty for fresh storage', async () => { const keys = await storage.keys(); expect(keys).toEqual([]); }); // ── Namespace isolation ───────────────────────── it('different namespaces are isolated', async () => { const s1 = new SecureStorage('ns1'); const s2 = new SecureStorage('ns2'); await s1.set('key', 'from-s1'); await s2.set('key', 'from-s2'); expect(await s1.get('key')).toBe('from-s1'); expect(await s2.get('key')).toBe('from-s2'); }); // ── Data types ────────────────────────────────── it('empty string', async () => { await storage.set('empty', ''); const val = await storage.get('empty'); expect(val).toBe(''); }); it('unicode values', async () => { const text = 'こんにちは世界 🌍 مرحبا Ñoño'; await storage.set('unicode', text); expect(await storage.get('unicode')).toBe(text); }); it('large value', async () => { const big = 'X'.repeat(100_000); await storage.set('big', big); expect(await storage.get('big')).toBe(big); }); it('JSON string value', async () => { const json = JSON.stringify({ token: 'abc', user: { id: 1 } }); await storage.set('session', json); const parsed = JSON.parse((await storage.get('session'))!); expect(parsed.token).toBe('abc'); expect(parsed.user.id).toBe(1); }); // ── isSupported ───────────────────────────────── it('isSupported returns true in test environment', () => { expect(SecureStorage.isSupported()).toBe(true); }); });