Files
TREK/server/tests/unit/nest/api-zod.test.ts
T
Maurice 90a2833011 feat(api): OpenAPI/Swagger docs at /api/docs behind TREK_API_DOCS_ENABLED (#1412)
Swagger UI + raw spec (/api/docs-json, -yaml) over all controllers, with
a bearer button that works with a plain session JWT. Off by default -
the spec enumerates the whole surface incl. admin routes, so exposing
it is an explicit self-hoster decision (same kill-switch pattern as
TREK_PLUGINS_ENABLED).

Request bodies come from the Zod schemas the routes already validate
with: an enricher walks every controller, finds whole-body
ZodValidationPipe params and lifts their schema into the document via
zod v4's native z.toJSONSchema - nothing is annotated twice, and any
route that gains a Zod pipe is documented automatically.
2026-07-05 00:23:38 +02:00

29 lines
1.2 KiB
TypeScript

/**
* zodToOpenApi (#1412): Zod → OpenAPI 3.0 conversion + the degrade path.
* The end-to-end enricher behaviour is covered by tests/integration/api-docs.
*/
import { describe, it, expect } from 'vitest';
import { z } from 'zod';
import { zodToOpenApi } from '../../../src/nest/common/api-zod';
describe('zodToOpenApi', () => {
it('converts an object schema with required/optional split', () => {
const out = zodToOpenApi(z.object({ name: z.string(), count: z.number().optional() })) as {
type: string; properties: Record<string, unknown>; required: string[];
};
expect(out.type).toBe('object');
expect(out.properties.name).toEqual({ type: 'string' });
expect(out.properties.count).toEqual({ type: 'number' });
expect(out.required).toEqual(['name']);
});
it('survives transform-heavy schemas via unrepresentable: any', () => {
const out = zodToOpenApi(z.object({ when: z.string().transform((s) => new Date(s)) }));
expect((out as { type: string }).type).toBe('object');
});
it('degrades to a bare object instead of throwing on a broken schema', () => {
expect(zodToOpenApi({} as never)).toEqual({ type: 'object' });
});
});