import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { validateSync } from 'class-validator'; import { describe, expect, it, vi } from 'vitest'; import { SendMessageDto } from '../../conversations/conversations.dto.js'; import { ChatRequestDto } from '../chat.dto.js'; import { validateSocketSession } from '../chat.gateway-auth.js'; describe('Chat controller source hardening', () => { it('applies AuthGuard and reads the current user', () => { const source = readFileSync(resolve('src/chat/chat.controller.ts'), 'utf8'); expect(source).toContain('@UseGuards(AuthGuard)'); expect(source).toContain('@CurrentUser() user: { id: string }'); }); }); describe('WebSocket session authentication', () => { it('returns null when the handshake does not resolve to a session', async () => { const result = await validateSocketSession( {}, { api: { getSession: vi.fn().mockResolvedValue(null), }, }, ); expect(result).toBeNull(); }); it('returns the resolved session when Better Auth accepts the headers', async () => { const session = { user: { id: 'user-1' }, session: { id: 'session-1' } }; const result = await validateSocketSession( { cookie: 'session=abc' }, { api: { getSession: vi.fn().mockResolvedValue(session), }, }, ); expect(result).toBe(session); }); }); describe('Chat DTO validation', () => { it('rejects unsupported message roles and system messages', () => { const dto = Object.assign(new SendMessageDto(), { content: 'hello', role: 'system', }); const errors = validateSync(dto); expect(errors.length).toBeGreaterThan(0); }); it('rejects oversized conversation message content above 32000 characters', () => { const dto = Object.assign(new SendMessageDto(), { content: 'x'.repeat(32_001), role: 'user', }); const errors = validateSync(dto); expect(errors.length).toBeGreaterThan(0); }); it('rejects oversized chat content above 10000 characters', () => { const dto = Object.assign(new ChatRequestDto(), { content: 'x'.repeat(10_001), }); const errors = validateSync(dto); expect(errors.length).toBeGreaterThan(0); }); });