From f319ddfd404f3bbf5f71919d02069e41269222a7 Mon Sep 17 00:00:00 2001 From: Jeff Posnick Date: Fri, 1 Dec 2017 14:47:19 -0500 Subject: [PATCH] Revamp runtimeCaching.options to account for new plugins usage. --- .../validator/service-worker-runtime.js | 10 +++ packages/workbox-build/src/lib/errors.js | 2 + .../src/lib/runtime-caching-converter.js | 79 +++++++++++++------ .../node/entry-points/generate-sw-string.js | 26 ++++-- .../node/entry-points/generate-sw.js | 12 ++- .../node/lib/runtime-caching-converter.js | 32 +++++--- 6 files changed, 118 insertions(+), 43 deletions(-) diff --git a/infra/testing/validator/service-worker-runtime.js b/infra/testing/validator/service-worker-runtime.js index fa325a3f7..47cba26bb 100644 --- a/infra/testing/validator/service-worker-runtime.js +++ b/infra/testing/validator/service-worker-runtime.js @@ -8,7 +8,15 @@ const vm = require('vm'); function setupSpiesAndContext() { const importScripts = sinon.spy(); const workbox = { + // To make testing easier, return the name of the plugin. + cacheableResponse: { + Plugin: sinon.stub().returns('workbox.cacheableResponse.Plugin'), + }, clientsClaim: sinon.spy(), + // To make testing easier, return the name of the plugin. + expiration: { + Plugin: sinon.stub().returns('workbox.expiration.Plugin'), + }, precaching: { precacheAndRoute: sinon.spy(), suppressWarnings: sinon.spy(), @@ -35,6 +43,8 @@ function setupSpiesAndContext() { const methodsToSpies = { importScripts, + cacheableResponsePlugin: workbox.cacheableResponse.Plugin, + cacheExpirationPlugin: workbox.expiration.Plugin, cacheFirst: workbox.strategies.cacheFirst, clientsClaim: workbox.clientsClaim, precacheAndRoute: workbox.precaching.precacheAndRoute, diff --git a/packages/workbox-build/src/lib/errors.js b/packages/workbox-build/src/lib/errors.js index 5206fe260..c20abd1c5 100644 --- a/packages/workbox-build/src/lib/errors.js +++ b/packages/workbox-build/src/lib/errors.js @@ -103,4 +103,6 @@ module.exports = { 'only-regexp-routes-supported': ol`Please use a regular expression object as the urlPattern parameter. (Express-style routes are not currently supported.)`, + 'bad-runtime-caching-config': ol`An unknown configuration option was used + with runtimeCaching:`, }; diff --git a/packages/workbox-build/src/lib/runtime-caching-converter.js b/packages/workbox-build/src/lib/runtime-caching-converter.js index 44f4760b5..fb74f26ec 100644 --- a/packages/workbox-build/src/lib/runtime-caching-converter.js +++ b/packages/workbox-build/src/lib/runtime-caching-converter.js @@ -14,6 +14,8 @@ limitations under the License. */ +const ol = require('common-tags').oneLine; + const errors = require('./errors'); /** @@ -26,32 +28,63 @@ const errors = require('./errors'); * * @private */ -function getOptionsString(options) { - const cacheOptions = options.cache || {}; - // Start with a base of a few properties that need to be renamed, as well - // as copying over all the other source properties as-is. - const effectiveOptions = Object.assign({ - cacheName: cacheOptions.name, - }, options); - - // Only create the cacheExpiration object if either maxEntries or - // maxAgeSeconds is set. - if (cacheOptions.maxEntries || cacheOptions.maxAgeSeconds) { - effectiveOptions.cacheExpiration = - Object.assign(effectiveOptions.cacheExpiration || {}, { - maxEntries: cacheOptions.maxEntries, - maxAgeSeconds: cacheOptions.maxAgeSeconds, - }); +function getOptionsString(options = {}) { + let plugins = []; + if (options.plugins) { + plugins = options.plugins.map((plugin) => JSON.stringify(plugin)); + delete options.plugins; + } + + let cacheName; + if (options.cache && options.cache.name) { + cacheName = options.cache.name; + delete options.cache.name; + } + + // Allow a top-level cacheName value to override the cache.name value. + if (options.cacheName) { + cacheName = options.cacheName; + delete options.cacheName; + } + + let networkTimeoutSeconds; + if (options.networkTimeoutSeconds) { + networkTimeoutSeconds = options.networkTimeoutSeconds; + delete options.networkTimeoutSeconds; } - // Everything should be copied to the corresponding new option names at this - // point, so set the old-style `cache` property to undefined so that it - // doesn't show up in the JSON output. - effectiveOptions.cache = undefined; + const pluginsMapping = { + backgroundSync: 'workbox.backgroundSync.Plugin', + broadcastCacheUpdate: 'workbox.broadcastCacheUpdate.Plugin', + cache: 'workbox.expiration.Plugin', + cacheExpiration: 'workbox.expiration.Plugin', + cacheableResponse: 'workbox.cacheableResponse.Plugin', + }; - // JSON.stringify() will automatically omit any properties that are set to - // undefined values. - return JSON.stringify(effectiveOptions, null, 2); + for (const [pluginName, pluginConfig] of Object.entries(options)) { + // Ensure that we have some valid configuration to pass to Plugin(). + if (Object.keys(pluginConfig).length === 0) { + continue; + } + + const pluginString = pluginsMapping[pluginName]; + if (!pluginString) { + throw new Error(`${errors['bad-runtime-caching-config']} ${pluginName}`); + } + + plugins.push(`${pluginString}(${JSON.stringify(pluginConfig)})`); + } + + if (networkTimeoutSeconds || cacheName || plugins.length > 0) { + return ol`{ + ${networkTimeoutSeconds ? ('networkTimeoutSeconds: ' + + JSON.stringify(networkTimeoutSeconds)) + ',' : ''} + ${cacheName ? ('cacheName: ' + JSON.stringify(cacheName)) + ',' : ''} + plugins: [${plugins.join(', ')}] + }`; + } else { + return ''; + } } module.exports = (runtimeCaching) => { diff --git a/test/workbox-build/node/entry-points/generate-sw-string.js b/test/workbox-build/node/entry-points/generate-sw-string.js index 468c0d797..1cda7a3fd 100644 --- a/test/workbox-build/node/entry-points/generate-sw-string.js +++ b/test/workbox-build/node/entry-points/generate-sw-string.js @@ -293,7 +293,7 @@ describe(`[workbox-build] entry-points/generate-sw-string.js (End to End)`, func const swCode = await generateSWString(options); await validateServiceWorkerRuntime({swCode, expectedMethodCalls: { - [STRING_HANDLER]: [[{}]], + [STRING_HANDLER]: [[]], importScripts: [[...DEFAULT_IMPORT_SCRIPTS]], suppressWarnings: [[]], precacheAndRoute: [[[], {}]], @@ -311,7 +311,7 @@ describe(`[workbox-build] entry-points/generate-sw-string.js (End to End)`, func const swCode = await generateSWString(options); await validateServiceWorkerRuntime({swCode, expectedMethodCalls: { - [STRING_HANDLER]: [[{}]], + [STRING_HANDLER]: [[]], importScripts: [[...DEFAULT_IMPORT_SCRIPTS]], suppressWarnings: [[]], precacheAndRoute: [[[], {}]], @@ -332,7 +332,7 @@ describe(`[workbox-build] entry-points/generate-sw-string.js (End to End)`, func const swCode = await generateSWString(options); await validateServiceWorkerRuntime({swCode, expectedMethodCalls: { - [STRING_HANDLER]: [[{}], [{}]], + [STRING_HANDLER]: [[], []], importScripts: [[...DEFAULT_IMPORT_SCRIPTS]], suppressWarnings: [[]], precacheAndRoute: [[[], {}]], @@ -385,7 +385,15 @@ describe(`[workbox-build] entry-points/generate-sw-string.js (End to End)`, func const swCode = await generateSWString(options); await validateServiceWorkerRuntime({swCode, expectedMethodCalls: { - [STRING_HANDLER]: [[runtimeCachingOptions]], + [STRING_HANDLER]: [[{ + cacheName: runtimeCachingOptions.cacheName, + plugins: runtimeCachingOptions.plugins.concat([ + 'workbox.expiration.Plugin', + 'workbox.cacheableResponse.Plugin', + ]), + }]], + cacheableResponsePlugin: [[runtimeCachingOptions.cacheableResponse]], + cacheExpirationPlugin: [[runtimeCachingOptions.cacheExpiration]], importScripts: [[...DEFAULT_IMPORT_SCRIPTS]], suppressWarnings: [[]], precacheAndRoute: [[[], {}]], @@ -424,7 +432,15 @@ describe(`[workbox-build] entry-points/generate-sw-string.js (End to End)`, func const swCode = await generateSWString(options); await validateServiceWorkerRuntime({swCode, expectedMethodCalls: { - [STRING_HANDLER]: [[firstRuntimeCachingOptions], [secondRuntimeCachingOptions]], + [STRING_HANDLER]: [[{ + cacheName: firstRuntimeCachingOptions.cacheName, + plugins: ['workbox.expiration.Plugin'], + }], [{ + cacheName: secondRuntimeCachingOptions.cacheName, + plugins: ['workbox.cacheableResponse.Plugin'], + }]], + cacheableResponsePlugin: [[secondRuntimeCachingOptions.cacheableResponse]], + cacheExpirationPlugin: [[firstRuntimeCachingOptions.cacheExpiration]], importScripts: [[...DEFAULT_IMPORT_SCRIPTS]], suppressWarnings: [[]], precacheAndRoute: [[[], {}]], diff --git a/test/workbox-build/node/entry-points/generate-sw.js b/test/workbox-build/node/entry-points/generate-sw.js index ee4028977..7e8062f67 100644 --- a/test/workbox-build/node/entry-points/generate-sw.js +++ b/test/workbox-build/node/entry-points/generate-sw.js @@ -444,7 +444,7 @@ describe(`[workbox-build] entry-points/generate-sw.js (End to End)`, function() expect(count).to.eql(6); expect(size).to.eql(2421); await validateServiceWorkerRuntime({swFile: swDest, expectedMethodCalls: { - [STRING_HANDLER]: [[{}]], + [STRING_HANDLER]: [[]], importScripts: [[WORKBOX_SW_CDN_URL]], suppressWarnings: [[]], precacheAndRoute: [[[{ @@ -507,7 +507,15 @@ describe(`[workbox-build] entry-points/generate-sw.js (End to End)`, function() expect(count).to.eql(6); expect(size).to.eql(2421); await validateServiceWorkerRuntime({swFile: swDest, expectedMethodCalls: { - [STRING_HANDLER]: [[firstRuntimeCachingOptions], [secondRuntimeCachingOptions]], + [STRING_HANDLER]: [[{ + cacheName: firstRuntimeCachingOptions.cacheName, + plugins: ['workbox.expiration.Plugin'], + }], [{ + cacheName: secondRuntimeCachingOptions.cacheName, + plugins: ['workbox.cacheableResponse.Plugin'], + }]], + cacheableResponsePlugin: [[secondRuntimeCachingOptions.cacheableResponse]], + cacheExpirationPlugin: [[firstRuntimeCachingOptions.cacheExpiration]], importScripts: [[WORKBOX_SW_CDN_URL]], suppressWarnings: [[]], precacheAndRoute: [[[{ diff --git a/test/workbox-build/node/lib/runtime-caching-converter.js b/test/workbox-build/node/lib/runtime-caching-converter.js index 58c1f2377..c83e9e365 100644 --- a/test/workbox-build/node/lib/runtime-caching-converter.js +++ b/test/workbox-build/node/lib/runtime-caching-converter.js @@ -16,6 +16,12 @@ function validate(runtimeCachingOptions, convertedOptions) { const globalScope = { workbox: { + cacheableResponse: { + Plugin: sinon.spy(), + }, + expiration: { + Plugin: sinon.spy(), + }, routing: { registerRoute: sinon.spy(), }, @@ -52,28 +58,28 @@ function validate(runtimeCachingOptions, convertedOptions) { const strategiesCall = globalScope.workbox.strategies[runtimeCachingOption.handler].firstCall; const strategiesOptions = strategiesCall.args[0]; - const expectedOptions = {}; if (runtimeCachingOption.options) { - if (runtimeCachingOption.options.networkTimeoutSeconds) { - expectedOptions.networkTimeoutSeconds = runtimeCachingOption.options.networkTimeoutSeconds; + const options = runtimeCachingOption.options; + if (options.networkTimeoutSeconds) { + expect(options.networkTimeoutSeconds) + .to.eql(strategiesOptions.networkTimeoutSeconds); } - if (runtimeCachingOption.options.cache) { - if (runtimeCachingOption.options.cache.name) { - expectedOptions.cacheName = runtimeCachingOption.options.cache.name; + if (options.cache) { + if (options.cache.name) { + expect(strategiesOptions.cacheName).to.eql(options.cache.name); + delete options.cache.name; } - if (runtimeCachingOption.options.cache.maxEntries || runtimeCachingOption.options.cache.maxAgeSeconds) { - expectedOptions.cacheExpiration = Object.assign({}, runtimeCachingOption.options.cache); - delete expectedOptions.cacheExpiration.name; + + if (Object.keys(options.cache).length > 0) { + expect(globalScope.workbox.expiration.Plugin.calledWith(options.cache)).to.be.true; } } - if (runtimeCachingOption.options.cacheableResponse) { - expectedOptions.cacheableResponse = runtimeCachingOption.options.cacheableResponse; + if (options.cacheableResponse) { + expect(globalScope.workbox.cacheableResponse.Plugin.calledWith(options.cacheableResponse)).to.be.true; } } - - expect(strategiesOptions).to.eql(expectedOptions); }); }