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.
		
		
		
		
		
			
		
			
				
					
					
						
							649 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
	
	
							649 lines
						
					
					
						
							13 KiB
						
					
					
				'use strict'
 | 
						|
 | 
						|
const { test } = require('tap')
 | 
						|
const Fastify = require('fastify')
 | 
						|
const Swagger = require('swagger-parser')
 | 
						|
const yaml = require('js-yaml')
 | 
						|
const fastifySwagger = require('../../../index')
 | 
						|
const { readPackageJson } = require('../../../lib/util/common')
 | 
						|
const { openapiOption } = require('../../../examples/options')
 | 
						|
 | 
						|
test('openapi should have default version', t => {
 | 
						|
  t.plan(2)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, { openapi: {} })
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.equal(openapiObject.openapi, '3.0.3')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('openapi should have default info properties', t => {
 | 
						|
  t.plan(3)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, { openapi: {} })
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const pkg = readPackageJson(function () {})
 | 
						|
    t.equal(openapiObject.info.title, pkg.name)
 | 
						|
    t.equal(openapiObject.info.version, pkg.version)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('openapi basic properties', t => {
 | 
						|
  t.plan(5)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        properties: {
 | 
						|
          hello: { type: 'string' },
 | 
						|
          obj: {
 | 
						|
            type: 'object',
 | 
						|
            properties: {
 | 
						|
              some: { type: 'string' }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.equal(openapiObject.info, openapiOption.openapi.info)
 | 
						|
    t.equal(openapiObject.servers, openapiOption.openapi.servers)
 | 
						|
    t.ok(openapiObject.paths)
 | 
						|
    t.ok(openapiObject.paths['/'])
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('openapi components', t => {
 | 
						|
  t.plan(2)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  openapiOption.openapi.components.schemas = {
 | 
						|
    ExampleModel: {
 | 
						|
      type: 'object',
 | 
						|
      properties: {
 | 
						|
        id: {
 | 
						|
          type: 'integer',
 | 
						|
          description: 'Some id'
 | 
						|
        },
 | 
						|
        name: {
 | 
						|
          type: 'string',
 | 
						|
          description: 'Name of smthng'
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  fastify.get('/', () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.same(openapiObject.components.schemas, openapiOption.openapi.components.schemas)
 | 
						|
    delete openapiOption.openapi.components.schemas // remove what we just added
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('hide support when property set in transform() - property', t => {
 | 
						|
  t.plan(2)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, {
 | 
						|
    ...openapiOption,
 | 
						|
    transform: ({ schema, url }) => {
 | 
						|
      return { schema: { ...schema, hide: true }, url }
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        properties: {
 | 
						|
          hello: { type: 'string' },
 | 
						|
          obj: {
 | 
						|
            type: 'object',
 | 
						|
            properties: {
 | 
						|
              some: { type: 'string' }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.notOk(openapiObject.paths['/'])
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('hide support - tags Default', t => {
 | 
						|
  t.plan(2)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      tags: ['X-HIDDEN'],
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        properties: {
 | 
						|
          hello: { type: 'string' },
 | 
						|
          obj: {
 | 
						|
            type: 'object',
 | 
						|
            properties: {
 | 
						|
              some: { type: 'string' }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.notOk(openapiObject.paths['/'])
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('hide support - tags Custom', t => {
 | 
						|
  t.plan(2)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, { ...openapiOption, hiddenTag: 'NOP' })
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      tags: ['NOP'],
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        properties: {
 | 
						|
          hello: { type: 'string' },
 | 
						|
          obj: {
 | 
						|
            type: 'object',
 | 
						|
            properties: {
 | 
						|
              some: { type: 'string' }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.notOk(openapiObject.paths['/'])
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('hide support - hidden untagged', t => {
 | 
						|
  t.plan(2)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, { ...openapiOption, hideUntagged: true })
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        properties: {
 | 
						|
          hello: { type: 'string' },
 | 
						|
          obj: {
 | 
						|
            type: 'object',
 | 
						|
            properties: {
 | 
						|
              some: { type: 'string' }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.notOk(openapiObject.paths['/'])
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('basePath support', t => {
 | 
						|
  t.plan(3)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, {
 | 
						|
    openapi: Object.assign({}, openapiOption.openapi, {
 | 
						|
      servers: [
 | 
						|
        {
 | 
						|
          url: 'http://localhost/prefix'
 | 
						|
        }
 | 
						|
      ]
 | 
						|
    })
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.get('/prefix/endpoint', {}, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.notOk(openapiObject.paths['/prefix/endpoint'])
 | 
						|
    t.ok(openapiObject.paths['/endpoint'])
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('basePath maintained when stripBasePath is set to false', t => {
 | 
						|
  t.plan(4)
 | 
						|
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, {
 | 
						|
    stripBasePath: false,
 | 
						|
    openapi: Object.assign({}, openapiOption.openapi, {
 | 
						|
      servers: [
 | 
						|
        {
 | 
						|
          url: 'http://localhost/foo'
 | 
						|
        }
 | 
						|
      ]
 | 
						|
    })
 | 
						|
  })
 | 
						|
 | 
						|
  fastify.get('/foo/endpoint', {}, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.notOk(openapiObject.paths.endpoint)
 | 
						|
    t.notOk(openapiObject.paths['/endpoint'])
 | 
						|
    t.ok(openapiObject.paths['/foo/endpoint'])
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('cache - json', t => {
 | 
						|
  t.plan(3)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    fastify.swagger()
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    t.equal(typeof openapiObject, 'object')
 | 
						|
 | 
						|
    Swagger.validate(openapiObject)
 | 
						|
      .then(function (api) {
 | 
						|
        t.pass('valid swagger object')
 | 
						|
      })
 | 
						|
      .catch(function (err) {
 | 
						|
        t.fail(err)
 | 
						|
      })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('cache - yaml', t => {
 | 
						|
  t.plan(3)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    fastify.swagger({ yaml: true })
 | 
						|
    const swaggerYaml = fastify.swagger({ yaml: true })
 | 
						|
    t.equal(typeof swaggerYaml, 'string')
 | 
						|
 | 
						|
    try {
 | 
						|
      yaml.load(swaggerYaml)
 | 
						|
      t.pass('valid swagger yaml')
 | 
						|
    } catch (err) {
 | 
						|
      t.fail(err)
 | 
						|
    }
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('transforms examples in example if single string example', t => {
 | 
						|
  t.plan(4)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        required: ['hello'],
 | 
						|
        properties: {
 | 
						|
          hello: {
 | 
						|
            type: 'string',
 | 
						|
            examples: ['world']
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const schema = openapiObject.paths['/'].get.requestBody.content['application/json'].schema
 | 
						|
 | 
						|
    t.ok(schema)
 | 
						|
    t.notOk(schema.properties.hello.examples)
 | 
						|
    t.equal(schema.properties.hello.example, 'world')
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('transforms examples in example if single object example', t => {
 | 
						|
  t.plan(4)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        required: ['hello'],
 | 
						|
        properties: {
 | 
						|
          hello: {
 | 
						|
            type: 'object',
 | 
						|
            properties: {
 | 
						|
              lorem: {
 | 
						|
                type: 'string'
 | 
						|
              }
 | 
						|
            },
 | 
						|
            examples: [{ lorem: 'ipsum' }]
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const schema = openapiObject.paths['/'].get.requestBody.content['application/json'].schema
 | 
						|
 | 
						|
    t.ok(schema)
 | 
						|
    t.notOk(schema.properties.hello.examples)
 | 
						|
    t.same(schema.properties.hello.example, { lorem: 'ipsum' })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('uses examples if has multiple string examples', t => {
 | 
						|
  t.plan(4)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        required: ['hello'],
 | 
						|
        properties: {
 | 
						|
          hello: {
 | 
						|
            type: 'string',
 | 
						|
            examples: ['hello', 'world']
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const schema = openapiObject.paths['/'].get.requestBody.content['application/json'].schema
 | 
						|
 | 
						|
    t.ok(schema)
 | 
						|
    t.ok(schema.properties.hello.examples)
 | 
						|
    t.same(schema.properties.hello.examples, {
 | 
						|
      hello: {
 | 
						|
        value: 'hello'
 | 
						|
      },
 | 
						|
      world: {
 | 
						|
        value: 'world'
 | 
						|
      }
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('uses examples if has multiple numbers examples', t => {
 | 
						|
  t.plan(4)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body: {
 | 
						|
        type: 'object',
 | 
						|
        required: ['hello'],
 | 
						|
        properties: {
 | 
						|
          hello: {
 | 
						|
            type: 'number',
 | 
						|
            examples: [1, 2]
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const schema = openapiObject.paths['/'].get.requestBody.content['application/json'].schema
 | 
						|
 | 
						|
    t.ok(schema)
 | 
						|
    t.ok(schema.properties.hello.examples)
 | 
						|
    t.same(schema.properties.hello.examples, {
 | 
						|
      1: {
 | 
						|
        value: 1
 | 
						|
      },
 | 
						|
      2: {
 | 
						|
        value: 2
 | 
						|
      }
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('uses examples if has multiple object examples', t => {
 | 
						|
  t.plan(4)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  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.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const schema = openapiObject.paths['/'].get.requestBody.content['application/json'].schema
 | 
						|
 | 
						|
    t.ok(schema)
 | 
						|
    t.ok(schema.properties.hello.examples)
 | 
						|
    t.same(schema.properties.hello.examples, {
 | 
						|
      example1: {
 | 
						|
        value: {
 | 
						|
          lorem: 'ipsum'
 | 
						|
        }
 | 
						|
      },
 | 
						|
      example2: {
 | 
						|
        value: {
 | 
						|
          hello: 'world'
 | 
						|
        }
 | 
						|
      }
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('uses examples if has multiple array examples', t => {
 | 
						|
  t.plan(4)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  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.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const schema = openapiObject.paths['/'].get.requestBody.content['application/json'].schema
 | 
						|
 | 
						|
    t.ok(schema)
 | 
						|
    t.ok(schema.properties.hello.examples)
 | 
						|
    t.same(schema.properties.hello.examples, {
 | 
						|
      example1: {
 | 
						|
        value: [
 | 
						|
          'a',
 | 
						|
          'b',
 | 
						|
          'c'
 | 
						|
        ]
 | 
						|
      },
 | 
						|
      example2: {
 | 
						|
        value: [
 | 
						|
          'd',
 | 
						|
          'f',
 | 
						|
          'g'
 | 
						|
        ]
 | 
						|
      }
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
test('uses examples if has property required in body', t => {
 | 
						|
  t.plan(5)
 | 
						|
  const fastify = Fastify()
 | 
						|
 | 
						|
  fastify.register(fastifySwagger, openapiOption)
 | 
						|
 | 
						|
  const body = {
 | 
						|
    type: 'object',
 | 
						|
    required: ['hello'],
 | 
						|
    properties: {
 | 
						|
      hello: {
 | 
						|
        type: 'string'
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  const opts = {
 | 
						|
    schema: {
 | 
						|
      body
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  fastify.get('/', opts, () => {})
 | 
						|
 | 
						|
  fastify.ready(err => {
 | 
						|
    t.error(err)
 | 
						|
 | 
						|
    const openapiObject = fastify.swagger()
 | 
						|
    const schema = openapiObject.paths['/'].get.requestBody.content['application/json'].schema
 | 
						|
    const requestBody = openapiObject.paths['/'].get.requestBody
 | 
						|
 | 
						|
    t.ok(schema)
 | 
						|
    t.ok(schema.properties)
 | 
						|
    t.same(body.required, ['hello'])
 | 
						|
    t.same(requestBody.required, true)
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
module.exports = { openapiOption }
 |