import { describe, it, expect, vi, beforeEach } from 'vitest'; import { NextRequest } from 'next/server'; vi.mock('@/lib/verification/socratic', () => ({ runSocraticProbe: vi.fn(), })); import { POST } from '../route'; import { runSocraticProbe } from '@/lib/verification/socratic'; const mockProbe = vi.mocked(runSocraticProbe); const VALID_BODY = { gradeId: '123e4567-e89b-12d3-a456-426614174000', userId: 'user-abc', followUpText: 'I meant that closures hold a reference to the outer scope, not a copy.', }; function makeRequest(body: unknown) { return new NextRequest('http://localhost:3000/api/socratic', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); } describe('POST /api/socratic', () => { beforeEach(() => vi.clearAllMocks()); it('returns 400 when gradeId is missing', async () => { const res = await POST(makeRequest({ userId: 'u', followUpText: 'text' })); expect(res.status).toBe(400); }); it('returns 400 when gradeId is not a UUID', async () => { const res = await POST(makeRequest({ ...VALID_BODY, gradeId: 'not-a-uuid' })); expect(res.status).toBe(400); }); it('returns 400 when followUpText is empty', async () => { const res = await POST(makeRequest({ ...VALID_BODY, followUpText: '' })); expect(res.status).toBe(400); }); it('returns 200 with reply and upgradedVerdict on success', async () => { mockProbe.mockResolvedValue({ reply: 'Yes, that is correct.', upgradedVerdict: 'mastered' }); const res = await POST(makeRequest(VALID_BODY)); expect(res.status).toBe(200); const body = await res.json(); expect(body.reply).toBe('Yes, that is correct.'); expect(body.upgradedVerdict).toBe('mastered'); }); it('returns 404 when grade not found', async () => { mockProbe.mockRejectedValue( new Error(`Grade not found: ${VALID_BODY.gradeId}`), ); const res = await POST(makeRequest(VALID_BODY)); expect(res.status).toBe(404); }); it('returns 500 on unexpected error', async () => { mockProbe.mockRejectedValue(new Error('DB down')); const res = await POST(makeRequest(VALID_BODY)); expect(res.status).toBe(500); }); });