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.
This commit is contained in:
kikootwo
2026-01-15 16:49:59 -05:00
parent b3f89d67bb
commit 94dbaf073b
127 changed files with 23549 additions and 2868 deletions
+177
View File
@@ -0,0 +1,177 @@
/**
* Component: Auth Middleware Tests
* Documentation: documentation/backend/services/auth.md
*/
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { NextResponse } from 'next/server';
import { createPrismaMock } from '../helpers/prisma';
const prismaMock = createPrismaMock();
const verifyAccessTokenMock = vi.fn();
vi.mock('@/lib/db', () => ({
prisma: prismaMock,
}));
vi.mock('@/lib/utils/jwt', () => ({
verifyAccessToken: verifyAccessTokenMock,
}));
const makeRequest = (authHeader?: string) => ({
headers: {
get: (key: string) => {
if (key.toLowerCase() === 'authorization') {
return authHeader ?? null;
}
return null;
},
},
});
describe('auth middleware', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('rejects requests without a token', async () => {
const { requireAuth } = await import('@/lib/middleware/auth');
const response = await requireAuth(makeRequest() as any, vi.fn());
const payload = await response.json();
expect(response.status).toBe(401);
expect(payload.error).toBe('Unauthorized');
});
it('rejects invalid tokens', async () => {
verifyAccessTokenMock.mockReturnValue(null);
const { requireAuth } = await import('@/lib/middleware/auth');
const response = await requireAuth(makeRequest('Bearer badtoken') as any, vi.fn());
const payload = await response.json();
expect(response.status).toBe(401);
expect(payload.message).toMatch(/invalid/i);
});
it('rejects tokens for missing users', async () => {
verifyAccessTokenMock.mockReturnValue({
sub: 'user-1',
plexId: 'plex-1',
username: 'user',
role: 'user',
iat: 1,
exp: 2,
});
prismaMock.user.findUnique.mockResolvedValue(null);
const { requireAuth } = await import('@/lib/middleware/auth');
const response = await requireAuth(makeRequest('Bearer token') as any, vi.fn());
const payload = await response.json();
expect(response.status).toBe(401);
expect(payload.message).toMatch(/user not found/i);
});
it('passes authenticated requests to handler', async () => {
verifyAccessTokenMock.mockReturnValue({
sub: 'user-1',
plexId: 'plex-1',
username: 'user',
role: 'user',
iat: 1,
exp: 2,
});
prismaMock.user.findUnique.mockResolvedValue({ id: 'user-1' });
const { requireAuth } = await import('@/lib/middleware/auth');
const handler = vi.fn(async (req: any) =>
NextResponse.json({ ok: true, userId: req.user?.id })
);
const response = await requireAuth(makeRequest('Bearer token') as any, handler);
const payload = await response.json();
expect(handler).toHaveBeenCalled();
expect(payload.userId).toBe('user-1');
});
it('requires admin role', async () => {
const { requireAdmin } = await import('@/lib/middleware/auth');
const noUserResponse = await requireAdmin({} as any, vi.fn());
expect(noUserResponse.status).toBe(401);
const response = await requireAdmin({ user: { role: 'user' } } as any, vi.fn());
expect(response.status).toBe(403);
});
it('allows admin users', async () => {
const { requireAdmin } = await import('@/lib/middleware/auth');
const handler = vi.fn(async () => NextResponse.json({ ok: true }));
const response = await requireAdmin({ user: { role: 'admin' } } as any, handler);
expect(handler).toHaveBeenCalled();
expect(response.status).toBe(200);
});
it('requires local admin with setup flag', async () => {
prismaMock.user.findUnique.mockResolvedValue({
isSetupAdmin: true,
plexId: 'local-admin',
});
const { requireLocalAdmin } = await import('@/lib/middleware/auth');
const handler = vi.fn(async () => NextResponse.json({ ok: true }));
const response = await requireLocalAdmin(
{ user: { id: 'user-1', role: 'admin' } } as any,
handler
);
expect(handler).toHaveBeenCalled();
expect(response.status).toBe(200);
});
it('rejects non-local admins', async () => {
prismaMock.user.findUnique.mockResolvedValue({
isSetupAdmin: false,
plexId: 'plex-user',
});
const { requireLocalAdmin } = await import('@/lib/middleware/auth');
const response = await requireLocalAdmin(
{ user: { id: 'user-1', role: 'admin' } } as any,
vi.fn()
);
expect(response.status).toBe(403);
});
it('checks local admin helper', async () => {
prismaMock.user.findUnique.mockResolvedValue({
isSetupAdmin: true,
plexId: 'local-admin',
});
const { isLocalAdmin } = await import('@/lib/middleware/auth');
const result = await isLocalAdmin('user-1');
expect(result).toBe(true);
});
it('returns current user from token', async () => {
verifyAccessTokenMock.mockReturnValue({
sub: 'user-1',
plexId: 'plex-1',
username: 'user',
role: 'admin',
iat: 1,
exp: 2,
});
const { getCurrentUser, isAdmin } = await import('@/lib/middleware/auth');
const payload = getCurrentUser(makeRequest('Bearer token') as any);
expect(payload?.sub).toBe('user-1');
expect(isAdmin(payload)).toBe(true);
});
});