process.env.JWT_SECRET = 'test-secret'; // The pure helpers under test never touch the database. jest.mock('../src/config/db', () => ({})); const { generateCode, hashCode, hashDeviceToken, maskEmail, maskPhone, hasRealEmail, } = require('../src/utils/twoFactor'); describe('generateCode', () => { test('always returns exactly six digits', () => { for (let i = 0; i < 500; i++) { expect(generateCode()).toMatch(/^\d{6}$/); } }); }); describe('hashCode / hashDeviceToken', () => { test('is deterministic and never returns the input', () => { expect(hashCode('123456')).toBe(hashCode('123456')); expect(hashCode('123456')).not.toContain('123456'); expect(hashCode('123456')).toMatch(/^[0-9a-f]{64}$/); }); test('different codes hash differently', () => { expect(hashCode('123456')).not.toBe(hashCode('123457')); }); test('code and device-token hashes are namespaced apart', () => { expect(hashCode('123456')).not.toBe(hashDeviceToken('123456')); }); test('depends on JWT_SECRET', () => { const before = hashCode('123456'); process.env.JWT_SECRET = 'another-secret'; expect(hashCode('123456')).not.toBe(before); process.env.JWT_SECRET = 'test-secret'; }); }); describe('masking', () => { test('maskEmail keeps the first letter and the domain', () => { expect(maskEmail('jane@example.com')).toBe('j•••@example.com'); }); test('maskEmail copes with junk input', () => { expect(maskEmail('')).toBe('•••'); expect(maskEmail(null)).toBe('•••'); }); test('maskPhone keeps only the last four digits', () => { expect(maskPhone('27821234567')).toBe('••• ••• 4567'); expect(maskPhone('+27 82 123 4567')).toBe('••• ••• 4567'); }); }); describe('hasRealEmail', () => { test('accepts a normal address', () => { expect(hasRealEmail({ email: 'jane@example.com' })).toBe(true); }); test('rejects guest and deleted placeholders and missing values', () => { expect(hasRealEmail({ email: 'abc@guest.local' })).toBe(false); expect(hasRealEmail({ email: 'deleted-1@deleted.invalid' })).toBe(false); expect(hasRealEmail({ email: 'deleted-1@deleted.local' })).toBe(false); expect(hasRealEmail({})).toBe(false); expect(hasRealEmail(null)).toBe(false); }); });