import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { getAnonymousId, setAnonymousId, clearAnonymousId, isAnonymousTrackingEnabled, } from '../src/utils/identity'; const ANONYMOUS_ID_KEY = 'light_sentry_aid'; describe('identity utils', () => { beforeEach(() => { localStorage.clear(); }); afterEach(() => { vi.restoreAllMocks(); }); describe('getAnonymousId', () => { it('should generate and store a new anonymous ID when none exists', () => { const id = getAnonymousId(); expect(id).toBeTruthy(); expect(typeof id).toBe('string'); expect(id!.length).toBeGreaterThan(0); const stored = localStorage.getItem(ANONYMOUS_ID_KEY); expect(stored).toBe(id); }); it('should return the same ID on subsequent calls', () => { const id1 = getAnonymousId(); const id2 = getAnonymousId(); expect(id1).toBe(id2); }); it('should return existing ID from localStorage', () => { localStorage.setItem(ANONYMOUS_ID_KEY, 'existing-id-123'); const id = getAnonymousId(); expect(id).toBe('existing-id-123'); }); it('should return null when localStorage is not available', () => { const originalLocalStorage = (global as any).localStorage; delete (global as any).localStorage; const id = getAnonymousId(); expect(id).toBeNull(); (global as any).localStorage = originalLocalStorage; }); it('should return null when localStorage throws', () => { const getItemSpy = vi.spyOn(Storage.prototype, 'getItem').mockImplementation(() => { throw new Error('Storage error'); }); const id = getAnonymousId(); expect(id).toBeNull(); getItemSpy.mockRestore(); }); it('should generate UUID format (32 hex chars without hyphens)', () => { const id = getAnonymousId(); expect(id).toMatch(/^[a-f0-9]{32}$/i); }); }); describe('setAnonymousId', () => { it('should set custom anonymous ID', () => { const result = setAnonymousId('custom-id-123'); expect(result).toBe(true); expect(localStorage.getItem(ANONYMOUS_ID_KEY)).toBe('custom-id-123'); }); it('should override existing ID', () => { localStorage.setItem(ANONYMOUS_ID_KEY, 'old-id'); setAnonymousId('new-id'); expect(localStorage.getItem(ANONYMOUS_ID_KEY)).toBe('new-id'); }); it('should return false when localStorage is not available', () => { const originalLocalStorage = (global as any).localStorage; delete (global as any).localStorage; const result = setAnonymousId('test-id'); expect(result).toBe(false); (global as any).localStorage = originalLocalStorage; }); it('should return false when localStorage throws', () => { const setItemSpy = vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => { throw new Error('Storage error'); }); const result = setAnonymousId('test-id'); expect(result).toBe(false); setItemSpy.mockRestore(); }); it('should set empty string ID', () => { const result = setAnonymousId(''); expect(result).toBe(true); expect(localStorage.getItem(ANONYMOUS_ID_KEY)).toBe(''); }); }); describe('clearAnonymousId', () => { it('should clear existing anonymous ID', () => { localStorage.setItem(ANONYMOUS_ID_KEY, 'existing-id'); const result = clearAnonymousId(); expect(result).toBe(true); expect(localStorage.getItem(ANONYMOUS_ID_KEY)).toBeNull(); }); it('should return true even when no ID exists', () => { const result = clearAnonymousId(); expect(result).toBe(true); }); it('should return false when localStorage is not available', () => { const originalLocalStorage = (global as any).localStorage; delete (global as any).localStorage; const result = clearAnonymousId(); expect(result).toBe(false); (global as any).localStorage = originalLocalStorage; }); it('should return false when localStorage throws', () => { const removeItemSpy = vi.spyOn(Storage.prototype, 'removeItem').mockImplementation(() => { throw new Error('Storage error'); }); const result = clearAnonymousId(); expect(result).toBe(false); removeItemSpy.mockRestore(); }); }); describe('isAnonymousTrackingEnabled', () => { it('should return true when trackAnonymousUsers is undefined', () => { expect(isAnonymousTrackingEnabled({})).toBe(true); }); it('should return true when trackAnonymousUsers is true', () => { expect(isAnonymousTrackingEnabled({ trackAnonymousUsers: true })).toBe(true); }); it('should return false when trackAnonymousUsers is false', () => { expect(isAnonymousTrackingEnabled({ trackAnonymousUsers: false })).toBe(false); }); it('should return true for other truthy values', () => { expect(isAnonymousTrackingEnabled({ trackAnonymousUsers: 1 as any })).toBe(true); expect(isAnonymousTrackingEnabled({ trackAnonymousUsers: 'yes' as any })).toBe(true); }); }); describe('integration: full lifecycle', () => { it('should handle set -> get -> clear flow', () => { const id1 = getAnonymousId(); expect(id1).toBeTruthy(); setAnonymousId('custom-user-id'); const id2 = getAnonymousId(); expect(id2).toBe('custom-user-id'); clearAnonymousId(); const id3 = getAnonymousId(); expect(id3).toBeTruthy(); expect(id3).not.toBe('custom-user-id'); expect(id3).not.toBe(id1); }); }); });