import { describe, it, expect, vi, beforeEach } from 'vitest'; import { NextRequest } from 'next/server'; import { requireAuth } from '@/lib/auth-helpers'; const mockTx = { delete: vi.fn().mockReturnValue({ where: vi.fn().mockResolvedValue([]) }), }; const mockDb = { transaction: vi.fn().mockImplementation(async (fn: (tx: typeof mockTx) => Promise) => fn(mockTx)), }; vi.mock('@/lib/db', () => ({ db: mockDb })); vi.mock('@/lib/db/schema', () => ({ users: {}, responses: {}, mastery: {}, journeyInstances: {}, })); vi.mock('drizzle-orm', () => ({ eq: vi.fn((col, val) => ({ col, val })), })); function makeRequest(): NextRequest { return new NextRequest('http://localhost/api/user/account', { method: 'DELETE' }); } describe('DELETE /api/user/account', () => { beforeEach(() => { vi.clearAllMocks(); mockTx.delete.mockReturnValue({ where: vi.fn().mockResolvedValue([]) }); mockDb.transaction.mockImplementation(async (fn: (tx: typeof mockTx) => Promise) => fn(mockTx)); }); it('returns 200 {ok:true} on happy path', async () => { const { DELETE } = await import('../route'); const res = await DELETE(); const body = await res.json(); expect(res.status).toBe(200); expect(body).toEqual({ ok: true }); }); it('runs transaction and deletes all four tables', async () => { const { DELETE } = await import('../route'); await DELETE(); expect(mockDb.transaction).toHaveBeenCalledOnce(); expect(mockTx.delete).toHaveBeenCalledTimes(4); }); it('returns 401 when requireAuth throws', async () => { vi.mocked(requireAuth).mockRejectedValueOnce(new Error('redirect')); const { DELETE } = await import('../route'); await expect(DELETE()).rejects.toThrow('redirect'); }); it('propagates transaction errors', async () => { mockDb.transaction.mockRejectedValueOnce(new Error('db error')); const { DELETE } = await import('../route'); await expect(DELETE()).rejects.toThrow('db error'); }); });