feat: revalidate webhook endpoint with tests
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
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('/')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user