import { describe, it, expect, vi, beforeEach } from 'vitest' import { NextRequest } from 'next/server' const mockRevalidatePath = vi.fn() vi.mock('next/cache', () => ({ revalidatePath: mockRevalidatePath, revalidateTag: vi.fn(), })) const SECRET = 'test-revalidate-secret' // matches vitest.setup.ts function makeRequest(body: unknown, token = SECRET): NextRequest { return new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: typeof body === 'string' ? body : JSON.stringify(body), headers: { 'content-type': 'application/json', authorization: `Bearer ${token}`, }, }) } let POST: (req: NextRequest) => Promise beforeEach(async () => { vi.resetModules() mockRevalidatePath.mockReset() vi.stubEnv('REVALIDATE_SECRET', SECRET) const mod = await import('@/app/api/revalidate/route') POST = mod.POST }) describe('POST /api/revalidate', () => { it('returns 401 when authorization header is missing', async () => { const req = new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: JSON.stringify({ slug: 'home' }), headers: { 'content-type': 'application/json' }, }) const res = await POST(req) expect(res.status).toBe(401) }) it('returns 401 for wrong token', async () => { const res = await POST(makeRequest({ slug: 'home' }, 'wrong-token')) expect(res.status).toBe(401) }) it('returns 401 when REVALIDATE_SECRET env is empty (no bypass)', async () => { vi.stubEnv('REVALIDATE_SECRET', '') vi.resetModules() const mod = await import('@/app/api/revalidate/route') const res = await mod.POST(makeRequest({ slug: 'home' }, '')) expect(res.status).toBe(401) }) it('returns 400 for invalid JSON body', async () => { const req = new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: 'not-json', headers: { 'content-type': 'application/json', authorization: `Bearer ${SECRET}`, }, }) const res = await POST(req) expect(res.status).toBe(400) }) it('revalidates a specific path when slug is provided', async () => { const res = await POST(makeRequest({ slug: 'about-us' })) expect(res.status).toBe(200) expect(mockRevalidatePath).toHaveBeenCalledWith('/about-us') expect((await res.json()).revalidated).toBe(true) }) it('revalidates layout when global is provided', async () => { const res = await POST(makeRequest({ global: 'header' })) expect(res.status).toBe(200) expect(mockRevalidatePath).toHaveBeenCalledWith('/', 'layout') }) it('revalidates layout when collection is provided', async () => { const res = await POST(makeRequest({ collection: 'posts' })) expect(res.status).toBe(200) expect(mockRevalidatePath).toHaveBeenCalledWith('/', 'layout') }) it('returns revalidated:true and calls no revalidation when body has none of slug/collection/global', async () => { const res = await POST(makeRequest({})) expect(res.status).toBe(200) expect(mockRevalidatePath).not.toHaveBeenCalled() }) it('returns 500 when revalidatePath throws', async () => { mockRevalidatePath.mockImplementationOnce(() => { throw new Error('cache error') }) const res = await POST(makeRequest({ slug: 'boom' })) expect(res.status).toBe(500) }) })