fix(service-worker): listen for messages on the right event source (#19954)
Currently, the SwUpdate service doesn't receive messages from the SW. This is because it attempts to subscribe to the 'message' event on ServiceWorkerRegistration, when really messages are emitted by the ServiceWorkerContainer. This change moves to listening on ServiceWorkerContainer and changes the mocks to reflect the way the browser actually works. PR Close #19954
This commit is contained in:
parent
703fcda590
commit
5adb7c9669
|
@ -106,8 +106,7 @@ export class NgswCommChannel {
|
||||||
this.registration = <Observable<ServiceWorkerRegistration>>(
|
this.registration = <Observable<ServiceWorkerRegistration>>(
|
||||||
op_switchMap.call(this.worker, () => serviceWorker.getRegistration()));
|
op_switchMap.call(this.worker, () => serviceWorker.getRegistration()));
|
||||||
|
|
||||||
const rawEvents = <Observable<MessageEvent>>(op_switchMap.call(
|
const rawEvents = obs_fromEvent(serviceWorker, 'message');
|
||||||
this.registration, (reg: ServiceWorkerRegistration) => obs_fromEvent(reg, 'message')));
|
|
||||||
|
|
||||||
const rawEventPayload =
|
const rawEventPayload =
|
||||||
<Observable<Object>>(op_map.call(rawEvents, (event: MessageEvent) => event.data));
|
<Observable<Object>>(op_map.call(rawEvents, (event: MessageEvent) => event.data));
|
||||||
|
|
|
@ -44,11 +44,9 @@ export function main() {
|
||||||
});
|
});
|
||||||
describe('SwPush', () => {
|
describe('SwPush', () => {
|
||||||
let push: SwPush;
|
let push: SwPush;
|
||||||
let reg: MockServiceWorkerRegistration;
|
beforeEach(() => {
|
||||||
beforeEach((done: DoneFn) => {
|
|
||||||
push = new SwPush(comm);
|
push = new SwPush(comm);
|
||||||
mock.setupSw();
|
mock.setupSw();
|
||||||
mock.mockRegistration.then(r => reg = r).then(() => done());
|
|
||||||
});
|
});
|
||||||
it('receives push messages', (done: DoneFn) => {
|
it('receives push messages', (done: DoneFn) => {
|
||||||
push.messages.subscribe(msg => {
|
push.messages.subscribe(msg => {
|
||||||
|
@ -57,7 +55,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
reg.sendMessage({
|
mock.sendMessage({
|
||||||
type: 'PUSH',
|
type: 'PUSH',
|
||||||
data: {
|
data: {
|
||||||
message: 'this was a push message',
|
message: 'this was a push message',
|
||||||
|
@ -76,11 +74,9 @@ export function main() {
|
||||||
});
|
});
|
||||||
describe('SwUpdate', () => {
|
describe('SwUpdate', () => {
|
||||||
let update: SwUpdate;
|
let update: SwUpdate;
|
||||||
let reg: MockServiceWorkerRegistration;
|
beforeEach(() => {
|
||||||
beforeEach((done: DoneFn) => {
|
|
||||||
update = new SwUpdate(comm);
|
update = new SwUpdate(comm);
|
||||||
mock.setupSw();
|
mock.setupSw();
|
||||||
mock.mockRegistration.then(r => reg = r).then(() => done());
|
|
||||||
});
|
});
|
||||||
it('processes update availability notifications when sent', (done: DoneFn) => {
|
it('processes update availability notifications when sent', (done: DoneFn) => {
|
||||||
update.available.subscribe(event => {
|
update.available.subscribe(event => {
|
||||||
|
@ -89,7 +85,7 @@ export function main() {
|
||||||
expect(event.type).toEqual('UPDATE_AVAILABLE');
|
expect(event.type).toEqual('UPDATE_AVAILABLE');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
reg.sendMessage({
|
mock.sendMessage({
|
||||||
type: 'UPDATE_AVAILABLE',
|
type: 'UPDATE_AVAILABLE',
|
||||||
current: {
|
current: {
|
||||||
version: 'A',
|
version: 'A',
|
||||||
|
@ -106,7 +102,7 @@ export function main() {
|
||||||
expect(event.type).toEqual('UPDATE_ACTIVATED');
|
expect(event.type).toEqual('UPDATE_ACTIVATED');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
reg.sendMessage({
|
mock.sendMessage({
|
||||||
type: 'UPDATE_ACTIVATED',
|
type: 'UPDATE_ACTIVATED',
|
||||||
previous: {
|
previous: {
|
||||||
version: 'A',
|
version: 'A',
|
||||||
|
@ -119,7 +115,7 @@ export function main() {
|
||||||
it('activates updates when requested', (done: DoneFn) => {
|
it('activates updates when requested', (done: DoneFn) => {
|
||||||
mock.messages.subscribe((msg: {action: string, statusNonce: number}) => {
|
mock.messages.subscribe((msg: {action: string, statusNonce: number}) => {
|
||||||
expect(msg.action).toEqual('ACTIVATE_UPDATE');
|
expect(msg.action).toEqual('ACTIVATE_UPDATE');
|
||||||
reg.sendMessage({
|
mock.sendMessage({
|
||||||
type: 'STATUS',
|
type: 'STATUS',
|
||||||
nonce: msg.statusNonce,
|
nonce: msg.statusNonce,
|
||||||
status: true,
|
status: true,
|
||||||
|
@ -130,7 +126,7 @@ export function main() {
|
||||||
it('reports activation failure when requested', (done: DoneFn) => {
|
it('reports activation failure when requested', (done: DoneFn) => {
|
||||||
mock.messages.subscribe((msg: {action: string, statusNonce: number}) => {
|
mock.messages.subscribe((msg: {action: string, statusNonce: number}) => {
|
||||||
expect(msg.action).toEqual('ACTIVATE_UPDATE');
|
expect(msg.action).toEqual('ACTIVATE_UPDATE');
|
||||||
reg.sendMessage({
|
mock.sendMessage({
|
||||||
type: 'STATUS',
|
type: 'STATUS',
|
||||||
nonce: msg.statusNonce,
|
nonce: msg.statusNonce,
|
||||||
status: false,
|
status: false,
|
||||||
|
|
|
@ -85,7 +85,7 @@ export function main() {
|
||||||
driver = new Driver(scope, scope, new CacheDatabase(scope, scope));
|
driver = new Driver(scope, scope, new CacheDatabase(scope, scope));
|
||||||
|
|
||||||
scope.clients.add('default');
|
scope.clients.add('default');
|
||||||
scope.clients.getMock('default') !.queue.subscribe(msg => { reg.sendMessage(msg); });
|
scope.clients.getMock('default') !.queue.subscribe(msg => { mock.sendMessage(msg); });
|
||||||
|
|
||||||
mock.messages.subscribe(msg => { scope.handleMessage(msg, 'default'); });
|
mock.messages.subscribe(msg => { scope.handleMessage(msg, 'default'); });
|
||||||
|
|
||||||
|
|
|
@ -10,17 +10,26 @@ import {Subject} from 'rxjs/Subject';
|
||||||
|
|
||||||
export class MockServiceWorkerContainer {
|
export class MockServiceWorkerContainer {
|
||||||
private onControllerChange: Function[] = [];
|
private onControllerChange: Function[] = [];
|
||||||
|
private onMessage: Function[] = [];
|
||||||
private registration: MockServiceWorkerRegistration|null = null;
|
private registration: MockServiceWorkerRegistration|null = null;
|
||||||
controller: MockServiceWorker|null = null;
|
controller: MockServiceWorker|null = null;
|
||||||
|
|
||||||
messages = new Subject();
|
messages = new Subject();
|
||||||
|
|
||||||
addEventListener(event: 'controllerchange', handler: Function) {
|
addEventListener(event: 'controllerchange'|'message', handler: Function) {
|
||||||
|
if (event === 'controllerchange') {
|
||||||
this.onControllerChange.push(handler);
|
this.onControllerChange.push(handler);
|
||||||
|
} else if (event === 'message') {
|
||||||
|
this.onMessage.push(handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeEventListener(event: 'controllerchange', handler: Function) {
|
removeEventListener(event: 'controllerchange', handler: Function) {
|
||||||
|
if (event === 'controllerchange') {
|
||||||
this.onControllerChange = this.onControllerChange.filter(h => h !== handler);
|
this.onControllerChange = this.onControllerChange.filter(h => h !== handler);
|
||||||
|
} else if (event === 'message') {
|
||||||
|
this.onMessage = this.onMessage.filter(h => h !== handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async register(url: string): Promise<void> { return; }
|
async register(url: string): Promise<void> { return; }
|
||||||
|
@ -36,6 +45,12 @@ export class MockServiceWorkerContainer {
|
||||||
get mockRegistration(): Promise<MockServiceWorkerRegistration> {
|
get mockRegistration(): Promise<MockServiceWorkerRegistration> {
|
||||||
return Promise.resolve(this.registration !);
|
return Promise.resolve(this.registration !);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendMessage(value: Object): void {
|
||||||
|
this.onMessage.forEach(onMessage => onMessage({
|
||||||
|
data: value,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MockServiceWorker {
|
export class MockServiceWorker {
|
||||||
|
@ -44,21 +59,4 @@ export class MockServiceWorker {
|
||||||
postMessage(value: Object) { this.mock.messages.next(value); }
|
postMessage(value: Object) { this.mock.messages.next(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MockServiceWorkerRegistration {
|
export class MockServiceWorkerRegistration {}
|
||||||
private onMessage: Function[] = [];
|
|
||||||
messages: Object[] = [];
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
addEventListener(event: 'message', handler: Function) { this.onMessage.push(handler); }
|
|
||||||
|
|
||||||
removeEventListener(event: 'message', handler: Function) {
|
|
||||||
this.onMessage = this.onMessage.filter(h => h !== handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessage(value: Object): void {
|
|
||||||
this.onMessage.forEach(onMessage => onMessage({
|
|
||||||
data: value,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue