Last active
January 12, 2018 04:22
-
-
Save xiaoyvr/5ec26fbd0f603d0ca312c2ab472d0920 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const _ = require('lodash') | |
const Ajv = require('ajv') | |
const pathToRegexp = require('path-to-regexp') | |
const {expect} = require('chai') | |
const SwaggerParser = require('swagger-parser') | |
const request = require('supertest') | |
module.exports = { | |
create: async(specFile) => { | |
const parser = new SwaggerParser() | |
const spec = await parser.dereference(specFile) | |
const validations = [], ajv = new Ajv() | |
_.forIn(spec.paths, (pathSpec, path) => { | |
_.forIn(pathSpec, (methodSpec, method) => { | |
const bodyParameter = _.find(methodSpec.parameters, p => p.in === 'body') | |
let requestBody | |
if (bodyParameter) { | |
const inlineBody = {} | |
_.forIn(bodyParameter.schema.properties, (value, key) => { | |
inlineBody[key] = value.example | |
}) | |
requestBody = Object.assign(inlineBody, bodyParameter.schema.example || {}) | |
} | |
validations.push({ | |
uriTemplate: spec.basePath + path, | |
method, | |
requestBody, | |
responses: methodSpec.responses | |
}) | |
}) | |
}) | |
function match(uriTemplate, path) { | |
const routeStr = (uriTemplate.replace(/{(\w+)}/g, ':$1')) | |
const keys = [] | |
const re = pathToRegexp(routeStr, keys) | |
const match = re.exec(path) | |
return !!match | |
} | |
function formatObjectSchema(obj) { | |
const properties = obj.properties || {} | |
for (let key in properties) { | |
const property = properties[key] | |
if (property.type === 'string' && property.format === 'byte') { | |
// remove properties[prop].format: byte | |
delete properties[key].format | |
} | |
if (property.type === 'number' && property.format === 'float') { | |
// remove properties[prop].format: byte | |
delete properties[key].format | |
} | |
if (property.type === 'object') { | |
formatObjectSchema(property) | |
} | |
} | |
} | |
function formatJSONSchema(schema) { | |
formatObjectSchema(schema) | |
} | |
function report(method, path, validate) { | |
return `${method} ${path} | |
${JSON.stringify(validate.errors, null, 2)}` | |
} | |
return { | |
getValidator: (method, path) => { | |
const validation = _.find(validations, v => match(v.uriTemplate, path) && v.method === method) | |
if ( !validation ) { | |
throw `No validation found for ${method} ${path}` | |
} | |
return { | |
validation, | |
validate: async(app, statusCode, headers, requestMap = (example => example)) => { | |
let req = request(app)[method](path) | |
_.forIn(headers, (value, key) => { | |
req = req.set(key, value) | |
}) | |
if (validation.requestBody) { | |
requestMap(validation.requestBody) | |
req = req.send(validation.requestBody) | |
} | |
return await req | |
.expect(statusCode) | |
.expect(res => { | |
const schema = validation.responses['' + statusCode].schema | |
formatJSONSchema(schema) | |
const validate = ajv.compile(schema) | |
const result = validate(res.body) | |
const msg = report(method, path, validate) | |
expect(result, msg).to.be.true | |
}) | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment