Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Show update banner rather than reload if update is detected after load
Browse files Browse the repository at this point in the history
  • Loading branch information
eyelidlessness committed Oct 15, 2022
1 parent 77af705 commit c1c9cb8
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 3 deletions.
9 changes: 8 additions & 1 deletion public/js/src/module/application-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ const init = async (survey) => {
workerURL
);

let isInitialUpdateCheck = true;

// Registration was successful
console.log(
'Offline application service worker registration successful with scope: ',
registration.scope
);
setInterval(() => {
isInitialUpdateCheck = false;
console.log(
'Checking for offline application cache service worker update'
);
Expand All @@ -68,7 +71,11 @@ const init = async (survey) => {
navigator.serviceWorker.addEventListener(
'controllerchange',
() => {
location.reload();
if (isInitialUpdateCheck) {
location.reload();
} else {
document.dispatchEvent(events.ApplicationUpdated());
}
}
);
}
Expand Down
53 changes: 51 additions & 2 deletions test/client/application-cache.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import applicationCache from '../../public/js/src/module/application-cache';
import events from '../../public/js/src/module/event';
import settings from '../../public/js/src/module/settings';

describe('Application Cache', () => {
describe('Application cache initialization (offline service worker registration)', () => {
const basePath = '-';
const version = `1.2.3-BADB3D`;
const applicationUpdatedEvent = events.ApplicationUpdated();
const applicationUpdatedType = applicationUpdatedEvent.type;
const offlineLaunchCapableType = events.OfflineLaunchCapable().type;

/** @type {ServiceWorker | null} */
Expand All @@ -28,6 +30,9 @@ describe('Application Cache', () => {
/** @type {sinon.SinonFake} */
let registrationUpdateFake;

/** @type {Function | null} */
let controllerChangeListener;

beforeEach(() => {
sandbox = sinon.createSandbox();
timers = sandbox.useFakeTimers(Date.now());
Expand Down Expand Up @@ -60,13 +65,41 @@ describe('Application Cache', () => {
settings.version ??= undefined;
sandbox.stub(settings, 'basePath').value(basePath);
sandbox.stub(settings, 'version').value(version);

const addControllerChangeListener =
navigator.serviceWorker.addEventListener;

controllerChangeListener = null;

sandbox
.stub(navigator.serviceWorker, 'addEventListener')
.callsFake((type, listener) => {
if (type === 'controllerchange') {
expect(controllerChangeListener).to.equal(null);
controllerChangeListener = listener;
}
addControllerChangeListener.call(
navigator.serviceWorker,
type,
listener
);
});
});

afterEach(() => {
document.removeEventListener(
offlineLaunchCapableType,
offlineLaunchCapableListener
);

if (controllerChangeListener != null) {
navigator.serviceWorker.removeEventListener(
'controllerchange',
controllerChangeListener
);
}

timers.reset();
timers.restore();
sandbox.restore();
});
Expand Down Expand Up @@ -142,7 +175,7 @@ describe('Application Cache', () => {
expect(caught.stack).to.equal(error.stack);
});

it('reloads when an updated service worker becomes active', async () => {
it('reloads when an updated service worker becomes active on load', async () => {
activeServiceWorker = {};
await applicationCache.init();

Expand All @@ -168,4 +201,20 @@ describe('Application Cache', () => {

expect(registrationUpdateFake).to.have.been.calledTwice;
});

it('notifies the user, rather than reloading, when the service worker has changed', async () => {
activeServiceWorker = {};
await applicationCache.init();

timers.tick(applicationCache.UPDATE_REGISTRATION_INTERVAL);

const listener = sandbox.fake();

document.addEventListener(applicationUpdatedType, listener);
navigator.serviceWorker.dispatchEvent(new Event('controllerchange'));
document.removeEventListener(applicationUpdatedType, listener);

expect(reloadStub).not.to.have.been.called;
expect(listener).to.have.been.calledOnceWith(applicationUpdatedEvent);
});
});

0 comments on commit c1c9cb8

Please sign in to comment.