// server/test/errorLogRoutes.test.js const test = require('node:test'); const assert = require('node:assert/strict'); const http = require('node:http'); require('dotenv').config(); // ─── Helpers ──────────────────────────────────────────────────────────────── function httpRequest(server, options, body) { return new Promise((resolve, reject) => { const addr = server.address(); const req = http.request( { host: '127.0.0.1', port: addr.port, ...options }, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { resolve({ status: res.statusCode, body: JSON.parse(data) }); } catch { resolve({ status: res.statusCode, body: data }); } }); } ); req.on('error', reject); if (body) { req.setHeader('Content-Type', 'application/json'); req.write(JSON.stringify(body)); } req.end(); }); } function startTestServer() { // Fresh copies each run so module-level state is clean delete require.cache[require.resolve('../utils/errorLogger')]; delete require.cache[require.resolve('../controllers/errorLogController')]; delete require.cache[require.resolve('../routes/errorLogRoutes')]; const express = require('express'); const cookieParser = require('cookie-parser'); const { protect, adminOnly } = require('../middleware/authMiddleware'); const { getErrorLogs, clearErrorLogs } = require('../controllers/errorLogController'); const app = express(); app.use(express.json()); app.use(cookieParser()); app.get('/api/admin/errors', protect, adminOnly, getErrorLogs); app.delete('/api/admin/errors', protect, adminOnly, clearErrorLogs); const server = http.createServer(app); return new Promise((resolve) => server.listen(0, '127.0.0.1', () => resolve(server))); } function makeAdminToken() { const jwt = require('jsonwebtoken'); const { env } = require('../configs/env'); return jwt.sign( { id: '507f1f77bcf86cd799439011' }, env.jwtSecret || 'test-secret-32-characters-minimum!!', { expiresIn: '1h' } ); } function mockAdminUser(role = 'admin') { const AdminUser = require('../models/AdminUser'); const original = AdminUser.findById.bind(AdminUser); AdminUser.findById = () => ({ select: () => ({ lean: async () => ({ _id: '507f1f77bcf86cd799439011', username: 'testadmin', role, isActive: true, }), }), }); return () => { AdminUser.findById = original; }; } // ─── Tests ─────────────────────────────────────────────────────────────────── test('GET /api/admin/errors returns paginated error log shape', async () => { const server = await startTestServer(); const restore = mockAdminUser('admin'); const token = makeAdminToken(); try { const { logError } = require('../utils/errorLogger'); logError(new Error('test error for GET')); const result = await httpRequest(server, { path: '/api/admin/errors?page=1&pageSize=10', method: 'GET', headers: { Cookie: `token=${token}` }, }); assert.equal(result.status, 200); assert.equal(result.body.success, true); assert.ok(Array.isArray(result.body.items), 'items must be an array'); assert.ok(typeof result.body.total === 'number', 'total must be a number'); assert.ok(typeof result.body.page === 'number', 'page must be a number'); assert.ok(typeof result.body.pageSize === 'number', 'pageSize must be a number'); assert.ok(typeof result.body.totalPages === 'number', 'totalPages must be a number'); } finally { restore(); await new Promise((r) => server.close(r)); } }); test('GET /api/admin/errors returns 401 with no token', async () => { const server = await startTestServer(); try { const result = await httpRequest(server, { path: '/api/admin/errors', method: 'GET', }); assert.equal(result.status, 401); } finally { await new Promise((r) => server.close(r)); } }); test('GET /api/admin/errors returns 403 for non-admin role', async () => { const server = await startTestServer(); const restore = mockAdminUser('viewer'); const token = makeAdminToken(); try { const result = await httpRequest(server, { path: '/api/admin/errors', method: 'GET', headers: { Cookie: `token=${token}` }, }); assert.equal(result.status, 403); } finally { restore(); await new Promise((r) => server.close(r)); } }); test('DELETE /api/admin/errors clears the memory buffer', async () => { const server = await startTestServer(); const restore = mockAdminUser('admin'); const token = makeAdminToken(); try { const { logError } = require('../utils/errorLogger'); logError(new Error('error before clear')); const deleteResult = await httpRequest(server, { path: '/api/admin/errors', method: 'DELETE', headers: { Cookie: `token=${token}` }, }); assert.equal(deleteResult.status, 200); assert.equal(deleteResult.body.success, true); assert.equal(deleteResult.body.cleared, true); const getResult = await httpRequest(server, { path: '/api/admin/errors?page=1&pageSize=10', method: 'GET', headers: { Cookie: `token=${token}` }, }); assert.equal(getResult.body.total, 0); assert.deepEqual(getResult.body.items, []); } finally { restore(); await new Promise((r) => server.close(r)); } }); test('DELETE /api/admin/errors returns 401 with no token', async () => { const server = await startTestServer(); try { const result = await httpRequest(server, { path: '/api/admin/errors', method: 'DELETE', }); assert.equal(result.status, 401); } finally { await new Promise((r) => server.close(r)); } }); test('DELETE /api/admin/errors returns 403 for non-admin role', async () => { const server = await startTestServer(); const restore = mockAdminUser('viewer'); const token = makeAdminToken(); try { const result = await httpRequest(server, { path: '/api/admin/errors', method: 'DELETE', headers: { Cookie: `token=${token}` }, }); assert.equal(result.status, 403); } finally { restore(); await new Promise((r) => server.close(r)); } });