gongxiangp2/app/api/health/route.test.ts
chenpei 7326e273e1 fix: harden media upload and release safety
Protect upload cleanup and atomic completion paths, add durable media worker leases and brand asset validation, and introduce verified migration/bootstrap/deployment gates.
2026-08-12 18:04:08 +08:00

86 lines
2.7 KiB
TypeScript

/** @jest-environment node */
import { NextRequest } from 'next/server'
import { GET } from '@/app/api/health/route'
import { prisma } from '@/lib/prisma'
import { redis } from '@/lib/upload-sessions-redis'
import { readFileSync } from 'fs'
jest.mock('fs', () => ({
...jest.requireActual('fs'),
readFileSync: jest.fn(),
}))
jest.mock('@/lib/prisma', () => ({
prisma: {
$queryRaw: jest.fn(),
},
}))
jest.mock('@/lib/upload-sessions-redis', () => ({
redis: {
ping: jest.fn(),
},
}))
describe('/api/health deployment identity', () => {
const originalUseRedis = process.env.USE_REDIS
const originalRedisUrl = process.env.REDIS_URL
const originalCommit = process.env.DEPLOYMENT_COMMIT
const bakedCommit = '0123456789abcdef0123456789abcdef01234567'
beforeEach(() => {
jest.clearAllMocks()
process.env.USE_REDIS = 'true'
process.env.REDIS_URL = 'redis://unit-test.invalid:6379'
;(readFileSync as jest.Mock).mockReturnValue(`${bakedCommit}\n`)
;(prisma.$queryRaw as jest.Mock).mockResolvedValue([{ ok: 1 }])
;(redis!.ping as jest.Mock).mockResolvedValue('PONG')
})
afterAll(() => {
if (originalUseRedis === undefined) delete process.env.USE_REDIS
else process.env.USE_REDIS = originalUseRedis
if (originalRedisUrl === undefined) delete process.env.REDIS_URL
else process.env.REDIS_URL = originalRedisUrl
if (originalCommit === undefined) delete process.env.DEPLOYMENT_COMMIT
else process.env.DEPLOYMENT_COMMIT = originalCommit
})
test('returns exact deployment commit with healthy database and Redis checks', async () => {
const response = await GET(new NextRequest('https://example.invalid/api/health'))
const body = await response.json()
expect(response.status).toBe(200)
expect(body).toMatchObject({
status: 'healthy',
deploymentCommit: bakedCommit,
checks: {
database: { status: 'ok' },
redis: { status: 'ok' },
},
})
})
test('keeps Redis failure visible as degraded so deploy can reject it', async () => {
;(redis!.ping as jest.Mock).mockRejectedValue(new Error('redis unavailable'))
const response = await GET(new NextRequest('https://example.invalid/api/health'))
const body = await response.json()
expect(response.status).toBe(200)
expect(body.status).toBe('degraded')
expect(body.checks.redis.status).toBe('error')
})
test('never trusts a mutable runtime environment variable as image identity', async () => {
process.env.DEPLOYMENT_COMMIT = 'f'.repeat(40)
;(readFileSync as jest.Mock).mockReturnValue('not-an-immutable-git-sha')
const response = await GET(new NextRequest('https://example.invalid/api/health'))
const body = await response.json()
expect(body.deploymentCommit).toBeNull()
})
})