import { describe, expect, it } from 'vitest'; import type { TFunction } from 'i18next'; import { resolveAuthError } from './auth-errors'; // Echo the key so we can assert which generic fallback path ran. const t = ((key: string) => key) as unknown as TFunction; // All copy resolves through t(); the mock echoes the key, so we assert on keys. describe('resolveAuthError', () => { it('maps 429 to a rate-limit message on every flow', () => { const r = resolveAuthError({ status: 429 }, 'login', t); expect(r.message).toBe('auth.errorRateLimited'); expect(r.action).toBeNull(); }); it('maps a duplicate-email signup to "email taken" with a log-in affordance', () => { const err = { status: 400, response: { data: { email: { code: 'validation_not_unique' } } } }; const r = resolveAuthError(err, 'register', t); expect(r.message).toBe('auth.errorEmailTaken'); expect(r.action).toBe('switchToLogin'); }); it('maps a 400 login failure to invalid credentials (not a raw PB string)', () => { const r = resolveAuthError({ status: 400 }, 'login', t); expect(r.message).toBe('auth.errorInvalidCredentials'); expect(r.message).not.toMatch(/Failed to authenticate/); }); it('maps a weak-password signup', () => { const err = { status: 400, response: { data: { password: { code: 'validation_length_out_of_range' } } }, }; const r = resolveAuthError(err, 'register', t); expect(r.message).toBe('auth.errorPasswordWeak'); }); it('falls back to the existing generic key for unknown login errors', () => { expect(resolveAuthError({ status: 500 }, 'login', t).message).toBe('auth.loginFailed'); }); it('treats a missing status as a network error', () => { const r = resolveAuthError(new Error('boom'), 'login', t); expect(r.message).toBe('auth.errorNetwork'); }); });