import { describe, expect, it } from 'vitest'; import { generateDeviceToken, generateFriendlyId, hashToken, normaliseMac, tokenMatches, } from './auth'; describe('generateDeviceToken', () => { it('is URL-safe and long enough to be worth nothing to a guesser', () => { const token = generateDeviceToken(); expect(token).toMatch(/^[A-Za-z0-9_-]+$/); expect(token.length).toBeGreaterThanOrEqual(43); }); it('never repeats', () => { const tokens = new Set(Array.from({ length: 50 }, generateDeviceToken)); expect(tokens.size).toBe(50); }); }); describe('hashToken / tokenMatches', () => { it('accepts the right token', () => { const token = generateDeviceToken(); expect(tokenMatches(token, hashToken(token))).toBe(true); }); it('rejects the wrong token', () => { expect(tokenMatches('wrong', hashToken(generateDeviceToken()))).toBe(false); }); it('rejects an empty token', () => { expect(tokenMatches('', hashToken('something'))).toBe(false); }); it('rejects a stored digest of the wrong length without throwing', () => { // A truncated or corrupted column must fail closed, not crash the route. expect(tokenMatches('token', 'abcd')).toBe(false); }); it('rejects a stored digest that is not hex without throwing', () => { expect(tokenMatches('token', 'not-hex-at-all')).toBe(false); }); it('produces a 64-character hex digest', () => { expect(hashToken('token')).toMatch(/^[0-9a-f]{64}$/); }); }); describe('generateFriendlyId', () => { it('uses only characters that survive being read aloud', () => { for (let attempt = 0; attempt < 50; attempt += 1) { expect(generateFriendlyId()).toMatch(/^[ABCDEFGHJKLMNPQRSTUVWXYZ23456789]{6}$/); } }); it('honours a requested length', () => { expect(generateFriendlyId(10)).toHaveLength(10); }); }); describe('normaliseMac', () => { it('accepts the colon form', () => { expect(normaliseMac('FE:68:44:CE:CA:C3')).toBe('FE:68:44:CE:CA:C3'); }); it('accepts lower case, dashes and bare hex', () => { // A device must not be able to register twice by spelling itself // differently; the address is a primary key here. expect(normaliseMac('fe:68:44:ce:ca:c3')).toBe('FE:68:44:CE:CA:C3'); expect(normaliseMac('fe-68-44-ce-ca-c3')).toBe('FE:68:44:CE:CA:C3'); expect(normaliseMac('fe6844ceCAc3')).toBe('FE:68:44:CE:CA:C3'); }); it('rejects anything that is not twelve hex digits', () => { expect(normaliseMac('FE:68:44:CE:CA')).toBeNull(); expect(normaliseMac('not a mac')).toBeNull(); expect(normaliseMac('')).toBeNull(); expect(normaliseMac(null)).toBeNull(); expect(normaliseMac(undefined)).toBeNull(); }); });