Files
ReadMeABook/tests/api/auth-oidc.routes.test.ts
T
kikootwo 94dbaf073b Add backend unit test framework and modularize settings UI
Introduced a Vitest-based backend unit testing framework with supporting scripts, helpers, and GitHub Actions integration. Refactored the admin settings page to a modular architecture, splitting monolithic logic into feature-specific tabs and hooks for improved maintainability and testability. Updated documentation to reflect the new testing setup and settings architecture, and added new dependencies for testing utilities.
2026-01-28 11:41:59 -05:00

77 lines
2.4 KiB
TypeScript

/**
* Component: OIDC Auth API Route Tests
* Documentation: documentation/testing.md
*/
import { beforeEach, describe, expect, it, vi } from 'vitest';
const authProviderMock = vi.hoisted(() => ({
initiateLogin: vi.fn(),
handleCallback: vi.fn(),
}));
const getBaseUrlMock = vi.hoisted(() => vi.fn(() => 'http://app'));
vi.mock('@/lib/services/auth', () => ({
getAuthProvider: async () => authProviderMock,
}));
vi.mock('@/lib/utils/url', () => ({
getBaseUrl: getBaseUrlMock,
}));
const makeRequest = (url: string) => ({
nextUrl: new URL(url),
});
describe('OIDC auth routes', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('redirects to provider on login', async () => {
authProviderMock.initiateLogin.mockResolvedValue({ redirectUrl: 'http://oidc/login' });
const { GET } = await import('@/app/api/auth/oidc/login/route');
const response = await GET();
expect(response.status).toBe(307);
expect(response.headers.get('location')).toBe('http://oidc/login');
});
it('redirects to login on missing code/state', async () => {
const { GET } = await import('@/app/api/auth/oidc/callback/route');
const response = await GET(makeRequest('http://app/api/auth/oidc/callback') as any);
expect(response.status).toBe(307);
expect(response.headers.get('location')).toContain('/login?error=');
});
it('redirects with pending approval when required', async () => {
authProviderMock.handleCallback.mockResolvedValue({ success: false, requiresApproval: true });
const { GET } = await import('@/app/api/auth/oidc/callback/route');
const response = await GET(makeRequest('http://app/api/auth/oidc/callback?code=abc&state=def') as any);
expect(response.status).toBe(307);
expect(response.headers.get('location')).toBe('http://app/login?pending=approval');
});
it('returns HTML response for successful callback', async () => {
authProviderMock.handleCallback.mockResolvedValue({
success: true,
tokens: { accessToken: 'access', refreshToken: 'refresh' },
user: { id: 'u1', username: 'user', email: 'a@b.com', avatarUrl: null, isAdmin: false },
isFirstLogin: false,
});
const { GET } = await import('@/app/api/auth/oidc/callback/route');
const response = await GET(makeRequest('http://app/api/auth/oidc/callback?code=abc&state=def') as any);
expect(response.status).toBe(200);
expect(response.headers.get('content-type')).toContain('text/html');
});
});