@fastify/swagger
Advanced tools
Comparing version 8.13.0 to 8.14.0
@@ -234,2 +234,36 @@ 'use strict' | ||
const schemaTypeToNestedSchemas = { | ||
object: (schema) => { | ||
return [ | ||
...Object.values(schema.properties || {}), | ||
...Object.values(schema.patternProperties || {}), | ||
...Object.values(schema.additionalProperties || {}) | ||
] | ||
}, | ||
array: (schema) => { | ||
return [ | ||
...(schema.items ? [schema.items] : []), | ||
...(schema.contains ? [schema.contains] : []) | ||
] | ||
} | ||
} | ||
function resolveSchemaExamples (schema) { | ||
const example = schema[xExamples] ?? schema.examples?.[0] | ||
if (typeof example !== 'undefined') { | ||
schema.example = example | ||
} | ||
delete schema[xExamples] | ||
delete schema.examples | ||
} | ||
function resolveSchemaExamplesRecursive (schema) { | ||
resolveSchemaExamples(schema) | ||
const getNestedSchemas = schemaTypeToNestedSchemas[schema.type] | ||
const nestedSchemas = getNestedSchemas?.(schema) ?? [] | ||
for (const nestedSchema of nestedSchemas) { | ||
resolveSchemaExamplesRecursive(nestedSchema) | ||
} | ||
} | ||
function schemaToMedia (schema) { | ||
@@ -255,2 +289,8 @@ const media = { schema } | ||
function schemaToMediaRecursive (schema) { | ||
const media = schemaToMedia(schema) | ||
resolveSchemaExamplesRecursive(schema) | ||
return media | ||
} | ||
function resolveBodyParams (body, schema, consumes, ref) { | ||
@@ -262,3 +302,3 @@ const resolved = transformDefsToComponents(ref.resolve(schema)) | ||
const media = schemaToMedia(resolved) | ||
const media = schemaToMediaRecursive(resolved) | ||
consumes.forEach((consume) => { | ||
@@ -352,3 +392,3 @@ body.content[consume] = media | ||
const media = schemaToMedia(resolved) | ||
const media = schemaToMediaRecursive(resolved) | ||
@@ -355,0 +395,0 @@ for (const produce of produces) { |
@@ -24,3 +24,3 @@ # Migration | ||
| uiConfig | {} | Configuration options for [Swagger UI](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md). Must be literal values, see [#5710](https://github.com/swagger-api/swagger-ui/issues/5710).| | ||
| uiHooks | {} | Additional hooks for the documentation's routes. You can provide the `onRequest` and `preHandler` hooks with the same [route's options](https://www.fastify.io/docs/latest/Routes/#options) interface.| | ||
| uiHooks | {} | Additional hooks for the documentation's routes. You can provide the `onRequest` and `preHandler` hooks with the same [route's options](https://fastify.dev/docs/latest/Routes/#options) interface.| | ||
@@ -27,0 +27,0 @@ The `baseDir` option is new and is only needed if external spec files should be |
{ | ||
"name": "@fastify/swagger", | ||
"version": "8.13.0", | ||
"version": "8.14.0", | ||
"description": "Serve Swagger/OpenAPI documentation for Fastify, supporting dynamic generation", | ||
@@ -53,3 +53,3 @@ "main": "index.js", | ||
"tap": "^16.2.0", | ||
"tsd": "^0.29.0" | ||
"tsd": "^0.30.1" | ||
}, | ||
@@ -56,0 +56,0 @@ "dependencies": { |
@@ -923,3 +923,3 @@ # @fastify/swagger | ||
### Integration | ||
You can integration this plugin with ```@fastify/helmet``` with some little work. | ||
You can integrate this plugin with ```@fastify/helmet``` with some little work. | ||
@@ -1004,3 +1004,3 @@ ```@fastify/helmet``` options example: | ||
}, | ||
"examples": [{ "foo": "bar", "bar": "baz" }] | ||
"example": { "foo": "bar", "bar": "baz" } | ||
} | ||
@@ -1007,0 +1007,0 @@ } |
@@ -446,5 +446,13 @@ 'use strict' | ||
test('transforms examples in example if single string example', async (t) => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
test('move examples from "x-examples" to examples field', async (t) => { | ||
t.plan(3) | ||
const fastify = Fastify({ | ||
ajv: { | ||
plugins: [ | ||
function (ajv) { | ||
ajv.addKeyword({ keyword: 'x-examples' }) | ||
} | ||
] | ||
} | ||
}) | ||
@@ -460,5 +468,15 @@ await fastify.register(fastifySwagger, openapiOption) | ||
hello: { | ||
type: 'string', | ||
examples: ['world'] | ||
type: 'object', | ||
properties: { | ||
lorem: { | ||
type: 'string' | ||
} | ||
} | ||
} | ||
}, | ||
'x-examples': { | ||
'lorem ipsum': { | ||
summary: 'Roman statesman', | ||
value: { lorem: 'ipsum' } | ||
} | ||
} | ||
@@ -474,78 +492,730 @@ } | ||
const openapiObject = fastify.swagger() | ||
const schema = openapiObject.paths['/'].post.requestBody.content['application/json'].schema | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema) | ||
t.same(schema.properties.hello.examples, ['world']) | ||
t.notOk(schema['x-examples']) | ||
t.same(content.examples, { | ||
'lorem ipsum': { | ||
summary: 'Roman statesman', | ||
value: { lorem: 'ipsum' } | ||
} | ||
}) | ||
}) | ||
test('transforms examples in example if single object example', async (t) => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
test('parameter & header examples', async t => { | ||
t.test('uses .example if has single example', async t => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const [params, querystring, headers] = Array(3).fill({ | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string', | ||
examples: ['world'] | ||
} | ||
} | ||
}) | ||
fastify.post('/', { schema: { params, querystring, headers } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const { parameters } = openapiObject.paths['/'].post | ||
await fastify.register(fastifySwagger, openapiOption) | ||
t.ok(parameters.every(({ example }) => example === 'world')) | ||
t.ok(parameters.every(param => !Object.prototype.hasOwnProperty.call(param, 'examples'))) | ||
}) | ||
const opts = { | ||
schema: { | ||
body: { | ||
t.test('uses .examples if has multiple examples', async t => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const [params, querystring, headers] = Array(3).fill({ | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string', | ||
examples: ['world', 'universe'] | ||
} | ||
} | ||
}) | ||
fastify.post('/', { schema: { params, querystring, headers } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const { parameters } = openapiObject.paths['/'].post | ||
const examples = parameters.map(({ examples }) => examples) | ||
t.strictSame(examples, Array(3).fill({ | ||
world: { value: 'world' }, | ||
universe: { value: 'universe' } | ||
})) | ||
t.ok(parameters.every(param => !Object.prototype.hasOwnProperty.call(param, 'example'))) | ||
}) | ||
}) | ||
test('request body examples', async t => { | ||
t.test('uses .example field if has single top-level string example', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'string', | ||
examples: ['hello'] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, 'hello') | ||
t.notOk(content.examples) | ||
}) | ||
t.test('uses .examples field if has multiple top-level string examples', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'string', | ||
examples: ['hello', 'world'] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.strictSame(content.examples, { | ||
hello: { value: 'hello' }, | ||
world: { value: 'world' } | ||
}) | ||
}) | ||
t.test('uses .example field if has single top-level numeric example', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'number', | ||
examples: [0] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, 0) | ||
t.notOk(content.examples) | ||
}) | ||
t.test('uses .examples field if has multiple top-level numeric examples', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'number', | ||
examples: [0, 1] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.strictSame(content.examples, { | ||
0: { value: 0 }, | ||
1: { value: 1 } | ||
}) | ||
}) | ||
t.test('uses .example field if has single top-level object example', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ hello: 'world' }] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, { hello: 'world' }) | ||
t.notOk(content.examples) | ||
}) | ||
t.test('uses .examples field if has multiple top-level object examples', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ hello: 'world' }, { hello: 'universe' }] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.examples, { | ||
example1: { value: { hello: 'world' } }, | ||
example2: { value: { hello: 'universe' } } | ||
}) | ||
t.notOk(content.example) | ||
}) | ||
t.test('uses .example field if has single top-level array example', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
required: ['hello'], | ||
properties: { | ||
hello: { | ||
type: 'object', | ||
properties: { | ||
lorem: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ lorem: 'ipsum' }] | ||
type: 'string' | ||
} | ||
} | ||
}, | ||
examples: [[{ hello: 'world' }]] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.items) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, [{ hello: 'world' }]) | ||
t.notOk(content.examples) | ||
}) | ||
t.test('uses .examples field if has multiple top-level array examples', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
} | ||
}, | ||
examples: [[{ hello: 'world' }], [{ hello: 'universe' }]] | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.items) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.examples, { | ||
example1: { value: [{ hello: 'world' }] }, | ||
example2: { value: [{ hello: 'universe' }] } | ||
}) | ||
t.notOk(content.example) | ||
}) | ||
t.test('uses .example field if has single nested string example', async t => { | ||
t.plan(9) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'object', | ||
properties: { | ||
flat: { | ||
type: 'string', | ||
examples: ['world'] | ||
}, | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
field: { | ||
type: 'string', | ||
examples: ['universe'] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
fastify.post('/', opts, () => {}) | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.flat.examples) | ||
t.notOk(schema.properties.deep.properties.field.examples) | ||
t.strictSame(schema.properties.flat.example, 'world') | ||
t.strictSame(schema.properties.deep.properties.field.example, 'universe') | ||
}) | ||
await fastify.ready() | ||
t.test('uses .example field if has multiple nested numeric examples', async t => { | ||
t.plan(9) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'object', | ||
properties: { | ||
flat: { | ||
type: 'number', | ||
examples: [0, 1] | ||
}, | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
field: { | ||
type: 'number', | ||
examples: [1, 0] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
const openapiObject = fastify.swagger() | ||
const schema = openapiObject.paths['/'].post.requestBody.content['application/json'].schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.flat.examples) | ||
t.notOk(schema.properties.deep.properties.field.examples) | ||
t.strictSame(schema.properties.flat.example, 0) | ||
t.strictSame(schema.properties.deep.properties.field.example, 1) | ||
}) | ||
t.ok(schema) | ||
t.same(schema.properties.hello.examples, [{ lorem: 'ipsum' }]) | ||
t.test('uses .example if has single nested array example', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'array', | ||
items: { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
}, | ||
examples: [['world', 'universe']] | ||
} | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.items) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.items.examples) | ||
t.strictSame(schema.items.example, ['world', 'universe']) | ||
}) | ||
t.test('uses .example if has multiple nested array examples', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'array', | ||
contains: { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
}, | ||
examples: [['world', 'universe'], ['world', 'universe']] | ||
} | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.contains) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.contains.examples) | ||
t.strictSame(schema.contains.example, ['world', 'universe']) | ||
}) | ||
t.test('uses .example if has single nested object example', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'object', | ||
properties: { | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ hello: 'world' }] | ||
} | ||
} | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.deep.examples) | ||
t.strictSame(schema.properties.deep.example, { hello: 'world' }) | ||
}) | ||
t.test('uses .example if has multiple nested object examples', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const body = { | ||
type: 'object', | ||
properties: { | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ hello: 'world' }, { hello: 'universe' }] | ||
} | ||
} | ||
} | ||
fastify.post('/', { schema: { body } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.deep.examples) | ||
t.strictSame(schema.properties.deep.example, { hello: 'world' }) | ||
}) | ||
}) | ||
test('move examples from "x-examples" to examples field', async (t) => { | ||
t.plan(3) | ||
const fastify = Fastify({ | ||
ajv: { | ||
plugins: [ | ||
function (ajv) { | ||
ajv.addKeyword({ keyword: 'x-examples' }) | ||
test('response examples', async t => { | ||
t.test('uses .example field if has single top-level string example', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'string', | ||
examples: ['hello'] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, 'hello') | ||
t.notOk(content.examples) | ||
}) | ||
t.test('uses .examples field if has multiple top-level string examples', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'string', | ||
examples: ['hello', 'world'] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.strictSame(content.examples, { | ||
hello: { value: 'hello' }, | ||
world: { value: 'world' } | ||
}) | ||
}) | ||
t.test('uses .example field if has single top-level numeric example', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'number', | ||
examples: [0] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, 0) | ||
t.notOk(content.examples) | ||
}) | ||
t.test('uses .examples field if has multiple top-level numeric examples', async t => { | ||
t.plan(4) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'number', | ||
examples: [0, 1] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.strictSame(content.examples, { | ||
0: { value: 0 }, | ||
1: { value: 1 } | ||
}) | ||
}) | ||
t.test('uses .example field if has single top-level object example', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
] | ||
}, | ||
examples: [{ hello: 'world' }] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, { hello: 'world' }) | ||
t.notOk(content.examples) | ||
}) | ||
await fastify.register(fastifySwagger, openapiOption) | ||
t.test('uses .examples field if has multiple top-level object examples', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ hello: 'world' }, { hello: 'universe' }] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
const opts = { | ||
schema: { | ||
body: { | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.examples, { | ||
example1: { value: { hello: 'world' } }, | ||
example2: { value: { hello: 'universe' } } | ||
}) | ||
t.notOk(content.example) | ||
}) | ||
t.test('uses .example field if has single top-level array example', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
required: ['hello'], | ||
properties: { | ||
hello: { | ||
type: 'object', | ||
properties: { | ||
lorem: { | ||
type: 'string' | ||
} | ||
type: 'string' | ||
} | ||
} | ||
}, | ||
examples: [[{ hello: 'world' }]] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.items) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.example, [{ hello: 'world' }]) | ||
t.notOk(content.examples) | ||
}) | ||
t.test('uses .examples field if has multiple top-level array examples', async t => { | ||
t.plan(5) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
} | ||
}, | ||
examples: [[{ hello: 'world' }], [{ hello: 'universe' }]] | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.items) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.strictSame(content.examples, { | ||
example1: { value: [{ hello: 'world' }] }, | ||
example2: { value: [{ hello: 'universe' }] } | ||
}) | ||
t.notOk(content.example) | ||
}) | ||
t.test('uses .example field if has single nested string example', async t => { | ||
t.plan(9) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'object', | ||
properties: { | ||
flat: { | ||
type: 'string', | ||
examples: ['world'] | ||
}, | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
field: { | ||
type: 'string', | ||
examples: ['universe'] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.flat.examples) | ||
t.notOk(schema.properties.deep.properties.field.examples) | ||
t.strictSame(schema.properties.flat.example, 'world') | ||
t.strictSame(schema.properties.deep.properties.field.example, 'universe') | ||
}) | ||
t.test('uses .example field if has multiple nested numeric examples', async t => { | ||
t.plan(9) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'object', | ||
properties: { | ||
flat: { | ||
type: 'number', | ||
examples: [0, 1] | ||
}, | ||
'x-examples': { | ||
'lorem ipsum': { | ||
summary: 'Roman statesman', | ||
value: { lorem: 'ipsum' } | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
field: { | ||
type: 'number', | ||
examples: [1, 0] | ||
} | ||
} | ||
@@ -555,20 +1225,142 @@ } | ||
} | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
fastify.post('/', opts, () => {}) | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.flat.examples) | ||
t.notOk(schema.properties.deep.properties.field.examples) | ||
t.strictSame(schema.properties.flat.example, 0) | ||
t.strictSame(schema.properties.deep.properties.field.example, 1) | ||
}) | ||
await fastify.ready() | ||
t.test('uses .example if has single nested array example', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'array', | ||
items: { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
}, | ||
examples: [['world', 'universe']] | ||
} | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.requestBody.content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.items) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.items.examples) | ||
t.strictSame(schema.items.example, ['world', 'universe']) | ||
}) | ||
t.ok(schema) | ||
t.notOk(schema['x-examples']) | ||
t.same(content.examples, { | ||
'lorem ipsum': { | ||
summary: 'Roman statesman', | ||
value: { lorem: 'ipsum' } | ||
t.test('uses .example if has multiple nested array examples', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'array', | ||
contains: { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
}, | ||
examples: [['world', 'universe'], ['world', 'universe']] | ||
} | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.contains) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.contains.examples) | ||
t.strictSame(schema.contains.example, ['world', 'universe']) | ||
}) | ||
t.test('uses .example if has single nested object example', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'object', | ||
properties: { | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ hello: 'world' }] | ||
} | ||
} | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.deep.examples) | ||
t.strictSame(schema.properties.deep.example, { hello: 'world' }) | ||
}) | ||
t.test('uses .example if has multiple nested object examples', async t => { | ||
t.plan(7) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const response = { | ||
type: 'object', | ||
properties: { | ||
deep: { | ||
type: 'object', | ||
properties: { | ||
hello: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ hello: 'world' }, { hello: 'universe' }] | ||
} | ||
} | ||
} | ||
fastify.post('/', { schema: { response: { 200: response } } }, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const content = openapiObject.paths['/'].post.responses['200'].content['application/json'] | ||
const schema = content.schema | ||
t.ok(schema.properties) | ||
t.notOk(schema.example) | ||
t.notOk(schema.examples) | ||
t.notOk(content.example) | ||
t.notOk(content.examples) | ||
t.notOk(schema.properties.deep.examples) | ||
t.strictSame(schema.properties.deep.example, { hello: 'world' }) | ||
}) | ||
}) | ||
@@ -822,149 +1614,3 @@ | ||
test('uses examples if has multiple string examples', async (t) => { | ||
t.plan(3) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const opts = { | ||
schema: { | ||
body: { | ||
type: 'object', | ||
required: ['hello'], | ||
properties: { | ||
hello: { | ||
type: 'string', | ||
examples: ['hello', 'world'] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
fastify.post('/', opts, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const schema = openapiObject.paths['/'].post.requestBody.content['application/json'].schema | ||
t.ok(schema) | ||
t.ok(schema.properties.hello.examples) | ||
t.same(schema.properties.hello.examples, ['hello', 'world']) | ||
}) | ||
test('uses examples if has multiple numbers examples', async (t) => { | ||
t.plan(3) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const opts = { | ||
schema: { | ||
body: { | ||
type: 'object', | ||
required: ['hello'], | ||
properties: { | ||
hello: { | ||
type: 'number', | ||
examples: [1, 2] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
fastify.post('/', opts, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const schema = openapiObject.paths['/'].post.requestBody.content['application/json'].schema | ||
t.ok(schema) | ||
t.ok(schema.properties.hello.examples) | ||
t.same(schema.properties.hello.examples, [1, 2]) | ||
}) | ||
test('uses examples if has multiple object examples', async (t) => { | ||
t.plan(3) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const opts = { | ||
schema: { | ||
body: { | ||
type: 'object', | ||
required: ['hello'], | ||
properties: { | ||
hello: { | ||
type: 'object', | ||
properties: { | ||
lorem: { | ||
type: 'string' | ||
} | ||
}, | ||
examples: [{ lorem: 'ipsum' }, { hello: 'world' }] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
fastify.post('/', opts, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const schema = openapiObject.paths['/'].post.requestBody.content['application/json'].schema | ||
t.ok(schema) | ||
t.ok(schema.properties.hello.examples) | ||
t.same(schema.properties.hello.examples, [ | ||
{ lorem: 'ipsum' }, | ||
{ hello: 'world' } | ||
]) | ||
}) | ||
test('uses examples if has multiple array examples', async (t) => { | ||
t.plan(3) | ||
const fastify = Fastify() | ||
await fastify.register(fastifySwagger, openapiOption) | ||
const opts = { | ||
schema: { | ||
body: { | ||
type: 'object', | ||
required: ['hello'], | ||
properties: { | ||
hello: { | ||
type: 'array', | ||
items: { | ||
type: 'string' | ||
}, | ||
examples: [['a', 'b', 'c'], ['d', 'f', 'g']] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
fastify.post('/', opts, () => {}) | ||
await fastify.ready() | ||
const openapiObject = fastify.swagger() | ||
const schema = openapiObject.paths['/'].post.requestBody.content['application/json'].schema | ||
t.ok(schema) | ||
t.ok(schema.properties.hello.examples) | ||
t.same(schema.properties.hello.examples, [ | ||
['a', 'b', 'c'], | ||
['d', 'f', 'g'] | ||
]) | ||
}) | ||
test('uses examples if has property required in body', async (t) => { | ||
test('marks request body as required', async (t) => { | ||
t.plan(4) | ||
@@ -971,0 +1617,0 @@ const fastify = Fastify() |
302810
8803
316101