67 lines
2.3 KiB
TypeScript
67 lines
2.3 KiB
TypeScript
|
|
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');
|
||
|
|
});
|
||
|
|
});
|