strong-tie/inbound-calls
0
1'use strict'2 3const t = require('tap')4const test = t.test5const Fastify = require('..')6const fp = require('fastify-plugin')7const sget = require('simple-get').concat8const symbols = require('../lib/symbols.js')9 10test('server methods should exist', t => {11 t.plan(2)12 const fastify = Fastify()13 t.ok(fastify.decorate)14 t.ok(fastify.hasDecorator)15})16 17test('should check if the given decoration already exist when null', t => {18 t.plan(1)19 const fastify = Fastify()20 fastify.decorate('null', null)21 fastify.ready(() => {22 t.ok(fastify.hasDecorator('null'))23 })24})25 26test('server methods should be encapsulated via .register', t => {27 t.plan(2)28 const fastify = Fastify()29 30 fastify.register((instance, opts, done) => {31 instance.decorate('test', () => {})32 t.ok(instance.test)33 done()34 })35 36 fastify.ready(() => {37 t.notOk(fastify.test)38 })39})40 41test('hasServerMethod should check if the given method already exist', t => {42 t.plan(2)43 const fastify = Fastify()44 45 fastify.register((instance, opts, done) => {46 instance.decorate('test', () => {})47 t.ok(instance.hasDecorator('test'))48 done()49 })50 51 fastify.ready(() => {52 t.notOk(fastify.hasDecorator('test'))53 })54})55 56test('decorate should throw if a declared dependency is not present', t => {57 t.plan(3)58 const fastify = Fastify()59 60 fastify.register((instance, opts, done) => {61 try {62 instance.decorate('test', () => {}, ['dependency'])63 t.fail()64 } catch (e) {65 t.same(e.code, 'FST_ERR_DEC_MISSING_DEPENDENCY')66 t.same(e.message, 'The decorator is missing dependency \'dependency\'.')67 }68 done()69 })70 71 fastify.ready(() => t.pass())72})73 74test('decorate should throw if declared dependency is not array', t => {75 t.plan(3)76 const fastify = Fastify()77 78 fastify.register((instance, opts, done) => {79 try {80 instance.decorate('test', () => {}, {})81 t.fail()82 } catch (e) {83 t.same(e.code, 'FST_ERR_DEC_DEPENDENCY_INVALID_TYPE')84 t.same(e.message, 'The dependencies of decorator \'test\' must be of type Array.')85 }86 done()87 })88 89 fastify.ready(() => t.pass())90})91 92// issue #77793test('should pass error for missing request decorator', t => {94 t.plan(2)95 const fastify = Fastify()96 97 const plugin = fp(function (instance, opts, done) {98 done()99 }, {100 decorators: {101 request: ['foo']102 }103 })104 fastify105 .register(plugin)106 .ready((err) => {107 t.type(err, Error)108 t.match(err, /The decorator 'foo'/)109 })110})111 112test('decorateReply inside register', t => {113 t.plan(11)114 const fastify = Fastify()115 116 fastify.register((instance, opts, done) => {117 instance.decorateReply('test', 'test')118 119 instance.get('/yes', (req, reply) => {120 t.ok(reply.test, 'test exists')121 reply.send({ hello: 'world' })122 })123 124 done()125 })126 127 fastify.get('/no', (req, reply) => {128 t.notOk(reply.test)129 reply.send({ hello: 'world' })130 })131 132 fastify.listen({ port: 0 }, err => {133 t.error(err)134 t.teardown(() => { fastify.close() })135 136 sget({137 method: 'GET',138 url: 'http://localhost:' + fastify.server.address().port + '/yes'139 }, (err, response, body) => {140 t.error(err)141 t.equal(response.statusCode, 200)142 t.equal(response.headers['content-length'], '' + body.length)143 t.same(JSON.parse(body), { hello: 'world' })144 })145 146 sget({147 method: 'GET',148 url: 'http://localhost:' + fastify.server.address().port + '/no'149 }, (err, response, body) => {150 t.error(err)151 t.equal(response.statusCode, 200)152 t.equal(response.headers['content-length'], '' + body.length)153 t.same(JSON.parse(body), { hello: 'world' })154 })155 })156})157 158test('decorateReply as plugin (inside .after)', t => {159 t.plan(11)160 const fastify = Fastify()161 162 fastify.register((instance, opts, done) => {163 instance.register(fp((i, o, n) => {164 instance.decorateReply('test', 'test')165 n()166 })).after(() => {167 instance.get('/yes', (req, reply) => {168 t.ok(reply.test)169 reply.send({ hello: 'world' })170 })171 })172 done()173 })174 175 fastify.get('/no', (req, reply) => {176 t.notOk(reply.test)177 reply.send({ hello: 'world' })178 })179 180 fastify.listen({ port: 0 }, err => {181 t.error(err)182 t.teardown(() => { fastify.close() })183 184 sget({185 method: 'GET',186 url: 'http://localhost:' + fastify.server.address().port + '/yes'187 }, (err, response, body) => {188 t.error(err)189 t.equal(response.statusCode, 200)190 t.equal(response.headers['content-length'], '' + body.length)191 t.same(JSON.parse(body), { hello: 'world' })192 })193 194 sget({195 method: 'GET',196 url: 'http://localhost:' + fastify.server.address().port + '/no'197 }, (err, response, body) => {198 t.error(err)199 t.equal(response.statusCode, 200)200 t.equal(response.headers['content-length'], '' + body.length)201 t.same(JSON.parse(body), { hello: 'world' })202 })203 })204})205 206test('decorateReply as plugin (outside .after)', t => {207 t.plan(11)208 const fastify = Fastify()209 210 fastify.register((instance, opts, done) => {211 instance.register(fp((i, o, n) => {212 instance.decorateReply('test', 'test')213 n()214 }))215 216 instance.get('/yes', (req, reply) => {217 t.ok(reply.test)218 reply.send({ hello: 'world' })219 })220 done()221 })222 223 fastify.get('/no', (req, reply) => {224 t.notOk(reply.test)225 reply.send({ hello: 'world' })226 })227 228 fastify.listen({ port: 0 }, err => {229 t.error(err)230 t.teardown(() => { fastify.close() })231 232 sget({233 method: 'GET',234 url: 'http://localhost:' + fastify.server.address().port + '/yes'235 }, (err, response, body) => {236 t.error(err)237 t.equal(response.statusCode, 200)238 t.equal(response.headers['content-length'], '' + body.length)239 t.same(JSON.parse(body), { hello: 'world' })240 })241 242 sget({243 method: 'GET',244 url: 'http://localhost:' + fastify.server.address().port + '/no'245 }, (err, response, body) => {246 t.error(err)247 t.equal(response.statusCode, 200)248 t.equal(response.headers['content-length'], '' + body.length)249 t.same(JSON.parse(body), { hello: 'world' })250 })251 })252})253 254test('decorateRequest inside register', t => {255 t.plan(11)256 const fastify = Fastify()257 258 fastify.register((instance, opts, done) => {259 instance.decorateRequest('test', 'test')260 261 instance.get('/yes', (req, reply) => {262 t.ok(req.test, 'test exists')263 reply.send({ hello: 'world' })264 })265 266 done()267 })268 269 fastify.get('/no', (req, reply) => {270 t.notOk(req.test)271 reply.send({ hello: 'world' })272 })273 274 fastify.listen({ port: 0 }, err => {275 t.error(err)276 t.teardown(() => { fastify.close() })277 278 sget({279 method: 'GET',280 url: 'http://localhost:' + fastify.server.address().port + '/yes'281 }, (err, response, body) => {282 t.error(err)283 t.equal(response.statusCode, 200)284 t.equal(response.headers['content-length'], '' + body.length)285 t.same(JSON.parse(body), { hello: 'world' })286 })287 288 sget({289 method: 'GET',290 url: 'http://localhost:' + fastify.server.address().port + '/no'291 }, (err, response, body) => {292 t.error(err)293 t.equal(response.statusCode, 200)294 t.equal(response.headers['content-length'], '' + body.length)295 t.same(JSON.parse(body), { hello: 'world' })296 })297 })298})299 300test('decorateRequest as plugin (inside .after)', t => {301 t.plan(11)302 const fastify = Fastify()303 304 fastify.register((instance, opts, done) => {305 instance.register(fp((i, o, n) => {306 instance.decorateRequest('test', 'test')307 n()308 })).after(() => {309 instance.get('/yes', (req, reply) => {310 t.ok(req.test)311 reply.send({ hello: 'world' })312 })313 })314 done()315 })316 317 fastify.get('/no', (req, reply) => {318 t.notOk(req.test)319 reply.send({ hello: 'world' })320 })321 322 fastify.listen({ port: 0 }, err => {323 t.error(err)324 t.teardown(() => { fastify.close() })325 326 sget({327 method: 'GET',328 url: 'http://localhost:' + fastify.server.address().port + '/yes'329 }, (err, response, body) => {330 t.error(err)331 t.equal(response.statusCode, 200)332 t.equal(response.headers['content-length'], '' + body.length)333 t.same(JSON.parse(body), { hello: 'world' })334 })335 336 sget({337 method: 'GET',338 url: 'http://localhost:' + fastify.server.address().port + '/no'339 }, (err, response, body) => {340 t.error(err)341 t.equal(response.statusCode, 200)342 t.equal(response.headers['content-length'], '' + body.length)343 t.same(JSON.parse(body), { hello: 'world' })344 })345 })346})347 348test('decorateRequest as plugin (outside .after)', t => {349 t.plan(11)350 const fastify = Fastify()351 352 fastify.register((instance, opts, done) => {353 instance.register(fp((i, o, n) => {354 instance.decorateRequest('test', 'test')355 n()356 }))357 358 instance.get('/yes', (req, reply) => {359 t.ok(req.test)360 reply.send({ hello: 'world' })361 })362 done()363 })364 365 fastify.get('/no', (req, reply) => {366 t.notOk(req.test)367 reply.send({ hello: 'world' })368 })369 370 fastify.listen({ port: 0 }, err => {371 t.error(err)372 t.teardown(() => { fastify.close() })373 374 sget({375 method: 'GET',376 url: 'http://localhost:' + fastify.server.address().port + '/yes'377 }, (err, response, body) => {378 t.error(err)379 t.equal(response.statusCode, 200)380 t.equal(response.headers['content-length'], '' + body.length)381 t.same(JSON.parse(body), { hello: 'world' })382 })383 384 sget({385 method: 'GET',386 url: 'http://localhost:' + fastify.server.address().port + '/no'387 }, (err, response, body) => {388 t.error(err)389 t.equal(response.statusCode, 200)390 t.equal(response.headers['content-length'], '' + body.length)391 t.same(JSON.parse(body), { hello: 'world' })392 })393 })394})395 396test('decorators should be instance separated', t => {397 t.plan(1)398 399 const fastify1 = Fastify()400 const fastify2 = Fastify()401 402 fastify1.decorate('test', 'foo')403 fastify2.decorate('test', 'foo')404 405 fastify1.decorateRequest('test', 'foo')406 fastify2.decorateRequest('test', 'foo')407 408 fastify1.decorateReply('test', 'foo')409 fastify2.decorateReply('test', 'foo')410 411 t.pass()412})413 414test('hasRequestDecorator', t => {415 const requestDecoratorName = 'my-decorator-name'416 417 t.test('is a function', t => {418 t.plan(1)419 const fastify = Fastify()420 t.ok(fastify.hasRequestDecorator)421 })422 423 t.test('should check if the given request decoration already exist', t => {424 t.plan(2)425 const fastify = Fastify()426 427 t.notOk(fastify.hasRequestDecorator(requestDecoratorName))428 fastify.decorateRequest(requestDecoratorName, 42)429 t.ok(fastify.hasRequestDecorator(requestDecoratorName))430 })431 432 t.test('should check if the given request decoration already exist when null', t => {433 t.plan(2)434 const fastify = Fastify()435 436 t.notOk(fastify.hasRequestDecorator(requestDecoratorName))437 fastify.decorateRequest(requestDecoratorName, null)438 t.ok(fastify.hasRequestDecorator(requestDecoratorName))439 })440 441 t.test('should be plugin encapsulable', t => {442 t.plan(4)443 const fastify = Fastify()444 445 t.notOk(fastify.hasRequestDecorator(requestDecoratorName))446 447 fastify.register(function (fastify2, opts, done) {448 fastify2.decorateRequest(requestDecoratorName, 42)449 t.ok(fastify2.hasRequestDecorator(requestDecoratorName))450 done()451 })452 453 t.notOk(fastify.hasRequestDecorator(requestDecoratorName))454 455 fastify.ready(function () {456 t.notOk(fastify.hasRequestDecorator(requestDecoratorName))457 })458 })459 460 t.test('should be inherited', t => {461 t.plan(2)462 const fastify = Fastify()463 464 fastify.decorateRequest(requestDecoratorName, 42)465 466 fastify.register(function (fastify2, opts, done) {467 t.ok(fastify2.hasRequestDecorator(requestDecoratorName))468 done()469 })470 471 fastify.ready(function () {472 t.ok(fastify.hasRequestDecorator(requestDecoratorName))473 })474 })475 476 t.end()477})478 479test('hasReplyDecorator', t => {480 const replyDecoratorName = 'my-decorator-name'481 482 t.test('is a function', t => {483 t.plan(1)484 const fastify = Fastify()485 t.ok(fastify.hasReplyDecorator)486 })487 488 t.test('should check if the given reply decoration already exist', t => {489 t.plan(2)490 const fastify = Fastify()491 492 t.notOk(fastify.hasReplyDecorator(replyDecoratorName))493 fastify.decorateReply(replyDecoratorName, 42)494 t.ok(fastify.hasReplyDecorator(replyDecoratorName))495 })496 497 t.test('should check if the given reply decoration already exist when null', t => {498 t.plan(2)499 const fastify = Fastify()500 501 t.notOk(fastify.hasReplyDecorator(replyDecoratorName))502 fastify.decorateReply(replyDecoratorName, null)503 t.ok(fastify.hasReplyDecorator(replyDecoratorName))504 })505 506 t.test('should be plugin encapsulable', t => {507 t.plan(4)508 const fastify = Fastify()509 510 t.notOk(fastify.hasReplyDecorator(replyDecoratorName))511 512 fastify.register(function (fastify2, opts, done) {513 fastify2.decorateReply(replyDecoratorName, 42)514 t.ok(fastify2.hasReplyDecorator(replyDecoratorName))515 done()516 })517 518 t.notOk(fastify.hasReplyDecorator(replyDecoratorName))519 520 fastify.ready(function () {521 t.notOk(fastify.hasReplyDecorator(replyDecoratorName))522 })523 })524 525 t.test('should be inherited', t => {526 t.plan(2)527 const fastify = Fastify()528 529 fastify.decorateReply(replyDecoratorName, 42)530 531 fastify.register(function (fastify2, opts, done) {532 t.ok(fastify2.hasReplyDecorator(replyDecoratorName))533 done()534 })535 536 fastify.ready(function () {537 t.ok(fastify.hasReplyDecorator(replyDecoratorName))538 })539 })540 541 t.end()542})543 544test('should register properties via getter/setter objects', t => {545 t.plan(3)546 const fastify = Fastify()547 548 fastify.register((instance, opts, done) => {549 instance.decorate('test', {550 getter () {551 return 'a getter'552 }553 })554 t.ok(instance.test)555 t.ok(instance.test, 'a getter')556 done()557 })558 559 fastify.ready(() => {560 t.notOk(fastify.test)561 })562})563 564test('decorateRequest should work with getter/setter', t => {565 t.plan(5)566 const fastify = Fastify()567 568 fastify.register((instance, opts, done) => {569 instance.decorateRequest('test', {570 getter () {571 return 'a getter'572 }573 })574 575 instance.get('/req-decorated-get-set', (req, res) => {576 res.send({ test: req.test })577 })578 579 done()580 })581 582 fastify.get('/not-decorated', (req, res) => {583 t.notOk(req.test)584 res.send()585 })586 587 fastify.ready(() => {588 fastify.inject({ url: '/req-decorated-get-set' }, (err, res) => {589 t.error(err)590 t.same(JSON.parse(res.payload), { test: 'a getter' })591 })592 593 fastify.inject({ url: '/not-decorated' }, (err, res) => {594 t.error(err)595 t.pass()596 })597 })598})599 600test('decorateReply should work with getter/setter', t => {601 t.plan(5)602 const fastify = Fastify()603 604 fastify.register((instance, opts, done) => {605 instance.decorateReply('test', {606 getter () {607 return 'a getter'608 }609 })610 611 instance.get('/res-decorated-get-set', (req, res) => {612 res.send({ test: res.test })613 })614 615 done()616 })617 618 fastify.get('/not-decorated', (req, res) => {619 t.notOk(res.test)620 res.send()621 })622 623 fastify.ready(() => {624 fastify.inject({ url: '/res-decorated-get-set' }, (err, res) => {625 t.error(err)626 t.same(JSON.parse(res.payload), { test: 'a getter' })627 })628 629 fastify.inject({ url: '/not-decorated' }, (err, res) => {630 t.error(err)631 t.pass()632 })633 })634})635 636test('should register empty values', t => {637 t.plan(2)638 const fastify = Fastify()639 640 fastify.register((instance, opts, done) => {641 instance.decorate('test', null)642 t.ok(Object.hasOwn(instance, 'test'))643 done()644 })645 646 fastify.ready(() => {647 t.notOk(fastify.test)648 })649})650 651test('nested plugins can override things', t => {652 t.plan(6)653 const fastify = Fastify()654 655 const rootFunc = () => {}656 fastify.decorate('test', rootFunc)657 fastify.decorateRequest('test', rootFunc)658 fastify.decorateReply('test', rootFunc)659 660 fastify.register((instance, opts, done) => {661 const func = () => {}662 instance.decorate('test', func)663 instance.decorateRequest('test', func)664 instance.decorateReply('test', func)665 666 t.equal(instance.test, func)667 t.equal(instance[symbols.kRequest].prototype.test, func)668 t.equal(instance[symbols.kReply].prototype.test, func)669 done()670 })671 672 fastify.ready(() => {673 t.equal(fastify.test, rootFunc)674 t.equal(fastify[symbols.kRequest].prototype.test, rootFunc)675 t.equal(fastify[symbols.kReply].prototype.test, rootFunc)676 })677})678 679test('a decorator should addSchema to all the encapsulated tree', t => {680 t.plan(1)681 const fastify = Fastify()682 683 const decorator = function (instance, opts, done) {684 instance.decorate('decoratorAddSchema', function (whereAddTheSchema) {685 instance.addSchema({686 $id: 'schema',687 type: 'string'688 })689 })690 done()691 }692 693 fastify.register(fp(decorator))694 695 fastify.register(function (instance, opts, done) {696 instance.register((subInstance, opts, done) => {697 subInstance.decoratorAddSchema()698 done()699 })700 done()701 })702 703 fastify.ready(t.error)704})705 706test('after can access to a decorated instance and previous plugin decoration', t => {707 t.plan(11)708 const TEST_VALUE = {}709 const OTHER_TEST_VALUE = {}710 const NEW_TEST_VALUE = {}711 712 const fastify = Fastify()713 714 fastify.register(fp(function (instance, options, done) {715 instance.decorate('test', TEST_VALUE)716 717 done()718 })).after(function (err, instance, done) {719 t.error(err)720 t.equal(instance.test, TEST_VALUE)721 722 instance.decorate('test2', OTHER_TEST_VALUE)723 done()724 })725 726 fastify.register(fp(function (instance, options, done) {727 t.equal(instance.test, TEST_VALUE)728 t.equal(instance.test2, OTHER_TEST_VALUE)729 730 instance.decorate('test3', NEW_TEST_VALUE)731 732 done()733 })).after(function (err, instance, done) {734 t.error(err)735 t.equal(instance.test, TEST_VALUE)736 t.equal(instance.test2, OTHER_TEST_VALUE)737 t.equal(instance.test3, NEW_TEST_VALUE)738 739 done()740 })741 742 fastify.get('/', function (req, res) {743 t.equal(this.test, TEST_VALUE)744 t.equal(this.test2, OTHER_TEST_VALUE)745 res.send({})746 })747 748 fastify.inject('/')749 .then(response => {750 t.equal(response.statusCode, 200)751 })752})753 754test('decorate* should throw if called after ready', async t => {755 t.plan(6)756 const fastify = Fastify()757 758 fastify.get('/', (request, reply) => {759 reply.send({760 hello: 'world'761 })762 })763 764 await fastify.listen({ port: 0 })765 try {766 fastify.decorate('test', true)767 t.fail('should not decorate')768 } catch (err) {769 t.same(err.code, 'FST_ERR_DEC_AFTER_START')770 t.same(err.message, "The decorator 'test' has been added after start!")771 }772 try {773 fastify.decorateRequest('test', true)774 t.fail('should not decorate')775 } catch (e) {776 t.same(e.code, 'FST_ERR_DEC_AFTER_START')777 t.same(e.message, "The decorator 'test' has been added after start!")778 }779 try {780 fastify.decorateReply('test', true)781 t.fail('should not decorate')782 } catch (e) {783 t.same(e.code, 'FST_ERR_DEC_AFTER_START')784 t.same(e.message, "The decorator 'test' has been added after start!")785 }786 await fastify.close()787})788 789test('decorate* should emit error if an array is passed', t => {790 t.plan(2)791 792 const fastify = Fastify()793 try {794 fastify.decorateRequest('test_array', [])795 t.fail('should not decorate')796 } catch (err) {797 t.same(err.code, 'FST_ERR_DEC_REFERENCE_TYPE')798 t.same(err.message, "The decorator 'test_array' of type 'object' is a reference type. Use the { getter, setter } interface instead.")799 }800})801 802test('server.decorate should not emit error if reference type is passed', async t => {803 t.plan(1)804 805 const fastify = Fastify()806 fastify.decorate('test_array', [])807 fastify.decorate('test_object', {})808 await fastify.ready()809 t.pass('Done')810})811 812test('decorate* should emit warning if object type is passed', t => {813 t.plan(2)814 815 const fastify = Fastify()816 try {817 fastify.decorateRequest('test_object', { foo: 'bar' })818 t.fail('should not decorate')819 } catch (err) {820 t.same(err.code, 'FST_ERR_DEC_REFERENCE_TYPE')821 t.same(err.message, "The decorator 'test_object' of type 'object' is a reference type. Use the { getter, setter } interface instead.")822 }823})824 825test('decorate* should not emit warning if object with getter/setter is passed', t => {826 const fastify = Fastify()827 828 fastify.decorateRequest('test_getter_setter', {829 setter (val) {830 this._ = val831 },832 getter () {833 return 'a getter'834 }835 })836 t.end('Done')837})838 839test('decorateRequest with getter/setter can handle encapsulation', async t => {840 t.plan(24)841 842 const fastify = Fastify({ logger: true })843 844 fastify.decorateRequest('test_getter_setter_holder')845 fastify.decorateRequest('test_getter_setter', {846 getter () {847 this.test_getter_setter_holder ??= {}848 return this.test_getter_setter_holder849 }850 })851 852 fastify.get('/', async function (req, reply) {853 t.same(req.test_getter_setter, {}, 'a getter')854 req.test_getter_setter.a = req.id855 t.same(req.test_getter_setter, { a: req.id })856 })857 858 fastify.addHook('onResponse', async function hook (req, reply) {859 t.same(req.test_getter_setter, { a: req.id })860 })861 862 await Promise.all([863 fastify.inject('/').then(res => t.same(res.statusCode, 200)),864 fastify.inject('/').then(res => t.same(res.statusCode, 200)),865 fastify.inject('/').then(res => t.same(res.statusCode, 200)),866 fastify.inject('/').then(res => t.same(res.statusCode, 200)),867 fastify.inject('/').then(res => t.same(res.statusCode, 200)),868 fastify.inject('/').then(res => t.same(res.statusCode, 200))869 ])870})871 872test('decorateRequest with getter/setter can handle encapsulation with arrays', async t => {873 t.plan(24)874 875 const fastify = Fastify({ logger: true })876 877 fastify.decorateRequest('array_holder')878 fastify.decorateRequest('my_array', {879 getter () {880 this.array_holder ??= []881 return this.array_holder882 }883 })884 885 fastify.get('/', async function (req, reply) {886 t.same(req.my_array, [])887 req.my_array.push(req.id)888 t.same(req.my_array, [req.id])889 })890 891 fastify.addHook('onResponse', async function hook (req, reply) {892 t.same(req.my_array, [req.id])893 })894 895 await Promise.all([896 fastify.inject('/').then(res => t.same(res.statusCode, 200)),897 fastify.inject('/').then(res => t.same(res.statusCode, 200)),898 fastify.inject('/').then(res => t.same(res.statusCode, 200)),899 fastify.inject('/').then(res => t.same(res.statusCode, 200)),900 fastify.inject('/').then(res => t.same(res.statusCode, 200)),901 fastify.inject('/').then(res => t.same(res.statusCode, 200))902 ])903})904 905test('decorate* should not emit error if string,bool,numbers are passed', t => {906 const fastify = Fastify()907 908 fastify.decorateRequest('test_str', 'foo')909 fastify.decorateRequest('test_bool', true)910 fastify.decorateRequest('test_number', 42)911 fastify.decorateRequest('test_null', null)912 fastify.decorateRequest('test_undefined', undefined)913 fastify.decorateReply('test_str', 'foo')914 fastify.decorateReply('test_bool', true)915 fastify.decorateReply('test_number', 42)916 fastify.decorateReply('test_null', null)917 fastify.decorateReply('test_undefined', undefined)918 t.end('Done')919})920 921test('Request/reply decorators should be able to access the server instance', async t => {922 t.plan(6)923 924 const server = require('..')({ logger: false })925 server.decorateRequest('assert', rootAssert)926 server.decorateReply('assert', rootAssert)927 928 server.get('/root-assert', async (req, rep) => {929 req.assert()930 rep.assert()931 return 'done'932 })933 934 server.register(async instance => {935 instance.decorateRequest('assert', nestedAssert)936 instance.decorateReply('assert', nestedAssert)937 instance.decorate('foo', 'bar')938 939 instance.get('/nested-assert', async (req, rep) => {940 req.assert()941 rep.assert()942 return 'done'943 })944 })945 946 await server.inject({ method: 'GET', url: '/root-assert' })947 await server.inject({ method: 'GET', url: '/nested-assert' })948 949 // ----950 function rootAssert () {951 t.equal(this.server, server)952 }953 954 function nestedAssert () {955 t.not(this.server, server)956 t.equal(this.server.foo, 'bar')957 }958})959 960test('plugin required decorators', async t => {961 const plugin1 = fp(962 async (instance) => {963 instance.decorateRequest('someThing', null)964 965 instance.addHook('onRequest', async (request, reply) => {966 request.someThing = 'hello'967 })968 },969 {970 name: 'custom-plugin-one'971 }972 )973 974 const plugin2 = fp(975 async () => {976 // nothing977 },978 {979 name: 'custom-plugin-two',980 dependencies: ['custom-plugin-one'],981 decorators: {982 request: ['someThing']983 }984 }985 )986 987 const app = Fastify()988 app.register(plugin1)989 app.register(plugin2)990 await app.ready()991})992 993test('decorateRequest/decorateReply empty string', t => {994 t.plan(7)995 const fastify = Fastify()996 997 fastify.decorateRequest('test', '')998 fastify.decorateReply('test2', '')999 fastify.get('/yes', (req, reply) => {1000 t.equal(req.test, '')1001 t.equal(reply.test2, '')1002 reply.send({ hello: 'world' })1003 })1004 t.teardown(fastify.close.bind(fastify))1005 1006 fastify.listen({ port: 0 }, err => {1007 t.error(err)1008 t.teardown(() => { fastify.close() })1009 1010 sget({1011 method: 'GET',1012 url: 'http://localhost:' + fastify.server.address().port + '/yes'1013 }, (err, response, body) => {1014 t.error(err)1015 t.equal(response.statusCode, 200)1016 t.equal(response.headers['content-length'], '' + body.length)1017 t.same(JSON.parse(body), { hello: 'world' })1018 })1019 })1020})1021 1022test('decorateRequest/decorateReply is undefined', t => {1023 t.plan(7)1024 const fastify = Fastify()1025 1026 fastify.decorateRequest('test', undefined)1027 fastify.decorateReply('test2', undefined)1028 fastify.get('/yes', (req, reply) => {1029 t.equal(req.test, undefined)1030 t.equal(reply.test2, undefined)1031 reply.send({ hello: 'world' })1032 })1033 t.teardown(fastify.close.bind(fastify))1034 1035 fastify.listen({ port: 0 }, err => {1036 t.error(err)1037 t.teardown(() => { fastify.close() })1038 1039 sget({1040 method: 'GET',1041 url: 'http://localhost:' + fastify.server.address().port + '/yes'1042 }, (err, response, body) => {1043 t.error(err)1044 t.equal(response.statusCode, 200)1045 t.equal(response.headers['content-length'], '' + body.length)1046 t.same(JSON.parse(body), { hello: 'world' })1047 })1048 })1049})1050 1051test('decorateRequest/decorateReply is not set to a value', t => {1052 t.plan(7)1053 const fastify = Fastify()1054 1055 fastify.decorateRequest('test')1056 fastify.decorateReply('test2')1057 fastify.get('/yes', (req, reply) => {1058 t.equal(req.test, undefined)1059 t.equal(reply.test2, undefined)1060 reply.send({ hello: 'world' })1061 })1062 t.teardown(fastify.close.bind(fastify))1063 1064 fastify.listen({ port: 0 }, err => {1065 t.error(err)1066 t.teardown(() => { fastify.close() })1067 1068 sget({1069 method: 'GET',1070 url: 'http://localhost:' + fastify.server.address().port + '/yes'1071 }, (err, response, body) => {1072 t.error(err)1073 t.equal(response.statusCode, 200)1074 t.equal(response.headers['content-length'], '' + body.length)1075 t.same(JSON.parse(body), { hello: 'world' })1076 })1077 })1078})1079 1080test('decorateRequest with dependencies', (t) => {1081 t.plan(2)1082 const app = Fastify()1083 1084 const decorator1 = 'bar'1085 const decorator2 = 'foo'1086 1087 app.decorate('decorator1', decorator1)1088 app.decorateRequest('decorator1', decorator1)1089 1090 if (1091 app.hasDecorator('decorator1') &&1092 app.hasRequestDecorator('decorator1')1093 ) {1094 t.doesNotThrow(() => app.decorateRequest('decorator2', decorator2, ['decorator1']))1095 t.ok(app.hasRequestDecorator('decorator2'))1096 }1097})1098 1099test('decorateRequest with dependencies (functions)', (t) => {1100 t.plan(2)1101 const app = Fastify()1102 1103 const decorator1 = () => 'bar'1104 const decorator2 = () => 'foo'1105 1106 app.decorate('decorator1', decorator1)1107 app.decorateRequest('decorator1', decorator1)1108 1109 if (1110 app.hasDecorator('decorator1') &&1111 app.hasRequestDecorator('decorator1')1112 ) {1113 t.doesNotThrow(() => app.decorateRequest('decorator2', decorator2, ['decorator1']))1114 t.ok(app.hasRequestDecorator('decorator2'))1115 }1116})1117 1118test('chain of decorators on Request', async (t) => {1119 const fastify = Fastify()1120 fastify.register(fp(async function (fastify) {1121 fastify.decorateRequest('foo', 'toto')1122 fastify.decorateRequest('bar', () => 'tata')1123 }, {1124 name: 'first'1125 }))1126 1127 fastify.get('/foo', async function (request, reply) {1128 return request.foo1129 })1130 fastify.get('/bar', function (request, reply) {1131 return request.bar()1132 })1133 fastify.register(async function second (fastify) {1134 fastify.get('/foo', async function (request, reply) {1135 return request.foo1136 })1137 fastify.get('/bar', async function (request, reply) {1138 return request.bar()1139 })1140 fastify.register(async function fourth (fastify) {1141 fastify.get('/plugin3/foo', async function (request, reply) {1142 return request.foo1143 })1144 fastify.get('/plugin3/bar', function (request, reply) {1145 return request.bar()1146 })1147 })1148 fastify.register(fp(async function (fastify) {1149 fastify.decorateRequest('fooB', 'toto')1150 fastify.decorateRequest('barB', () => 'tata')1151 }, {1152 name: 'third'1153 }))1154 },1155 { prefix: '/plugin2', name: 'plugin2' }1156 )1157 1158 await fastify.ready()1159 1160 {1161 const response = await fastify.inject('/foo')1162 t.equal(response.body, 'toto')1163 }1164 1165 {1166 const response = await fastify.inject('/bar')1167 t.equal(response.body, 'tata')1168 }1169 1170 {1171 const response = await fastify.inject('/plugin2/foo')1172 t.equal(response.body, 'toto')1173 }1174 1175 {1176 const response = await fastify.inject('/plugin2/bar')1177 t.equal(response.body, 'tata')1178 }1179 1180 {1181 const response = await fastify.inject('/plugin2/plugin3/foo')1182 t.equal(response.body, 'toto')1183 }1184 1185 {1186 const response = await fastify.inject('/plugin2/plugin3/bar')1187 t.equal(response.body, 'tata')1188 }1189})1190 1191test('chain of decorators on Reply', async (t) => {1192 const fastify = Fastify()1193 fastify.register(fp(async function (fastify) {1194 fastify.decorateReply('foo', 'toto')1195 fastify.decorateReply('bar', () => 'tata')1196 }, {1197 name: 'first'1198 }))1199 1200 fastify.get('/foo', async function (request, reply) {