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.
		
		
		
		
		
			
		
			
				
					424 lines
				
				8.5 KiB
			
		
		
			
		
	
	
					424 lines
				
				8.5 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | const { test } = require('tap') | ||
|  | const boot = require('..') | ||
|  | const { promisify } = require('util') | ||
|  | const sleep = promisify(setTimeout) | ||
|  | const fs = require('fs').promises | ||
|  | const path = require('path') | ||
|  | 
 | ||
|  | test('await after - nested plugins with same tick callbacks', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   let secondLoaded = false | ||
|  | 
 | ||
|  |   app.use(async (app) => { | ||
|  |     t.pass('plugin init') | ||
|  |     app.use(async () => { | ||
|  |       t.pass('plugin2 init') | ||
|  |       await sleep(1) | ||
|  |       secondLoaded = true | ||
|  |     }) | ||
|  |   }) | ||
|  |   await app.after() | ||
|  |   t.pass('reachable') | ||
|  |   t.equal(secondLoaded, true) | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  |   t.pass('reachable') | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after without server', async (t) => { | ||
|  |   const app = boot() | ||
|  | 
 | ||
|  |   let secondLoaded = false | ||
|  | 
 | ||
|  |   app.use(async (app) => { | ||
|  |     t.pass('plugin init') | ||
|  |     app.use(async () => { | ||
|  |       t.pass('plugin2 init') | ||
|  |       await sleep(1) | ||
|  |       secondLoaded = true | ||
|  |     }) | ||
|  |   }) | ||
|  |   await app.after() | ||
|  |   t.pass('reachable') | ||
|  |   t.equal(secondLoaded, true) | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  |   t.pass('reachable') | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - nested plugins with future tick callbacks', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   app.use((f, opts, cb) => { | ||
|  |     t.pass('plugin init') | ||
|  |     app.use((f, opts, cb) => { | ||
|  |       t.pass('plugin2 init') | ||
|  |       setImmediate(cb) | ||
|  |     }) | ||
|  |     setImmediate(cb) | ||
|  |   }) | ||
|  |   await app.after() | ||
|  |   t.pass('reachable') | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  |   t.pass('reachable') | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - nested async function plugins', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(5) | ||
|  | 
 | ||
|  |   app.use(async (f, opts) => { | ||
|  |     t.pass('plugin init') | ||
|  |     await app.use(async (f, opts) => { | ||
|  |       t.pass('plugin2 init') | ||
|  |     }) | ||
|  |     t.pass('reachable') | ||
|  |   }) | ||
|  |   await app.after() | ||
|  |   t.pass('reachable') | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  |   t.pass('reachable') | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - promise resolves to undefined', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   app.use(async (f, opts, cb) => { | ||
|  |     app.use((f, opts, cb) => { | ||
|  |       t.pass('plugin init') | ||
|  |       cb() | ||
|  |     }) | ||
|  |     const instance = await app.after() | ||
|  |     t.equal(instance, undefined) | ||
|  |   }) | ||
|  |   t.pass('reachable') | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  |   t.pass('reachable') | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - promise returning function plugins + promise chaining', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(6) | ||
|  | 
 | ||
|  |   app.use((f, opts) => { | ||
|  |     t.pass('plugin init') | ||
|  |     return app.use((f, opts) => { | ||
|  |       t.pass('plugin2 init') | ||
|  |       return Promise.resolve() | ||
|  |     }).then((f2) => { | ||
|  |       t.equal(f2, f) | ||
|  |       return 'test' | ||
|  |     }).then((val) => { | ||
|  |       t.equal(val, 'test') | ||
|  |     }) | ||
|  |   }) | ||
|  |   await app.after() | ||
|  |   t.pass('reachable') | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  |   t.pass('reachable') | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - error handling, async throw', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const e = new Error('kaboom') | ||
|  | 
 | ||
|  |   app.use(async (f, opts) => { | ||
|  |     throw Error('kaboom') | ||
|  |   }) | ||
|  | 
 | ||
|  |   await t.rejects(app.after(), e) | ||
|  | 
 | ||
|  |   await t.rejects(() => app.ready(), Error('kaboom')) | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - error handling, async throw, nested', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const e = new Error('kaboom') | ||
|  | 
 | ||
|  |   app.use(async (f, opts) => { | ||
|  |     app.use(async (f, opts) => { | ||
|  |       throw e | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   await t.rejects(app.after()) | ||
|  |   await t.rejects(() => app.ready(), e) | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - error handling, same tick cb err', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   app.use((f, opts, cb) => { | ||
|  |     cb(Error('kaboom')) | ||
|  |   }) | ||
|  |   await t.rejects(app.after()) | ||
|  |   await t.rejects(app.ready(), Error('kaboom')) | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - error handling, same tick cb err, nested', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   app.use((f, opts, cb) => { | ||
|  |     app.use((f, opts, cb) => { | ||
|  |       cb(Error('kaboom')) | ||
|  |     }) | ||
|  |     cb() | ||
|  |   }) | ||
|  | 
 | ||
|  |   await t.rejects(app.after()) | ||
|  |   await t.rejects(app.ready(), Error('kaboom')) | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - error handling, future tick cb err', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   app.use((f, opts, cb) => { | ||
|  |     setImmediate(() => { cb(Error('kaboom')) }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   await t.rejects(app.after()) | ||
|  |   await t.rejects(app.ready(), Error('kaboom')) | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after - error handling, future tick cb err, nested', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  | 
 | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   app.use((f, opts, cb) => { | ||
|  |     app.use((f, opts, cb) => { | ||
|  |       setImmediate(() => { cb(Error('kaboom')) }) | ||
|  |     }) | ||
|  |     cb() | ||
|  |   }) | ||
|  |   await t.rejects(app.after(), Error('kaboom')) | ||
|  |   await t.rejects(app.ready(), Error('kaboom')) | ||
|  | }) | ||
|  | 
 | ||
|  | test('await after complex scenario', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app) | ||
|  |   t.plan(16) | ||
|  | 
 | ||
|  |   let firstLoaded = false | ||
|  |   let secondLoaded = false | ||
|  |   let thirdLoaded = false | ||
|  |   let fourthLoaded = false | ||
|  | 
 | ||
|  |   app.use(first) | ||
|  |   await app.after() | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.notOk(secondLoaded, 'second is not loaded') | ||
|  |   t.notOk(thirdLoaded, 'third is not loaded') | ||
|  |   t.notOk(fourthLoaded, 'fourth is not loaded') | ||
|  |   app.use(second) | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.notOk(secondLoaded, 'second is not loaded') | ||
|  |   t.notOk(thirdLoaded, 'third is not loaded') | ||
|  |   t.notOk(fourthLoaded, 'fourth is not loaded') | ||
|  |   app.use(third) | ||
|  |   await app.after() | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.ok(secondLoaded, 'second is loaded') | ||
|  |   t.ok(thirdLoaded, 'third is loaded') | ||
|  |   t.ok(fourthLoaded, 'fourth is loaded') | ||
|  |   await app.ready() | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.ok(secondLoaded, 'second is loaded') | ||
|  |   t.ok(thirdLoaded, 'third is loaded') | ||
|  |   t.ok(fourthLoaded, 'fourth is loaded') | ||
|  | 
 | ||
|  |   async function first () { | ||
|  |     firstLoaded = true | ||
|  |   } | ||
|  | 
 | ||
|  |   async function second () { | ||
|  |     secondLoaded = true | ||
|  |   } | ||
|  | 
 | ||
|  |   async function third (app) { | ||
|  |     thirdLoaded = true | ||
|  |     app.use(fourth) | ||
|  |   } | ||
|  | 
 | ||
|  |   async function fourth () { | ||
|  |     fourthLoaded = true | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('without autostart and sync/async plugin mix', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app, { autostart: false }) | ||
|  |   t.plan(21) | ||
|  | 
 | ||
|  |   let firstLoaded = false | ||
|  |   let secondLoaded = false | ||
|  |   let thirdLoaded = false | ||
|  |   let fourthLoaded = false | ||
|  | 
 | ||
|  |   app.use(first) | ||
|  |   await app.after() | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.notOk(secondLoaded, 'second is not loaded') | ||
|  |   t.notOk(thirdLoaded, 'third is not loaded') | ||
|  |   t.notOk(fourthLoaded, 'fourth is not loaded') | ||
|  | 
 | ||
|  |   app.use(second) | ||
|  |   await app.after() | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.ok(secondLoaded, 'second is loaded') | ||
|  |   t.notOk(thirdLoaded, 'third is not loaded') | ||
|  |   t.notOk(fourthLoaded, 'fourth is not loaded') | ||
|  | 
 | ||
|  |   await sleep(10) | ||
|  | 
 | ||
|  |   app.use(third) | ||
|  |   await app.after() | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.ok(secondLoaded, 'second is loaded') | ||
|  |   t.ok(thirdLoaded, 'third is loaded') | ||
|  |   t.notOk(fourthLoaded, 'fourth is not loaded') | ||
|  | 
 | ||
|  |   app.use(fourth) | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.ok(secondLoaded, 'second is loaded') | ||
|  |   t.ok(thirdLoaded, 'third is loaded') | ||
|  |   t.notOk(fourthLoaded, 'fourth is not loaded') | ||
|  | 
 | ||
|  |   await app.after() | ||
|  |   t.ok(firstLoaded, 'first is loaded') | ||
|  |   t.ok(secondLoaded, 'second is loaded') | ||
|  |   t.ok(thirdLoaded, 'third is loaded') | ||
|  |   t.ok(fourthLoaded, 'fourth is loaded') | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  | 
 | ||
|  |   async function first () { | ||
|  |     firstLoaded = true | ||
|  |   } | ||
|  | 
 | ||
|  |   async function second () { | ||
|  |     const contents = await fs.readFile(path.join(__dirname, 'fixtures', 'dummy.txt'), 'utf-8') | ||
|  |     t.equal(contents, 'hello, world!') | ||
|  |     secondLoaded = true | ||
|  |   } | ||
|  | 
 | ||
|  |   async function third () { | ||
|  |     await sleep(10) | ||
|  |     thirdLoaded = true | ||
|  |   } | ||
|  | 
 | ||
|  |   function fourth (server, opts, done) { | ||
|  |     fourthLoaded = true | ||
|  |     done() | ||
|  |   } | ||
|  | }) | ||
|  | 
 | ||
|  | test('without autostart', async (t) => { | ||
|  |   const app = {} | ||
|  |   boot(app, { autostart: false }) | ||
|  |   let firstLoaded = false | ||
|  |   let secondLoaded = false | ||
|  |   let thirdLoaded = false | ||
|  | 
 | ||
|  |   app.use(async function first (app) { | ||
|  |     firstLoaded = true | ||
|  |     app.use(async () => { | ||
|  |       await sleep(1) | ||
|  |       secondLoaded = true | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   await app.after() | ||
|  |   t.equal(firstLoaded, true) | ||
|  |   t.equal(secondLoaded, true) | ||
|  | 
 | ||
|  |   await app.use(async () => { | ||
|  |     thirdLoaded = true | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.equal(thirdLoaded, true) | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  | }) | ||
|  | 
 | ||
|  | test('without autostart and with override', async (t) => { | ||
|  |   const app = {} | ||
|  |   const _ = boot(app, { autostart: false }) | ||
|  |   let count = 0 | ||
|  | 
 | ||
|  |   _.override = function (s) { | ||
|  |     const res = Object.create(s) | ||
|  |     res.count = ++count | ||
|  | 
 | ||
|  |     return res | ||
|  |   } | ||
|  | 
 | ||
|  |   app.use(async function first (app) { | ||
|  |     t.equal(app.count, 1) | ||
|  |     app.use(async (app) => { | ||
|  |       t.equal(app.count, 2) | ||
|  |       await app.after() | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   await app.after() | ||
|  | 
 | ||
|  |   await app.use(async (app) => { | ||
|  |     t.equal(app.count, 3) | ||
|  |   }) | ||
|  | 
 | ||
|  |   await app.ready() | ||
|  | }) | ||
|  | 
 | ||
|  | test('stop processing after errors', async (t) => { | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const app = boot() | ||
|  | 
 | ||
|  |   try { | ||
|  |     await app.use(async function first (app) { | ||
|  |       t.pass('first should be loaded') | ||
|  |       throw new Error('kaboom') | ||
|  |     }) | ||
|  |   } catch (e) { | ||
|  |     t.equal(e.message, 'kaboom') | ||
|  |   } | ||
|  | }) |