62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { buildApp } from '../../src/app.js';
|
|
import { loadConfig } from '../../src/config.js';
|
|
|
|
const config = loadConfig({
|
|
DATABASE_URL: 'postgres://localhost/staff',
|
|
STANDALONE_TENANT_ID: '01ARZ3NDEKTSV4RRFFQ69G5FAV',
|
|
STANDALONE_ACTOR_ID: '01J00000000000000000000001',
|
|
LOG_LEVEL: 'silent',
|
|
NODE_ENV: 'test',
|
|
});
|
|
const database = {
|
|
ping: vi.fn(async () => undefined),
|
|
close: vi.fn(async () => undefined),
|
|
} as never;
|
|
|
|
describe('operational endpoints', () => {
|
|
it('reports liveness, readiness and version without domain APIs', async () => {
|
|
const app = await buildApp({ config, database });
|
|
expect((await app.inject('/api/v1/staff/live')).statusCode).toBe(200);
|
|
expect((await app.inject('/api/v1/staff/ready')).statusCode).toBe(200);
|
|
expect((await app.inject('/api/v1/staff/version')).json()).toMatchObject({
|
|
name: 'krona-staff',
|
|
mode: 'standalone',
|
|
});
|
|
expect((await app.inject('/live')).statusCode).toBe(404);
|
|
expect((await app.inject('/api/v1/staff/not-a-route')).statusCode).toBe(404);
|
|
await app.close();
|
|
});
|
|
|
|
it('returns 503 without leaking database errors', async () => {
|
|
const unavailableDatabase = {
|
|
ping: vi.fn(async () => {
|
|
throw new Error('password=secret internal driver detail');
|
|
}),
|
|
close: vi.fn(async () => undefined),
|
|
} as never;
|
|
const app = await buildApp({ config, database: unavailableDatabase });
|
|
const response = await app.inject('/api/v1/staff/ready');
|
|
expect(response.statusCode).toBe(503);
|
|
expect(response.body).toBe('{"status":"unavailable"}');
|
|
expect(response.body).not.toContain('secret');
|
|
await app.close();
|
|
});
|
|
|
|
it('accepts only ULID correlation identifiers', async () => {
|
|
const app = await buildApp({ config, database });
|
|
const valid = '01J00000000000000000000009';
|
|
expect(
|
|
(await app.inject({ url: '/api/v1/staff/live', headers: { 'x-correlation-id': valid } }))
|
|
.headers['x-correlation-id'],
|
|
).toBe(valid);
|
|
const generated = (
|
|
await app.inject({
|
|
url: '/api/v1/staff/live',
|
|
headers: { 'x-correlation-id': 'not-a-ulid'.repeat(100) },
|
|
})
|
|
).headers['x-correlation-id'];
|
|
expect(generated).toMatch(/^[0-9A-HJKMNP-TV-Z]{26}$/);
|
|
await app.close();
|
|
});
|
|
});
|