test coverage for config.json handling (ref. 31)

merge-requests/11/head
Michał 'rysiek' Woźniak 2022-01-25 00:28:41 +00:00
rodzic e7c09f3065
commit 629b2eef33
2 zmienionych plików z 219 dodań i 18 usunięć

Wyświetl plik

@ -3,7 +3,11 @@ const makeServiceWorkerEnv = require('service-worker-mock');
global.fetch = require('node-fetch');
jest.mock('node-fetch')
global.fetch.mockImplementation((url, init) => {
describe("service-worker", () => {
beforeEach(() => {
global.fetch.mockImplementation((url, init) => {
return Promise.resolve(
new Response(
new Blob(
@ -20,9 +24,7 @@ global.fetch.mockImplementation((url, init) => {
})
);
});
describe("service-worker", () => {
beforeEach(() => {
Object.assign(global, makeServiceWorkerEnv());
global.self = new ServiceWorkerGlobalScope()
jest.resetModules();
@ -81,15 +83,196 @@ describe("service-worker", () => {
}
})
test("basic set-up: LibResilientConfig", async () => {
test("basic set-up: use default LibResilientConfig values when config.json missing", async () => {
self.LibResilientConfig = null
global.fetch.mockImplementation((url, init) => {
return Promise.resolve(
new Response(
new Blob(
[JSON.stringify({ test: "fail" })],
{type: "application/json"}
),
{
status: 404,
statusText: "Not Found",
headers: {
'ETag': 'TestingETagHeader'
},
url: url
})
);
});
try {
require("../service-worker.js");
} catch(e) {}
await self.trigger('install')
await self.trigger('activate')
expect(typeof self.LibResilientConfig).toEqual('object')
expect(self.LibResilientConfig.defaultPluginTimeout).toBe(10000)
expect(typeof self.LibResilientConfig.plugins).toEqual('object')
expect(self.LibResilientConfig.loggedComponents).toBeInstanceOf(Array)
expect(self.LibResilientConfig.plugins).toStrictEqual([{name: "fetch"},{name: "cache"}])
expect(self.LibResilientConfig.loggedComponents).toStrictEqual(['service-worker', 'fetch', 'cache'])
})
test("basic set-up: use default LibResilientConfig values when config.json not valid JSON", async () => {
self.LibResilientConfig = null
global.fetch.mockImplementation((url, init) => {
return Promise.resolve(
new Response(
new Blob(
["not a JSON"],
{type: "application/json"}
),
{
status: 200,
statusText: "OK",
headers: {
'ETag': 'TestingETagHeader'
},
url: url
})
);
});
try {
require("../service-worker.js");
} catch(e) {}
await self.trigger('install')
await self.trigger('activate')
expect(typeof self.LibResilientConfig).toEqual('object')
expect(self.LibResilientConfig.defaultPluginTimeout).toBe(10000)
expect(self.LibResilientConfig.plugins).toStrictEqual([{name: "fetch"},{name: "cache"}])
expect(self.LibResilientConfig.loggedComponents).toStrictEqual(['service-worker', 'fetch', 'cache'])
})
test("basic set-up: use default LibResilientConfig values when no valid 'plugins' field in config.json", async () => {
self.LibResilientConfig = null
global.fetch.mockImplementation((url, init) => {
return Promise.resolve(
new Response(
new Blob(
[JSON.stringify({loggedComponents: ['service-worker', 'fetch'], plugins: 'not a valid array'})],
{type: "application/json"}
),
{
status: 200,
statusText: "OK",
headers: {
'ETag': 'TestingETagHeader'
},
url: url
})
);
});
try {
require("../service-worker.js");
} catch(e) {}
await self.trigger('install')
await self.trigger('activate')
expect(typeof self.LibResilientConfig).toEqual('object')
expect(self.LibResilientConfig.defaultPluginTimeout).toBe(10000)
expect(self.LibResilientConfig.plugins).toStrictEqual([{name: "fetch"},{name: "cache"}])
expect(self.LibResilientConfig.loggedComponents).toStrictEqual(['service-worker', 'fetch', 'cache'])
})
test("basic set-up: use default LibResilientConfig values when no valid 'loggedComponents' field in config.json", async () => {
self.LibResilientConfig = null
global.fetch.mockImplementation((url, init) => {
return Promise.resolve(
new Response(
new Blob(
[JSON.stringify({loggedComponents: 'not a valid array', plugins: [{name: "fetch"}]})],
{type: "application/json"}
),
{
status: 200,
statusText: "OK",
headers: {
'ETag': 'TestingETagHeader'
},
url: url
})
);
});
try {
require("../service-worker.js");
} catch(e) {}
await self.trigger('install')
await self.trigger('activate')
expect(typeof self.LibResilientConfig).toEqual('object')
expect(self.LibResilientConfig.defaultPluginTimeout).toBe(10000)
expect(self.LibResilientConfig.plugins).toStrictEqual([{name: "fetch"},{name: "cache"}])
expect(self.LibResilientConfig.loggedComponents).toStrictEqual(['service-worker', 'fetch', 'cache'])
})
test("basic set-up: use default LibResilientConfig values when 'defaultPluginTimeout' field in config.json contains an invalid value", async () => {
self.LibResilientConfig = null
global.fetch.mockImplementation((url, init) => {
return Promise.resolve(
new Response(
new Blob(
[JSON.stringify({loggedComponents: ['service-worker', 'fetch'], plugins: [{name: "fetch"}], defaultPluginTimeout: 'not an integer'})],
{type: "application/json"}
),
{
status: 200,
statusText: "OK",
headers: {
'ETag': 'TestingETagHeader'
},
url: url
})
);
});
try {
require("../service-worker.js");
} catch(e) {}
await self.trigger('install')
await self.trigger('activate')
expect(typeof self.LibResilientConfig).toEqual('object')
expect(self.LibResilientConfig.defaultPluginTimeout).toBe(10000)
expect(self.LibResilientConfig.plugins).toStrictEqual([{name: "fetch"},{name: "cache"}])
expect(self.LibResilientConfig.loggedComponents).toStrictEqual(['service-worker', 'fetch', 'cache'])
})
test("basic set-up: use config values from a valid config.json file", async () => {
self.LibResilientConfig = null
global.fetch.mockImplementation((url, init) => {
return Promise.resolve(
new Response(
new Blob(
[JSON.stringify({loggedComponents: ['service-worker', 'cache'], plugins: [{name: "cache"}], defaultPluginTimeout: 5000})],
{type: "application/json"}
),
{
status: 200,
statusText: "OK",
headers: {
'ETag': 'TestingETagHeader'
},
url: url
})
);
});
try {
require("../service-worker.js");
} catch(e) {}
await self.trigger('install')
await self.trigger('activate')
expect(typeof self.LibResilientConfig).toEqual('object')
expect(self.LibResilientConfig.defaultPluginTimeout).toBe(5000)
expect(self.LibResilientConfig.plugins).toStrictEqual([{name: "cache"}])
expect(self.LibResilientConfig.loggedComponents).toStrictEqual(['service-worker', 'cache'])
})
test("fetching content should work", async () => {

Wyświetl plik

@ -107,6 +107,13 @@ let verifyConfigData = (cdata) => {
self.log('service-worker', 'fetched config does not contain a valid "loggedComponents" field')
return false;
}
// defaultPluginTimeout optional
if ("defaultPluginTimeout" in cdata) {
if (!Number.isInteger(cdata.defaultPluginTimeout)) {
self.log('service-worker', 'fetched config contains invalid "defaultPluginTimeout" data (integer expected)')
return false;
}
}
// we're good
return true;
}
@ -129,16 +136,23 @@ let initServiceWorker = async () => {
try {
//self.importScripts(self.registration.scope + "config.json")
var cdata = await fetch(self.registration.scope + "config.json")
cdata = await cdata.json()
if (verifyConfigData(cdata)) {
self.LibResilientConfig.plugins = cdata.plugins
self.LibResilientConfig.loggedComponents = cdata.loggedComponents
self.log('service-worker', 'config loaded.')
if (cdata.status != 200) {
self.log('service-worker', `failed to fetch config (${cdata.status} ${cdata.statusText}).`)
} else {
self.log('service-worker', 'ignoring invalid config, using defaults.')
cdata = await cdata.json()
if (verifyConfigData(cdata)) {
self.LibResilientConfig.plugins = cdata.plugins
self.LibResilientConfig.loggedComponents = cdata.loggedComponents
if ("defaultPluginTimeout" in cdata) {
self.LibResilientConfig.defaultPluginTimeout = cdata.defaultPluginTimeout
}
self.log('service-worker', 'config loaded.')
} else {
self.log('service-worker', 'ignoring invalid config, using defaults.')
}
}
} catch (e) {
self.log('service-worker', 'config loading failed, using defaults')
self.log('service-worker', 'config loading failed, using defaults; error:', e)
}
// create the LibResilientPluginConstructors map
@ -146,14 +160,19 @@ let initServiceWorker = async () => {
// TODO: find a better way
self.LibResilientPluginConstructors = self.LibResilientPluginConstructors || new Map()
// copy of the plugins config
// we need to work on it so that self.LibResilientConfig.plugins remains unmodified
// in case we need it later (for example, when re-loading the config)
var pluginsConfig = [...self.LibResilientConfig.plugins]
// this is the stash for plugins that need dependencies instantiated first
var dependentPlugins = new Array()
// only now load the plugins (config.json could have changed the defaults)
while (self.LibResilientConfig.plugins.length > 0) {
while (pluginsConfig.length > 0) {
// get the first plugin config from the array
let pluginConfig = self.LibResilientConfig.plugins.shift()
let pluginConfig = pluginsConfig.shift()
self.log('service-worker', `handling plugin type: ${pluginConfig.name}`)
// load the relevant plugin script (if not yet loaded)
@ -170,7 +189,7 @@ let initServiceWorker = async () => {
for (var i=(pluginConfig.uses.length); i--; i>=0) {
self.log('service-worker', `${pluginConfig.name}: dependency found: ${pluginConfig.uses[i].name}`)
// put the plugin config in front of the plugin configs array
self.LibResilientConfig.plugins.unshift(pluginConfig.uses[i])
pluginsConfig.unshift(pluginConfig.uses[i])
// set each dependency plugin config to false so that we can keep track
// as we fill those gaps later with instantiated dependency plugins
pluginConfig.uses[i] = false
@ -702,7 +721,6 @@ self.addEventListener('install', async (event) => {
// TODO: Might we want to have a local cache?
// "COMMIT_UNKNOWN" will be replaced with commit ID
self.log('service-worker', "0. Installed LibResilient Service Worker (commit: COMMIT_UNKNOWN).");
// TODO: should we do some plugin initialization here?
});
self.addEventListener('activate', event => {