import { describe, it, expect, vi, beforeEach } from 'vitest' import { NextRequest } from 'next/server' const mockRevalidatePath = vi.fn() const mockRequest = vi.fn() const mockWith = vi.fn() vi.mock('next/cache', () => ({ revalidatePath: mockRevalidatePath })) vi.mock('@directus/sdk', () => ({ createDirectus: vi.fn(() => ({ with: mockWith })), rest: vi.fn(), staticToken: vi.fn(), readItem: vi.fn(), })) mockWith.mockReturnValue({ with: mockWith, request: mockRequest }) beforeEach(() => { vi.resetModules() mockRevalidatePath.mockReset() mockRequest.mockReset() mockWith.mockReturnValue({ with: mockWith, request: mockRequest }) process.env.REVALIDATE_SECRET = 'test-secret' process.env.DIRECTUS_URL = 'https://cms.achmad.dev' process.env.DIRECTUS_TOKEN = 'test-token' }) describe('POST /api/revalidate', () => { it('returns 401 when secret is wrong', async () => { const { POST } = await import('@/app/api/revalidate/route') const req = new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: JSON.stringify({ secret: 'wrong-secret', article_id: '123' }), }) const res = await POST(req) expect(res.status).toBe(401) expect(mockRevalidatePath).not.toHaveBeenCalled() }) it('returns 400 when article_id is missing and type is not homepage', async () => { const { POST } = await import('@/app/api/revalidate/route') const req = new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: JSON.stringify({ secret: 'test-secret' }), }) const res = await POST(req) expect(res.status).toBe(400) }) it('revalidates /, /category, and /category/slug on valid article request', async () => { mockRequest.mockResolvedValue({ slug: 'frieren-season-2', category: { slug: 'anime' }, }) const { POST } = await import('@/app/api/revalidate/route') const req = new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: JSON.stringify({ secret: 'test-secret', article_id: 'uuid-123' }), }) const res = await POST(req) expect(res.status).toBe(200) expect(mockRevalidatePath).toHaveBeenCalledWith('/') expect(mockRevalidatePath).toHaveBeenCalledWith('/anime') expect(mockRevalidatePath).toHaveBeenCalledWith('/anime/frieren-season-2') }) it('returns 404 when article is not found in Directus', async () => { mockRequest.mockResolvedValue(null) const { POST } = await import('@/app/api/revalidate/route') const req = new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: JSON.stringify({ secret: 'test-secret', article_id: 'nonexistent' }), }) const res = await POST(req) expect(res.status).toBe(404) expect(mockRevalidatePath).not.toHaveBeenCalled() }) it('revalidates only / when type is homepage', async () => { const { POST } = await import('@/app/api/revalidate/route') const req = new NextRequest('http://localhost/api/revalidate', { method: 'POST', body: JSON.stringify({ secret: 'test-secret', type: 'homepage' }), }) const res = await POST(req) expect(res.status).toBe(200) expect(mockRevalidatePath).toHaveBeenCalledTimes(1) expect(mockRevalidatePath).toHaveBeenCalledWith('/') }) })