From 84ab9fb9a03b8b6b9fae67d33032d15cfbff4c7b Mon Sep 17 00:00:00 2001 From: namdamdoi68-oss Date: Wed, 29 Jul 2026 08:43:05 +0700 Subject: [PATCH] test(health): add response shape contract tests for healthy and degraded states Signed-off-by: namdamdoi68-oss --- backend/tests/health.test.ts | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) 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); + }); + }); }); +