A sandboxed ServiceWorker context for testing your ServiceWorker code on the command line.
Testing code written to run in a ServiceWorker is hard, and generally requires a browser environment and lots of ceremony to work. sw-test-env is the magic ingredient for easy unit/integration testing of ServiceWorker code. Just load your script, and poke, prod, inspect, and manipulate the ServiceWorker context:
import assert from 'assert';
import { connect } from 'sw-test-env';
// Equivalent to opening a browser window and accessing window.navigator.serviceWorker
const sw = connect('http://localhost:3000', 'path/to/webroot');
async function test() {
// Load and execute sw.js in a sandboxed ServiceWorker context
const registration = await sw.register('sw.js');
// Trigger the 'install' event
await sw.trigger('install');
// Inspect the cache contents by reading from the installing service worker's internal scope
const cache = await sw.__serviceWorker__.self.caches.open('v1');
const requests = await cache.keys();
const urls = requests.map((request) => request.url);
assert.ok(urls.includes('assets/index.js'));
}- load and execute
ServiceWorkerscript files in a sandboxed context - inspect the properties of the
ServiceWorkerscope (clients,caches,registration, variables, etc) - manually trigger events on
ServiceWorker(install,activate,fetch,error, etc) - connect multiple clients
- register multiple, scoped
ServiceWorkerinstances postMessagebetween clients and registeredServiceWorkerinstances- use
indexedDB - TODO: register for notifications and push messages to connected clients
- limited
Responsestreaming and body conversion (uses the primitives from node-fetch) fetchcalls will be executed, so a request mocking tool like nock is recommendedimportScripts()in service worker files not supported (useimportstatements instead)- requires at least version 16 of Node
- not yet possible to cache based on
VARYheader - not tested against spec test suite or specific browser behaviour
Create a new MockServiceWorkerContainer instance at url (default is http://localhost:3333/) with webroot (default is current working directory). This is equivalent to opening a browser at url and accessing the window.navigator.serviceworker object. See MockServiceWorkerContainer below for additional behaviour.
Multiple connections to same/different origins are supported, with access to MockServiceWorker instances determined by scope.
Note: the webroot argument is used to resolve the path for registering the MockServiceWorker.
Destroy all active MockServiceWorkerContainer instances and their registered MockServiceWorker instances. Should generally be called after each test (for example, in afterEach() when using Mocha/Jest/etc).
Classes for creating instances of Headers, MessageChannel, Request, and Response to be used when interacting with the MockServiceWorker context.
In addition to the behaviour documented here, a MockServiceWorkerContainer instance returned by connect() has the following additions:
Load and execute scriptURL in a MockServiceWorker context. scriptURL may be a relative or absolute filepath.
options include:
scope: StringtheMockServiceWorkerregistration scope (defaults to./). MultipleMockServiceWorkerinstances can be registered on the same origin with different scopes.
Force registered script to install and activate:
const registration = await sw.register('sw.js');
await sw.ready;
assert.equal(sw.controller.state, 'activated');Manually trigger an event in the MockServiceWorker scope:
const registration = await sw.register('sw.js');
await sw.ready;
const response = await sw.trigger('fetch', { request: '/assets/index.js' });
assert.equal(response.url, 'http://localhost:3333/assets/index.js');Access the registered MockServiceWorker, including it's internal self scope:
const registration = await sw.register('sw.js');
await sw.ready;
const cache = sw.__serviceWorker__.self.caches.open('v1');
const requests = await cache.keys();
const urls = requests.map((request) => request.url);
assert.ok(urls.includes('assets/index.js'));Special thanks goes to Pinterest (service-worker-mock) and Nolan Lawson (pseudo-worker) for their ideas (some of which were borrowed here) and inspiring work.