import { describe, it, expect, vi, beforeEach } from 'vitest' vi.mock('@/lib/prisma', () => ({ prisma: { claudeQuestion: { updateMany: vi.fn() }, loginPairing: { updateMany: vi.fn() }, }, })) import { prisma } from '@/lib/prisma' import { POST } from '@/app/api/cron/expire-questions/route' const mockPrisma = prisma as unknown as { claudeQuestion: { updateMany: ReturnType } loginPairing: { updateMany: ReturnType } } const SECRET = 'test-cron-secret-abc123' function makeReq(headers: Record = {}): Request { return new Request('http://localhost:3000/api/cron/expire-questions', { method: 'POST', headers, }) } beforeEach(() => { vi.clearAllMocks() process.env.CRON_SECRET = SECRET mockPrisma.claudeQuestion.updateMany.mockResolvedValue({ count: 0 }) mockPrisma.loginPairing.updateMany.mockResolvedValue({ count: 0 }) }) describe('POST /api/cron/expire-questions', () => { it('401 zonder Authorization-header', async () => { const res = await POST(makeReq()) expect(res.status).toBe(401) expect(mockPrisma.claudeQuestion.updateMany).not.toHaveBeenCalled() expect(mockPrisma.loginPairing.updateMany).not.toHaveBeenCalled() }) it('401 met verkeerde secret', async () => { const res = await POST(makeReq({ authorization: 'Bearer wrong-secret' })) expect(res.status).toBe(401) }) it('401 als CRON_SECRET niet is gezet (faal-veilig)', async () => { delete process.env.CRON_SECRET const res = await POST(makeReq({ authorization: 'Bearer ' + SECRET })) expect(res.status).toBe(401) }) it('200 met juiste secret + beide updateMany aangeroepen', async () => { mockPrisma.claudeQuestion.updateMany.mockResolvedValue({ count: 3 }) mockPrisma.loginPairing.updateMany.mockResolvedValue({ count: 1 }) const res = await POST(makeReq({ authorization: 'Bearer ' + SECRET })) expect(res.status).toBe(200) const body = await res.json() expect(body).toMatchObject({ expired_questions: 3, expired_pairings: 1, }) expect(body.ran_at).toMatch(/^\d{4}-\d{2}-\d{2}T/) // Question-update: status='open' AND expires_at < now → 'expired' const qArg = mockPrisma.claudeQuestion.updateMany.mock.calls[0][0] expect(qArg.where).toMatchObject({ status: 'open' }) expect(qArg.where.expires_at).toMatchObject({ lt: expect.any(Date) }) expect(qArg.data).toEqual({ status: 'expired' }) // Pairing-update: status='pending' AND expires_at < now → 'cancelled' const pArg = mockPrisma.loginPairing.updateMany.mock.calls[0][0] expect(pArg.where).toMatchObject({ status: 'pending' }) expect(pArg.data).toEqual({ status: 'cancelled' }) }) })