auth-v2-workspace.test.ts86 lines · main
1import { describe, expect, test } from 'bun:test';
2
3import { DEFAULT_AUTH_CONFIG, type AuthConfig } from './tenant-config-store.js';
4import {
5 flagsFromConfig,
6 hasAtLeastOneProvider,
7 normalizeTwoFactorFlags,
8 twoFactorFromConfig,
9 type AuthV2ProviderFlags,
10} from './auth-v2-workspace.js';
11
12describe('auth-v2-workspace — provider proof helpers', () => {
13 test('flagsFromConfig maps DEFAULT starter pack (all core ON)', () => {
14 const flags = flagsFromConfig(DEFAULT_AUTH_CONFIG);
15 expect(flags).toEqual({
16 emailPassword: true,
17 magicLink: true,
18 emailOtp: true,
19 passkey: true,
20 });
21 expect(hasAtLeastOneProvider(flags)).toBe(true);
22 });
23
24 test('flagsFromConfig reflects partial OFF (save-sticks shape)', () => {
25 const config = {
26 ...DEFAULT_AUTH_CONFIG,
27 providers: {
28 ...DEFAULT_AUTH_CONFIG.providers,
29 magicLink: { enabled: false, expiryMinutes: 15 },
30 emailOtp: { enabled: false, codeLength: 6, expiryMinutes: 5 },
31 passkey: { enabled: true },
32 emailPassword: { enabled: true },
33 },
34 } as AuthConfig;
35
36 const flags = flagsFromConfig(config);
37 expect(flags.magicLink).toBe(false);
38 expect(flags.emailOtp).toBe(false);
39 expect(flags.passkey).toBe(true);
40 expect(flags.emailPassword).toBe(true);
41 expect(hasAtLeastOneProvider(flags)).toBe(true);
42 });
43
44 test('hasAtLeastOneProvider rejects all-off (dashboard 400 rule)', () => {
45 const allOff: AuthV2ProviderFlags = {
46 emailPassword: false,
47 magicLink: false,
48 emailOtp: false,
49 passkey: false,
50 };
51 expect(hasAtLeastOneProvider(allOff)).toBe(false);
52 });
53});
54
55describe('auth-v2-workspace — Phase 8.1 two-factor / backup codes', () => {
56 test('default config has 2FA off and zero backup codes', () => {
57 const tf = twoFactorFromConfig(DEFAULT_AUTH_CONFIG);
58 expect(tf.enabled).toBe(false);
59 expect(tf.required).toBe(false);
60 expect(tf.backupCodeCount).toBe(0);
61 });
62
63 test('when 2FA is on, backupCodeCount is 10 (Better Auth amount)', () => {
64 const config = {
65 ...DEFAULT_AUTH_CONFIG,
66 twoFactor: { enabled: true, issuer: 'Acme', required: false },
67 } as AuthConfig;
68 const tf = twoFactorFromConfig(config);
69 expect(tf.enabled).toBe(true);
70 expect(tf.backupCodeCount).toBe(10);
71 });
72
73 test('normalizeTwoFactorFlags clears required when 2FA is off', () => {
74 const tf = normalizeTwoFactorFlags({ enabled: false, required: true });
75 expect(tf.enabled).toBe(false);
76 expect(tf.required).toBe(false);
77 expect(tf.backupCodeCount).toBe(0);
78 });
79
80 test('normalizeTwoFactorFlags keeps required only when enabled', () => {
81 const tf = normalizeTwoFactorFlags({ enabled: true, required: true });
82 expect(tf.enabled).toBe(true);
83 expect(tf.required).toBe(true);
84 expect(tf.backupCodeCount).toBe(10);
85 });
86});