You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					1005 lines
				
				22 KiB
			
		
		
			
		
	
	
					1005 lines
				
				22 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | /* eslint no-prototype-builtins: 0 */ | ||
|  | 
 | ||
|  | const t = require('tap') | ||
|  | const test = t.test | ||
|  | const Fastify = require('..') | ||
|  | const sget = require('simple-get').concat | ||
|  | const fp = require('fastify-plugin') | ||
|  | const fakeTimer = require('@sinonjs/fake-timers') | ||
|  | 
 | ||
|  | test('require a plugin', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(require('./plugin.helper')) | ||
|  |   fastify.ready(() => { | ||
|  |     t.ok(fastify.test) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - ignore prefix', t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   fastify.register(plugin, { prefix: 'foo' }) | ||
|  | 
 | ||
|  |   fastify.inject({ | ||
|  |     method: 'GET', | ||
|  |     url: '/' | ||
|  |   }, function (err, res) { | ||
|  |     t.error(err) | ||
|  |     t.equal(res.payload, 'hello') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     instance.get('/', function (request, reply) { | ||
|  |       reply.send('hello') | ||
|  |     }) | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - naming plugins', async t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register(require('./plugin.name.display')) | ||
|  |   fastify.register(function (fastify, opts, done) { | ||
|  |     // one line
 | ||
|  |     t.equal(fastify.pluginName, 'function (fastify, opts, done) { -- // one line') | ||
|  |     done() | ||
|  |   }) | ||
|  |   fastify.register(function fooBar (fastify, opts, done) { | ||
|  |     t.equal(fastify.pluginName, 'fooBar') | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   await fastify.ready() | ||
|  | }) | ||
|  | 
 | ||
|  | test('fastify.register with fastify-plugin should not encapsulate his code', t => { | ||
|  |   t.plan(10) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       i.decorate('test', () => {}) | ||
|  |       t.ok(i.test) | ||
|  |       n() | ||
|  |     })) | ||
|  | 
 | ||
|  |     t.notOk(instance.test) | ||
|  | 
 | ||
|  |     // the decoration is added at the end
 | ||
|  |     instance.after(() => { | ||
|  |       t.ok(instance.test) | ||
|  |     }) | ||
|  | 
 | ||
|  |     instance.get('/', (req, reply) => { | ||
|  |       t.ok(instance.test) | ||
|  |       reply.send({ hello: 'world' }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.notOk(fastify.test) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('fastify.register with fastify-plugin should provide access to external fastify instance if opts argument is a function', t => { | ||
|  |   t.plan(22) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       i.decorate('global', () => {}) | ||
|  |       t.ok(i.global) | ||
|  |       n() | ||
|  |     })) | ||
|  | 
 | ||
|  |     instance.register((i, o, n) => n(), p => { | ||
|  |       t.notOk(p === instance || p === fastify) | ||
|  |       t.ok(instance.isPrototypeOf(p)) | ||
|  |       t.ok(fastify.isPrototypeOf(p)) | ||
|  |       t.ok(p.global) | ||
|  |     }) | ||
|  | 
 | ||
|  |     instance.register((i, o, n) => { | ||
|  |       i.decorate('local', () => {}) | ||
|  |       n() | ||
|  |     }) | ||
|  | 
 | ||
|  |     instance.register((i, o, n) => n(), p => t.notOk(p.local)) | ||
|  | 
 | ||
|  |     instance.register((i, o, n) => { | ||
|  |       t.ok(i.local) | ||
|  |       n() | ||
|  |     }, p => p.decorate('local', () => {})) | ||
|  | 
 | ||
|  |     instance.register((i, o, n) => n(), p => t.notOk(p.local)) | ||
|  | 
 | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       t.ok(i.global_2) | ||
|  |       n() | ||
|  |     }), p => p.decorate('global_2', () => 'hello')) | ||
|  | 
 | ||
|  |     instance.register((i, o, n) => { | ||
|  |       i.decorate('global_2', () => 'world') | ||
|  |       n() | ||
|  |     }, p => p.get('/', (req, reply) => { | ||
|  |       t.ok(p.global_2) | ||
|  |       reply.send({ hello: p.global_2() }) | ||
|  |     })) | ||
|  | 
 | ||
|  |     t.notOk(instance.global) | ||
|  |     t.notOk(instance.global_2) | ||
|  |     t.notOk(instance.local) | ||
|  | 
 | ||
|  |     // the decoration is added at the end
 | ||
|  |     instance.after(() => { | ||
|  |       t.ok(instance.global) | ||
|  |       t.equal(instance.global_2(), 'hello') | ||
|  |       t.notOk(instance.local) | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.notOk(fastify.global) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('fastify.register with fastify-plugin registers root level plugins', t => { | ||
|  |   t.plan(15) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   function rootPlugin (instance, opts, done) { | ||
|  |     instance.decorate('test', 'first') | ||
|  |     t.ok(instance.test) | ||
|  |     done() | ||
|  |   } | ||
|  | 
 | ||
|  |   function innerPlugin (instance, opts, done) { | ||
|  |     instance.decorate('test2', 'second') | ||
|  |     done() | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(fp(rootPlugin)) | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     t.ok(instance.test) | ||
|  |     instance.register(fp(innerPlugin)) | ||
|  | 
 | ||
|  |     instance.get('/test2', (req, reply) => { | ||
|  |       t.ok(instance.test2) | ||
|  |       reply.send({ test2: instance.test2 }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.ok(fastify.test) | ||
|  |     t.notOk(fastify.test2) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/', (req, reply) => { | ||
|  |     t.ok(fastify.test) | ||
|  |     reply.send({ test: fastify.test }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { test: 'first' }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/test2' | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { test2: 'second' }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('check dependencies - should not throw', t => { | ||
|  |   t.plan(12) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       i.decorate('test', () => {}) | ||
|  |       t.ok(i.test) | ||
|  |       n() | ||
|  |     })) | ||
|  | 
 | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       try { | ||
|  |         i.decorate('otherTest', () => {}, ['test']) | ||
|  |         t.ok(i.test) | ||
|  |         t.ok(i.otherTest) | ||
|  |         n() | ||
|  |       } catch (e) { | ||
|  |         t.fail() | ||
|  |       } | ||
|  |     })) | ||
|  | 
 | ||
|  |     instance.get('/', (req, reply) => { | ||
|  |       t.ok(instance.test) | ||
|  |       t.ok(instance.otherTest) | ||
|  |       reply.send({ hello: 'world' }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.notOk(fastify.test) | ||
|  |     t.notOk(fastify.otherTest) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('check dependencies - should throw', t => { | ||
|  |   t.plan(12) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       try { | ||
|  |         i.decorate('otherTest', () => {}, ['test']) | ||
|  |         t.fail() | ||
|  |       } catch (e) { | ||
|  |         t.equal(e.code, 'FST_ERR_DEC_MISSING_DEPENDENCY') | ||
|  |         t.equal(e.message, 'The decorator is missing dependency \'test\'.') | ||
|  |       } | ||
|  |       n() | ||
|  |     })) | ||
|  | 
 | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       i.decorate('test', () => {}) | ||
|  |       t.ok(i.test) | ||
|  |       t.notOk(i.otherTest) | ||
|  |       n() | ||
|  |     })) | ||
|  | 
 | ||
|  |     instance.get('/', (req, reply) => { | ||
|  |       t.ok(instance.test) | ||
|  |       t.notOk(instance.otherTest) | ||
|  |       reply.send({ hello: 'world' }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.notOk(fastify.test) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('set the plugin name based on the plugin displayName symbol', t => { | ||
|  |   t.plan(5) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register(fp((fastify, opts, done) => { | ||
|  |     t.equal(fastify.pluginName, 'plugin-A') | ||
|  |     fastify.register(fp((fastify, opts, done) => { | ||
|  |       t.equal(fastify.pluginName, 'plugin-A -> plugin-AB') | ||
|  |       done() | ||
|  |     }, { name: 'plugin-AB' })) | ||
|  |     fastify.register(fp((fastify, opts, done) => { | ||
|  |       t.equal(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC') | ||
|  |       done() | ||
|  |     }, { name: 'plugin-AC' })) | ||
|  |     done() | ||
|  |   }, { name: 'plugin-A' })) | ||
|  | 
 | ||
|  |   fastify.register(fp((fastify, opts, done) => { | ||
|  |     t.equal(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC -> plugin-B') | ||
|  |     done() | ||
|  |   }, { name: 'plugin-B' })) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.close() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin name will change when using no encapsulation', t => { | ||
|  |   t.plan(5) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register(fp((fastify, opts, done) => { | ||
|  |     // store it in a different variable will hold the correct name
 | ||
|  |     const pluginName = fastify.pluginName | ||
|  |     fastify.register(fp((fastify, opts, done) => { | ||
|  |       t.equal(fastify.pluginName, 'plugin-A -> plugin-AB') | ||
|  |       done() | ||
|  |     }, { name: 'plugin-AB' })) | ||
|  |     fastify.register(fp((fastify, opts, done) => { | ||
|  |       t.equal(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC') | ||
|  |       done() | ||
|  |     }, { name: 'plugin-AC' })) | ||
|  |     setImmediate(() => { | ||
|  |       // normally we would expect the name plugin-A
 | ||
|  |       // but we operate on the same instance in each plugin
 | ||
|  |       t.equal(fastify.pluginName, 'plugin-A -> plugin-AB -> plugin-AC') | ||
|  |       t.equal(pluginName, 'plugin-A') | ||
|  |     }) | ||
|  |     done() | ||
|  |   }, { name: 'plugin-A' })) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.close() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin name is undefined when accessing in no plugin context', t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   t.equal(fastify.pluginName, undefined) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.close() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('set the plugin name based on the plugin function name', t => { | ||
|  |   t.plan(5) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register(function myPluginA (fastify, opts, done) { | ||
|  |     t.equal(fastify.pluginName, 'myPluginA') | ||
|  |     fastify.register(function myPluginAB (fastify, opts, done) { | ||
|  |       t.equal(fastify.pluginName, 'myPluginAB') | ||
|  |       done() | ||
|  |     }) | ||
|  |     setImmediate(() => { | ||
|  |       // exact name due to encapsulation
 | ||
|  |       t.equal(fastify.pluginName, 'myPluginA') | ||
|  |     }) | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(function myPluginB (fastify, opts, done) { | ||
|  |     t.equal(fastify.pluginName, 'myPluginB') | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.close() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('approximate a plugin name when no meta data is available', t => { | ||
|  |   t.plan(7) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register((fastify, opts, done) => { | ||
|  |     // A
 | ||
|  |     t.equal(fastify.pluginName.startsWith('(fastify, opts, done)'), true) | ||
|  |     t.equal(fastify.pluginName.includes('// A'), true) | ||
|  |     fastify.register((fastify, opts, done) => { | ||
|  |       // B
 | ||
|  |       t.equal(fastify.pluginName.startsWith('(fastify, opts, done)'), true) | ||
|  |       t.equal(fastify.pluginName.includes('// B'), true) | ||
|  |       done() | ||
|  |     }) | ||
|  |     setImmediate(() => { | ||
|  |       t.equal(fastify.pluginName.startsWith('(fastify, opts, done)'), true) | ||
|  |       t.equal(fastify.pluginName.includes('// A'), true) | ||
|  |     }) | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.close() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('approximate a plugin name also when fastify-plugin has no meta data', t => { | ||
|  |   t.plan(4) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register(fp((fastify, opts, done) => { | ||
|  |     t.match(fastify.pluginName, /plugin\.test/) | ||
|  |     fastify.register(fp(function B (fastify, opts, done) { | ||
|  |       // function has name
 | ||
|  |       t.match(fastify.pluginName, /plugin\.test-auto-\d+ -> B/) | ||
|  |       done() | ||
|  |     })) | ||
|  |     setImmediate(() => { | ||
|  |       t.match(fastify.pluginName, /plugin\.test-auto-\d+ -> B/) | ||
|  |     }) | ||
|  |     done() | ||
|  |   })) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.close() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin encapsulation', t => { | ||
|  |   t.plan(10) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       i.decorate('test', 'first') | ||
|  |       n() | ||
|  |     })) | ||
|  | 
 | ||
|  |     instance.get('/first', (req, reply) => { | ||
|  |       reply.send({ plugin: instance.test }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     instance.register(fp((i, o, n) => { | ||
|  |       i.decorate('test', 'second') | ||
|  |       n() | ||
|  |     })) | ||
|  | 
 | ||
|  |     instance.get('/second', (req, reply) => { | ||
|  |       reply.send({ plugin: instance.test }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.notOk(fastify.test) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/first' | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { plugin: 'first' }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/second' | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['content-length'], '' + body.length) | ||
|  |       t.same(JSON.parse(body), { plugin: 'second' }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('if a plugin raises an error and there is not a callback to handle it, the server must not start', t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register((instance, opts, done) => { | ||
|  |     done(new Error('err')) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.ok(err instanceof Error) | ||
|  |     t.equal(err.message, 'err') | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('add hooks after route declaration', t => { | ||
|  |   t.plan(3) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     instance.decorateRequest('check', null) | ||
|  |     instance.addHook('onRequest', (req, reply, done) => { | ||
|  |       req.check = {} | ||
|  |       done() | ||
|  |     }) | ||
|  |     setImmediate(done) | ||
|  |   } | ||
|  |   fastify.register(fp(plugin)) | ||
|  | 
 | ||
|  |   fastify.register((instance, options, done) => { | ||
|  |     instance.addHook('preHandler', function b (req, res, done) { | ||
|  |       req.check.hook2 = true | ||
|  |       done() | ||
|  |     }) | ||
|  | 
 | ||
|  |     instance.get('/', (req, reply) => { | ||
|  |       reply.send(req.check) | ||
|  |     }) | ||
|  | 
 | ||
|  |     instance.addHook('preHandler', function c (req, res, done) { | ||
|  |       req.check.hook3 = true | ||
|  |       done() | ||
|  |     }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.addHook('preHandler', function a (req, res, done) { | ||
|  |     req.check.hook1 = true | ||
|  |     done() | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.same(JSON.parse(body), { hook1: true, hook2: true, hook3: true }) | ||
|  |       fastify.close() | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('nested plugins', t => { | ||
|  |   t.plan(5) | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.register(function (fastify, opts, done) { | ||
|  |     fastify.register((fastify, opts, done) => { | ||
|  |       fastify.get('/', function (req, reply) { | ||
|  |         reply.send('I am child 1') | ||
|  |       }) | ||
|  |       done() | ||
|  |     }, { prefix: '/child1' }) | ||
|  | 
 | ||
|  |     fastify.register((fastify, opts, done) => { | ||
|  |       fastify.get('/', function (req, reply) { | ||
|  |         reply.send('I am child 2') | ||
|  |       }) | ||
|  |       done() | ||
|  |     }, { prefix: '/child2' }) | ||
|  | 
 | ||
|  |     done() | ||
|  |   }, { prefix: '/parent' }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/parent/child1' | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.same(body.toString(), 'I am child 1') | ||
|  |     }) | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/parent/child2' | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.same(body.toString(), 'I am child 2') | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('nested plugins awaited', t => { | ||
|  |   t.plan(5) | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.register(async function wrap (fastify, opts) { | ||
|  |     await fastify.register(async function child1 (fastify, opts) { | ||
|  |       fastify.get('/', function (req, reply) { | ||
|  |         reply.send('I am child 1') | ||
|  |       }) | ||
|  |     }, { prefix: '/child1' }) | ||
|  | 
 | ||
|  |     await fastify.register(async function child2 (fastify, opts) { | ||
|  |       fastify.get('/', function (req, reply) { | ||
|  |         reply.send('I am child 2') | ||
|  |       }) | ||
|  |     }, { prefix: '/child2' }) | ||
|  |   }, { prefix: '/parent' }) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/parent/child1' | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.same(body.toString(), 'I am child 1') | ||
|  |     }) | ||
|  | 
 | ||
|  |     sget({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/parent/child2' | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.same(body.toString(), 'I am child 2') | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - decorators', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.decorate('plugin1', true) | ||
|  |   fastify.decorateReply('plugin1', true) | ||
|  |   fastify.decorateRequest('plugin1', true) | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     decorators: { | ||
|  |       fastify: ['plugin1'], | ||
|  |       reply: ['plugin1'], | ||
|  |       request: ['plugin1'] | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.ok(fastify.plugin) | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     instance.decorate('plugin', true) | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - decorators - should throw', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.decorate('plugin1', true) | ||
|  |   fastify.decorateReply('plugin1', true) | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     decorators: { | ||
|  |       fastify: ['plugin1'], | ||
|  |       reply: ['plugin1'], | ||
|  |       request: ['plugin1'] | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  |   fastify.ready((err) => { | ||
|  |     t.equal(err.message, "The decorator 'plugin1' is not present in Request") | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     instance.decorate('plugin', true) | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - decorators - should throw with plugin name', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.decorate('plugin1', true) | ||
|  |   fastify.decorateReply('plugin1', true) | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'the-plugin', | ||
|  |     decorators: { | ||
|  |       fastify: ['plugin1'], | ||
|  |       reply: ['plugin1'], | ||
|  |       request: ['plugin1'] | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  |   fastify.ready((err) => { | ||
|  |     t.equal(err.message, "The decorator 'plugin1' required by 'the-plugin' is not present in Request") | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     instance.decorate('plugin', true) | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - dependencies', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   dependency[Symbol.for('skip-override')] = true | ||
|  |   dependency[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'plugin' | ||
|  |   } | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     dependencies: ['plugin'] | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(dependency) | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.pass('everything right') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function dependency (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - dependencies (nested)', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   dependency[Symbol.for('skip-override')] = true | ||
|  |   dependency[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'plugin' | ||
|  |   } | ||
|  | 
 | ||
|  |   nested[Symbol.for('skip-override')] = true | ||
|  |   nested[Symbol.for('plugin-meta')] = { | ||
|  |     dependencies: ['plugin'] | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(dependency) | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.pass('everything right') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function dependency (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     instance.register(nested) | ||
|  |     done() | ||
|  |   } | ||
|  | 
 | ||
|  |   function nested (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('pluginTimeout', t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify({ | ||
|  |     pluginTimeout: 10 | ||
|  |   }) | ||
|  |   fastify.register(function (app, opts, done) { | ||
|  |     // to no call done on purpose
 | ||
|  |   }) | ||
|  |   fastify.ready((err) => { | ||
|  |     t.ok(err) | ||
|  |     t.equal(err.code, 'ERR_AVVIO_PLUGIN_TIMEOUT') | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | test('pluginTimeout default', t => { | ||
|  |   t.plan(2) | ||
|  |   const clock = fakeTimer.install() | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(function (app, opts, done) { | ||
|  |     // default time elapsed without calling done
 | ||
|  |     clock.tick(10000) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready((err) => { | ||
|  |     t.ok(err) | ||
|  |     t.equal(err.code, 'ERR_AVVIO_PLUGIN_TIMEOUT') | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(clock.uninstall) | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - version', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'plugin', | ||
|  |     fastify: '2.0.0' | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.pass('everything right') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - version range', t => { | ||
|  |   t.plan(1) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'plugin', | ||
|  |     fastify: '>=2.0.0' | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready(() => { | ||
|  |     t.pass('everything right') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - version not matching requirement', t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'plugin', | ||
|  |     fastify: '99.0.0' | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready((err) => { | ||
|  |     t.ok(err) | ||
|  |     t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - version not matching requirement 2', t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'plugin', | ||
|  |     fastify: '<=3.0.0' | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready((err) => { | ||
|  |     t.ok(err) | ||
|  |     t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('plugin metadata - version not matching requirement 3', t => { | ||
|  |   t.plan(2) | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   plugin[Symbol.for('skip-override')] = true | ||
|  |   plugin[Symbol.for('plugin-meta')] = { | ||
|  |     name: 'plugin', | ||
|  |     fastify: '>=99.0.0' | ||
|  |   } | ||
|  | 
 | ||
|  |   fastify.register(plugin) | ||
|  | 
 | ||
|  |   fastify.ready((err) => { | ||
|  |     t.ok(err) | ||
|  |     t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH') | ||
|  |   }) | ||
|  | 
 | ||
|  |   function plugin (instance, opts, done) { | ||
|  |     done() | ||
|  |   } | ||
|  | }) |