/** @jest-environment node */ import { GET } from '@/app/(frontend)/release.json/route'; import { readFile } from 'node:fs/promises'; jest.mock('node:fs/promises', () => ({ readFile: jest.fn() })); const realFetch = global.fetch; const identity = { sha: 'a'.repeat(40), build_id: 'b'.repeat(32) }; beforeEach(() => { jest.mocked(readFile).mockResolvedValue(JSON.stringify(identity)); global.fetch = jest.fn(async () => Response.json(identity)); }); afterEach(() => { global.fetch = realFetch; jest.resetAllMocks(); }); test('reports immutable file identity and backend identity without caching', async () => { const response = await GET(); expect(response.status).toBe(200); expect(response.headers.get('Cache-Control')).toBe('no-store'); expect(await response.json()).toEqual({ frontend: identity, backend: identity }); expect(fetch).toHaveBeenCalledWith(expect.stringMatching(/\/api\/release$/), expect.objectContaining({ cache: 'no-store', signal: expect.anything() })); }); test('missing build metadata cannot pass the release gate', async () => { jest.mocked(readFile).mockRejectedValueOnce(new Error('missing file')); expect((await GET()).status).toBe(503); }); test('backend failure cannot pass the release gate', async () => { jest.mocked(fetch).mockResolvedValueOnce(new Response('', { status: 503 })); expect((await GET()).status).toBe(503); });