import { describe, it, expect, vi, beforeEach } from 'vitest'; import { ConsentStorage } from './ConsentStorage'; import type { ConsentConfig, ConsentState } from '../types'; describe('ConsentStorage', () => { let storage: ConsentStorage; const mockConfig: ConsentConfig = { apiEndpoint: 'https://api.example.com', siteId: 'test-site', debug: false, consent: { rememberDays: 365, }, }; const mockConsent: ConsentState = { categories: { essential: true, functional: true, analytics: false, marketing: false, social: false, }, vendors: {}, timestamp: '2024-01-15T10:00:00.000Z', version: '1.0.0', }; beforeEach(() => { localStorage.clear(); storage = new ConsentStorage(mockConfig); }); describe('constructor', () => { it('should create storage with site-specific key', () => { expect(storage).toBeDefined(); }); }); describe('get', () => { it('should return null when no consent stored', () => { const result = storage.get(); expect(result).toBeNull(); }); it('should return consent when valid data exists', () => { storage.set(mockConsent); const result = storage.get(); expect(result).toBeDefined(); expect(result?.categories.essential).toBe(true); expect(result?.categories.analytics).toBe(false); }); it('should return null and clear when version mismatch', () => { // Manually set invalid version in storage const storageKey = `bp_consent_${mockConfig.siteId}`; localStorage.setItem( storageKey, JSON.stringify({ version: 'invalid', consent: mockConsent, signature: 'test', }) ); const result = storage.get(); expect(result).toBeNull(); }); it('should return null and clear when signature invalid', () => { const storageKey = `bp_consent_${mockConfig.siteId}`; localStorage.setItem( storageKey, JSON.stringify({ version: '1', consent: mockConsent, signature: 'invalid-signature', }) ); const result = storage.get(); expect(result).toBeNull(); }); it('should return null when JSON is invalid', () => { const storageKey = `bp_consent_${mockConfig.siteId}`; localStorage.setItem(storageKey, 'invalid-json'); const result = storage.get(); expect(result).toBeNull(); }); }); describe('set', () => { it('should store consent in localStorage', () => { storage.set(mockConsent); const storageKey = `bp_consent_${mockConfig.siteId}`; const stored = localStorage.getItem(storageKey); expect(stored).toBeDefined(); expect(stored).toContain('"version":"1"'); }); it('should set a cookie for SSR support', () => { storage.set(mockConsent); expect(document.cookie).toContain(`bp_consent_${mockConfig.siteId}`); }); it('should include signature in stored data', () => { storage.set(mockConsent); const storageKey = `bp_consent_${mockConfig.siteId}`; const stored = JSON.parse(localStorage.getItem(storageKey) || '{}'); expect(stored.signature).toBeDefined(); expect(typeof stored.signature).toBe('string'); }); }); describe('clear', () => { it('should remove consent from localStorage', () => { storage.set(mockConsent); storage.clear(); const result = storage.get(); expect(result).toBeNull(); }); it('should clear the cookie', () => { storage.set(mockConsent); storage.clear(); // Cookie should be cleared (expired) expect(document.cookie).toContain('expires='); }); }); describe('exists', () => { it('should return false when no consent exists', () => { expect(storage.exists()).toBe(false); }); it('should return true when consent exists', () => { storage.set(mockConsent); expect(storage.exists()).toBe(true); }); }); describe('signature verification', () => { it('should detect tampered consent data', () => { storage.set(mockConsent); const storageKey = `bp_consent_${mockConfig.siteId}`; const stored = JSON.parse(localStorage.getItem(storageKey) || '{}'); // Tamper with the data stored.consent.categories.marketing = true; localStorage.setItem(storageKey, JSON.stringify(stored)); const result = storage.get(); expect(result).toBeNull(); // Signature mismatch should clear }); }); describe('debug mode', () => { it('should log when debug is enabled', () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); const debugStorage = new ConsentStorage({ ...mockConfig, debug: true, }); debugStorage.set(mockConsent); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); }); describe('cookie settings', () => { it('should set Secure flag on HTTPS', () => { storage.set(mockConsent); expect(document.cookie).toContain('Secure'); }); it('should set SameSite=Lax', () => { storage.set(mockConsent); expect(document.cookie).toContain('SameSite=Lax'); }); it('should set expiration based on rememberDays', () => { storage.set(mockConsent); expect(document.cookie).toContain('expires='); }); }); describe('different sites', () => { it('should isolate storage by siteId', () => { const storage1 = new ConsentStorage({ ...mockConfig, siteId: 'site-1' }); const storage2 = new ConsentStorage({ ...mockConfig, siteId: 'site-2' }); storage1.set(mockConsent); expect(storage1.exists()).toBe(true); expect(storage2.exists()).toBe(false); }); }); });