From d2aa96b1884ae6fd1ae05aaf59034534a5c93c22 Mon Sep 17 00:00:00 2001 From: Philip Walton Date: Fri, 5 Oct 2018 10:35:15 -0700 Subject: [PATCH 1/2] Decouple Router~handleRequest from events --- packages/workbox-build/package-lock.json | 2 +- .../workbox-google-analytics/initialize.mjs | 7 +- packages/workbox-routing/NavigationRoute.mjs | 9 +- packages/workbox-routing/Router.mjs | 97 +- packages/workbox-routing/_default.mjs | 3 +- packages/workbox-routing/_types.mjs | 54 +- packages/workbox-strategies/CacheFirst.mjs | 17 +- packages/workbox-strategies/CacheOnly.mjs | 17 +- packages/workbox-strategies/NetworkFirst.mjs | 17 +- packages/workbox-strategies/NetworkOnly.mjs | 17 +- .../StaleWhileRevalidate.mjs | 18 +- .../workbox-webpack-plugin/package-lock.json | 971 +++++++----------- .../node/test-NavigationRoute.mjs | 55 +- test/workbox-routing/node/test-Router.mjs | 283 ++++- test/workbox-routing/node/test-default.mjs | 191 ++-- .../node/test-UsageWithRouter.mjs | 7 +- 16 files changed, 873 insertions(+), 892 deletions(-) diff --git a/packages/workbox-build/package-lock.json b/packages/workbox-build/package-lock.json index e10205c9e..4d602aa37 100644 --- a/packages/workbox-build/package-lock.json +++ b/packages/workbox-build/package-lock.json @@ -1,6 +1,6 @@ { "name": "workbox-build", - "version": "3.6.1", + "version": "3.6.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/workbox-google-analytics/initialize.mjs b/packages/workbox-google-analytics/initialize.mjs index 9615a66fa..d06f03498 100644 --- a/packages/workbox-google-analytics/initialize.mjs +++ b/packages/workbox-google-analytics/initialize.mjs @@ -192,10 +192,11 @@ const initialize = (options = {}) => { router.registerRoute(route); } - self.addEventListener('fetch', (evt) => { - const responsePromise = router.handleRequest(evt); + self.addEventListener('fetch', (event) => { + const {request} = event; + const responsePromise = router.handleRequest({request, event}); if (responsePromise) { - evt.respondWith(responsePromise); + event.respondWith(responsePromise); } }); }; diff --git a/packages/workbox-routing/NavigationRoute.mjs b/packages/workbox-routing/NavigationRoute.mjs index 19e75c3c5..c2413d20f 100644 --- a/packages/workbox-routing/NavigationRoute.mjs +++ b/packages/workbox-routing/NavigationRoute.mjs @@ -62,7 +62,7 @@ class NavigationRoute extends Route { }); } - super((...args) => this._match(...args), handler); + super((options) => this._match(options), handler); this._whitelist = whitelist; this._blacklist = blacklist; @@ -72,14 +72,15 @@ class NavigationRoute extends Route { * Routes match handler. * * @param {Object} options - * @param {FetchEvent} options.event * @param {URL} options.url + * @param {Request} options.request + * @param {Event} [options.event] * @return {boolean} * * @private */ - _match({event, url}) { - if (event.request.mode !== 'navigate') { + _match({url, request}) { + if (request.mode !== 'navigate') { return false; } diff --git a/packages/workbox-routing/Router.mjs b/packages/workbox-routing/Router.mjs index 0d2dace42..63f079f49 100644 --- a/packages/workbox-routing/Router.mjs +++ b/packages/workbox-routing/Router.mjs @@ -45,23 +45,26 @@ class Router { * Apply the routing rules to a FetchEvent object to get a Response from an * appropriate Route's handler. * - * @param {FetchEvent} event The event from a service worker's 'fetch' event - * listener. + * @param {Object} options + * @param {Request} options.request The request to handle (this is usually + * from a fetch event, but it does not have to be). + * @param {FetchEvent} [options.event] The event that triggered the request, + * if applicable. * @return {Promise|undefined} A promise is returned if a - * registered route can handle the FetchEvent's request. If there is no - * matching route and there's no `defaultHandler`, `undefined` is returned. + * registered route can handle the request. If there is no matching + * route and there's no `defaultHandler`, `undefined` is returned. */ - handleRequest(event) { + handleRequest({request, event}) { if (process.env.NODE_ENV !== 'production') { - assert.isInstance(event, FetchEvent, { + assert.isInstance(request, Request, { moduleName: 'workbox-routing', className: 'Router', funcName: 'handleRequest', - paramName: 'event', + paramName: 'options.request', }); } - const url = new URL(event.request.url); + const url = new URL(request.url, location); if (!url.protocol.startsWith('http')) { if (process.env.NODE_ENV !== 'production') { logger.debug( @@ -70,15 +73,10 @@ class Router { return; } - let route = null; - let handler = null; - let params = null; - let debugMessages = []; + let {params, route} = this.findMatchingRoute({url, request, event}); + let handler = route && route.handler; - const result = this._findHandlerAndParams(event, url); - handler = result.handler; - params = result.params; - route = result.route; + let debugMessages = []; if (process.env.NODE_ENV !== 'production') { if (handler) { debugMessages.push([ @@ -130,7 +128,7 @@ class Router { // The Request and Response objects contains a great deal of information, // hide it under a group in case developers want to see it. logger.groupCollapsed(`View request details here.`); - logger.unprefixed.log(event.request); + logger.unprefixed.log(request); logger.groupEnd(); logger.groupEnd(); @@ -140,7 +138,7 @@ class Router { // error. It should still callback to the catch handler. let responsePromise; try { - responsePromise = handler.handle({url, event, params}); + responsePromise = handler.handle({url, request, event, params}); } catch (err) { responsePromise = Promise.reject(err); } @@ -164,43 +162,54 @@ class Router { } /** - * Checks the incoming `event.request` against the registered routes, and if - * there's a match, returns the corresponding handler along with any params - * generated by the match. + * Checks a request and URL (and optionally an event) against the list of + * registered routes, and if there's a match, returns the corresponding + * route along with any params generated by the match. * - * @param {FetchEvent} event - * @param {URL} url - * @return {Object} Returns an object with `handler` and `params` properties. - * They are populated if a matching route was found or `undefined` otherwise. - * - * @private + * @param {Object} options + * @param {URL} options.url + * @param {Request} options.request The request to match. + * @param {FetchEvent} [options.event] The corresponding event (unless N/A). + * @return {Object} An object with `route` and `params` properties. + * They are populated if a matching route was found or `undefined` + * otherwise. */ - _findHandlerAndParams(event, url) { - const routes = this._routes.get(event.request.method) || []; + findMatchingRoute({url, request, event}) { + if (process.env.NODE_ENV !== 'production') { + assert.isInstance(url, URL, { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'findMatchingRoute', + paramName: 'options.url', + }); + assert.isInstance(request, Request, { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'findMatchingRoute', + paramName: 'options.request', + }); + } + + const routes = this._routes.get(request.method) || []; for (const route of routes) { - let matchResult = route.match({url, event}); + let params; + let matchResult = route.match({url, request, event}); if (matchResult) { - if (Array.isArray(matchResult) && matchResult.length === 0) { + if (Array.isArray(matchResult) && matchResult.length > 0) { // Instead of passing an empty array in as params, use undefined. - matchResult = undefined; + params = matchResult; } else if ((matchResult.constructor === Object && - Object.keys(matchResult).length === 0) || matchResult === true) { + Object.keys(matchResult).length > 0)) { // Instead of passing an empty object in as params, use undefined. - matchResult = undefined; + params = matchResult; } - // Break out of the loop and return the appropriate values as soon as - // we have a match. - return { - route, - params: matchResult, - handler: route.handler, - }; + // Return early if have a match. + return {route, params}; } } - - // If we didn't have a match, then return undefined values. - return {handler: undefined, params: undefined}; + // If no match was found above, return and empty object. + return {}; } /** diff --git a/packages/workbox-routing/_default.mjs b/packages/workbox-routing/_default.mjs index be62619eb..23bd9a97f 100644 --- a/packages/workbox-routing/_default.mjs +++ b/packages/workbox-routing/_default.mjs @@ -191,7 +191,8 @@ const router = new DefaultRouter(); // By default, register a fetch event listener that will respond to a request // only if there's a matching route. self.addEventListener('fetch', (event) => { - const responsePromise = router.handleRequest(event); + const request = event.request; + const responsePromise = router.handleRequest({request, event}); if (responsePromise) { event.respondWith(responsePromise); } diff --git a/packages/workbox-routing/_types.mjs b/packages/workbox-routing/_types.mjs index ddb85af2f..1bf885068 100644 --- a/packages/workbox-routing/_types.mjs +++ b/packages/workbox-routing/_types.mjs @@ -9,45 +9,49 @@ import './_version.mjs'; /** - * The "match" callback is used to determine if a `Route` should handle a - * service worker's `fetch` event. Returning a truthy value means - * this `Route` will handle and respond to the event. - * - * Return `null` if this Route shouldn't match against the `fetch` event. - * - * Any truthy value returned by this callback will be passed to the - * Route's - * [handler callback]{@link workbox.routing.Route~handlerCallback}. + * The "match" callback is used to determine if a `Route` should apply for a + * particular URL. When matching occurs in response to a fetch event from the + * client, the `event` and `request` objects are supplied in addition to the + * URL. However, since the match callback can be invoked outside of a fetch + * event, matching logic should not assume the `event` or `request` objects + * will always be available (unlike URL, which is always available). + * If the match callback returns a truthy value, the matching route's + * [handler callback]{@link workbox.routing.Route~handlerCallback} will be + * invoked immediately. If the value returned is a non-empty array or object, + * that value will be set on the handler's `context.params` argument. * * @callback Route~matchCallback * @param {Object} context * @param {URL} context.url The request's URL. - * @param {FetchEvent} context.event The service worker`s `fetch` - * event. - * @return {Object|null} To signify a match, return anything other than `null`. - * Return `null` if the route shouldn't match. - * [handler]{@link workbox.routing.Route~handlerCallback}. + * @param {FetchEvent} [context.request] The corresponding request, + * if available. + * @param {FetchEvent} [context.event] The corresponding event that triggered + * the request, if available. + * @return {*} To signify a match, return a truthy value. * * @memberof workbox.routing */ /** - * The "handler" callback is called when a service worker's `fetch` event - * has been matched by a `Route`. This callback should return a Promise that - * resolves with a `Response`. + * The "handler" callback is invoked whenever a `Router` matches a URL to a + * `Route` via its [match]{@link workbox.routing.Route~handlerCallback} + * callback. This callback should return a Promise that resolves with a + * `Response`. * - * If a value is returned by the + * If a non-empty array or object is returned by the * [match callback]{@link workbox.routing.Route~matchCallback} it - * will be passed in as the `context.params` argument. + * will be passed in as the handler's `context.params` argument. * * @callback Route~handlerCallback * @param {Object} context - * @param {URL} context.url The request's URL. - * @param {FetchEvent} context.event The service worker's `fetch` - * event. - * @param {Object} [context.params] Parameters returned by the Route's - * [match callback]{@link workbox.routing.Route~matchCallback} function. - * This will be undefined if nothing was returned. + * @param {URL} context.url The URL that matched. + * @param {FetchEvent} [context.request] The corresponding request, + * if available. + * @param {FetchEvent} [context.event] The corresponding event that triggered + * the request, if available. + * @param {Object} [context.params] Array or Object parameters returned by the + * Route's [match callback]{@link workbox.routing.Route~matchCallback}. + * This will be undefined if an empty array or object were returned. * @return {Promise} The response that will fulfill the request. * * @memberof workbox.routing diff --git a/packages/workbox-strategies/CacheFirst.mjs b/packages/workbox-strategies/CacheFirst.mjs index 326e84135..96bd7b594 100644 --- a/packages/workbox-strategies/CacheFirst.mjs +++ b/packages/workbox-strategies/CacheFirst.mjs @@ -56,23 +56,14 @@ class CacheFirst { * [Workbox Router]{@link workbox.routing.Router}. * * @param {Object} options - * @param {FetchEvent} options.event The fetch event to run this strategy - * against. + * @param {Request} options.request The request to run this strategy for. + * @param {Event} [options.event] The event that triggered the request. * @return {Promise} */ - async handle({event}) { - if (process.env.NODE_ENV !== 'production') { - assert.isInstance(event, FetchEvent, { - moduleName: 'workbox-strategies', - className: 'CacheFirst', - funcName: 'handle', - paramName: 'event', - }); - } - + async handle({event, request}) { return this.makeRequest({ event, - request: event.request, + request: request || event.request, }); } diff --git a/packages/workbox-strategies/CacheOnly.mjs b/packages/workbox-strategies/CacheOnly.mjs index 65476c391..1eeff3520 100644 --- a/packages/workbox-strategies/CacheOnly.mjs +++ b/packages/workbox-strategies/CacheOnly.mjs @@ -50,23 +50,14 @@ class CacheOnly { * [Workbox Router]{@link workbox.routing.Router}. * * @param {Object} options - * @param {FetchEvent} options.event The fetch event to run this strategy - * against. + * @param {Request} options.request The request to run this strategy for. + * @param {Event} [options.event] The event that triggered the request. * @return {Promise} */ - async handle({event}) { - if (process.env.NODE_ENV !== 'production') { - assert.isInstance(event, FetchEvent, { - moduleName: 'workbox-strategies', - className: 'CacheOnly', - funcName: 'handle', - paramName: 'event', - }); - } - + async handle({event, request}) { return this.makeRequest({ event, - request: event.request, + request: request || event.request, }); } diff --git a/packages/workbox-strategies/NetworkFirst.mjs b/packages/workbox-strategies/NetworkFirst.mjs index 14e6e82c8..d60522659 100644 --- a/packages/workbox-strategies/NetworkFirst.mjs +++ b/packages/workbox-strategies/NetworkFirst.mjs @@ -87,23 +87,14 @@ class NetworkFirst { * [Workbox Router]{@link workbox.routing.Router}. * * @param {Object} options - * @param {FetchEvent} options.event The fetch event to run this strategy - * against. + * @param {Request} options.request The request to run this strategy for. + * @param {Event} [options.event] The event that triggered the request. * @return {Promise} */ - async handle({event}) { - if (process.env.NODE_ENV !== 'production') { - assert.isInstance(event, FetchEvent, { - moduleName: 'workbox-strategies', - className: 'NetworkFirst', - funcName: 'handle', - paramName: 'event', - }); - } - + async handle({event, request}) { return this.makeRequest({ event, - request: event.request, + request: request || event.request, }); } diff --git a/packages/workbox-strategies/NetworkOnly.mjs b/packages/workbox-strategies/NetworkOnly.mjs index dfe7ccc04..6ab5c80df 100644 --- a/packages/workbox-strategies/NetworkOnly.mjs +++ b/packages/workbox-strategies/NetworkOnly.mjs @@ -51,23 +51,14 @@ class NetworkOnly { * [Workbox Router]{@link workbox.routing.Router}. * * @param {Object} options - * @param {FetchEvent} options.event The fetch event to run this strategy - * against. + * @param {Request} options.request The request to run this strategy for. + * @param {Event} [options.event] The event that triggered the request. * @return {Promise} */ - async handle({event}) { - if (process.env.NODE_ENV !== 'production') { - assert.isInstance(event, FetchEvent, { - moduleName: 'workbox-strategies', - className: 'NetworkOnly', - funcName: 'handle', - paramName: 'event', - }); - } - + async handle({event, request}) { return this.makeRequest({ event, - request: event.request, + request: request || event.request, }); } diff --git a/packages/workbox-strategies/StaleWhileRevalidate.mjs b/packages/workbox-strategies/StaleWhileRevalidate.mjs index 02dff8c2f..fb4fc8ab4 100644 --- a/packages/workbox-strategies/StaleWhileRevalidate.mjs +++ b/packages/workbox-strategies/StaleWhileRevalidate.mjs @@ -75,26 +75,16 @@ class StaleWhileRevalidate { * [Workbox Router]{@link workbox.routing.Router}. * * @param {Object} options - * @param {FetchEvent} options.event The fetch event to run this strategy - * against. + * @param {Request} options.request The request to run this strategy for. + * @param {Event} [options.event] The event that triggered the request. * @return {Promise} */ - async handle({event}) { - if (process.env.NODE_ENV !== 'production') { - assert.isInstance(event, FetchEvent, { - moduleName: 'workbox-strategies', - className: 'StaleWhileRevalidate', - funcName: 'handle', - paramName: 'event', - }); - } - + async handle({event, request}) { return this.makeRequest({ event, - request: event.request, + request: request || event.request, }); } - /** * This method can be used to perform a make a standalone request outside the * context of the [Workbox Router]{@link workbox.routing.Router}. diff --git a/packages/workbox-webpack-plugin/package-lock.json b/packages/workbox-webpack-plugin/package-lock.json index c3f7cc224..e91adb4c6 100644 --- a/packages/workbox-webpack-plugin/package-lock.json +++ b/packages/workbox-webpack-plugin/package-lock.json @@ -10,15 +10,165 @@ "integrity": "sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg==", "requires": { "regenerator-runtime": "^0.12.0" + } + }, + "babel-extract-comments": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz", + "integrity": "sha512-qWWzi4TlddohA91bFwgt6zO/J0X+io7Qp184Fw0m2JYRSTZnJbFR8+07KmzudHCZgOiKRCrjhylwv9Xd8gfhVQ==", + "requires": { + "babylon": "^6.18.0" + } + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" }, "dependencies": { "regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" } } }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "get-own-enumerable-property-symbols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz", + "integrity": "sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug==" + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "is-obj": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + }, + "isemail": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.3.tgz", + "integrity": "sha512-5xbsG5wYADIcB+mfLsd+nst1V/D+I7EU7LEZPo2GOIMu4JzfcRs5yQoypP4avA7QtUqgxYLKBYNv4IdzBmbhdw==", + "requires": { + "punycode": "2.x.x" + } + }, + "joi": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-11.4.0.tgz", + "integrity": "sha512-O7Uw+w/zEWgbL6OcHbyACKSj0PkQeUgmehdoXVSxt92QFCq4+1390Rwh5moI2K/OgC7D8RHRZqHZxT2husMJHA==", + "requires": { + "hoek": "4.x.x", + "isemail": "3.x.x", + "topo": "2.x.x" + } + }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", @@ -27,15 +177,131 @@ "jsonify": "~0.0.0" } }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" + }, + "stringify-object": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.2.tgz", + "integrity": "sha512-O696NF21oLiDy8PhpWu8AEqoZHw++QW6mUv0UvKZe8gWSdSvMXkiLufK7OmnP27Dro4GU5kb9U7JIO0mBuCRQg==", + "requires": { + "get-own-enumerable-property-symbols": "^2.0.1", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-comments": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-1.0.2.tgz", + "integrity": "sha512-kL97alc47hoyIQSV165tTt9rG5dn4w1dNnBhOQ3bOU1Nc1hel09jnXANaHJ7vzHLd4Ju8kseDGzlev96pghLFw==", + "requires": { + "babel-extract-comments": "^1.0.0", + "babel-plugin-transform-object-rest-spread": "^6.26.0" + } + }, + "topo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "requires": { + "hoek": "4.x.x" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "workbox-background-sync": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-3.6.2.tgz", + "integrity": "sha512-K34wiTM50gSpzJUuRmGRqbd91IpJj0vwMBSHCpixw/jiTg10uytSfnixMNGzeTK0i7LTd/bkA8ptx4HXP+MliA==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-broadcast-cache-update": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-broadcast-cache-update/-/workbox-broadcast-cache-update-3.6.2.tgz", + "integrity": "sha512-wmN3k94Kv3/lYOqRy08ymp8RyTPCpgLI9UW/BrQ1XuZHJyFejWnBoy/pCKk9mRZYZX7EyvnzA4O1PLILgLC43g==", + "requires": { + "workbox-core": "^3.6.2" + } + }, "workbox-build": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-3.6.2.tgz", + "integrity": "sha512-PYw4SRbfbUE/+DDhb89zbspDLBi86hpra+l6SsX7yBqCthw4sHyH8IIQw5MMHI04HPV5ZDYru8A5SNLXVDGMcg==", "requires": { - "@babel/runtime": "^7.0.0", + "babel-runtime": "^6.26.0", "common-tags": "^1.4.0", "fs-extra": "^4.0.2", "glob": "^7.1.2", @@ -57,614 +323,97 @@ "workbox-strategies": "^3.6.2", "workbox-streams": "^3.6.2", "workbox-sw": "^3.6.2" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.0.0", - "bundled": true, - "requires": { - "regenerator-runtime": "^0.12.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.12.1", - "bundled": true - } - } - }, - "babel-extract-comments": { - "version": "1.0.0", - "bundled": true, - "requires": { - "babylon": "^6.18.0" - } - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "bundled": true - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "bundled": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "bundled": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babylon": { - "version": "6.18.0", - "bundled": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "common-tags": { - "version": "1.8.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "core-js": { - "version": "2.5.7", - "bundled": true - }, - "fs-extra": { - "version": "4.0.3", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "get-own-enumerable-property-symbols": { - "version": "2.0.1", - "bundled": true - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true - }, - "hoek": { - "version": "4.2.1", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "is-obj": { - "version": "1.0.1", - "bundled": true - }, - "is-regexp": { - "version": "1.0.0", - "bundled": true - }, - "isemail": { - "version": "3.1.3", - "bundled": true, - "requires": { - "punycode": "2.x.x" - } - }, - "joi": { - "version": "11.4.0", - "bundled": true, - "requires": { - "hoek": "4.x.x", - "isemail": "3.x.x", - "topo": "2.x.x" - } - }, - "jsonfile": { - "version": "4.0.0", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "bundled": true - }, - "lodash.template": { - "version": "4.4.0", - "bundled": true, - "requires": { - "lodash._reinterpolate": "~3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "bundled": true, - "requires": { - "lodash._reinterpolate": "~3.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "pretty-bytes": { - "version": "4.0.2", - "bundled": true - }, - "punycode": { - "version": "2.1.1", - "bundled": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "bundled": true - }, - "stringify-object": { - "version": "3.2.2", - "bundled": true, - "requires": { - "get-own-enumerable-property-symbols": "^2.0.1", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, - "strip-comments": { - "version": "1.0.2", - "bundled": true, - "requires": { - "babel-extract-comments": "^1.0.0", - "babel-plugin-transform-object-rest-spread": "^6.26.0" - } - }, - "topo": { - "version": "2.0.2", - "bundled": true, - "requires": { - "hoek": "4.x.x" - } - }, - "universalify": { - "version": "0.1.2", - "bundled": true - }, - "workbox-background-sync": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-broadcast-cache-update": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-cache-expiration": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-cacheable-response": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - }, - "workbox-google-analytics": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-background-sync": "^3.6.2", - "workbox-core": "^3.6.2", - "workbox-routing": "^3.6.2", - "workbox-strategies": "^3.6.2" - }, - "dependencies": { - "workbox-background-sync": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - }, - "workbox-routing": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "@arr/every": { - "version": "1.0.0", - "bundled": true - }, - "@arr/filter": { - "version": "1.0.0", - "bundled": true - }, - "matchit": { - "version": "1.0.0", - "bundled": true, - "requires": { - "@arr/every": "^1.0.0", - "@arr/filter": "^1.0.0" - } - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-strategies": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-cache-expiration": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-cacheable-response": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - } - } - }, - "workbox-navigation-preload": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-precaching": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - }, - "workbox-routing": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "@arr/every": { - "version": "1.0.0", - "bundled": true - }, - "@arr/filter": { - "version": "1.0.0", - "bundled": true - }, - "matchit": { - "version": "1.0.0", - "bundled": true, - "requires": { - "@arr/every": "^1.0.0", - "@arr/filter": "^1.0.0" - } - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - } - } - }, - "workbox-range-requests": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-routing": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "@arr/every": { - "version": "1.0.0", - "bundled": true - }, - "@arr/filter": { - "version": "1.0.0", - "bundled": true - }, - "matchit": { - "version": "1.0.0", - "bundled": true, - "requires": { - "@arr/every": "^1.0.0", - "@arr/filter": "^1.0.0" - } - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-strategies": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-cache-expiration": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": {} - }, - "workbox-cacheable-response": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": {} - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-streams": { - "version": "3.6.2", - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-sw": { - "version": "3.6.2", - "bundled": true, - "dependencies": { - "workbox-broadcast-cache-update": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-cache-expiration": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-cacheable-response": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - }, - "workbox-precaching": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "workbox-core": { - "version": "3.6.2", - "bundled": true - }, - "workbox-routing": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": {} - } - } - }, - "workbox-routing": { - "bundled": true, - "requires": { - "workbox-core": "^3.6.2" - }, - "dependencies": { - "@arr/every": { - "version": "1.0.0", - "bundled": true - }, - "@arr/filter": { - "version": "1.0.0", - "bundled": true - }, - "matchit": { - "version": "1.0.0", - "bundled": true, - "requires": { - "@arr/every": "^1.0.0", - "@arr/filter": "^1.0.0" - } - }, - "workbox-core": { - "version": "3.6.2", - "bundled": true - } - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - } } + }, + "workbox-cache-expiration": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-cache-expiration/-/workbox-cache-expiration-3.6.2.tgz", + "integrity": "sha512-LJLYfqG7ItYucppun5I92fcN21kDZFEVqZ8uAOz5t8piOsHh1ThAiiLv/4ubG/d7CUgqW/1bmcX6DM4xqackzg==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-cacheable-response": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-3.6.2.tgz", + "integrity": "sha512-WvICMN3SfEi48C96KEfkLDIqnU0rkQeajdLjYXuzbUID3EX31gzUVlIbqQGrc+9xtIlvxs2+ZoaTR3Rjdtbh/Q==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-core": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-3.6.2.tgz", + "integrity": "sha512-5T5WBFy5nMm7zx+P2RwdzEVu5CK++bqwiEsGF+INwUxsOKpH9oXUlUdJE/KfUaMsKcZtHXEb74mMB6vvE88a/w==" + }, + "workbox-google-analytics": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-3.6.2.tgz", + "integrity": "sha512-NXBbo9xyHQvkHcvYoZkNJw7DB53dJUnmusKdSPg138A6HGt2ilycwTUuXNDWpkXXp3YHxcslrBMdptolwbzidg==", + "requires": { + "workbox-background-sync": "^3.6.2", + "workbox-core": "^3.6.2", + "workbox-routing": "^3.6.2", + "workbox-strategies": "^3.6.2" + } + }, + "workbox-navigation-preload": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-3.6.2.tgz", + "integrity": "sha512-fN/CWSFZiySQH/OEJQsIizAM4ob6IgZVDfWvA58jAwiyI5QziqfFtL/EiHHNvmIa5jTdcoXfuNNv1WUdpRV18A==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-precaching": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-3.6.2.tgz", + "integrity": "sha512-oQmBfvCzCUfLcwTokfbVhIIcyNS9aF692EhdqAz/SB2e40ehUgcctAUhQOezsedZFqBBnwphJQUhs+hD3mu72A==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-range-requests": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-3.6.2.tgz", + "integrity": "sha512-y1MFB97ydbT8PxBiihndLzG66sNIRzL0lkyoeaWPGfaPGWTP8ghMe4SkGqqdiY+E54rhd7lTdb7RZdv3Av1lTg==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-routing": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-3.6.2.tgz", + "integrity": "sha512-rhoH1AlETUfffJXJSlc0/T5rBB6vatxpD/8IZgxgHByBnYokV+/HxO7It6wBbxIzdO31UrWVroYm0iVa5sO7Jw==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-strategies": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-3.6.2.tgz", + "integrity": "sha512-4jAyL3n0Fl1BLB3QDUoUoBTzBsE8FwH0K7He1JvLzFiDtYp1ewcKjDecYCNZyTsFVgaLL7WClEQCOKSBquBfOg==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-streams": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-3.6.2.tgz", + "integrity": "sha512-lKTh5fOAf+Qae7GHYXZve40ZXULCf9kxlkrWjTXqGcTh6cxeibuWl6Mnt4aroChNB8jOEbHfGOy0iaG0R159ew==", + "requires": { + "workbox-core": "^3.6.2" + } + }, + "workbox-sw": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-3.6.2.tgz", + "integrity": "sha512-EwQZaeGB+tEogABMj9FaEDuszaSBQgjAUEqTFiizZWSU8owZrt0BFfi69TMAhILOfWLFh3aASMzQnPMDY7id4w==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } } diff --git a/test/workbox-routing/node/test-NavigationRoute.mjs b/test/workbox-routing/node/test-NavigationRoute.mjs index 8fccbcdd5..147afd569 100644 --- a/test/workbox-routing/node/test-NavigationRoute.mjs +++ b/test/workbox-routing/node/test-NavigationRoute.mjs @@ -11,7 +11,6 @@ import expectError from '../../../infra/testing/expectError.js'; import {devOnly} from '../../../infra/testing/env-it'; import {NavigationRoute} from '../../../packages/workbox-routing/NavigationRoute.mjs'; -const match = () => {}; const handler = { handle: () => {}, }; @@ -45,7 +44,7 @@ describe(`[workbox-routing] NavigationRoute`, function() { }); it(`should not throw when called with valid handler in dev`, function() { - expect(() => new NavigationRoute(match, handler)).not.to.throw(); + expect(() => new NavigationRoute(handler)).not.to.throw(); }); it(`should not throw when called with a valid function handler`, function() { @@ -64,10 +63,10 @@ describe(`[workbox-routing] NavigationRoute`, function() { ]; const navigationRoute = new NavigationRoute(handler); urls.forEach((url) => { - const request = new Request(url, { - mode: 'navigate', - }); - expect(navigationRoute.match({event: {request}, url})).to.equal(true); + const request = new Request(url); + Object.defineProperty(request, 'mode', {value: 'navigate'}); + + expect(navigationRoute.match({request, url})).to.equal(true); }); }); @@ -79,74 +78,68 @@ describe(`[workbox-routing] NavigationRoute`, function() { const navigationRoute = new NavigationRoute(handler); urls.forEach((url) => { const request = new Request(url); - expect(navigationRoute.match({event: {request}, url})).to.equal(false); + expect(navigationRoute.match({request, url})).to.equal(false); }); }); it(`should not include urls in blacklist that completely match`, function() { const url = new URL('/testing/path.html', self.location); - const request = new Request(url, { - mode: 'navigate', - }); + const request = new Request(url); + Object.defineProperty(request, 'mode', {value: 'navigate'}); const navigationRoute = new NavigationRoute(handler, { blacklist: [/\/testing\/.*/], }); - expect(navigationRoute.match({event: {request}, url})).to.equal(false); + expect(navigationRoute.match({request, url})).to.equal(false); }); it(`should blacklist urls with search params that result in partial match with regex`, function() { const url = new URL('/testing/path.html?test=hello', self.location); - const request = new Request(url, { - mode: 'navigate', - }); + const request = new Request(url); + Object.defineProperty(request, 'mode', {value: 'navigate'}); const navigationRoute = new NavigationRoute(handler, { blacklist: [/\/testing\/path.html/], }); - expect(navigationRoute.match({event: {request}, url})).to.equal(false); + expect(navigationRoute.match({request, url})).to.equal(false); }); it(`should only match urls in custom whitelist`, function() { let url = new URL('/testing/path.html?test=hello', self.location); - let request = new Request(url, { - mode: 'navigate', - }); + let request = new Request(url); + Object.defineProperty(request, 'mode', {value: 'navigate'}); const navigationRoute = new NavigationRoute(handler, { whitelist: [/\/testing\/path.html/], }); - expect(navigationRoute.match({event: {request}, url})).to.equal(true); + expect(navigationRoute.match({request, url})).to.equal(true); url = new URL('/other/path.html?test=hello', self.location); - request = new Request(url, { - mode: 'navigate', - }); + request = new Request(url); + Object.defineProperty(request, 'mode', {value: 'navigate'}); - expect(navigationRoute.match({event: {request}, url})).to.equal(false); + expect(navigationRoute.match({request, url})).to.equal(false); }); it(`should take blacklist as priority`, function() { let url = new URL('/testing/path.html?test=hello', self.location); - let request = new Request(url, { - mode: 'navigate', - }); + let request = new Request(url); + Object.defineProperty(request, 'mode', {value: 'navigate'}); const navigationRoute = new NavigationRoute(handler, { whitelist: [/\/testing\/.*/], blacklist: [/\/testing\/path.html/], }); - expect(navigationRoute.match({event: {request}, url})).to.equal(false); + expect(navigationRoute.match({request, url})).to.equal(false); url = new URL('/testing/index.html?test=hello', self.location); - request = new Request(url, { - mode: 'navigate', - }); + request = new Request(url); + Object.defineProperty(request, 'mode', {value: 'navigate'}); - expect(navigationRoute.match({event: {request}, url})).to.equal(true); + expect(navigationRoute.match({request, url})).to.equal(true); }); }); diff --git a/test/workbox-routing/node/test-Router.mjs b/test/workbox-routing/node/test-Router.mjs index fd6d22af9..23fe30732 100644 --- a/test/workbox-routing/node/test-Router.mjs +++ b/test/workbox-routing/node/test-Router.mjs @@ -214,8 +214,9 @@ describe(`[workbox-routing] Router`, function() { router.setDefaultHandler(() => new Response(EXPECTED_RESPONSE_BODY)); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - const response = await router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + const response = await router.handleRequest({request, event}); const responseBody = await response.text(); @@ -241,8 +242,9 @@ describe(`[workbox-routing] Router`, function() { router.setCatchHandler(() => new Response(EXPECTED_RESPONSE_BODY)); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - const response = await router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + const response = await router.handleRequest({request, event}); const responseBody = await response.text(); expect(responseBody).to.eql(EXPECTED_RESPONSE_BODY); @@ -260,8 +262,9 @@ describe(`[workbox-routing] Router`, function() { router.setCatchHandler(() => new Response(EXPECTED_RESPONSE_BODY)); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - const response = await router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + const response = await router.handleRequest({request, event}); const responseBody = await response.text(); expect(responseBody).to.eql(EXPECTED_RESPONSE_BODY); @@ -269,6 +272,24 @@ describe(`[workbox-routing] Router`, function() { }); describe(`handleRequest()`, function() { + it(`should throw in dev when not passed a request`, async function() { + if (process.env.NODE_ENV === 'production') return this.skip(); + + const router = new Router(); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + + await expectError( + () => router.handleRequest({event}), + 'incorrect-class', + (error) => { + expect(error.details).to.have.property('moduleName').that.eql('workbox-routing'); + expect(error.details).to.have.property('className').that.eql('Router'); + expect(error.details).to.have.property('funcName').that.eql('handleRequest'); + expect(error.details).to.have.property('paramName').that.eql('options.request'); + }); + }); + it(`should return a response from the Route's handler when there's a matching route`, async function() { const router = new Router(); const route = new Route( @@ -278,8 +299,9 @@ describe(`[workbox-routing] Router`, function() { router.registerRoute(route); // route.match() always returns true, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - const response = await router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + const response = await router.handleRequest({request, event}); const responseBody = await response.text(); expect(responseBody).to.eql(EXPECTED_RESPONSE_BODY); @@ -301,13 +323,54 @@ describe(`[workbox-routing] Router`, function() { router.registerRoute(route2); // route.match() always returns true, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - const response = await router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + const response = await router.handleRequest({request, event}); const responseBody = await response.text(); expect(responseBody).to.eql(response1); }); + it(`should work when no event is passed`, async function() { + const router = new Router(); + const route = new Route( + () => true, + () => new Response(EXPECTED_RESPONSE_BODY), + ); + router.registerRoute(route); + + // route.match() always returns true, so the Request details don't matter. + const request = new Request(location); + const response = await router.handleRequest({request}); + const responseBody = await response.text(); + + expect(responseBody).to.eql(EXPECTED_RESPONSE_BODY); + }); + + it(`should work when request and event.request are different`, async function() { + const router = new Router(); + const route = new Route( + () => true, + ({url}) => { + // Ensure request (not event.request) is passed to the handler. + if (url.href !== 'https://unexpected.com') { + return new Response(EXPECTED_RESPONSE_BODY); + } + } + ); + router.registerRoute(route); + + // route.match() always returns true, so the Request details don't matter. + const request1 = new Request(location); + const request2 = new Request('https://unexpected.com'); + + const event = new FetchEvent('fetch', {request: request2}); + const response = await router.handleRequest({request: request1, event}); + const responseBody = await response.text(); + + expect(responseBody).to.eql(EXPECTED_RESPONSE_BODY); + }); + it(`should not return a response when there's no matching route and no default handler`, async function() { const router = new Router(); const route = new Route( @@ -317,8 +380,9 @@ describe(`[workbox-routing] Router`, function() { router.registerRoute(route); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - const response = router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + const response = await router.handleRequest({request, event}); expect(response).not.to.exist; }); @@ -327,12 +391,43 @@ describe(`[workbox-routing] Router`, function() { const router = new Router(); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(`example://test.com`)}); - const response = router.handleRequest(event); + const request = new Request(`example://test.com`); + const event = new FetchEvent('fetch', {request}); + const response = router.handleRequest({request, event}); expect(response).not.to.exist; }); + it(`should invoke route handlers with the correct arguments`, async function() { + const router = new Router(); + const match = sandbox.stub() + .onCall(0).returns(true) + .onCall(1).returns([1, 2, 3]); + + const handler = sandbox.stub().returns(new Response()); + + const route = new Route(match, handler); + router.registerRoute(route); + + const url = new URL('/one', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + await router.handleRequest({request}); + await router.handleRequest({request, event}); + + expect(handler.callCount).to.equal(2); + expect(handler.firstCall.args[0].url).to.deep.equal(url); + expect(handler.firstCall.args[0].request).to.equal(request); + expect(handler.firstCall.args[0].event).to.equal(undefined); + expect(handler.firstCall.args[0].params).to.equal(undefined); + + expect(handler.secondCall.args[0].url).to.deep.equal(url); + expect(handler.secondCall.args[0].request).to.equal(request); + expect(handler.secondCall.args[0].event).to.equal(event); + expect(handler.secondCall.args[0].params).to.deep.equal([1, 2, 3]); + }); + it(`should result in params in handler`, function() { const expectedParams = { test: 'hello', @@ -348,8 +443,9 @@ describe(`[workbox-routing] Router`, function() { router.registerRoute(route); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + router.handleRequest({request, event}); }); it(`should result in no params in handler`, function() { @@ -366,8 +462,9 @@ describe(`[workbox-routing] Router`, function() { router.registerRoute(route); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + router.handleRequest({request, event}); }); it(`should result in no params in handler for 'true'`, function() { @@ -382,15 +479,157 @@ describe(`[workbox-routing] Router`, function() { router.registerRoute(route); // route.match() always returns false, so the Request details don't matter. - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + router.handleRequest({request, event}); }); it(`should not throw for router with no-routes set`, function() { const router = new Router(); - const event = new FetchEvent('fetch', {request: new Request(self.location)}); - router.handleRequest(event); + const request = new Request(location); + const event = new FetchEvent('fetch', {request}); + router.handleRequest({request, event}); + }); + }); + + describe(`findMatchingRoute()`, function() { + it(`should throw in dev when not passed a URL`, async function() { + if (process.env.NODE_ENV === 'production') return this.skip(); + + const router = new Router(); + const url = new URL(location.href); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + await expectError( + () => router.findMatchingRoute({request, event}), + 'incorrect-class', + (error) => { + expect(error.details).to.have.property('moduleName').that.eql('workbox-routing'); + expect(error.details).to.have.property('className').that.eql('Router'); + expect(error.details).to.have.property('funcName').that.eql('findMatchingRoute'); + expect(error.details).to.have.property('paramName').that.eql('options.url'); + }); + }); + + it(`should throw in dev when not passed a request`, async function() { + if (process.env.NODE_ENV === 'production') return this.skip(); + + const router = new Router(); + const url = new URL(location.href); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + await expectError( + () => router.findMatchingRoute({url, event}), + 'incorrect-class', + (error) => { + expect(error.details).to.have.property('moduleName').that.eql('workbox-routing'); + expect(error.details).to.have.property('className').that.eql('Router'); + expect(error.details).to.have.property('funcName').that.eql('findMatchingRoute'); + expect(error.details).to.have.property('paramName').that.eql('options.request'); + }); + }); + + it(`should return the first matching route`, function() { + const router = new Router(); + + const match1 = sandbox.stub().returns(false); + const route1 = new Route(match1, () => new Response()); + router.registerRoute(route1); + + const match2 = sandbox.stub().returns(true); + const route2 = new Route(match2, () => new Response()); + router.registerRoute(route2); + + const match3 = sandbox.stub().returns(false); + const route3 = new Route(match2, () => new Response()); + router.registerRoute(route3); + + const url = new URL(location.href); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + const {route} = router.findMatchingRoute({url, request, event}); + + expect(match1.callCount).to.equal(1); + expect(match2.callCount).to.equal(1); + expect(match3.callCount).to.equal(0); + + expect(route).to.equal(route2); + }); + + it(`should invoke route match functions with the correct arguments`, function() { + const router = new Router(); + + const match1 = sandbox.stub().returns(false); + const route1 = new Route(match1, () => new Response()); + router.registerRoute(route1); + + const match2 = sandbox.stub().returns(true); + const route2 = new Route(match2, () => new Response()); + router.registerRoute(route2); + + const url = new URL(location.href); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + const {route} = router.findMatchingRoute({url, request, event}); + + expect(match1.callCount).to.equal(1); + expect(match1.args[0][0].url).to.deep.equal(url); + expect(match1.args[0][0].request).to.equal(request); + expect(match1.args[0][0].event).to.equal(event); + + expect(match2.callCount).to.equal(1); + expect(match2.args[0][0].url).to.deep.equal(url); + expect(match2.args[0][0].request).to.equal(request); + expect(match2.args[0][0].event).to.equal(event); + + expect(route).to.equal(route2); + }); + + it(`should return the route and params (if applicable)`, function() { + const router = new Router(); + const match = sandbox.stub() + .onCall(0).returns(true) + .onCall(1).returns('truthy') + .onCall(2).returns([1, 2, 3]) + .onCall(3).returns([]) + .onCall(4).returns({a: 1}) + .onCall(5).returns({}); + + const route = new Route(match, () => new Response()); + router.registerRoute(route); + + const url = new URL(location.href); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + const result1 = router.findMatchingRoute({url, request, event}); + expect(result1.route).to.equal(route); + expect(result1.params).to.equal(undefined); + + const result2 = router.findMatchingRoute({url, request, event}); + expect(result2.route).to.equal(route); + expect(result2.params).to.equal(undefined); + + const result3 = router.findMatchingRoute({url, request, event}); + expect(result3.route).to.equal(route); + expect(result3.params).to.deep.equal([1, 2, 3]); + + const result4 = router.findMatchingRoute({url, request, event}); + expect(result4.route).to.equal(route); + expect(result4.params).to.equal(undefined); + + const result5 = router.findMatchingRoute({url, request, event}); + expect(result5.route).to.equal(route); + expect(result5.params).to.deep.equal({a: 1}); + + const result6 = router.findMatchingRoute({url, request, event}); + expect(result6.route).to.equal(route); + expect(result6.params).to.equal(undefined); }); }); }); diff --git a/test/workbox-routing/node/test-default.mjs b/test/workbox-routing/node/test-default.mjs index e195bfde7..0dc68ff50 100644 --- a/test/workbox-routing/node/test-default.mjs +++ b/test/workbox-routing/node/test-default.mjs @@ -49,20 +49,21 @@ describe(`[workbox-routing] Default Router`, function() { const route = defaultRouter.registerRoute('/abc', handlerSpy); expect(route).to.be.an.instanceof(Route); - const event = new FetchEvent('fetch', { - request: new Request( - new URL('/abc', self.location).toString() - ), - }); - await defaultRouter.handleRequest(event); + const url = new URL('/abc', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + await defaultRouter.handleRequest({request, event}); expect(handlerSpy.callCount).to.equal(1); + expect(handlerSpy.getCall(0).args[0].url).to.deep.equal(url); + expect(handlerSpy.getCall(0).args[0].request).to.equal(request); expect(handlerSpy.getCall(0).args[0].event).to.equal(event); sandbox.resetHistory(); defaultRouter.unregisterRoute(route); - await defaultRouter.handleRequest(event); + await defaultRouter.handleRequest({request, event}); expect(handlerSpy.callCount).to.equal(0); }); @@ -75,34 +76,49 @@ describe(`[workbox-routing] Default Router`, function() { const route = defaultRouter.registerRoute(pathname, handlerSpy); expect(route).to.be.an.instanceof(Route); - const sameOriginEvent = new FetchEvent('fetch', { - request: new Request( - new URL(pathname, self.location).toString() - ), + const sameOriginUrl = new URL(pathname, location); + const sameOriginRequest = new Request(sameOriginUrl); + const sameOriginEvent = + new FetchEvent('fetch', {request: sameOriginRequest}); + + await defaultRouter.handleRequest({ + request: sameOriginRequest, + event: sameOriginEvent, }); - await defaultRouter.handleRequest(sameOriginEvent); - const sameOriginEventNotMatching = new FetchEvent('fetch', { - request: new Request( - new URL('/does/not/match', self.location).toString() - ), + const sameOriginUrlNotMatching = new URL('/does/not/match', location); + const sameOriginRequestNotMatching = + new Request(sameOriginUrlNotMatching); + const sameOriginEventNotMatching = + new FetchEvent('fetch', {request: sameOriginRequestNotMatching}); + + await defaultRouter.handleRequest({ + request: sameOriginRequestNotMatching, + event: sameOriginEventNotMatching, }); - await defaultRouter.handleRequest(sameOriginEventNotMatching); - const crossOriginEvent = new FetchEvent('fetch', { - request: new Request( - new URL(pathname, crossOrigin).toString() - ), + const crossOriginUrl = new URL(pathname, crossOrigin); + const crossOriginRequest = new Request(crossOriginUrl); + const crossOriginEvent = + new FetchEvent('fetch', {request: crossOriginRequest}); + + await defaultRouter.handleRequest({ + request: crossOriginRequest, + event: crossOriginEvent, }); - await defaultRouter.handleRequest(crossOriginEvent); expect(handlerSpy.callCount).to.equal(1); - expect(handlerSpy.getCall(0).args[0].event).to.equal(sameOriginEvent); + expect(handlerSpy.firstCall.args[0].url).to.deep.equal(sameOriginUrl); + expect(handlerSpy.firstCall.args[0].request).to.equal(sameOriginRequest); + expect(handlerSpy.firstCall.args[0].event).to.equal(sameOriginEvent); sandbox.resetHistory(); defaultRouter.unregisterRoute(route); - await defaultRouter.handleRequest(sameOriginEvent); + await defaultRouter.handleRequest({ + request: sameOriginRequest, + event: crossOriginEvent, + }); expect(handlerSpy.callCount).to.equal(0); }); @@ -115,27 +131,37 @@ describe(`[workbox-routing] Default Router`, function() { const route = defaultRouter.registerRoute(`${crossOrigin}${pathname}`, handlerSpy); expect(route).to.be.an.instanceof(Route); - const sameOriginEvent = new FetchEvent('fetch', { - request: new Request( - new URL(pathname, self.location).toString() - ), + const sameOriginUrl = new URL(pathname, location); + const sameOriginRequest = new Request(sameOriginUrl); + const sameOriginEvent = + new FetchEvent('fetch', {request: sameOriginRequest}); + + await defaultRouter.handleRequest({ + request: sameOriginRequest, + event: sameOriginEvent, }); - await defaultRouter.handleRequest(sameOriginEvent); - const crossOriginEvent = new FetchEvent('fetch', { - request: new Request( - new URL(pathname, crossOrigin).toString() - ), + const crossOriginUrl = new URL(pathname, crossOrigin); + const crossOriginRequest = new Request(crossOriginUrl); + const crossOriginEvent = + new FetchEvent('fetch', {request: crossOriginRequest}); + + await defaultRouter.handleRequest({ + request: crossOriginRequest, + event: crossOriginEvent, }); - await defaultRouter.handleRequest(crossOriginEvent); expect(handlerSpy.callCount).to.equal(1); - expect(handlerSpy.getCall(0).args[0].event).to.equal(crossOriginEvent); - + expect(handlerSpy.args[0][0].url).to.deep.equal(crossOriginUrl); + expect(handlerSpy.args[0][0].request).to.equal(crossOriginRequest); + expect(handlerSpy.args[0][0].event).to.equal(crossOriginEvent); sandbox.resetHistory(); defaultRouter.unregisterRoute(route); - await defaultRouter.handleRequest(crossOriginEvent); + await defaultRouter.handleRequest({ + request: crossOriginRequest, + event: crossOriginEvent, + }); expect(handlerSpy.callCount).to.equal(0); }); @@ -145,45 +171,46 @@ describe(`[workbox-routing] Default Router`, function() { const route = defaultRouter.registerRoute(/.*/, handlerSpy); expect(route).to.be.an.instanceof(RegExpRoute); - const event = new FetchEvent('fetch', { - request: new Request( - new URL('/', self.location).toString() - ), - }); - await defaultRouter.handleRequest(event); + const url = new URL('/', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + await defaultRouter.handleRequest({request, event}); expect(handlerSpy.callCount).to.equal(1); + expect(handlerSpy.getCall(0).args[0].url).to.deep.equal(url); + expect(handlerSpy.getCall(0).args[0].request).to.equal(request); expect(handlerSpy.getCall(0).args[0].event).to.equal(event); sandbox.resetHistory(); defaultRouter.unregisterRoute(route); - await defaultRouter.handleRequest(event); + await defaultRouter.handleRequest({request, event}); expect(handlerSpy.callCount).to.equal(0); }); it(`should handle a function for input and return a route that can be unregistered.`, async function() { - const captureSpy = sandbox.stub().callsFake(() => true); + const captureSpy = sandbox.stub().returns(true); const handlerSpy = sandbox.spy(); const route = defaultRouter.registerRoute(captureSpy, handlerSpy); expect(route).to.be.an.instanceof(Route); - const event = new FetchEvent('fetch', { - request: new Request( - new URL('/', self.location).toString() - ), - }); - await defaultRouter.handleRequest(event); + const url = new URL('/', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + await defaultRouter.handleRequest({request, event}); expect(captureSpy.callCount).to.equal(1); expect(handlerSpy.callCount).to.equal(1); + expect(handlerSpy.getCall(0).args[0].url).to.deep.equal(url); + expect(handlerSpy.getCall(0).args[0].request).to.equal(request); expect(handlerSpy.getCall(0).args[0].event).to.equal(event); sandbox.resetHistory(); defaultRouter.unregisterRoute(route); - await defaultRouter.handleRequest(event); + await defaultRouter.handleRequest({request, event}); expect(captureSpy.callCount).to.equal(0); expect(handlerSpy.callCount).to.equal(0); }); @@ -202,21 +229,22 @@ describe(`[workbox-routing] Default Router`, function() { const outputRoute = defaultRouter.registerRoute(inputRoute); expect(outputRoute).to.equal(inputRoute); - const event = new FetchEvent('fetch', { - request: new Request( - new URL('/', self.location).toString() - ), - }); - await defaultRouter.handleRequest(event); + const url = new URL('/', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + + await defaultRouter.handleRequest({request, event}); expect(captureSpy.callCount).to.equal(1); expect(handlerSpy.callCount).to.equal(1); + expect(handlerSpy.getCall(0).args[0].url).to.deep.equal(url); + expect(handlerSpy.getCall(0).args[0].request).to.equal(request); expect(handlerSpy.getCall(0).args[0].event).to.equal(event); sandbox.resetHistory(); defaultRouter.unregisterRoute(outputRoute); - await defaultRouter.handleRequest(event); + await defaultRouter.handleRequest({request, event}); expect(captureSpy.callCount).to.equal(0); expect(handlerSpy.callCount).to.equal(0); }); @@ -228,20 +256,20 @@ describe(`[workbox-routing] Default Router`, function() { const outputRoute = defaultRouter.registerRoute(inputRoute); expect(outputRoute).to.equal(inputRoute); - const event = new FetchEvent('fetch', { - request: new Request( - new URL('/', self.location).toString() - ), - }); - await defaultRouter.handleRequest(event); + const url = new URL('/', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + await defaultRouter.handleRequest({request, event}); expect(handlerSpy.callCount).to.equal(1); + expect(handlerSpy.getCall(0).args[0].url).to.deep.equal(url); + expect(handlerSpy.getCall(0).args[0].request).to.equal(request); expect(handlerSpy.getCall(0).args[0].event).to.equal(event); sandbox.resetHistory(); defaultRouter.unregisterRoute(outputRoute); - await defaultRouter.handleRequest(event); + await defaultRouter.handleRequest({request, event}); expect(handlerSpy.callCount).to.equal(0); }); @@ -351,14 +379,13 @@ describe(`[workbox-routing] Default Router`, function() { it(`should not call event methods for no route`, function() { sandbox.spy(defaultRouter, 'handleRequest'); - const fetchEvent = new FetchEvent('fetch', { - request: new Request(new URL('/random/navigation.html', self.location)), - }); - sandbox.stub(fetchEvent, 'respondWith'); - self.dispatchEvent(fetchEvent); + const url = new URL('/random/navigation.html', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + sandbox.stub(event, 'respondWith'); + self.dispatchEvent(event); expect(defaultRouter.handleRequest.callCount).to.equal(1); - expect(defaultRouter.handleRequest.args[0][0]).to.equal(fetchEvent); - expect(fetchEvent.respondWith.callCount).to.equal(0); + expect(event.respondWith.callCount).to.equal(0); }); it(`should pass Fetch Events to router.handleRequest`, function() { @@ -367,19 +394,21 @@ describe(`[workbox-routing] Default Router`, function() { const injectResponse = new Response(`Injected Response`); defaultRouter.registerRoute(/./, () => injectResponse); - const fetchEvent = new FetchEvent( - 'fetch', { - request: new Request(new URL('/random/navigation.html', self.location)), - }); + const url = new URL('/random/navigation.html', location); + const request = new Request(url); + const event = new FetchEvent('fetch', {request}); + return new Promise((resolve) => { - sandbox.stub(fetchEvent, 'respondWith').callsFake((response) => { + sandbox.stub(event, 'respondWith').callsFake((response) => { expect(response).to.equal(injectResponse); resolve(); }); - self.dispatchEvent(fetchEvent); + self.dispatchEvent(event); expect(defaultRouter.handleRequest.callCount).to.equal(1); - expect(defaultRouter.handleRequest.args[0][0]).to.equal(fetchEvent); - expect(fetchEvent.respondWith.callCount).to.equal(1); + expect(defaultRouter.handleRequest.args[0][0].url).to.deep.equal(url); + expect(defaultRouter.handleRequest.args[0][0].request).to.equal(request); + expect(defaultRouter.handleRequest.args[0][0].event).to.equal(event); + expect(event.respondWith.callCount).to.equal(1); }); }); }); diff --git a/test/workbox-strategies/node/test-UsageWithRouter.mjs b/test/workbox-strategies/node/test-UsageWithRouter.mjs index 9814e31d1..4d6e818b1 100644 --- a/test/workbox-strategies/node/test-UsageWithRouter.mjs +++ b/test/workbox-strategies/node/test-UsageWithRouter.mjs @@ -19,9 +19,10 @@ describe(`[workbox-strategies] Usages with Router`, function() { it(`should show Router and '${StrategyClass.name}' will work together`, function() { const router = new Router(); router.registerRoute(new Route(() => true, new StrategyClass())); - return router.handleRequest(new FetchEvent('fetch', { - request: new Request(self.location), - })); + + const request = new Request(self.location); + const event = new FetchEvent('fetch', {request}); + return router.handleRequest({request, event}); }); }); }); From 6e5dd96a01b4f38070143020193a99f1b8fb38a4 Mon Sep 17 00:00:00 2001 From: Philip Walton Date: Mon, 8 Oct 2018 10:30:56 -0700 Subject: [PATCH 2/2] Address review feedback --- packages/workbox-routing/NavigationRoute.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/workbox-routing/NavigationRoute.mjs b/packages/workbox-routing/NavigationRoute.mjs index c2413d20f..cfe7cd8e0 100644 --- a/packages/workbox-routing/NavigationRoute.mjs +++ b/packages/workbox-routing/NavigationRoute.mjs @@ -74,7 +74,6 @@ class NavigationRoute extends Route { * @param {Object} options * @param {URL} options.url * @param {Request} options.request - * @param {Event} [options.event] * @return {boolean} * * @private