/** * Tests unitaires pour src/utils/helpers.js */ import { generateToken, generateJWT, verifyJWT, generateTicketCode, isValidEmail, isValidPhone, cleanPhone, formatDate, maskEmail, getTokenExpiry, isExpired, generateRandomPassword, getPagination, formatPaginatedResponse, } from '../../src/utils/helpers.js'; describe('Helpers - Token Generation', () => { describe('generateToken', () => { it('should generate a token of default length 32', () => { const token = generateToken(); expect(token).toHaveLength(64); // hex string is 2x the byte length }); it('should generate a token of specified length', () => { const token = generateToken(16); expect(token).toHaveLength(32); }); it('should generate unique tokens', () => { const token1 = generateToken(); const token2 = generateToken(); expect(token1).not.toBe(token2); }); }); describe('generateJWT', () => { it('should generate a valid JWT token', () => { const token = generateJWT(1, 'test@example.com', 'CLIENT'); expect(token).toBeDefined(); expect(typeof token).toBe('string'); expect(token.split('.')).toHaveLength(3); }); }); describe('verifyJWT', () => { it('should verify a valid JWT token', () => { const token = generateJWT(1, 'test@example.com', 'CLIENT'); const decoded = verifyJWT(token); expect(decoded).toBeDefined(); expect(decoded.userId).toBe(1); expect(decoded.email).toBe('test@example.com'); expect(decoded.role).toBe('CLIENT'); }); it('should return null for invalid token', () => { const decoded = verifyJWT('invalid-token'); expect(decoded).toBeNull(); }); }); }); describe('Helpers - Ticket Code Generation', () => { describe('generateTicketCode', () => { it('should generate a ticket code starting with TTP', () => { const code = generateTicketCode(); expect(code).toMatch(/^TTP/); }); it('should generate a 10-character code', () => { const code = generateTicketCode(); expect(code).toHaveLength(10); }); it('should include current year', () => { const code = generateTicketCode(); const year = new Date().getFullYear().toString(); expect(code).toContain(year); }); it('should generate unique codes', () => { const codes = new Set(); for (let i = 0; i < 100; i++) { codes.add(generateTicketCode()); } expect(codes.size).toBe(100); }); }); }); describe('Helpers - Validation', () => { describe('isValidEmail', () => { it('should return true for valid emails', () => { expect(isValidEmail('test@example.com')).toBe(true); expect(isValidEmail('user.name@domain.fr')).toBe(true); expect(isValidEmail('user+tag@example.org')).toBe(true); }); it('should return false for invalid emails', () => { expect(isValidEmail('invalid')).toBe(false); expect(isValidEmail('invalid@')).toBe(false); expect(isValidEmail('@domain.com')).toBe(false); expect(isValidEmail('')).toBe(false); }); }); describe('isValidPhone', () => { it('should return true for valid French phone numbers', () => { expect(isValidPhone('0612345678')).toBe(true); expect(isValidPhone('06 12 34 56 78')).toBe(true); expect(isValidPhone('+33612345678')).toBe(true); }); it('should return false for invalid phone numbers', () => { expect(isValidPhone('123')).toBe(false); expect(isValidPhone('')).toBe(false); }); }); describe('cleanPhone', () => { it('should remove spaces from phone number', () => { expect(cleanPhone('06 12 34 56 78')).toBe('0612345678'); }); it('should handle already clean numbers', () => { expect(cleanPhone('0612345678')).toBe('0612345678'); }); }); }); describe('Helpers - Date Functions', () => { describe('formatDate', () => { it('should format date to French locale', () => { const date = new Date('2025-01-15'); const formatted = formatDate(date); expect(formatted).toContain('2025'); }); }); describe('getTokenExpiry', () => { it('should return a future date', () => { const expiry = getTokenExpiry(24); expect(new Date(expiry).getTime()).toBeGreaterThan(Date.now()); }); }); describe('isExpired', () => { it('should return true for past dates', () => { const pastDate = new Date('2020-01-01'); expect(isExpired(pastDate)).toBe(true); }); it('should return false for future dates', () => { const futureDate = new Date('2030-01-01'); expect(isExpired(futureDate)).toBe(false); }); }); }); describe('Helpers - Security', () => { describe('maskEmail', () => { it('should mask the middle of email', () => { const masked = maskEmail('john.doe@example.com'); expect(masked).toContain('***'); expect(masked).not.toBe('john.doe@example.com'); }); }); describe('generateRandomPassword', () => { it('should generate password of specified length', () => { const password = generateRandomPassword(12); expect(password).toHaveLength(12); }); it('should generate unique passwords', () => { const p1 = generateRandomPassword(16); const p2 = generateRandomPassword(16); expect(p1).not.toBe(p2); }); }); }); describe('Helpers - Pagination', () => { describe('getPagination', () => { it('should calculate correct offset', () => { expect(getPagination(1, 10)).toEqual({ offset: 0, limit: 10 }); expect(getPagination(2, 10)).toEqual({ offset: 10, limit: 10 }); expect(getPagination(3, 20)).toEqual({ offset: 40, limit: 20 }); }); it('should handle default values', () => { const result = getPagination(); expect(result.offset).toBeDefined(); expect(result.limit).toBeDefined(); }); }); describe('formatPaginatedResponse', () => { it('should format paginated response correctly', () => { const data = [{ id: 1 }, { id: 2 }]; const response = formatPaginatedResponse(data, 100, 1, 10); expect(response.data).toEqual(data); expect(response.pagination.total).toBe(100); expect(response.pagination.page).toBe(1); expect(response.pagination.limit).toBe(10); expect(response.pagination.totalPages).toBe(10); }); }); });