CoolFace
Apppublic

strong-tie/inbound-calls

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
schema-feature.test.js2128 linesDownload Raw Back to test
1'use strict'2 3const { test } = require('tap')4const Fastify = require('..')5const fp = require('fastify-plugin')6const deepClone = require('rfdc')({ circles: true, proto: false })7const Ajv = require('ajv')8const { kSchemaController } = require('../lib/symbols.js')9const { FSTWRN001 } = require('../lib/warnings')10 11const echoParams = (req, reply) => { reply.send(req.params) }12const echoBody = (req, reply) => { reply.send(req.body) }13 14;['addSchema', 'getSchema', 'getSchemas', 'setValidatorCompiler', 'setSerializerCompiler'].forEach(f => {15  test(`Should expose ${f} function`, t => {16    t.plan(1)17    const fastify = Fastify()18    t.equal(typeof fastify[f], 'function')19  })20})21 22;['setValidatorCompiler', 'setSerializerCompiler'].forEach(f => {23  test(`cannot call ${f} after binding`, t => {24    t.plan(2)25    const fastify = Fastify()26    t.teardown(fastify.close.bind(fastify))27    fastify.listen({ port: 0 }, err => {28      t.error(err)29      try {30        fastify[f](() => { })31        t.fail()32      } catch (e) {33        t.pass()34      }35    })36  })37})38 39test('The schemas should be added to an internal storage', t => {40  t.plan(1)41  const fastify = Fastify()42  const schema = { $id: 'id', my: 'schema' }43  fastify.addSchema(schema)44  t.same(fastify[kSchemaController].schemaBucket.store, { id: schema })45})46 47test('The schemas should be accessible via getSchemas', t => {48  t.plan(1)49  const fastify = Fastify()50 51  const schemas = {52    id: { $id: 'id', my: 'schema' },53    abc: { $id: 'abc', my: 'schema' },54    bcd: { $id: 'bcd', my: 'schema', properties: { a: 'a', b: 1 } }55  }56 57  Object.values(schemas).forEach(schema => { fastify.addSchema(schema) })58  t.same(fastify.getSchemas(), schemas)59})60 61test('The schema should be accessible by id via getSchema', t => {62  t.plan(5)63  const fastify = Fastify()64 65  const schemas = [66    { $id: 'id', my: 'schema' },67    { $id: 'abc', my: 'schema' },68    { $id: 'bcd', my: 'schema', properties: { a: 'a', b: 1 } }69  ]70  schemas.forEach(schema => { fastify.addSchema(schema) })71  t.same(fastify.getSchema('abc'), schemas[1])72  t.same(fastify.getSchema('id'), schemas[0])73  t.same(fastify.getSchema('foo'), undefined)74 75  fastify.register((instance, opts, done) => {76    const pluginSchema = { $id: 'cde', my: 'schema' }77    instance.addSchema(pluginSchema)78    t.same(instance.getSchema('cde'), pluginSchema)79    done()80  })81 82  fastify.ready(err => t.error(err))83})84 85test('Get validatorCompiler after setValidatorCompiler', t => {86  t.plan(2)87  const myCompiler = () => { }88  const fastify = Fastify()89  fastify.setValidatorCompiler(myCompiler)90  const sc = fastify.validatorCompiler91  t.ok(Object.is(myCompiler, sc))92  fastify.ready(err => t.error(err))93})94 95test('Get serializerCompiler after setSerializerCompiler', t => {96  t.plan(2)97  const myCompiler = () => { }98  const fastify = Fastify()99  fastify.setSerializerCompiler(myCompiler)100  const sc = fastify.serializerCompiler101  t.ok(Object.is(myCompiler, sc))102  fastify.ready(err => t.error(err))103})104 105test('Get compilers is empty when settle on routes', t => {106  t.plan(3)107 108  const fastify = Fastify()109 110  fastify.post('/', {111    schema: {112      body: { type: 'object', properties: { hello: { type: 'string' } } },113      response: {114        '2xx': {115          type: 'object',116          properties: {117            foo: { type: 'array', items: { type: 'string' } }118          }119        }120      }121    },122    validatorCompiler: ({ schema, method, url, httpPart }) => {},123    serializerCompiler: ({ schema, method, url, httpPart }) => {}124  }, function (req, reply) {125    reply.send('ok')126  })127 128  fastify.inject({129    method: 'POST',130    payload: {},131    url: '/'132  }, (err, res) => {133    t.error(err)134    t.equal(fastify.validatorCompiler, undefined)135    t.equal(fastify.serializerCompiler, undefined)136  })137})138 139test('Should throw if the $id property is missing', t => {140  t.plan(1)141  const fastify = Fastify()142  try {143    fastify.addSchema({ type: 'string' })144    t.fail()145  } catch (err) {146    t.equal(err.code, 'FST_ERR_SCH_MISSING_ID')147  }148})149 150test('Cannot add multiple times the same id', t => {151  t.plan(2)152  const fastify = Fastify()153 154  fastify.addSchema({ $id: 'id' })155  try {156    fastify.addSchema({ $id: 'id' })157  } catch (err) {158    t.equal(err.code, 'FST_ERR_SCH_ALREADY_PRESENT')159    t.equal(err.message, 'Schema with id \'id\' already declared!')160  }161})162 163test('Cannot add schema for query and querystring', t => {164  t.plan(2)165  const fastify = Fastify()166 167  fastify.get('/', {168    handler: () => {},169    schema: {170      query: {171        type: 'object',172        properties: {173          foo: { type: 'string' }174        }175      },176      querystring: {177        type: 'object',178        properties: {179          foo: { type: 'string' }180        }181      }182    }183  })184 185  fastify.ready(err => {186    t.equal(err.code, 'FST_ERR_SCH_DUPLICATE')187    t.equal(err.message, 'Schema with \'querystring\' already present!')188  })189})190 191test('Should throw of the schema does not exists in input', t => {192  t.plan(2)193  const fastify = Fastify()194 195  fastify.get('/:id', {196    handler: echoParams,197    schema: {198      params: {199        type: 'object',200        properties: {201          name: { $ref: '#notExist' }202        }203      }204    }205  })206 207  fastify.ready(err => {208    t.equal(err.code, 'FST_ERR_SCH_VALIDATION_BUILD')209    t.equal(err.message, "Failed building the validation schema for GET: /:id, due to error can't resolve reference #notExist from id #")210  })211})212 213test('Should throw if schema is missing for content type', t => {214  t.plan(2)215 216  const fastify = Fastify()217  fastify.post('/', {218    handler: echoBody,219    schema: {220      body: {221        content: {222          'application/json': {}223        }224      }225    }226  })227 228  fastify.ready(err => {229    t.equal(err.code, 'FST_ERR_SCH_CONTENT_MISSING_SCHEMA')230    t.equal(err.message, "Schema is missing for the content type 'application/json'")231  })232})233 234test('Should throw of the schema does not exists in output', t => {235  t.plan(2)236  const fastify = Fastify()237 238  fastify.get('/:id', {239    handler: echoParams,240    schema: {241      response: {242        '2xx': {243          type: 'object',244          properties: {245            name: { $ref: '#notExist' }246          }247        }248      }249    }250  })251 252  fastify.ready(err => {253    t.equal(err.code, 'FST_ERR_SCH_SERIALIZATION_BUILD')254    t.match(err.message, /^Failed building the serialization schema for GET: \/:id, due to error Cannot find reference.*/) // error from fast-json-stringify255  })256})257 258test('Should not change the input schemas', t => {259  t.plan(4)260 261  const theSchema = {262    $id: 'helloSchema',263    type: 'object',264    definitions: {265      hello: { type: 'string' }266    }267  }268 269  const fastify = Fastify()270  fastify.post('/', {271    handler: echoBody,272    schema: {273      body: {274        type: 'object',275        additionalProperties: false,276        properties: {277          name: { $ref: 'helloSchema#/definitions/hello' }278        }279      },280      response: {281        '2xx': {282          type: 'object',283          properties: {284            name: { $ref: 'helloSchema#/definitions/hello' }285          }286        }287      }288    }289  })290  fastify.addSchema(theSchema)291 292  fastify.inject({293    url: '/',294    method: 'POST',295    payload: { name: 'Foo', surname: 'Bar' }296  }, (err, res) => {297    t.error(err)298    t.same(res.json(), { name: 'Foo' })299    t.ok(theSchema.$id, 'the $id is not removed')300    t.same(fastify.getSchema('helloSchema'), theSchema)301  })302})303 304test('Should emit warning if the schema headers is undefined', t => {305  t.plan(4)306  const fastify = Fastify()307 308  process.on('warning', onWarning)309  function onWarning (warning) {310    t.equal(warning.name, 'FastifyWarning')311    t.equal(warning.code, FSTWRN001.code)312  }313 314  t.teardown(() => {315    process.removeListener('warning', onWarning)316    FSTWRN001.emitted = false317  })318 319  fastify.post('/:id', {320    handler: echoParams,321    schema: {322      headers: undefined323    }324  })325 326  fastify.inject({327    method: 'POST',328    url: '/123'329  }, (error, res) => {330    t.error(error)331    t.equal(res.statusCode, 200)332  })333})334 335test('Should emit warning if the schema body is undefined', t => {336  t.plan(4)337  const fastify = Fastify()338 339  process.on('warning', onWarning)340  function onWarning (warning) {341    t.equal(warning.name, 'FastifyWarning')342    t.equal(warning.code, FSTWRN001.code)343  }344 345  t.teardown(() => {346    process.removeListener('warning', onWarning)347    FSTWRN001.emitted = false348  })349 350  fastify.post('/:id', {351    handler: echoParams,352    schema: {353      body: undefined354    }355  })356 357  fastify.inject({358    method: 'POST',359    url: '/123'360  }, (error, res) => {361    t.error(error)362    t.equal(res.statusCode, 200)363  })364})365 366test('Should emit warning if the schema query is undefined', t => {367  t.plan(4)368  const fastify = Fastify()369 370  process.on('warning', onWarning)371  function onWarning (warning) {372    t.equal(warning.name, 'FastifyWarning')373    t.equal(warning.code, FSTWRN001.code)374  }375 376  t.teardown(() => {377    process.removeListener('warning', onWarning)378    FSTWRN001.emitted = false379  })380 381  fastify.post('/:id', {382    handler: echoParams,383    schema: {384      querystring: undefined385    }386  })387 388  fastify.inject({389    method: 'POST',390    url: '/123'391  }, (error, res) => {392    t.error(error)393    t.equal(res.statusCode, 200)394  })395})396 397test('Should emit warning if the schema params is undefined', t => {398  t.plan(4)399  const fastify = Fastify()400 401  process.on('warning', onWarning)402  function onWarning (warning) {403    t.equal(warning.name, 'FastifyWarning')404    t.equal(warning.code, FSTWRN001.code)405  }406 407  t.teardown(() => {408    process.removeListener('warning', onWarning)409    FSTWRN001.emitted = false410  })411 412  fastify.post('/:id', {413    handler: echoParams,414    schema: {415      params: undefined416    }417  })418 419  fastify.inject({420    method: 'POST',421    url: '/123'422  }, (error, res) => {423    t.error(error)424    t.equal(res.statusCode, 200)425  })426})427 428test('Should emit a warning for every route with undefined schema', t => {429  t.plan(16)430  const fastify = Fastify()431 432  let runs = 0433  const expectedWarningEmitted = [0, 1, 2, 3]434  // It emits 4 warnings:435  // - 2 - GET and HEAD for /undefinedParams/:id436  // - 2 - GET and HEAD for /undefinedBody/:id437  // => 3 x 4 assertions = 12 assertions438  function onWarning (warning) {439    t.equal(warning.name, 'FastifyWarning')440    t.equal(warning.code, FSTWRN001.code)441    t.equal(runs++, expectedWarningEmitted.shift())442  }443 444  process.on('warning', onWarning)445  t.teardown(() => {446    process.removeListener('warning', onWarning)447    FSTWRN001.emitted = false448  })449 450  fastify.get('/undefinedParams/:id', {451    handler: echoParams,452    schema: {453      params: undefined454    }455  })456 457  fastify.get('/undefinedBody/:id', {458    handler: echoParams,459    schema: {460      body: undefined461    }462  })463 464  fastify.inject({465    method: 'GET',466    url: '/undefinedParams/123'467  }, (error, res) => {468    t.error(error)469    t.equal(res.statusCode, 200)470  })471 472  fastify.inject({473    method: 'GET',474    url: '/undefinedBody/123'475  }, (error, res) => {476    t.error(error)477    t.equal(res.statusCode, 200)478  })479})480 481test('First level $ref', t => {482  t.plan(2)483  const fastify = Fastify()484 485  fastify.addSchema({486    $id: 'test',487    type: 'object',488    properties: {489      id: { type: 'number' }490    }491  })492 493  fastify.get('/:id', {494    handler: (req, reply) => {495      reply.send({ id: req.params.id * 2, ignore: 'it' })496    },497    schema: {498      params: { $ref: 'test#' },499      response: {500        200: { $ref: 'test#' }501      }502    }503  })504 505  fastify.inject({506    method: 'GET',507    url: '/123'508  }, (err, res) => {509    t.error(err)510    t.same(res.json(), { id: 246 })511  })512})513 514test('Customize validator compiler in instance and route', t => {515  t.plan(28)516  const fastify = Fastify({ exposeHeadRoutes: false })517 518  fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {519    t.equal(method, 'POST') // run 4 times520    t.equal(url, '/:id') // run 4 times521    switch (httpPart) {522      case 'body':523        t.pass('body evaluated')524        return body => {525          t.same(body, { foo: ['bar', 'BAR'] })526          return true527        }528      case 'params':529        t.pass('params evaluated')530        return params => {531          t.same(params, { id: 1234 })532          return true533        }534      case 'querystring':535        t.pass('querystring evaluated')536        return query => {537          t.same(query, { lang: 'en' })538          return true539        }540      case 'headers':541        t.pass('headers evaluated')542        return headers => {543          t.match(headers, { x: 'hello' })544          return true545        }546      case '2xx':547        t.fail('the validator doesn\'t process the response')548        break549      default:550        t.fail(`unknown httpPart ${httpPart}`)551    }552  })553 554  fastify.post('/:id', {555    handler: echoBody,556    schema: {557      query: {558        type: 'object',559        properties: {560          lang: { type: 'string', enum: ['it', 'en'] }561        }562      },563      headers: {564        type: 'object',565        properties: {566          x: { type: 'string' }567        }568      },569      params: {570        type: 'object',571        properties: {572          id: { type: 'number' }573        }574      },575      body: {576        type: 'object',577        properties: {578          foo: { type: 'array' }579        }580      },581      response: {582        '2xx': {583          type: 'object',584          properties: {585            foo: { type: 'array', items: { type: 'string' } }586          }587        }588      }589    }590  })591 592  fastify.get('/wow/:id', {593    handler: echoParams,594    validatorCompiler: ({ schema, method, url, httpPart }) => {595      t.equal(method, 'GET') // run 3 times (params, headers, query)596      t.equal(url, '/wow/:id') // run 4 times597      return () => { return true } // ignore the validation598    },599    schema: {600      query: {601        type: 'object',602        properties: {603          lang: { type: 'string', enum: ['it', 'en'] }604        }605      },606      headers: {607        type: 'object',608        properties: {609          x: { type: 'string' }610        }611      },612      params: {613        type: 'object',614        properties: {615          id: { type: 'number' }616        }617      },618      response: {619        '2xx': {620          type: 'object',621          properties: {622            foo: { type: 'array', items: { type: 'string' } }623          }624        }625      }626    }627  })628 629  fastify.inject({630    url: '/1234',631    method: 'POST',632    headers: { x: 'hello' },633    query: { lang: 'en' },634    payload: { foo: ['bar', 'BAR'] }635  }, (err, res) => {636    t.error(err)637    t.equal(res.statusCode, 200)638    t.same(res.json(), { foo: ['bar', 'BAR'] })639  })640 641  fastify.inject({642    url: '/wow/should-be-a-num',643    method: 'GET',644    headers: { x: 'hello' },645    query: { lang: 'jp' } // not in the enum646  }, (err, res) => {647    t.error(err)648    t.equal(res.statusCode, 200) // the validation is always true649    t.same(res.json(), {})650  })651})652 653test('Use the same schema across multiple routes', t => {654  t.plan(4)655  const fastify = Fastify()656 657  fastify.addSchema({658    $id: 'test',659    type: 'object',660    properties: {661      id: { type: 'number' }662    }663  })664 665  fastify.get('/first/:id', {666    schema: {667      params: {668        type: 'object',669        properties: {670          id: { $ref: 'test#/properties/id' }671        }672      }673    },674    handler: (req, reply) => {675      reply.send(typeof req.params.id)676    }677  })678 679  fastify.get('/second/:id', {680    schema: {681      params: {682        type: 'object',683        properties: {684          id: { $ref: 'test#/properties/id' }685        }686      }687    },688    handler: (req, reply) => {689      reply.send(typeof req.params.id)690    }691  })692 693  fastify.inject({694    method: 'GET',695    url: '/first/123'696  }, (err, res) => {697    t.error(err)698    t.equal(res.payload, 'number')699  })700 701  fastify.inject({702    method: 'GET',703    url: '/second/123'704  }, (err, res) => {705    t.error(err)706    t.equal(res.payload, 'number')707  })708})709 710test('Encapsulation should intervene', t => {711  t.plan(2)712  const fastify = Fastify()713 714  fastify.register((instance, opts, done) => {715    instance.addSchema({716      $id: 'encapsulation',717      type: 'object',718      properties: {719        id: { type: 'number' }720      }721    })722    done()723  })724 725  fastify.register((instance, opts, done) => {726    instance.get('/:id', {727      handler: echoParams,728      schema: {729        params: {730          type: 'object',731          properties: {732            id: { $ref: 'encapsulation#/properties/id' }733          }734        }735      }736    })737    done()738  })739 740  fastify.ready(err => {741    t.equal(err.code, 'FST_ERR_SCH_VALIDATION_BUILD')742    t.equal(err.message, "Failed building the validation schema for GET: /:id, due to error can't resolve reference encapsulation#/properties/id from id #")743  })744})745 746test('Encapsulation isolation', t => {747  t.plan(1)748  const fastify = Fastify()749 750  fastify.register((instance, opts, done) => {751    instance.addSchema({ $id: 'id' })752    done()753  })754 755  fastify.register((instance, opts, done) => {756    instance.addSchema({ $id: 'id' })757    done()758  })759 760  fastify.ready(err => t.error(err))761})762 763test('Add schema after register', t => {764  t.plan(5)765 766  const fastify = Fastify()767  fastify.register((instance, opts, done) => {768    instance.get('/:id', {769      handler: echoParams,770      schema: {771        params: { $ref: 'test#' }772      }773    })774 775    // add it to the parent instance776    fastify.addSchema({777      $id: 'test',778      type: 'object',779      properties: {780        id: { type: 'number' }781      }782    })783 784    try {785      instance.addSchema({ $id: 'test' })786    } catch (err) {787      t.equal(err.code, 'FST_ERR_SCH_ALREADY_PRESENT')788      t.equal(err.message, 'Schema with id \'test\' already declared!')789    }790    done()791  })792 793  fastify.inject({794    method: 'GET',795    url: '/4242'796  }, (err, res) => {797    t.error(err)798    t.equal(res.statusCode, 200)799    t.same(res.json(), { id: 4242 })800  })801})802 803test('Encapsulation isolation for getSchemas', t => {804  t.plan(5)805  const fastify = Fastify()806 807  let pluginDeepOneSide808  let pluginDeepOne809  let pluginDeepTwo810 811  const schemas = {812    z: { $id: 'z', my: 'schema' },813    a: { $id: 'a', my: 'schema' },814    b: { $id: 'b', my: 'schema' },815    c: { $id: 'c', my: 'schema', properties: { a: 'a', b: 1 } }816  }817 818  fastify.addSchema(schemas.z)819 820  fastify.register((instance, opts, done) => {821    instance.addSchema(schemas.a)822    pluginDeepOneSide = instance823    done()824  })825 826  fastify.register((instance, opts, done) => {827    instance.addSchema(schemas.b)828    instance.register((subinstance, opts, done) => {829      subinstance.addSchema(schemas.c)830      pluginDeepTwo = subinstance831      done()832    })833    pluginDeepOne = instance834    done()835  })836 837  fastify.ready(err => {838    t.error(err)839    t.same(fastify.getSchemas(), { z: schemas.z })840    t.same(pluginDeepOneSide.getSchemas(), { z: schemas.z, a: schemas.a })841    t.same(pluginDeepOne.getSchemas(), { z: schemas.z, b: schemas.b })842    t.same(pluginDeepTwo.getSchemas(), { z: schemas.z, b: schemas.b, c: schemas.c })843  })844})845 846test('Use the same schema id in different places', t => {847  t.plan(1)848  const fastify = Fastify()849 850  fastify.addSchema({851    $id: 'test',852    type: 'object',853    properties: {854      id: { type: 'number' }855    }856  })857 858  fastify.get('/:id', {859    handler: echoParams,860    schema: {861      response: {862        200: {863          type: 'array',864          items: { $ref: 'test#/properties/id' }865        }866      }867    }868  })869 870  fastify.post('/:id', {871    handler: echoBody,872    schema: {873      body: {874        type: 'object',875        properties: {876          id: { $ref: 'test#/properties/id' }877        }878      },879      response: {880        200: {881          type: 'object',882          properties: {883            id: { $ref: 'test#/properties/id' }884          }885        }886      }887    }888  })889 890  fastify.ready(err => t.error(err))891})892 893test('Get schema anyway should not add `properties` if allOf is present', t => {894  t.plan(1)895  const fastify = Fastify()896 897  fastify.addSchema({898    $id: 'first',899    type: 'object',900    properties: {901      first: { type: 'number' }902    }903  })904 905  fastify.addSchema({906    $id: 'second',907    type: 'object',908    allOf: [909      {910        type: 'object',911        properties: {912          second: { type: 'number' }913        }914      },915      fastify.getSchema('first')916    ]917  })918 919  fastify.get('/', {920    handler: () => {},921    schema: {922      querystring: fastify.getSchema('second'),923      response: { 200: fastify.getSchema('second') }924    }925  })926 927  fastify.ready(err => t.error(err))928})929 930test('Get schema anyway should not add `properties` if oneOf is present', t => {931  t.plan(1)932  const fastify = Fastify()933 934  fastify.addSchema({935    $id: 'first',936    type: 'object',937    properties: {938      first: { type: 'number' }939    }940  })941 942  fastify.addSchema({943    $id: 'second',944    type: 'object',945    oneOf: [946      {947        type: 'object',948        properties: {949          second: { type: 'number' }950        }951      },952      fastify.getSchema('first')953    ]954  })955 956  fastify.get('/', {957    handler: () => {},958    schema: {959      querystring: fastify.getSchema('second'),960      response: { 200: fastify.getSchema('second') }961    }962  })963 964  fastify.ready(err => t.error(err))965})966 967test('Get schema anyway should not add `properties` if anyOf is present', t => {968  t.plan(1)969  const fastify = Fastify()970 971  fastify.addSchema({972    $id: 'first',973    type: 'object',974    properties: {975      first: { type: 'number' }976    }977  })978 979  fastify.addSchema({980    $id: 'second',981    type: 'object',982    anyOf: [983      {984        type: 'object',985        properties: {986          second: { type: 'number' }987        }988      },989      fastify.getSchema('first')990    ]991  })992 993  fastify.get('/', {994    handler: () => {},995    schema: {996      querystring: fastify.getSchema('second'),997      response: { 200: fastify.getSchema('second') }998    }999  })1000 1001  fastify.ready(err => t.error(err))1002})1003 1004test('Shared schema should be ignored in string enum', t => {1005  t.plan(2)1006  const fastify = Fastify()1007 1008  fastify.get('/:lang', {1009    handler: echoParams,1010    schema: {1011      params: {1012        type: 'object',1013        properties: {1014          lang: {1015            type: 'string',1016            enum: ['Javascript', 'C++', 'C#']1017          }1018        }1019      }1020    }1021  })1022 1023  fastify.inject('/C%23', (err, res) => {1024    t.error(err)1025    t.same(res.json(), { lang: 'C#' })1026  })1027})1028 1029test('Shared schema should NOT be ignored in != string enum', t => {1030  t.plan(2)1031  const fastify = Fastify()1032 1033  fastify.addSchema({1034    $id: 'C',1035    type: 'object',1036    properties: {1037      lang: {1038        type: 'string',1039        enum: ['Javascript', 'C++', 'C#']1040      }1041    }1042  })1043 1044  fastify.post('/:lang', {1045    handler: echoBody,1046    schema: {1047      body: fastify.getSchema('C')1048    }1049  })1050 1051  fastify.inject({1052    url: '/',1053    method: 'POST',1054    payload: { lang: 'C#' }1055  }, (err, res) => {1056    t.error(err)1057    t.same(res.json(), { lang: 'C#' })1058  })1059})1060 1061test('Case insensitive header validation', t => {1062  t.plan(2)1063  const fastify = Fastify()1064  fastify.get('/', {1065    handler: (req, reply) => {1066      reply.code(200).send(req.headers.foobar)1067    },1068    schema: {1069      headers: {1070        type: 'object',1071        required: ['FooBar'],1072        properties: {1073          FooBar: { type: 'string' }1074        }1075      }1076    }1077  })1078  fastify.inject({1079    url: '/',1080    method: 'GET',1081    headers: {1082      FooBar: 'Baz'1083    }1084  }, (err, res) => {1085    t.error(err)1086    t.equal(res.payload, 'Baz')1087  })1088})1089 1090test('Not evaluate json-schema $schema keyword', t => {1091  t.plan(2)1092  const fastify = Fastify()1093  fastify.post('/', {1094    handler: echoBody,1095    schema: {1096      body: {1097        $schema: 'http://json-schema.org/draft-07/schema#',1098        type: 'object',1099        additionalProperties: false,1100        properties: {1101          hello: {1102            type: 'string'1103          }1104        }1105      }1106    }1107  })1108  fastify.inject({1109    url: '/',1110    method: 'POST',1111    body: { hello: 'world', foo: 'bar' }1112  }, (err, res) => {1113    t.error(err)1114    t.same(res.json(), { hello: 'world' })1115  })1116})1117 1118test('Validation context in validation result', t => {1119  t.plan(5)1120  const fastify = Fastify()1121  // custom error handler to expose validation context in response, so we can test it later1122  fastify.setErrorHandler((err, request, reply) => {1123    t.equal(err instanceof Error, true)1124    t.ok(err.validation, 'detailed errors')1125    t.equal(err.validationContext, 'body')1126    reply.code(400).send()1127  })1128  fastify.post('/', {1129    handler: echoParams,1130    schema: {1131      body: {1132        type: 'object',1133        required: ['hello'],1134        properties: {1135          hello: { type: 'string' }1136        }1137      }1138    }1139  })1140  fastify.inject({1141    method: 'POST',1142    url: '/',1143    payload: {} // body lacks required field, will fail validation1144  }, (err, res) => {1145    t.error(err)1146    t.equal(res.statusCode, 400)1147  })1148})1149 1150test('The schema build should not modify the input', t => {1151  t.plan(3)1152  const fastify = Fastify()1153 1154  const first = {1155    $id: 'first',1156    type: 'object',1157    properties: {1158      first: {1159        type: 'number'1160      }1161    }1162  }1163 1164  fastify.addSchema(first)1165 1166  fastify.addSchema({1167    $id: 'second',1168    type: 'object',1169    allOf: [1170      {1171        type: 'object',1172        properties: {1173          second: {1174            type: 'number'1175          }1176        }1177      },1178      { $ref: 'first#' }1179    ]1180  })1181 1182  fastify.post('/', {1183    schema: {1184      description: 'get',1185      body: { $ref: 'second#' },1186      response: {1187        200: { $ref: 'second#' }1188      }1189    },1190    handler: (request, reply) => {1191      reply.send({ hello: 'world' })1192    }1193  })1194 1195  fastify.patch('/', {1196    schema: {1197      description: 'patch',1198      body: { $ref: 'first#' },1199      response: {1200        200: { $ref: 'first#' }

Showing the first 1,200 of 2128 lines. Download the file for the rest.