169 lines
5.5 KiB
TypeScript
169 lines
5.5 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|