strong-tie/inbound-calls
0
1'use strict'2 3const t = require('tap')4const test = t.test5const Fastify = require('../fastify')6const fp = require('fastify-plugin')7const fakeTimer = require('@sinonjs/fake-timers')8const { FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER } = require('../lib/errors')9 10test('pluginTimeout', t => {11 t.plan(5)12 const fastify = Fastify({13 pluginTimeout: 1014 })15 fastify.register(function (app, opts, done) {16 // to no call done on purpose17 })18 fastify.ready((err) => {19 t.ok(err)20 t.equal(err.message,21 "fastify-plugin: Plugin did not start in time: 'function (app, opts, done) { -- // to no call done on purpose'. You may have forgotten to call 'done' function or to resolve a Promise")22 t.equal(err.code, 'FST_ERR_PLUGIN_TIMEOUT')23 t.ok(err.cause)24 t.equal(err.cause.code, 'AVV_ERR_PLUGIN_EXEC_TIMEOUT')25 })26})27 28test('pluginTimeout - named function', t => {29 t.plan(5)30 const fastify = Fastify({31 pluginTimeout: 1032 })33 fastify.register(function nameFunction (app, opts, done) {34 // to no call done on purpose35 })36 fastify.ready((err) => {37 t.ok(err)38 t.equal(err.message,39 "fastify-plugin: Plugin did not start in time: 'nameFunction'. You may have forgotten to call 'done' function or to resolve a Promise")40 t.equal(err.code, 'FST_ERR_PLUGIN_TIMEOUT')41 t.ok(err.cause)42 t.equal(err.cause.code, 'AVV_ERR_PLUGIN_EXEC_TIMEOUT')43 })44})45 46test('pluginTimeout default', t => {47 t.plan(5)48 const clock = fakeTimer.install({ shouldClearNativeTimers: true })49 50 const fastify = Fastify()51 fastify.register(function (app, opts, done) {52 // default time elapsed without calling done53 clock.tick(10000)54 })55 56 fastify.ready((err) => {57 t.ok(err)58 t.equal(err.message,59 "fastify-plugin: Plugin did not start in time: 'function (app, opts, done) { -- // default time elapsed without calling done'. You may have forgotten to call 'done' function or to resolve a Promise")60 t.equal(err.code, 'FST_ERR_PLUGIN_TIMEOUT')61 t.ok(err.cause)62 t.equal(err.cause.code, 'AVV_ERR_PLUGIN_EXEC_TIMEOUT')63 })64 65 t.teardown(clock.uninstall)66})67 68test('plugin metadata - version', t => {69 t.plan(1)70 const fastify = Fastify()71 72 plugin[Symbol.for('skip-override')] = true73 plugin[Symbol.for('plugin-meta')] = {74 name: 'plugin',75 fastify: '2.0.0'76 }77 78 fastify.register(plugin)79 80 fastify.ready(() => {81 t.pass('everything right')82 })83 84 function plugin (instance, opts, done) {85 done()86 }87})88 89test('plugin metadata - version range', t => {90 t.plan(1)91 const fastify = Fastify()92 93 plugin[Symbol.for('skip-override')] = true94 plugin[Symbol.for('plugin-meta')] = {95 name: 'plugin',96 fastify: '>=2.0.0'97 }98 99 fastify.register(plugin)100 101 fastify.ready(() => {102 t.pass('everything right')103 })104 105 function plugin (instance, opts, done) {106 done()107 }108})109 110test('plugin metadata - version not matching requirement', t => {111 t.plan(2)112 const fastify = Fastify()113 114 plugin[Symbol.for('skip-override')] = true115 plugin[Symbol.for('plugin-meta')] = {116 name: 'plugin',117 fastify: '99.0.0'118 }119 120 fastify.register(plugin)121 122 fastify.ready((err) => {123 t.ok(err)124 t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH')125 })126 127 function plugin (instance, opts, done) {128 done()129 }130})131 132test('plugin metadata - version not matching requirement 2', t => {133 t.plan(2)134 const fastify = Fastify()135 Object.defineProperty(fastify, 'version', {136 value: '99.0.0'137 })138 139 plugin[Symbol.for('skip-override')] = true140 plugin[Symbol.for('plugin-meta')] = {141 name: 'plugin',142 fastify: '<=3.0.0'143 }144 145 fastify.register(plugin)146 147 fastify.ready((err) => {148 t.ok(err)149 t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH')150 })151 152 function plugin (instance, opts, done) {153 done()154 }155})156 157test('plugin metadata - version not matching requirement 3', t => {158 t.plan(2)159 const fastify = Fastify()160 161 plugin[Symbol.for('skip-override')] = true162 plugin[Symbol.for('plugin-meta')] = {163 name: 'plugin',164 fastify: '>=99.0.0'165 }166 167 fastify.register(plugin)168 169 fastify.ready((err) => {170 t.ok(err)171 t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH')172 })173 174 function plugin (instance, opts, done) {175 done()176 }177})178 179test('plugin metadata - release candidate', t => {180 t.plan(2)181 const fastify = Fastify()182 Object.defineProperty(fastify, 'version', {183 value: '99.0.0-rc.1'184 })185 186 plugin[Symbol.for('plugin-meta')] = {187 name: 'plugin',188 fastify: '99.x'189 }190 191 fastify.register(plugin)192 193 fastify.ready((err) => {194 t.error(err)195 t.pass('everything right')196 })197 198 function plugin (instance, opts, done) {199 done()200 }201})202 203test('fastify-rc loads prior version plugins', async t => {204 t.test('baseline (rc)', t => {205 t.plan(2)206 207 const fastify = Fastify()208 Object.defineProperty(fastify, 'version', {209 value: '99.0.0-rc.1'210 })211 212 plugin[Symbol.for('plugin-meta')] = {213 name: 'plugin',214 fastify: '^98.1.0'215 }216 plugin2[Symbol.for('plugin-meta')] = {217 name: 'plugin2',218 fastify: '98.x'219 }220 221 fastify.register(plugin)222 223 fastify.ready((err) => {224 t.error(err)225 t.pass('everything right')226 })227 228 function plugin (instance, opts, done) {229 done()230 }231 232 function plugin2 (instance, opts, done) {233 done()234 }235 })236 237 t.test('pre', t => {238 t.plan(2)239 240 const fastify = Fastify()241 Object.defineProperty(fastify, 'version', { value: '99.0.0-pre.1' })242 243 plugin[Symbol.for('plugin-meta')] = { name: 'plugin', fastify: '^98.x' }244 245 fastify.register(plugin)246 247 fastify.ready((err) => {248 t.error(err)249 t.pass()250 })251 252 function plugin (instance, opts, done) { done() }253 })254 255 t.test('alpha', t => {256 t.plan(2)257 258 const fastify = Fastify()259 Object.defineProperty(fastify, 'version', { value: '99.0.0-pre.1' })260 261 plugin[Symbol.for('plugin-meta')] = { name: 'plugin', fastify: '^98.x' }262 263 fastify.register(plugin)264 265 fastify.ready((err) => {266 t.error(err)267 t.pass()268 })269 270 function plugin (instance, opts, done) { done() }271 })272})273 274test('hasPlugin method exists as a function', t => {275 t.plan(1)276 277 const fastify = Fastify()278 t.equal(typeof fastify.hasPlugin, 'function')279})280 281test('hasPlugin returns true if the specified plugin has been registered', async t => {282 t.plan(4)283 284 const fastify = Fastify()285 286 function pluginA (fastify, opts, done) {287 t.ok(fastify.hasPlugin('plugin-A'))288 done()289 }290 pluginA[Symbol.for('fastify.display-name')] = 'plugin-A'291 fastify.register(pluginA)292 293 fastify.register(function pluginB (fastify, opts, done) {294 t.ok(fastify.hasPlugin('pluginB'))295 done()296 })297 298 fastify.register(function (fastify, opts, done) {299 // one line300 t.ok(fastify.hasPlugin('function (fastify, opts, done) { -- // one line'))301 done()302 })303 304 await fastify.ready()305 306 t.ok(fastify.hasPlugin('fastify'))307})308 309test('hasPlugin returns false if the specified plugin has not been registered', t => {310 t.plan(1)311 312 const fastify = Fastify()313 t.notOk(fastify.hasPlugin('pluginFoo'))314})315 316test('hasPlugin returns false when using encapsulation', async t => {317 t.plan(25)318 319 const fastify = Fastify()320 321 fastify.register(function pluginA (fastify, opts, done) {322 t.ok(fastify.hasPlugin('pluginA'))323 t.notOk(fastify.hasPlugin('pluginAA'))324 t.notOk(fastify.hasPlugin('pluginAAA'))325 t.notOk(fastify.hasPlugin('pluginAB'))326 t.notOk(fastify.hasPlugin('pluginB'))327 328 fastify.register(function pluginAA (fastify, opts, done) {329 t.notOk(fastify.hasPlugin('pluginA'))330 t.ok(fastify.hasPlugin('pluginAA'))331 t.notOk(fastify.hasPlugin('pluginAAA'))332 t.notOk(fastify.hasPlugin('pluginAB'))333 t.notOk(fastify.hasPlugin('pluginB'))334 335 fastify.register(function pluginAAA (fastify, opts, done) {336 t.notOk(fastify.hasPlugin('pluginA'))337 t.notOk(fastify.hasPlugin('pluginAA'))338 t.ok(fastify.hasPlugin('pluginAAA'))339 t.notOk(fastify.hasPlugin('pluginAB'))340 t.notOk(fastify.hasPlugin('pluginB'))341 342 done()343 })344 345 done()346 })347 348 fastify.register(function pluginAB (fastify, opts, done) {349 t.notOk(fastify.hasPlugin('pluginA'))350 t.notOk(fastify.hasPlugin('pluginAA'))351 t.notOk(fastify.hasPlugin('pluginAAA'))352 t.ok(fastify.hasPlugin('pluginAB'))353 t.notOk(fastify.hasPlugin('pluginB'))354 355 done()356 })357 358 done()359 })360 361 fastify.register(function pluginB (fastify, opts, done) {362 t.notOk(fastify.hasPlugin('pluginA'))363 t.notOk(fastify.hasPlugin('pluginAA'))364 t.notOk(fastify.hasPlugin('pluginAAA'))365 t.notOk(fastify.hasPlugin('pluginAB'))366 t.ok(fastify.hasPlugin('pluginB'))367 368 done()369 })370 371 await fastify.ready()372})373 374test('hasPlugin returns true when using no encapsulation', async t => {375 t.plan(26)376 377 const fastify = Fastify()378 379 fastify.register(fp((fastify, opts, done) => {380 t.equal(fastify.pluginName, 'fastify -> plugin-AA')381 t.ok(fastify.hasPlugin('plugin-AA'))382 t.notOk(fastify.hasPlugin('plugin-A'))383 t.notOk(fastify.hasPlugin('plugin-AAA'))384 t.notOk(fastify.hasPlugin('plugin-AB'))385 t.notOk(fastify.hasPlugin('plugin-B'))386 387 fastify.register(fp((fastify, opts, done) => {388 t.ok(fastify.hasPlugin('plugin-AA'))389 t.ok(fastify.hasPlugin('plugin-A'))390 t.notOk(fastify.hasPlugin('plugin-AAA'))391 t.notOk(fastify.hasPlugin('plugin-AB'))392 t.notOk(fastify.hasPlugin('plugin-B'))393 394 fastify.register(fp((fastify, opts, done) => {395 t.ok(fastify.hasPlugin('plugin-AA'))396 t.ok(fastify.hasPlugin('plugin-A'))397 t.ok(fastify.hasPlugin('plugin-AAA'))398 t.notOk(fastify.hasPlugin('plugin-AB'))399 t.notOk(fastify.hasPlugin('plugin-B'))400 401 done()402 }, { name: 'plugin-AAA' }))403 404 done()405 }, { name: 'plugin-A' }))406 407 fastify.register(fp((fastify, opts, done) => {408 t.ok(fastify.hasPlugin('plugin-AA'))409 t.ok(fastify.hasPlugin('plugin-A'))410 t.ok(fastify.hasPlugin('plugin-AAA'))411 t.ok(fastify.hasPlugin('plugin-AB'))412 t.notOk(fastify.hasPlugin('plugin-B'))413 414 done()415 }, { name: 'plugin-AB' }))416 417 done()418 }, { name: 'plugin-AA' }))419 420 fastify.register(fp((fastify, opts, done) => {421 t.ok(fastify.hasPlugin('plugin-AA'))422 t.ok(fastify.hasPlugin('plugin-A'))423 t.ok(fastify.hasPlugin('plugin-AAA'))424 t.ok(fastify.hasPlugin('plugin-AB'))425 t.ok(fastify.hasPlugin('plugin-B'))426 427 done()428 }, { name: 'plugin-B' }))429 430 await fastify.ready()431})432 433test('hasPlugin returns true when using encapsulation', async t => {434 t.plan(2)435 436 const fastify = Fastify()437 438 const pluginCallback = function (server, options, done) {439 done()440 }441 const pluginName = 'awesome-plugin'442 const plugin = fp(pluginCallback, { name: pluginName })443 444 fastify.register(plugin)445 446 fastify.register(async (server) => {447 t.ok(server.hasPlugin(pluginName))448 })449 450 fastify.register(async function foo (server) {451 server.register(async function bar (server) {452 t.ok(server.hasPlugin(pluginName))453 })454 })455 456 await fastify.ready()457})458 459test('registering anonymous plugin with mixed style should throw', async t => {460 t.plan(2)461 462 const fastify = Fastify()463 464 const anonymousPlugin = async (app, opts, done) => {465 done()466 }467 468 fastify.register(anonymousPlugin)469 470 try {471 await fastify.ready()472 t.fail('should throw')473 } catch (error) {474 t.type(error, FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER)475 t.equal(error.message, 'The anonymousPlugin plugin being registered mixes async and callback styles. Async plugin should not mix async and callback style.')476 }477})478 479test('registering named plugin with mixed style should throw', async t => {480 t.plan(2)481 482 const fastify = Fastify()483 484 const pluginName = 'error-plugin'485 const errorPlugin = async (app, opts, done) => {486 done()487 }488 const namedPlugin = fp(errorPlugin, { name: pluginName })489 490 fastify.register(namedPlugin)491 492 try {493 await fastify.ready()494 t.fail('should throw')495 } catch (error) {496 t.type(error, FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER)497 t.equal(error.message, 'The error-plugin plugin being registered mixes async and callback styles. Async plugin should not mix async and callback style.')498 }499})500 