strong-tie/inbound-calls
0
1'use strict'2 3const { test } = require('tap')4const boot = require('..')5const { promisify } = require('node:util')6const sleep = promisify(setTimeout)7const fs = require('node:fs').promises8const path = require('node:path')9 10test('await after - nested plugins with same tick callbacks', async (t) => {11 const app = {}12 boot(app)13 14 let secondLoaded = false15 16 app.use(async (app) => {17 t.pass('plugin init')18 app.use(async () => {19 t.pass('plugin2 init')20 await sleep(1)21 secondLoaded = true22 })23 })24 await app.after()25 t.pass('reachable')26 t.equal(secondLoaded, true)27 28 await app.ready()29 t.pass('reachable')30})31 32test('await after without server', async (t) => {33 const app = boot()34 35 let secondLoaded = false36 37 app.use(async (app) => {38 t.pass('plugin init')39 app.use(async () => {40 t.pass('plugin2 init')41 await sleep(1)42 secondLoaded = true43 })44 })45 await app.after()46 t.pass('reachable')47 t.equal(secondLoaded, true)48 49 await app.ready()50 t.pass('reachable')51})52 53test('await after with cb functions', async (t) => {54 const app = boot()55 let secondLoaded = false56 let record = ''57 58 app.use(async (app) => {59 t.pass('plugin init')60 record += 'plugin|'61 app.use(async () => {62 t.pass('plugin2 init')63 record += 'plugin2|'64 await sleep(1)65 secondLoaded = true66 })67 })68 await app.after(() => {69 record += 'after|'70 })71 t.pass('reachable')72 t.equal(secondLoaded, true)73 record += 'ready'74 await app.ready()75 t.pass('reachable')76 t.equal(record, 'plugin|plugin2|after|ready')77})78 79test('await after - nested plugins with future tick callbacks', async (t) => {80 const app = {}81 boot(app)82 83 t.plan(4)84 85 app.use((f, opts, cb) => {86 t.pass('plugin init')87 app.use((f, opts, cb) => {88 t.pass('plugin2 init')89 setImmediate(cb)90 })91 setImmediate(cb)92 })93 await app.after()94 t.pass('reachable')95 96 await app.ready()97 t.pass('reachable')98})99 100test('await after - nested async function plugins', async (t) => {101 const app = {}102 boot(app)103 104 t.plan(5)105 106 app.use(async (f, opts) => {107 t.pass('plugin init')108 await app.use(async (f, opts) => {109 t.pass('plugin2 init')110 })111 t.pass('reachable')112 })113 await app.after()114 t.pass('reachable')115 116 await app.ready()117 t.pass('reachable')118})119 120test('await after - promise resolves to undefined', async (t) => {121 const app = {}122 boot(app)123 124 t.plan(4)125 126 app.use(async (f, opts, cb) => {127 app.use((f, opts, cb) => {128 t.pass('plugin init')129 cb()130 })131 const instance = await app.after()132 t.equal(instance, undefined)133 })134 t.pass('reachable')135 136 await app.ready()137 t.pass('reachable')138})139 140test('await after - promise returning function plugins + promise chaining', async (t) => {141 const app = {}142 boot(app)143 144 t.plan(6)145 146 app.use((f, opts) => {147 t.pass('plugin init')148 return app.use((f, opts) => {149 t.pass('plugin2 init')150 return Promise.resolve()151 }).then((f2) => {152 t.equal(f2, f)153 return 'test'154 }).then((val) => {155 t.equal(val, 'test')156 })157 })158 await app.after()159 t.pass('reachable')160 161 await app.ready()162 t.pass('reachable')163})164 165test('await after - error handling, async throw', async (t) => {166 const app = {}167 boot(app)168 169 t.plan(2)170 171 const e = new Error('kaboom')172 173 app.use(async (f, opts) => {174 throw Error('kaboom')175 })176 177 await t.rejects(app.after(), e)178 179 await t.rejects(() => app.ready(), Error('kaboom'))180})181 182test('await after - error handling, async throw, nested', async (t) => {183 const app = {}184 boot(app)185 186 t.plan(2)187 188 const e = new Error('kaboom')189 190 app.use(async (f, opts) => {191 app.use(async (f, opts) => {192 throw e193 })194 })195 196 await t.rejects(app.after())197 await t.rejects(() => app.ready(), e)198})199 200test('await after - error handling, same tick cb err', async (t) => {201 const app = {}202 boot(app)203 204 t.plan(2)205 206 app.use((f, opts, cb) => {207 cb(Error('kaboom'))208 })209 await t.rejects(app.after())210 await t.rejects(app.ready(), Error('kaboom'))211})212 213test('await after - error handling, same tick cb err, nested', async (t) => {214 const app = {}215 boot(app)216 217 t.plan(2)218 219 app.use((f, opts, cb) => {220 app.use((f, opts, cb) => {221 cb(Error('kaboom'))222 })223 cb()224 })225 226 await t.rejects(app.after())227 await t.rejects(app.ready(), Error('kaboom'))228})229 230test('await after - error handling, future tick cb err', async (t) => {231 const app = {}232 boot(app)233 234 t.plan(2)235 236 app.use((f, opts, cb) => {237 setImmediate(() => { cb(Error('kaboom')) })238 })239 240 await t.rejects(app.after())241 await t.rejects(app.ready(), Error('kaboom'))242})243 244test('await after - error handling, future tick cb err, nested', async (t) => {245 const app = {}246 boot(app)247 248 t.plan(2)249 250 app.use((f, opts, cb) => {251 app.use((f, opts, cb) => {252 setImmediate(() => { cb(Error('kaboom')) })253 })254 cb()255 })256 await t.rejects(app.after(), Error('kaboom'))257 await t.rejects(app.ready(), Error('kaboom'))258})259 260test('await after complex scenario', async (t) => {261 const app = {}262 boot(app)263 t.plan(16)264 265 let firstLoaded = false266 let secondLoaded = false267 let thirdLoaded = false268 let fourthLoaded = false269 270 app.use(first)271 await app.after()272 t.ok(firstLoaded, 'first is loaded')273 t.notOk(secondLoaded, 'second is not loaded')274 t.notOk(thirdLoaded, 'third is not loaded')275 t.notOk(fourthLoaded, 'fourth is not loaded')276 app.use(second)277 t.ok(firstLoaded, 'first is loaded')278 t.notOk(secondLoaded, 'second is not loaded')279 t.notOk(thirdLoaded, 'third is not loaded')280 t.notOk(fourthLoaded, 'fourth is not loaded')281 app.use(third)282 await app.after()283 t.ok(firstLoaded, 'first is loaded')284 t.ok(secondLoaded, 'second is loaded')285 t.ok(thirdLoaded, 'third is loaded')286 t.ok(fourthLoaded, 'fourth is loaded')287 await app.ready()288 t.ok(firstLoaded, 'first is loaded')289 t.ok(secondLoaded, 'second is loaded')290 t.ok(thirdLoaded, 'third is loaded')291 t.ok(fourthLoaded, 'fourth is loaded')292 293 async function first () {294 firstLoaded = true295 }296 297 async function second () {298 secondLoaded = true299 }300 301 async function third (app) {302 thirdLoaded = true303 app.use(fourth)304 }305 306 async function fourth () {307 fourthLoaded = true308 }309})310 311test('without autostart and sync/async plugin mix', async (t) => {312 const app = {}313 boot(app, { autostart: false })314 t.plan(21)315 316 let firstLoaded = false317 let secondLoaded = false318 let thirdLoaded = false319 let fourthLoaded = false320 321 app.use(first)322 await app.after()323 t.ok(firstLoaded, 'first is loaded')324 t.notOk(secondLoaded, 'second is not loaded')325 t.notOk(thirdLoaded, 'third is not loaded')326 t.notOk(fourthLoaded, 'fourth is not loaded')327 328 app.use(second)329 await app.after()330 t.ok(firstLoaded, 'first is loaded')331 t.ok(secondLoaded, 'second is loaded')332 t.notOk(thirdLoaded, 'third is not loaded')333 t.notOk(fourthLoaded, 'fourth is not loaded')334 335 await sleep(10)336 337 app.use(third)338 await app.after()339 t.ok(firstLoaded, 'first is loaded')340 t.ok(secondLoaded, 'second is loaded')341 t.ok(thirdLoaded, 'third is loaded')342 t.notOk(fourthLoaded, 'fourth is not loaded')343 344 app.use(fourth)345 t.ok(firstLoaded, 'first is loaded')346 t.ok(secondLoaded, 'second is loaded')347 t.ok(thirdLoaded, 'third is loaded')348 t.notOk(fourthLoaded, 'fourth is not loaded')349 350 await app.after()351 t.ok(firstLoaded, 'first is loaded')352 t.ok(secondLoaded, 'second is loaded')353 t.ok(thirdLoaded, 'third is loaded')354 t.ok(fourthLoaded, 'fourth is loaded')355 356 await app.ready()357 358 async function first () {359 firstLoaded = true360 }361 362 async function second () {363 const contents = await fs.readFile(path.join(__dirname, 'fixtures', 'dummy.txt'), 'utf-8')364 t.equal(contents, 'hello, world!')365 secondLoaded = true366 }367 368 async function third () {369 await sleep(10)370 thirdLoaded = true371 }372 373 function fourth (server, opts, done) {374 fourthLoaded = true375 done()376 }377})378 379test('without autostart', async (t) => {380 const app = {}381 boot(app, { autostart: false })382 let firstLoaded = false383 let secondLoaded = false384 let thirdLoaded = false385 386 app.use(async function first (app) {387 firstLoaded = true388 app.use(async () => {389 await sleep(1)390 secondLoaded = true391 })392 })393 394 await app.after()395 t.equal(firstLoaded, true)396 t.equal(secondLoaded, true)397 398 await app.use(async () => {399 thirdLoaded = true400 })401 402 t.equal(thirdLoaded, true)403 404 await app.ready()405})406 407test('without autostart and with override', async (t) => {408 const app = {}409 const _ = boot(app, { autostart: false })410 let count = 0411 412 _.override = function (s) {413 const res = Object.create(s)414 res.count = ++count415 416 return res417 }418 419 app.use(async function first (app) {420 t.equal(app.count, 1)421 app.use(async (app) => {422 t.equal(app.count, 2)423 await app.after()424 })425 })426 427 await app.after()428 429 await app.use(async (app) => {430 t.equal(app.count, 3)431 })432 433 await app.ready()434})435 436test('stop processing after errors', async (t) => {437 t.plan(2)438 439 const app = boot()440 441 try {442 await app.use(async function first (app) {443 t.pass('first should be loaded')444 throw new Error('kaboom')445 })446 } catch (e) {447 t.equal(e.message, 'kaboom')448 }449})450 