511 lines
12 KiB
JavaScript
511 lines
12 KiB
JavaScript
'use strict'
|
|
|
|
const path = require('node:path')
|
|
const { test } = require('node:test')
|
|
const Fastify = require('fastify')
|
|
const fastifySwagger = require('../../index')
|
|
const fastifySwaggerDynamic = require('../../lib/mode/dynamic')
|
|
const Swagger = require('@apidevtools/swagger-parser')
|
|
const readFileSync = require('node:fs').readFileSync
|
|
const resolve = require('node:path').resolve
|
|
const yaml = require('yaml')
|
|
|
|
test('specification validation check works', async (t) => {
|
|
const specificationTests = [
|
|
{
|
|
specification: '',
|
|
error: 'Error: specification is missing in the module options'
|
|
},
|
|
{
|
|
specification: '123',
|
|
error: 'Error: specification is not an object'
|
|
},
|
|
{
|
|
specification: {},
|
|
error: 'Error: both specification.path and specification.document are missing, should be path to the file or swagger document spec'
|
|
},
|
|
{
|
|
specification: {
|
|
path: 123
|
|
},
|
|
error: 'Error: specification.path is not a string'
|
|
},
|
|
{
|
|
specification: {
|
|
path: '/hello/lionel.richie'
|
|
},
|
|
error: 'Error: /hello/lionel.richie does not exist'
|
|
},
|
|
{
|
|
specification: {
|
|
path: './examples/example-static-specification.yaml',
|
|
postProcessor: 'hello'
|
|
},
|
|
error: 'Error: specification.postProcessor should be a function'
|
|
}
|
|
]
|
|
|
|
t.plan(specificationTests.length * 2)
|
|
|
|
for (const specificationTest of specificationTests) {
|
|
try {
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, {
|
|
mode: 'static',
|
|
specification: specificationTest.specification
|
|
})
|
|
} catch (err) {
|
|
t.assert.notEqual(err, undefined)
|
|
t.assert.strictEqual(err.toString(), specificationTest.error)
|
|
}
|
|
}
|
|
})
|
|
|
|
test('registering plugin with invalid mode throws an error', async (t) => {
|
|
const config = {
|
|
mode: 'error'
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
try {
|
|
await fastify.register(fastifySwagger, config)
|
|
} catch (err) {
|
|
t.assert.strictEqual(err.message, 'unsupported mode, should be one of [\'static\', \'dynamic\']')
|
|
}
|
|
})
|
|
|
|
test('unsupported file extension in specification.path throws an error', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.js'
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
try {
|
|
await fastify.register(fastifySwagger, config)
|
|
} catch (err) {
|
|
t.assert.strictEqual(err.message, 'specification.path extension name is not supported, should be one from [\'.yaml\', \'.json\']')
|
|
}
|
|
})
|
|
|
|
test('non-string specification.baseDir throws an error ', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.yaml',
|
|
baseDir: 1
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
try {
|
|
await fastify.register(fastifySwagger, config)
|
|
} catch (err) {
|
|
t.assert.strictEqual(err.message, 'specification.baseDir should be string')
|
|
}
|
|
})
|
|
|
|
test('valid specification.baseDir is handled properly /1', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.json',
|
|
baseDir: __dirname
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
await fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
t.assert.deepStrictEqual(
|
|
JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.json'), 'utf8')),
|
|
fastify.swagger({ json: true })
|
|
)
|
|
})
|
|
|
|
test('valid specification.baseDir is handled properly /2', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.json',
|
|
baseDir: __dirname + '/' // eslint-disable-line n/no-path-concat
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
await fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
t.assert.deepStrictEqual(
|
|
JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.json'), 'utf8')),
|
|
fastify.swagger({ json: true })
|
|
)
|
|
})
|
|
|
|
test('valid yaml-specification is converted properly to json', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.yaml'
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
await fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
t.assert.deepStrictEqual(
|
|
JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.json'), 'utf8')),
|
|
fastify.swagger()
|
|
)
|
|
})
|
|
|
|
test('valid specification yaml is properly handled as yaml', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.yaml',
|
|
baseDir: __dirname
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
await fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
t.assert.strictEqual(
|
|
readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.yaml'), 'utf8'),
|
|
fastify.swagger({ yaml: true })
|
|
)
|
|
})
|
|
|
|
test('non-object specification.document throws an error', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
document: 'doc'
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = new Fastify()
|
|
|
|
await t.assert.rejects(async () => await fastify.register(fastifySwagger, config), new Error('specification.document is not an object'))
|
|
})
|
|
|
|
test('object specification.document', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
document: {
|
|
type: 'object'
|
|
}
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = new Fastify()
|
|
fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
t.assert.deepStrictEqual(fastify.swagger(), { type: 'object' })
|
|
})
|
|
|
|
test('inserts default opts in fastifySwagger', async (t) => {
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
await fastify.register(fastifySwagger)
|
|
|
|
t.assert.ok(true, 'Inserted default option for fastifySwagger.')
|
|
})
|
|
|
|
test('inserts default package name', async (t) => {
|
|
const config = {
|
|
mode: 'dynamic',
|
|
specification: {
|
|
path: './examples/example-static-specification.json'
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
|
|
const originalPathJoin = path.join
|
|
const testPackageJSON = path.join(__dirname, '../../examples/test-package.json')
|
|
|
|
path.join = (...args) => {
|
|
if (args[3] === 'package.json') {
|
|
return testPackageJSON
|
|
}
|
|
return originalPathJoin(...args)
|
|
}
|
|
|
|
await fastify.ready()
|
|
|
|
t.assert.deepStrictEqual(fastify.swagger(), {
|
|
swagger: '2.0',
|
|
info: { version: '1.0.0', title: 'test' },
|
|
definitions: {},
|
|
paths: {}
|
|
})
|
|
})
|
|
|
|
test('inserts default package name - openapi', async (t) => {
|
|
const config = {
|
|
mode: 'dynamic',
|
|
openapi: {
|
|
servers: []
|
|
},
|
|
specification: {
|
|
path: './examples/example-static-specification.json'
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
|
|
const originalPathJoin = path.join
|
|
const testPackageJSON = path.join(__dirname, '../../examples/test-package.json')
|
|
|
|
path.join = (...args) => {
|
|
if (args[3] === 'package.json') {
|
|
return testPackageJSON
|
|
}
|
|
return originalPathJoin(...args)
|
|
}
|
|
|
|
await fastify.ready()
|
|
|
|
t.assert.deepStrictEqual(fastify.swagger(), {
|
|
openapi: '3.0.3',
|
|
info: { version: '1.0.0', title: 'test' },
|
|
components: { schemas: {} },
|
|
paths: {},
|
|
servers: []
|
|
})
|
|
})
|
|
|
|
test('throws an error if cannot parse package\'s JSON', async (t) => {
|
|
const config = {
|
|
mode: 'dynamic',
|
|
specification: {
|
|
path: './examples/example-static-specification.json'
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
|
|
const originalPathJoin = path.join
|
|
const testPackageJSON = path.join(__dirname, '')
|
|
|
|
path.join = (...args) => {
|
|
if (args[3] === 'package.json') {
|
|
return testPackageJSON
|
|
}
|
|
return originalPathJoin(...args)
|
|
}
|
|
|
|
await fastify.ready()
|
|
|
|
t.assert.deepStrictEqual(fastify.swagger(), {
|
|
swagger: '2.0',
|
|
info: { version: '1.0.0', title: '' },
|
|
definitions: {},
|
|
paths: {}
|
|
})
|
|
})
|
|
|
|
test('throws an error if cannot parse package\'s JSON - openapi', async (t) => {
|
|
const config = {
|
|
mode: 'dynamic',
|
|
openapi: {
|
|
servers: []
|
|
},
|
|
specification: {
|
|
path: './examples/example-static-specification.json'
|
|
}
|
|
}
|
|
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
|
|
const originalPathJoin = path.join
|
|
const testPackageJSON = path.join(__dirname, '')
|
|
|
|
path.join = (...args) => {
|
|
if (args[3] === 'package.json') {
|
|
return testPackageJSON
|
|
}
|
|
return originalPathJoin(...args)
|
|
}
|
|
|
|
await fastify.ready()
|
|
|
|
t.assert.deepStrictEqual(fastify.swagger(), {
|
|
openapi: '3.0.3',
|
|
info: { version: '1.0.0', title: '' },
|
|
components: { schemas: {} },
|
|
paths: {},
|
|
servers: []
|
|
})
|
|
})
|
|
|
|
test('inserts default opts in fastifySwaggerDynamic (dynamic.js)', async (t) => {
|
|
t.plan(1)
|
|
const fastify = Fastify()
|
|
|
|
await fastify.register(fastifySwaggerDynamic)
|
|
|
|
t.assert.ok(true, 'Inserted default option for fastifySwagger.')
|
|
})
|
|
|
|
test('should still return valid swagger object when missing package.json', async (t) => {
|
|
const config = {
|
|
mode: 'dynamic',
|
|
specification: {
|
|
path: './examples/example-static-specification.json'
|
|
}
|
|
}
|
|
|
|
t.plan(2)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
|
|
const originalPathJoin = path.join
|
|
const testPackageJSON = path.join(__dirname, 'missing.json')
|
|
|
|
path.join = (...args) => {
|
|
if (args[3] === 'package.json') {
|
|
return testPackageJSON
|
|
}
|
|
return originalPathJoin(...args)
|
|
}
|
|
|
|
await fastify.ready()
|
|
|
|
const swaggerObject = fastify.swagger()
|
|
t.assert.strictEqual(typeof swaggerObject, 'object')
|
|
|
|
await Swagger.validate(swaggerObject)
|
|
t.assert.ok(true, 'Swagger object is still valid.')
|
|
})
|
|
|
|
test('.swagger() returns cache.swaggerObject on second request in static mode', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.json'
|
|
}
|
|
}
|
|
|
|
t.plan(3)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
|
|
const swaggerJson1 = fastify.swagger()
|
|
t.assert.strictEqual(typeof swaggerJson1, 'object')
|
|
|
|
const swaggerJson2 = fastify.swagger()
|
|
t.assert.strictEqual(typeof swaggerJson2, 'object')
|
|
t.assert.strictEqual(swaggerJson1, swaggerJson2)
|
|
})
|
|
|
|
test('.swagger({ yaml: true }) returns cache.swaggerString on second request in static mode', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.yaml'
|
|
}
|
|
}
|
|
|
|
t.plan(3)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
|
|
const swaggerYaml1 = fastify.swagger({ yaml: true })
|
|
t.assert.strictEqual(typeof swaggerYaml1, 'string')
|
|
|
|
const swaggerYaml2 = fastify.swagger({ yaml: true })
|
|
t.assert.strictEqual(typeof swaggerYaml2, 'string')
|
|
t.assert.strictEqual(swaggerYaml1, swaggerYaml2)
|
|
})
|
|
|
|
test('postProcessor works, swagger route returns updated yaml', async (t) => {
|
|
const config = {
|
|
mode: 'static',
|
|
specification: {
|
|
path: './examples/example-static-specification.yaml',
|
|
postProcessor: function (swaggerObject) {
|
|
swaggerObject.servers[0].url = 'http://localhost:4000/'
|
|
return swaggerObject
|
|
}
|
|
}
|
|
}
|
|
|
|
const expectedYaml = `openapi: 3.0.0
|
|
info:
|
|
description: Test swagger specification
|
|
version: 1.0.0
|
|
title: Test swagger specification
|
|
contact:
|
|
email: super.developer@gmail.com
|
|
servers:
|
|
- url: http://localhost:4000/
|
|
description: Localhost (uses test data)
|
|
paths:
|
|
/status:
|
|
get:
|
|
description: Status route, so we can check if server is alive
|
|
tags:
|
|
- Status
|
|
responses:
|
|
"200":
|
|
description: Server is alive
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
health:
|
|
type: boolean
|
|
date:
|
|
type: string
|
|
example:
|
|
health: true
|
|
date: 2018-02-19T15:36:46.758Z
|
|
`
|
|
|
|
t.plan(3)
|
|
const fastify = Fastify()
|
|
await fastify.register(fastifySwagger, config)
|
|
await fastify.ready()
|
|
|
|
// check that yaml is there
|
|
const res = fastify.swagger({ yaml: true })
|
|
|
|
t.assert.strictEqual(typeof res, 'string')
|
|
yaml.parse(res)
|
|
t.assert.strictEqual(res, expectedYaml)
|
|
t.assert.ok(true, 'valid swagger yaml')
|
|
})
|