/** * GET /api/auth/mode — unit tests (Plan 19-03, TDD RED → GREEN). * * Covers: * Test 5: returns { localEnabled:true, oidcEnabled:false } when no oidc_issuer in env or app_config * Test 6: returns { oidcEnabled:true } when OIDC_ISSUER env var is set * Test 6b: returns { oidcEnabled:true } when oidc_issuer is in app_config (no env var) * * Pre-auth surface: reachable without OIDC session (same as /api/setup/status). */ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; // --------------------------------------------------------------------------- // DB mock — controls app_config rows returned for oidc_issuer // --------------------------------------------------------------------------- let mockAppConfigOidcIssuer: string | null = null; vi.mock('../../src/db/client.js', () => ({ db: { execute: vi.fn().mockResolvedValue([[{ '1': 1 }]]), select: vi.fn().mockImplementation(() => ({ from: vi.fn().mockReturnValue({ where: vi.fn().mockReturnValue({ limit: vi.fn().mockImplementation(() => { if (mockAppConfigOidcIssuer) { return Promise.resolve([{ value: mockAppConfigOidcIssuer }]); } return Promise.resolve([]); }), }), }), })), insert: vi.fn().mockReturnValue({ values: vi.fn().mockReturnValue({ onDuplicateKeyUpdate: vi.fn().mockResolvedValue(undefined), }), }), }, })); vi.mock('@hono/oidc-auth', () => ({ oidcAuthMiddleware: () => async (_c: unknown, next: () => Promise) => next(), processOAuthCallback: () => async (c: { json: (v: unknown) => unknown }) => c.json({ ok: true }), getAuth: vi.fn().mockResolvedValue(null), })); vi.mock('../../src/auth/devBypass.js', () => ({ devAuthBypass: () => async (_c: unknown, next: () => Promise) => next(), // Phase 19 Option C: devSessionCookieMiddleware is a no-op in tests devSessionCookieMiddleware: () => async (_c: unknown, next: () => Promise) => next(), })); vi.mock('../../src/auth/localAuthMiddleware.js', () => ({ localAuthMiddleware: () => async (_c: unknown, next: () => Promise) => next(), })); // --------------------------------------------------------------------------- // Env snapshot // --------------------------------------------------------------------------- const originalOidcIssuer = process.env.OIDC_ISSUER; beforeEach(() => { mockAppConfigOidcIssuer = null; delete process.env.OIDC_ISSUER; vi.resetModules(); }); afterEach(() => { if (originalOidcIssuer === undefined) { delete process.env.OIDC_ISSUER; } else { process.env.OIDC_ISSUER = originalOidcIssuer; } vi.resetModules(); }); // --------------------------------------------------------------------------- // Tests // --------------------------------------------------------------------------- describe('GET /api/auth/mode', () => { it('Test 5: returns { localEnabled:true, oidcEnabled:false } when no oidc_issuer in env or app_config', async () => { delete process.env.OIDC_ISSUER; mockAppConfigOidcIssuer = null; const { app } = await import('../../src/index.js'); const res = await app.request('/api/auth/mode'); expect(res.status).toBe(200); const body = (await res.json()) as { localEnabled: boolean; oidcEnabled: boolean }; expect(body.localEnabled).toBe(true); expect(body.oidcEnabled).toBe(false); }); it('Test 6: returns { oidcEnabled:true } when OIDC_ISSUER env var is set', async () => { process.env.OIDC_ISSUER = 'https://auth.example.com'; mockAppConfigOidcIssuer = null; const { app } = await import('../../src/index.js'); const res = await app.request('/api/auth/mode'); expect(res.status).toBe(200); const body = (await res.json()) as { localEnabled: boolean; oidcEnabled: boolean }; expect(body.localEnabled).toBe(true); expect(body.oidcEnabled).toBe(true); }); it('Test 6b: returns { oidcEnabled:true } when oidc_issuer is in app_config (no env var)', async () => { delete process.env.OIDC_ISSUER; mockAppConfigOidcIssuer = 'https://auth-from-config.example.com'; const { app } = await import('../../src/index.js'); const res = await app.request('/api/auth/mode'); expect(res.status).toBe(200); const body = (await res.json()) as { localEnabled: boolean; oidcEnabled: boolean }; expect(body.localEnabled).toBe(true); expect(body.oidcEnabled).toBe(true); }); });