import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; import { Socket } from 'socket.io'; import { NotificationsGateway } from './notifications.gateway'; import { JwtStrategy } from '../auth/jwt.strategy'; import { AuthService } from '../auth/auth.service'; import { NotificationService } from '../services/notification.service'; describe('notification socket sessions', () => { const jwt = new JwtService({ secret: 'test-only-socket-secret' }); const validateUser = jest.fn(); const notifications = { getUnreadCount: jest.fn(async () => 0), getRecentNotifications: jest.fn(async () => []), markAllAsRead: jest.fn(), }; let gateway: NotificationsGateway; const socket = (token: string) => ({ id: 'socket-1', data: {}, handshake: { headers: {}, query: {}, auth: { token } }, join: jest.fn(), emit: jest.fn(), disconnect: jest.fn(), }) as unknown as Socket; const token = (type = 'access', expiresIn = 300) => jwt.sign({ sub: 'user-1', type }, { expiresIn }); beforeEach(() => { jest.clearAllMocks(); validateUser.mockResolvedValue({ id: 'user-1', organizationId: 'org-1' }); const strategy = new JwtStrategy(new ConfigService({ JWT_SECRET: 'test-only-socket-secret' }), { validateUser, } as unknown as AuthService); gateway = new NotificationsGateway( jwt, notifications as unknown as NotificationService, strategy ); }); it.each(['refresh', 'unknown'])('rejects %s tokens before any data is sent', async type => { const client = socket(token(type)); await gateway.handleConnection(client); expect(client.disconnect).toHaveBeenCalled(); expect(client.emit).not.toHaveBeenCalled(); }); it('rejects expired and disabled sessions', async () => { const expired = socket(token('access', -1)); await gateway.handleConnection(expired); expect(expired.emit).not.toHaveBeenCalled(); validateUser.mockResolvedValue(null); const disabled = socket(token()); await gateway.handleConnection(disabled); expect(disabled.emit).not.toHaveBeenCalled(); }); it('rechecks the account on messages after a valid connection', async () => { const client = socket(token()); await gateway.handleConnection(client); expect(client.emit).toHaveBeenCalledWith('unread_count', { count: 0 }); validateUser.mockResolvedValue(null); const result = await gateway.handleMarkAllAsRead(client); expect(result.success).toBe(false); expect(notifications.markAllAsRead).not.toHaveBeenCalled(); expect(client.disconnect).toHaveBeenCalled(); }); });