Files
Shade/packages/shade-server/tests/health-metrics.test.ts

67 lines
2.3 KiB
TypeScript
Raw Normal View History

import { describe, test, expect } from 'bun:test';
import { Hono } from 'hono';
import { createHealthRoutes } from '../src/health.js';
import { createMetricsRoutes, metricsMiddleware, metrics } from '../src/metrics.js';
import { MemoryPrekeyStore } from '../src/memory-store.js';
describe('Health endpoints', () => {
test('GET /health returns ok with version and uptime', async () => {
const store = new MemoryPrekeyStore();
const app = createHealthRoutes(store, '1.2.3');
const res = await app.request('/health');
expect(res.status).toBe(200);
const body = await res.json();
expect(body.status).toBe('ok');
expect(body.version).toBe('1.2.3');
expect(body.uptimeSeconds).toBeGreaterThanOrEqual(0);
});
test('GET /healthz returns text "ok"', async () => {
const store = new MemoryPrekeyStore();
const app = createHealthRoutes(store, '1.0.0');
const res = await app.request('/healthz');
expect(res.status).toBe(200);
expect(await res.text()).toBe('ok');
});
test('GET /ready returns text "ready"', async () => {
const store = new MemoryPrekeyStore();
const app = createHealthRoutes(store, '1.0.0');
const res = await app.request('/ready');
expect(res.status).toBe(200);
expect(await res.text()).toBe('ready');
});
test('returns 503 if store throws', async () => {
const broken = {
getOneTimePreKeyCount: async () => { throw new Error('db down'); },
} as any;
const app = createHealthRoutes(broken, '1.0.0');
const res = await app.request('/health');
expect(res.status).toBe(503);
const body = await res.json();
expect(body.status).toBe('error');
});
});
describe('Metrics endpoint', () => {
test('returns Prometheus exposition format', async () => {
// Trigger some metrics
const app = new Hono();
app.use('*', metricsMiddleware());
app.get('/test', (c) => c.text('hello'));
app.route('/', createMetricsRoutes());
await app.request('/test');
await app.request('/test');
const res = await app.request('/metrics');
expect(res.status).toBe(200);
expect(res.headers.get('content-type')).toMatch(/text\/plain/);
const body = await res.text();
expect(body).toContain('shade_requests_total');
expect(body).toContain('shade_request_duration_ms');
});
});