kopia lustrzana https://gitlab.com/rysiekpl/libresilient
WIP: config.json caching/verification; some tests fixed, v1:verified cache implemented (ref. #48)
rodzic
5bca087442
commit
0fe53bcc20
|
@ -289,16 +289,16 @@ beforeEach(async ()=>{
|
||||||
// clear the caches
|
// clear the caches
|
||||||
await caches
|
await caches
|
||||||
.has('v1')
|
.has('v1')
|
||||||
.then(async (hasv1) => {
|
.then(async (hasit) => {
|
||||||
if (hasv1) {
|
if (hasit) {
|
||||||
await caches.delete('v1')
|
await caches.delete('v1')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await caches
|
await caches
|
||||||
.has('v1:temp')
|
.has('v1:verified')
|
||||||
.then(async (hasv1) => {
|
.then(async (hasit) => {
|
||||||
if (hasv1) {
|
if (hasit) {
|
||||||
await caches.delete('v1:temp')
|
await caches.delete('v1:verified')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// make sure we're starting with a clean slate in LibResilientPluginConstructors
|
// make sure we're starting with a clean slate in LibResilientPluginConstructors
|
||||||
|
@ -370,6 +370,44 @@ describe('service-worker', async () => {
|
||||||
assertSpyCalls(self.fetch, 1)
|
assertSpyCalls(self.fetch, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should use default LibResilientConfig values when fetching config.json throws an exception", async () => {
|
||||||
|
|
||||||
|
window.fetch = spy(() => {
|
||||||
|
throw new Error('Testing exception')
|
||||||
|
})
|
||||||
|
|
||||||
|
await import("../../service-worker.js?" + window.test_id);
|
||||||
|
await self.dispatchEvent(new Event('install'))
|
||||||
|
await self.waitForSWInstall()
|
||||||
|
|
||||||
|
assertEquals(typeof self.LibResilientConfig, "object")
|
||||||
|
assertEquals(self.LibResilientConfig.defaultPluginTimeout, 10000)
|
||||||
|
assertEquals(self.LibResilientConfig.plugins, [{name: "fetch"},{name: "cache"}])
|
||||||
|
assertEquals(self.LibResilientConfig.loggedComponents, ['service-worker', 'fetch', 'cache'])
|
||||||
|
assertEquals(self.LibResilientConfig.normalizeQueryParams, true)
|
||||||
|
assertEquals(self.LibResilientConfig.useMimeSniffingLibrary, false)
|
||||||
|
assertSpyCalls(self.fetch, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should use default LibResilientConfig values when fetching config.json returns undefined", async () => {
|
||||||
|
|
||||||
|
window.fetch = spy(() => {
|
||||||
|
return undefined;
|
||||||
|
})
|
||||||
|
|
||||||
|
await import("../../service-worker.js?" + window.test_id);
|
||||||
|
await self.dispatchEvent(new Event('install'))
|
||||||
|
await self.waitForSWInstall()
|
||||||
|
|
||||||
|
assertEquals(typeof self.LibResilientConfig, "object")
|
||||||
|
assertEquals(self.LibResilientConfig.defaultPluginTimeout, 10000)
|
||||||
|
assertEquals(self.LibResilientConfig.plugins, [{name: "fetch"},{name: "cache"}])
|
||||||
|
assertEquals(self.LibResilientConfig.loggedComponents, ['service-worker', 'fetch', 'cache'])
|
||||||
|
assertEquals(self.LibResilientConfig.normalizeQueryParams, true)
|
||||||
|
assertEquals(self.LibResilientConfig.useMimeSniffingLibrary, false)
|
||||||
|
assertSpyCalls(self.fetch, 1)
|
||||||
|
})
|
||||||
|
|
||||||
it("should use default LibResilientConfig values when config.json not valid JSON", async () => {
|
it("should use default LibResilientConfig values when config.json not valid JSON", async () => {
|
||||||
|
|
||||||
let mock_response_data = {
|
let mock_response_data = {
|
||||||
|
@ -490,7 +528,7 @@ describe('service-worker', async () => {
|
||||||
assertSpyCalls(self.fetch, 1)
|
assertSpyCalls(self.fetch, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should use config values from a valid fetched config.json file, caching it", async () => {
|
it("should use config values from a valid fetched config.json file, caching it in both caches (v1, v1:verified)", async () => {
|
||||||
let mock_response_data = {
|
let mock_response_data = {
|
||||||
data: JSON.stringify({loggedComponents: ['service-worker', 'cache'], plugins: [{name: "cache"}], defaultPluginTimeout: 5000, normalizeQueryParams: false, useMimeSniffingLibrary: true})
|
data: JSON.stringify({loggedComponents: ['service-worker', 'cache'], plugins: [{name: "cache"}], defaultPluginTimeout: 5000, normalizeQueryParams: false, useMimeSniffingLibrary: true})
|
||||||
}
|
}
|
||||||
|
@ -515,6 +553,10 @@ describe('service-worker', async () => {
|
||||||
await window.waitForCacheAction(window.location.origin + 'config.json', 'v1'),
|
await window.waitForCacheAction(window.location.origin + 'config.json', 'v1'),
|
||||||
mock_response_data.data
|
mock_response_data.data
|
||||||
);
|
);
|
||||||
|
assertEquals(
|
||||||
|
await window.waitForCacheAction(window.location.origin + 'config.json', 'v1:verified'),
|
||||||
|
mock_response_data.data
|
||||||
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should instantiate a complex tree of configured plugins", async () => {
|
it("should instantiate a complex tree of configured plugins", async () => {
|
||||||
|
@ -775,9 +817,17 @@ describe('service-worker', async () => {
|
||||||
assertEquals(self.LibResilientConfig.defaultPluginTimeout, 5000)
|
assertEquals(self.LibResilientConfig.defaultPluginTimeout, 5000)
|
||||||
assertEquals(self.LibResilientConfig.plugins, [{name: "cache"}])
|
assertEquals(self.LibResilientConfig.plugins, [{name: "cache"}])
|
||||||
assertEquals(self.LibResilientConfig.loggedComponents, ['service-worker', 'cache'])
|
assertEquals(self.LibResilientConfig.loggedComponents, ['service-worker', 'cache'])
|
||||||
|
|
||||||
|
// cacheConfigJSON() is called asynchronously in the Service Worker,
|
||||||
|
// if we don't make sure that the caching has completed, we will get an error.
|
||||||
|
// so we wait until config.json is cached, and use that to verify it is in fact cached
|
||||||
|
assertEquals(
|
||||||
|
await window.waitForCacheAction(window.location.origin + 'config.json', 'v1:verified'),
|
||||||
|
mock_response_data.data
|
||||||
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should use a stale cached valid config.json file without a fetch, then retrieve and cache a fresh config.json using the configured plugins", async () => {
|
it("should use a stale cached valid config.json file without a fetch, caching it in v1:verified cache, then retrieve and cache a fresh config.json using the configured plugins", async () => {
|
||||||
|
|
||||||
// this does not change
|
// this does not change
|
||||||
var config_url = window.location.origin + 'config.json'
|
var config_url = window.location.origin + 'config.json'
|
||||||
|
@ -839,6 +889,14 @@ describe('service-worker', async () => {
|
||||||
assertSpyCalls(self.fetch, 0)
|
assertSpyCalls(self.fetch, 0)
|
||||||
assertSpyCalls(resolveConfigFetch, 1)
|
assertSpyCalls(resolveConfigFetch, 1)
|
||||||
|
|
||||||
|
// cacheConfigJSON() is called asynchronously in the Service Worker,
|
||||||
|
// if we don't make sure that the caching has completed, we will get an error.
|
||||||
|
// so we wait until config.json is cached, and use that to verify it is in fact cached
|
||||||
|
assertEquals(
|
||||||
|
await window.waitForCacheAction(window.location.origin + 'config.json', 'v1:verified'),
|
||||||
|
mock_response_data.data
|
||||||
|
);
|
||||||
|
|
||||||
// wait until verify the *new* config got cached
|
// wait until verify the *new* config got cached
|
||||||
// running waitForCacheAdd only once might not be enough, as the cache
|
// running waitForCacheAdd only once might not be enough, as the cache
|
||||||
// already contained config.json!
|
// already contained config.json!
|
||||||
|
@ -847,7 +905,7 @@ describe('service-worker', async () => {
|
||||||
// so as not to end up in a forever loop
|
// so as not to end up in a forever loop
|
||||||
for (let i=0; i<100; i++) {
|
for (let i=0; i<100; i++) {
|
||||||
// did we get the new config?
|
// did we get the new config?
|
||||||
if (await window.waitForCacheAction(config_url, 'v1:temp') === mock_response_data2.data) {
|
if (await window.waitForCacheAction(config_url, 'v1') === mock_response_data2.data) {
|
||||||
// we did! we're done
|
// we did! we're done
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -855,7 +913,7 @@ describe('service-worker', async () => {
|
||||||
throw new Error('New config failed to cache, apparently!')
|
throw new Error('New config failed to cache, apparently!')
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should use a stale cached valid config.json file without a fetch; invalid config.json retrieved using the configured plugins should not be cached", async () => {
|
it("should use a stale cached valid config.json file without a fetch, caching it in v1:verified cache; invalid config.json retrieved using the configured plugins should not be cached", async () => {
|
||||||
|
|
||||||
// this does not change
|
// this does not change
|
||||||
var config_url = window.location.origin + 'config.json'
|
var config_url = window.location.origin + 'config.json'
|
||||||
|
@ -917,6 +975,14 @@ describe('service-worker', async () => {
|
||||||
assertSpyCalls(self.fetch, 0)
|
assertSpyCalls(self.fetch, 0)
|
||||||
assertSpyCalls(resolveConfigFetch, 1)
|
assertSpyCalls(resolveConfigFetch, 1)
|
||||||
|
|
||||||
|
// cacheConfigJSON() is called asynchronously in the Service Worker,
|
||||||
|
// if we don't make sure that the caching has completed, we will get an error.
|
||||||
|
// so we wait until config.json is cached, and use that to verify it is in fact cached
|
||||||
|
assertEquals(
|
||||||
|
await window.waitForCacheAction(window.location.origin + 'config.json', 'v1:verified'),
|
||||||
|
mock_response_data.data
|
||||||
|
);
|
||||||
|
|
||||||
// waiting for potential caching of the "new" config
|
// waiting for potential caching of the "new" config
|
||||||
for (let i=0; i<100; i++) {
|
for (let i=0; i<100; i++) {
|
||||||
// did we get the new config?
|
// did we get the new config?
|
||||||
|
@ -927,7 +993,7 @@ describe('service-worker', async () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should use a stale cached valid config.json file without a fetch; valid config.json retrieved using the configured plugins other than fetch should not be cached", async () => {
|
it("should use a stale cached valid config.json file without a fetch; invalid config.json retrieved using the configured plugins other than fetch should not be cached", async () => {
|
||||||
|
|
||||||
// this does not change
|
// this does not change
|
||||||
var config_url = window.location.origin + 'config.json'
|
var config_url = window.location.origin + 'config.json'
|
||||||
|
@ -956,7 +1022,7 @@ describe('service-worker', async () => {
|
||||||
console.log(await resp.text())
|
console.log(await resp.text())
|
||||||
})
|
})
|
||||||
|
|
||||||
// prepare the fresh invalid config request/response
|
// prepare the fresh valid config request/response
|
||||||
let mock_response_data2 = {
|
let mock_response_data2 = {
|
||||||
data: JSON.stringify({loggedComponents: ['service-worker', 'resolve-config', 'cache'], plugins: [{name: "resolve-config"}, {name: "cache"}], defaultPluginTimeout: 2000}),
|
data: JSON.stringify({loggedComponents: ['service-worker', 'resolve-config', 'cache'], plugins: [{name: "resolve-config"}, {name: "cache"}], defaultPluginTimeout: 2000}),
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
@ -459,7 +459,7 @@ let initServiceWorker = async () => {
|
||||||
let lrpcBackup = new Map(self.LibResilientPluginConstructors)
|
let lrpcBackup = new Map(self.LibResilientPluginConstructors)
|
||||||
|
|
||||||
// caches to try: temp cache, main cache
|
// caches to try: temp cache, main cache
|
||||||
let available_caches = ['v1:temp', 'v1']
|
let available_caches = ['v1', 'v1:verified']
|
||||||
|
|
||||||
// keep track
|
// keep track
|
||||||
let config_executed = false
|
let config_executed = false
|
||||||
|
@ -548,12 +548,19 @@ let initServiceWorker = async () => {
|
||||||
self.LibResilientConfig = config
|
self.LibResilientConfig = config
|
||||||
self.log('service-worker', 'config loaded.')
|
self.log('service-worker', 'config loaded.')
|
||||||
|
|
||||||
// we're good, let's cache the config if we need to
|
// we're good, let's cache the config as verified if we need to
|
||||||
// that is, if it comes from the "v1:temp" cache
|
// that is, if it comes from the "v1" cache...
|
||||||
|
if (use_cache === "v1") {
|
||||||
|
self.log('service-worker', `successfully loaded config.json; caching in cache: v1:verified`)
|
||||||
|
cacheConfigJSON(configURL, cresponse, 'v1:verified')
|
||||||
// or, was fetch()ed and valid (no caching if we're going with defaults, obviously)
|
// or, was fetch()ed and valid (no caching if we're going with defaults, obviously)
|
||||||
if ( (use_cache === "v1:temp") || ( (use_cache === undefined) && (cresponse !== false) ) ) {
|
} else if ( (use_cache === undefined) && (cresponse !== false) ) {
|
||||||
self.log('service-worker', `successfully loaded config.json; caching in cache: v1`)
|
self.log('service-worker', `successfully loaded config.json; caching in cache: v1, v1:verified`)
|
||||||
cacheConfigJSON(configURL, cresponse, 'v1')
|
// we want to cache to both, so that:
|
||||||
|
// 1. we get the extra bit of performance from using the v1 cache that is checked first
|
||||||
|
// 2. but we get the verified config already in the v1:verified cache for later
|
||||||
|
cacheConfigJSON(configURL, await cresponse.clone(), 'v1')
|
||||||
|
cacheConfigJSON(configURL, cresponse, 'v1:verified')
|
||||||
}
|
}
|
||||||
|
|
||||||
// inform
|
// inform
|
||||||
|
@ -622,7 +629,7 @@ let initServiceWorker = async () => {
|
||||||
self.log('service-worker', `valid config.json successfully retrieved through plugins; caching.`)
|
self.log('service-worker', `valid config.json successfully retrieved through plugins; caching.`)
|
||||||
// cache it, asynchronously, in the temporary cache
|
// cache it, asynchronously, in the temporary cache
|
||||||
// as the config has not been "execute-tested" yet
|
// as the config has not been "execute-tested" yet
|
||||||
cacheConfigJSON(configURL, cresponse, "v1:temp")
|
cacheConfigJSON(configURL, cresponse, "v1")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue