diff --git a/packages/examples/service-worker/push/BUILD.bazel b/packages/examples/service-worker/push/BUILD.bazel
new file mode 100644
index 0000000000..3a8460d255
--- /dev/null
+++ b/packages/examples/service-worker/push/BUILD.bazel
@@ -0,0 +1,62 @@
+package(default_visibility = ["//visibility:public"])
+
+load("//tools:defaults.bzl", "ng_module", "ts_library")
+load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
+load("@npm_bazel_typescript//:index.bzl", "ts_devserver")
+
+ng_module(
+ name = "sw_push_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_push_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/push/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_push_examples"],
+)
+
+protractor_web_test_suite(
+ name = "protractor_tests",
+ data = ["//packages/bazel/src/protractor/utils"],
+ on_prepare = "start-server.js",
+ server = ":devserver",
+ deps = [
+ ":sw_push_e2e_tests_lib",
+ "@npm//protractor",
+ "@npm//selenium-webdriver",
+ ],
+)
diff --git a/packages/examples/service-worker/push/e2e_test/push_spec.ts b/packages/examples/service-worker/push/e2e_test/push_spec.ts
new file mode 100644
index 0000000000..bf01e83a49
--- /dev/null
+++ b/packages/examples/service-worker/push/e2e_test/push_spec.ts
@@ -0,0 +1,22 @@
+/**
+ * @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 `SwPush` example', () => {
+ const pageUrl = '/push';
+ const appElem = element(by.css('example-app'));
+
+ afterEach(verifyNoBrowserErrors);
+
+ it('should be enabled', () => {
+ browser.get(pageUrl);
+ expect(appElem.getText()).toBe('SW enabled: true');
+ });
+});
diff --git a/packages/examples/service-worker/push/main.ts b/packages/examples/service-worker/push/main.ts
new file mode 100644
index 0000000000..5ac1a58e47
--- /dev/null
+++ b/packages/examples/service-worker/push/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/push/module.ts b/packages/examples/service-worker/push/module.ts
new file mode 100644
index 0000000000..e0c06440ee
--- /dev/null
+++ b/packages/examples/service-worker/push/module.ts
@@ -0,0 +1,66 @@
+/**
+ * @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, NgModule} from '@angular/core';
+import {BrowserModule} from '@angular/platform-browser';
+import {ServiceWorkerModule} from '@angular/service-worker';
+// #docregion inject-sw-push
+import {SwPush} from '@angular/service-worker';
+// #enddocregion inject-sw-push
+// tslint:enable: no-duplicate-imports
+
+const PUBLIC_VAPID_KEY_OF_SERVER = '...';
+
+@Component({
+ selector: 'example-app',
+ template: 'SW enabled: {{ swPush.isEnabled }}',
+})
+// #docregion inject-sw-push
+export class AppComponent {
+ constructor(readonly swPush: SwPush) {}
+ // #enddocregion inject-sw-push
+
+ // #docregion subscribe-to-push
+ private async subscribeToPush() {
+ try {
+ const sub = await this.swPush.requestSubscription({
+ serverPublicKey: PUBLIC_VAPID_KEY_OF_SERVER,
+ });
+ // TODO: Send to server.
+ } catch (err) {
+ console.error('Could not subscribe due to:', err);
+ }
+ }
+ // #enddocregion subscribe-to-push
+
+ private subscribeToNotificationClicks() {
+ // #docregion subscribe-to-notification-clicks
+ this.swPush.notificationClicks.subscribe(
+ ({action, notification}) => {
+ // TODO: Do something in response to notification click.
+ });
+ // #enddocregion subscribe-to-notification-clicks
+ }
+ // #docregion inject-sw-push
+}
+// #enddocregion inject-sw-push
+
+@NgModule({
+ bootstrap: [
+ AppComponent,
+ ],
+ declarations: [
+ AppComponent,
+ ],
+ imports: [
+ BrowserModule,
+ ServiceWorkerModule.register('ngsw-worker.js'),
+ ],
+})
+export class AppModule {
+}
diff --git a/packages/examples/service-worker/push/ngsw-worker.js b/packages/examples/service-worker/push/ngsw-worker.js
new file mode 100644
index 0000000000..45b1769cca
--- /dev/null
+++ b/packages/examples/service-worker/push/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/push/start-server.js b/packages/examples/service-worker/push/start-server.js
new file mode 100644
index 0000000000..cd47c54c05
--- /dev/null
+++ b/packages/examples/service-worker/push/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('@bazel/protractor/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/push.ts b/packages/service-worker/src/push.ts
index 61e37129b9..38b8930f87 100644
--- a/packages/service-worker/src/push.ts
+++ b/packages/service-worker/src/push.ts
@@ -23,30 +23,14 @@ import {ERR_SW_NOT_SUPPORTED, NgswCommChannel, PushEvent} from './low_level';
* You can inject a `SwPush` instance into any component or service
* as a dependency.
*
- * ```ts
- * import {SwPush} from '@angular/service-worker';
- * ...
- * constructor(private swPush: SwPush) {}
- * ...
- * ```
+ *
*
* To subscribe, call `SwPush.requestSubscription()`, which asks the user for permission.
* The call returns a `Promise` with a new
* [`PushSubscription`](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription)
* instance.
*
- * ```ts
- * async subscribeToPush() {
- * try {
- * const sub = await this.swPush.requestSubscription({
- * serverPublicKey: PUBLIC_VAPID_KEY_OF_SERVER,
- * });
- * // TODO: Send to server.
- * } catch (e) {
- * console.error('Could not subscribe:', e);
- * }
- * }
- * ```
+ *
*
* A request is rejected if the user denies permission, or if the browser
* blocks or does not support the Push API or ServiceWorkers.
@@ -90,11 +74,7 @@ import {ERR_SW_NOT_SUPPORTED, NgswCommChannel, PushEvent} from './low_level';
* An application can subscribe to `SwPush.notificationClicks` observable to be notified when a user
* clicks on a notification. For example:
*
- * ```ts
- * swPush.notificationClicks.subscribe(({action, notification}) => {
- * // TODO: Do something in response to notification click.
- * });
- * ```
+ *
*
* @see [Push Notifications](https://developers.google.com/web/fundamentals/codelabs/push-notifications/)
* @see [Angular Push Notifications](https://blog.angular-university.io/angular-push-notifications/)