import assert from 'node:assert/strict'; import test from 'node:test'; import type { NextFunction } from 'express'; import { createRequest, createResponse } from 'node-mocks-http'; import * as swaggerUI from 'swagger-ui-express'; import { createOpenApiDocument } from '../src/openapi/document.ts'; import type { OpenApiDocument } from '../src/openapi/document.ts'; function createTestDocument(): OpenApiDocument { return createOpenApiDocument({ serverUrl: 'http://localhost:3000', }); } function collectRefs(value: unknown): Set { const refs = new Set(); const serialized = JSON.stringify(value); const refPattern = /"\$ref"\s*:\s*"([^"]+)"/g; for (const match of serialized.matchAll(refPattern)) { const ref = match[1]; if (ref) { refs.add(ref); } } return refs; } function hasComponentRef(document: OpenApiDocument, ref: string): boolean { const match = /^#\/components\/(schemas|responses|parameters|securitySchemes)\/(.+)$/.exec(ref); if (!match) return false; const section = match[1]; const name = match[2]; if (!section || !name) return false; switch (section) { case 'schemas': return name in document.components.schemas; case 'responses': return name in document.components.responses; case 'parameters': return name in document.components.parameters; case 'securitySchemes': return name in document.components.securitySchemes; default: return false; } } void test('OpenAPI document exposes comprehensive route coverage', () => { const document = createTestDocument(); const requiredPaths = [ '/api/health', '/api/auth/signin/local', '/api/users', '/api/users/count', '/api/users/autocomplete', '/api/projects/{id}/clone', '/api/file/presign', '/api/file/upload-sessions/{sessionId}/chunks/{chunkIndex}', '/api/runtime-access/me', '/api/project-ui-control-settings/project/{projectId}/env/{environment}', '/api/tour_pages/reverse-video-status', ]; assert.equal(document.openapi, '3.0.0'); for (const path of requiredPaths) { assert.ok(document.paths[path], `Missing OpenAPI path: ${path}`); } }); void test('OpenAPI document resolves all internal refs', () => { const document = createTestDocument(); const refs = collectRefs(document); const missingRefs = [...refs].filter((ref) => !hasComponentRef(document, ref)); assert.equal(missingRefs.length, 0, `Missing refs: ${missingRefs.join(', ')}`); }); void test('OpenAPI factory CRUD paths are generated consistently', () => { const document = createTestDocument(); const resourcePath = '/api/assets'; assert.ok(document.paths[resourcePath]?.post); assert.ok(document.paths[resourcePath]?.get); assert.ok(document.paths[`${resourcePath}/bulk-import`]?.post); assert.ok(document.paths[`${resourcePath}/deleteByIds`]?.post); assert.ok(document.paths[`${resourcePath}/count`]?.get); assert.ok(document.paths[`${resourcePath}/autocomplete`]?.get); assert.ok(document.paths[`${resourcePath}/{id}`]?.get); assert.ok(document.paths[`${resourcePath}/{id}`]?.put); assert.ok(document.paths[`${resourcePath}/{id}`]?.delete); }); void test('Swagger UI setup serves documentation HTML without throwing', () => { const document = createTestDocument(); const req = createRequest({ url: '/api-docs/' }); const res = createResponse(); const handler = swaggerUI.setup(document); let nextError: unknown = null; const next: NextFunction = (error?: unknown) => { nextError = error; }; handler(req, res, next); assert.equal(nextError, null); assert.equal(res.statusCode, 200); assert.match(String(res._getData()), /swagger-ui/); });