import { Test, TestingModule } from '@nestjs/testing'; import { WebSocketGateway } from './websocket.gateway'; import { Server, Socket } from 'socket.io'; import { describe, it, expect, vi, beforeEach } from 'vitest'; interface AuthenticatedSocket extends Socket { data: { userId: string; workspaceId: string; }; } describe('WebSocketGateway', () => { let gateway: WebSocketGateway; let mockServer: Server; let mockClient: AuthenticatedSocket; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [WebSocketGateway], }).compile(); gateway = module.get(WebSocketGateway); // Mock Socket.IO server mockServer = { to: vi.fn().mockReturnThis(), emit: vi.fn(), } as unknown as Server; // Mock authenticated client mockClient = { id: 'test-socket-id', join: vi.fn(), leave: vi.fn(), emit: vi.fn(), data: { userId: 'user-123', workspaceId: 'workspace-456', }, handshake: { auth: { token: 'valid-token', }, }, } as unknown as AuthenticatedSocket; gateway.server = mockServer; }); describe('handleConnection', () => { it('should join client to workspace room on connection', async () => { await gateway.handleConnection(mockClient); expect(mockClient.join).toHaveBeenCalledWith('workspace:workspace-456'); }); it('should reject connection without authentication', async () => { const unauthClient = { ...mockClient, data: {}, disconnect: vi.fn(), } as unknown as AuthenticatedSocket; await gateway.handleConnection(unauthClient); expect(unauthClient.disconnect).toHaveBeenCalled(); }); }); describe('handleDisconnect', () => { it('should leave workspace room on disconnect', () => { gateway.handleDisconnect(mockClient); expect(mockClient.leave).toHaveBeenCalledWith('workspace:workspace-456'); }); }); describe('emitTaskCreated', () => { it('should emit task:created event to workspace room', () => { const task = { id: 'task-1', title: 'Test Task', workspaceId: 'workspace-456', }; gateway.emitTaskCreated('workspace-456', task); expect(mockServer.to).toHaveBeenCalledWith('workspace:workspace-456'); expect(mockServer.emit).toHaveBeenCalledWith('task:created', task); }); }); describe('emitTaskUpdated', () => { it('should emit task:updated event to workspace room', () => { const task = { id: 'task-1', title: 'Updated Task', workspaceId: 'workspace-456', }; gateway.emitTaskUpdated('workspace-456', task); expect(mockServer.to).toHaveBeenCalledWith('workspace:workspace-456'); expect(mockServer.emit).toHaveBeenCalledWith('task:updated', task); }); }); describe('emitTaskDeleted', () => { it('should emit task:deleted event to workspace room', () => { const taskId = 'task-1'; gateway.emitTaskDeleted('workspace-456', taskId); expect(mockServer.to).toHaveBeenCalledWith('workspace:workspace-456'); expect(mockServer.emit).toHaveBeenCalledWith('task:deleted', { id: taskId }); }); }); describe('emitEventCreated', () => { it('should emit event:created event to workspace room', () => { const event = { id: 'event-1', title: 'Test Event', workspaceId: 'workspace-456', }; gateway.emitEventCreated('workspace-456', event); expect(mockServer.to).toHaveBeenCalledWith('workspace:workspace-456'); expect(mockServer.emit).toHaveBeenCalledWith('event:created', event); }); }); describe('emitEventUpdated', () => { it('should emit event:updated event to workspace room', () => { const event = { id: 'event-1', title: 'Updated Event', workspaceId: 'workspace-456', }; gateway.emitEventUpdated('workspace-456', event); expect(mockServer.to).toHaveBeenCalledWith('workspace:workspace-456'); expect(mockServer.emit).toHaveBeenCalledWith('event:updated', event); }); }); describe('emitEventDeleted', () => { it('should emit event:deleted event to workspace room', () => { const eventId = 'event-1'; gateway.emitEventDeleted('workspace-456', eventId); expect(mockServer.to).toHaveBeenCalledWith('workspace:workspace-456'); expect(mockServer.emit).toHaveBeenCalledWith('event:deleted', { id: eventId }); }); }); describe('emitProjectUpdated', () => { it('should emit project:updated event to workspace room', () => { const project = { id: 'project-1', name: 'Updated Project', workspaceId: 'workspace-456', }; gateway.emitProjectUpdated('workspace-456', project); expect(mockServer.to).toHaveBeenCalledWith('workspace:workspace-456'); expect(mockServer.emit).toHaveBeenCalledWith('project:updated', project); }); }); });