import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { createAuthRouter } from './auth.router.ts'; import { AuthService } from './auth.service.ts'; import { Pool } from 'pg'; import { Request, Response } from 'express'; function createMockResponse() { const res: Partial = {}; const data = { statusCode: 200, jsonPayload: null as any, cookies: {} as any }; res.status = function (code: number) { data.statusCode = code; return this as Response; }; res.json = function (payload: any) { data.jsonPayload = payload; return this as Response; }; res.cookie = function (name: string, val: string, options: any) { data.cookies[name] = { val, options }; return this as Response; }; return { mockRes: res as Response, data }; } function createMockDb(userRows: any[], sessionRows: any[] = []) { return { query: async (text: string, values: any[]) => { if (text.trim().startsWith('SELECT') && text.includes('FROM users')) { return { rows: userRows }; } return { rows: sessionRows }; } } as unknown as Pool; } describe('Auth Router (TDD)', () => { const authService = new AuthService(); describe('POST /register', () => { it('should block registrations missing username or password with a 400 status', async () => { const mockDb = createMockDb([]); const router = createAuthRouter(mockDb, authService); const mockReq = { body: { username: '' } } as unknown as Request; const { mockRes, data } = createMockResponse(); const handler = router.stack.find((l: any) => l.route.path === '/register').route.stack[0].handle; await handler(mockReq, mockRes); assert.equal(data.statusCode, 400); assert.equal(data.jsonPayload.success, false); }); }); describe('POST /login', () => { it('should successfully issue a high-entropy cookie on valid credentials', async () => { const password = 'secure-password'; const hash = await authService.hashPassword(password); // Simulate database finding the registered user const mockDb = createMockDb([{ id: 42, username: 'testuser', password_hash: hash }]); const router = createAuthRouter(mockDb, authService); const mockReq = { body: { username: 'testuser', password } } as unknown as Request; const { mockRes, data } = createMockResponse(); const handler = router.stack.find((l: any) => l.route.path === '/login').route.stack[0].handle; await handler(mockReq, mockRes); assert.equal(data.statusCode, 200); assert.equal(data.jsonPayload.success, true); assert.ok(data.cookies['session_token']); assert.equal(data.cookies['session_token'].options.httpOnly, true); assert.equal(data.cookies['session_token'].options.sameSite, 'strict'); }); it('should reject invalid passwords with a 401 status code', async () => { const hash = await authService.hashPassword('real-password'); const mockDb = createMockDb([{ id: 42, username: 'testuser', password_hash: hash }]); const router = createAuthRouter(mockDb, authService); const mockReq = { body: { username: 'testuser', password: 'wrong-password' } } as unknown as Request; const { mockRes, data } = createMockResponse(); const handler = router.stack.find((l: any) => l.route.path === '/login').route.stack[0].handle; await handler(mockReq, mockRes); assert.equal(data.statusCode, 401); assert.equal(data.jsonPayload.success, false); }); }); });