11/**
22 * @jest -environment node
33 */
4- import { POST } from './route' ;
4+ import { GET , POST } from './route' ;
55import { revalidatePath , revalidateTag } from 'next/cache' ;
66
77// Mock Next.js cache
@@ -15,6 +15,96 @@ jest.mock('../../../i18n/routing', () => ({
1515 AVAILABLE_LOCALES : [ 'en' , 'fr' ] ,
1616} ) ) ;
1717
18+ describe ( 'GET /api/revalidate' , ( ) => {
19+ const mockRevalidatePath = revalidatePath as jest . MockedFunction <
20+ typeof revalidatePath
21+ > ;
22+ const mockRevalidateTag = revalidateTag as jest . MockedFunction <
23+ typeof revalidateTag
24+ > ;
25+ const originalEnv = process . env ;
26+
27+ beforeEach ( ( ) => {
28+ jest . clearAllMocks ( ) ;
29+ process . env = { ...originalEnv } ;
30+ } ) ;
31+
32+ afterAll ( ( ) => {
33+ process . env = originalEnv ;
34+ } ) ;
35+
36+ it ( 'returns 500 when CRON_SECRET is not configured' , async ( ) => {
37+ delete process . env . CRON_SECRET ;
38+
39+ const request = new Request ( 'http://localhost:3000/api/revalidate' , {
40+ method : 'GET' ,
41+ headers : {
42+ authorization : 'Bearer some-secret' ,
43+ } ,
44+ } ) ;
45+
46+ const response = await GET ( request ) ;
47+ const json = await response . json ( ) ;
48+
49+ expect ( response . status ) . toBe ( 500 ) ;
50+ expect ( json ) . toEqual ( {
51+ ok : false ,
52+ error : 'Server misconfigured: CRON_SECRET missing' ,
53+ } ) ;
54+ expect ( mockRevalidatePath ) . not . toHaveBeenCalled ( ) ;
55+ expect ( mockRevalidateTag ) . not . toHaveBeenCalled ( ) ;
56+ } ) ;
57+
58+ it ( 'returns 401 when authorization header does not match' , async ( ) => {
59+ process . env . CRON_SECRET = 'correct-secret' ;
60+
61+ const request = new Request ( 'http://localhost:3000/api/revalidate' , {
62+ method : 'GET' ,
63+ headers : {
64+ authorization : 'Bearer wrong-secret' ,
65+ } ,
66+ } ) ;
67+
68+ const response = await GET ( request ) ;
69+ const json = await response . json ( ) ;
70+
71+ expect ( response . status ) . toBe ( 401 ) ;
72+ expect ( json ) . toEqual ( {
73+ ok : false ,
74+ error : 'Unauthorized' ,
75+ } ) ;
76+ expect ( mockRevalidatePath ) . not . toHaveBeenCalled ( ) ;
77+ expect ( mockRevalidateTag ) . not . toHaveBeenCalled ( ) ;
78+ } ) ;
79+
80+ it ( 'revalidates only GBFS feed pages for authorized cron requests' , async ( ) => {
81+ process . env . CRON_SECRET = 'test-secret' ;
82+
83+ const request = new Request ( 'http://localhost:3000/api/revalidate' , {
84+ method : 'GET' ,
85+ headers : {
86+ authorization : 'Bearer test-secret' ,
87+ } ,
88+ } ) ;
89+
90+ const response = await GET ( request ) ;
91+ const json = await response . json ( ) ;
92+
93+ expect ( response . status ) . toBe ( 200 ) ;
94+ expect ( json ) . toEqual ( {
95+ ok : true ,
96+ message : 'All GBFS feeds revalidated successfully' ,
97+ } ) ;
98+ expect ( mockRevalidateTag ) . toHaveBeenCalledWith ( 'feed-type-gbfs' , 'max' ) ;
99+ expect ( mockRevalidatePath ) . toHaveBeenCalledWith (
100+ '/[locale]/feeds/gbfs/[feedId]' ,
101+ 'layout' ,
102+ ) ;
103+ expect ( mockRevalidateTag ) . toHaveBeenCalledTimes ( 1 ) ;
104+ expect ( mockRevalidatePath ) . toHaveBeenCalledTimes ( 1 ) ;
105+ } ) ;
106+ } ) ;
107+
18108describe ( 'POST /api/revalidate' , ( ) => {
19109 const mockRevalidatePath = revalidatePath as jest . MockedFunction <
20110 typeof revalidatePath
0 commit comments