From 39c0152b76a362a44128207989c4081328a9147f Mon Sep 17 00:00:00 2001 From: deebloo Date: Thu, 25 Apr 2019 16:51:07 +0300 Subject: [PATCH] feat(service-worker): expose `SwRegistrationOptions` token to allow runtime config (#21842) Previously, the ServiceWorker registration options should be defined as an object literal (in order for them to be compatible with Ahead-of-Time compilation), thus making it impossible to base the ServiceWorker behavior on runtime conditions. This commit allows specifying the registration options using a regular provider, which means that it can take advantage of the `useFactory` option to determine the config at runtime, while still remaining compatible with AoT compilation. PR Close #21842 --- packages/service-worker/src/index.ts | 2 +- packages/service-worker/src/module.ts | 8 +++- packages/service-worker/test/comm_spec.ts | 41 ++++++++++++++++++- .../service-worker/service-worker.d.ts | 10 +++-- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/packages/service-worker/src/index.ts b/packages/service-worker/src/index.ts index a7defed04f..57bef7b8bc 100644 --- a/packages/service-worker/src/index.ts +++ b/packages/service-worker/src/index.ts @@ -15,6 +15,6 @@ */ export {UpdateActivatedEvent, UpdateAvailableEvent} from './low_level'; -export {ServiceWorkerModule} from './module'; +export {ServiceWorkerModule, SwRegistrationOptions} from './module'; export {SwPush} from './push'; export {SwUpdate} from './update'; diff --git a/packages/service-worker/src/module.ts b/packages/service-worker/src/module.ts index 3d324bc37d..15f174688b 100644 --- a/packages/service-worker/src/module.ts +++ b/packages/service-worker/src/module.ts @@ -14,6 +14,12 @@ import {NgswCommChannel} from './low_level'; import {SwPush} from './push'; import {SwUpdate} from './update'; +/** + * Token that can be used to provide options for `ServiceWorkerModule` outside of + * `ServiceWorkerModule.register()`. + * + * @publicApi + */ export abstract class SwRegistrationOptions { scope?: string; enabled?: boolean; @@ -69,7 +75,7 @@ export class ServiceWorkerModule { * If `enabled` is set to `false` in the given options, the module will behave as if service * workers are not supported by the browser, and the service worker will not be registered. */ - static register(script: string, opts: {scope?: string; enabled?: boolean;} = {}): + static register(script: string, opts: SwRegistrationOptions = {}): ModuleWithProviders { return { ngModule: ServiceWorkerModule, diff --git a/packages/service-worker/test/comm_spec.ts b/packages/service-worker/test/comm_spec.ts index 09b9af248e..3e313bc445 100644 --- a/packages/service-worker/test/comm_spec.ts +++ b/packages/service-worker/test/comm_spec.ts @@ -9,7 +9,7 @@ import {PLATFORM_ID} from '@angular/core'; import {TestBed} from '@angular/core/testing'; import {NgswCommChannel} from '@angular/service-worker/src/low_level'; -import {SwRegistrationOptions, ngswCommChannelFactory} from '@angular/service-worker/src/module'; +import {ServiceWorkerModule, SwRegistrationOptions, ngswCommChannelFactory} from '@angular/service-worker/src/module'; import {SwPush} from '@angular/service-worker/src/push'; import {SwUpdate} from '@angular/service-worker/src/update'; import {MockPushManager, MockPushSubscription, MockServiceWorkerContainer, MockServiceWorkerRegistration, patchDecodeBase64} from '@angular/service-worker/testing/mock'; @@ -47,6 +47,45 @@ import {async_fit, async_it} from './async'; }); }); + describe('ServiceWorkerModule config', () => { + it('SwUpdate isEnabled is false when configuring via static method', () => { + TestBed.configureTestingModule( + {imports: [ServiceWorkerModule.register('', {enabled: false})]}); + + expect(TestBed.get(SwUpdate).isEnabled).toEqual(false); + }); + + it('SwUpdate isEnabled is true when configuring via static method', () => { + TestBed.configureTestingModule({ + imports: [ServiceWorkerModule.register('', {enabled: true})], + providers: [{provide: NgswCommChannel, useValue: comm}] + }); + + expect(TestBed.get(SwUpdate).isEnabled).toEqual(true); + }); + + it('SwUpdate isEnabled is false when configuring directly via token', () => { + TestBed.configureTestingModule({ + imports: [ServiceWorkerModule.register('')], + providers: [{provide: SwRegistrationOptions, useFactory: () => ({enabled: false})}] + }); + + expect(TestBed.get(SwUpdate).isEnabled).toEqual(false); + }); + + it('SwUpdate isEnabled is true when configuring directly via token', () => { + TestBed.configureTestingModule({ + imports: [ServiceWorkerModule.register('')], + providers: [ + {provide: NgswCommChannel, useValue: comm}, + {provide: SwRegistrationOptions, useFactory: () => ({enabled: true})} + ] + }); + + expect(TestBed.get(SwUpdate).isEnabled).toEqual(true); + }); + }); + describe('ngswCommChannelFactory', () => { it('gives disabled NgswCommChannel for platform-server', () => { TestBed.configureTestingModule({ diff --git a/tools/public_api_guard/service-worker/service-worker.d.ts b/tools/public_api_guard/service-worker/service-worker.d.ts index b24a965be2..80eddf9878 100644 --- a/tools/public_api_guard/service-worker/service-worker.d.ts +++ b/tools/public_api_guard/service-worker/service-worker.d.ts @@ -1,8 +1,5 @@ export declare class ServiceWorkerModule { - static register(script: string, opts?: { - scope?: string; - enabled?: boolean; - }): ModuleWithProviders; + static register(script: string, opts?: SwRegistrationOptions): ModuleWithProviders; } export declare class SwPush { @@ -22,6 +19,11 @@ export declare class SwPush { unsubscribe(): Promise; } +export declare abstract class SwRegistrationOptions { + enabled?: boolean; + scope?: string; +} + export declare class SwUpdate { readonly activated: Observable; readonly available: Observable;