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.
		
		
		
		
		
			
		
			
				
					557 lines
				
				12 KiB
			
		
		
			
		
	
	
					557 lines
				
				12 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const { test } = require('tap')
							 | 
						||
| 
								 | 
							
								const localize = require('ajv-i18n')
							 | 
						||
| 
								 | 
							
								const Fastify = require('..')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - URI $id', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  fastify.addSchema({
							 | 
						||
| 
								 | 
							
								    $id: 'http://example.com/',
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      hello: { type: 'string' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/', {
							 | 
						||
| 
								 | 
							
								    handler () { },
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      body: {
							 | 
						||
| 
								 | 
							
								        type: 'array',
							 | 
						||
| 
								 | 
							
								        items: { $ref: 'http://example.com#/properties/hello' }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - string $id', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  fastify.addSchema({
							 | 
						||
| 
								 | 
							
								    $id: 'commonSchema',
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      hello: { type: 'string' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/', {
							 | 
						||
| 
								 | 
							
								    handler () { },
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      body: { $ref: 'commonSchema#' },
							 | 
						||
| 
								 | 
							
								      headers: { $ref: 'commonSchema#' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - get schema', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  fastify.addSchema({
							 | 
						||
| 
								 | 
							
								    $id: 'schemaId',
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      hello: { type: 'string' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const mySchemas = fastify.getSchemas()
							 | 
						||
| 
								 | 
							
								  const mySchema = fastify.getSchema('schemaId')
							 | 
						||
| 
								 | 
							
								  t.same(mySchemas.schemaId, mySchema)
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - get schema encapsulated', async t => {
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.addSchema({ $id: 'one', my: 'hello' })
							 | 
						||
| 
								 | 
							
								  // will return only `one` schema
							 | 
						||
| 
								 | 
							
								  fastify.get('/', (request, reply) => { reply.send(fastify.getSchemas()) })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.register((instance, opts, done) => {
							 | 
						||
| 
								 | 
							
								    instance.addSchema({ $id: 'two', my: 'ciao' })
							 | 
						||
| 
								 | 
							
								    // will return `one` and `two` schemas
							 | 
						||
| 
								 | 
							
								    instance.get('/sub', (request, reply) => { reply.send(instance.getSchemas()) })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    instance.register((subinstance, opts, done) => {
							 | 
						||
| 
								 | 
							
								      subinstance.addSchema({ $id: 'three', my: 'hola' })
							 | 
						||
| 
								 | 
							
								      // will return `one`, `two` and `three`
							 | 
						||
| 
								 | 
							
								      subinstance.get('/deep', (request, reply) => { reply.send(subinstance.getSchemas()) })
							 | 
						||
| 
								 | 
							
								      done()
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								    done()
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const r1 = await fastify.inject('/')
							 | 
						||
| 
								 | 
							
								  const r2 = await fastify.inject('/sub')
							 | 
						||
| 
								 | 
							
								  const r3 = await fastify.inject('/deep')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  t.same(Object.keys(r1.json()), ['one'])
							 | 
						||
| 
								 | 
							
								  t.same(Object.keys(r2.json()), ['one', 'two'])
							 | 
						||
| 
								 | 
							
								  t.same(Object.keys(r3.json()), ['one', 'two', 'three'])
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - validation', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  const handler = () => { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const bodyJsonSchema = {
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    required: ['requiredKey'],
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      someKey: { type: 'string' },
							 | 
						||
| 
								 | 
							
								      someOtherKey: { type: 'number' },
							 | 
						||
| 
								 | 
							
								      requiredKey: {
							 | 
						||
| 
								 | 
							
								        type: 'array',
							 | 
						||
| 
								 | 
							
								        maxItems: 3,
							 | 
						||
| 
								 | 
							
								        items: { type: 'integer' }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      nullableKey: { type: ['number', 'null'] }, // or { type: 'number', nullable: true }
							 | 
						||
| 
								 | 
							
								      multipleTypesKey: { type: ['boolean', 'number'] },
							 | 
						||
| 
								 | 
							
								      multipleRestrictedTypesKey: {
							 | 
						||
| 
								 | 
							
								        oneOf: [
							 | 
						||
| 
								 | 
							
								          { type: 'string', maxLength: 5 },
							 | 
						||
| 
								 | 
							
								          { type: 'number', minimum: 10 }
							 | 
						||
| 
								 | 
							
								        ]
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      enumKey: {
							 | 
						||
| 
								 | 
							
								        type: 'string',
							 | 
						||
| 
								 | 
							
								        enum: ['John', 'Foo']
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      notTypeKey: {
							 | 
						||
| 
								 | 
							
								        not: { type: 'array' }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const queryStringJsonSchema = {
							 | 
						||
| 
								 | 
							
								    name: { type: 'string' },
							 | 
						||
| 
								 | 
							
								    excitement: { type: 'integer' }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const paramsJsonSchema = {
							 | 
						||
| 
								 | 
							
								    par1: { type: 'string' },
							 | 
						||
| 
								 | 
							
								    par2: { type: 'number' }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const headersJsonSchema = {
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      'x-foo': { type: 'string' }
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    required: ['x-foo']
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const schema = {
							 | 
						||
| 
								 | 
							
								    body: bodyJsonSchema,
							 | 
						||
| 
								 | 
							
								    querystring: queryStringJsonSchema,
							 | 
						||
| 
								 | 
							
								    params: paramsJsonSchema,
							 | 
						||
| 
								 | 
							
								    headers: headersJsonSchema
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/the/url', { schema }, handler)
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - ajv config', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify({
							 | 
						||
| 
								 | 
							
								    ajv: {
							 | 
						||
| 
								 | 
							
								      plugins: [
							 | 
						||
| 
								 | 
							
								        require('ajv-merge-patch')
							 | 
						||
| 
								 | 
							
								      ]
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/', {
							 | 
						||
| 
								 | 
							
								    handler (req, reply) { reply.send({ ok: 1 }) },
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      body: {
							 | 
						||
| 
								 | 
							
								        $patch: {
							 | 
						||
| 
								 | 
							
								          source: {
							 | 
						||
| 
								 | 
							
								            type: 'object',
							 | 
						||
| 
								 | 
							
								            properties: {
							 | 
						||
| 
								 | 
							
								              q: {
							 | 
						||
| 
								 | 
							
								                type: 'string'
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          with: [
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              op: 'add',
							 | 
						||
| 
								 | 
							
								              path: '/properties/q',
							 | 
						||
| 
								 | 
							
								              value: { type: 'number' }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          ]
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/foo', {
							 | 
						||
| 
								 | 
							
								    handler (req, reply) { reply.send({ ok: 1 }) },
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      body: {
							 | 
						||
| 
								 | 
							
								        $merge: {
							 | 
						||
| 
								 | 
							
								          source: {
							 | 
						||
| 
								 | 
							
								            type: 'object',
							 | 
						||
| 
								 | 
							
								            properties: {
							 | 
						||
| 
								 | 
							
								              q: {
							 | 
						||
| 
								 | 
							
								                type: 'string'
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          },
							 | 
						||
| 
								 | 
							
								          with: {
							 | 
						||
| 
								 | 
							
								            required: ['q']
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example Joi', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  const handler = () => { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const Joi = require('@hapi/joi')
							 | 
						||
| 
								 | 
							
								  fastify.post('/the/url', {
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      body: Joi.object().keys({
							 | 
						||
| 
								 | 
							
								        hello: Joi.string().required()
							 | 
						||
| 
								 | 
							
								      }).required()
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    validatorCompiler: ({ schema, method, url, httpPart }) => {
							 | 
						||
| 
								 | 
							
								      return data => schema.validate(data)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }, handler)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example yup', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  const handler = () => { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const yup = require('yup')
							 | 
						||
| 
								 | 
							
								  // Validation options to match ajv's baseline options used in Fastify
							 | 
						||
| 
								 | 
							
								  const yupOptions = {
							 | 
						||
| 
								 | 
							
								    strict: false,
							 | 
						||
| 
								 | 
							
								    abortEarly: false, // return all errors
							 | 
						||
| 
								 | 
							
								    stripUnknown: true, // remove additional properties
							 | 
						||
| 
								 | 
							
								    recursive: true
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/the/url', {
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      body: yup.object({
							 | 
						||
| 
								 | 
							
								        age: yup.number().integer().required(),
							 | 
						||
| 
								 | 
							
								        sub: yup.object().shape({
							 | 
						||
| 
								 | 
							
								          name: yup.string().required()
							 | 
						||
| 
								 | 
							
								        }).required()
							 | 
						||
| 
								 | 
							
								      })
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    validatorCompiler: ({ schema, method, url, httpPart }) => {
							 | 
						||
| 
								 | 
							
								      return function (data) {
							 | 
						||
| 
								 | 
							
								        // with option strict = false, yup `validateSync` function returns the coerced value if validation was successful, or throws if validation failed
							 | 
						||
| 
								 | 
							
								        try {
							 | 
						||
| 
								 | 
							
								          const result = schema.validateSync(data, yupOptions)
							 | 
						||
| 
								 | 
							
								          return { value: result }
							 | 
						||
| 
								 | 
							
								        } catch (e) {
							 | 
						||
| 
								 | 
							
								          return { error: e }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }, handler)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - serialization', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  const handler = () => { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const schema = {
							 | 
						||
| 
								 | 
							
								    response: {
							 | 
						||
| 
								 | 
							
								      200: {
							 | 
						||
| 
								 | 
							
								        type: 'object',
							 | 
						||
| 
								 | 
							
								        properties: {
							 | 
						||
| 
								 | 
							
								          value: { type: 'string' },
							 | 
						||
| 
								 | 
							
								          otherValue: { type: 'boolean' }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/the/url', { schema }, handler)
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - serialization 2', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  const handler = () => { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const schema = {
							 | 
						||
| 
								 | 
							
								    response: {
							 | 
						||
| 
								 | 
							
								      '2xx': {
							 | 
						||
| 
								 | 
							
								        type: 'object',
							 | 
						||
| 
								 | 
							
								        properties: {
							 | 
						||
| 
								 | 
							
								          value: { type: 'string' },
							 | 
						||
| 
								 | 
							
								          otherValue: { type: 'boolean' }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      201: {
							 | 
						||
| 
								 | 
							
								        // the contract sintax
							 | 
						||
| 
								 | 
							
								        value: { type: 'string' }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/the/url', { schema }, handler)
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - serializator', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.setSerializerCompiler(({ schema, method, url, httpStatus }) => {
							 | 
						||
| 
								 | 
							
								    return data => JSON.stringify(data)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.get('/user', {
							 | 
						||
| 
								 | 
							
								    handler (req, reply) {
							 | 
						||
| 
								 | 
							
								      reply.send({ id: 1, name: 'Foo', image: 'BIG IMAGE' })
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      response: {
							 | 
						||
| 
								 | 
							
								        '2xx': {
							 | 
						||
| 
								 | 
							
								          id: { type: 'number' },
							 | 
						||
| 
								 | 
							
								          name: { type: 'string' }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('Example - schemas examples', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(1)
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify()
							 | 
						||
| 
								 | 
							
								  const handler = () => { }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.addSchema({
							 | 
						||
| 
								 | 
							
								    $id: 'http://foo/common.json',
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    definitions: {
							 | 
						||
| 
								 | 
							
								      foo: {
							 | 
						||
| 
								 | 
							
								        $id: '#address',
							 | 
						||
| 
								 | 
							
								        type: 'object',
							 | 
						||
| 
								 | 
							
								        properties: {
							 | 
						||
| 
								 | 
							
								          city: { type: 'string' }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.addSchema({
							 | 
						||
| 
								 | 
							
								    $id: 'http://foo/shared.json',
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    definitions: {
							 | 
						||
| 
								 | 
							
								      foo: {
							 | 
						||
| 
								 | 
							
								        type: 'object',
							 | 
						||
| 
								 | 
							
								        properties: {
							 | 
						||
| 
								 | 
							
								          city: { type: 'string' }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const refToId = {
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    definitions: {
							 | 
						||
| 
								 | 
							
								      foo: {
							 | 
						||
| 
								 | 
							
								        $id: '#address',
							 | 
						||
| 
								 | 
							
								        type: 'object',
							 | 
						||
| 
								 | 
							
								        properties: {
							 | 
						||
| 
								 | 
							
								          city: { type: 'string' }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      home: { $ref: '#address' },
							 | 
						||
| 
								 | 
							
								      work: { $ref: '#address' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const refToDefinitions = {
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    definitions: {
							 | 
						||
| 
								 | 
							
								      foo: {
							 | 
						||
| 
								 | 
							
								        $id: '#address',
							 | 
						||
| 
								 | 
							
								        type: 'object',
							 | 
						||
| 
								 | 
							
								        properties: {
							 | 
						||
| 
								 | 
							
								          city: { type: 'string' }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      home: { $ref: '#/definitions/foo' },
							 | 
						||
| 
								 | 
							
								      work: { $ref: '#/definitions/foo' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const refToSharedSchemaId = {
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      home: { $ref: 'http://foo/common.json#address' },
							 | 
						||
| 
								 | 
							
								      work: { $ref: 'http://foo/common.json#address' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const refToSharedSchemaDefinitions = {
							 | 
						||
| 
								 | 
							
								    type: 'object',
							 | 
						||
| 
								 | 
							
								    properties: {
							 | 
						||
| 
								 | 
							
								      home: { $ref: 'http://foo/shared.json#/definitions/foo' },
							 | 
						||
| 
								 | 
							
								      work: { $ref: 'http://foo/shared.json#/definitions/foo' }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.get('/', {
							 | 
						||
| 
								 | 
							
								    handler,
							 | 
						||
| 
								 | 
							
								    schema: {
							 | 
						||
| 
								 | 
							
								      body: refToId,
							 | 
						||
| 
								 | 
							
								      headers: refToDefinitions,
							 | 
						||
| 
								 | 
							
								      params: refToSharedSchemaId,
							 | 
						||
| 
								 | 
							
								      query: refToSharedSchemaDefinitions
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.ready(err => t.error(err))
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('should return custom error messages with ajv-errors', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(3)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify({
							 | 
						||
| 
								 | 
							
								    ajv: {
							 | 
						||
| 
								 | 
							
								      customOptions: { allErrors: true, jsonPointers: true },
							 | 
						||
| 
								 | 
							
								      plugins: [
							 | 
						||
| 
								 | 
							
								        require('ajv-errors')
							 | 
						||
| 
								 | 
							
								      ]
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const schema = {
							 | 
						||
| 
								 | 
							
								    body: {
							 | 
						||
| 
								 | 
							
								      type: 'object',
							 | 
						||
| 
								 | 
							
								      properties: {
							 | 
						||
| 
								 | 
							
								        name: { type: 'string' },
							 | 
						||
| 
								 | 
							
								        work: { type: 'string' },
							 | 
						||
| 
								 | 
							
								        age: {
							 | 
						||
| 
								 | 
							
								          type: 'number',
							 | 
						||
| 
								 | 
							
								          errorMessage: {
							 | 
						||
| 
								 | 
							
								            type: 'bad age - should be num'
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      required: ['name', 'work'],
							 | 
						||
| 
								 | 
							
								      errorMessage: {
							 | 
						||
| 
								 | 
							
								        required: {
							 | 
						||
| 
								 | 
							
								          name: 'name please',
							 | 
						||
| 
								 | 
							
								          work: 'work please',
							 | 
						||
| 
								 | 
							
								          age: 'age please'
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/', { schema }, function (req, reply) {
							 | 
						||
| 
								 | 
							
								    reply.code(200).send(req.body.name)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.inject({
							 | 
						||
| 
								 | 
							
								    method: 'POST',
							 | 
						||
| 
								 | 
							
								    payload: {
							 | 
						||
| 
								 | 
							
								      hello: 'salman',
							 | 
						||
| 
								 | 
							
								      age: 'bad'
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    url: '/'
							 | 
						||
| 
								 | 
							
								  }, (err, res) => {
							 | 
						||
| 
								 | 
							
								    t.error(err)
							 | 
						||
| 
								 | 
							
								    t.same(JSON.parse(res.payload), {
							 | 
						||
| 
								 | 
							
								      statusCode: 400,
							 | 
						||
| 
								 | 
							
								      error: 'Bad Request',
							 | 
						||
| 
								 | 
							
								      message: 'body/age bad age - should be num, body name please, body work please'
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								    t.equal(res.statusCode, 400)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								test('should return localized error messages with ajv-i18n', t => {
							 | 
						||
| 
								 | 
							
								  t.plan(3)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const schema = {
							 | 
						||
| 
								 | 
							
								    body: {
							 | 
						||
| 
								 | 
							
								      type: 'object',
							 | 
						||
| 
								 | 
							
								      properties: {
							 | 
						||
| 
								 | 
							
								        name: { type: 'string' },
							 | 
						||
| 
								 | 
							
								        work: { type: 'string' }
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      required: ['name', 'work']
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const fastify = Fastify({
							 | 
						||
| 
								 | 
							
								    ajv: {
							 | 
						||
| 
								 | 
							
								      customOptions: { allErrors: true }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.setErrorHandler(function (error, request, reply) {
							 | 
						||
| 
								 | 
							
								    if (error.validation) {
							 | 
						||
| 
								 | 
							
								      localize.ru(error.validation)
							 | 
						||
| 
								 | 
							
								      reply.status(400).send(error.validation)
							 | 
						||
| 
								 | 
							
								      return
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    reply.send(error)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.post('/', { schema }, function (req, reply) {
							 | 
						||
| 
								 | 
							
								    reply.code(200).send(req.body.name)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.inject({
							 | 
						||
| 
								 | 
							
								    method: 'POST',
							 | 
						||
| 
								 | 
							
								    payload: {
							 | 
						||
| 
								 | 
							
								      name: 'salman'
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    url: '/'
							 | 
						||
| 
								 | 
							
								  }, (err, res) => {
							 | 
						||
| 
								 | 
							
								    t.error(err)
							 | 
						||
| 
								 | 
							
								    t.same(JSON.parse(res.payload), [{
							 | 
						||
| 
								 | 
							
								      dataPath: '',
							 | 
						||
| 
								 | 
							
								      keyword: 'required',
							 | 
						||
| 
								 | 
							
								      message: 'должно иметь обязательное поле work',
							 | 
						||
| 
								 | 
							
								      params: { missingProperty: 'work' },
							 | 
						||
| 
								 | 
							
								      schemaPath: '#/required'
							 | 
						||
| 
								 | 
							
								    }])
							 | 
						||
| 
								 | 
							
								    t.equal(res.statusCode, 400)
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								})
							 |