From aa53d6cc6d38620f43ca2044aed0d49a70a0ce89 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 25 Apr 2019 16:51:08 +0300 Subject: [PATCH] docs(service-worker): improve `SwRegistrationOptions` docs and add example (#21842) PR Close #21842 --- .../registration-options/BUILD.bazel | 62 +++++++++++++++++++ .../e2e_test/registration-options_spec.ts | 27 ++++++++ .../registration-options/main.ts | 12 ++++ .../registration-options/module.ts | 49 +++++++++++++++ .../registration-options/ngsw-worker.js | 14 +++++ .../registration-options/start-server.js | 17 +++++ packages/service-worker/src/module.ts | 20 +++++- packages/tsconfig.json | 2 +- 8 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 packages/examples/service-worker/registration-options/BUILD.bazel create mode 100644 packages/examples/service-worker/registration-options/e2e_test/registration-options_spec.ts create mode 100644 packages/examples/service-worker/registration-options/main.ts create mode 100644 packages/examples/service-worker/registration-options/module.ts create mode 100644 packages/examples/service-worker/registration-options/ngsw-worker.js create mode 100644 packages/examples/service-worker/registration-options/start-server.js diff --git a/packages/examples/service-worker/registration-options/BUILD.bazel b/packages/examples/service-worker/registration-options/BUILD.bazel new file mode 100644 index 0000000000..b9b9e7f5b6 --- /dev/null +++ b/packages/examples/service-worker/registration-options/BUILD.bazel @@ -0,0 +1,62 @@ +package(default_visibility = ["//visibility:public"]) + +load("//packages/bazel:index.bzl", "protractor_web_test_suite") +load("//tools:defaults.bzl", "ng_module", "ts_library") +load("@npm_bazel_typescript//:index.bzl", "ts_devserver") + +ng_module( + name = "sw_registration_options_examples", + srcs = glob( + ["**/*.ts"], + exclude = ["**/*_spec.ts"], + ), + # TODO: FW-1004 Type checking is currently not complete. + type_check = False, + deps = [ + "//packages/core", + "//packages/platform-browser", + "//packages/platform-browser-dynamic", + "//packages/service-worker", + ], +) + +ts_library( + name = "sw_registration_options_e2e_tests_lib", + testonly = True, + srcs = glob(["**/e2e_test/*_spec.ts"]), + tsconfig = "//packages/examples:tsconfig-e2e.json", + deps = [ + "//packages/examples/test-utils", + "//packages/private/testing", + "@npm//@types/jasminewd2", + "@npm//protractor", + ], +) + +ts_devserver( + name = "devserver", + entry_module = "@angular/examples/service-worker/registration-options/main", + index_html = "//packages/examples:index.html", + port = 4200, + scripts = [ + "//tools/rxjs:rxjs_umd_modules", + "@npm//node_modules/tslib:tslib.js", + ], + static_files = [ + "ngsw-worker.js", + "@npm//node_modules/zone.js:dist/zone.js", + ], + deps = [":sw_registration_options_examples"], +) + +protractor_web_test_suite( + name = "protractor_tests", + data = ["//packages/bazel/src/protractor/utils"], + on_prepare = "start-server.js", + server = ":devserver", + deps = [ + ":sw_registration_options_e2e_tests_lib", + "@npm//protractor", + "@npm//selenium-webdriver", + ], +) diff --git a/packages/examples/service-worker/registration-options/e2e_test/registration-options_spec.ts b/packages/examples/service-worker/registration-options/e2e_test/registration-options_spec.ts new file mode 100644 index 0000000000..5af093b1f4 --- /dev/null +++ b/packages/examples/service-worker/registration-options/e2e_test/registration-options_spec.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {browser, by, element} from 'protractor'; +import {verifyNoBrowserErrors} from '../../../test-utils'; + +describe('SW `SwRegistrationOptions` example', () => { + const pageUrl = '/registration-options'; + const appElem = element(by.css('example-app')); + + afterEach(verifyNoBrowserErrors); + + it('not register the SW by default', () => { + browser.get(pageUrl); + expect(appElem.getText()).toBe('SW enabled: false'); + }); + + it('register the SW when navigating to `?sw=true`', () => { + browser.get(`${pageUrl}?sw=true`); + expect(appElem.getText()).toBe('SW enabled: true'); + }); +}); diff --git a/packages/examples/service-worker/registration-options/main.ts b/packages/examples/service-worker/registration-options/main.ts new file mode 100644 index 0000000000..5ac1a58e47 --- /dev/null +++ b/packages/examples/service-worker/registration-options/main.ts @@ -0,0 +1,12 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; +import {AppModuleNgFactory} from './module.ngfactory'; + +platformBrowserDynamic().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/packages/examples/service-worker/registration-options/module.ts b/packages/examples/service-worker/registration-options/module.ts new file mode 100644 index 0000000000..c7128ccc02 --- /dev/null +++ b/packages/examples/service-worker/registration-options/module.ts @@ -0,0 +1,49 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +// tslint:disable: no-duplicate-imports +import {Component} from '@angular/core'; +// #docregion registration-options +import {NgModule} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; +import {ServiceWorkerModule, SwRegistrationOptions} from '@angular/service-worker'; +// #enddocregion registration-options +import {SwUpdate} from '@angular/service-worker'; +// tslint:enable: no-duplicate-imports + +@Component({ + selector: 'example-app', + template: 'SW enabled: {{ swu.isEnabled }}', +}) +export class AppComponent { + constructor(readonly swu: SwUpdate) {} +} +// #docregion registration-options + +@NgModule({ + // #enddocregion registration-options + bootstrap: [ + AppComponent, + ], + declarations: [ + AppComponent, + ], + // #docregion registration-options + imports: [ + BrowserModule, + ServiceWorkerModule.register('ngsw-worker.js'), + ], + providers: [ + { + provide: SwRegistrationOptions, + useFactory: () => ({enabled: location.search.includes('sw=true')}), + }, + ], +}) +export class AppModule { +} +// #enddocregion registration-options diff --git a/packages/examples/service-worker/registration-options/ngsw-worker.js b/packages/examples/service-worker/registration-options/ngsw-worker.js new file mode 100644 index 0000000000..45b1769cca --- /dev/null +++ b/packages/examples/service-worker/registration-options/ngsw-worker.js @@ -0,0 +1,14 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +// Mock `ngsw-worker.js` used for testing the examples. +// Immediately takes over and unregisters itself. +self.addEventListener('install', evt => evt.waitUntil(self.skipWaiting())); +self.addEventListener( + 'activate', + evt => evt.waitUntil(self.clients.claim().then(() => self.registration.unregister()))); diff --git a/packages/examples/service-worker/registration-options/start-server.js b/packages/examples/service-worker/registration-options/start-server.js new file mode 100644 index 0000000000..e7d432281a --- /dev/null +++ b/packages/examples/service-worker/registration-options/start-server.js @@ -0,0 +1,17 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +const protractorUtils = require('@angular/bazel/protractor-utils'); +const protractor = require('protractor'); + +module.exports = async function(config) { + const {port} = await protractorUtils.runServer(config.workspace, config.server, '-port', []); + const serverUrl = `http://localhost:${port}`; + + protractor.browser.baseUrl = serverUrl; +}; diff --git a/packages/service-worker/src/module.ts b/packages/service-worker/src/module.ts index 15f174688b..ddcd9102a4 100644 --- a/packages/service-worker/src/module.ts +++ b/packages/service-worker/src/module.ts @@ -18,11 +18,29 @@ import {SwUpdate} from './update'; * Token that can be used to provide options for `ServiceWorkerModule` outside of * `ServiceWorkerModule.register()`. * + * You can use this token to define a provider that generates the registration options at runtime, + * for example via a function call: + * + * {@example service-worker/registration-options/module.ts region="registration-options" + * header="app.module.ts" linenums="false"} + * * @publicApi */ export abstract class SwRegistrationOptions { - scope?: string; + /** + * Whether the ServiceWorker will be registered and the related services (such as `SwPush` and + * `SwUpdate`) will attempt to communicate and interact with it. + * + * Default: true + */ enabled?: boolean; + + /** + * A URL that defines the ServiceWorker's registration scope; that is, what range of URLs it can + * control. It will be used when calling + * [ServiceWorkerContainer#register()](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register). + */ + scope?: string; } export const SCRIPT = new InjectionToken('NGSW_REGISTER_SCRIPT'); diff --git a/packages/tsconfig.json b/packages/tsconfig.json index 8a3c22122f..f951fee5d1 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -39,7 +39,7 @@ "examples/**/e2e_test/*", // Exclude the "main.ts" files for each example group because this file is used by // Bazel to launch the devserver and uses AOT compilation. - "examples/*/main.ts", + "examples/**/main.ts", "platform-server/integrationtest", "router/test/aot_ngsummary_test", ]