test(httpapi): compare request body schema kind

This commit is contained in:
Kit Langton
2026-04-28 22:20:10 -04:00
parent 0033c4474c
commit ca2f54a68d
2 changed files with 32 additions and 6 deletions
@@ -379,7 +379,7 @@ function normalizeLegacyErrorResponses(operation: OpenApiOperation) {
}
function applyLegacyErrorResponses(operation: OpenApiOperation, route: string) {
const responses = LegacyErrorResponses[route as keyof typeof LegacyErrorResponses]
const responses: ReadonlyArray<400 | 404> | undefined = LegacyErrorResponses[route as keyof typeof LegacyErrorResponses]
if (!responses) return
operation.responses ??= {}
if (responses.includes(400)) operation.responses["400"] = legacyErrorResponse("Bad request", "BadRequestError")
@@ -57,16 +57,32 @@ function openApiParameters(spec: { paths: Record<string, Partial<Record<(typeof
)
}
function openApiRequestBodies(spec: { paths: Record<string, Partial<Record<(typeof methods)[number], Operation>>> }) {
function openApiRequestBodies(spec: OpenApiSpec) {
return Object.fromEntries(
Object.entries(spec.paths).flatMap(([path, item]) =>
methods
.filter((method) => item[method])
.map((method) => [`${method.toUpperCase()} ${path}`, requestBodyKey(item[method]?.requestBody)]),
.map((method) => [`${method.toUpperCase()} ${path}`, requestBodyKey(spec, item[method]?.requestBody)]),
),
)
}
type OpenApiSpec = {
components?: {
schemas?: Record<string, unknown>
}
paths: Record<string, Partial<Record<(typeof methods)[number], Operation>>>
}
type OpenApiSchema = {
$ref?: string
allOf?: unknown[]
anyOf?: unknown[]
oneOf?: unknown[]
properties?: Record<string, unknown>
type?: string | string[]
}
type Operation = {
parameters?: unknown[]
responses?: unknown
@@ -74,7 +90,7 @@ type Operation = {
}
type RequestBody = {
content?: Record<string, { schema?: { $ref?: string; type?: string } }>
content?: Record<string, { schema?: OpenApiSchema }>
required?: boolean
}
@@ -97,17 +113,27 @@ function parameterSchema(input: {
return param.schema
}
function requestBodyKey(body: unknown) {
function requestBodyKey(spec: OpenApiSpec, body: unknown) {
if (!body || typeof body !== "object" || !("content" in body)) return ""
const requestBody = body as RequestBody
return JSON.stringify({
required: requestBody.required === true,
content: Object.entries(requestBody.content ?? {})
.map(([type, value]) => [type, value.schema?.$ref ?? value.schema?.type ?? "inline"])
.map(([type, value]) => [type, requestBodySchemaKind(spec, value.schema)])
.sort(),
})
}
function requestBodySchemaKind(spec: OpenApiSpec, schema: OpenApiSchema | undefined) {
if (!schema) return ""
const resolved = (schema.$ref ? spec.components?.schemas?.[schema.$ref.replace("#/components/schemas/", "")] : schema) as
| OpenApiSchema
| undefined
if (resolved?.properties) return "object"
if (resolved?.anyOf ?? resolved?.oneOf ?? resolved?.allOf) return "object"
return resolved?.type ?? schema.type ?? "inline"
}
function responseContentTypes(input: {
spec: { paths: Record<string, Partial<Record<(typeof methods)[number], Operation>>> }
path: string