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.
		
		
		
		
		
			
		
			
				
					333 lines
				
				8.5 KiB
			
		
		
			
		
	
	
					333 lines
				
				8.5 KiB
			| 
											3 years ago
										 | 
 | ||
|  | 'use strict' | ||
|  | 
 | ||
|  | const sget = require('simple-get').concat | ||
|  | const Ajv = require('ajv') | ||
|  | const Joi = require('@hapi/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(0, function (err) { | ||
|  |     if (err) { | ||
|  |       t.error(err) | ||
|  |     } | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     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 should be integer', | ||
|  |           statusCode: 400 | ||
|  |         }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     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 | ||
|  |         }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     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.same(body, { | ||
|  |           error: 'Bad Request', | ||
|  |           message: 'hello must be a `string` type, but the final value was: `44`.', | ||
|  |           statusCode: 400 | ||
|  |         }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     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' | ||
|  |         }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     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' | ||
|  |         }) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | } |