strong-tie/inbound-calls
0
1'use strict'2 3const { test } = require('node:test')4const Fastify = require('..')5const S = require('fluent-json-schema')6 7test('use fluent-json-schema object', async (t) => {8 t.plan(10)9 const fastify = Fastify()10 11 fastify.post('/:id', {12 handler: (req, reply) => { reply.send({ name: 'a', surname: 'b', dateOfBirth: '01-01-2020' }) },13 schema: {14 params: S.object().prop('id', S.integer().minimum(42)),15 headers: S.object().prop('x-custom', S.string().format('email')),16 query: S.object().prop('surname', S.string().required()),17 body: S.object().prop('name', S.string().required()),18 response: {19 200: S.object()20 .prop('name', S.string())21 .prop('surname', S.string())22 }23 }24 })25 26 const res1 = await fastify.inject({27 method: 'POST',28 url: '/1',29 headers: { 'x-custom': 'me@me.me' },30 query: { surname: 'bar' },31 payload: { name: 'foo' }32 })33 t.assert.strictEqual(res1.statusCode, 400)34 t.assert.deepStrictEqual(res1.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: 'params/id must be >= 42' })35 36 // check header37 const res2 = await fastify.inject({38 method: 'POST',39 url: '/42',40 headers: { 'x-custom': 'invalid' },41 query: { surname: 'bar' },42 payload: { name: 'foo' }43 })44 t.assert.strictEqual(res2.statusCode, 400)45 t.assert.deepStrictEqual(res2.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: 'headers/x-custom must match format "email"' })46 47 // check query48 const res3 = await fastify.inject({49 method: 'POST',50 url: '/42',51 headers: { 'x-custom': 'me@me.me' },52 query: { },53 payload: { name: 'foo' }54 })55 t.assert.strictEqual(res3.statusCode, 400)56 t.assert.deepStrictEqual(res3.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: 'querystring must have required property \'surname\'' })57 58 // check body59 const res4 = await fastify.inject({60 method: 'POST',61 url: '/42',62 headers: { 'x-custom': 'me@me.me' },63 query: { surname: 'bar' },64 payload: { name: [1, 2, 3] }65 })66 t.assert.strictEqual(res4.statusCode, 400)67 t.assert.deepStrictEqual(res4.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: 'body/name must be string' })68 69 // check response70 const res5 = await fastify.inject({71 method: 'POST',72 url: '/42',73 headers: { 'x-custom': 'me@me.me' },74 query: { surname: 'bar' },75 payload: { name: 'foo' }76 })77 t.assert.strictEqual(res5.statusCode, 200)78 t.assert.deepStrictEqual(res5.json(), { name: 'a', surname: 'b' })79})80 81test('use complex fluent-json-schema object', (t, done) => {82 t.plan(1)83 const fastify = Fastify()84 85 const addressSchema = S.object()86 .id('#address')87 .prop('line1').required()88 .prop('line2')89 .prop('country').required()90 .prop('city').required()91 .prop('zipcode').required()92 93 const commonSchemas = S.object()94 .id('https://fastify/demo')95 .definition('addressSchema', addressSchema)96 97 fastify.addSchema(commonSchemas)98 99 const bodyJsonSchema = S.object()100 .prop('residence', S.ref('https://fastify/demo#address')).required()101 .prop('office', S.ref('https://fastify/demo#/definitions/addressSchema')).required()102 103 fastify.post('/the/url', { schema: { body: bodyJsonSchema } }, () => { })104 fastify.ready(err => {105 t.assert.ifError(err)106 done()107 })108})109 110test('use fluent schema and plain JSON schema', (t, done) => {111 t.plan(1)112 113 const fastify = Fastify()114 115 const addressSchema = S.object()116 .id('#address')117 .prop('line1').required()118 .prop('line2')119 .prop('country').required()120 .prop('city').required()121 .prop('zipcode').required()122 123 const commonSchemas = S.object()124 .id('https://fastify/demo')125 .definition('addressSchema', addressSchema)126 127 const sharedAddressSchema = {128 $id: 'sharedAddress',129 type: 'object',130 required: ['line1', 'country', 'city', 'zipcode'],131 properties: {132 line1: { type: 'string' },133 line2: { type: 'string' },134 country: { type: 'string' },135 city: { type: 'string' },136 zipcode: { type: 'string' }137 }138 }139 140 fastify.addSchema(commonSchemas)141 fastify.addSchema(sharedAddressSchema)142 143 const bodyJsonSchema = S.object()144 .prop('residence', S.ref('https://fastify/demo#address')).required()145 .prop('office', S.ref('https://fastify/demo#/definitions/addressSchema')).required()146 147 fastify.post('/the/url', { schema: { body: bodyJsonSchema } }, () => { })148 fastify.ready(err => {149 t.assert.ifError(err)150 done()151 })152})153 154test('Should call valueOf internally', (t, done) => {155 t.plan(1)156 157 const fastify = new Fastify()158 159 const addressSchema = S.object()160 .id('#address')161 .prop('line1').required()162 .prop('line2')163 .prop('country').required()164 .prop('city').required()165 .prop('zipcode').required()166 167 const commonSchemas = S.object()168 .id('https://fastify/demo')169 .definition('addressSchema', addressSchema)170 171 fastify.addSchema(commonSchemas)172 173 fastify.route({174 method: 'POST',175 url: '/query',176 handler: () => {},177 schema: {178 query: S.object().prop('hello', S.string()).required(),179 body: S.object().prop('hello', S.string()).required(),180 params: S.object().prop('hello', S.string()).required(),181 headers: S.object().prop('hello', S.string()).required(),182 response: {183 200: S.object().prop('hello', S.string()).required(),184 201: S.object().prop('hello', S.string()).required()185 }186 }187 })188 189 fastify.route({190 method: 'POST',191 url: '/querystring',192 handler: () => {},193 schema: {194 querystring: S.object().prop('hello', S.string()).required(),195 body: S.object().prop('hello', S.string()).required(),196 params: S.object().prop('hello', S.string()).required(),197 headers: S.object().prop('hello', S.string()).required(),198 response: {199 200: S.object().prop('hello', S.string()).required(),200 201: S.object().prop('hello', S.string()).required()201 }202 }203 })204 205 fastify.ready(err => {206 t.assert.ifError(err)207 done()208 })209})210 