You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
576 lines
14 KiB
576 lines
14 KiB
3 years ago
|
'use strict'
|
||
|
|
||
|
const t = require('tap')
|
||
|
const test = t.test
|
||
|
const Fastify = require('fastify')
|
||
|
const Swagger = require('swagger-parser')
|
||
|
const yaml = require('js-yaml')
|
||
|
const fastifySwagger = require('../index')
|
||
|
const {
|
||
|
schemaQuerystring,
|
||
|
schemaBody,
|
||
|
schemaParams,
|
||
|
schemaSecurity
|
||
|
} = require('../examples/options')
|
||
|
let {
|
||
|
swaggerOption
|
||
|
} = require('../examples/options')
|
||
|
|
||
|
const resolve = require('path').resolve
|
||
|
const readFileSync = require('fs').readFileSync
|
||
|
|
||
|
swaggerOption = {
|
||
|
...swaggerOption,
|
||
|
exposeRoute: true
|
||
|
}
|
||
|
|
||
|
const schemaParamsWithoutDesc = {
|
||
|
schema: {
|
||
|
params: {
|
||
|
type: 'object',
|
||
|
properties: {
|
||
|
id: {
|
||
|
type: 'string'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const schemaParamsWithKey = {
|
||
|
schema: {
|
||
|
params: {
|
||
|
type: 'object',
|
||
|
properties: {
|
||
|
id: {
|
||
|
type: 'string',
|
||
|
description: 'user id'
|
||
|
},
|
||
|
key: {
|
||
|
type: 'string',
|
||
|
description: 'just some random key'
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
test('/documentation/json route', t => {
|
||
|
t.plan(2)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/json'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
|
||
|
const payload = JSON.parse(res.payload)
|
||
|
|
||
|
Swagger.validate(payload)
|
||
|
.then(function (api) {
|
||
|
t.pass('valid swagger object')
|
||
|
})
|
||
|
.catch(function (err) {
|
||
|
t.fail(err)
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/uiConfig route', t => {
|
||
|
t.plan(2)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
const uiConfig = {
|
||
|
docExpansion: 'full'
|
||
|
}
|
||
|
|
||
|
const opts = {
|
||
|
...swaggerOption,
|
||
|
uiConfig
|
||
|
}
|
||
|
|
||
|
fastify.register(fastifySwagger, opts)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/uiConfig'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
|
||
|
const payload = JSON.parse(res.payload)
|
||
|
|
||
|
t.match(payload, uiConfig, 'uiConfig should be valid')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/initOAuth route', t => {
|
||
|
t.plan(2)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
const initOAuth = {
|
||
|
scopes: ['openid', 'profile', 'email', 'offline_access']
|
||
|
}
|
||
|
|
||
|
const opts = {
|
||
|
...swaggerOption,
|
||
|
initOAuth
|
||
|
}
|
||
|
|
||
|
fastify.register(fastifySwagger, opts)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/initOAuth'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
|
||
|
const payload = JSON.parse(res.payload)
|
||
|
|
||
|
t.match(payload, initOAuth, 'initOAuth should be valid')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('fastify.swagger should return a valid swagger yaml', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
fastify.all('/parametersWithoutDesc/:id', schemaParamsWithoutDesc, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/yaml'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
t.equal(res.headers['content-type'], 'application/x-yaml')
|
||
|
try {
|
||
|
yaml.load(res.payload)
|
||
|
t.pass('valid swagger yaml')
|
||
|
} catch (err) {
|
||
|
t.fail(err)
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation should redirect to ./documentation/static/index.html', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './documentation/static/index.html')
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/ should redirect to ./static/index.html', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './static/index.html')
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/v1/documentation should redirect to ./documentation/static/index.html', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
const opts = JSON.parse(JSON.stringify(swaggerOption))
|
||
|
opts.routePrefix = '/v1/documentation'
|
||
|
fastify.register(fastifySwagger, opts)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/v1/documentation'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './documentation/static/index.html')
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/v1/documentation/ should redirect to ./static/index.html', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
const opts = JSON.parse(JSON.stringify(swaggerOption))
|
||
|
opts.routePrefix = '/v1/documentation'
|
||
|
fastify.register(fastifySwagger, opts)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/v1/documentation/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './static/index.html')
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/v1/foobar should redirect to ./foobar/static/index.html - in plugin', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.register(function (fastify, options, next) {
|
||
|
const opts = JSON.parse(JSON.stringify(swaggerOption))
|
||
|
opts.routePrefix = '/foobar'
|
||
|
fastify.register(fastifySwagger, opts)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
next()
|
||
|
}, { prefix: '/v1' })
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/v1/foobar'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './foobar/static/index.html')
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/v1/foobar/ should redirect to ./static/index.html - in plugin', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.register(function (fastify, options, next) {
|
||
|
const opts = JSON.parse(JSON.stringify(swaggerOption))
|
||
|
opts.routePrefix = '/foobar'
|
||
|
fastify.register(fastifySwagger, opts)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
next()
|
||
|
}, { prefix: '/v1' })
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/v1/foobar/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './static/index.html')
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('with routePrefix: \'/\' should redirect to ./static/index.html', t => {
|
||
|
t.plan(4)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
const opts = JSON.parse(JSON.stringify(swaggerOption))
|
||
|
opts.routePrefix = '/'
|
||
|
fastify.register(fastifySwagger, opts)
|
||
|
|
||
|
fastify.get('/foo', () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './static/index.html')
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/static/:file should send back the correct file', t => {
|
||
|
t.plan(24)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './static/index.html')
|
||
|
})
|
||
|
|
||
|
fastify.ready(() => {
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/static/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
t.equal(res.headers['content-type'], 'text/html; charset=UTF-8')
|
||
|
t.equal(
|
||
|
readFileSync(
|
||
|
resolve(__dirname, '..', 'static', 'index.html'),
|
||
|
'utf8'
|
||
|
),
|
||
|
res.payload
|
||
|
)
|
||
|
t.ok(res.payload.indexOf('resolveUrl') !== -1)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/static/oauth2-redirect.html'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
t.equal(res.headers['content-type'], 'text/html; charset=UTF-8')
|
||
|
t.equal(
|
||
|
readFileSync(
|
||
|
resolve(__dirname, '..', 'static', 'oauth2-redirect.html'),
|
||
|
'utf8'
|
||
|
),
|
||
|
res.payload
|
||
|
)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/static/swagger-ui.css'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
t.equal(res.headers['content-type'], 'text/css; charset=UTF-8')
|
||
|
t.equal(
|
||
|
readFileSync(
|
||
|
resolve(__dirname, '..', 'static', 'swagger-ui.css'),
|
||
|
'utf8'
|
||
|
),
|
||
|
res.payload
|
||
|
)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/static/swagger-ui-bundle.js'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
t.equal(res.headers['content-type'], 'application/javascript; charset=UTF-8')
|
||
|
t.equal(
|
||
|
readFileSync(
|
||
|
resolve(__dirname, '..', 'static', 'swagger-ui-bundle.js'),
|
||
|
'utf8'
|
||
|
),
|
||
|
res.payload
|
||
|
)
|
||
|
})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/static/swagger-ui-standalone-preset.js'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(typeof res.payload, 'string')
|
||
|
t.equal(res.headers['content-type'], 'application/javascript; charset=UTF-8')
|
||
|
t.equal(
|
||
|
readFileSync(
|
||
|
resolve(__dirname, '..', 'static', 'swagger-ui-standalone-preset.js'),
|
||
|
'utf8'
|
||
|
),
|
||
|
res.payload
|
||
|
)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/static/:file 404', t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/static/stuff.css'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
const payload = JSON.parse(res.payload)
|
||
|
t.equal(res.statusCode, 404)
|
||
|
t.match(payload, {
|
||
|
error: 'Not Found',
|
||
|
statusCode: 404
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation2/json route (overwrite)', t => {
|
||
|
t.plan(2)
|
||
|
const fastify = Fastify()
|
||
|
const swaggerOptionWithRouteOverwrite = JSON.parse(JSON.stringify(swaggerOption))
|
||
|
swaggerOptionWithRouteOverwrite.routePrefix = '/documentation2'
|
||
|
fastify.register(fastifySwagger, swaggerOptionWithRouteOverwrite)
|
||
|
|
||
|
fastify.get('/', () => {})
|
||
|
fastify.post('/', () => {})
|
||
|
fastify.get('/example', schemaQuerystring, () => {})
|
||
|
fastify.post('/example', schemaBody, () => {})
|
||
|
fastify.get('/parameters/:id', schemaParams, () => {})
|
||
|
fastify.get('/example1', schemaSecurity, () => {})
|
||
|
fastify.get('/parameters/:id/:key', schemaParamsWithKey, () => {})
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation2/json'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
|
||
|
const payload = JSON.parse(res.payload)
|
||
|
|
||
|
Swagger.validate(payload)
|
||
|
.then(function (api) {
|
||
|
t.pass('valid swagger object')
|
||
|
})
|
||
|
.catch(function (err) {
|
||
|
t.fail(err)
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/:myfile should return 404 in dynamic mode', t => {
|
||
|
t.plan(2)
|
||
|
const fastify = Fastify()
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/swagger-ui.js'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 404)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/:myfile should run custom NotFoundHandler in dynamic mode', t => {
|
||
|
t.plan(2)
|
||
|
const fastify = Fastify()
|
||
|
const notFoundHandler = function (req, reply) {
|
||
|
reply.code(410).send()
|
||
|
}
|
||
|
fastify.setNotFoundHandler(notFoundHandler)
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/swagger-ui.js'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 410)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
test('/documentation/ should redirect to ./static/index.html', t => {
|
||
|
t.plan(3)
|
||
|
const fastify = Fastify()
|
||
|
fastify.register(fastifySwagger, swaggerOption)
|
||
|
|
||
|
fastify.inject({
|
||
|
method: 'GET',
|
||
|
url: '/documentation/'
|
||
|
}, (err, res) => {
|
||
|
t.error(err)
|
||
|
t.equal(res.statusCode, 302)
|
||
|
t.equal(res.headers.location, './static/index.html')
|
||
|
})
|
||
|
})
|