1 | 'use strict'
|
2 |
|
3 | const sget = require('simple-get').concat
|
4 | const Ajv = require('ajv')
|
5 | const Joi = require('joi')
|
6 | const yup = require('yup')
|
7 |
|
8 | module.exports.payloadMethod = function (method, t) {
|
9 | const test = t.test
|
10 | const fastify = require('..')()
|
11 | const upMethod = method.toUpperCase()
|
12 | const loMethod = method.toLowerCase()
|
13 |
|
14 | const opts = {
|
15 | schema: {
|
16 | body: {
|
17 | type: 'object',
|
18 | properties: {
|
19 | hello: {
|
20 | type: 'integer'
|
21 | }
|
22 | }
|
23 | }
|
24 | }
|
25 | }
|
26 |
|
27 | const ajv = new Ajv({ coerceTypes: true, removeAdditional: true })
|
28 | const optsWithCustomValidator = {
|
29 | schema: {
|
30 | body: {
|
31 | type: 'object',
|
32 | properties: {
|
33 | hello: {
|
34 | type: 'integer'
|
35 | }
|
36 | },
|
37 | additionalProperties: false
|
38 | }
|
39 | },
|
40 | schemaCompiler: function (schema) {
|
41 | return ajv.compile(schema)
|
42 | }
|
43 | }
|
44 |
|
45 | const optsWithJoiValidator = {
|
46 | schema: {
|
47 | body: Joi.object().keys({
|
48 | hello: Joi.string().required()
|
49 | }).required()
|
50 | },
|
51 | schemaCompiler: function (schema) {
|
52 | return schema.validate.bind(schema)
|
53 | }
|
54 | }
|
55 |
|
56 | const yupOptions = {
|
57 | strict: true,
|
58 | abortEarly: false,
|
59 | stripUnknown: true,
|
60 | recursive: true
|
61 | }
|
62 |
|
63 | const optsWithYupValidator = {
|
64 | schema: {
|
65 | body: yup.object().shape({
|
66 | hello: yup.string().required()
|
67 | }).required()
|
68 | },
|
69 | schemaCompiler: schema => data => {
|
70 | try {
|
71 | const result = schema.validateSync(data, yupOptions)
|
72 | return { value: result }
|
73 | } catch (e) {
|
74 | return { error: e }
|
75 | }
|
76 | }
|
77 | }
|
78 |
|
79 | test(`${upMethod} can be created`, t => {
|
80 | t.plan(1)
|
81 | try {
|
82 | fastify[loMethod]('/', opts, function (req, reply) {
|
83 | reply.send(req.body)
|
84 | })
|
85 | fastify[loMethod]('/custom', optsWithCustomValidator, function (req, reply) {
|
86 | reply.send(req.body)
|
87 | })
|
88 | fastify[loMethod]('/joi', optsWithJoiValidator, function (req, reply) {
|
89 | reply.send(req.body)
|
90 | })
|
91 | fastify[loMethod]('/yup', optsWithYupValidator, function (req, reply) {
|
92 | reply.send(req.body)
|
93 | })
|
94 |
|
95 | fastify.register(function (fastify2, opts, next) {
|
96 | fastify2.setSchemaCompiler(function schema (schema) {
|
97 | return body => ({ error: new Error('From custom schema compiler!') })
|
98 | })
|
99 | const withInstanceCustomCompiler = {
|
100 | schema: {
|
101 | body: {
|
102 | type: 'object',
|
103 | properties: { },
|
104 | additionalProperties: false
|
105 | }
|
106 | }
|
107 | }
|
108 | fastify2[loMethod]('/plugin', withInstanceCustomCompiler, (req, reply) => reply.send({ hello: 'never here!' }))
|
109 |
|
110 | const optsWithCustomValidator2 = {
|
111 | schema: {
|
112 | body: {
|
113 | type: 'object',
|
114 | properties: { },
|
115 | additionalProperties: false
|
116 | }
|
117 | },
|
118 | schemaCompiler: function (schema) {
|
119 | return function (body) {
|
120 | return { error: new Error('Always fail!') }
|
121 | }
|
122 | }
|
123 | }
|
124 | fastify2[loMethod]('/plugin/custom', optsWithCustomValidator2, (req, reply) => reply.send({ hello: 'never here!' }))
|
125 |
|
126 | next()
|
127 | })
|
128 | t.pass()
|
129 | } catch (e) {
|
130 | t.fail()
|
131 | }
|
132 | })
|
133 |
|
134 | fastify.listen(0, function (err) {
|
135 | if (err) {
|
136 | t.error(err)
|
137 | }
|
138 |
|
139 | fastify.server.unref()
|
140 |
|
141 | test(`${upMethod} - correctly replies`, t => {
|
142 | if (upMethod === 'HEAD') {
|
143 | t.plan(2)
|
144 | sget({
|
145 | method: upMethod,
|
146 | url: 'http://localhost:' + fastify.server.address().port
|
147 | }, (err, response) => {
|
148 | t.error(err)
|
149 | t.strictEqual(response.statusCode, 200)
|
150 | })
|
151 | } else {
|
152 | t.plan(3)
|
153 | sget({
|
154 | method: upMethod,
|
155 | url: 'http://localhost:' + fastify.server.address().port,
|
156 | body: {
|
157 | hello: 42
|
158 | },
|
159 | json: true
|
160 | }, (err, response, body) => {
|
161 | t.error(err)
|
162 | t.strictEqual(response.statusCode, 200)
|
163 | t.deepEqual(body, { hello: 42 })
|
164 | })
|
165 | }
|
166 | })
|
167 |
|
168 | test(`${upMethod} - 400 on bad parameters`, t => {
|
169 | t.plan(3)
|
170 | sget({
|
171 | method: upMethod,
|
172 | url: 'http://localhost:' + fastify.server.address().port,
|
173 | body: {
|
174 | hello: 'world'
|
175 | },
|
176 | json: true
|
177 | }, (err, response, body) => {
|
178 | t.error(err)
|
179 | t.strictEqual(response.statusCode, 400)
|
180 | t.deepEqual(body, {
|
181 | error: 'Bad Request',
|
182 | message: 'body.hello should be integer',
|
183 | statusCode: 400
|
184 | })
|
185 | })
|
186 | })
|
187 |
|
188 | test(`${upMethod} - input-validation coerce`, t => {
|
189 | t.plan(3)
|
190 | sget({
|
191 | method: upMethod,
|
192 | url: 'http://localhost:' + fastify.server.address().port,
|
193 | body: {
|
194 | hello: '42'
|
195 | },
|
196 | json: true
|
197 | }, (err, response, body) => {
|
198 | t.error(err)
|
199 | t.strictEqual(response.statusCode, 200)
|
200 | t.deepEqual(body, { hello: 42 })
|
201 | })
|
202 | })
|
203 |
|
204 | test(`${upMethod} - input-validation custom schema compiler`, t => {
|
205 | t.plan(3)
|
206 | sget({
|
207 | method: upMethod,
|
208 | url: 'http://localhost:' + fastify.server.address().port + '/custom',
|
209 | body: {
|
210 | hello: '42',
|
211 | world: 55
|
212 | },
|
213 | json: true
|
214 | }, (err, response, body) => {
|
215 | t.error(err)
|
216 | t.strictEqual(response.statusCode, 200)
|
217 | t.deepEqual(body, { hello: 42 })
|
218 | })
|
219 | })
|
220 |
|
221 | test(`${upMethod} - input-validation joi schema compiler ok`, t => {
|
222 | t.plan(3)
|
223 | sget({
|
224 | method: upMethod,
|
225 | url: 'http://localhost:' + fastify.server.address().port + '/joi',
|
226 | body: {
|
227 | hello: '42'
|
228 | },
|
229 | json: true
|
230 | }, (err, response, body) => {
|
231 | t.error(err)
|
232 | t.strictEqual(response.statusCode, 200)
|
233 | t.deepEqual(body, { hello: 42 })
|
234 | })
|
235 | })
|
236 |
|
237 | test(`${upMethod} - input-validation joi schema compiler ko`, t => {
|
238 | t.plan(3)
|
239 | sget({
|
240 | method: upMethod,
|
241 | url: 'http://localhost:' + fastify.server.address().port + '/joi',
|
242 | body: {
|
243 | hello: 44
|
244 | },
|
245 | json: true
|
246 | }, (err, response, body) => {
|
247 | t.error(err)
|
248 | t.strictEqual(response.statusCode, 400)
|
249 | t.deepEqual(body, {
|
250 | error: 'Bad Request',
|
251 | message: 'child "hello" fails because ["hello" must be a string]',
|
252 | statusCode: 400
|
253 | })
|
254 | })
|
255 | })
|
256 |
|
257 | test(`${upMethod} - input-validation yup schema compiler ok`, t => {
|
258 | t.plan(3)
|
259 | sget({
|
260 | method: upMethod,
|
261 | url: 'http://localhost:' + fastify.server.address().port + '/yup',
|
262 | body: {
|
263 | hello: '42'
|
264 | },
|
265 | json: true
|
266 | }, (err, response, body) => {
|
267 | t.error(err)
|
268 | t.strictEqual(response.statusCode, 200)
|
269 | t.deepEqual(body, { hello: 42 })
|
270 | })
|
271 | })
|
272 |
|
273 | test(`${upMethod} - input-validation yup schema compiler ko`, t => {
|
274 | t.plan(3)
|
275 | sget({
|
276 | method: upMethod,
|
277 | url: 'http://localhost:' + fastify.server.address().port + '/yup',
|
278 | body: {
|
279 | hello: 44
|
280 | },
|
281 | json: true
|
282 | }, (err, response, body) => {
|
283 | t.error(err)
|
284 | t.strictEqual(response.statusCode, 400)
|
285 | t.deepEqual(body, {
|
286 | error: 'Bad Request',
|
287 | message: 'hello must be a `string` type, but the final value was: `44`.',
|
288 | statusCode: 400
|
289 | })
|
290 | })
|
291 | })
|
292 |
|
293 | test(`${upMethod} - input-validation instance custom schema compiler encapsulated`, t => {
|
294 | t.plan(3)
|
295 | sget({
|
296 | method: upMethod,
|
297 | url: 'http://localhost:' + fastify.server.address().port + '/plugin',
|
298 | body: { },
|
299 | json: true
|
300 | }, (err, response, body) => {
|
301 | t.error(err)
|
302 | t.strictEqual(response.statusCode, 400)
|
303 | t.deepEqual(body, {
|
304 | error: 'Bad Request',
|
305 | message: 'From custom schema compiler!',
|
306 | statusCode: '400'
|
307 | })
|
308 | })
|
309 | })
|
310 |
|
311 | test(`${upMethod} - input-validation custom schema compiler encapsulated`, t => {
|
312 | t.plan(3)
|
313 | sget({
|
314 | method: upMethod,
|
315 | url: 'http://localhost:' + fastify.server.address().port + '/plugin/custom',
|
316 | body: { },
|
317 | json: true
|
318 | }, (err, response, body) => {
|
319 | t.error(err)
|
320 | t.strictEqual(response.statusCode, 400)
|
321 | t.deepEqual(body, {
|
322 | error: 'Bad Request',
|
323 | message: 'Always fail!',
|
324 | statusCode: '400'
|
325 | })
|
326 | })
|
327 | })
|
328 | })
|
329 | }
|