diff --git a/backend/tests/health.test.ts b/backend/tests/health.test.ts index 7d97973a..76704dd6 100644 --- a/backend/tests/health.test.ts +++ b/backend/tests/health.test.ts @@ -97,4 +97,75 @@ describe('GET /health', () => { expect(typeof res.body.indexerLag).toBe('number'); expect(typeof res.body.uptime).toBe('number'); }); + + describe('response shape contract assertions', () => { + const EXPECTED_HEALTH_KEYS = ['db', 'indexerEnabled', 'indexerLag', 'status', 'uptime']; + + it('matches exact response shape contract in healthy state (200 OK)', async () => { + vi.stubEnv('STREAM_CONTRACT_ID', 'CSOME_CONTRACT_ADDRESS'); + prismaMock.indexerState.findUnique.mockResolvedValue(makeState(15)); + + const res = await request(app).get('/health'); + expect(res.status).toBe(200); + + // Verify exact keys set + expect(Object.keys(res.body).sort()).toEqual(EXPECTED_HEALTH_KEYS); + + // Verify type & contract values + expect(res.body).toEqual({ + status: 'ok', + db: 'connected', + indexerEnabled: true, + indexerLag: expect.any(Number), + uptime: expect.any(Number), + }); + expect(res.body.indexerLag).toBe(15); + expect(res.body.uptime).toBeGreaterThanOrEqual(0); + }); + + it('matches exact response shape contract in degraded state (indexer lagging > 60s -> 503)', async () => { + vi.stubEnv('STREAM_CONTRACT_ID', 'CSOME_CONTRACT_ADDRESS'); + prismaMock.indexerState.findUnique.mockResolvedValue(makeState(120)); + + const res = await request(app).get('/health'); + expect(res.status).toBe(503); + + // Verify exact keys set + expect(Object.keys(res.body).sort()).toEqual(EXPECTED_HEALTH_KEYS); + + // Verify type & contract values + expect(res.body).toEqual({ + status: 'degraded', + db: 'connected', + indexerEnabled: true, + indexerLag: expect.any(Number), + uptime: expect.any(Number), + }); + expect(res.body.indexerLag).toBe(120); + expect(res.body.uptime).toBeGreaterThanOrEqual(0); + }); + + it('matches exact response shape contract in degraded state (DB disconnected -> 503)', async () => { + vi.stubEnv('STREAM_CONTRACT_ID', 'CSOME_CONTRACT_ADDRESS'); + prismaMock.$queryRaw.mockRejectedValue(new Error('DB Connection Error')); + prismaMock.indexerState.findUnique.mockResolvedValue(makeState(5)); + + const res = await request(app).get('/health'); + expect(res.status).toBe(503); + + // Verify exact keys set + expect(Object.keys(res.body).sort()).toEqual(EXPECTED_HEALTH_KEYS); + + // Verify type & contract values + expect(res.body).toEqual({ + status: 'degraded', + db: 'disconnected', + indexerEnabled: true, + indexerLag: 5, + uptime: expect.any(Number), + }); + expect(res.body.uptime).toBeGreaterThanOrEqual(0); + }); + }); }); +