From 50c70537642ab9adeffbc2f5af9c95116f7da82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=27rysiek=27=20Wo=C5=BAniak?= Date: Wed, 9 Mar 2022 18:13:41 +0000 Subject: [PATCH] service-worker: implemented "enabled" config flag for plugins, incl. tests (ref. #45) --- __tests__/service-worker.test.js | 268 +++++++++++++++++++++++++++++-- service-worker.js | 9 +- 2 files changed, 262 insertions(+), 15 deletions(-) diff --git a/__tests__/service-worker.test.js b/__tests__/service-worker.test.js index b0b6fdb..abb8b55 100644 --- a/__tests__/service-worker.test.js +++ b/__tests__/service-worker.test.js @@ -40,19 +40,7 @@ describe("service-worker", () => { self.LibResilientPluginConstructors = global.LibResilientPluginConstructors }) - test("basic set-up: LibResilientPlugins", async () => { - self.LibResilientPlugins = false - self.LibResilientConfig = { - plugins: [], - loggedComponents: [ - 'service-worker' - ] - } - require("../service-worker.js"); - expect(self.LibResilientPlugins).toBeInstanceOf(Array) - }) - - test("Promise.any() polyfill should work", async () => { + test("reality-check: Promise.any() polyfill should work", async () => { self.LibResilientPlugins = false self.LibResilientConfig = { plugins: [], @@ -83,6 +71,18 @@ describe("service-worker", () => { } }) + test("basic set-up: LibResilientPlugins", async () => { + self.LibResilientPlugins = false + self.LibResilientConfig = { + plugins: [], + loggedComponents: [ + 'service-worker' + ] + } + require("../service-worker.js"); + expect(self.LibResilientPlugins).toBeInstanceOf(Array) + }) + test("basic set-up: use default LibResilientConfig values when config.json missing", async () => { self.LibResilientConfig = null @@ -299,6 +299,248 @@ describe("service-worker", () => { expect(fetch).toHaveBeenCalled(); }) + + test("basic set-up: instantiate a complex tree of configured plugins", async () => { + self.LibResilientConfig = { + plugins: [{ + name: 'plugin-1', + uses: [{ + name: 'plugin-2', + uses: [{ + name: 'plugin-3' + }] + },{ + name: 'plugin-3' + }] + },{ + name: 'plugin-2', + uses: [{ + name: 'plugin-3' + }] + },{ + name: 'plugin-3', + uses: [{ + name: 'plugin-1' + },{ + name: 'plugin-2', + uses: [{ + name: 'plugin-1', + uses: [{ + name: 'plugin-4' + }] + }] + }] + },{ + name: 'plugin-4' + } + ] + } + + global.LibResilientPluginConstructors.set('plugin-1', (LRPC, config)=>{ + return { + name: 'plugin-1', + description: 'Plugin Type 1', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + global.LibResilientPluginConstructors.set('plugin-2', (LRPC, config)=>{ + return { + name: 'plugin-2', + description: 'Plugin Type 2', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + global.LibResilientPluginConstructors.set('plugin-3', (LRPC, config)=>{ + return { + name: 'plugin-3', + description: 'Plugin Type 3', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + global.LibResilientPluginConstructors.set('plugin-4', (LRPC, config)=>{ + return { + name: 'plugin-4', + description: 'Plugin Type 4', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + + + try { + require("../service-worker.js"); + } catch(e) {} + await self.trigger('install') + // this is silly but works, and is necessary because + // event.waitUntil() in the install event handler is not handled correctly in NodeJS + await new Promise(resolve => setTimeout(resolve, 100)); + await self.trigger('activate') + expect(typeof self.LibResilientConfig).toEqual('object') + // basic stuff + expect(self.LibResilientPlugins.length).toEqual(4) + expect(self.LibResilientPlugins[0].name).toEqual('plugin-1') + expect(self.LibResilientPlugins[1].name).toEqual('plugin-2') + expect(self.LibResilientPlugins[2].name).toEqual('plugin-3') + expect(self.LibResilientPlugins[3].name).toEqual('plugin-4') + // first plugin dependencies + expect(self.LibResilientPlugins[0].uses.length).toEqual(2) + expect(self.LibResilientPlugins[0].uses[0].name).toEqual('plugin-2') + expect(self.LibResilientPlugins[0].uses[0].uses.length).toEqual(1) + expect(self.LibResilientPlugins[0].uses[0].uses[0].name).toEqual('plugin-3') + expect(self.LibResilientPlugins[0].uses[0].uses[0].uses.length).toEqual(0) + expect(self.LibResilientPlugins[0].uses[1].name).toEqual('plugin-3') + expect(self.LibResilientPlugins[0].uses[1].uses.length).toEqual(0) + // second plugin dependencies + expect(self.LibResilientPlugins[1].uses.length).toEqual(1) + expect(self.LibResilientPlugins[1].uses[0].name).toEqual('plugin-3') + expect(self.LibResilientPlugins[1].uses[0].uses.length).toEqual(0) + // third plugin dependencies + expect(self.LibResilientPlugins[2].uses.length).toEqual(2) + expect(self.LibResilientPlugins[2].uses[0].name).toEqual('plugin-1') + expect(self.LibResilientPlugins[2].uses[0].uses.length).toEqual(0) + expect(self.LibResilientPlugins[2].uses[1].name).toEqual('plugin-2') + expect(self.LibResilientPlugins[2].uses[1].uses.length).toEqual(1) + expect(self.LibResilientPlugins[2].uses[1].uses[0].name).toEqual('plugin-1') + expect(self.LibResilientPlugins[2].uses[1].uses[0].uses.length).toEqual(1) + expect(self.LibResilientPlugins[2].uses[1].uses[0].uses[0].name).toEqual('plugin-4') + expect(self.LibResilientPlugins[2].uses[1].uses[0].uses[0].uses.length).toEqual(0) + // fourth plugin dependencies + expect(self.LibResilientPlugins[3].uses.length).toEqual(0) + }) + + + test("basic set-up: instantiate configured plugins; explicitly disabled plugins should not be instantiated", async () => { + self.LibResilientConfig = { + plugins: [{ + name: 'plugin-enabled' + },{ + name: 'plugin-disabled', + enabled: false + },{ + name: 'plugin-enabled', + enabled: true + }] + } + + global.LibResilientPluginConstructors.set('plugin-enabled', ()=>{ + return { + name: 'plugin-enabled', + description: 'Enabled plugin', + version: '0.0.1', + fetch: (url)=>{return true} + } + }) + global.LibResilientPluginConstructors.set('plugin-disabled', ()=>{ + return { + name: 'plugin-disabled', + description: 'Disabled plugin', + version: '0.0.1', + fetch: (url)=>{return true} + } + }) + + try { + require("../service-worker.js"); + } catch(e) {} + await self.trigger('install') + // this is silly but works, and is necessary because + // event.waitUntil() in the install event handler is not handled correctly in NodeJS + await new Promise(resolve => setTimeout(resolve, 100)); + await self.trigger('activate') + expect(typeof self.LibResilientConfig).toEqual('object') + expect(self.LibResilientPlugins.length).toEqual(2) + expect(self.LibResilientPlugins[0].name).toEqual('plugin-enabled') + expect(self.LibResilientPlugins[1].name).toEqual('plugin-enabled') + }) + + + test("basic set-up: instantiate configured plugins; explicitly disabled dependencies should not be instantiated", async () => { + self.LibResilientConfig = { + plugins: [{ + name: 'plugin-disabled', + enabled: false, + uses: [{ + name: 'dependency-enabled' + }] + },{ + name: 'plugin-enabled', + uses: [{ + name: 'dependency-disabled', + enabled: false + }] + },{ + name: 'plugin-enabled', + uses: [{ + name: 'dependency-enabled', + enabled: true + }] + }], + loggedComponents: ['service-worker'] + } + + global.LibResilientPluginConstructors.set('plugin-enabled', (LRPC, config)=>{ + return { + name: 'plugin-enabled', + description: 'Enabled plugin', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + global.LibResilientPluginConstructors.set('plugin-disabled', (LRPC, config)=>{ + return { + name: 'plugin-disabled', + description: 'Disabled plugin', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + global.LibResilientPluginConstructors.set('dependency-disabled', (LRPC, config)=>{ + return { + name: 'dependency-disabled', + description: 'Disabled dependency plugin', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + global.LibResilientPluginConstructors.set('dependency-enabled', (LRPC, config)=>{ + return { + name: 'dependency-enabled', + description: 'Enabled dependency plugin', + version: '0.0.1', + fetch: (url)=>{return true}, + uses: config.uses || [] + } + }) + + try { + require("../service-worker.js"); + } catch(e) {} + await self.trigger('install') + // this is silly but works, and is necessary because + // event.waitUntil() in the install event handler is not handled correctly in NodeJS + await new Promise(resolve => setTimeout(resolve, 100)); + await self.trigger('activate') + expect(typeof self.LibResilientConfig).toEqual('object') + expect(self.LibResilientPlugins.length).toEqual(2) + expect(self.LibResilientPlugins[0].name).toEqual('plugin-enabled') + expect(self.LibResilientPlugins[0].uses.length).toEqual(0) + expect(self.LibResilientPlugins[1].name).toEqual('plugin-enabled') + expect(self.LibResilientPlugins[1].uses.length).toEqual(1) + expect(self.LibResilientPlugins[1].uses[0].name).toEqual('dependency-enabled') + expect(self.LibResilientPlugins[1].uses[0].uses.length).toEqual(0) + }) + + test("basic set-up: a valid config.json file gets cached", async () => { self.LibResilientConfig = null diff --git a/service-worker.js b/service-worker.js index 5cebd06..f8dc154 100644 --- a/service-worker.js +++ b/service-worker.js @@ -283,7 +283,12 @@ let initServiceWorker = async () => { // if the pluginConfig does not have an "enabled" field, it should be assumed to be "true" if ( ( "enabled" in pluginConfig ) && ( pluginConfig.enabled != true ) ) { self.log('service-worker', `skipping ${pluginConfig.name} instantiation: plugin not enabled (dependencies will also not be instantiated)`) - break; + pluginConfig = dependentPlugins.pop() + if (pluginConfig !== undefined) { + let didx = pluginConfig.uses.indexOf(false) + pluginConfig.uses.splice(didx, 1) + } + continue; } // instantiate the plugin @@ -325,7 +330,7 @@ let initServiceWorker = async () => { // if pluginConfig is not false, rinse-repeat the plugin instantiation steps // since we are dealing with the last element of dependentPlugins - } while (pluginConfig !== false) + } while ( (pluginConfig !== false) && (pluginConfig !== undefined) ) }