265 lines
5.6 KiB
JavaScript
265 lines
5.6 KiB
JavaScript
'use strict'
|
|
|
|
const t = require('tap')
|
|
const fastify = require('fastify')
|
|
const AjvCompiler = require('../index')
|
|
|
|
const ajvFormats = require('ajv-formats')
|
|
const ajvErrors = require('ajv-errors')
|
|
const localize = require('ajv-i18n')
|
|
|
|
t.test('Format Baseline test', async (t) => {
|
|
const app = buildApplication({
|
|
customOptions: {
|
|
validateFormats: false
|
|
}
|
|
})
|
|
|
|
const res = await app.inject({
|
|
url: '/hello',
|
|
headers: {
|
|
'x-foo': 'hello',
|
|
'x-date': 'not a date',
|
|
'x-email': 'not an email'
|
|
},
|
|
query: {
|
|
foo: 'hello',
|
|
date: 'not a date',
|
|
email: 'not an email'
|
|
}
|
|
})
|
|
t.equal(res.statusCode, 200, 'format validation does not apply as configured')
|
|
t.equal(res.payload, 'hello')
|
|
})
|
|
|
|
t.test('Custom Format plugin loading test', (t) => {
|
|
t.plan(6)
|
|
const app = buildApplication({
|
|
customOptions: {
|
|
validateFormats: true
|
|
},
|
|
plugins: [[ajvFormats, { mode: 'fast' }]]
|
|
})
|
|
|
|
app.inject('/hello', (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 400, 'format validation applies')
|
|
})
|
|
|
|
app.inject('/2ad0612c-7578-4b18-9a6f-579863f40e0b', (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 400, 'format validation applies')
|
|
})
|
|
|
|
app.inject({
|
|
url: '/2ad0612c-7578-4b18-9a6f-579863f40e0b',
|
|
headers: {
|
|
'x-foo': 'hello',
|
|
'x-date': new Date().toISOString(),
|
|
'x-email': 'foo@bar.baz'
|
|
},
|
|
query: {
|
|
foo: 'hello',
|
|
date: new Date().toISOString(),
|
|
email: 'foo@bar.baz'
|
|
}
|
|
}, (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 200)
|
|
})
|
|
})
|
|
|
|
t.test('Format plugin set by default test', (t) => {
|
|
t.plan(6)
|
|
const app = buildApplication({})
|
|
|
|
app.inject('/hello', (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 400, 'format validation applies')
|
|
})
|
|
|
|
app.inject('/2ad0612c-7578-4b18-9a6f-579863f40e0b', (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 400, 'format validation applies')
|
|
})
|
|
|
|
app.inject({
|
|
url: '/2ad0612c-7578-4b18-9a6f-579863f40e0b',
|
|
headers: {
|
|
'x-foo': 'hello',
|
|
'x-date': new Date().toISOString(),
|
|
'x-email': 'foo@bar.baz'
|
|
},
|
|
query: {
|
|
foo: 'hello',
|
|
date: new Date().toISOString(),
|
|
email: 'foo@bar.baz'
|
|
}
|
|
}, (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 200)
|
|
})
|
|
})
|
|
|
|
t.test('Custom error messages', (t) => {
|
|
t.plan(9)
|
|
|
|
const app = buildApplication({
|
|
customOptions: {
|
|
removeAdditional: false,
|
|
allErrors: true
|
|
},
|
|
plugins: [ajvFormats, ajvErrors]
|
|
})
|
|
|
|
const errorMessage = {
|
|
required: 'custom miss',
|
|
type: 'custom type', // will not replace internal "type" error for the property "foo"
|
|
_: 'custom type', // this prop will do it
|
|
additionalProperties: 'custom too many params'
|
|
}
|
|
|
|
app.post('/', {
|
|
handler: () => { t.fail('dont call me') },
|
|
schema: {
|
|
body: {
|
|
type: 'object',
|
|
required: ['foo'],
|
|
properties: {
|
|
foo: { type: 'integer' }
|
|
},
|
|
additionalProperties: false,
|
|
errorMessage
|
|
}
|
|
}
|
|
})
|
|
|
|
app.inject({
|
|
url: '/',
|
|
method: 'post',
|
|
payload: {}
|
|
}, (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 400)
|
|
t.match(res.json().message, errorMessage.required)
|
|
})
|
|
|
|
app.inject({
|
|
url: '/',
|
|
method: 'post',
|
|
payload: { foo: 'not a number' }
|
|
}, (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 400)
|
|
t.match(res.json().message, errorMessage.type)
|
|
})
|
|
|
|
app.inject({
|
|
url: '/',
|
|
method: 'post',
|
|
payload: { foo: 3, bar: 'ops' }
|
|
}, (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.statusCode, 400)
|
|
t.match(res.json().message, errorMessage.additionalProperties)
|
|
})
|
|
})
|
|
|
|
t.test('Custom i18n error messages', (t) => {
|
|
t.plan(3)
|
|
|
|
const app = buildApplication({
|
|
customOptions: {
|
|
allErrors: true,
|
|
messages: false
|
|
},
|
|
plugins: [ajvFormats]
|
|
})
|
|
|
|
app.post('/', {
|
|
handler: () => { t.fail('dont call me') },
|
|
schema: {
|
|
body: {
|
|
type: 'object',
|
|
required: ['foo'],
|
|
properties: {
|
|
foo: { type: 'integer' }
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
app.setErrorHandler((error, request, reply) => {
|
|
t.pass('Error handler executed')
|
|
if (error.validation) {
|
|
localize.ru(error.validation)
|
|
reply.status(400).send(error.validation)
|
|
return
|
|
}
|
|
t.fail('not other errors')
|
|
})
|
|
|
|
app.inject({
|
|
method: 'POST',
|
|
url: '/',
|
|
payload: {
|
|
foo: 'string'
|
|
}
|
|
}, (err, res) => {
|
|
t.error(err)
|
|
t.equal(res.json()[0].message, 'должно быть integer')
|
|
})
|
|
})
|
|
|
|
function buildApplication (ajvOptions) {
|
|
const factory = AjvCompiler()
|
|
|
|
const app = fastify({
|
|
ajv: ajvOptions,
|
|
schemaController: {
|
|
compilersFactory: {
|
|
buildValidator: factory
|
|
}
|
|
}
|
|
})
|
|
|
|
app.get('/:id', {
|
|
schema: {
|
|
headers: {
|
|
type: 'object',
|
|
required: [
|
|
'x-foo',
|
|
'x-date',
|
|
'x-email'
|
|
],
|
|
properties: {
|
|
'x-foo': { type: 'string' },
|
|
'x-date': { type: 'string', format: 'date-time' },
|
|
'x-email': { type: 'string', format: 'email' }
|
|
}
|
|
},
|
|
query: {
|
|
type: 'object',
|
|
required: [
|
|
'foo',
|
|
'date',
|
|
'email'
|
|
],
|
|
properties: {
|
|
foo: { type: 'string' },
|
|
date: { type: 'string', format: 'date-time' },
|
|
email: { type: 'string', format: 'email' }
|
|
}
|
|
},
|
|
params: {
|
|
type: 'object',
|
|
properties: {
|
|
id: { type: 'string', format: 'uuid' }
|
|
}
|
|
}
|
|
}
|
|
}, async () => 'hello')
|
|
|
|
return app
|
|
}
|