fastify
Version:
Fast and low overhead web framework, for Node.js
337 lines (313 loc) • 8.9 kB
JavaScript
'use strict'
const sget = require('simple-get').concat
const Ajv = require('ajv')
const Joi = require('joi')
const yup = require('yup')
module.exports.payloadMethod = function (method, t) {
const test = t.test
const fastify = require('..')()
const upMethod = method.toUpperCase()
const loMethod = method.toLowerCase()
const opts = {
schema: {
body: {
type: 'object',
properties: {
hello: {
type: 'integer'
}
}
}
}
}
const ajv = new Ajv({ coerceTypes: true, removeAdditional: true })
const optsWithCustomValidator = {
schema: {
body: {
type: 'object',
properties: {
hello: {
type: 'integer'
}
},
additionalProperties: false
}
},
validatorCompiler: function ({ schema, method, url, httpPart }) {
return ajv.compile(schema)
}
}
const optsWithJoiValidator = {
schema: {
body: Joi.object().keys({
hello: Joi.string().required()
}).required()
},
validatorCompiler: function ({ schema, method, url, httpPart }) {
return schema.validate.bind(schema)
}
}
const yupOptions = {
strict: true, // don't coerce
abortEarly: false, // return all errors
stripUnknown: true, // remove additional properties
recursive: true
}
const optsWithYupValidator = {
schema: {
body: yup.object().shape({
hello: yup.string().required()
}).required()
},
validatorCompiler: function ({ schema, method, url, httpPart }) {
return data => {
try {
const result = schema.validateSync(data, yupOptions)
return { value: result }
} catch (e) {
return { error: [e] }
}
}
}
}
test(`${upMethod} can be created`, t => {
t.plan(1)
try {
fastify[loMethod]('/', opts, function (req, reply) {
reply.send(req.body)
})
fastify[loMethod]('/custom', optsWithCustomValidator, function (req, reply) {
reply.send(req.body)
})
fastify[loMethod]('/joi', optsWithJoiValidator, function (req, reply) {
reply.send(req.body)
})
fastify[loMethod]('/yup', optsWithYupValidator, function (req, reply) {
reply.send(req.body)
})
fastify.register(function (fastify2, opts, done) {
fastify2.setValidatorCompiler(function schema ({ schema, method, url, httpPart }) {
return body => ({ error: new Error('From custom schema compiler!') })
})
const withInstanceCustomCompiler = {
schema: {
body: {
type: 'object',
properties: { },
additionalProperties: false
}
}
}
fastify2[loMethod]('/plugin', withInstanceCustomCompiler, (req, reply) => reply.send({ hello: 'never here!' }))
const optsWithCustomValidator2 = {
schema: {
body: {
type: 'object',
properties: { },
additionalProperties: false
}
},
validatorCompiler: function ({ schema, method, url, httpPart }) {
return function (body) {
return { error: new Error('Always fail!') }
}
}
}
fastify2[loMethod]('/plugin/custom', optsWithCustomValidator2, (req, reply) => reply.send({ hello: 'never here!' }))
done()
})
t.pass()
} catch (e) {
t.fail()
}
})
fastify.listen({ port: 0 }, function (err) {
if (err) {
t.error(err)
}
t.teardown(() => { fastify.close() })
test(`${upMethod} - correctly replies`, t => {
if (upMethod === 'HEAD') {
t.plan(2)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port
}, (err, response) => {
t.error(err)
t.equal(response.statusCode, 200)
})
} else {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port,
body: {
hello: 42
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.same(body, { hello: 42 })
})
}
})
test(`${upMethod} - 400 on bad parameters`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port,
body: {
hello: 'world'
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.same(body, {
error: 'Bad Request',
message: 'body/hello must be integer',
statusCode: 400,
code: 'FST_ERR_VALIDATION'
})
})
})
test(`${upMethod} - input-validation coerce`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port,
body: {
hello: '42'
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.same(body, { hello: 42 })
})
})
test(`${upMethod} - input-validation custom schema compiler`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port + '/custom',
body: {
hello: '42',
world: 55
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.same(body, { hello: 42 })
})
})
test(`${upMethod} - input-validation joi schema compiler ok`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port + '/joi',
body: {
hello: '42'
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.same(body, { hello: 42 })
})
})
test(`${upMethod} - input-validation joi schema compiler ko`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port + '/joi',
body: {
hello: 44
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.same(body, {
error: 'Bad Request',
message: '"hello" must be a string',
statusCode: 400,
code: 'FST_ERR_VALIDATION'
})
})
})
test(`${upMethod} - input-validation yup schema compiler ok`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port + '/yup',
body: {
hello: '42'
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.same(body, { hello: 42 })
})
})
test(`${upMethod} - input-validation yup schema compiler ko`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port + '/yup',
body: {
hello: 44
},
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.match(body, {
error: 'Bad Request',
message: /body hello must be a `string` type, but the final value was: `44`./,
statusCode: 400,
code: 'FST_ERR_VALIDATION'
})
})
})
test(`${upMethod} - input-validation instance custom schema compiler encapsulated`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port + '/plugin',
body: { },
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.same(body, {
error: 'Bad Request',
message: 'From custom schema compiler!',
statusCode: '400',
code: 'FST_ERR_VALIDATION'
})
})
})
test(`${upMethod} - input-validation custom schema compiler encapsulated`, t => {
t.plan(3)
sget({
method: upMethod,
url: 'http://localhost:' + fastify.server.address().port + '/plugin/custom',
body: { },
json: true
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 400)
t.same(body, {
error: 'Bad Request',
message: 'Always fail!',
statusCode: '400',
code: 'FST_ERR_VALIDATION'
})
})
})
})
}