Skip to content

Commit

Permalink
Merge pull request GoogleChrome#1989 from GoogleChrome/migrate-precac…
Browse files Browse the repository at this point in the history
…hing-tests

Migrate precaching tests to run in a SW environment
  • Loading branch information
philipwalton committed Mar 28, 2019
2 parents 04092a2 + 4898222 commit d4c630f
Show file tree
Hide file tree
Showing 31 changed files with 937 additions and 1,073 deletions.
8 changes: 8 additions & 0 deletions infra/testing/helpers/extendable-event-utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@


const extendLifetimePromises = new WeakMap();
const eventResponses = new WeakMap();

export const eventDoneWaiting = async (event) => {
const promises = extendLifetimePromises.get(event);
Expand All @@ -29,6 +30,7 @@ export const watchEvent = (event) => {

if (event instanceof FetchEvent) {
event.respondWith = (responseOrPromise) => {
eventResponses.set(event, responseOrPromise);
promises.push(Promise.resolve(responseOrPromise));

// TODO(philipwalton): we cannot currently call the native
Expand All @@ -44,3 +46,9 @@ export const dispatchAndWaitUntilDone = async (event) => {
self.dispatchEvent(event);
await eventDoneWaiting(event);
};

export const dispatchAndWaitForResponse = async (event) => {
await dispatchAndWaitUntilDone(event);
const response = await eventResponses.get(event);
return response;
};
74 changes: 4 additions & 70 deletions packages/workbox-precaching/addRoute.mjs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@

/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/

import {cacheNames} from 'workbox-core/_private/cacheNames.mjs';
import {getFriendlyURL} from 'workbox-core/_private/getFriendlyURL.mjs';
import {logger} from 'workbox-core/_private/logger.mjs';
import {getCacheKeyForURL} from './utils/getCacheKeyForURL.mjs';
import {addFetchListener} from './utils/addFetchListener.mjs';
import './_version.mjs';


Expand Down Expand Up @@ -39,72 +36,9 @@ let listenerAdded = false;
*
* @alias workbox.precaching.addRoute
*/
export const addRoute = ({
ignoreURLParametersMatching = [/^utm_/],
directoryIndex = 'index.html',
cleanURLs = true,
urlManipulation = null,
} = {}) => {
export const addRoute = (options) => {
if (!listenerAdded) {
const cacheName = cacheNames.getPrecacheName();

addEventListener('fetch', (event) => {
const precachedURL = getCacheKeyForURL(event.request.url, {
cleanURLs,
directoryIndex,
ignoreURLParametersMatching,
urlManipulation,
});
if (!precachedURL) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Precaching did not find a match for ` +
getFriendlyURL(event.request.url));
}
return;
}

let responsePromise = caches.open(cacheName).then((cache) => {
return cache.match(precachedURL);
}).then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}

// Fall back to the network if we don't have a cached response
// (perhaps due to manual cache cleanup).
if (process.env.NODE_ENV !== 'production') {
logger.warn(`The precached response for ` +
`${getFriendlyURL(precachedURL)} in ${cacheName} was not found. ` +
`Falling back to the network instead.`);
}

return fetch(precachedURL);
});

if (process.env.NODE_ENV !== 'production') {
responsePromise = responsePromise.then((response) => {
// Workbox is going to handle the route.
// print the routing details to the console.
logger.groupCollapsed(`Precaching is responding to: ` +
getFriendlyURL(event.request.url));
logger.log(`Serving the precached url: ${precachedURL}`);

logger.groupCollapsed(`View request details here.`);
logger.log(event.request);
logger.groupEnd();

logger.groupCollapsed(`View response details here.`);
logger.log(response);
logger.groupEnd();

logger.groupEnd();
return response;
});
}

event.respondWith(responsePromise);
});

addFetchListener(options);
listenerAdded = true;
}
};
55 changes: 30 additions & 25 deletions packages/workbox-precaching/precache.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,34 @@
*/

import {logger} from 'workbox-core/_private/logger.mjs';
import {getOrCreatePrecacheController}
from './utils/getOrCreatePrecacheController.mjs';
import {getOrCreatePrecacheController} from './utils/getOrCreatePrecacheController.mjs';
import {precachePlugins} from './utils/precachePlugins.mjs';
import './_version.mjs';


let listenersAdded = false;
const installListener = (event) => {
const precacheController = getOrCreatePrecacheController();
const plugins = precachePlugins.get();

event.waitUntil(
precacheController.install({event, plugins})
.catch((error) => {
if (process.env.NODE_ENV !== 'production') {
logger.error(`Service worker installation failed. It will ` +
`be retried automatically during the next navigation.`);
}
// Re-throw the error to ensure installation fails.
throw error;
})
);
};

const activateListener = (event) => {
const precacheController = getOrCreatePrecacheController();
const plugins = precachePlugins.get();

event.waitUntil(precacheController.activate({event, plugins}));
};

/**
* Adds items to the precache list, removing any duplicates and
Expand All @@ -38,27 +59,11 @@ export const precache = (entries) => {
const precacheController = getOrCreatePrecacheController();
precacheController.addToCacheList(entries);

if (!listenersAdded && entries.length > 0) {
const plugins = precachePlugins.get();

self.addEventListener('install', (event) => {
event.waitUntil(
precacheController.install({event, plugins})
.catch((error) => {
if (process.env.NODE_ENV !== 'production') {
logger.error(`Service worker installation failed. It will ` +
`be retried automatically during the next navigation.`);
}
// Re-throw the error to ensure installation fails.
throw error;
})
);
});

self.addEventListener('activate', (event) => {
event.waitUntil(precacheController.activate({event, plugins}));
});

listenersAdded = true;
if (entries.length > 0) {
// NOTE: these listeners will only be added once (even if the `precache()`
// method is called multiple times) because event listeners are implemented
// as a set, where each listener must be unique.
addEventListener('install', installListener);
addEventListener('activate', activateListener);
}
};
107 changes: 107 additions & 0 deletions packages/workbox-precaching/utils/addFetchListener.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/

import {cacheNames} from 'workbox-core/_private/cacheNames.mjs';
import {getFriendlyURL} from 'workbox-core/_private/getFriendlyURL.mjs';
import {logger} from 'workbox-core/_private/logger.mjs';
import {getCacheKeyForURL} from './getCacheKeyForURL.mjs';
import '../_version.mjs';


/**
* Adds a `fetch` listener to the service worker that will
* respond to
* [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests}
* with precached assets.
*
* Requests for assets that aren't precached, the `FetchEvent` will not be
* responded to, allowing the event to fall through to other `fetch` event
* listeners.
*
* NOTE: when called more than once this method will replace the previously set
* configuration options. Calling it more than once is not recommended outside
* of tests.
*
* @private
* @param {Object} options
* @param {string} [options.directoryIndex=index.html] The `directoryIndex` will
* check cache entries for a URLs ending with '/' to see if there is a hit when
* appending the `directoryIndex` value.
* @param {Array<RegExp>} [options.ignoreURLParametersMatching=[/^utm_/]] An
* array of regex's to remove search params when looking for a cache match.
* @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will
* check the cache for the URL with a `.html` added to the end of the end.
* @param {workbox.precaching~urlManipulation} [options.urlManipulation]
* This is a function that should take a URL and return an array of
* alternative URL's that should be checked for precache matches.
*/
export const addFetchListener = ({
ignoreURLParametersMatching = [/^utm_/],
directoryIndex = 'index.html',
cleanURLs = true,
urlManipulation = null,
} = {}) => {
const cacheName = cacheNames.getPrecacheName();

addEventListener('fetch', (event) => {
const precachedURL = getCacheKeyForURL(event.request.url, {
cleanURLs,
directoryIndex,
ignoreURLParametersMatching,
urlManipulation,
});
if (!precachedURL) {
if (process.env.NODE_ENV !== 'production') {
logger.debug(`Precaching did not find a match for ` +
getFriendlyURL(event.request.url));
}
return;
}

let responsePromise = caches.open(cacheName).then((cache) => {
return cache.match(precachedURL);
}).then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}

// Fall back to the network if we don't have a cached response
// (perhaps due to manual cache cleanup).
if (process.env.NODE_ENV !== 'production') {
logger.warn(`The precached response for ` +
`${getFriendlyURL(precachedURL)} in ${cacheName} was not found. ` +
`Falling back to the network instead.`);
}

return fetch(precachedURL);
});

if (process.env.NODE_ENV !== 'production') {
responsePromise = responsePromise.then((response) => {
// Workbox is going to handle the route.
// print the routing details to the console.
logger.groupCollapsed(`Precaching is responding to: ` +
getFriendlyURL(event.request.url));
logger.log(`Serving the precached url: ${precachedURL}`);

logger.groupCollapsed(`View request details here.`);
logger.log(event.request);
logger.groupEnd();

logger.groupCollapsed(`View response details here.`);
logger.log(response);
logger.groupEnd();

logger.groupEnd();
return response;
});
}

event.respondWith(responsePromise);
});
};
4 changes: 2 additions & 2 deletions test/workbox-navigation-preload/integration/test-sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
const {runUnitTests} = require('../../../infra/testing/webdriver/runUnitTests');


describe(`[workbox-google-analytics]`, function() {
describe(`[workbox-navigation-preload]`, function() {
it(`passes all SW unit tests`, async function() {
await runUnitTests('/test/workbox-google-analytics/sw/');
await runUnitTests('/test/workbox-navigation-preload/sw/');
});
});
7 changes: 7 additions & 0 deletions test/workbox-navigation-preload/sw/test-disable.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ describe(`disable`, function() {
sandbox.restore();
});

// This is needed because we're skipping the last test, which for some
// reasons seems to be skipping the afterEach hook:
// https://github.com/mochajs/mocha/pull/2571#issuecomment-477407091
after(function() {
sandbox.restore();
});

it(`should call addEventListener iff navigation preload is supported`, async function() {
disable();

Expand Down
7 changes: 7 additions & 0 deletions test/workbox-navigation-preload/sw/test-enable.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ describe(`enable`, function() {
sandbox.restore();
});

// This is needed because we're skipping the last test, which for some
// reasons seems to be skipping the afterEach hook:
// https://github.com/mochajs/mocha/pull/2571#issuecomment-477407091
after(function() {
sandbox.restore();
});

it(`should call addEventListener iff navigation preload is supported`, async function() {
enable();

Expand Down
16 changes: 16 additions & 0 deletions test/workbox-precaching/integration/test-sw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
Copyright 2019 Google LLC
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
*/

const {runUnitTests} = require('../../../infra/testing/webdriver/runUnitTests');


describe(`[workbox-precaching]`, function() {
it(`passes all SW unit tests`, async function() {
await runUnitTests('/test/workbox-precaching/sw/');
});
});
Loading

0 comments on commit d4c630f

Please sign in to comment.