TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1import { beforeAll, describe, expect, it } from 'vitest';2import { hashPassword, verifyPassword, encryptSecret, decryptSecret, signPayload, verifyPayload, numericCode, recoveryCode, normalizeRecoveryCode, hmacToken } from './crypto';3import { newTotpSecret, verifyTotp, currentTotp, totpUri } from './totp';4import { passwordStrength } from './password-strength';56beforeAll(() => {7 process.env.SESSION_SECRET = 'test-secret-test-secret-test-secret';8});910describe('password hashing', () => {11 it('hashes and verifies with scrypt', async () => {12 const h = await hashPassword('correct horse battery');13 expect(h.startsWith('scrypt$')).toBe(true);14 expect(await verifyPassword('correct horse battery', h)).toBe(true);15 expect(await verifyPassword('wrong', h)).toBe(false);16 expect(await verifyPassword('x', null)).toBe(false);17 });18 it('strength meter', () => {19 expect(passwordStrength('short').score).toBe(0);20 expect(passwordStrength('password12').score).toBe(0);21 expect(passwordStrength('aaaaaaaaaaaa').score).toBe(0);22 expect(passwordStrength('Tr0ub4dor&3xyz!!').score).toBeGreaterThanOrEqual(2);23 expect(passwordStrength('correct horse battery staple hymn').score).toBe(4);24 });25});2627describe('codes & secrets', () => {28 it('numeric codes are 6 digits and hmac is stable', () => {29 for (let i = 0; i < 50; i++) expect(numericCode(6)).toMatch(/^\d{6}$/);30 expect(hmacToken('a', 'x')).toBe(hmacToken('a', 'x'));31 expect(hmacToken('a', 'x')).not.toBe(hmacToken('a', 'y'));32 });33 it('recovery codes normalise', () => {34 const c = recoveryCode();35 expect(c).toMatch(/^[A-Z2-9]{5}-[A-Z2-9]{5}$/);36 expect(normalizeRecoveryCode(c.toLowerCase().replace('-', ' '))).toBe(c);37 });38 it('aes-gcm roundtrip', () => {39 const enc = encryptSecret('JBSWY3DPEHPK3PXP');40 expect(enc).not.toContain('JBSWY3DPEHPK3PXP');41 expect(decryptSecret(enc)).toBe('JBSWY3DPEHPK3PXP');42 });43 it('signed payloads expire and detect tampering', () => {44 const t = signPayload({ uid: 'usr_1', stage: 'mfa' }, 60);45 expect(verifyPayload<{ uid: string }>(t)?.uid).toBe('usr_1');46 expect(verifyPayload(`${t}x`)).toBeNull();47 const expired = signPayload({ uid: 'usr_1' }, -1);48 expect(verifyPayload(expired)).toBeNull();49 });50});5152describe('totp', () => {53 it('generates and validates', () => {54 const s = newTotpSecret();55 expect(totpUri(s, 'a@b.c')).toContain('otpauth://totp/RareIndex:a%40b.c');56 const code = currentTotp(s);57 expect(verifyTotp(s, code)).not.toBeNull();58 expect(verifyTotp(s, '000000') === null || code === '000000').toBe(true);59 expect(verifyTotp(s, 'abc')).toBeNull();60 });61});62