import request from 'supertest'; import express from 'express'; import { createServer } from 'http'; import { LLMService } from '../src/services/LLMService'; // Mock the LLMService jest.mock('../src/services/LLMService'); // Mock the ws module const mockHandleWebSocketMessage = jest.fn(); const mockSessions = new Map(); const mockBroadcastToSession = jest.fn(); jest.mock('../src/ws', () => ({ sessions: mockSessions, handleWebSocketMessage: mockHandleWebSocketMessage, broadcastToSession: mockBroadcastToSession, SessionState: { SETUP: 'SETUP', GATHERING: 'GATHERING', HARMONIZING: 'HARMONIZING', FINAL: 'FINAL', ERROR: 'ERROR', }, })); // Mock the routes const app = express(); app.use(express.json()); // Import the actual router after mocks are set up import sessionsRouter from '../src/routes/sessions'; app.use('/', sessionsRouter); describe('POST /sessions', () => { beforeEach(() => { mockSessions.clear(); }); it('should create a new session and return a session ID', async () => { const response = await request(app) .post('/sessions') .send(); expect(response.status).toBe(201); expect(response.body).toHaveProperty('sessionId'); expect(typeof response.body.sessionId).toBe('string'); expect(mockSessions.has(response.body.sessionId)).toBe(true); }); }); describe('POST /sessions/:sessionId/responses', () => { const testSessionId = 'test-session-id'; const testUserId = 'test-user-id'; beforeEach(() => { mockSessions.clear(); mockHandleWebSocketMessage.mockClear(); mockBroadcastToSession.mockClear(); // Initialize a session for testing mockSessions.set(testSessionId, { state: 'GATHERING', topic: 'Test Topic', expectedResponses: 1, submittedCount: 0, responses: new Map(), clients: new Map(), finalResult: null, }); }); it('should accept a response with afraidToAsk and call handleWebSocketMessage', async () => { const responsePayload = { userId: testUserId, wants: ['More features'], accepts: ['Bug fixes'], afraidToAsk: 'A raise', }; const response = await request(app) .post(`/sessions/${testSessionId}/responses`) .send(responsePayload); expect(response.status).toBe(202); expect(response.body).toEqual({ message: 'Response submission acknowledged and processed.' }); expect(mockHandleWebSocketMessage).toHaveBeenCalledTimes(1); expect(mockHandleWebSocketMessage).toHaveBeenCalledWith( expect.any(Object), // dummyWs testSessionId, { type: 'SUBMIT_RESPONSE', clientId: testUserId, payload: { response: { wants: ['More features'], accepts: ['Bug fixes'], afraidToAsk: 'A raise', }, }, } ); }); it('should return 404 if session is not found', async () => { const responsePayload = { userId: testUserId, wants: ['More features'], accepts: ['Bug fixes'], afraidToAsk: 'A raise', }; const response = await request(app) .post(`/sessions/non-existent-session/responses`) .send(responsePayload); expect(response.status).toBe(404); expect(response.body).toEqual({ message: 'Session not found.' }); expect(mockHandleWebSocketMessage).not.toHaveBeenCalled(); }); it('should return 500 if handleWebSocketMessage throws an error', async () => { mockHandleWebSocketMessage.mockRejectedValueOnce(new Error('WebSocket processing error')); const responsePayload = { userId: testUserId, wants: ['More features'], accepts: ['Bug fixes'], afraidToAsk: 'A raise', }; const response = await request(app) .post(`/sessions/${testSessionId}/responses`) .send(responsePayload); expect(response.status).toBe(500); expect(response.body).toHaveProperty('message', 'Error processing response.'); expect(response.body).toHaveProperty('error', 'WebSocket processing error'); expect(mockHandleWebSocketMessage).toHaveBeenCalledTimes(1); }); }); describe('POST /sessions/:sessionId/terminate', () => { const testSessionId = 'session-to-terminate'; beforeEach(() => { mockSessions.clear(); // Initialize a session for testing termination mockSessions.set(testSessionId, { state: 'FINAL', topic: 'Test Topic', expectedResponses: 1, submittedCount: 1, responses: new Map([['client1', { wants: ['test'], accepts: [], noGoes: [], afraidToAsk: 'secret' }]]), clients: new Map(), finalResult: { goTo: 'test' }, }); }); it('should terminate the session and purge its data', async () => { expect(mockSessions.has(testSessionId)).toBe(true); const response = await request(app) .post(`/sessions/${testSessionId}/terminate`) .send(); expect(response.status).toBe(200); expect(response.body).toEqual({ message: 'Session terminated and data purged successfully.' }); expect(mockSessions.has(testSessionId)).toBe(false); }); it('should return 404 if session is not found', async () => { const response = await request(app) .post(`/sessions/non-existent-session/terminate`) .send(); expect(response.status).toBe(404); expect(response.body).toEqual({ message: 'Session not found.' }); }); });