const express = require('express'); const fetch = require('node-fetch'); jest.mock('../database/mariadb', () => ({ logToFile: jest.fn(), })); jest.mock('../database/sessionModel', () => ({ validateSession: jest.fn(), deleteSession: jest.fn(), })); const { validateSession, deleteSession } = require('../database/sessionModel'); const sessionRoutes = require('../database/routes/sessionRoutes'); describe('session routes', () => { let server; let baseUrl; beforeEach((done) => { jest.clearAllMocks(); const app = express(); app.use(express.json()); app.use('/api/sessions', sessionRoutes); server = app.listen(0, () => { baseUrl = `http://127.0.0.1:${server.address().port}`; done(); }); }); afterEach((done) => { server.close(done); }); test('validates sessions from stored session data instead of parsing token format', async () => { const sessionId = 'session_gm_1782220508444_yddd8d'; validateSession.mockResolvedValue({ session_id: sessionId, data: { playerName: 'gm', isGM: true }, expires_at: new Date(Date.now() + 60_000), }); const res = await fetch(`${baseUrl}/api/sessions/validate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sessionId }), }); expect(res.status).toBe(200); await expect(res.json()).resolves.toEqual({ valid: true, playerName: 'gm' }); expect(validateSession).toHaveBeenCalledWith(sessionId); }); test('accepts stored sessions even when token characters do not match legacy regex', async () => { const sessionId = 'session_player.name_1782220508444_ABC-123'; validateSession.mockResolvedValue({ session_id: sessionId, data: { playerName: 'player.name' }, expires_at: new Date(Date.now() + 60_000), }); const res = await fetch(`${baseUrl}/api/sessions/validate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sessionId }), }); expect(res.status).toBe(200); await expect(res.json()).resolves.toEqual({ valid: true, playerName: 'player.name' }); }); test('rejects missing or expired sessions', async () => { validateSession.mockResolvedValue(null); const res = await fetch(`${baseUrl}/api/sessions/validate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sessionId: 'missing-session' }), }); expect(res.status).toBe(401); await expect(res.json()).resolves.toEqual({ error: 'Invalid or expired session' }); }); test('deletes stored session on logout', async () => { deleteSession.mockResolvedValue(undefined); const res = await fetch(`${baseUrl}/api/sessions/logout`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sessionId: 'session_gm_123' }), }); expect(res.status).toBe(200); await expect(res.json()).resolves.toEqual({ success: true }); expect(deleteSession).toHaveBeenCalledWith('session_gm_123'); }); });