From 22a81231f2dae4eb4766c213be46a52fe98b1b8b Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 8 Jul 2021 16:25:15 +0300 Subject: [PATCH] test(service-worker): better align mock event implementations with actual implementations (#42736) This commit better aligns the mock event implementations used in ServiceWorker tests (and the associated typings) with the actual implementations (and the official TypeScript typings). This allows verifying the ServiceWorker behavior in a slightly more realistic environment. This is in preparation of switching from our custom typings to the official TypeScript typings (`lib.webworker.d.ts`). PR Close #42736 --- .../worker/src/service-worker.d.ts | 32 ++++++++--------- .../service-worker/worker/test/happy_spec.ts | 2 +- .../service-worker/worker/testing/events.ts | 34 +++++++++++-------- .../service-worker/worker/testing/scope.ts | 9 ++--- 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/packages/service-worker/worker/src/service-worker.d.ts b/packages/service-worker/worker/src/service-worker.d.ts index 7af223bc07..f01adabfe6 100644 --- a/packages/service-worker/worker/src/service-worker.d.ts +++ b/packages/service-worker/worker/src/service-worker.d.ts @@ -64,29 +64,24 @@ type WindowClientState = 'hidden'|'visible'|'prerender'|'unloaded'; // Fetch API interface FetchEvent extends ExtendableEvent { - request: Request; - clientId?: string; - resultingClientId?: string; - respondWith(response: Promise|Response): Promise; + readonly clientId: string; + readonly preloadResponse: Promise; + readonly request: Request; + readonly resultingClientId: string; + respondWith(r: Response|Promise): void; } -interface InstallEvent extends ExtendableEvent { - activeWorker: ServiceWorker; -} - -interface ActivateEvent extends ExtendableEvent {} - // Notification API interface NotificationEvent extends ExtendableEvent { - action: string; - notification: Notification; + readonly action: string; + readonly notification: Notification; } // Push API interface PushEvent extends ExtendableEvent { - data: PushMessageData; + readonly data: PushMessageData|null; } interface PushMessageData { @@ -99,13 +94,16 @@ interface PushMessageData { // Sync API interface SyncEvent extends ExtendableEvent { - lastChance: boolean; - tag: string; + readonly lastChance: boolean; + readonly tag: string; } interface ExtendableMessageEvent extends ExtendableEvent { - data: any; - source: Client|Object; + readonly data: any; + readonly lastEventId: string; + readonly origin: string; + readonly ports: ReadonlyArray; + readonly source: Client|ServiceWorker|MessagePort|null; } // ServiceWorkerGlobalScope diff --git a/packages/service-worker/worker/test/happy_spec.ts b/packages/service-worker/worker/test/happy_spec.ts index 0a9561dcf2..fafff3990b 100644 --- a/packages/service-worker/worker/test/happy_spec.ts +++ b/packages/service-worker/worker/test/happy_spec.ts @@ -783,7 +783,7 @@ describe('Driver', () => { const message: any = scope.clients.getMock('default')!.messages[0]; expect(message.type).toEqual('NOTIFICATION_CLICK'); - expect(message.data.action).toBeUndefined(); + expect(message.data.action).toBe(''); expect(message.data.notification.title).toEqual('This is a test without action'); expect(message.data.notification.body).toEqual('Test body without action'); }); diff --git a/packages/service-worker/worker/testing/events.ts b/packages/service-worker/worker/testing/events.ts index f42c1698a0..bedd3a7ce1 100644 --- a/packages/service-worker/worker/testing/events.ts +++ b/packages/service-worker/worker/testing/events.ts @@ -49,7 +49,7 @@ export class MockEvent implements Event { } export class MockExtendableEvent extends MockEvent implements ExtendableEvent { - private queue: Promise[] = []; + private queue: Promise[] = []; get ready(): Promise { return (async () => { @@ -59,7 +59,7 @@ export class MockExtendableEvent extends MockEvent implements ExtendableEvent { })(); } - waitUntil(promise: Promise): void { + waitUntil(promise: Promise): void { this.queue.push(promise); } } @@ -70,7 +70,8 @@ export class MockActivateEvent extends MockExtendableEvent { } } -export class MockFetchEvent extends MockExtendableEvent { +export class MockFetchEvent extends MockExtendableEvent implements FetchEvent { + readonly preloadResponse = Promise.resolve(); response: Promise = Promise.resolve(undefined); constructor( @@ -78,9 +79,8 @@ export class MockFetchEvent extends MockExtendableEvent { super('fetch'); } - respondWith(promise: Promise): Promise { - this.response = promise; - return promise; + respondWith(r: Response|Promise): void { + this.response = Promise.resolve(r); } } @@ -90,27 +90,33 @@ export class MockInstallEvent extends MockExtendableEvent { } } -export class MockMessageEvent extends MockExtendableEvent { - constructor(readonly data: Object, readonly source: MockClient|null) { +export class MockExtendableMessageEvent extends MockExtendableEvent implements + ExtendableMessageEvent { + readonly lastEventId = ''; + readonly origin = ''; + readonly ports: ReadonlyArray = []; + + constructor(readonly data: any, readonly source: Client|MessagePort|ServiceWorker|null) { super('message'); } } -export class MockNotificationEvent extends MockExtendableEvent { +export class MockNotificationEvent extends MockExtendableEvent implements NotificationEvent { readonly notification = { ...this._notification, close: () => undefined, - }; + } as Notification; - constructor(private _notification: any, readonly action?: string) { + constructor(private _notification: Partial, readonly action = '') { super('notification'); } } -export class MockPushEvent extends MockExtendableEvent { - data = { +export class MockPushEvent extends MockExtendableEvent implements PushEvent { + readonly data = { json: () => this._data, - }; + text: () => JSON.stringify(this._data), + } as PushMessageData; constructor(private _data: object) { super('push'); diff --git a/packages/service-worker/worker/testing/scope.ts b/packages/service-worker/worker/testing/scope.ts index 2619a8de94..3dd0dcac5b 100644 --- a/packages/service-worker/worker/testing/scope.ts +++ b/packages/service-worker/worker/testing/scope.ts @@ -13,7 +13,7 @@ import {AssetGroupConfig, Manifest} from '../src/manifest'; import {sha1} from '../src/sha1'; import {MockCacheStorage} from './cache'; -import {MockActivateEvent, MockFetchEvent, MockInstallEvent, MockMessageEvent, MockNotificationEvent, MockPushEvent} from './events'; +import {MockActivateEvent, MockExtendableMessageEvent, MockFetchEvent, MockInstallEvent, MockNotificationEvent, MockPushEvent} from './events'; import {MockHeaders, MockRequest, MockResponse} from './fetch'; import {MockServerState, MockServerStateBuilder} from './mock'; import {normalizeUrl, parseUrl} from './utils'; @@ -244,12 +244,13 @@ export class SwTestHarness extends Adapter implements ServiceW if (!this.eventHandlers.has('message')) { throw new Error('No message handler registered'); } - let event: MockMessageEvent; + let event: MockExtendableMessageEvent; if (clientId === null) { - event = new MockMessageEvent(data, null); + event = new MockExtendableMessageEvent(data, null); } else { this.clients.add(clientId); - event = new MockMessageEvent(data, this.clients.getMock(clientId) || null); + event = new MockExtendableMessageEvent( + data, this.clients.getMock(clientId) as unknown as Client || null); } this.eventHandlers.get('message')!.call(this, event); return event.ready;