CoolFace
Apppublic

strong-tie/inbound-calls

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
schema-validation.test.js1303 linesDownload Raw Back to test
1'use strict'2 3const { test } = require('tap')4const Fastify = require('..')5 6const AJV = require('ajv')7const Schema = require('fluent-json-schema')8 9const customSchemaCompilers = {10  body: new AJV({11    coerceTypes: false12  }),13  params: new AJV({14    coerceTypes: true15  }),16  querystring: new AJV({17    coerceTypes: true18  })19}20 21const customValidatorCompiler = req => {22  if (!req.httpPart) {23    throw new Error('Missing httpPart')24  }25 26  const compiler = customSchemaCompilers[req.httpPart]27 28  if (!compiler) {29    throw new Error(`Missing compiler for ${req.httpPart}`)30  }31 32  return compiler.compile(req.schema)33}34 35const schemaA = {36  $id: 'urn:schema:foo',37  type: 'object',38  definitions: {39    foo: { type: 'integer' }40  },41  properties: {42    foo: { $ref: '#/definitions/foo' }43  }44}45const schemaBRefToA = {46  $id: 'urn:schema:response',47  type: 'object',48  required: ['foo'],49  properties: {50    foo: { $ref: 'urn:schema:foo#/definitions/foo' }51  }52}53 54const schemaCRefToB = {55  $id: 'urn:schema:request',56  type: 'object',57  required: ['foo'],58  properties: {59    foo: { $ref: 'urn:schema:response#/properties/foo' }60  }61}62 63const schemaArtist = {64  type: 'object',65  properties: {66    name: { type: 'string' },67    work: { type: 'string' }68  },69  required: ['name', 'work']70}71 72test('Basic validation test', t => {73  t.plan(6)74 75  const fastify = Fastify()76  fastify.post('/', {77    schema: {78      body: schemaArtist79    }80  }, function (req, reply) {81    reply.code(200).send(req.body.name)82  })83 84  fastify.inject({85    method: 'POST',86    payload: {87      name: 'michelangelo',88      work: 'sculptor, painter, architect and poet'89    },90    url: '/'91  }, (err, res) => {92    t.error(err)93    t.same(res.payload, 'michelangelo')94    t.equal(res.statusCode, 200)95  })96 97  fastify.inject({98    method: 'POST',99    payload: { name: 'michelangelo' },100    url: '/'101  }, (err, res) => {102    t.error(err)103    t.same(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })104    t.equal(res.statusCode, 400)105  })106})107 108test('Different schema per content type', t => {109  t.plan(12)110 111  const fastify = Fastify()112  fastify.addContentTypeParser('application/octet-stream', {113    parseAs: 'buffer'114  }, async function (_, payload) {115    return payload116  })117  fastify.post('/', {118    schema: {119      body: {120        content: {121          'application/json': {122            schema: schemaArtist123          },124          'application/octet-stream': {125            schema: {} // Skip validation126          },127          'text/plain': {128            schema: { type: 'string' }129          }130        }131      }132    }133  }, async function (req, reply) {134    return reply.send(req.body)135  })136 137  fastify.inject({138    url: '/',139    method: 'POST',140    headers: { 'Content-Type': 'application/json' },141    body: {142      name: 'michelangelo',143      work: 'sculptor, painter, architect and poet'144    }145  }, (err, res) => {146    t.error(err)147    t.same(JSON.parse(res.payload).name, 'michelangelo')148    t.equal(res.statusCode, 200)149  })150 151  fastify.inject({152    url: '/',153    method: 'POST',154    headers: { 'Content-Type': 'application/json' },155    body: { name: 'michelangelo' }156  }, (err, res) => {157    t.error(err)158    t.same(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })159    t.equal(res.statusCode, 400)160  })161 162  fastify.inject({163    url: '/',164    method: 'POST',165    headers: { 'Content-Type': 'application/octet-stream' },166    body: Buffer.from('AAAAAAAA')167  }, (err, res) => {168    t.error(err)169    t.same(res.payload, 'AAAAAAAA')170    t.equal(res.statusCode, 200)171  })172 173  fastify.inject({174    url: '/',175    method: 'POST',176    headers: { 'Content-Type': 'text/plain' },177    body: 'AAAAAAAA'178  }, (err, res) => {179    t.error(err)180    t.same(res.payload, 'AAAAAAAA')181    t.equal(res.statusCode, 200)182  })183})184 185test('Skip validation if no schema for content type', t => {186  t.plan(3)187 188  const fastify = Fastify()189  fastify.post('/', {190    schema: {191      body: {192        content: {193          'application/json': {194            schema: schemaArtist195          }196          // No schema for 'text/plain'197        }198      }199    }200  }, async function (req, reply) {201    return reply.send(req.body)202  })203 204  fastify.inject({205    url: '/',206    method: 'POST',207    headers: { 'Content-Type': 'text/plain' },208    body: 'AAAAAAAA'209  }, (err, res) => {210    t.error(err)211    t.same(res.payload, 'AAAAAAAA')212    t.equal(res.statusCode, 200)213  })214})215 216test('Skip validation if no content type schemas', t => {217  t.plan(3)218 219  const fastify = Fastify()220  fastify.post('/', {221    schema: {222      body: {223        content: {224          // No schemas225        }226      }227    }228  }, async function (req, reply) {229    return reply.send(req.body)230  })231 232  fastify.inject({233    url: '/',234    method: 'POST',235    headers: { 'Content-Type': 'text/plain' },236    body: 'AAAAAAAA'237  }, (err, res) => {238    t.error(err)239    t.same(res.payload, 'AAAAAAAA')240    t.equal(res.statusCode, 200)241  })242})243 244test('External AJV instance', t => {245  t.plan(5)246 247  const fastify = Fastify()248  const ajv = new AJV()249  ajv.addSchema(schemaA)250  ajv.addSchema(schemaBRefToA)251 252  // the user must provide the schemas to fastify also253  fastify.addSchema(schemaA)254  fastify.addSchema(schemaBRefToA)255 256  fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {257    t.pass('custom validator compiler called')258    return ajv.compile(schema)259  })260 261  fastify.post('/', {262    handler (req, reply) { reply.send({ foo: 1 }) },263    schema: {264      body: schemaCRefToB,265      response: {266        '2xx': ajv.getSchema('urn:schema:response').schema267      }268    }269  })270 271  fastify.inject({272    method: 'POST',273    url: '/',274    payload: { foo: 42 }275  }, (err, res) => {276    t.error(err)277    t.equal(res.statusCode, 200)278  })279 280  fastify.inject({281    method: 'POST',282    url: '/',283    payload: { foo: 'not a number' }284  }, (err, res) => {285    t.error(err)286    t.equal(res.statusCode, 400)287  })288})289 290test('Encapsulation', t => {291  t.plan(21)292 293  const fastify = Fastify()294  const ajv = new AJV()295  ajv.addSchema(schemaA)296  ajv.addSchema(schemaBRefToA)297 298  // the user must provide the schemas to fastify also299  fastify.addSchema(schemaA)300  fastify.addSchema(schemaBRefToA)301 302  fastify.register((instance, opts, done) => {303    const validator = ({ schema, method, url, httpPart }) => {304      t.pass('custom validator compiler called')305      return ajv.compile(schema)306    }307    instance.setValidatorCompiler(validator)308    instance.post('/one', {309      handler (req, reply) { reply.send({ foo: 'one' }) },310      schema: {311        body: ajv.getSchema('urn:schema:response').schema312      }313    })314 315    instance.register((instance, opts, done) => {316      instance.post('/two', {317        handler (req, reply) {318          t.same(instance.validatorCompiler, validator)319          reply.send({ foo: 'two' })320        },321        schema: {322          body: ajv.getSchema('urn:schema:response').schema323        }324      })325 326      const anotherValidator = ({ schema, method, url, httpPart }) => {327        return () => { return true } // always valid328      }329      instance.post('/three', {330        validatorCompiler: anotherValidator,331        handler (req, reply) {332          t.same(instance.validatorCompiler, validator, 'the route validator does not change the instance one')333          reply.send({ foo: 'three' })334        },335        schema: {336          body: ajv.getSchema('urn:schema:response').schema337        }338      })339      done()340    })341    done()342  })343 344  fastify.register((instance, opts, done) => {345    instance.post('/clean', function (req, reply) {346      t.equal(instance.validatorCompiler, undefined)347      reply.send({ foo: 'bar' })348    })349    done()350  })351 352  fastify.inject({353    method: 'POST',354    url: '/one',355    payload: { foo: 1 }356  }, (err, res) => {357    t.error(err)358    t.equal(res.statusCode, 200)359    t.same(res.json(), { foo: 'one' })360  })361 362  fastify.inject({363    method: 'POST',364    url: '/one',365    payload: { wrongFoo: 'bar' }366  }, (err, res) => {367    t.error(err)368    t.equal(res.statusCode, 400)369  })370 371  fastify.inject({372    method: 'POST',373    url: '/two',374    payload: { foo: 2 }375  }, (err, res) => {376    t.error(err)377    t.equal(res.statusCode, 200)378    t.same(res.json(), { foo: 'two' })379  })380 381  fastify.inject({382    method: 'POST',383    url: '/two',384    payload: { wrongFoo: 'bar' }385  }, (err, res) => {386    t.error(err)387    t.equal(res.statusCode, 400)388  })389 390  fastify.inject({391    method: 'POST',392    url: '/three',393    payload: { wrongFoo: 'but works' }394  }, (err, res) => {395    t.error(err)396    t.equal(res.statusCode, 200)397    t.same(res.json(), { foo: 'three' })398  })399 400  fastify.inject({401    method: 'POST',402    url: '/clean',403    payload: { wrongFoo: 'bar' }404  }, (err, res) => {405    t.error(err)406    t.equal(res.statusCode, 200)407    t.same(res.json(), { foo: 'bar' })408  })409})410 411test('Triple $ref with a simple $id', t => {412  t.plan(7)413 414  const fastify = Fastify()415  const ajv = new AJV()416  ajv.addSchema(schemaA)417  ajv.addSchema(schemaBRefToA)418  ajv.addSchema(schemaCRefToB)419 420  // the user must provide the schemas to fastify also421  fastify.addSchema(schemaA)422  fastify.addSchema(schemaBRefToA)423  fastify.addSchema(schemaCRefToB)424 425  fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {426    t.pass('custom validator compiler called')427    return ajv.compile(schema)428  })429 430  fastify.post('/', {431    handler (req, reply) { reply.send({ foo: 105, bar: 'foo' }) },432    schema: {433      body: ajv.getSchema('urn:schema:request').schema,434      response: {435        '2xx': ajv.getSchema('urn:schema:response').schema436      }437    }438  })439 440  fastify.inject({441    method: 'POST',442    url: '/',443    payload: { foo: 43 }444  }, (err, res) => {445    t.error(err)446    t.equal(res.statusCode, 200)447    t.same(res.json(), { foo: 105 })448  })449 450  fastify.inject({451    method: 'POST',452    url: '/',453    payload: { fool: 'bar' }454  }, (err, res) => {455    t.error(err)456    t.equal(res.statusCode, 400)457    t.same(res.json().message, "body must have required property 'foo'")458  })459})460 461test('Extending schema', t => {462  t.plan(4)463  const fastify = Fastify()464 465  fastify.addSchema({466    $id: 'address.id',467    type: 'object',468    definitions: {469      address: {470        type: 'object',471        properties: {472          city: { type: 'string' },473          state: { type: 'string' }474        },475        required: ['city', 'state']476      }477    }478  })479 480  fastify.post('/', {481    handler (req, reply) { reply.send('works') },482    schema: {483      body: {484        type: 'object',485        properties: {486          billingAddress: { $ref: 'address.id#/definitions/address' },487          shippingAddress: {488            allOf: [489              { $ref: 'address.id#/definitions/address' },490              {491                type: 'object',492                properties: { type: { enum: ['residential', 'business'] } },493                required: ['type']494              }495            ]496          }497        }498      }499    }500  })501 502  fastify.inject({503    method: 'POST',504    url: '/',505    payload: {506      shippingAddress: {507        city: 'Forlì',508        state: 'FC'509      }510    }511  }, (err, res) => {512    t.error(err)513    t.equal(res.statusCode, 400)514  })515 516  fastify.inject({517    method: 'POST',518    url: '/',519    payload: {520      shippingAddress: {521        city: 'Forlì',522        state: 'FC',523        type: 'business'524      }525    }526  }, (err, res) => {527    t.error(err)528    t.equal(res.statusCode, 200)529  })530})531 532test('Should work with nested ids', t => {533  t.plan(6)534  const fastify = Fastify()535 536  fastify.addSchema({537    $id: 'test',538    type: 'object',539    properties: {540      id: { type: 'number' }541    }542  })543 544  fastify.addSchema({545    $id: 'greetings',546    type: 'string'547  })548 549  fastify.post('/:id', {550    handler (req, reply) { reply.send(typeof req.params.id) },551    schema: {552      params: { $ref: 'test#' },553      body: {554        type: 'object',555        properties: {556          hello: { $ref: 'greetings#' }557        }558      }559    }560  })561 562  fastify.inject({563    method: 'POST',564    url: '/123',565    payload: {566      hello: 'world'567    }568  }, (err, res) => {569    t.error(err)570    t.equal(res.statusCode, 200)571    t.equal(res.payload, 'number')572  })573 574  fastify.inject({575    method: 'POST',576    url: '/abc',577    payload: {578      hello: 'world'579    }580  }, (err, res) => {581    t.error(err)582    t.equal(res.statusCode, 400)583    t.equal(res.json().message, 'params/id must be number')584  })585})586 587test('Use the same schema across multiple routes', t => {588  t.plan(8)589  const fastify = Fastify()590 591  fastify.addSchema({592    $id: 'test',593    type: 'object',594    properties: {595      id: { type: 'number' }596    }597  })598 599  fastify.get('/first/:id', {600    handler (req, reply) { reply.send(typeof req.params.id) },601    schema: {602      params: { $ref: 'test#' }603    }604  })605 606  fastify.get('/second/:id', {607    handler (req, reply) { reply.send(typeof req.params.id) },608    schema: {609      params: { $ref: 'test#' }610    }611  })612 613  ;[614    '/first/123',615    '/second/123'616  ].forEach(url => {617    fastify.inject({618      url,619      method: 'GET'620    }, (err, res) => {621      t.error(err)622      t.equal(res.payload, 'number')623    })624  })625 626  ;[627    '/first/abc',628    '/second/abc'629  ].forEach(url => {630    fastify.inject({631      url,632      method: 'GET'633    }, (err, res) => {634      t.error(err)635      t.equal(res.statusCode, 400)636    })637  })638})639 640test('JSON Schema validation keywords', t => {641  t.plan(6)642  const fastify = Fastify()643 644  fastify.addSchema({645    $id: 'test',646    type: 'object',647    properties: {648      ip: {649        type: 'string',650        format: 'ipv4'651      }652    }653  })654 655  fastify.get('/:ip', {656    handler (req, reply) { reply.send(typeof req.params.ip) },657    schema: {658      params: { $ref: 'test#' }659    }660  })661 662  fastify.inject({663    method: 'GET',664    url: '/127.0.0.1'665  }, (err, res) => {666    t.error(err)667    t.equal(res.statusCode, 200)668    t.equal(res.payload, 'string')669  })670 671  fastify.inject({672    method: 'GET',673    url: '/localhost'674  }, (err, res) => {675    t.error(err)676    t.equal(res.statusCode, 400)677    t.same(res.json(), {678      statusCode: 400,679      code: 'FST_ERR_VALIDATION',680      error: 'Bad Request',681      message: 'params/ip must match format "ipv4"'682    })683  })684})685 686test('Nested id calls', t => {687  t.plan(6)688  const fastify = Fastify()689 690  fastify.addSchema({691    $id: 'test',692    type: 'object',693    properties: {694      ip: {695        type: 'string',696        format: 'ipv4'697      }698    }699  })700 701  fastify.addSchema({702    $id: 'hello',703    type: 'object',704    properties: {705      host: { $ref: 'test#' }706    }707  })708 709  fastify.post('/', {710    handler (req, reply) { reply.send(typeof req.body.host.ip) },711    schema: {712      body: { $ref: 'hello#' }713    }714  })715 716  fastify.inject({717    method: 'POST',718    url: '/',719    payload: { host: { ip: '127.0.0.1' } }720  }, (err, res) => {721    t.error(err)722    t.equal(res.statusCode, 200)723    t.equal(res.payload, 'string')724  })725 726  fastify.inject({727    method: 'POST',728    url: '/',729    payload: { host: { ip: 'localhost' } }730  }, (err, res) => {731    t.error(err)732    t.equal(res.statusCode, 400)733    t.same(res.json(), {734      error: 'Bad Request',735      message: 'body/host/ip must match format "ipv4"',736      statusCode: 400,737      code: 'FST_ERR_VALIDATION'738    })739  })740})741 742test('Use the same schema id in different places', t => {743  t.plan(2)744  const fastify = Fastify()745 746  fastify.addSchema({747    $id: 'test',748    type: 'object',749    properties: {750      id: { type: 'number' }751    }752  })753 754  fastify.post('/', {755    handler (req, reply) { reply.send({ id: req.body.id / 2 }) },756    schema: {757      body: { $ref: 'test#' },758      response: {759        200: { $ref: 'test#' }760      }761    }762  })763 764  fastify.inject({765    method: 'POST',766    url: '/',767    payload: { id: 42 }768  }, (err, res) => {769    t.error(err)770    t.same(res.json(), { id: 21 })771  })772})773 774test('Use shared schema and $ref with $id ($ref to $id)', t => {775  t.plan(5)776  const fastify = Fastify()777 778  fastify.addSchema({779    $id: 'http://foo/test',780    type: 'object',781    properties: {782      id: { type: 'number' }783    }784  })785 786  const body = {787    $id: 'http://foo/user',788    $schema: 'http://json-schema.org/draft-07/schema#',789    type: 'object',790    definitions: {791      address: {792        $id: '#address',793        type: 'object',794        properties: {795          city: { type: 'string' }796        }797      }798    },799    required: ['address'],800    properties: {801      test: { $ref: 'http://foo/test#' }, // to external802      address: { $ref: '#address' } // to local803    }804  }805 806  fastify.post('/', {807    handler (req, reply) { reply.send(req.body.test) },808    schema: {809      body,810      response: {811        200: { $ref: 'http://foo/test#' }812      }813    }814  })815 816  const id = Date.now()817  fastify.inject({818    method: 'POST',819    url: '/',820    payload: {821      address: { city: 'New Node' },822      test: { id }823    }824  }, (err, res) => {825    t.error(err)826    t.same(res.json(), { id })827  })828 829  fastify.inject({830    method: 'POST',831    url: '/',832    payload: { test: { id } }833  }, (err, res) => {834    t.error(err)835    t.equal(res.statusCode, 400)836    t.same(res.json(), {837      error: 'Bad Request',838      message: "body must have required property 'address'",839      statusCode: 400,840      code: 'FST_ERR_VALIDATION'841    })842  })843})844 845test('Use items with $ref', t => {846  t.plan(4)847  const fastify = Fastify()848 849  fastify.addSchema({850    $id: 'http://example.com/ref-to-external-validator.json',851    type: 'object',852    properties: {853      hello: { type: 'string' }854    }855  })856 857  const body = {858    type: 'array',859    items: { $ref: 'http://example.com/ref-to-external-validator.json#' }860  }861 862  fastify.post('/', {863    schema: { body },864    handler: (_, r) => { r.send('ok') }865  })866 867  fastify.inject({868    method: 'POST',869    url: '/',870    payload: [{ hello: 'world' }]871  }, (err, res) => {872    t.error(err)873    t.equal(res.payload, 'ok')874  })875 876  fastify.inject({877    method: 'POST',878    url: '/',879    payload: { hello: 'world' }880  }, (err, res) => {881    t.error(err)882    t.equal(res.statusCode, 400)883  })884})885 886test('Use $ref to /definitions', t => {887  t.plan(6)888  const fastify = Fastify()889 890  fastify.addSchema({891    $id: 'test',892    type: 'object',893    properties: {894      id: { type: 'number' }895    }896  })897 898  const body = {899    type: 'object',900    definitions: {901      address: {902        $id: '#otherId',903        type: 'object',904        properties: {905          city: { type: 'string' }906        }907      }908    },909    properties: {910      test: { $ref: 'test#' },911      address: { $ref: '#/definitions/address' }912    },913    required: ['address', 'test']914  }915 916  fastify.post('/', {917    schema: {918      body,919      response: {920        200: body921      }922    },923    handler: (req, reply) => {924      req.body.removeThis = 'it should not be serialized'925      reply.send(req.body)926    }927  })928 929  const payload = {930    address: { city: 'New Node' },931    test: { id: Date.now() }932  }933  fastify.inject({934    method: 'POST',935    url: '/',936    payload937  }, (err, res) => {938    t.error(err)939    t.equal(res.statusCode, 200)940    t.same(res.json(), payload)941  })942 943  fastify.inject({944    method: 'POST',945    url: '/',946    payload: {947      address: { city: 'New Node' },948      test: { id: 'wrong' }949    }950  }, (err, res) => {951    t.error(err)952    t.equal(res.statusCode, 400)953    t.same(res.json(), {954      error: 'Bad Request',955      message: 'body/test/id must be number',956      statusCode: 400,957      code: 'FST_ERR_VALIDATION'958    })959  })960})961 962test('Custom AJV settings - pt1', t => {963  t.plan(4)964  const fastify = Fastify()965 966  fastify.post('/', {967    schema: {968      body: {969        type: 'object',970        properties: {971          num: { type: 'integer' }972        }973      }974    },975    handler: (req, reply) => {976      t.equal(req.body.num, 12)977      reply.send(req.body)978    }979  })980 981  fastify.inject({982    method: 'POST',983    url: '/',984    payload: {985      num: '12'986    }987  }, (err, res) => {988    t.error(err)989    t.equal(res.statusCode, 200)990    t.same(res.json(), { num: 12 })991  })992})993 994test('Custom AJV settings - pt2', t => {995  t.plan(2)996  const fastify = Fastify({997    ajv: {998      customOptions: {999        coerceTypes: false1000      }1001    }1002  })1003 1004  fastify.post('/', {1005    schema: {1006      body: {1007        type: 'object',1008        properties: {1009          num: { type: 'integer' }1010        }1011      }1012    },1013    handler: (req, reply) => {1014      t.fail('the handler is not called because the "12" is not coerced to number')1015    }1016  })1017 1018  fastify.inject({1019    method: 'POST',1020    url: '/',1021    payload: {1022      num: '12'1023    }1024  }, (err, res) => {1025    t.error(err)1026    t.equal(res.statusCode, 400)1027  })1028})1029 1030test('Custom AJV settings on different parameters - pt1', t => {1031  t.plan(2)1032  const fastify = Fastify()1033 1034  fastify.setValidatorCompiler(customValidatorCompiler)1035 1036  fastify.post('/api/:id', {1037    schema: {1038      querystring: {1039        type: 'object',1040        properties: {1041          id: { type: 'integer' }1042        }1043      },1044      body: {1045        type: 'object',1046        properties: {1047          num: { type: 'number' }1048        },1049        required: ['num']1050      }1051    },1052    handler: (req, reply) => {1053      t.fail('the handler is not called because the "12" is not coerced to number')1054    }1055  })1056 1057  fastify.inject({1058    method: 'POST',1059    url: '/api/42',1060    payload: {1061      num: '12'1062    }1063  }, (err, res) => {1064    t.error(err)1065    t.equal(res.statusCode, 400)1066  })1067})1068 1069test('Custom AJV settings on different parameters - pt2', t => {1070  t.plan(4)1071  const fastify = Fastify()1072 1073  fastify.setValidatorCompiler(customValidatorCompiler)1074 1075  fastify.post('/api/:id', {1076    schema: {1077      params: {1078        type: 'object',1079        properties: {1080          id: { type: 'number' }1081        },1082        required: ['id']1083      },1084      body: {1085        type: 'object',1086        properties: {1087          num: { type: 'number' }1088        },1089        required: ['num']1090      }1091    },1092    handler: (req, reply) => {1093      t.same(typeof req.params.id, 'number')1094      t.same(typeof req.body.num, 'number')1095      t.same(req.params.id, 42)1096      t.same(req.body.num, 12)1097    }1098  })1099 1100  fastify.inject({1101    method: 'POST',1102    url: '/api/42',1103    payload: {1104      num: 121105    }1106  })1107})1108 1109test("The same $id in route's schema must not overwrite others", t => {1110  t.plan(4)1111  const fastify = Fastify()1112 1113  const UserSchema = Schema.object()1114    .id('http://mydomain.com/user')1115    .title('User schema')1116    .description('Contains all user fields')1117    .prop('id', Schema.integer())1118    .prop('username', Schema.string().minLength(4))1119    .prop('firstName', Schema.string().minLength(1))1120    .prop('lastName', Schema.string().minLength(1))1121    .prop('fullName', Schema.string().minLength(1))1122    .prop('email', Schema.string())1123    .prop('password', Schema.string().minLength(6))1124    .prop('bio', Schema.string())1125 1126  const userCreateSchema = UserSchema.only([1127    'username',1128    'firstName',1129    'lastName',1130    'email',1131    'bio',1132    'password',1133    'password_confirm'1134  ])1135    .required([1136      'username',1137      'firstName',1138      'lastName',1139      'email',1140      'bio',1141      'password'1142    ])1143 1144  const userPatchSchema = UserSchema.only([1145    'firstName',1146    'lastName',1147    'bio'1148  ])1149 1150  fastify1151    .patch('/user/:id', {1152      schema: { body: userPatchSchema },1153      handler: () => { return 'ok' }1154    })1155    .post('/user', {1156      schema: { body: userCreateSchema },1157      handler: () => { return 'ok' }1158    })1159 1160  fastify.inject({1161    method: 'POST',1162    url: '/user',1163    body: {}1164  }, (err, res) => {1165    t.error(err)1166    t.same(res.json().message, "body must have required property 'username'")1167  })1168 1169  fastify.inject({1170    url: '/user/1',1171    method: 'PATCH',1172    body: {}1173  }, (err, res) => {1174    t.error(err)1175    t.same(res.payload, 'ok')1176  })1177})1178 1179test('Custom validator compiler should not mutate schema', async t => {1180  t.plan(2)1181  class Headers { }1182  const fastify = Fastify()1183 1184  fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {1185    t.type(schema, Headers)1186    return () => { }1187  })1188 1189  fastify.get('/', {1190    schema: {1191      headers: new Headers()1192    }1193  }, () => { })1194 1195  await fastify.ready()1196})1197 1198test('Custom validator builder override by custom validator compiler', async t => {1199  t.plan(3)1200  const ajvDefaults = {

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