fastify-swagger
Version:
Serve Swagger/OpenAPI documentation for Fastify, supporting dynamic generation
256 lines (221 loc) • 6.7 kB
JavaScript
'use strict'
const { test } = require('tap')
const Fastify = require('fastify')
const Swagger = require('swagger-parser')
const fastifySwagger = require('../../../index')
const {
openapiOption,
schemaAllOf
} = require('../../../examples/options')
test('support - oneOf, anyOf, allOf', t => {
t.plan(3)
const fastify = Fastify()
fastify.register(fastifySwagger, openapiOption)
fastify.get('/', schemaAllOf, () => {})
fastify.ready(err => {
t.error(err)
const openapiObject = fastify.swagger()
Swagger.validate(openapiObject)
.then(function (api) {
const definedPath = api.paths['/'].get
t.ok(definedPath)
t.same(definedPath.parameters, [
{
required: false,
in: 'query',
name: 'foo',
schema: {
type: 'string'
}
}
])
})
.catch(function (err) {
t.fail(err)
})
})
})
test('support 2xx response', async t => {
const opt = {
schema: {
response: {
'2XX': {
type: 'object'
},
'3xx': {
type: 'object'
}
}
}
}
const fastify = Fastify()
fastify.register(fastifySwagger, {
openapi: true,
routePrefix: '/docs',
exposeRoute: true
})
fastify.get('/', opt, () => {})
await fastify.ready()
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
const definedPath = api.paths['/'].get
t.same(definedPath.responses['2XX'].description, 'Default Response')
t.same(definedPath.responses['3XX'].description, 'Default Response')
})
test('support status code 204', async t => {
const opt = {
schema: {
response: {
204: {
type: 'null',
description: 'No Content'
}
}
}
}
const fastify = Fastify()
fastify.register(fastifySwagger, {
openapi: true,
routePrefix: '/docs',
exposeRoute: true
})
fastify.get('/', opt, () => {})
await fastify.ready()
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
const definedPath = api.paths['/'].get
t.same(definedPath.responses['204'].description, 'No Content')
t.notOk(definedPath.responses['204'].content)
})
test('support response headers', async t => {
const opt = {
schema: {
response: {
200: {
type: 'object',
properties: {
hello: {
type: 'string'
}
},
headers: {
'X-WORLD': {
type: 'string'
},
'X-DESCRIPTION': {
description: 'Foo',
type: 'string'
}
}
}
}
}
}
const fastify = Fastify()
fastify.register(fastifySwagger, {
openapi: true,
routePrefix: '/docs',
exposeRoute: true
})
fastify.get('/', opt, () => {})
await fastify.ready()
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
const definedPath = api.paths['/'].get
t.same(definedPath.responses['200'].headers['X-WORLD'], {
schema: {
type: 'string'
}
})
t.same(definedPath.responses['200'].headers['X-DESCRIPTION'], {
description: 'Foo',
schema: {
type: 'string'
}
})
t.notOk(definedPath.responses['200'].content['application/json'].schema.headers)
})
test('response: description and x-response-description', async () => {
const description = 'description - always that of response body, sometimes also that of response as a whole'
const responseDescription = 'description only for the response as a whole'
test('description without x-response-description doubles as response description', async t => {
// Given a /description endpoint with only a |description| field in its response schema
const fastify = Fastify()
fastify.register(fastifySwagger, openapiOption)
fastify.get('/description', {
schema: {
response: {
200: {
description,
type: 'string'
}
}
}
}, () => {})
await fastify.ready()
// When the Swagger schema is generated
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
// Then the /description endpoint uses the |description| as both the description of the Response Object as well as of its Schema Object
/** @type {import('openapi-types').OpenAPIV3.ResponseObject} */
const responseObject = api.paths['/description'].get.responses['200']
t.ok(responseObject)
t.equal(responseObject.description, description)
const schemaObject = responseObject.content['application/json'].schema
t.ok(schemaObject)
t.equal(schemaObject.description, description)
})
test('description alongside x-response-description only describes response body', async t => {
// Given a /x-response-description endpoint that also has a |x-response-description| field in its response schema
const fastify = Fastify()
fastify.register(fastifySwagger, openapiOption)
fastify.get('/responseDescription', {
schema: {
response: {
200: {
'x-response-description': responseDescription,
description,
type: 'string'
}
}
}
}, () => {})
await fastify.ready()
// When the Swagger schema is generated
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
// Then the /responseDescription endpoint uses the |responseDescription| only for the Response Object and the |description| only for the Schema Object
const responseObject = api.paths['/responseDescription'].get.responses['200']
t.ok(responseObject)
t.equal(responseObject.description, responseDescription)
const schemaObject = responseObject.content['application/json'].schema
t.ok(schemaObject)
t.equal(schemaObject.description, description)
t.equal(schemaObject.responseDescription, undefined)
})
})
test('support default=null', async t => {
const opt = {
schema: {
response: {
'2XX': {
type: 'string',
nullable: true,
default: null
}
}
}
}
const fastify = Fastify()
fastify.register(fastifySwagger, {
openapi: true,
routePrefix: '/docs',
exposeRoute: true
})
fastify.get('/', opt, () => {})
await fastify.ready()
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
const definedPath = api.paths['/'].get
t.same(definedPath.responses['2XX'].default, null)
})