import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import http from 'node:http'; import { readFileSync } from 'node:fs'; import { join } from 'node:path'; describe('api auth contract', () => { it('returns ok for liveness-style health response', async () => { const server = http.createServer((req, res) => { if (req.url === '/api/v1/health/live') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end( JSON.stringify({ status: 'ok', service: 'api', timestamp: new Date().toISOString(), }), ); return; } res.writeHead(404); res.end(); }); await new Promise((resolve) => server.listen(0, resolve)); const addr = server.address(); assert.ok(addr && typeof addr === 'object'); const port = addr.port; const response = await fetch(`http://127.0.0.1:${port}/api/v1/health/live`); assert.equal(response.status, 200); const body = await response.json(); assert.equal(body.status, 'ok'); assert.equal(body.service, 'api'); await new Promise((resolve, reject) => server.close((err) => (err ? reject(err) : resolve())), ); }); it('documents auth module routes in source', () => { const authControllerPath = join( process.cwd(), 'src', 'auth', 'auth.controller.ts', ); const meControllerPath = join(process.cwd(), 'src', 'auth', 'me.controller.ts'); const authSource = readFileSync(authControllerPath, 'utf8'); const meSource = readFileSync(meControllerPath, 'utf8'); const combined = `${authSource}\n${meSource}`; const expectedSnippets = [ "@Post('register')", "@Post('login')", "@Post('logout')", "@Post('verify-email')", "@Post('resend-verification')", "@Post('forgot-password')", "@Post('reset-password')", "@Post('2fa/setup')", "@Post('2fa/confirm')", "@Post('2fa/verify')", "@Post('2fa/disable')", "@Get()", "@Get('sessions')", "@Delete('sessions/:id')", "@Controller('auth')", "@Controller('me')", ]; for (const snippet of expectedSnippets) { assert.ok(combined.includes(snippet), `missing ${snippet}`); } }); });