57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
import { readFile } from 'node:fs/promises';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
import YAML from 'yaml';
|
|
import { buildApp } from '../../src/app.js';
|
|
import { loadConfig } from '../../src/config.js';
|
|
|
|
interface OpenApiDocument {
|
|
servers: Array<{ url: string }>;
|
|
paths: Record<string, unknown>;
|
|
}
|
|
|
|
function assertOpenApiDocument(value: unknown): asserts value is OpenApiDocument {
|
|
if (
|
|
typeof value !== 'object' ||
|
|
value === null ||
|
|
!('servers' in value) ||
|
|
!Array.isArray(value.servers) ||
|
|
!('paths' in value) ||
|
|
typeof value.paths !== 'object' ||
|
|
value.paths === null
|
|
) {
|
|
throw new Error('api/openapi.yaml is not an OpenAPI document');
|
|
}
|
|
}
|
|
|
|
const config = loadConfig({
|
|
DATABASE_URL: 'postgres://localhost/staff',
|
|
STANDALONE_TENANT_ID: '01J00000000000000000000000',
|
|
STANDALONE_ACTOR_ID: '01J00000000000000000000001',
|
|
LOG_LEVEL: 'silent',
|
|
NODE_ENV: 'test',
|
|
});
|
|
|
|
describe('OpenAPI runtime contract', () => {
|
|
it('exposes the documented operational paths under the module prefix', async () => {
|
|
const database = {
|
|
ping: vi.fn(async () => undefined),
|
|
close: vi.fn(async () => undefined),
|
|
} as never;
|
|
const app = await buildApp({ config, database });
|
|
await app.ready();
|
|
const documented: unknown = YAML.parse(await readFile('api/openapi.yaml', 'utf8'));
|
|
assertOpenApiDocument(documented);
|
|
const runtime = app.swagger();
|
|
const prefix = documented.servers[0]?.url;
|
|
if (!prefix) throw new Error('OpenAPI server prefix is missing');
|
|
const documentedPaths = Object.keys(documented.paths).sort();
|
|
const runtimePaths = Object.keys(runtime.paths ?? {})
|
|
.filter((path) => path !== '/' && path !== '/openapi.json')
|
|
.sort();
|
|
expect(runtimePaths).toEqual(documentedPaths);
|
|
for (const path of documentedPaths) {
|
|
expect((await app.inject(`${prefix}${path}`)).statusCode).not.toBe(404);
|
|
}
|
|
await app.close();
|
|
});
|
|
});
|