From 06952b4f0fede6952e5f775b8dc2be708ea3f1d0 Mon Sep 17 00:00:00 2001 From: Matthieu Riegler Date: Mon, 26 Jan 2026 12:13:26 +0100 Subject: [PATCH] docs(docs-infra): remove unused examples (cherry picked from commit 899df39c7c18ea2a87e892241a575847a92c23a4) --- .../e2e/src/app.e2e-spec.ts | 185 ------ .../dependency-injection/example-config.json | 0 .../src/app/app-config.ts | 10 - .../src/app/app.component.1.ts | 17 - .../src/app/app.component.2.ts | 24 - .../src/app/app.component.ts | 72 --- .../src/app/app.config.ts | 16 - .../src/app/car/car-creations.ts | 39 -- .../src/app/car/car-factory.ts | 19 - .../src/app/car/car-injector.ts | 32 - .../src/app/car/car-no-di.ts | 21 - .../src/app/car/car.component.ts | 35 - .../dependency-injection/src/app/car/car.ts | 28 - .../src/app/heroes/dummy.module.ts | 34 - .../src/app/heroes/hero-list.component.1.ts | 15 - .../src/app/heroes/hero-list.component.2.ts | 24 - .../src/app/heroes/hero-list.component.ts | 24 - .../src/app/heroes/hero.service.0.ts | 6 - .../src/app/heroes/hero.service.1.ts | 12 - .../src/app/heroes/hero.service.2.ts | 15 - .../src/app/heroes/hero.service.3.ts | 14 - .../src/app/heroes/hero.service.5.ts | 20 - .../src/app/heroes/hero.service.provider.ts | 17 - .../src/app/heroes/hero.service.ts | 26 - .../src/app/heroes/hero.ts | 6 - .../src/app/heroes/heroes-tsp.component.ts | 18 - .../src/app/heroes/heroes.component.1.ts | 15 - .../src/app/heroes/heroes.component.ts | 15 - .../src/app/heroes/mock-heroes.ts | 14 - .../src/app/injection.config.ts | 13 - .../src/app/injector.component.ts | 45 -- .../src/app/logger.service.ts | 14 - .../src/app/providers.component.ts | 287 --------- .../src/app/providers.module.ts | 33 - .../src/app/test.component.ts | 54 -- .../src/app/tree-shaking/app.module.ts | 10 - .../app/tree-shaking/service-and-module.ts | 12 - .../src/app/tree-shaking/service.0.ts | 10 - .../src/app/tree-shaking/service.ts | 7 - .../src/app/user.service.ts | 25 - .../dependency-injection/src/index.html | 14 - .../examples/dependency-injection/src/main.ts | 5 - .../dependency-injection/stackblitz.json | 11 - .../injection-token/e2e/src/app.e2e-spec.ts | 8 - .../injection-token/example-config.json | 8 - .../examples/injection-token/src/main.ts | 26 - .../examples/pipes/e2e/src/app.e2e-spec.ts | 121 ---- .../examples/pipes/example-config.json | 0 .../examples/pipes/src/app/app.component.html | 45 -- .../examples/pipes/src/app/app.component.ts | 36 -- .../app/birthday-formatting.component.html | 8 - .../src/app/birthday-formatting.component.ts | 20 - .../app/birthday-pipe-chaining.component.html | 9 - .../app/birthday-pipe-chaining.component.ts | 11 - .../pipes/src/app/birthday.component.html | 1 - .../pipes/src/app/birthday.component.ts | 11 - .../src/app/exponential-strength.pipe.ts | 20 - .../app/flying-heroes-impure.component.html | 37 -- .../src/app/flying-heroes.component.html | 43 -- .../pipes/src/app/flying-heroes.component.ts | 83 --- .../pipes/src/app/flying-heroes.pipe.ts | 28 - .../src/app/hero-async-message.component.ts | 34 - .../examples/pipes/src/app/heroes.json | 6 - .../content/examples/pipes/src/app/heroes.ts | 10 - .../pipes/src/app/json-pipe.component.ts | 18 - .../pipes/src/app/power-booster.component.ts | 12 - .../pipes/src/app/precedence.component.html | 45 -- .../pipes/src/app/precedence.component.ts | 25 - .../examples/pipes/src/assets/heroes.json | 6 - .../src/content/examples/pipes/src/index.html | 13 - adev/src/content/examples/pipes/src/main.ts | 12 - .../content/examples/pipes/stackblitz.json | 7 - .../e2e/src/app.e2e-spec.ts | 17 - .../resolution-modifiers/example-config.json | 0 .../src/app/app.component.css | 0 .../src/app/app.component.html | 14 - .../src/app/app.component.ts | 32 - .../src/app/app.config.ts | 10 - .../src/app/flower.service.ts | 8 - .../app/host-child/host-child.component.css | 5 - .../app/host-child/host-child.component.html | 4 - .../app/host-child/host-child.component.ts | 11 - .../app/host-parent/host-parent.component.css | 5 - .../host-parent/host-parent.component.html | 5 - .../app/host-parent/host-parent.component.ts | 14 - .../src/app/host/host.component.css | 5 - .../src/app/host/host.component.html | 6 - .../src/app/host/host.component.ts | 20 - .../src/app/leaf.service.ts | 10 - .../src/app/optional.service.ts | 6 - .../src/app/optional/optional.component.css | 5 - .../src/app/optional/optional.component.html | 8 - .../src/app/optional/optional.component.ts | 18 - .../self-no-data/self-no-data.component.css | 5 - .../self-no-data/self-no-data.component.html | 4 - .../self-no-data/self-no-data.component.ts | 17 - .../src/app/self/self.component.css | 5 - .../src/app/self/self.component.html | 4 - .../src/app/self/self.component.ts | 17 - .../src/app/skipself/skipself.component.css | 5 - .../src/app/skipself/skipself.component.html | 4 - .../src/app/skipself/skipself.component.ts | 18 - .../resolution-modifiers/src/index.html | 13 - .../examples/resolution-modifiers/src/main.ts | 5 - .../resolution-modifiers/stackblitz.json | 10 - .../router-tutorial/e2e/src/app.e2e-spec.ts | 39 -- .../router-tutorial/example-config.json | 0 .../router-tutorial/src/app/app.component.css | 23 - .../src/app/app.component.html | 44 -- .../router-tutorial/src/app/app.component.ts | 15 - .../router-tutorial/src/app/app.config.ts | 9 - .../router-tutorial/src/app/app.routes.ts | 12 - .../app/crisis-list/crisis-list.component.css | 0 .../crisis-list/crisis-list.component.html | 2 - .../app/crisis-list/crisis-list.component.ts | 8 - .../app/heroes-list/heroes-list.component.css | 0 .../heroes-list/heroes-list.component.html | 2 - .../app/heroes-list/heroes-list.component.ts | 8 - .../page-not-found.component.css | 0 .../page-not-found.component.html | 2 - .../page-not-found.component.ts | 8 - .../examples/router-tutorial/src/index.html | 13 - .../examples/router-tutorial/src/main.ts | 6 - .../examples/router-tutorial/stackblitz.json | 9 - .../examples/router/example-config.json | 0 .../router/src/app/app.component.1.html | 9 - .../content/examples/router/src/index.html | 18 - adev/src/content/examples/router/src/main.ts | 8 - .../content/examples/router/stackblitz.json | 12 - .../examples/testing/e2e/src/app.e2e-spec.ts | 30 - .../examples/testing/example-config.json | 7 - .../src/app/about/about.component.spec.ts | 29 - .../testing/src/app/about/about.component.ts | 15 - .../src/app/app-initial.component.spec.ts | 70 -- .../testing/src/app/app-initial.component.ts | 11 - .../testing/src/app/app.component.html | 11 - .../src/app/app.component.router.spec.ts | 173 ----- .../testing/src/app/app.component.spec.ts | 131 ---- .../examples/testing/src/app/app.component.ts | 13 - .../examples/testing/src/app/app.config.ts | 30 - .../examples/testing/src/app/app.routes.ts | 11 - .../app/banner/banner-external.component.css | 4 - .../app/banner/banner-external.component.html | 1 - .../banner/banner-external.component.spec.ts | 78 --- .../app/banner/banner-external.component.ts | 14 - .../banner/banner-initial.component.spec.ts | 113 ---- .../app/banner/banner-initial.component.ts | 10 - .../banner.component.detect-changes.spec.ts | 48 -- .../src/app/banner/banner.component.spec.ts | 49 -- .../src/app/banner/banner.component.ts | 12 - .../dashboard/dashboard-hero.component.css | 30 - .../dashboard-hero.component.spec.ts | 155 ----- .../app/dashboard/dashboard-hero.component.ts | 26 - .../src/app/dashboard/dashboard.component.css | 36 -- .../app/dashboard/dashboard.component.html | 9 - .../dashboard.component.no-testbed.spec.ts | 62 -- .../app/dashboard/dashboard.component.spec.ts | 126 ---- .../src/app/dashboard/dashboard.component.ts | 42 -- .../testing/src/app/demo/async-helper.spec.ts | 210 ------ .../src/app/demo/demo-external-template.html | 1 - .../testing/src/app/demo/demo.spec.ts | 142 ----- .../testing/src/app/demo/demo.testbed.spec.ts | 599 ------------------ .../examples/testing/src/app/demo/demo.ts | 337 ---------- .../src/app/hero/hero-detail.component.css | 29 - .../src/app/hero/hero-detail.component.html | 15 - .../app/hero/hero-detail.component.spec.ts | 310 --------- .../src/app/hero/hero-detail.component.ts | 64 -- .../src/app/hero/hero-detail.service.ts | 29 - .../src/app/hero/hero-list.component.css | 70 -- .../src/app/hero/hero-list.component.html | 11 - .../src/app/hero/hero-list.component.spec.ts | 144 ----- .../src/app/hero/hero-list.component.ts | 32 - .../testing/src/app/hero/hero.routes.ts | 8 - .../testing/src/app/in-memory-data.service.ts | 24 - .../src/app/model/hero.service.spec.ts | 218 ------- .../testing/src/app/model/hero.service.ts | 95 --- .../examples/testing/src/app/model/hero.ts | 4 - .../examples/testing/src/app/model/index.ts | 3 - .../src/app/model/testing/http-client.spec.ts | 162 ----- .../testing/src/app/model/testing/index.ts | 1 - .../app/model/testing/test-hero.service.ts | 63 -- .../src/app/model/testing/test-heroes.ts | 13 - .../testing/src/app/model/user.service.ts | 7 - .../src/app/shared/canvas.component.spec.ts | 31 - .../src/app/shared/canvas.component.ts | 32 - .../app/shared/highlight.directive.spec.ts | 101 --- .../src/app/shared/highlight.directive.ts | 24 - .../examples/testing/src/app/shared/shared.ts | 6 - .../src/app/shared/title-case.pipe.spec.ts | 33 - .../testing/src/app/shared/title-case.pipe.ts | 12 - .../examples/testing/src/app/twain/quote.ts | 4 - .../app/twain/twain.component.marbles.spec.ts | 86 --- .../src/app/twain/twain.component.spec.ts | 157 ----- .../testing/src/app/twain/twain.component.ts | 47 -- .../testing/src/app/twain/twain.data.ts | 14 - .../testing/src/app/twain/twain.service.ts | 45 -- .../src/app/welcome/welcome.component.spec.ts | 77 --- .../src/app/welcome/welcome.component.ts | 20 - .../content/examples/testing/src/expected.ts | 1 - .../examples/testing/src/index-specs.html | 4 - .../content/examples/testing/src/index.html | 14 - adev/src/content/examples/testing/src/main.ts | 6 - .../src/content/examples/testing/src/test.css | 1 - .../src/testing/async-observable-helpers.ts | 33 - .../examples/testing/src/testing/index.ts | 34 - .../testing/src/testing/jasmine-matchers.d.ts | 6 - .../testing/src/testing/jasmine-matchers.ts | 51 -- .../content/examples/testing/stackblitz.json | 25 - .../content/guide/routing/router-reference.md | 4 +- .../content/guide/routing/router-tutorial.md | 276 -------- adev/src/context/llms-list.md | 1 - packages.bzl | 21 - packages/examples/injection-token/src/main.ts | 1 - .../debug_element_view_listener/providers.ts | 20 - 214 files changed, 3 insertions(+), 7694 deletions(-) delete mode 100644 adev/src/content/examples/dependency-injection/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/dependency-injection/example-config.json delete mode 100644 adev/src/content/examples/dependency-injection/src/app/app-config.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/app.component.1.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/app.component.2.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/app.component.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/app.config.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/car/car-creations.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/car/car-factory.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/car/car-injector.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/car/car-no-di.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/car/car.component.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/car/car.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/dummy.module.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.1.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.2.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.3.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.5.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.provider.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/hero.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/heroes/heroes-tsp.component.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.1.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/heroes/mock-heroes.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/injection.config.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/injector.component.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/logger.service.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/providers.component.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/providers.module.ts delete mode 100755 adev/src/content/examples/dependency-injection/src/app/test.component.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/tree-shaking/app.module.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/tree-shaking/service-and-module.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.0.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/app/user.service.ts delete mode 100644 adev/src/content/examples/dependency-injection/src/index.html delete mode 100755 adev/src/content/examples/dependency-injection/src/main.ts delete mode 100644 adev/src/content/examples/dependency-injection/stackblitz.json delete mode 100644 adev/src/content/examples/injection-token/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/injection-token/example-config.json delete mode 100644 adev/src/content/examples/injection-token/src/main.ts delete mode 100644 adev/src/content/examples/pipes/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/pipes/example-config.json delete mode 100644 adev/src/content/examples/pipes/src/app/app.component.html delete mode 100644 adev/src/content/examples/pipes/src/app/app.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/birthday-formatting.component.html delete mode 100644 adev/src/content/examples/pipes/src/app/birthday-formatting.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.html delete mode 100644 adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/birthday.component.html delete mode 100644 adev/src/content/examples/pipes/src/app/birthday.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/exponential-strength.pipe.ts delete mode 100644 adev/src/content/examples/pipes/src/app/flying-heroes-impure.component.html delete mode 100644 adev/src/content/examples/pipes/src/app/flying-heroes.component.html delete mode 100644 adev/src/content/examples/pipes/src/app/flying-heroes.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/flying-heroes.pipe.ts delete mode 100644 adev/src/content/examples/pipes/src/app/hero-async-message.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/heroes.json delete mode 100644 adev/src/content/examples/pipes/src/app/heroes.ts delete mode 100644 adev/src/content/examples/pipes/src/app/json-pipe.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/power-booster.component.ts delete mode 100644 adev/src/content/examples/pipes/src/app/precedence.component.html delete mode 100644 adev/src/content/examples/pipes/src/app/precedence.component.ts delete mode 100644 adev/src/content/examples/pipes/src/assets/heroes.json delete mode 100644 adev/src/content/examples/pipes/src/index.html delete mode 100644 adev/src/content/examples/pipes/src/main.ts delete mode 100644 adev/src/content/examples/pipes/stackblitz.json delete mode 100644 adev/src/content/examples/resolution-modifiers/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/resolution-modifiers/example-config.json delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/app.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/app.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/app.component.ts delete mode 100644 adev/src/content/examples/resolution-modifiers/src/app/app.config.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/flower.service.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host/host.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host/host.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/host/host.component.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/leaf.service.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/optional.service.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/self/self.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/self/self.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/self/self.component.ts delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.css delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.ts delete mode 100644 adev/src/content/examples/resolution-modifiers/src/index.html delete mode 100755 adev/src/content/examples/resolution-modifiers/src/main.ts delete mode 100644 adev/src/content/examples/resolution-modifiers/stackblitz.json delete mode 100644 adev/src/content/examples/router-tutorial/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/router-tutorial/example-config.json delete mode 100644 adev/src/content/examples/router-tutorial/src/app/app.component.css delete mode 100644 adev/src/content/examples/router-tutorial/src/app/app.component.html delete mode 100644 adev/src/content/examples/router-tutorial/src/app/app.component.ts delete mode 100644 adev/src/content/examples/router-tutorial/src/app/app.config.ts delete mode 100644 adev/src/content/examples/router-tutorial/src/app/app.routes.ts delete mode 100644 adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.css delete mode 100644 adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.html delete mode 100644 adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.ts delete mode 100644 adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.css delete mode 100644 adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.html delete mode 100644 adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.ts delete mode 100644 adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.css delete mode 100644 adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.html delete mode 100644 adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.ts delete mode 100644 adev/src/content/examples/router-tutorial/src/index.html delete mode 100644 adev/src/content/examples/router-tutorial/src/main.ts delete mode 100644 adev/src/content/examples/router-tutorial/stackblitz.json delete mode 100644 adev/src/content/examples/router/example-config.json delete mode 100644 adev/src/content/examples/router/src/app/app.component.1.html delete mode 100644 adev/src/content/examples/router/src/index.html delete mode 100644 adev/src/content/examples/router/src/main.ts delete mode 100644 adev/src/content/examples/router/stackblitz.json delete mode 100644 adev/src/content/examples/testing/e2e/src/app.e2e-spec.ts delete mode 100644 adev/src/content/examples/testing/example-config.json delete mode 100755 adev/src/content/examples/testing/src/app/about/about.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/about/about.component.ts delete mode 100755 adev/src/content/examples/testing/src/app/app-initial.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/app-initial.component.ts delete mode 100644 adev/src/content/examples/testing/src/app/app.component.html delete mode 100755 adev/src/content/examples/testing/src/app/app.component.router.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/app.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/app.component.ts delete mode 100644 adev/src/content/examples/testing/src/app/app.config.ts delete mode 100644 adev/src/content/examples/testing/src/app/app.routes.ts delete mode 100644 adev/src/content/examples/testing/src/app/banner/banner-external.component.css delete mode 100644 adev/src/content/examples/testing/src/app/banner/banner-external.component.html delete mode 100755 adev/src/content/examples/testing/src/app/banner/banner-external.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/banner/banner-external.component.ts delete mode 100755 adev/src/content/examples/testing/src/app/banner/banner-initial.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/banner/banner-initial.component.ts delete mode 100755 adev/src/content/examples/testing/src/app/banner/banner.component.detect-changes.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/banner/banner.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/banner/banner.component.ts delete mode 100644 adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.css delete mode 100755 adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.ts delete mode 100644 adev/src/content/examples/testing/src/app/dashboard/dashboard.component.css delete mode 100644 adev/src/content/examples/testing/src/app/dashboard/dashboard.component.html delete mode 100644 adev/src/content/examples/testing/src/app/dashboard/dashboard.component.no-testbed.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/dashboard/dashboard.component.ts delete mode 100644 adev/src/content/examples/testing/src/app/demo/async-helper.spec.ts delete mode 100644 adev/src/content/examples/testing/src/app/demo/demo-external-template.html delete mode 100644 adev/src/content/examples/testing/src/app/demo/demo.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/demo/demo.testbed.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/demo/demo.ts delete mode 100644 adev/src/content/examples/testing/src/app/hero/hero-detail.component.css delete mode 100644 adev/src/content/examples/testing/src/app/hero/hero-detail.component.html delete mode 100755 adev/src/content/examples/testing/src/app/hero/hero-detail.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/hero/hero-detail.component.ts delete mode 100755 adev/src/content/examples/testing/src/app/hero/hero-detail.service.ts delete mode 100644 adev/src/content/examples/testing/src/app/hero/hero-list.component.css delete mode 100644 adev/src/content/examples/testing/src/app/hero/hero-list.component.html delete mode 100755 adev/src/content/examples/testing/src/app/hero/hero-list.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/hero/hero-list.component.ts delete mode 100755 adev/src/content/examples/testing/src/app/hero/hero.routes.ts delete mode 100644 adev/src/content/examples/testing/src/app/in-memory-data.service.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/hero.service.spec.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/hero.service.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/hero.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/index.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/testing/http-client.spec.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/testing/index.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/testing/test-hero.service.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/testing/test-heroes.ts delete mode 100644 adev/src/content/examples/testing/src/app/model/user.service.ts delete mode 100755 adev/src/content/examples/testing/src/app/shared/canvas.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/shared/canvas.component.ts delete mode 100755 adev/src/content/examples/testing/src/app/shared/highlight.directive.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/shared/highlight.directive.ts delete mode 100755 adev/src/content/examples/testing/src/app/shared/shared.ts delete mode 100644 adev/src/content/examples/testing/src/app/shared/title-case.pipe.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/shared/title-case.pipe.ts delete mode 100644 adev/src/content/examples/testing/src/app/twain/quote.ts delete mode 100755 adev/src/content/examples/testing/src/app/twain/twain.component.marbles.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/twain/twain.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/twain/twain.component.ts delete mode 100644 adev/src/content/examples/testing/src/app/twain/twain.data.ts delete mode 100644 adev/src/content/examples/testing/src/app/twain/twain.service.ts delete mode 100755 adev/src/content/examples/testing/src/app/welcome/welcome.component.spec.ts delete mode 100755 adev/src/content/examples/testing/src/app/welcome/welcome.component.ts delete mode 100644 adev/src/content/examples/testing/src/expected.ts delete mode 100644 adev/src/content/examples/testing/src/index-specs.html delete mode 100644 adev/src/content/examples/testing/src/index.html delete mode 100755 adev/src/content/examples/testing/src/main.ts delete mode 100644 adev/src/content/examples/testing/src/test.css delete mode 100644 adev/src/content/examples/testing/src/testing/async-observable-helpers.ts delete mode 100644 adev/src/content/examples/testing/src/testing/index.ts delete mode 100644 adev/src/content/examples/testing/src/testing/jasmine-matchers.d.ts delete mode 100644 adev/src/content/examples/testing/src/testing/jasmine-matchers.ts delete mode 100644 adev/src/content/examples/testing/stackblitz.json delete mode 100644 adev/src/content/guide/routing/router-tutorial.md delete mode 100644 packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts diff --git a/adev/src/content/examples/dependency-injection/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/dependency-injection/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 70898dd3f55..00000000000 --- a/adev/src/content/examples/dependency-injection/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,185 +0,0 @@ -import {browser, element, by, ElementFinder} from 'protractor'; - -describe('Dependency Injection Tests', () => { - let expectedMsg: string; - let expectedMsgRx: RegExp; - - beforeAll(() => browser.get('')); - - describe('Cars:', () => { - it('DI car displays as expected', async () => { - expectedMsg = 'DI car with 4 cylinders and Flintstone tires.'; - expect(await element(by.css('#di')).getText()).toEqual(expectedMsg); - }); - - it('No DI car displays as expected', async () => { - expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.'; - expect(await element(by.css('#nodi')).getText()).toEqual(expectedMsg); - }); - - it('Injector car displays as expected', async () => { - expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.'; - expect(await element(by.css('#injector')).getText()).toEqual(expectedMsg); - }); - - it('Factory car displays as expected', async () => { - expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.'; - expect(await element(by.css('#factory')).getText()).toEqual(expectedMsg); - }); - - it('Simple car displays as expected', async () => { - expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.'; - expect(await element(by.css('#simple')).getText()).toEqual(expectedMsg); - }); - - it('Super car displays as expected', async () => { - expectedMsg = 'Super car with 12 cylinders and Flintstone tires.'; - expect(await element(by.css('#super')).getText()).toEqual(expectedMsg); - }); - - it('Test car displays as expected', async () => { - expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.'; - expect(await element(by.css('#test')).getText()).toEqual(expectedMsg); - }); - }); - - describe('Other Injections:', () => { - it('DI car displays as expected', async () => { - expectedMsg = 'DI car with 4 cylinders and Flintstone tires.'; - expect(await element(by.css('#car')).getText()).toEqual(expectedMsg); - }); - - it('Hero displays as expected', async () => { - expectedMsg = 'Dr. Nice'; - expect(await element(by.css('#hero')).getText()).toEqual(expectedMsg); - }); - - it('Optional injection displays as expected', async () => { - expectedMsg = "R.O.U.S.'s? I don't think they exist!"; - expect(await element(by.css('#rodent')).getText()).toEqual(expectedMsg); - }); - }); - - describe('Tests:', () => { - it('Tests display as expected', async () => { - expectedMsgRx = /Tests passed/; - expect(await element(by.css('#tests')).getText()).toMatch(expectedMsgRx); - }); - }); - - describe('Provider variations:', () => { - it('P1 (class) displays as expected', async () => { - expectedMsg = 'Hello from logger provided with Logger class'; - expect(await element(by.css('#p1')).getText()).toEqual(expectedMsg); - }); - - it('P3 (provide) displays as expected', async () => { - expectedMsg = 'Hello from logger provided with useClass:Logger'; - expect(await element(by.css('#p3')).getText()).toEqual(expectedMsg); - }); - - it('P4 (useClass:BetterLogger) displays as expected', async () => { - expectedMsg = 'Hello from logger provided with useClass:BetterLogger'; - expect(await element(by.css('#p4')).getText()).toEqual(expectedMsg); - }); - - it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', async () => { - expectedMsg = 'Message to Bob: Hello from EvenBetterlogger'; - expect(await element(by.css('#p5')).getText()).toEqual(expectedMsg); - }); - - it('P6a (no alias) displays as expected', async () => { - expectedMsg = 'Hello OldLogger (but we want NewLogger)'; - expect(await element(by.css('#p6a')).getText()).toEqual(expectedMsg); - }); - - it('P6b (alias) displays as expected', async () => { - expectedMsg = 'Hello from NewLogger (via aliased OldLogger)'; - expect(await element(by.css('#p6b')).getText()).toEqual(expectedMsg); - }); - - it('P7 (useValue) displays as expected', async () => { - expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"'; - expect(await element(by.css('#p7')).getText()).toEqual(expectedMsg); - }); - - it('P8 (useFactory) displays as expected', async () => { - expectedMsg = 'Hero service injected successfully via heroServiceProvider'; - expect(await element(by.css('#p8')).getText()).toEqual(expectedMsg); - }); - - it('P9 (InjectionToken) displays as expected', async () => { - expectedMsg = 'APP_CONFIG Application title is Dependency Injection'; - expect(await element(by.css('#p9')).getText()).toEqual(expectedMsg); - }); - - it('P10 (optional dependency) displays as expected', async () => { - expectedMsg = 'Optional logger was not available'; - expect(await element(by.css('#p10')).getText()).toEqual(expectedMsg); - }); - }); - - describe('User/Heroes:', () => { - it('User is Bob - unauthorized', async () => { - expectedMsgRx = /Bob, is not authorized/; - expect(await element(by.css('#user')).getText()).toMatch(expectedMsgRx); - }); - - it('should have button', async () => { - expect( - await element.all(by.cssContainingText('button', 'Next User')).get(0).isDisplayed(), - ).toBe(true, "'Next User' button should be displayed"); - }); - - it('unauthorized user should have multiple unauthorized heroes', async () => { - const heroes = element.all(by.css('#unauthorized app-hero-list div')); - expect(await heroes.count()).toBeGreaterThan(0); - }); - - it('unauthorized user should have no secret heroes', async () => { - const heroes = element.all(by.css('#unauthorized app-hero-list div')); - expect(await heroes.count()).toBeGreaterThan(0); - - const filteredHeroes = heroes.filter(async (elem) => /secret/.test(await elem.getText())); - expect(await filteredHeroes.count()).toEqual(0); - }); - - it('unauthorized user should have no authorized heroes listed', async () => { - expect(await element.all(by.css('#authorized app-hero-list div')).count()).toEqual(0); - }); - - describe('after button click', () => { - beforeAll(async () => { - const buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0); - await buttonEle.click(); - }); - - it('User is Alice - authorized', async () => { - expectedMsgRx = /Alice, is authorized/; - expect(await element(by.css('#user')).getText()).toMatch(expectedMsgRx); - }); - - it('authorized user should have multiple authorized heroes ', async () => { - const heroes = element.all(by.css('#authorized app-hero-list div')); - expect(await heroes.count()).toBeGreaterThan(0); - }); - - it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', async () => { - const heroes = element.all(by.css('#tspAuthorized app-hero-list div')); - expect(await heroes.count()).toBeGreaterThan(0); - }); - - it('authorized user should have secret heroes', async () => { - const heroes = element.all(by.css('#authorized app-hero-list div')); - expect(await heroes.count()).toBeGreaterThan(0); - - const filteredHeroes = heroes.filter(async (elem) => /secret/.test(await elem.getText())); - expect(await filteredHeroes.count()).toBeGreaterThan(0); - }); - - it('authorized user should have no unauthorized heroes listed', async () => { - expect(await element.all(by.css('#unauthorized app-hero-list div')).count()).toEqual(0); - }); - }); - }); -}); diff --git a/adev/src/content/examples/dependency-injection/example-config.json b/adev/src/content/examples/dependency-injection/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/dependency-injection/src/app/app-config.ts b/adev/src/content/examples/dependency-injection/src/app/app-config.ts deleted file mode 100644 index 81c0479ffdf..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/app-config.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - Must put this interface in its own file instead of app.config.ts - or else TypeScript gives a (bogus) warning: - WARNING in ./src/app/... .ts - "export 'AppConfig' was not found in './app.config' -*/ -export interface AppConfig { - apiEndpoint: string; - title: string; -} diff --git a/adev/src/content/examples/dependency-injection/src/app/app.component.1.ts b/adev/src/content/examples/dependency-injection/src/app/app.component.1.ts deleted file mode 100755 index de82a93ba6a..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/app.component.1.ts +++ /dev/null @@ -1,17 +0,0 @@ -// #docregion -import {Component} from '@angular/core'; -import {CarComponent} from './car/car.component'; -import {HeroesComponent} from './heroes/heroes.component'; - -@Component({ - selector: 'app-root', - template: ` -

{{ title }}

- - - `, - imports: [CarComponent, HeroesComponent], -}) -export class AppComponent { - title = 'Dependency Injection'; -} diff --git a/adev/src/content/examples/dependency-injection/src/app/app.component.2.ts b/adev/src/content/examples/dependency-injection/src/app/app.component.2.ts deleted file mode 100755 index e066411edf7..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/app.component.2.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {Component, Inject} from '@angular/core'; - -import {APP_CONFIG, AppConfig} from './injection.config'; -import {CarComponent} from './car/car.component'; -import {HeroesComponent} from './heroes/heroes.component'; - -@Component({ - selector: 'app-root', - template: ` -

{{ title }}

- - - `, - imports: [CarComponent, HeroesComponent], -}) -export class AppComponent { - title: string; - - // #docregion ctor - constructor(@Inject(APP_CONFIG) config: AppConfig) { - this.title = config.title; - } - // #enddocregion ctor -} diff --git a/adev/src/content/examples/dependency-injection/src/app/app.component.ts b/adev/src/content/examples/dependency-injection/src/app/app.component.ts deleted file mode 100755 index b1b5ed58663..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/app.component.ts +++ /dev/null @@ -1,72 +0,0 @@ -import {Component, Inject} from '@angular/core'; - -import {APP_CONFIG, AppConfig} from './injection.config'; -import {UserService} from './user.service'; -import {HeroesComponent} from './heroes/heroes.component'; -import {HeroesTspComponent} from './heroes/heroes-tsp.component'; -import {ProvidersComponent} from './providers.component'; -import {CarComponent} from './car/car.component'; -import {InjectorComponent} from './injector.component'; -import {TestComponent} from './test.component'; - -@Component({ - selector: 'app-root', - template: ` -

{{ title }}

- - - -

User

-

- {{ userInfo }} - -

- -

- @if (isAuthorized) { - - } - @if (!isAuthorized) { - - } - @if (isAuthorized) { - - } - -

- `, - imports: [ - HeroesComponent, - HeroesTspComponent, - ProvidersComponent, - CarComponent, - InjectorComponent, - TestComponent, - ], -}) -export class AppComponent { - title: string; - - constructor( - @Inject(APP_CONFIG) config: AppConfig, - private userService: UserService, - ) { - this.title = config.title; - } - - get isAuthorized() { - return this.user.isAuthorized; - } - nextUser() { - this.userService.getNewUser(); - } - get user() { - return this.userService.user; - } - - get userInfo() { - return ( - `Current user, ${this.user.name}, is ` + `${this.isAuthorized ? '' : 'not'} authorized. ` - ); - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/app.config.ts b/adev/src/content/examples/dependency-injection/src/app/app.config.ts deleted file mode 100644 index 32158046b4f..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/app.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {ApplicationConfig} from '@angular/core'; -import {Logger} from './logger.service'; -import {UserService} from './user.service'; -import {APP_CONFIG, HERO_DI_CONFIG} from './injection.config'; -import {provideProtractorTestingSupport} from '@angular/platform-browser'; - -const appConfig: ApplicationConfig = { - providers: [ - provideProtractorTestingSupport(), - Logger, - UserService, - {provide: APP_CONFIG, useValue: HERO_DI_CONFIG}, - ], -}; - -export default appConfig; diff --git a/adev/src/content/examples/dependency-injection/src/app/car/car-creations.ts b/adev/src/content/examples/dependency-injection/src/app/car/car-creations.ts deleted file mode 100644 index 289263d64b4..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/car/car-creations.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Examples with car and engine variations - -import {Car, Engine, Tires} from './car'; - -///////// example 1 //////////// -export function simpleCar() { - // Simple car with 4 cylinders and Flintstone tires. - const car = new Car(new Engine(), new Tires()); - car.description = 'Simple'; - return car; -} - -///////// example 2 //////////// -class Engine2 { - constructor(public cylinders: number) {} -} - -export function superCar() { - // Super car with 12 cylinders and Flintstone tires. - const bigCylinders = 12; - const car = new Car(new Engine2(bigCylinders), new Tires()); - car.description = 'Super'; - return car; -} - -/////////// example 3 ////////// -class MockEngine extends Engine { - override cylinders = 8; -} -class MockTires extends Tires { - override make = 'YokoGoodStone'; -} - -export function testCar() { - // Test car with 8 cylinders and YokoGoodStone tires. - const car = new Car(new MockEngine(), new MockTires()); - car.description = 'Test'; - return car; -} diff --git a/adev/src/content/examples/dependency-injection/src/app/car/car-factory.ts b/adev/src/content/examples/dependency-injection/src/app/car/car-factory.ts deleted file mode 100644 index 409233fccce..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/car/car-factory.ts +++ /dev/null @@ -1,19 +0,0 @@ -// #docregion -import {Engine, Tires, Car} from './car'; - -// BAD pattern! -export class CarFactory { - createCar() { - const car = new Car(this.createEngine(), this.createTires()); - car.description = 'Factory'; - return car; - } - - createEngine() { - return new Engine(); - } - - createTires() { - return new Tires(); - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/car/car-injector.ts b/adev/src/content/examples/dependency-injection/src/app/car/car-injector.ts deleted file mode 100644 index a0ac863a81f..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/car/car-injector.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Injector} from '@angular/core'; - -import {Car, Engine, Tires} from './car'; -import {Logger} from '../logger.service'; - -export function useInjector() { - let injector: Injector; - /* - // Cannot instantiate an Injector like this! - let injector = new Injector([ - { provide: Car, deps: [Engine, Tires] }, - { provide: Engine, deps: [] }, - { provide: Tires, deps: [] } - ]); - */ - injector = Injector.create({ - providers: [ - {provide: Car, deps: [Engine, Tires]}, - {provide: Engine, deps: []}, - {provide: Tires, deps: []}, - ], - }); - const car = injector.get(Car); - car.description = 'Injector'; - - injector = Injector.create({ - providers: [{provide: Logger, deps: []}], - }); - const logger = injector.get(Logger); - logger.log('Injector car.drive() said: ' + car.drive()); - return car; -} diff --git a/adev/src/content/examples/dependency-injection/src/app/car/car-no-di.ts b/adev/src/content/examples/dependency-injection/src/app/car/car-no-di.ts deleted file mode 100644 index a455580a216..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/car/car-no-di.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Car without DI -import {Engine, Tires} from './car'; - -export class Car { - public engine: Engine; - public tires: Tires; - public description = 'No DI'; - - constructor() { - this.engine = new Engine(); - this.tires = new Tires(); - } - - // Method using the engine and tires - drive() { - return ( - `${this.description} car with ` + - `${this.engine.cylinders} cylinders and ${this.tires.make} tires.` - ); - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/car/car.component.ts b/adev/src/content/examples/dependency-injection/src/app/car/car.component.ts deleted file mode 100755 index 8e94268e6af..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/car/car.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -// #docregion -import {Component, inject} from '@angular/core'; - -import {Car, Engine, Tires} from './car'; -import {Car as CarNoDi} from './car-no-di'; -import {CarFactory} from './car-factory'; - -import {testCar, simpleCar, superCar} from './car-creations'; - -import {useInjector} from './car-injector'; - -@Component({ - selector: 'app-car', - template: ` -

Cars

-
{{ car.drive() }}
-
{{ noDiCar.drive() }}
-
{{ injectorCar.drive() }}
-
{{ factoryCar.drive() }}
-
{{ simpleCar.drive() }}
-
{{ superCar.drive() }}
-
{{ testCar.drive() }}
- `, - providers: [Car, Engine, Tires], -}) -export class CarComponent { - factoryCar = new CarFactory().createCar(); - injectorCar = useInjector(); - noDiCar = new CarNoDi(); - simpleCar = simpleCar(); - superCar = superCar(); - testCar = testCar(); - - public car = inject(Car); -} diff --git a/adev/src/content/examples/dependency-injection/src/app/car/car.ts b/adev/src/content/examples/dependency-injection/src/app/car/car.ts deleted file mode 100644 index ba392feee8f..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/car/car.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {Injectable} from '@angular/core'; - -export class Engine { - public cylinders = 4; -} - -export class Tires { - public make = 'Flintstone'; - public model = 'Square'; -} - -@Injectable() -export class Car { - public description = 'DI'; - - constructor( - public engine: Engine, - public tires: Tires, - ) {} - - // Method using the engine and tires - drive() { - return ( - `${this.description} car with ` + - `${this.engine.cylinders} cylinders and ${this.tires.make} tires.` - ); - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/dummy.module.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/dummy.module.ts deleted file mode 100644 index c735a0f63f2..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/dummy.module.ts +++ /dev/null @@ -1,34 +0,0 @@ -/// Dummy modules to satisfy Angular Language Service -import {NgModule} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -//////// - -import {HeroListComponent as HeroListComponent1} from './hero-list.component.1'; - -@NgModule({ - imports: [CommonModule], - declarations: [HeroListComponent1], - exports: [HeroListComponent1], -}) -export class DummyModule1 {} - -///////// - -import {HeroListComponent as HeroListComponent2} from './hero-list.component.2'; - -@NgModule({ - imports: [CommonModule], - declarations: [HeroListComponent2], -}) -export class DummyModule2 {} - -///////// - -import {HeroesComponent as HeroesComponent1} from './heroes.component.1'; - -@NgModule({ - imports: [CommonModule, DummyModule1], - declarations: [HeroesComponent1], -}) -export class DummyModule3 {} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.1.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.1.ts deleted file mode 100755 index 15f66843eef..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.1.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {NgFor} from '@angular/common'; -import {Component} from '@angular/core'; -import {HEROES} from './mock-heroes'; - -@Component({ - selector: 'app-hero-list', - template: ` - @for (hero of heroes; track hero) { -
{{ hero.id }} - {{ hero.name }}
- } - `, -}) -export class HeroListComponent { - heroes = HEROES; -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.2.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.2.ts deleted file mode 100755 index b64f594d0bf..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.2.ts +++ /dev/null @@ -1,24 +0,0 @@ -// #docplaster -// #docregion -import {Component, inject} from '@angular/core'; -import {Hero} from './hero'; -// #enddocregion -import {HeroService} from './hero.service.1'; -/* -// #docregion -import { HeroService } from './hero.service'; -// #enddocregion -*/ -// #docregion - -@Component({ - selector: 'app-hero-list', - template: ` - @for (hero of heroes; track hero) { -
{{ hero.id }} - {{ hero.name }}
- } - `, -}) -export class HeroListComponent { - heroes: Hero[] = inject(HeroService).getHeroes(); -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.ts deleted file mode 100755 index 29dc09b405c..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero-list.component.ts +++ /dev/null @@ -1,24 +0,0 @@ -// #docregion -import {Component} from '@angular/core'; -import {Hero} from './hero'; -import {HeroService} from './hero.service'; -import {NgFor} from '@angular/common'; - -@Component({ - selector: 'app-hero-list', - template: ` - @for (hero of heroes; track hero) { -
{{ hero.id }} - {{ hero.name }} ({{ hero.isSecret ? 'secret' : 'public' }})
- } - `, -}) -export class HeroListComponent { - heroes: Hero[]; - - // #docregion ctor-signature - constructor( - heroService: HeroService, // #enddocregion ctor-signature - ) { - this.heroes = heroService.getHeroes(); - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts deleted file mode 100644 index afbf419544b..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {Injectable} from '@angular/core'; - -@Injectable({ - providedIn: 'root', -}) -export class HeroService {} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts deleted file mode 100644 index dbf412c8148..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts +++ /dev/null @@ -1,12 +0,0 @@ -// #docregion -import {Injectable} from '@angular/core'; -import {HEROES} from './mock-heroes'; - -@Injectable({ - providedIn: 'root', -}) -export class HeroService { - getHeroes() { - return HEROES; - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts deleted file mode 100644 index 10e2b278c26..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {inject, Injectable} from '@angular/core'; -import {HEROES} from './mock-heroes'; -import {Logger} from '../logger.service'; - -@Injectable({ - providedIn: 'root', -}) -export class HeroService { - private logger = inject(Logger); - - getHeroes() { - this.logger.log('Getting heroes ...'); - return HEROES; - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.3.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.3.ts deleted file mode 100644 index 9837be3a74d..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.3.ts +++ /dev/null @@ -1,14 +0,0 @@ -// #docregion -import {Injectable} from '@angular/core'; -import {HEROES} from './mock-heroes'; - -@Injectable({ - // declares that this service should be created - // by the root application injector. - providedIn: 'root', -}) -export class HeroService { - getHeroes() { - return HEROES; - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.5.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.5.ts deleted file mode 100644 index 7b444dbf89c..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.5.ts +++ /dev/null @@ -1,20 +0,0 @@ -// #docregion -import {EnvironmentInjector, inject, Injectable, runInInjectionContext} from '@angular/core'; - -@Injectable({providedIn: 'root'}) -export class SomeService {} - -// #docregion run-in-context -@Injectable({ - providedIn: 'root', -}) -export class HeroService { - private environmentInjector = inject(EnvironmentInjector); - - someMethod() { - runInInjectionContext(this.environmentInjector, () => { - inject(SomeService); // Do what you need with the injected service - }); - } -} -// #enddocregion run-in-context diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.provider.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.provider.ts deleted file mode 100644 index 529536d9ab2..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.provider.ts +++ /dev/null @@ -1,17 +0,0 @@ -// #docregion -import {HeroService} from './hero.service'; -import {Logger} from '../logger.service'; -import {UserService} from '../user.service'; - -// #docregion factory -const heroServiceFactory = (logger: Logger, userService: UserService) => - new HeroService(logger, userService.user.isAuthorized); -// #enddocregion factory - -// #docregion provider -export const heroServiceProvider = { - provide: HeroService, - useFactory: heroServiceFactory, - deps: [Logger, UserService], -}; -// #enddocregion provider diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.ts deleted file mode 100644 index c8ce4a34b4c..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.service.ts +++ /dev/null @@ -1,26 +0,0 @@ -// #docregion -import {Injectable} from '@angular/core'; -import {HEROES} from './mock-heroes'; -import {Logger} from '../logger.service'; -import {UserService} from '../user.service'; - -@Injectable({ - providedIn: 'root', - useFactory: (logger: Logger, userService: UserService) => - new HeroService(logger, userService.user.isAuthorized), - deps: [Logger, UserService], -}) -export class HeroService { - // #docregion internals - constructor( - private logger: Logger, - private isAuthorized: boolean, - ) {} - - getHeroes() { - const auth = this.isAuthorized ? 'authorized' : 'unauthorized'; - this.logger.log(`Getting heroes for ${auth} user.`); - return HEROES.filter((hero) => this.isAuthorized || !hero.isSecret); - } - // #enddocregion internals -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/hero.ts deleted file mode 100644 index 1128cf6be22..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/hero.ts +++ /dev/null @@ -1,6 +0,0 @@ -// #docregion -export interface Hero { - id: number; - name: string; - isSecret: boolean; -} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/heroes-tsp.component.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/heroes-tsp.component.ts deleted file mode 100755 index 9d71e3124a1..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/heroes-tsp.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {Component} from '@angular/core'; -import {HeroListComponent} from './hero-list.component'; - -/** - * A version of `HeroesComponent` that does not provide the `HeroService` (and thus relies on its - * `Injectable`-declared provider) in order to function. - * - * TSP stands for Tree-Shakeable Provider. - */ -@Component({ - selector: 'app-heroes-tsp', - template: ` -

Heroes

- - `, - imports: [HeroListComponent], -}) -export class HeroesTspComponent {} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.1.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.1.ts deleted file mode 100755 index 4fb2718ce1a..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.1.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {Component} from '@angular/core'; - -import {HeroService} from './hero.service'; -import {HeroListComponent} from './hero-list.component'; - -@Component({ - selector: 'app-heroes', - providers: [HeroService], - template: ` -

Heroes

- - `, - imports: [HeroListComponent], -}) -export class HeroesComponent {} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.ts deleted file mode 100755 index 9d6e4859b0b..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/heroes.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -// #docregion -import {Component} from '@angular/core'; -import {heroServiceProvider} from './hero.service.provider'; -import {HeroListComponent} from './hero-list.component'; - -@Component({ - selector: 'app-heroes', - providers: [heroServiceProvider], - template: ` -

Heroes

- - `, - imports: [HeroListComponent], -}) -export class HeroesComponent {} diff --git a/adev/src/content/examples/dependency-injection/src/app/heroes/mock-heroes.ts b/adev/src/content/examples/dependency-injection/src/app/heroes/mock-heroes.ts deleted file mode 100644 index 32c2c78412a..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/heroes/mock-heroes.ts +++ /dev/null @@ -1,14 +0,0 @@ -// #docregion -import {Hero} from './hero'; - -export const HEROES: Hero[] = [ - {id: 12, isSecret: false, name: 'Dr. Nice'}, - {id: 13, isSecret: false, name: 'Bombasto'}, - {id: 14, isSecret: false, name: 'Celeritas'}, - {id: 15, isSecret: false, name: 'Magneta'}, - {id: 16, isSecret: false, name: 'RubberMan'}, - {id: 17, isSecret: false, name: 'Dynama'}, - {id: 18, isSecret: true, name: 'Dr. IQ'}, - {id: 19, isSecret: true, name: 'Magma'}, - {id: 20, isSecret: true, name: 'Tornado'}, -]; diff --git a/adev/src/content/examples/dependency-injection/src/app/injection.config.ts b/adev/src/content/examples/dependency-injection/src/app/injection.config.ts deleted file mode 100755 index 4a76a54d7b7..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/injection.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {AppConfig} from './app-config'; -export {AppConfig} from './app-config'; - -// #docregion token -import {InjectionToken} from '@angular/core'; - -export const APP_CONFIG = new InjectionToken('app.config'); -// #enddocregion token - -export const HERO_DI_CONFIG: AppConfig = { - apiEndpoint: 'api.heroes.com', - title: 'Dependency Injection', -}; diff --git a/adev/src/content/examples/dependency-injection/src/app/injector.component.ts b/adev/src/content/examples/dependency-injection/src/app/injector.component.ts deleted file mode 100755 index 04e3e618cad..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/injector.component.ts +++ /dev/null @@ -1,45 +0,0 @@ -// #docplaster -// #docregion -import {Component, inject, Injector} from '@angular/core'; - -import {Car, Engine, Tires} from './car/car'; -import {Hero} from './heroes/hero'; -import {HeroService} from './heroes/hero.service'; -import {heroServiceProvider} from './heroes/hero.service.provider'; -import {Logger} from './logger.service'; - -@Component({ - selector: 'app-injectors', - template: ` -

Other Injections

-
{{ car.drive() }}
-
{{ hero.name }}
-
{{ rodent }}
- `, - providers: [Car, Engine, Tires, heroServiceProvider, Logger], -}) -export class InjectorComponent { - car: Car; - - heroService: HeroService; - hero: Hero; - - private injector = inject(Injector); - - constructor() { - this.car = this.injector.get(Car); - this.heroService = this.injector.get(HeroService); - this.hero = this.heroService.getHeroes()[0]; - } - - get rodent() { - const rousDontExist = "R.O.U.S.'s? I don't think they exist!"; - return this.injector.get(ROUS, rousDontExist); - } -} - -/** - * R.O.U.S. - Rodents Of Unusual Size - * // https://www.youtube.com/watch?v=BOv5ZjAOpC8 - */ -class ROUS {} diff --git a/adev/src/content/examples/dependency-injection/src/app/logger.service.ts b/adev/src/content/examples/dependency-injection/src/app/logger.service.ts deleted file mode 100644 index 0a132328a11..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/logger.service.ts +++ /dev/null @@ -1,14 +0,0 @@ -// #docregion -import {Injectable} from '@angular/core'; - -@Injectable({ - providedIn: 'root', -}) -export class Logger { - logs: string[] = []; // capture logs for testing - - log(message: string) { - this.logs.push(message); - console.log(message); - } -} diff --git a/adev/src/content/examples/dependency-injection/src/app/providers.component.ts b/adev/src/content/examples/dependency-injection/src/app/providers.component.ts deleted file mode 100755 index b264be3cfc4..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/providers.component.ts +++ /dev/null @@ -1,287 +0,0 @@ -/* - * A collection of demo components showing different ways to provide services - * in @Component metadata - */ -import {Component, inject, Injectable, OnInit} from '@angular/core'; - -import {APP_CONFIG, HERO_DI_CONFIG} from './injection.config'; - -import {HeroService} from './heroes/hero.service'; -import {heroServiceProvider} from './heroes/hero.service.provider'; -import {Logger} from './logger.service'; -import {UserService} from './user.service'; - -const template = '{{log}}'; - -@Component({ - selector: 'provider-1', - template, - // #docregion providers-logger - providers: [Logger], - // #enddocregion providers-logger -}) -export class Provider1Component { - log: string; - constructor() { - const logger = inject(Logger); - logger.log('Hello from logger provided with Logger class'); - this.log = logger.logs[0]; - } -} - -////////////////////////////////////////// - -@Component({ - selector: 'provider-3', - template, - providers: - // #docregion providers-3 - [{provide: Logger, useClass: Logger}], - // #enddocregion providers-3 -}) -export class Provider3Component { - log: string; - constructor() { - const logger = inject(Logger); - logger.log('Hello from logger provided with useClass:Logger'); - this.log = logger.logs[0]; - } -} - -////////////////////////////////////////// -export class BetterLogger extends Logger {} - -@Component({ - selector: 'provider-4', - template, - providers: - // #docregion providers-4 - [{provide: Logger, useClass: BetterLogger}], - // #enddocregion providers-4 -}) -export class Provider4Component { - log: string; - constructor() { - const logger = inject(Logger); - logger.log('Hello from logger provided with useClass:BetterLogger'); - this.log = logger.logs[0]; - } -} - -////////////////////////////////////////// - -// #docregion EvenBetterLogger -@Injectable() -export class EvenBetterLogger extends Logger { - private userService = inject(UserService); - - override log(message: string) { - const name = this.userService.user.name; - super.log(`Message to ${name}: ${message}`); - } -} -// #enddocregion EvenBetterLogger - -@Component({ - selector: 'provider-5', - template, - providers: - // #docregion providers-5 - [UserService, {provide: Logger, useClass: EvenBetterLogger}], - // #enddocregion providers-5 -}) -export class Provider5Component { - log: string; - constructor() { - const logger = inject(Logger); - logger.log('Hello from EvenBetterlogger'); - this.log = logger.logs[0]; - } -} - -////////////////////////////////////////// - -export class NewLogger extends Logger {} - -export class OldLogger { - logs: string[] = []; - log(message: string) { - throw new Error('Should not call the old logger!'); - } -} - -@Component({ - selector: 'provider-6a', - template, - providers: [ - NewLogger, - // Not aliased! Creates two instances of `NewLogger` - {provide: OldLogger, useClass: NewLogger}, - ], -}) -export class Provider6aComponent { - log: string; - constructor() { - const newLogger = inject(NewLogger); - const oldLogger = inject(OldLogger); - if (newLogger === oldLogger) { - throw new Error('expected the two loggers to be different instances'); - } - oldLogger.log('Hello OldLogger (but we want NewLogger)'); - // The newLogger wasn't called so no logs[] - // display the logs of the oldLogger. - this.log = newLogger.logs[0] || oldLogger.logs[0]; - } -} - -@Component({ - selector: 'provider-6b', - template, - providers: - // #docregion providers-6b - [ - NewLogger, - // Alias OldLogger w/ reference to NewLogger - {provide: OldLogger, useExisting: NewLogger}, - ], - // #enddocregion providers-6b -}) -export class Provider6bComponent { - log: string; - constructor() { - const newLogger = inject(NewLogger); - const oldLogger = inject(OldLogger); - if (newLogger !== oldLogger) { - throw new Error('expected the two loggers to be the same instance'); - } - oldLogger.log('Hello from NewLogger (via aliased OldLogger)'); - this.log = newLogger.logs[0]; - } -} - -////////////////////////////////////////// - -// An object in the shape of the logger service -function silentLoggerFn() {} - -export const SilentLogger = { - logs: ['Silent logger says "Shhhhh!". Provided via "useValue"'], - log: silentLoggerFn, -}; - -@Component({ - selector: 'provider-7', - template, - providers: [{provide: Logger, useValue: SilentLogger}], -}) -export class Provider7Component { - log: string; - constructor() { - const logger = inject(Logger); - logger.log('Hello from logger provided with useValue'); - this.log = logger.logs[0]; - } -} - -///////////////// - -@Component({ - selector: 'provider-8', - template, - providers: [heroServiceProvider, Logger, UserService], -}) -export class Provider8Component { - // must be true else this component would have blown up at runtime - log = 'Hero service injected successfully via heroServiceProvider'; - - heroService = inject(HeroService); -} - -///////////////// - -@Component({ - selector: 'provider-9', - template, - /* - // #docregion providers-9-interface - // Can't use interface as provider token - [{ provide: AppConfig, useValue: HERO_DI_CONFIG })] - // #enddocregion providers-9-interface - */ - // #docregion providers-9 - providers: [{provide: APP_CONFIG, useValue: HERO_DI_CONFIG}], - // #enddocregion providers-9 -}) -export class Provider9Component { - log = ''; - /* - // #docregion provider-9-ctor-interface - // Can't inject using the interface as the parameter type - constructor(private config: AppConfig){ } - // #enddocregion provider-9-ctor-interface - */ - private config = inject(APP_CONFIG); - - constructor() { - this.log = 'APP_CONFIG Application title is ' + this.config.title; - } -} - -////////////////////////////////////////// -// Sample providers 1 to 7 illustrate a required logger dependency. -// Optional logger, can be null -import {Optional} from '@angular/core'; - -const someMessage = 'Hello from the injected logger'; - -@Component({ - selector: 'provider-10', - template, - providers: [{provide: Logger, useValue: null}], -}) -export class Provider10Component implements OnInit { - log = ''; - private logger = inject(Logger, {optional: true}); - - constructor() { - if (this.logger) { - this.logger.log(someMessage); - } - } - - ngOnInit() { - this.log = this.logger ? this.logger.logs[0] : 'Optional logger was not available'; - } -} - -///////////////// - -@Component({ - selector: 'app-providers', - template: ` -

Provider variations

-
-
-
-
-
-
-
-
-
-
- `, - imports: [ - Provider1Component, - Provider3Component, - Provider4Component, - Provider5Component, - Provider6aComponent, - Provider6bComponent, - Provider7Component, - Provider8Component, - Provider9Component, - Provider10Component, - ], -}) -export class ProvidersComponent {} diff --git a/adev/src/content/examples/dependency-injection/src/app/providers.module.ts b/adev/src/content/examples/dependency-injection/src/app/providers.module.ts deleted file mode 100644 index 4fc63a55f01..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/providers.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {NgModule} from '@angular/core'; - -import { - Provider1Component, - Provider3Component, - Provider4Component, - Provider5Component, - Provider6aComponent, - Provider6bComponent, - Provider7Component, - Provider8Component, - Provider9Component, - Provider10Component, - ProvidersComponent, -} from './providers.component'; - -@NgModule({ - declarations: [ - Provider1Component, - Provider3Component, - Provider4Component, - Provider5Component, - Provider6aComponent, - Provider6bComponent, - Provider7Component, - Provider8Component, - Provider9Component, - Provider10Component, - ProvidersComponent, - ], - exports: [ProvidersComponent], -}) -export class ProvidersModule {} diff --git a/adev/src/content/examples/dependency-injection/src/app/test.component.ts b/adev/src/content/examples/dependency-injection/src/app/test.component.ts deleted file mode 100755 index 03563660fe4..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/test.component.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Simulate a simple test -// Reader should look to the testing chapter for the real thing - -import {Component} from '@angular/core'; - -import {Hero} from './heroes/hero'; -import {HeroService} from './heroes/hero.service'; -import {HeroListComponent} from './heroes/hero-list.component'; - -@Component({ - selector: 'app-tests', - template: ` -

Tests

-

Tests {{ results.pass }}: {{ results.message }}

- `, -}) -export class TestComponent { - results = runTests(); -} - -///////////////////////////////////// -function runTests() { - const expectedHeroes = [{name: 'A'}, {name: 'B'}]; - const mockService = {getHeroes: () => expectedHeroes} as HeroService; - - it('should have heroes when HeroListComponent created', () => { - // Pass the mock to the constructor as the Angular injector would - const component = new HeroListComponent(mockService); - expect(component.heroes.length).toEqual(expectedHeroes.length); - }); - - return testResults; -} - -////////////////////////////////// -// Fake Jasmine infrastructure -let testName: string; -let testResults: {pass: string; message: string}; - -function expect(actual: any) { - return { - toEqual: (expected: any) => { - testResults = - actual === expected - ? {pass: 'passed', message: testName} - : {pass: 'failed', message: `${testName}; expected ${actual} to equal ${expected}.`}; - }, - }; -} - -function it(label: string, test: () => void) { - testName = label; - test(); -} diff --git a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/app.module.ts b/adev/src/content/examples/dependency-injection/src/app/tree-shaking/app.module.ts deleted file mode 100644 index 5b998b6f4f6..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/app.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {NgModule} from '@angular/core'; -import {BrowserModule} from '@angular/platform-browser'; -import {RouterModule} from '@angular/router'; -import {ServiceModule} from './service-and-module'; - -// #docregion -@NgModule({ - imports: [BrowserModule, RouterModule.forRoot([]), ServiceModule], -}) -export class AppModule {} diff --git a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service-and-module.ts b/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service-and-module.ts deleted file mode 100644 index 62492b3e867..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service-and-module.ts +++ /dev/null @@ -1,12 +0,0 @@ -// #docregion -import {Injectable, NgModule} from '@angular/core'; - -@Injectable() -export class Service { - doSomething(): void {} -} - -@NgModule({ - providers: [Service], -}) -export class ServiceModule {} diff --git a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.0.ts b/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.0.ts deleted file mode 100644 index 521d1a1b535..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.0.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {Injectable} from '@angular/core'; - -// #docregion -@Injectable({ - providedIn: 'root', - useFactory: () => new Service('dependency'), -}) -export class Service { - constructor(private dep: string) {} -} diff --git a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.ts b/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.ts deleted file mode 100644 index e5dc837303a..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/tree-shaking/service.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {Injectable} from '@angular/core'; - -// #docregion -@Injectable({ - providedIn: 'root', -}) -export class Service {} diff --git a/adev/src/content/examples/dependency-injection/src/app/user.service.ts b/adev/src/content/examples/dependency-injection/src/app/user.service.ts deleted file mode 100644 index 31aaf61e150..00000000000 --- a/adev/src/content/examples/dependency-injection/src/app/user.service.ts +++ /dev/null @@ -1,25 +0,0 @@ -// #docregion -import {Injectable} from '@angular/core'; - -export class User { - constructor( - public name: string, - public isAuthorized = false, - ) {} -} - -// TODO: get the user; don't 'new' it. -const alice = new User('Alice', true); -const bob = new User('Bob', false); - -@Injectable({ - providedIn: 'root', -}) -export class UserService { - user = bob; // initial user is Bob - - // swap users - getNewUser() { - return (this.user = this.user === bob ? alice : bob); - } -} diff --git a/adev/src/content/examples/dependency-injection/src/index.html b/adev/src/content/examples/dependency-injection/src/index.html deleted file mode 100644 index 48414ec86c7..00000000000 --- a/adev/src/content/examples/dependency-injection/src/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Dependency Injection - - - - - - - - - diff --git a/adev/src/content/examples/dependency-injection/src/main.ts b/adev/src/content/examples/dependency-injection/src/main.ts deleted file mode 100755 index b03d104ab29..00000000000 --- a/adev/src/content/examples/dependency-injection/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {bootstrapApplication} from '@angular/platform-browser'; -import {AppComponent} from './app/app.component'; -import appConfig from './app/app.config'; - -bootstrapApplication(AppComponent, appConfig); diff --git a/adev/src/content/examples/dependency-injection/stackblitz.json b/adev/src/content/examples/dependency-injection/stackblitz.json deleted file mode 100644 index bb9b63d3087..00000000000 --- a/adev/src/content/examples/dependency-injection/stackblitz.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "description": "Dependency Injection", - "files":[ - "!**/*.d.ts", - "!**/*.js", - "!**/*.[0,1,2,3,4].*", - "!**/dummy.module.ts" - ], - "file": "src/app/app.component.ts", - "tags": ["dependency", "di"] -} diff --git a/adev/src/content/examples/injection-token/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/injection-token/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 540e3cb0224..00000000000 --- a/adev/src/content/examples/injection-token/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * This example project is special in that it is not a cli app. - * - * This is an empty placeholder file to ensure that example tests correctly runs - * tests for this project. - * - * TODO: Fix our infrastructure/tooling, so that this hack is not necessary. - */ diff --git a/adev/src/content/examples/injection-token/example-config.json b/adev/src/content/examples/injection-token/example-config.json deleted file mode 100644 index c07fa9794c5..00000000000 --- a/adev/src/content/examples/injection-token/example-config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "tests": [ - { - "cmd": "yarn", - "args": [ "tsc", "--project", "./tsconfig.app.json" ] - } - ] -} diff --git a/adev/src/content/examples/injection-token/src/main.ts b/adev/src/content/examples/injection-token/src/main.ts deleted file mode 100644 index 8923a32feb9..00000000000 --- a/adev/src/content/examples/injection-token/src/main.ts +++ /dev/null @@ -1,26 +0,0 @@ -// TODO: Add unit tests for this file. -/* eslint-disable @angular-eslint/no-output-native */ -// #docregion -import {Injector, InjectionToken} from '@angular/core'; - -interface MyInterface { - someProperty: string; -} - -// #docregion InjectionToken - -const TOKEN = new InjectionToken('SomeToken'); - -// Setting up the provider using the same token instance -const providers = [ - {provide: TOKEN, useValue: {someProperty: 'exampleValue'}}, // Mock value for MyInterface -]; - -// Creating the injector with the provider -const injector = Injector.create({providers}); - -// Retrieving the value using the same token instance -const myInterface = injector.get(TOKEN); -// myInterface is inferred to be MyInterface. - -// #enddocregion InjectionToken diff --git a/adev/src/content/examples/pipes/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/pipes/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 762b8118cc2..00000000000 --- a/adev/src/content/examples/pipes/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,121 +0,0 @@ -import {browser, element, by} from 'protractor'; - -describe('Pipes', () => { - beforeAll(() => browser.get('')); - - it('should open correctly', async () => { - expect(await element.all(by.tagName('h1')).get(0).getText()).toEqual('Pipes'); - expect(await element(by.css('app-birthday p')).getText()).toEqual( - `The hero's birthday is Apr 15, 1988`, - ); - }); - - it('should show 4 heroes', async () => { - expect(await element.all(by.css('app-hero-list div')).count()).toEqual(4); - }); - - it('should show a familiar hero in json', async () => { - expect( - await element(by.cssContainingText('app-hero-list p', 'Heroes as JSON')).getText(), - ).toContain('Bombasto'); - }); - - it('should show alternate birthday formats', async () => { - expect( - await element( - by.cssContainingText('app-birthday-formatting > p', `The hero's birthday is 4/15/88`), - ).isDisplayed(), - ).toBe(true); - expect( - await element( - by.cssContainingText('app-birthday-formatting > p', `The hero's birthday is Apr 15, 1988`), - ).isDisplayed(), - ).toBe(true); - }); - - it('should be able to chain and compose pipes', async () => { - const chainedPipeEles = element.all( - by.cssContainingText('app-birthday-pipe-chaining p', `The chained hero's`), - ); - expect(await chainedPipeEles.count()).toBe(2, 'should have 2 chained pipe examples'); - expect(await chainedPipeEles.get(0).getText()).toContain('APR 15, 1988'); - expect(await chainedPipeEles.get(1).getText()).toContain('FRIDAY, APRIL 15, 1988'); - }); - - it('should be able to use ExponentialStrengthPipe pipe', async () => { - const ele = element(by.css('app-power-booster p')); - expect(await ele.getText()).toContain('Super power boost: 1024'); - }); - - it('should be able to use the exponential calculator', async () => { - const eles = element.all(by.css('app-power-boost-calculator input')); - const baseInputEle = eles.get(0); - const factorInputEle = eles.get(1); - const outputEle = element(by.css('app-power-boost-calculator p')); - - await baseInputEle.clear(); - await baseInputEle.sendKeys('7'); - await factorInputEle.clear(); - await factorInputEle.sendKeys('3'); - expect(await outputEle.getText()).toContain('343'); - }); - - it('should support flying heroes (pure) ', async () => { - const nameEle = element(by.css('app-flying-heroes input[type="text"]')); - const canFlyCheckEle = element(by.css('app-flying-heroes #can-fly')); - const mutateCheckEle = element(by.css('app-flying-heroes #mutate')); - const resetEle = element(by.css('app-flying-heroes button')); - const flyingHeroesEle = element.all(by.css('app-flying-heroes #flyers div')); - - expect(await canFlyCheckEle.getAttribute('checked')).toEqual( - 'true', - 'should default to "can fly"', - ); - expect(await mutateCheckEle.getAttribute('checked')).toEqual( - 'true', - 'should default to mutating array', - ); - expect(await flyingHeroesEle.count()).toEqual(2, 'only two of the original heroes can fly'); - - await nameEle.sendKeys('test1\n'); - expect(await flyingHeroesEle.count()).toEqual(2, 'no change while mutating array'); - - await mutateCheckEle.click(); - await nameEle.sendKeys('test2\n'); - expect(await flyingHeroesEle.count()).toEqual(4, 'not mutating; should see both adds'); - expect(await flyingHeroesEle.get(2).getText()).toContain('test1'); - expect(await flyingHeroesEle.get(3).getText()).toContain('test2'); - - await resetEle.click(); - expect(await flyingHeroesEle.count()).toEqual(2, 'reset should restore original flying heroes'); - }); - - it('should support flying heroes (impure) ', async () => { - const nameEle = element(by.css('app-flying-heroes-impure input[type="text"]')); - const canFlyCheckEle = element(by.css('app-flying-heroes-impure #can-fly')); - const mutateCheckEle = element(by.css('app-flying-heroes-impure #mutate')); - const flyingHeroesEle = element.all(by.css('app-flying-heroes-impure #flyers div')); - - expect(await canFlyCheckEle.getAttribute('checked')).toEqual( - 'true', - 'should default to "can fly"', - ); - expect(await mutateCheckEle.getAttribute('checked')).toEqual( - 'true', - 'should default to mutating array', - ); - expect(await flyingHeroesEle.count()).toEqual(2, 'only two of the original heroes can fly'); - - await nameEle.sendKeys('test1\n'); - expect(await flyingHeroesEle.count()).toEqual( - 3, - 'new flying hero should show in mutating array', - ); - }); - - it('should show an async hero message', async () => { - expect(await element.all(by.tagName('app-hero-async-message')).get(0).getText()).toContain( - 'hero', - ); - }); -}); diff --git a/adev/src/content/examples/pipes/example-config.json b/adev/src/content/examples/pipes/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/pipes/src/app/app.component.html b/adev/src/content/examples/pipes/src/app/app.component.html deleted file mode 100644 index 8f707596f7a..00000000000 --- a/adev/src/content/examples/pipes/src/app/app.component.html +++ /dev/null @@ -1,45 +0,0 @@ -

Pipes

-Date Pipe -Date Pipe Formatting -Pipe Chaining -Power Booster custom pipe -Async Messages and AsyncPipe -Json Pipe for Debugging -Pipes and Precedence -Flying Heroes filter pipe (pure) -Flying Heroes filter pipe (impure) - -
-

Date Pipe

- - -
-

Date Pipe Formatting

- - -
-

Pipe Chaining

- - -
- - -

Pipes and Precedence

- - -
- - -
-

Json Pipe for Debugging

-

Use the JsonPipe to display component properties for debugging.

-data | json -

- -

- -
- - -
- diff --git a/adev/src/content/examples/pipes/src/app/app.component.ts b/adev/src/content/examples/pipes/src/app/app.component.ts deleted file mode 100644 index 894f313c2e3..00000000000 --- a/adev/src/content/examples/pipes/src/app/app.component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Component} from '@angular/core'; - -import {BirthdayComponent} from './birthday.component'; -import {BirthdayFormattingComponent} from './birthday-formatting.component'; -import {BirthdayPipeChainingComponent} from './birthday-pipe-chaining.component'; -import {FlyingHeroesComponent, FlyingHeroesImpureComponent} from './flying-heroes.component'; -import {HeroAsyncMessageComponent} from './hero-async-message.component'; -import {PrecedenceComponent} from './precedence.component'; -import {JsonPipeComponent} from './json-pipe.component'; -import {PowerBoosterComponent} from './power-booster.component'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - imports: [ - // Example components - BirthdayComponent, - BirthdayFormattingComponent, - BirthdayPipeChainingComponent, - FlyingHeroesComponent, - FlyingHeroesImpureComponent, - HeroAsyncMessageComponent, - PrecedenceComponent, - JsonPipeComponent, - PowerBoosterComponent, - ], - styles: [ - 'a[href] {display: block; padding: 10px 0;}', - 'a:hover {text-decoration: none;}', - 'h2 {margin: 0;}', - 'code {font-family: monospace; background-color: #eee; padding: 0.5em;}', - ], -}) -export class AppComponent { - birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based -} diff --git a/adev/src/content/examples/pipes/src/app/birthday-formatting.component.html b/adev/src/content/examples/pipes/src/app/birthday-formatting.component.html deleted file mode 100644 index d7fe15157e0..00000000000 --- a/adev/src/content/examples/pipes/src/app/birthday-formatting.component.html +++ /dev/null @@ -1,8 +0,0 @@ -

The hero's birthday is {{ birthday | date: 'shortDate' }} in the "shortDate" format.

- -

- The hero's birthday is {{ birthday | date: format }} in "{{ format }}" format. Click the toggle - button to change formats. -

- - diff --git a/adev/src/content/examples/pipes/src/app/birthday-formatting.component.ts b/adev/src/content/examples/pipes/src/app/birthday-formatting.component.ts deleted file mode 100644 index 9e9543cca31..00000000000 --- a/adev/src/content/examples/pipes/src/app/birthday-formatting.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {Component} from '@angular/core'; -import {DatePipe} from '@angular/common'; - -@Component({ - selector: 'app-birthday-formatting', - templateUrl: './birthday-formatting.component.html', - imports: [DatePipe], -}) -export class BirthdayFormattingComponent { - birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based - toggle = true; - - get format() { - return this.toggle ? 'mediumDate' : 'fullDate'; - } - - toggleFormat() { - this.toggle = !this.toggle; - } -} diff --git a/adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.html b/adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.html deleted file mode 100644 index 97483e9a1dc..00000000000 --- a/adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.html +++ /dev/null @@ -1,9 +0,0 @@ -

- The chained hero's uppercase birthday is - {{ birthday | date | uppercase }} -

- -

- The chained hero's uppercase birthday in "fullDate" format is - {{ birthday | date: 'fullDate' | uppercase }} -

diff --git a/adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.ts b/adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.ts deleted file mode 100644 index 035a80980af..00000000000 --- a/adev/src/content/examples/pipes/src/app/birthday-pipe-chaining.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {Component} from '@angular/core'; -import {DatePipe, UpperCasePipe} from '@angular/common'; - -@Component({ - selector: 'app-birthday-pipe-chaining', - templateUrl: './birthday-pipe-chaining.component.html', - imports: [DatePipe, UpperCasePipe], -}) -export class BirthdayPipeChainingComponent { - birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based -} diff --git a/adev/src/content/examples/pipes/src/app/birthday.component.html b/adev/src/content/examples/pipes/src/app/birthday.component.html deleted file mode 100644 index 51786992259..00000000000 --- a/adev/src/content/examples/pipes/src/app/birthday.component.html +++ /dev/null @@ -1 +0,0 @@ -

The hero's birthday is {{ birthday | date }}

diff --git a/adev/src/content/examples/pipes/src/app/birthday.component.ts b/adev/src/content/examples/pipes/src/app/birthday.component.ts deleted file mode 100644 index ce96fb1cc15..00000000000 --- a/adev/src/content/examples/pipes/src/app/birthday.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {Component} from '@angular/core'; -import {DatePipe} from '@angular/common'; - -@Component({ - selector: 'app-birthday', - templateUrl: './birthday.component.html', - imports: [DatePipe], -}) -export class BirthdayComponent { - birthday = new Date(1988, 3, 15); // April 15, 1988 -- since month parameter is zero-based -} diff --git a/adev/src/content/examples/pipes/src/app/exponential-strength.pipe.ts b/adev/src/content/examples/pipes/src/app/exponential-strength.pipe.ts deleted file mode 100644 index 1aa1fee76b3..00000000000 --- a/adev/src/content/examples/pipes/src/app/exponential-strength.pipe.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {Pipe, PipeTransform} from '@angular/core'; -/* - * Raise the value exponentially - * Takes an exponent argument that defaults to 1. - * Usage: - * value | exponentialStrength:exponent - * Example: - * {{ 2 | exponentialStrength:10 }} - * formats to: 1024 - */ -// #docregion pipe-class -@Pipe({ - name: 'exponentialStrength', -}) -export class ExponentialStrengthPipe implements PipeTransform { - transform(value: number, exponent = 1): number { - return Math.pow(value, exponent); - } -} -// #enddocregion pipe-class diff --git a/adev/src/content/examples/pipes/src/app/flying-heroes-impure.component.html b/adev/src/content/examples/pipes/src/app/flying-heroes-impure.component.html deleted file mode 100644 index 7202ee9b45e..00000000000 --- a/adev/src/content/examples/pipes/src/app/flying-heroes-impure.component.html +++ /dev/null @@ -1,37 +0,0 @@ - - -

{{ title }}

- - - -
- - -
- -
- Mutate array - -
- -

Heroes who fly (piped)

-
- - @for (hero of heroes | flyingHeroesImpure; track hero) { -
{{ hero.name }}
- } - -
- -

All Heroes (no pipe)

-
- @for (hero of heroes; track hero) { -
{{ hero.name }}
- } -
diff --git a/adev/src/content/examples/pipes/src/app/flying-heroes.component.html b/adev/src/content/examples/pipes/src/app/flying-heroes.component.html deleted file mode 100644 index 98afe701c54..00000000000 --- a/adev/src/content/examples/pipes/src/app/flying-heroes.component.html +++ /dev/null @@ -1,43 +0,0 @@ - - -

{{ title }}

-

Create a new hero and press enter to add it to the list.

- - - - -
- - -
-
- - - - - -
- -

Heroes who fly (piped)

-
- - @for (hero of heroes | flyingHeroes; track hero) { -
{{ hero.name }}
- } - -
- -

All Heroes (no pipe)

-
- - @for (hero of heroes; track hero) { -
{{ hero.name }}
- } - -
diff --git a/adev/src/content/examples/pipes/src/app/flying-heroes.component.ts b/adev/src/content/examples/pipes/src/app/flying-heroes.component.ts deleted file mode 100644 index 0796b7709e8..00000000000 --- a/adev/src/content/examples/pipes/src/app/flying-heroes.component.ts +++ /dev/null @@ -1,83 +0,0 @@ -// #docplaster -// #docregion -import {Component} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {FormsModule} from '@angular/forms'; - -import {FlyingHeroesPipe, FlyingHeroesImpurePipe} from './flying-heroes.pipe'; -import {HEROES} from './heroes'; - -@Component({ - selector: 'app-flying-heroes', - templateUrl: './flying-heroes.component.html', - imports: [CommonModule, FormsModule, FlyingHeroesPipe], - styles: [ - ` - #flyers, - #all { - font-style: italic; - } - button { - display: block; - } - input { - margin: 0.25rem 0.25rem 0.5rem 0; - } - `, - ], -}) -// #docregion v1 -export class FlyingHeroesComponent { - heroes: any[] = []; - canFly = true; - // #enddocregion v1 - mutate = true; - title = 'Flying Heroes (pure pipe)'; - - // #docregion v1 - constructor() { - this.reset(); - } - - addHero(name: string) { - name = name.trim(); - if (!name) { - return; - } - const hero = {name, canFly: this.canFly}; - // #enddocregion v1 - if (this.mutate) { - // Pure pipe won't update display because heroes array reference is unchanged - // Impure pipe will display - // #docregion v1 - // #docregion push - this.heroes.push(hero); - // #enddocregion push - // #enddocregion v1 - } else { - // Pipe updates display because heroes array is a new object - this.heroes = this.heroes.concat(hero); - } - // #docregion v1 - } - - reset() { - this.heroes = HEROES.slice(); - } -} -// #enddocregion v1 - -////// Identical except for impure pipe ////// -@Component({ - selector: 'app-flying-heroes-impure', - templateUrl: './flying-heroes-impure.component.html', - imports: [CommonModule, FormsModule, FlyingHeroesImpurePipe], - styles: [ - '#flyers, #all {font-style: italic}', - 'button {display: block}', - 'input {margin: .25rem .25rem .5rem 0;}', - ], -}) -export class FlyingHeroesImpureComponent extends FlyingHeroesComponent { - override title = 'Flying Heroes (impure pipe)'; -} diff --git a/adev/src/content/examples/pipes/src/app/flying-heroes.pipe.ts b/adev/src/content/examples/pipes/src/app/flying-heroes.pipe.ts deleted file mode 100644 index 278964d6d5e..00000000000 --- a/adev/src/content/examples/pipes/src/app/flying-heroes.pipe.ts +++ /dev/null @@ -1,28 +0,0 @@ -// #docregion -// #docregion pure -import {Pipe, PipeTransform} from '@angular/core'; - -import {Hero} from './heroes'; - -@Pipe({ - name: 'flyingHeroes', -}) -export class FlyingHeroesPipe implements PipeTransform { - transform(allHeroes: Hero[]) { - // #docregion filter - return allHeroes.filter((hero) => hero.canFly); - // #enddocregion filter - } -} -// #enddocregion pure - -/////// Identical except for the pure flag -// #docregion impure -// #docregion pipe-decorator -@Pipe({ - name: 'flyingHeroesImpure', - pure: false, -}) -// #enddocregion pipe-decorator -export class FlyingHeroesImpurePipe extends FlyingHeroesPipe {} -// #enddocregion impure diff --git a/adev/src/content/examples/pipes/src/app/hero-async-message.component.ts b/adev/src/content/examples/pipes/src/app/hero-async-message.component.ts deleted file mode 100644 index 72de7c50ae7..00000000000 --- a/adev/src/content/examples/pipes/src/app/hero-async-message.component.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {Component} from '@angular/core'; -import {AsyncPipe} from '@angular/common'; - -import {Observable, interval} from 'rxjs'; -import {map, startWith, take} from 'rxjs/operators'; - -@Component({ - selector: 'app-hero-async-message', - template: `

Async Messages and AsyncPipe

-

{{ message$ | async }}

- `, - imports: [AsyncPipe], -}) -export class HeroAsyncMessageComponent { - message$: Observable; - - private messages = ['You are my hero!', 'You are the best hero!', 'Will you be my hero?']; - - constructor() { - this.message$ = this.getResendObservable(); - } - - resend() { - this.message$ = this.getResendObservable(); - } - - private getResendObservable() { - return interval(1000).pipe( - map((i) => `Message #${i + 1}: ${this.messages[i]}`), - take(this.messages.length), - startWith('Waiting for messages...'), - ); - } -} diff --git a/adev/src/content/examples/pipes/src/app/heroes.json b/adev/src/content/examples/pipes/src/app/heroes.json deleted file mode 100644 index e5f0b77262f..00000000000 --- a/adev/src/content/examples/pipes/src/app/heroes.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - {"name": "Windstorm", "canFly": true}, - {"name": "Bombasto", "canFly": false}, - {"name": "Magneto", "canFly": false}, - {"name": "Tornado", "canFly": true} -] diff --git a/adev/src/content/examples/pipes/src/app/heroes.ts b/adev/src/content/examples/pipes/src/app/heroes.ts deleted file mode 100644 index 8e2ba072342..00000000000 --- a/adev/src/content/examples/pipes/src/app/heroes.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface Hero { - name: string; - canFly: boolean; -} -export const HEROES: Hero[] = [ - {name: 'Windstorm', canFly: true}, - {name: 'Bombasto', canFly: false}, - {name: 'Magneto', canFly: false}, - {name: 'Tornado', canFly: true}, -]; diff --git a/adev/src/content/examples/pipes/src/app/json-pipe.component.ts b/adev/src/content/examples/pipes/src/app/json-pipe.component.ts deleted file mode 100644 index 09f9c19f038..00000000000 --- a/adev/src/content/examples/pipes/src/app/json-pipe.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {Component} from '@angular/core'; -import {JsonPipe} from '@angular/common'; - -@Component({ - selector: 'app-json-pipe', - template: `{{ data | json }}`, - imports: [JsonPipe], -}) -export class JsonPipeComponent { - data = { - name: 'John Doe', - age: 30, - address: { - street: '123 Main St', - city: 'Anytown', - }, - }; -} diff --git a/adev/src/content/examples/pipes/src/app/power-booster.component.ts b/adev/src/content/examples/pipes/src/app/power-booster.component.ts deleted file mode 100644 index 1c70e3ed52b..00000000000 --- a/adev/src/content/examples/pipes/src/app/power-booster.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {Component} from '@angular/core'; -import {ExponentialStrengthPipe} from './exponential-strength.pipe'; - -@Component({ - selector: 'app-power-booster', - template: ` -

Power Booster

-

Super power boost: {{ 2 | exponentialStrength: 10 }}

- `, - imports: [ExponentialStrengthPipe], -}) -export class PowerBoosterComponent {} diff --git a/adev/src/content/examples/pipes/src/app/precedence.component.html b/adev/src/content/examples/pipes/src/app/precedence.component.html deleted file mode 100644 index da4265287ab..00000000000 --- a/adev/src/content/examples/pipes/src/app/precedence.component.html +++ /dev/null @@ -1,45 +0,0 @@ - - -

- In most cases, you'll wrap the entire ternary expression in parentheses before passing the result - to a pipe. -

- -

- Example: (isLeft ? 'left' : 'right') | uppercase - - {{ (isLeft ? 'left' : 'right') | uppercase }} - -

- - -

Without parentheses, only the second value is uppercased.

- -

- Example: isGood ? 'good' : 'bad' | uppercase - - {{ isGood ? 'good' : ('bad' | uppercase) }} - -

- -

- Same as: isGood ? 'good' : ('bad' | uppercase) - - {{ isGood ? 'good' : ('bad' | uppercase) }} - -

- - -

- If only one of the values should be passed to a pipe, be explicit and surround that value with - parentheses. -

- -

- Example: isUpper ? ('upper' | uppercase) : 'lower' - - {{ isUpper ? ('upper' | uppercase) : 'lower' }} - -

- - diff --git a/adev/src/content/examples/pipes/src/app/precedence.component.ts b/adev/src/content/examples/pipes/src/app/precedence.component.ts deleted file mode 100644 index 20bf24c12de..00000000000 --- a/adev/src/content/examples/pipes/src/app/precedence.component.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {Component} from '@angular/core'; -import {UpperCasePipe} from '@angular/common'; - -@Component({ - selector: 'app-pipe-precedence', - templateUrl: './precedence.component.html', - imports: [UpperCasePipe], - styles: ['code {font-family: monospace; background-color: #eee; padding: 0.5em;}'], -}) -export class PrecedenceComponent { - isLeft = true; - toggleDirection() { - this.isLeft = !this.isLeft; - } - - isGood = true; - toggleGood() { - this.isGood = !this.isGood; - } - - isUpper = true; - toggleCase() { - this.isUpper = !this.isUpper; - } -} diff --git a/adev/src/content/examples/pipes/src/assets/heroes.json b/adev/src/content/examples/pipes/src/assets/heroes.json deleted file mode 100644 index e5f0b77262f..00000000000 --- a/adev/src/content/examples/pipes/src/assets/heroes.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - {"name": "Windstorm", "canFly": true}, - {"name": "Bombasto", "canFly": false}, - {"name": "Magneto", "canFly": false}, - {"name": "Tornado", "canFly": true} -] diff --git a/adev/src/content/examples/pipes/src/index.html b/adev/src/content/examples/pipes/src/index.html deleted file mode 100644 index 79c649b2e7a..00000000000 --- a/adev/src/content/examples/pipes/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Pipes - - - - - - - - - diff --git a/adev/src/content/examples/pipes/src/main.ts b/adev/src/content/examples/pipes/src/main.ts deleted file mode 100644 index 34504c3be92..00000000000 --- a/adev/src/content/examples/pipes/src/main.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser'; -import {provideHttpClient} from '@angular/common/http'; - -import {AppComponent} from './app/app.component'; - -bootstrapApplication(AppComponent, { - // HttpClientModule is only used in deprecated HeroListComponent - providers: [ - provideHttpClient(), - provideProtractorTestingSupport(), // essential for e2e testing - ], -}); diff --git a/adev/src/content/examples/pipes/stackblitz.json b/adev/src/content/examples/pipes/stackblitz.json deleted file mode 100644 index a27408cfec1..00000000000 --- a/adev/src/content/examples/pipes/stackblitz.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Pipes", - "files":[ - "!**/*.d.ts", - "!**/*.js"], - "tags": ["pipe"] -} diff --git a/adev/src/content/examples/resolution-modifiers/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/resolution-modifiers/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 5b64dd7ce36..00000000000 --- a/adev/src/content/examples/resolution-modifiers/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {browser, element, by} from 'protractor'; - -describe('Resolution-modifiers-example', () => { - beforeAll(() => browser.get('')); - - it('shows basic flower emoji', async () => { - expect(await element.all(by.css('p')).get(0).getText()).toContain('🌸'); - }); - - it('shows basic leaf emoji', async () => { - expect(await element.all(by.css('p')).get(1).getText()).toContain('🌿'); - }); - - it('shows tulip in host child', async () => { - expect(await element.all(by.css('p')).get(9).getText()).toContain('🌷'); - }); -}); diff --git a/adev/src/content/examples/resolution-modifiers/example-config.json b/adev/src/content/examples/resolution-modifiers/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/resolution-modifiers/src/app/app.component.css b/adev/src/content/examples/resolution-modifiers/src/app/app.component.css deleted file mode 100755 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/resolution-modifiers/src/app/app.component.html b/adev/src/content/examples/resolution-modifiers/src/app/app.component.html deleted file mode 100755 index c66483cb0b6..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/app.component.html +++ /dev/null @@ -1,14 +0,0 @@ -

DI resolution modifiers

- -

Basic flower service: {{ flower.emoji }}

-

Basic leaf service: {{ leaf.emoji }}

- - - - - - - - - - diff --git a/adev/src/content/examples/resolution-modifiers/src/app/app.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/app.component.ts deleted file mode 100755 index d8d543a21ed..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/app.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Component} from '@angular/core'; -import {LeafService} from './leaf.service'; -import {FlowerService} from './flower.service'; -import {HostComponent} from './host/host.component'; -import {OptionalComponent} from './optional/optional.component'; -import {SelfComponent} from './self/self.component'; -import {HostParentComponent} from './host-parent/host-parent.component'; -import {HostChildComponent} from './host-child/host-child.component'; -import {SelfNoDataComponent} from './self-no-data/self-no-data.component'; -import {SkipselfComponent} from './skipself/skipself.component'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'], - imports: [ - HostComponent, - HostChildComponent, - HostParentComponent, - OptionalComponent, - SelfComponent, - SelfNoDataComponent, - SkipselfComponent, - ], -}) -export class AppComponent { - name = 'Angular'; - constructor( - public flower: FlowerService, - public leaf: LeafService, - ) {} -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/app.config.ts b/adev/src/content/examples/resolution-modifiers/src/app/app.config.ts deleted file mode 100644 index 25ca3f3cf33..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/app.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {ApplicationConfig} from '@angular/core'; -import {provideProtractorTestingSupport} from '@angular/platform-browser'; - -const appConfig: ApplicationConfig = { - providers: [ - provideProtractorTestingSupport(), //only needed for docs e2e testing - ], -}; - -export default appConfig; diff --git a/adev/src/content/examples/resolution-modifiers/src/app/flower.service.ts b/adev/src/content/examples/resolution-modifiers/src/app/flower.service.ts deleted file mode 100755 index 706d4bf11d6..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/flower.service.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Injectable} from '@angular/core'; - -@Injectable({ - providedIn: 'root', // provide this service in the root ModuleInjector -}) -export class FlowerService { - emoji = '🌸'; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.css b/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.css deleted file mode 100755 index 78336a39059..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.css +++ /dev/null @@ -1,5 +0,0 @@ -.section { - border: 2px solid #369; - padding: 1rem; - margin: 1rem 0; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.html b/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.html deleted file mode 100755 index d21f41c9520..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.html +++ /dev/null @@ -1,4 +0,0 @@ -
-

Child of @Host() Component

-

Flower emoji: {{ flower.emoji }}

-
diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.ts deleted file mode 100755 index a148594a603..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host-child/host-child.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {Component, inject} from '@angular/core'; -import {FlowerService} from '../flower.service'; - -@Component({ - selector: 'app-host-child', - templateUrl: './host-child.component.html', - styleUrls: ['./host-child.component.css'], -}) -export class HostChildComponent { - public flower = inject(FlowerService); -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.css b/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.css deleted file mode 100755 index 78336a39059..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.css +++ /dev/null @@ -1,5 +0,0 @@ -.section { - border: 2px solid #369; - padding: 1rem; - margin: 1rem 0; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.html b/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.html deleted file mode 100755 index 129d5b77aeb..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.html +++ /dev/null @@ -1,5 +0,0 @@ -
-

Parent of @Host() Component

-

Flower emoji: {{ flower.emoji }}

- -
diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.ts deleted file mode 100755 index 5c252129a50..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host-parent/host-parent.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {Component, inject} from '@angular/core'; -import {FlowerService} from '../flower.service'; -import {HostComponent} from '../host/host.component'; - -@Component({ - selector: 'app-host-parent', - templateUrl: './host-parent.component.html', - styleUrls: ['./host-parent.component.css'], - providers: [{provide: FlowerService, useValue: {emoji: '🌺'}}], - imports: [HostComponent], -}) -export class HostParentComponent { - public flower = inject(FlowerService); -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.css b/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.css deleted file mode 100755 index 78336a39059..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.css +++ /dev/null @@ -1,5 +0,0 @@ -.section { - border: 2px solid #369; - padding: 1rem; - margin: 1rem 0; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.html b/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.html deleted file mode 100755 index 1f17295fe8d..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.html +++ /dev/null @@ -1,6 +0,0 @@ -
-

@Host() Component

-

Flower emoji: {{ flower?.emoji }}

-

(@Host() stops it here)

- -
diff --git a/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.ts deleted file mode 100755 index 48bb6c25be2..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/host/host.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {Component, Host, Optional} from '@angular/core'; -import {FlowerService} from '../flower.service'; -import {HostChildComponent} from '../host-child/host-child.component'; - -// #docregion host-component -@Component({ - selector: 'app-host', - templateUrl: './host.component.html', - styleUrls: ['./host.component.css'], - // provide the service - providers: [{provide: FlowerService, useValue: {emoji: '🌷'}}], - imports: [HostChildComponent], -}) -export class HostComponent { - // use @Host() in the constructor when injecting the service - constructor(@Host() @Optional() public flower?: FlowerService) {} -} -// #enddocregion host-component - -// if you take out @Host() and the providers array, flower will be red hibiscus diff --git a/adev/src/content/examples/resolution-modifiers/src/app/leaf.service.ts b/adev/src/content/examples/resolution-modifiers/src/app/leaf.service.ts deleted file mode 100755 index b4f6b2e6df0..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/leaf.service.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {Injectable} from '@angular/core'; - -@Injectable({ - providedIn: 'root', -}) -// #docregion leafservice -export class LeafService { - emoji = '🌿'; -} -// #enddocregion leafservice diff --git a/adev/src/content/examples/resolution-modifiers/src/app/optional.service.ts b/adev/src/content/examples/resolution-modifiers/src/app/optional.service.ts deleted file mode 100755 index 05f31cbee3c..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/optional.service.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {Injectable} from '@angular/core'; - -@Injectable() -export class OptionalService {} - -// This service isn't provided anywhere. diff --git a/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.css b/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.css deleted file mode 100755 index 78336a39059..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.css +++ /dev/null @@ -1,5 +0,0 @@ -.section { - border: 2px solid #369; - padding: 1rem; - margin: 1rem 0; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.html b/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.html deleted file mode 100755 index e5017994904..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.html +++ /dev/null @@ -1,8 +0,0 @@ -
-

@Optional() Component

-

- This component still works even though the OptionalService (notice @Optional() in the - constructor isn't provided or configured anywhere. Angular goes through tree and visibility - rules, and if it doesn't find the requested service, returns null. -

-
diff --git a/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.ts deleted file mode 100755 index aaf3b36f221..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/optional/optional.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {Component, Optional} from '@angular/core'; -import {OptionalService} from '../optional.service'; - -@Component({ - selector: 'app-optional', - templateUrl: './optional.component.html', - styleUrls: ['./optional.component.css'], -}) - -// #docregion optional-component -export class OptionalComponent { - constructor(@Optional() public optional?: OptionalService) {} -} -// #enddocregion optional-component - -// The OptionalService isn't provided here, in the @Injectable() -// providers array, or in the NgModule. If you remove @Optional() -// from the constructor, you'll get an error. diff --git a/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.css b/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.css deleted file mode 100755 index 78336a39059..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.css +++ /dev/null @@ -1,5 +0,0 @@ -.section { - border: 2px solid #369; - padding: 1rem; - margin: 1rem 0; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.html b/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.html deleted file mode 100755 index 84d6306da3f..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.html +++ /dev/null @@ -1,4 +0,0 @@ -
-

@Self() Component (without a provider)

-

Leaf emoji: {{ leaf?.emoji }}

-
diff --git a/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.ts deleted file mode 100755 index b6673bfa4e8..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/self-no-data/self-no-data.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {Component, Self, Optional} from '@angular/core'; -import {LeafService} from '../leaf.service'; - -// #docregion self-no-data-component -@Component({ - selector: 'app-self-no-data', - templateUrl: './self-no-data.component.html', - styleUrls: ['./self-no-data.component.css'], -}) -export class SelfNoDataComponent { - constructor(@Self() @Optional() public leaf?: LeafService) {} -} - -// #enddocregion self-no-data-component - -// The app doesn't break because the value being available at self is optional. -// If you remove @Optional(), the app breaks. diff --git a/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.css b/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.css deleted file mode 100755 index 78336a39059..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.css +++ /dev/null @@ -1,5 +0,0 @@ -.section { - border: 2px solid #369; - padding: 1rem; - margin: 1rem 0; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.html b/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.html deleted file mode 100755 index fba7c08ed70..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.html +++ /dev/null @@ -1,4 +0,0 @@ -
-

@Self() Component

-

Flower emoji: {{ flower.emoji }}

-
diff --git a/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.ts deleted file mode 100755 index ec0e8b3bc13..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/self/self.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {Component, Self} from '@angular/core'; -import {FlowerService} from '../flower.service'; - -// #docregion self-component -@Component({ - selector: 'app-self', - templateUrl: './self.component.html', - styleUrls: ['./self.component.css'], - providers: [{provide: FlowerService, useValue: {emoji: '🌷'}}], -}) -export class SelfComponent { - constructor(@Self() public flower: FlowerService) {} -} -// #enddocregion self-component - -// This component provides the FlowerService so the injector -// doesn't have to look further up the injector tree diff --git a/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.css b/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.css deleted file mode 100755 index 78336a39059..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.css +++ /dev/null @@ -1,5 +0,0 @@ -.section { - border: 2px solid #369; - padding: 1rem; - margin: 1rem 0; -} diff --git a/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.html b/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.html deleted file mode 100755 index 01bc38abdeb..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.html +++ /dev/null @@ -1,4 +0,0 @@ -
-

@SkipSelf() Component

-

Leaf emoji: {{ leaf.emoji }}

-
diff --git a/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.ts b/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.ts deleted file mode 100755 index 0f663c65ff8..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/app/skipself/skipself.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {Component, SkipSelf} from '@angular/core'; -import {LeafService} from '../leaf.service'; - -// #docregion skipself-component -@Component({ - selector: 'app-skipself', - templateUrl: './skipself.component.html', - styleUrls: ['./skipself.component.css'], - // Angular would ignore this LeafService instance - providers: [{provide: LeafService, useValue: {emoji: '🍁'}}], -}) -export class SkipselfComponent { - // Use @SkipSelf() in the constructor - constructor(@SkipSelf() public leaf: LeafService) {} -} -// #enddocregion skipself-component - -// @SkipSelf(): Specifies that the dependency resolution should start from the parent injector, not here. diff --git a/adev/src/content/examples/resolution-modifiers/src/index.html b/adev/src/content/examples/resolution-modifiers/src/index.html deleted file mode 100644 index 846c8514a42..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - DI Resolution Modifiers Example - - - - - - Loading... - - diff --git a/adev/src/content/examples/resolution-modifiers/src/main.ts b/adev/src/content/examples/resolution-modifiers/src/main.ts deleted file mode 100755 index b03d104ab29..00000000000 --- a/adev/src/content/examples/resolution-modifiers/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {bootstrapApplication} from '@angular/platform-browser'; -import {AppComponent} from './app/app.component'; -import appConfig from './app/app.config'; - -bootstrapApplication(AppComponent, appConfig); diff --git a/adev/src/content/examples/resolution-modifiers/stackblitz.json b/adev/src/content/examples/resolution-modifiers/stackblitz.json deleted file mode 100644 index 6bc4252b821..00000000000 --- a/adev/src/content/examples/resolution-modifiers/stackblitz.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "description": "NgModules", - "files": [ - "!**/*.d.ts", - "!**/*.js", - "!**/*.[1,2].*" - ], - "file": "src/app/app.component.ts", - "tags": ["NgModules"] -} diff --git a/adev/src/content/examples/router-tutorial/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/router-tutorial/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 8f850c55638..00000000000 --- a/adev/src/content/examples/router-tutorial/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import {browser, element, by} from 'protractor'; - -describe('Router basic tutorial e2e tests', () => { - beforeEach(() => browser.get('')); - - it('should display Angular Router Sample', async () => { - expect(await element(by.css('h1')).getText()).toBe('Angular Router Sample'); - }); - - it('should display Crisis Center button', async () => { - expect(await element.all(by.css('a')).get(0).getText()).toBe('Crisis Center'); - }); - - it('should display Heroes button', async () => { - expect(await element.all(by.css('a')).get(1).getText()).toBe('Heroes'); - }); - - it('should display HEROES', async () => { - expect(await element(by.css('h3')).getText()).toBe('HEROES'); - }); - - it('should change to display crisis list component', async () => { - const crisisButton = element.all(by.css('a')).get(0); - await crisisButton.click(); - expect(await element(by.css('h3')).getText()).toBe('CRISIS CENTER'); - }); - - it('should change to display heroes component', async () => { - const heroesButton = element.all(by.css('a')).get(1); - await heroesButton.click(); - expect(await element(by.css('h3')).getText()).toBe('HEROES'); - }); - - it('should use wildcard route', async () => { - await browser.get('/fake-page'); - expect(await browser.getCurrentUrl()).toContain('fake-page'); - expect(await element(by.css('h2')).getText()).toBe('Page Not Found'); - }); -}); diff --git a/adev/src/content/examples/router-tutorial/example-config.json b/adev/src/content/examples/router-tutorial/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/router-tutorial/src/app/app.component.css b/adev/src/content/examples/router-tutorial/src/app/app.component.css deleted file mode 100644 index d48d0ce9468..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/app.component.css +++ /dev/null @@ -1,23 +0,0 @@ -.button { - box-shadow: inset 0 1px 0 0 #ffffff; - background: #ffffff linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%); - border-radius: 6px; - border: 1px solid #dcdcdc; - display: inline-block; - cursor: pointer; - color: #666666; - font-family: Arial, sans-serif; - font-size: 15px; - font-weight: bold; - padding: 6px 24px; - text-decoration: none; - text-shadow: 0 1px 0 #ffffff; - outline: 0; -} -.activebutton { - box-shadow: inset 0 1px 0 0 #dcecfb; - background: #bddbfa linear-gradient(to bottom, #bddbfa 5%, #80b5ea 100%); - border: 1px solid #84bbf3; - color: #ffffff; - text-shadow: 0 1px 0 #528ecc; -} diff --git a/adev/src/content/examples/router-tutorial/src/app/app.component.html b/adev/src/content/examples/router-tutorial/src/app/app.component.html deleted file mode 100644 index 80ae3a9a46d..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/app.component.html +++ /dev/null @@ -1,44 +0,0 @@ - - -

Angular Router Sample

- - - - - - - - -
- - - - - - - - - - -
diff --git a/adev/src/content/examples/router-tutorial/src/app/app.component.ts b/adev/src/content/examples/router-tutorial/src/app/app.component.ts deleted file mode 100644 index 30d8424ecd3..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/app.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {Component} from '@angular/core'; -import {RouterLink, RouterLinkActive, RouterOutlet} from '@angular/router'; - -import {CrisisListComponent} from './crisis-list/crisis-list.component'; -import {HeroesListComponent} from './heroes-list/heroes-list.component'; - -@Component({ - selector: 'app-root', - imports: [RouterOutlet, RouterLink, RouterLinkActive, CrisisListComponent, HeroesListComponent], - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'], -}) -export class AppComponent { - title = 'angular-router-sample'; -} diff --git a/adev/src/content/examples/router-tutorial/src/app/app.config.ts b/adev/src/content/examples/router-tutorial/src/app/app.config.ts deleted file mode 100644 index b4df777bde3..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/app.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {ApplicationConfig} from '@angular/core'; -import {provideProtractorTestingSupport} from '@angular/platform-browser'; -import {provideRouter} from '@angular/router'; - -import {routes} from './app.routes'; - -export const appConfig: ApplicationConfig = { - providers: [provideRouter(routes), provideProtractorTestingSupport()], -}; diff --git a/adev/src/content/examples/router-tutorial/src/app/app.routes.ts b/adev/src/content/examples/router-tutorial/src/app/app.routes.ts deleted file mode 100644 index e81d1e6ad4f..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/app.routes.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {Routes} from '@angular/router'; - -import {CrisisListComponent} from './crisis-list/crisis-list.component'; -import {HeroesListComponent} from './heroes-list/heroes-list.component'; -import {PageNotFoundComponent} from './page-not-found/page-not-found.component'; - -export const routes: Routes = [ - {path: 'crisis-list', component: CrisisListComponent}, - {path: 'heroes-list', component: HeroesListComponent}, - {path: '', redirectTo: '/heroes-list', pathMatch: 'full'}, - {path: '**', component: PageNotFoundComponent}, -]; diff --git a/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.css b/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.html b/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.html deleted file mode 100644 index 76ebcaf88ff..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.html +++ /dev/null @@ -1,2 +0,0 @@ -

CRISIS CENTER

-

Get your crisis here

diff --git a/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.ts b/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.ts deleted file mode 100644 index f4a8cad2792..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/crisis-list/crisis-list.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-crisis-list', - templateUrl: './crisis-list.component.html', - styleUrls: ['./crisis-list.component.css'], -}) -export class CrisisListComponent {} diff --git a/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.css b/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.html b/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.html deleted file mode 100644 index 563d7e44784..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.html +++ /dev/null @@ -1,2 +0,0 @@ -

HEROES

-

Get your heroes here

diff --git a/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.ts b/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.ts deleted file mode 100644 index 2532b1dbde1..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/heroes-list/heroes-list.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-heroes-list', - templateUrl: './heroes-list.component.html', - styleUrls: ['./heroes-list.component.css'], -}) -export class HeroesListComponent {} diff --git a/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.css b/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.html b/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.html deleted file mode 100644 index cd89fb76898..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.html +++ /dev/null @@ -1,2 +0,0 @@ -

Page Not Found

-

We couldn't find that page! Not even with x-ray vision.

diff --git a/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.ts b/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.ts deleted file mode 100644 index e2abef1049d..00000000000 --- a/adev/src/content/examples/router-tutorial/src/app/page-not-found/page-not-found.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-page-not-found', - templateUrl: './page-not-found.component.html', - styleUrls: ['./page-not-found.component.css'], -}) -export class PageNotFoundComponent {} diff --git a/adev/src/content/examples/router-tutorial/src/index.html b/adev/src/content/examples/router-tutorial/src/index.html deleted file mode 100644 index a5967ee545d..00000000000 --- a/adev/src/content/examples/router-tutorial/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Angular Router Sample - - - - - - - - diff --git a/adev/src/content/examples/router-tutorial/src/main.ts b/adev/src/content/examples/router-tutorial/src/main.ts deleted file mode 100644 index 92e4bd8713b..00000000000 --- a/adev/src/content/examples/router-tutorial/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {bootstrapApplication} from '@angular/platform-browser'; - -import {AppComponent} from './app/app.component'; -import {appConfig} from './app/app.config'; - -bootstrapApplication(AppComponent, appConfig); diff --git a/adev/src/content/examples/router-tutorial/stackblitz.json b/adev/src/content/examples/router-tutorial/stackblitz.json deleted file mode 100644 index 7e88374d3fd..00000000000 --- a/adev/src/content/examples/router-tutorial/stackblitz.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "description": "Router", - "files":[ - "!**/*.d.ts", - "!**/*.js", - "!**/*.[0-9].*" - ], - "tags": ["router-tutorial"] -} diff --git a/adev/src/content/examples/router/example-config.json b/adev/src/content/examples/router/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/adev/src/content/examples/router/src/app/app.component.1.html b/adev/src/content/examples/router/src/app/app.component.1.html deleted file mode 100644 index 925bb944cef..00000000000 --- a/adev/src/content/examples/router/src/app/app.component.1.html +++ /dev/null @@ -1,9 +0,0 @@ - -

Angular Router

- - diff --git a/adev/src/content/examples/router/src/index.html b/adev/src/content/examples/router/src/index.html deleted file mode 100644 index 51b7f07c498..00000000000 --- a/adev/src/content/examples/router/src/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - Angular Router - - - - - - - - - diff --git a/adev/src/content/examples/router/src/main.ts b/adev/src/content/examples/router/src/main.ts deleted file mode 100644 index 7ee4587a88e..00000000000 --- a/adev/src/content/examples/router/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -// #docregion -import {platformBrowser} from '@angular/platform-browser'; - -import {AppModule} from './app/app.module'; - -platformBrowser() - .bootstrapModule(AppModule) - .catch((err) => console.error(err)); diff --git a/adev/src/content/examples/router/stackblitz.json b/adev/src/content/examples/router/stackblitz.json deleted file mode 100644 index 043d2e74306..00000000000 --- a/adev/src/content/examples/router/stackblitz.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "description": "Router", - "files":[ - "!**/*.d.ts", - "!**/*.js", - "!**/*.[0-9].*", - "!src/app/crisis-list/*.*", - "!src/app/hero-list/*.*" - ], - "tags": ["router"], - "file": "src/app/app-routing.module.ts" -} diff --git a/adev/src/content/examples/testing/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/testing/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 93dba43b66e..00000000000 --- a/adev/src/content/examples/testing/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {browser, element, by} from 'protractor'; - -describe('Testing Example', () => { - const expectedViewNames = ['Dashboard', 'Heroes', 'About']; - - beforeAll(() => browser.get('')); - - function getPageElts() { - return { - navElts: element.all(by.css('app-root nav a')), - appDashboard: element(by.css('app-root app-dashboard')), - }; - } - - it('has title', async () => { - expect(await browser.getTitle()).toEqual('App Under Test'); - }); - - it(`has views ${expectedViewNames}`, async () => { - const viewNames = await getPageElts().navElts.map((el) => el!.getText()); - - expect(viewNames).toEqual(expectedViewNames); - }); - - it('has dashboard as the active view', async () => { - const page = getPageElts(); - - expect(await page.appDashboard.isPresent()).toBeTruthy(); - }); -}); diff --git a/adev/src/content/examples/testing/example-config.json b/adev/src/content/examples/testing/example-config.json deleted file mode 100644 index 239710e2cd0..00000000000 --- a/adev/src/content/examples/testing/example-config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "projectType": "testing", - "tests": [ - {"cmd": "yarn", "args": ["test", "--browsers=ChromeHeadlessNoSandbox", "--no-watch"]}, - {"cmd": "yarn", "args": ["e2e", "--configuration=production", "--protractor-config=e2e/protractor-bazel.conf.js", "--no-webdriver-update", "--port=0"]} - ] -} diff --git a/adev/src/content/examples/testing/src/app/about/about.component.spec.ts b/adev/src/content/examples/testing/src/app/about/about.component.spec.ts deleted file mode 100755 index 60ff9790588..00000000000 --- a/adev/src/content/examples/testing/src/app/about/about.component.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {provideHttpClient} from '@angular/common/http'; -import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; -import {ComponentFixture, TestBed} from '@angular/core/testing'; - -import {UserService} from '../model'; -import {TwainService} from '../twain/twain.service'; - -import {AboutComponent} from './about.component'; - -let fixture: ComponentFixture; - -describe('AboutComponent (highlightDirective)', () => { - // #docregion tests - beforeEach(() => { - fixture = TestBed.configureTestingModule({ - imports: [AboutComponent], - providers: [provideHttpClient(), TwainService, UserService], - schemas: [CUSTOM_ELEMENTS_SCHEMA], - }).createComponent(AboutComponent); - fixture.detectChanges(); // initial binding - }); - - it('should have skyblue

', () => { - const h2: HTMLElement = fixture.nativeElement.querySelector('h2'); - const bgColor = h2.style.backgroundColor; - expect(bgColor).toBe('skyblue'); - }); - // #enddocregion tests -}); diff --git a/adev/src/content/examples/testing/src/app/about/about.component.ts b/adev/src/content/examples/testing/src/app/about/about.component.ts deleted file mode 100755 index 0d863133be0..00000000000 --- a/adev/src/content/examples/testing/src/app/about/about.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -// #docregion -import {Component} from '@angular/core'; - -import {HighlightDirective} from '../shared/highlight.directive'; -import {TwainComponent} from '../twain/twain.component'; - -@Component({ - template: ` -

About

-

Quote of the day:

- - `, - imports: [TwainComponent, HighlightDirective], -}) -export class AboutComponent {} diff --git a/adev/src/content/examples/testing/src/app/app-initial.component.spec.ts b/adev/src/content/examples/testing/src/app/app-initial.component.spec.ts deleted file mode 100755 index c8799d3fc0c..00000000000 --- a/adev/src/content/examples/testing/src/app/app-initial.component.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -// #docplaster -// #docregion -import {TestBed, waitForAsync} from '@angular/core/testing'; -// #enddocregion -import {AppComponent} from './app-initial.component'; -/* -// #docregion -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { -// #enddocregion -*/ -describe('AppComponent (initial CLI version)', () => { - // #docregion - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [AppComponent], - }); - })); - it('should create the app', waitForAsync(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app).toBeTruthy(); - })); - it("should have as title 'app'", waitForAsync(() => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('app'); - })); - it('should render title', waitForAsync(() => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain('Welcome to app!'); - })); -}); -// #enddocregion - -/// As it should be -import {DebugElement} from '@angular/core'; -import {ComponentFixture} from '@angular/core/testing'; - -describe('AppComponent (initial CLI version - as it should be)', () => { - let app: AppComponent; - let de: DebugElement; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [AppComponent], - }); - - fixture = TestBed.createComponent(AppComponent); - app = fixture.componentInstance; - de = fixture.debugElement; - }); - - it('should create the app', () => { - expect(app).toBeDefined(); - }); - - it("should have as title 'app'", () => { - expect(app.title).toEqual('app'); - }); - - it('should render title in an h1 tag', () => { - fixture.detectChanges(); - expect(de.nativeElement.querySelector('h1').textContent).toContain('Welcome to app!'); - }); -}); diff --git a/adev/src/content/examples/testing/src/app/app-initial.component.ts b/adev/src/content/examples/testing/src/app/app-initial.component.ts deleted file mode 100755 index 599733145a4..00000000000 --- a/adev/src/content/examples/testing/src/app/app-initial.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -// #docregion -// Reduced version of the initial AppComponent generated by CLI -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-root', - template: '

Welcome to {{title}}!

', -}) -export class AppComponent { - title = 'app'; -} diff --git a/adev/src/content/examples/testing/src/app/app.component.html b/adev/src/content/examples/testing/src/app/app.component.html deleted file mode 100644 index c0d2670fab5..00000000000 --- a/adev/src/content/examples/testing/src/app/app.component.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/adev/src/content/examples/testing/src/app/app.component.router.spec.ts b/adev/src/content/examples/testing/src/app/app.component.router.spec.ts deleted file mode 100755 index 4b9c47bdb3f..00000000000 --- a/adev/src/content/examples/testing/src/app/app.component.router.spec.ts +++ /dev/null @@ -1,173 +0,0 @@ -// For more examples: -// https://github.com/angular/angular/blob/main/packages/router/test/integration.spec.ts - -import {Location} from '@angular/common'; -import {provideLocationMocks, SpyLocation} from '@angular/common/testing'; -import {DebugElement, Type} from '@angular/core'; -import {ComponentFixture, fakeAsync, TestBed, tick, waitForAsync} from '@angular/core/testing'; -import {By} from '@angular/platform-browser'; -import {provideRouter, Router, RouterLink} from '@angular/router'; - -import {asyncData, click} from '../testing'; - -import {AboutComponent} from './about/about.component'; -import {AppComponent} from './app.component'; -import {DashboardComponent} from './dashboard/dashboard.component'; -import {HeroService, TestHeroService} from './model/testing/test-hero.service'; -import {TwainService} from './twain/twain.service'; - -let comp: AppComponent; -let fixture: ComponentFixture; -let page: Page; -let router: Router; -let location: SpyLocation; - -describe('AppComponent & router testing', () => { - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule( - Object.assign({}, appConfig, { - providers: [ - {provide: HeroService, useClass: TestHeroService}, - TwainService, - provideHttpClient(), - provideLocationMocks(), - provideRouter([ - {path: '', redirectTo: 'dashboard', pathMatch: 'full'}, - {path: 'about', component: AboutComponent}, - {path: 'dashboard', component: DashboardComponent}, - ]), - ], - }), - ); - })); - - it('should navigate to "Dashboard" immediately', fakeAsync(() => { - createComponent(); - tick(); // wait for async data to arrive - expectPathToBe('/dashboard', 'after initialNavigation()'); - expectElementOf(DashboardComponent); - })); - - it('should navigate to "About" on click', fakeAsync(() => { - createComponent(); - click(page.aboutLinkDe); - // page.aboutLinkDe.nativeElement.click(); // ok but fails in phantom - - advance(); - expectPathToBe('/about'); - expectElementOf(AboutComponent); - })); - - it('should navigate to "About" w/ browser location URL change', fakeAsync(() => { - createComponent(); - location.simulateHashChange('/about'); - advance(); - expectPathToBe('/about'); - expectElementOf(AboutComponent); - })); - - // Can't navigate to lazy loaded modules with this technique - xit('should navigate to "Heroes" on click (not working yet)', fakeAsync(() => { - createComponent(); - page.heroesLinkDe.nativeElement.click(); - advance(); - expectPathToBe('/heroes'); - })); -}); - -/////////////// - -import {HeroListComponent} from './hero/hero-list.component'; -import {appConfig} from './app.config'; -import heroRoutes from './hero/hero.routes'; -import {UserService} from './model'; -import {provideHttpClient} from '@angular/common/http'; - -///////// Can't get lazy loaded Heroes to work yet -xdescribe('AppComponent & Lazy Loading (not working yet)', () => { - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule(appConfig); - })); - - beforeEach(fakeAsync(() => { - createComponent(); - router.resetConfig([{path: 'heroes', loadChildren: () => heroRoutes}]); - })); - - it('should navigate to "Heroes" on click', waitForAsync(() => { - page.heroesLinkDe.nativeElement.click(); - advance(); - expectPathToBe('/heroes'); - expectElementOf(HeroListComponent); - })); - - it('can navigate to "Heroes" w/ browser location URL change', fakeAsync(() => { - location.go('/heroes'); - advance(); - expectPathToBe('/heroes'); - expectElementOf(HeroListComponent); - })); -}); - -////// Helpers ///////// - -/** - * Advance to the routed page - * Wait a tick, then detect changes, and tick again - */ -function advance(): void { - tick(); // wait while navigating - fixture.detectChanges(); // update view - tick(); // wait for async data to arrive -} - -function createComponent() { - fixture = TestBed.createComponent(AppComponent); - comp = fixture.componentInstance; - - const injector = fixture.debugElement.injector; - location = injector.get(Location) as SpyLocation; - router = injector.get(Router); - router.initialNavigation(); - spyOn(injector.get(TwainService), 'getQuote') - // fake fast async observable - .and.returnValue(asyncData('Test Quote')); - advance(); - - page = new Page(); -} - -class Page { - aboutLinkDe: DebugElement; - dashboardLinkDe: DebugElement; - heroesLinkDe: DebugElement; - - // for debugging - comp: AppComponent; - router: Router; - fixture: ComponentFixture; - - constructor() { - const links = fixture.debugElement.queryAll(By.directive(RouterLink)); - this.aboutLinkDe = links[2]; - this.dashboardLinkDe = links[0]; - this.heroesLinkDe = links[1]; - - // for debugging - this.comp = comp; - this.fixture = fixture; - this.router = router; - } -} - -function expectPathToBe(path: string, expectationFailOutput?: any) { - expect(location.path()) - .withContext(expectationFailOutput || 'location.path()') - .toEqual(path); -} - -function expectElementOf(type: Type): any { - const el = fixture.debugElement.query(By.directive(type)); - expect(el).withContext(`expected an element for ${type.name}`).toBeTruthy(); - return el; -} diff --git a/adev/src/content/examples/testing/src/app/app.component.spec.ts b/adev/src/content/examples/testing/src/app/app.component.spec.ts deleted file mode 100755 index a573f2c168b..00000000000 --- a/adev/src/content/examples/testing/src/app/app.component.spec.ts +++ /dev/null @@ -1,131 +0,0 @@ -// #docplaster -import {Component, DebugElement, NO_ERRORS_SCHEMA} from '@angular/core'; -import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; -import {By} from '@angular/platform-browser'; -import {provideRouter, Router, RouterLink, RouterOutlet} from '@angular/router'; - -import {AppComponent} from './app.component'; -import {appConfig} from './app.config'; -import {UserService} from './model'; -import {WelcomeComponent} from './welcome/welcome.component'; - -// #docregion component-stubs -@Component({selector: 'app-banner', template: ''}) -class BannerStubComponent {} - -@Component({selector: 'router-outlet', template: ''}) -class RouterOutletStubComponent {} - -@Component({selector: 'app-welcome', template: ''}) -class WelcomeStubComponent {} -// #enddocregion component-stubs - -let comp: AppComponent; -let fixture: ComponentFixture; - -describe('AppComponent & TestModule', () => { - beforeEach(() => { - // #docregion testbed-stubs - TestBed.configureTestingModule( - Object.assign({}, appConfig, { - providers: [provideRouter([]), UserService], - }), - ).overrideComponent(AppComponent, { - set: { - imports: [BannerStubComponent, RouterLink, RouterOutletStubComponent, WelcomeStubComponent], - }, - }); - // #enddocregion testbed-stubs - - fixture = TestBed.createComponent(AppComponent); - comp = fixture.componentInstance; - }); - tests(); -}); - -//////// Testing w/ NO_ERRORS_SCHEMA ////// -describe('AppComponent & NO_ERRORS_SCHEMA', () => { - beforeEach(() => { - // #docregion no-errors-schema - TestBed.configureTestingModule( - Object.assign({}, appConfig, { - providers: [provideRouter([]), UserService], - }), - ).overrideComponent(AppComponent, { - set: { - imports: [], // resets all imports - schemas: [NO_ERRORS_SCHEMA], - }, - }); - // #enddocregion no-errors-schema - - fixture = TestBed.createComponent(AppComponent); - comp = fixture.componentInstance; - }); - tests(); -}); - -describe('AppComponent & NO_ERRORS_SCHEMA', () => { - beforeEach(() => { - // #docregion mixed-setup - TestBed.configureTestingModule( - Object.assign({}, appConfig, { - providers: [provideRouter([]), UserService], - }), - ).overrideComponent(AppComponent, { - remove: { - imports: [RouterOutlet, WelcomeComponent], - }, - set: { - schemas: [NO_ERRORS_SCHEMA], - }, - }); - // #enddocregion mixed-setup - - fixture = TestBed.createComponent(AppComponent); - comp = fixture.componentInstance; - }); - tests(); -}); - -function tests() { - let routerLinks: RouterLink[]; - let linkDes: DebugElement[]; - - // #docregion test-setup - beforeEach(() => { - fixture.detectChanges(); // trigger initial data binding - - // find DebugElements with an attached RouterLinkStubDirective - linkDes = fixture.debugElement.queryAll(By.directive(RouterLink)); - - // get attached link directive instances - // using each DebugElement's injector - routerLinks = linkDes.map((de) => de.injector.get(RouterLink)); - }); - // #enddocregion test-setup - - it('can instantiate the component', () => { - expect(comp).not.toBeNull(); - }); - - // #docregion tests - it('can get RouterLinks from template', () => { - expect(routerLinks.length).withContext('should have 3 routerLinks').toBe(3); - expect(routerLinks[0].href).toBe('/dashboard'); - expect(routerLinks[1].href).toBe('/heroes'); - expect(routerLinks[2].href).toBe('/about'); - }); - - it('can click Heroes link in template', fakeAsync(() => { - const heroesLinkDe = linkDes[1]; // heroes link DebugElement - - TestBed.inject(Router).resetConfig([{path: '**', children: []}]); - heroesLinkDe.triggerEventHandler('click', {button: 0}); - tick(); - fixture.detectChanges(); - - expect(TestBed.inject(Router).url).toBe('/heroes'); - })); - // #enddocregion tests -} diff --git a/adev/src/content/examples/testing/src/app/app.component.ts b/adev/src/content/examples/testing/src/app/app.component.ts deleted file mode 100755 index 4d723ad0e9f..00000000000 --- a/adev/src/content/examples/testing/src/app/app.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -// #docregion -import {Component} from '@angular/core'; -import {RouterLink, RouterOutlet} from '@angular/router'; - -import {BannerComponent} from './banner/banner.component'; -import {WelcomeComponent} from './welcome/welcome.component'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - imports: [BannerComponent, WelcomeComponent, RouterOutlet, RouterLink], -}) -export class AppComponent {} diff --git a/adev/src/content/examples/testing/src/app/app.config.ts b/adev/src/content/examples/testing/src/app/app.config.ts deleted file mode 100644 index 147e316cddd..00000000000 --- a/adev/src/content/examples/testing/src/app/app.config.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {provideHttpClient} from '@angular/common/http'; -import {ApplicationConfig, importProvidersFrom} from '@angular/core'; -import {provideProtractorTestingSupport} from '@angular/platform-browser'; -import {provideRouter} from '@angular/router'; -import {HttpClientInMemoryWebApiModule} from 'angular-in-memory-web-api'; - -import {routes} from './app.routes'; -import {InMemoryDataService} from './in-memory-data.service'; -import {HeroService} from './model/hero.service'; -import {UserService} from './model/user.service'; -import {TwainService} from './twain/twain.service'; - -export const appProviders = [ - provideRouter(routes), - provideHttpClient(), - provideProtractorTestingSupport(), - importProvidersFrom( - // The HttpClientInMemoryWebApiModule module intercepts HTTP requests - // and returns simulated server responses. - // Remove it when a real server is ready to receive requests. - HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService, {dataEncapsulation: false}), - ), - HeroService, - TwainService, - UserService, -]; - -export const appConfig: ApplicationConfig = { - providers: appProviders, -}; diff --git a/adev/src/content/examples/testing/src/app/app.routes.ts b/adev/src/content/examples/testing/src/app/app.routes.ts deleted file mode 100644 index c92c9f8b8d4..00000000000 --- a/adev/src/content/examples/testing/src/app/app.routes.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {Routes} from '@angular/router'; - -import {AboutComponent} from './about/about.component'; -import {DashboardComponent} from './dashboard/dashboard.component'; - -export const routes: Routes = [ - {path: '', redirectTo: 'dashboard', pathMatch: 'full'}, - {path: 'about', component: AboutComponent}, - {path: 'dashboard', component: DashboardComponent}, - {path: 'heroes', loadChildren: () => import('./hero/hero.routes')}, -]; diff --git a/adev/src/content/examples/testing/src/app/banner/banner-external.component.css b/adev/src/content/examples/testing/src/app/banner/banner-external.component.css deleted file mode 100644 index 333c9a102f5..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner-external.component.css +++ /dev/null @@ -1,4 +0,0 @@ -h1 { - color: green; - font-size: 350%; -} diff --git a/adev/src/content/examples/testing/src/app/banner/banner-external.component.html b/adev/src/content/examples/testing/src/app/banner/banner-external.component.html deleted file mode 100644 index b6515528b8c..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner-external.component.html +++ /dev/null @@ -1 +0,0 @@ -

{{ title }}

diff --git a/adev/src/content/examples/testing/src/app/banner/banner-external.component.spec.ts b/adev/src/content/examples/testing/src/app/banner/banner-external.component.spec.ts deleted file mode 100755 index 6badd6972b7..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner-external.component.spec.ts +++ /dev/null @@ -1,78 +0,0 @@ -// #docplaster -import {ComponentFixture, TestBed} from '@angular/core/testing'; - -import {BannerComponent} from './banner-external.component'; - -describe('BannerComponent (external files)', () => { - let component: BannerComponent; - let fixture: ComponentFixture; - let h1: HTMLElement; - - describe('setup that may fail', () => { - // #docregion setup-may-fail - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [BannerComponent], - }); // missing call to compileComponents() - fixture = TestBed.createComponent(BannerComponent); - }); - // #enddocregion setup-may-fail - - it('should create', () => { - expect(fixture.componentInstance).toBeDefined(); - }); - }); - - describe('Two beforeEach', () => { - // #docregion async-before-each - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [BannerComponent], - }).compileComponents(); // compile template and css - }); - // #enddocregion async-before-each - - // synchronous beforeEach - // #docregion sync-before-each - beforeEach(() => { - fixture = TestBed.createComponent(BannerComponent); - component = fixture.componentInstance; // BannerComponent test instance - h1 = fixture.nativeElement.querySelector('h1'); - }); - // #enddocregion sync-before-each - - tests(); - }); - - describe('One beforeEach', () => { - // #docregion one-before-each - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [BannerComponent], - }); - fixture = TestBed.createComponent(BannerComponent); - component = fixture.componentInstance; - h1 = fixture.nativeElement.querySelector('h1'); - }); - // #enddocregion one-before-each - - tests(); - }); - - function tests() { - it('no title in the DOM until manually call `detectChanges`', () => { - expect(h1.textContent).toEqual(''); - }); - - it('should display original title', () => { - fixture.detectChanges(); - expect(h1.textContent).toContain(component.title); - }); - - it('should display a different test title', () => { - component.title = 'Test Title'; - fixture.detectChanges(); - expect(h1.textContent).toContain('Test Title'); - }); - } -}); diff --git a/adev/src/content/examples/testing/src/app/banner/banner-external.component.ts b/adev/src/content/examples/testing/src/app/banner/banner-external.component.ts deleted file mode 100755 index 72d7ba0ea18..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner-external.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -// #docplaster -// #docregion -import {Component} from '@angular/core'; - -// #docregion metadata -@Component({ - selector: 'app-banner', - templateUrl: './banner-external.component.html', - styleUrls: ['./banner-external.component.css'], -}) -// #enddocregion metadata -export class BannerComponent { - title = 'Test Tour of Heroes'; -} diff --git a/adev/src/content/examples/testing/src/app/banner/banner-initial.component.spec.ts b/adev/src/content/examples/testing/src/app/banner/banner-initial.component.spec.ts deleted file mode 100755 index ef951d417be..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner-initial.component.spec.ts +++ /dev/null @@ -1,113 +0,0 @@ -// #docplaster -// #docregion import-debug-element -import {DebugElement} from '@angular/core'; -// #enddocregion import-debug-element -// #docregion v1 -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; - -// #enddocregion v1 -// #docregion import-by -import {By} from '@angular/platform-browser'; -// #enddocregion import-by -import {BannerComponent} from './banner-initial.component'; - -/* -// #docregion v1 -import { BannerComponent } from './banner.component'; - -describe('BannerComponent', () => { -// #enddocregion v1 -*/ -describe('BannerComponent (initial CLI generated)', () => { - // #docregion v1 - let component: BannerComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({imports: [BannerComponent]}); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(BannerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeDefined(); - }); -}); -// #enddocregion v1 - -// #docregion v2 -describe('BannerComponent (minimal)', () => { - it('should create', () => { - // #docregion configureTestingModule - TestBed.configureTestingModule({imports: [BannerComponent]}); - // #enddocregion configureTestingModule - // #docregion createComponent - const fixture = TestBed.createComponent(BannerComponent); - // #enddocregion createComponent - // #docregion componentInstance - const component = fixture.componentInstance; - expect(component).toBeDefined(); - // #enddocregion componentInstance - }); -}); -// #enddocregion v2 - -// #docregion v3 -describe('BannerComponent (with beforeEach)', () => { - let component: BannerComponent; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({imports: [BannerComponent]}); - fixture = TestBed.createComponent(BannerComponent); - component = fixture.componentInstance; - }); - - it('should create', () => { - expect(component).toBeDefined(); - }); - // #enddocregion v3 - - // #docregion v4-test-2 - it('should contain "banner works!"', () => { - const bannerElement: HTMLElement = fixture.nativeElement; - expect(bannerElement.textContent).toContain('banner works!'); - }); - // #enddocregion v4-test-2 - - // #docregion v4-test-3 - it('should have

with "banner works!"', () => { - // #docregion nativeElement - const bannerElement: HTMLElement = fixture.nativeElement; - // #enddocregion nativeElement - const p = bannerElement.querySelector('p')!; - expect(p.textContent).toEqual('banner works!'); - }); - // #enddocregion v4-test-3 - - // #docregion v4-test-4 - it('should find the

with fixture.debugElement.nativeElement', () => { - // #docregion debugElement-nativeElement - const bannerDe: DebugElement = fixture.debugElement; - const bannerEl: HTMLElement = bannerDe.nativeElement; - // #enddocregion debugElement-nativeElement - const p = bannerEl.querySelector('p')!; - expect(p.textContent).toEqual('banner works!'); - }); - // #enddocregion v4-test-4 - - // #docregion v4-test-5 - it('should find the

with fixture.debugElement.query(By.css)', () => { - const bannerDe: DebugElement = fixture.debugElement; - const paragraphDe = bannerDe.query(By.css('p')); - const p: HTMLElement = paragraphDe.nativeElement; - expect(p.textContent).toEqual('banner works!'); - }); - // #enddocregion v4-test-5 - // #docregion v3 -}); -// #enddocregion v3 diff --git a/adev/src/content/examples/testing/src/app/banner/banner-initial.component.ts b/adev/src/content/examples/testing/src/app/banner/banner-initial.component.ts deleted file mode 100755 index 0fc13cc0a69..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner-initial.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -// BannerComponent as initially generated by the CLI -// #docregion -import {Component} from '@angular/core'; - -@Component({ - selector: 'app-banner', - template: '

banner works!

', - styles: [], -}) -export class BannerComponent {} diff --git a/adev/src/content/examples/testing/src/app/banner/banner.component.detect-changes.spec.ts b/adev/src/content/examples/testing/src/app/banner/banner.component.detect-changes.spec.ts deleted file mode 100755 index 1b752ee0d4c..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner.component.detect-changes.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -// #docplaster -// #docregion -// #docregion import-ComponentFixtureAutoDetect -import {ComponentFixtureAutoDetect} from '@angular/core/testing'; -// #enddocregion import-ComponentFixtureAutoDetect -import {ComponentFixture, TestBed} from '@angular/core/testing'; - -import {BannerComponent} from './banner.component'; - -describe('BannerComponent (AutoChangeDetect)', () => { - let comp: BannerComponent; - let fixture: ComponentFixture; - let h1: HTMLElement; - - beforeEach(() => { - // #docregion auto-detect - TestBed.configureTestingModule({ - providers: [{provide: ComponentFixtureAutoDetect, useValue: true}], - }); - // #enddocregion auto-detect - fixture = TestBed.createComponent(BannerComponent); - comp = fixture.componentInstance; - h1 = fixture.nativeElement.querySelector('h1'); - }); - - // #docregion auto-detect-tests - it('should display original title', () => { - // Hooray! No `fixture.detectChanges()` needed - expect(h1.textContent).toContain(comp.title); - }); - - it('should still see original title after comp.title change', async () => { - const oldTitle = comp.title; - const newTitle = 'Test Title'; - comp.title.set(newTitle); - // Displayed title is old because Angular didn't yet run change detection - expect(h1.textContent).toContain(oldTitle); - await fixture.whenStable(); - expect(h1.textContent).toContain(newTitle); - }); - - it('should display updated title after detectChanges', () => { - comp.title.set('Test Title'); - fixture.detectChanges(); // detect changes explicitly - expect(h1.textContent).toContain(comp.title); - }); - // #enddocregion auto-detect-tests -}); diff --git a/adev/src/content/examples/testing/src/app/banner/banner.component.spec.ts b/adev/src/content/examples/testing/src/app/banner/banner.component.spec.ts deleted file mode 100755 index 34d043fbb6a..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner.component.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -// #docplaster -// #docregion -import {ComponentFixture, TestBed} from '@angular/core/testing'; - -import {BannerComponent} from './banner.component'; - -describe('BannerComponent (inline template)', () => { - // #docregion setup - let component: BannerComponent; - let fixture: ComponentFixture; - let h1: HTMLElement; - - beforeEach(() => { - fixture = TestBed.createComponent(BannerComponent); - component = fixture.componentInstance; // BannerComponent test instance - h1 = fixture.nativeElement.querySelector('h1'); - }); - // #enddocregion setup - - // #docregion test-w-o-detect-changes - it('no title in the DOM after createComponent()', () => { - expect(h1.textContent).toEqual(''); - }); - // #enddocregion test-w-o-detect-changes - - // #docregion expect-h1-default-v1 - it('should display original title', () => { - // #enddocregion expect-h1-default-v1 - fixture.detectChanges(); - // #docregion expect-h1-default-v1 - expect(h1.textContent).toContain(component.title); - }); - // #enddocregion expect-h1-default-v1 - - // #docregion expect-h1-default - it('should display original title after detectChanges()', () => { - fixture.detectChanges(); - expect(h1.textContent).toContain(component.title); - }); - // #enddocregion expect-h1-default - - // #docregion after-change - it('should display a different test title', () => { - component.title = 'Test Title'; - fixture.detectChanges(); - expect(h1.textContent).toContain('Test Title'); - }); - // #enddocregion after-change -}); diff --git a/adev/src/content/examples/testing/src/app/banner/banner.component.ts b/adev/src/content/examples/testing/src/app/banner/banner.component.ts deleted file mode 100755 index b8652d895c1..00000000000 --- a/adev/src/content/examples/testing/src/app/banner/banner.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {Component, signal} from '@angular/core'; - -// #docregion component -@Component({ - selector: 'app-banner', - template: '

{{title()}}

', - styles: ['h1 { color: green; font-size: 350%}'], -}) -export class BannerComponent { - title = signal('Test Tour of Heroes'); -} -// #enddocregion component diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.css b/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.css deleted file mode 100644 index 0ad175414b3..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.css +++ /dev/null @@ -1,30 +0,0 @@ -.hero { - padding: 20px; - position: relative; - text-align: center; - color: #eee; - max-height: 120px; - width: 100%; - min-width: 120px; - background-color: #607d8b; - border-radius: 2px; -} - -.hero:hover { - background-color: #eee; - cursor: pointer; - color: #607d8b; -} - -@media (max-width: 600px) { - .hero { - font-size: 10px; - max-height: 75px; - } -} - -@media (max-width: 1024px) { - .hero { - min-width: 60px; - } -} diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.spec.ts b/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.spec.ts deleted file mode 100755 index 13750e34820..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.spec.ts +++ /dev/null @@ -1,155 +0,0 @@ -// #docplaster -import {DebugElement} from '@angular/core'; -import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; -import {By} from '@angular/platform-browser'; -import {first} from 'rxjs/operators'; - -import {addMatchers, click} from '../../testing'; -import {appProviders} from '../app.config'; -import {Hero} from '../model/hero'; - -import {DashboardHeroComponent} from './dashboard-hero.component'; - -beforeEach(addMatchers); - -describe('DashboardHeroComponent when tested directly', () => { - let comp: DashboardHeroComponent; - let expectedHero: Hero; - let fixture: ComponentFixture; - let heroDe: DebugElement; - let heroEl: HTMLElement; - - beforeEach(() => { - // #docregion setup, config-testbed - TestBed.configureTestingModule({ - providers: appProviders, - }); - // #enddocregion setup, config-testbed - }); - - beforeEach(async () => { - // #docregion setup - fixture = TestBed.createComponent(DashboardHeroComponent); - fixture.autoDetectChanges(); - comp = fixture.componentInstance; - - // find the hero's DebugElement and element - heroDe = fixture.debugElement.query(By.css('.hero')); - heroEl = heroDe.nativeElement; - - // mock the hero supplied by the parent component - expectedHero = {id: 42, name: 'Test Name'}; - - // simulate the parent setting the input property with that hero - fixture.componentRef.setInput('hero', expectedHero); - - // wait for initial data binding - await fixture.whenStable(); - // #enddocregion setup - }); - - // #docregion name-test - it('should display hero name in uppercase', () => { - const expectedPipedName = expectedHero.name.toUpperCase(); - expect(heroEl.textContent).toContain(expectedPipedName); - }); - // #enddocregion name-test - - // #docregion click-test - it('should raise selected event when clicked (triggerEventHandler)', () => { - let selectedHero: Hero | undefined; - comp.selected.subscribe((hero: Hero) => (selectedHero = hero)); - - // #docregion trigger-event-handler - heroDe.triggerEventHandler('click'); - // #enddocregion trigger-event-handler - expect(selectedHero).toBe(expectedHero); - }); - // #enddocregion click-test - - // #docregion click-test-2 - it('should raise selected event when clicked (element.click)', () => { - let selectedHero: Hero | undefined; - comp.selected.subscribe((hero: Hero) => (selectedHero = hero)); - - heroEl.click(); - expect(selectedHero).toBe(expectedHero); - }); - // #enddocregion click-test-2 - - // #docregion click-test-3 - it('should raise selected event when clicked (click helper with DebugElement)', () => { - let selectedHero: Hero | undefined; - comp.selected.subscribe((hero: Hero) => (selectedHero = hero)); - - click(heroDe); // click helper with DebugElement - - expect(selectedHero).toBe(expectedHero); - }); - // #enddocregion click-test-3 - - it('should raise selected event when clicked (click helper with native element)', () => { - let selectedHero: Hero | undefined; - comp.selected.subscribe((hero: Hero) => (selectedHero = hero)); - - click(heroEl); // click helper with native element - - expect(selectedHero).toBe(expectedHero); - }); -}); - -////////////////// - -describe('DashboardHeroComponent when inside a test host', () => { - let testHost: TestHostComponent; - let fixture: ComponentFixture; - let heroEl: HTMLElement; - - beforeEach(waitForAsync(() => { - // #docregion test-host-setup - TestBed.configureTestingModule({ - providers: appProviders, - }); - // #enddocregion test-host-setup - })); - - beforeEach(() => { - // #docregion test-host-setup - // create TestHostComponent instead of DashboardHeroComponent - fixture = TestBed.createComponent(TestHostComponent); - testHost = fixture.componentInstance; - heroEl = fixture.nativeElement.querySelector('.hero'); - fixture.detectChanges(); // trigger initial data binding - // #enddocregion test-host-setup - }); - - // #docregion test-host-tests - it('should display hero name', () => { - const expectedPipedName = testHost.hero.name.toUpperCase(); - expect(heroEl.textContent).toContain(expectedPipedName); - }); - - it('should raise selected event when clicked', () => { - click(heroEl); - // selected hero should be the same data bound hero - expect(testHost.selectedHero).toBe(testHost.hero); - }); - // #enddocregion test-host-tests -}); - -////// Test Host Component ////// -import {Component} from '@angular/core'; - -// #docregion test-host -@Component({ - imports: [DashboardHeroComponent], - template: ` `, -}) -class TestHostComponent { - hero: Hero = {id: 42, name: 'Test Name'}; - selectedHero: Hero | undefined; - onSelected(hero: Hero) { - this.selectedHero = hero; - } -} -// #enddocregion test-host diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.ts b/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.ts deleted file mode 100755 index 4036eea2bd3..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard-hero.component.ts +++ /dev/null @@ -1,26 +0,0 @@ -// #docregion -import {Component, input, output} from '@angular/core'; -import {UpperCasePipe} from '@angular/common'; - -import {Hero} from '../model/hero'; - -// #docregion component -@Component({ - selector: 'dashboard-hero', - template: ` - - `, - styleUrls: ['./dashboard-hero.component.css'], - imports: [UpperCasePipe], -}) -// #docregion class -export class DashboardHeroComponent { - readonly hero = input.required(); - readonly selected = output(); - click() { - this.selected.emit(this.hero()); - } -} -// #enddocregion component, class diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.css b/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.css deleted file mode 100644 index 74a3be5966d..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.css +++ /dev/null @@ -1,36 +0,0 @@ -[class*='col-'] { - float: left; -} -*, -*::after, -*::before { - box-sizing: border-box; -} -h3 { - text-align: center; - margin-bottom: 0; -} -[class*='col-'] { - padding-right: 20px; - padding-bottom: 20px; -} -[class*='col-']:last-of-type { - padding-right: 0; -} -.grid { - margin: 0; -} -.col-1-4 { - width: 25%; -} -.grid-pad { - padding: 10px 0; -} -.grid-pad > [class*='col-']:last-of-type { - padding-right: 20px; -} -@media (max-width: 1024px) { - .grid { - margin: 0; - } -} diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.html b/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.html deleted file mode 100644 index 83b20316559..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.html +++ /dev/null @@ -1,9 +0,0 @@ -

{{ title }}

- -
- - @for (hero of heroes; track hero) { - - } - -
diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.no-testbed.spec.ts b/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.no-testbed.spec.ts deleted file mode 100644 index 8c364ef57e0..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.no-testbed.spec.ts +++ /dev/null @@ -1,62 +0,0 @@ -import {Router} from '@angular/router'; - -import {DashboardComponent} from './dashboard.component'; -import {Hero} from '../model/hero'; - -import {addMatchers} from '../../testing'; -import {TestHeroService} from '../model/testing/test-hero.service'; - -class FakeRouter { - navigateByUrl(url: string) { - return url; - } -} - -describe('DashboardComponent class only', () => { - let comp: DashboardComponent; - let heroService: TestHeroService; - let router: Router; - - beforeEach(() => { - addMatchers(); - router = new FakeRouter() as any as Router; - heroService = new TestHeroService(); - comp = new DashboardComponent(router, heroService); - }); - - it('should NOT have heroes before calling OnInit', () => { - expect(comp.heroes.length).withContext('should not have heroes before OnInit').toBe(0); - }); - - it('should NOT have heroes immediately after OnInit', () => { - comp.ngOnInit(); // ngOnInit -> getHeroes - expect(comp.heroes.length) - .withContext('should not have heroes until service promise resolves') - .toBe(0); - }); - - it('should HAVE heroes after HeroService gets them', (done: DoneFn) => { - comp.ngOnInit(); // ngOnInit -> getHeroes - heroService.lastResult // the one from getHeroes - .subscribe({ - next: () => { - // throw new Error('deliberate error'); // see it fail gracefully - expect(comp.heroes.length) - .withContext('should have heroes after service promise resolves') - .toBeGreaterThan(0); - done(); - }, - error: done.fail, - }); - }); - - it('should tell ROUTER to navigate by hero id', () => { - const hero: Hero = {id: 42, name: 'Abbracadabra'}; - const spy = spyOn(router, 'navigateByUrl'); - - comp.gotoDetail(hero); - - const navArgs = spy.calls.mostRecent().args[0]; - expect(navArgs).withContext('should nav to HeroDetail for Hero 42').toBe('/heroes/42'); - }); -}); diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts b/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts deleted file mode 100755 index 1f3e02c9b17..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts +++ /dev/null @@ -1,126 +0,0 @@ -import {provideHttpClient} from '@angular/common/http'; -import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; -import {NO_ERRORS_SCHEMA} from '@angular/core'; -import {TestBed, waitForAsync} from '@angular/core/testing'; -import {By} from '@angular/platform-browser'; -import {NavigationEnd, provideRouter, Router} from '@angular/router'; -import {RouterTestingHarness} from '@angular/router/testing'; -import {firstValueFrom} from 'rxjs'; -import {filter} from 'rxjs/operators'; - -import {addMatchers, click} from '../../testing'; -import {HeroService} from '../model/hero.service'; -import {getTestHeroes} from '../model/testing/test-heroes'; - -import {DashboardComponent} from './dashboard.component'; -import {appConfig} from '../app.config'; -import {HeroDetailComponent} from '../hero/hero-detail.component'; - -beforeEach(addMatchers); - -let comp: DashboardComponent; -let harness: RouterTestingHarness; - -//////// Deep //////////////// - -describe('DashboardComponent (deep)', () => { - compileAndCreate(); - - tests(clickForDeep); - - function clickForDeep() { - // get first
- const heroEl: HTMLElement = harness.routeNativeElement!.querySelector('.hero')!; - click(heroEl); - return firstValueFrom( - TestBed.inject(Router).events.pipe(filter((e) => e instanceof NavigationEnd)), - ); - } -}); - -//////// Shallow //////////////// - -describe('DashboardComponent (shallow)', () => { - beforeEach(() => { - TestBed.configureTestingModule( - Object.assign({}, appConfig, { - imports: [DashboardComponent, HeroDetailComponent], - providers: [provideRouter([{path: 'heroes/:id', component: HeroDetailComponent}])], - schemas: [NO_ERRORS_SCHEMA], - }), - ); - }); - - compileAndCreate(); - - tests(clickForShallow); - - function clickForShallow() { - // get first DebugElement - const heroDe = harness.routeDebugElement!.query(By.css('dashboard-hero')); - heroDe.triggerEventHandler('selected', comp.heroes[0]); - return Promise.resolve(); - } -}); - -/** Add TestBed providers, compile, and create DashboardComponent */ -function compileAndCreate() { - beforeEach(async () => { - // #docregion router-harness - TestBed.configureTestingModule( - Object.assign({}, appConfig, { - providers: [ - provideRouter([{path: '**', component: DashboardComponent}]), - provideHttpClient(), - provideHttpClientTesting(), - HeroService, - ], - }), - ); - harness = await RouterTestingHarness.create(); - comp = await harness.navigateByUrl('/', DashboardComponent); - TestBed.inject(HttpTestingController).expectOne('api/heroes').flush(getTestHeroes()); - // #enddocregion router-harness - }); -} - -/** - * The (almost) same tests for both. - * Only change: the way that the first hero is clicked - */ -function tests(heroClick: () => Promise) { - describe('after get dashboard heroes', () => { - let router: Router; - - // Trigger component so it gets heroes and binds to them - beforeEach(waitForAsync(() => { - router = TestBed.inject(Router); - harness.detectChanges(); // runs ngOnInit -> getHeroes - })); - - it('should HAVE heroes', () => { - expect(comp.heroes.length) - .withContext('should have heroes after service promise resolves') - .toBeGreaterThan(0); - }); - - it('should DISPLAY heroes', () => { - // Find and examine the displayed heroes - // Look for them in the DOM by css class - const heroes = harness.routeNativeElement!.querySelectorAll('dashboard-hero'); - expect(heroes.length).withContext('should display 4 heroes').toBe(4); - }); - - // #docregion navigate-test - it('should tell navigate when hero clicked', async () => { - await heroClick(); // trigger click on first inner
- - // expecting to navigate to id of the component's first hero - const id = comp.heroes[0].id; - expect(TestBed.inject(Router).url) - .withContext('should nav to HeroDetail for first hero') - .toEqual(`/heroes/${id}`); - }); - // #enddocregion navigate-test - }); -} diff --git a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.ts b/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.ts deleted file mode 100755 index 966d49052cf..00000000000 --- a/adev/src/content/examples/testing/src/app/dashboard/dashboard.component.ts +++ /dev/null @@ -1,42 +0,0 @@ -// #docregion -import {Component, OnInit} from '@angular/core'; -import {Router} from '@angular/router'; - -import {Hero} from '../model/hero'; -import {HeroService} from '../model/hero.service'; -import {sharedImports} from '../shared/shared'; - -import {DashboardHeroComponent} from './dashboard-hero.component'; - -@Component({ - selector: 'app-dashboard', - templateUrl: './dashboard.component.html', - styleUrls: ['./dashboard.component.css'], - imports: [DashboardHeroComponent, sharedImports], -}) -export class DashboardComponent implements OnInit { - heroes: Hero[] = []; - - // #docregion ctor - constructor( - private router: Router, - private heroService: HeroService, - ) {} - // #enddocregion ctor - - ngOnInit() { - this.heroService.getHeroes().subscribe((heroes) => (this.heroes = heroes.slice(1, 5))); - } - - // #docregion goto-detail - gotoDetail(hero: Hero) { - const url = `/heroes/${hero.id}`; - this.router.navigateByUrl(url); - } - // #enddocregion goto-detail - - get title() { - const cnt = this.heroes.length; - return cnt === 0 ? 'No Heroes' : cnt === 1 ? 'Top Hero' : `Top ${cnt} Heroes`; - } -} diff --git a/adev/src/content/examples/testing/src/app/demo/async-helper.spec.ts b/adev/src/content/examples/testing/src/app/demo/async-helper.spec.ts deleted file mode 100644 index 17e08c4cb96..00000000000 --- a/adev/src/content/examples/testing/src/app/demo/async-helper.spec.ts +++ /dev/null @@ -1,210 +0,0 @@ -import {fakeAsync, tick, waitForAsync} from '@angular/core/testing'; -import {interval, of} from 'rxjs'; -import {delay, take} from 'rxjs/operators'; - -describe('Angular async helper', () => { - describe('async', () => { - let actuallyDone = false; - - beforeEach(() => { - actuallyDone = false; - }); - - afterEach(() => { - expect(actuallyDone).withContext('actuallyDone should be true').toBe(true); - }); - - it('should run normal test', () => { - actuallyDone = true; - }); - - it('should run normal async test', (done: DoneFn) => { - setTimeout(() => { - actuallyDone = true; - done(); - }, 0); - }); - - it('should run async test with task', waitForAsync(() => { - setTimeout(() => { - actuallyDone = true; - }, 0); - })); - - it('should run async test with task', waitForAsync(() => { - const id = setInterval(() => { - actuallyDone = true; - clearInterval(id); - }, 100); - })); - - it('should run async test with successful promise', waitForAsync(() => { - const p = new Promise((resolve) => { - setTimeout(resolve, 10); - }); - p.then(() => { - actuallyDone = true; - }); - })); - - it('should run async test with failed promise', waitForAsync(() => { - const p = new Promise((resolve, reject) => { - setTimeout(reject, 10); - }); - p.catch(() => { - actuallyDone = true; - }); - })); - - // Use done. Can also use async or fakeAsync. - it('should run async test with successful delayed Observable', (done: DoneFn) => { - const source = of(true).pipe(delay(10)); - source.subscribe({ - next: (val) => (actuallyDone = true), - error: (err) => fail(err), - complete: done, - }); - }); - - it('should run async test with successful delayed Observable', waitForAsync(() => { - const source = of(true).pipe(delay(10)); - source.subscribe({ - next: (val) => (actuallyDone = true), - error: (err) => fail(err), - }); - })); - - it('should run async test with successful delayed Observable', fakeAsync(() => { - const source = of(true).pipe(delay(10)); - source.subscribe({ - next: (val) => (actuallyDone = true), - error: (err) => fail(err), - }); - - tick(10); - })); - }); - - describe('fakeAsync', () => { - // #docregion fake-async-test-tick - it('should run timeout callback with delay after call tick with millis', fakeAsync(() => { - let called = false; - setTimeout(() => { - called = true; - }, 100); - tick(100); - expect(called).toBe(true); - })); - // #enddocregion fake-async-test-tick - - // #docregion fake-async-test-tick-new-macro-task-sync - it('should run new macro task callback with delay after call tick with millis', fakeAsync(() => { - function nestedTimer(cb: () => any): void { - setTimeout(() => setTimeout(() => cb())); - } - const callback = jasmine.createSpy('callback'); - nestedTimer(callback); - expect(callback).not.toHaveBeenCalled(); - tick(0); - // the nested timeout will also be triggered - expect(callback).toHaveBeenCalled(); - })); - // #enddocregion fake-async-test-tick-new-macro-task-sync - - // #docregion fake-async-test-tick-new-macro-task-async - it('should not run new macro task callback with delay after call tick with millis', fakeAsync(() => { - function nestedTimer(cb: () => any): void { - setTimeout(() => setTimeout(() => cb())); - } - const callback = jasmine.createSpy('callback'); - nestedTimer(callback); - expect(callback).not.toHaveBeenCalled(); - tick(0, {processNewMacroTasksSynchronously: false}); - // the nested timeout will not be triggered - expect(callback).not.toHaveBeenCalled(); - tick(0); - expect(callback).toHaveBeenCalled(); - })); - // #enddocregion fake-async-test-tick-new-macro-task-async - - // #docregion fake-async-test-date - it('should get Date diff correctly in fakeAsync', fakeAsync(() => { - const start = Date.now(); - tick(100); - const end = Date.now(); - expect(end - start).toBe(100); - })); - // #enddocregion fake-async-test-date - - // #docregion fake-async-test-rxjs - it('should get Date diff correctly in fakeAsync with rxjs scheduler', fakeAsync(() => { - // need to add `import 'zone.js/plugins/zone-patch-rxjs-fake-async' - // to patch rxjs scheduler - let result = ''; - of('hello') - .pipe(delay(1000)) - .subscribe((v) => { - result = v; - }); - expect(result).toBe(''); - tick(1000); - expect(result).toBe('hello'); - - const start = new Date().getTime(); - let dateDiff = 0; - interval(1000) - .pipe(take(2)) - .subscribe(() => (dateDiff = new Date().getTime() - start)); - - tick(1000); - expect(dateDiff).toBe(1000); - tick(1000); - expect(dateDiff).toBe(2000); - })); - // #enddocregion fake-async-test-rxjs - }); - - // #docregion fake-async-test-clock - describe('use jasmine.clock()', () => { - // need to config __zone_symbol__fakeAsyncPatchLock flag - // before loading zone.js/testing - beforeEach(() => { - jasmine.clock().install(); - }); - afterEach(() => { - jasmine.clock().uninstall(); - }); - it('should auto enter fakeAsync', () => { - // is in fakeAsync now, don't need to call fakeAsync(testFn) - let called = false; - setTimeout(() => { - called = true; - }, 100); - jasmine.clock().tick(100); - expect(called).toBe(true); - }); - }); - // #enddocregion fake-async-test-clock - - describe('test jsonp', () => { - function jsonp(url: string, callback: () => void) { - // do a jsonp call which is not zone aware - } - // need to config __zone_symbol__supportWaitUnResolvedChainedPromise flag - // before loading zone.js/testing - it('should wait until promise.then is called', waitForAsync(() => { - let finished = false; - new Promise((res) => { - jsonp('localhost:8080/jsonp', () => { - // success callback and resolve the promise - finished = true; - res(); - }); - }).then(() => { - // async will wait until promise.then is called - // if __zone_symbol__supportWaitUnResolvedChainedPromise is set - expect(finished).toBe(true); - }); - })); - }); -}); diff --git a/adev/src/content/examples/testing/src/app/demo/demo-external-template.html b/adev/src/content/examples/testing/src/app/demo/demo-external-template.html deleted file mode 100644 index 4c2b23755fe..00000000000 --- a/adev/src/content/examples/testing/src/app/demo/demo-external-template.html +++ /dev/null @@ -1 +0,0 @@ -from external template diff --git a/adev/src/content/examples/testing/src/app/demo/demo.spec.ts b/adev/src/content/examples/testing/src/app/demo/demo.spec.ts deleted file mode 100644 index 562c91a8448..00000000000 --- a/adev/src/content/examples/testing/src/app/demo/demo.spec.ts +++ /dev/null @@ -1,142 +0,0 @@ -// #docplaster -import {LightswitchComponent, MasterService, ValueService, ReversePipe} from './demo'; - -///////// Fakes ///////// -export class FakeValueService extends ValueService { - override value = 'faked service value'; -} -//////////////////////// -describe('demo (no TestBed):', () => { - // #docregion ValueService - // Straight Jasmine testing without Angular's testing support - describe('ValueService', () => { - let service: ValueService; - beforeEach(() => { - service = new ValueService(); - }); - - it('#getValue should return real value', () => { - expect(service.getValue()).toBe('real value'); - }); - - it('#getObservableValue should return value from observable', (done: DoneFn) => { - service.getObservableValue().subscribe((value) => { - expect(value).toBe('observable value'); - done(); - }); - }); - - it('#getPromiseValue should return value from a promise', (done: DoneFn) => { - service.getPromiseValue().then((value) => { - expect(value).toBe('promise value'); - done(); - }); - }); - }); - // #enddocregion ValueService - - // MasterService requires injection of a ValueService - // #docregion MasterService - describe('MasterService without Angular testing support', () => { - let masterService: MasterService; - - it('#getValue should return real value from the real service', () => { - masterService = new MasterService(new ValueService()); - expect(masterService.getValue()).toBe('real value'); - }); - - it('#getValue should return faked value from a fakeService', () => { - masterService = new MasterService(new FakeValueService()); - expect(masterService.getValue()).toBe('faked service value'); - }); - - it('#getValue should return faked value from a fake object', () => { - const fake = {getValue: () => 'fake value'}; - masterService = new MasterService(fake as ValueService); - expect(masterService.getValue()).toBe('fake value'); - }); - - it('#getValue should return stubbed value from a spy', () => { - // create `getValue` spy on an object representing the ValueService - const valueServiceSpy = jasmine.createSpyObj('ValueService', ['getValue']); - - // set the value to return when the `getValue` spy is called. - const stubValue = 'stub value'; - valueServiceSpy.getValue.and.returnValue(stubValue); - - masterService = new MasterService(valueServiceSpy); - - expect(masterService.getValue()).withContext('service returned stub value').toBe(stubValue); - expect(valueServiceSpy.getValue.calls.count()) - .withContext('spy method was called once') - .toBe(1); - expect(valueServiceSpy.getValue.calls.mostRecent().returnValue).toBe(stubValue); - }); - }); - // #enddocregion MasterService - - describe('MasterService (no beforeEach)', () => { - // #docregion no-before-each-test - it('#getValue should return stubbed value from a spy', () => { - // #docregion no-before-each-setup-call - const {masterService, stubValue, valueServiceSpy} = setup(); - // #enddocregion no-before-each-setup-call - expect(masterService.getValue()).withContext('service returned stub value').toBe(stubValue); - expect(valueServiceSpy.getValue.calls.count()) - .withContext('spy method was called once') - .toBe(1); - expect(valueServiceSpy.getValue.calls.mostRecent().returnValue).toBe(stubValue); - }); - // #enddocregion no-before-each-test - - // #docregion no-before-each-setup - function setup() { - const valueServiceSpy = jasmine.createSpyObj('ValueService', ['getValue']); - const stubValue = 'stub value'; - const masterService = new MasterService(valueServiceSpy); - - valueServiceSpy.getValue.and.returnValue(stubValue); - return {masterService, stubValue, valueServiceSpy}; - } - // #enddocregion no-before-each-setup - }); - - describe('ReversePipe', () => { - let pipe: ReversePipe; - - beforeEach(() => { - pipe = new ReversePipe(); - }); - - it('transforms "abc" to "cba"', () => { - expect(pipe.transform('abc')).toBe('cba'); - }); - - it('no change to palindrome: "able was I ere I saw elba"', () => { - const palindrome = 'able was I ere I saw elba'; - expect(pipe.transform(palindrome)).toBe(palindrome); - }); - }); - - // #docregion Lightswitch - describe('LightswitchComp', () => { - it('#clicked() should toggle #isOn', () => { - const comp = new LightswitchComponent(); - expect(comp.isOn).withContext('off at first').toBe(false); - comp.clicked(); - expect(comp.isOn).withContext('on after click').toBe(true); - comp.clicked(); - expect(comp.isOn).withContext('off after second click').toBe(false); - }); - - it('#clicked() should set #message to "is on"', () => { - const comp = new LightswitchComponent(); - expect(comp.message) - .withContext('off at first') - .toMatch(/is off/i); - comp.clicked(); - expect(comp.message).withContext('on after clicked').toMatch(/is on/i); - }); - }); - // #enddocregion Lightswitch -}); diff --git a/adev/src/content/examples/testing/src/app/demo/demo.testbed.spec.ts b/adev/src/content/examples/testing/src/app/demo/demo.testbed.spec.ts deleted file mode 100755 index 403eb656a7e..00000000000 --- a/adev/src/content/examples/testing/src/app/demo/demo.testbed.spec.ts +++ /dev/null @@ -1,599 +0,0 @@ -// #docplaster -import {Component, DebugElement, Injectable} from '@angular/core'; -import { - ComponentFixture, - fakeAsync, - inject, - TestBed, - tick, - waitForAsync, -} from '@angular/core/testing'; -import {FormsModule, NgControl, NgModel} from '@angular/forms'; -import {By} from '@angular/platform-browser'; - -import {addMatchers, click} from '../../testing'; - -import { - BankAccountComponent, - BankAccountParentComponent, - Child1Component, - Child2Component, - Child3Component, - ExternalTemplateComponent, - InputComponent, - IoComponent, - IoParentComponent, - LightswitchComponent, - MasterService, - MyIfChildComponent, - MyIfComponent, - MyIfParentComponent, - NeedsContentComponent, - ParentComponent, - ReversePipeComponent, - ShellComponent, - TestProvidersComponent, - TestViewProvidersComponent, - ValueService, -} from './demo'; - -export class NotProvided extends ValueService { - /* example below */ -} -beforeEach(addMatchers); - -describe('demo (with TestBed):', () => { - //////// Service Tests ///////////// - - describe('ValueService', () => { - // #docregion value-service-before-each - let service: ValueService; - - // #docregion value-service-inject-before-each - beforeEach(() => { - TestBed.configureTestingModule({providers: [ValueService]}); - // #enddocregion value-service-before-each - service = TestBed.inject(ValueService); - // #docregion value-service-before-each - }); - // #enddocregion value-service-before-each, value-service-inject-before-each - - // #docregion value-service-inject-it - it('should use ValueService', () => { - service = TestBed.inject(ValueService); - expect(service.getValue()).toBe('real value'); - }); - // #enddocregion value-service-inject-it - - it('can inject a default value when service is not provided', () => { - // #docregion testbed-get-w-null - expect(TestBed.inject(NotProvided, null)).toBeNull(); - // #enddocregion testbed-get-w-null - }); - - it('test should wait for ValueService.getPromiseValue', waitForAsync(() => { - service.getPromiseValue().then((value) => expect(value).toBe('promise value')); - })); - - it('test should wait for ValueService.getObservableValue', waitForAsync(() => { - service.getObservableValue().subscribe((value) => expect(value).toBe('observable value')); - })); - - // Must use done. See https://github.com/angular/angular/issues/10127 - it('test should wait for ValueService.getObservableDelayValue', (done: DoneFn) => { - service.getObservableDelayValue().subscribe((value) => { - expect(value).toBe('observable delay value'); - done(); - }); - }); - - it('should allow the use of fakeAsync', fakeAsync(() => { - let value: any; - service.getPromiseValue().then((val: any) => (value = val)); - tick(); // Trigger JS engine cycle until all promises resolve. - expect(value).toBe('promise value'); - })); - }); - - describe('MasterService', () => { - // #docregion master-service-before-each - let masterService: MasterService; - let valueServiceSpy: jasmine.SpyObj; - - beforeEach(() => { - const spy = jasmine.createSpyObj('ValueService', ['getValue']); - - TestBed.configureTestingModule({ - // Provide both the service-to-test and its (spy) dependency - providers: [MasterService, {provide: ValueService, useValue: spy}], - }); - // Inject both the service-to-test and its (spy) dependency - masterService = TestBed.inject(MasterService); - valueServiceSpy = TestBed.inject(ValueService) as jasmine.SpyObj; - }); - // #enddocregion master-service-before-each - - // #docregion master-service-it - it('#getValue should return stubbed value from a spy', () => { - const stubValue = 'stub value'; - valueServiceSpy.getValue.and.returnValue(stubValue); - - expect(masterService.getValue()).withContext('service returned stub value').toBe(stubValue); - expect(valueServiceSpy.getValue.calls.count()) - .withContext('spy method was called once') - .toBe(1); - expect(valueServiceSpy.getValue.calls.mostRecent().returnValue).toBe(stubValue); - }); - // #enddocregion master-service-it - }); - - describe('use inject within `it`', () => { - beforeEach(() => { - TestBed.configureTestingModule({providers: [ValueService]}); - }); - - it('should use modified providers', inject([ValueService], (service: ValueService) => { - service.setValue('value modified in beforeEach'); - expect(service.getValue()).toBe('value modified in beforeEach'); - })); - }); - - describe('using waitForAsync(inject) within beforeEach', () => { - let serviceValue: string; - - beforeEach(() => { - TestBed.configureTestingModule({providers: [ValueService]}); - }); - - beforeEach(waitForAsync( - inject([ValueService], (service: ValueService) => { - service.getPromiseValue().then((value) => (serviceValue = value)); - }), - )); - - it('should use asynchronously modified value ... in synchronous test', () => { - expect(serviceValue).toBe('promise value'); - }); - }); - - /////////// Component Tests ////////////////// - - describe('TestBed component tests', () => { - // beforeEach(waitForAsync(() => { - // TestBed.configureTestingModule() - // // Compile everything in DemoModule - // ; - // })); - - it('should create a component with inline template', () => { - const fixture = TestBed.createComponent(Child1Component); - fixture.detectChanges(); - - expect(fixture).toHaveText('Child'); - }); - - it('should create a component with external template', () => { - const fixture = TestBed.createComponent(ExternalTemplateComponent); - fixture.detectChanges(); - - expect(fixture).toHaveText('from external template'); - }); - - it('should allow changing members of the component', () => { - const fixture = TestBed.createComponent(MyIfComponent); - - fixture.detectChanges(); - expect(fixture).toHaveText('MyIf()'); - - fixture.componentInstance.showMore = true; - fixture.detectChanges(); - expect(fixture).toHaveText('MyIf(More)'); - }); - - it('should create a nested component bound to inputs/outputs', () => { - const fixture = TestBed.createComponent(IoParentComponent); - - fixture.detectChanges(); - const heroes = fixture.debugElement.queryAll(By.css('.hero')); - expect(heroes.length).withContext('has heroes').toBeGreaterThan(0); - - const comp = fixture.componentInstance; - const hero = comp.heroes[0]; - - click(heroes[0]); - fixture.detectChanges(); - - const selected = fixture.debugElement.query(By.css('p')); - expect(selected).toHaveText(hero.name); - }); - - it('can access the instance variable of an `*ngFor` row component', () => { - const fixture = TestBed.createComponent(IoParentComponent); - const comp = fixture.componentInstance; - const heroName = comp.heroes[0].name; // first hero's name - - fixture.detectChanges(); - const ngForRow = fixture.debugElement.query(By.directive(IoComponent)); // first hero ngForRow - - const hero = ngForRow.context.hero; // the hero object passed into the row - expect(hero.name).withContext('ngRow.context.hero').toBe(heroName); - - const rowComp = ngForRow.componentInstance; - // jasmine.any is an "instance-of-type" test. - expect(rowComp).withContext('component is IoComp').toEqual(jasmine.any(IoComponent)); - expect(rowComp.hero.name).withContext('component.hero').toBe(heroName); - }); - - it('should support clicking a button', () => { - const fixture = TestBed.createComponent(LightswitchComponent); - const btn = fixture.debugElement.query(By.css('button')); - const span = fixture.debugElement.query(By.css('span')).nativeElement; - - fixture.detectChanges(); - expect(span.textContent) - .withContext('before click') - .toMatch(/is off/i); - - click(btn); - fixture.detectChanges(); - expect(span.textContent).withContext('after click').toMatch(/is on/i); - }); - - // ngModel is async so we must wait for it with promise-based `whenStable` - it('should support entering text in input box (ngModel)', waitForAsync(() => { - const expectedOrigName = 'John'; - const expectedNewName = 'Sally'; - - const fixture = TestBed.createComponent(InputComponent); - fixture.detectChanges(); - - const comp = fixture.componentInstance; - const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement; - - expect(comp.name) - .withContext(`At start name should be ${expectedOrigName} `) - .toBe(expectedOrigName); - - // wait until ngModel binds comp.name to input box - fixture - .whenStable() - .then(() => { - expect(input.value) - .withContext( - `After ngModel updates input box, input.value should be ${expectedOrigName} `, - ) - .toBe(expectedOrigName); - - // simulate user entering new name in input - input.value = expectedNewName; - - // that change doesn't flow to the component immediately - expect(comp.name()) - .withContext( - `comp.name should still be ${expectedOrigName} after value change, before binding happens`, - ) - .toBe(expectedOrigName); - - // Dispatch a DOM event so that Angular learns of input value change. - // then wait while ngModel pushes input.box value to comp.name - input.dispatchEvent(new Event('input')); - return fixture.whenStable(); - }) - .then(() => { - expect(comp.name()) - .withContext(`After ngModel updates the model, comp.name should be ${expectedNewName} `) - .toBe(expectedNewName); - }); - })); - - // fakeAsync version of ngModel input test enables sync test style - // synchronous `tick` replaces asynchronous promise-base `whenStable` - it('should support entering text in input box (ngModel) - fakeAsync', fakeAsync(() => { - const expectedOrigName = 'John'; - const expectedNewName = 'Sally'; - - const fixture = TestBed.createComponent(InputComponent); - fixture.detectChanges(); - - const comp = fixture.componentInstance; - const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement; - - expect(comp.name) - .withContext(`At start name should be ${expectedOrigName} `) - .toBe(expectedOrigName); - - // wait until ngModel binds comp.name to input box - tick(); - expect(input.value) - .withContext(`After ngModel updates input box, input.value should be ${expectedOrigName} `) - .toBe(expectedOrigName); - - // simulate user entering new name in input - input.value = expectedNewName; - - // that change doesn't flow to the component immediately - expect(comp.name) - .withContext( - `comp.name should still be ${expectedOrigName} after value change, before binding happens`, - ) - .toBe(expectedOrigName); - - // Dispatch a DOM event so that Angular learns of input value change. - // then wait a tick while ngModel pushes input.box value to comp.name - input.dispatchEvent(new Event('input')); - tick(); - expect(comp.name) - .withContext(`After ngModel updates the model, comp.name should be ${expectedNewName} `) - .toBe(expectedNewName); - })); - - it('ReversePipeComp should reverse the input text', fakeAsync(() => { - const inputText = 'the quick brown fox.'; - const expectedText = '.xof nworb kciuq eht'; - - const fixture = TestBed.createComponent(ReversePipeComponent); - fixture.detectChanges(); - - const comp = fixture.componentInstance; - const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement; - const span = fixture.debugElement.query(By.css('span')).nativeElement as HTMLElement; - - // simulate user entering new name in input - input.value = inputText; - - // Dispatch a DOM event so that Angular learns of input value change. - // then wait a tick while ngModel pushes input.box value to comp.text - // and Angular updates the output span - input.dispatchEvent(new Event('input')); - tick(); - fixture.detectChanges(); - expect(span.textContent).withContext('output span').toBe(expectedText); - expect(comp.text).withContext('component.text').toBe(inputText); - })); - - // Use this technique to find attached directives of any kind - it('can examine attached directives and listeners', () => { - const fixture = TestBed.createComponent(InputComponent); - fixture.detectChanges(); - - const inputEl = fixture.debugElement.query(By.css('input')); - - expect(inputEl.providerTokens).withContext('NgModel directive').toContain(NgModel); - - const ngControl = inputEl.injector.get(NgControl); - expect(ngControl).withContext('NgControl directive').toEqual(jasmine.any(NgControl)); - - expect(inputEl.listeners.length).withContext('several listeners attached').toBeGreaterThan(2); - }); - - it('BankAccountComponent should set attributes, styles, classes, and properties', () => { - const fixture = TestBed.createComponent(BankAccountParentComponent); - fixture.detectChanges(); - const comp = fixture.componentInstance; - - // the only child is debugElement of the BankAccount component - const el = fixture.debugElement.children[0]; - const childComp = el.componentInstance as BankAccountComponent; - expect(childComp).toEqual(jasmine.any(BankAccountComponent)); - - expect(el.context).withContext('context is the child component').toBe(childComp); - - expect(el.attributes['account']).withContext('account attribute').toBe(childComp.id); - expect(el.attributes['bank']).withContext('bank attribute').toBe(childComp.bank); - - expect(el.classes['closed']).withContext('closed class').toBe(true); - expect(el.classes['open']).withContext('open class').toBeFalsy(); - - expect(el.styles['color']).withContext('color style').toBe(comp.color); - expect(el.styles['width']) - .withContext('width style') - .toBe(comp.width + 'px'); - - // Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future? - // expect(el.properties['customProperty']).toBe(true, 'customProperty'); - }); - }); - - describe('TestBed component overrides:', () => { - it("should override ChildComp's template", () => { - const fixture = TestBed.configureTestingModule({ - imports: [Child1Component], - }) - .overrideComponent(Child1Component, { - set: {template: 'Fake'}, - }) - .createComponent(Child1Component); - - fixture.detectChanges(); - expect(fixture).toHaveText('Fake'); - }); - - it("should override TestProvidersComp's ValueService provider", () => { - const fixture = TestBed.configureTestingModule({ - imports: [TestProvidersComponent], - }) - .overrideComponent(TestProvidersComponent, { - remove: {providers: [ValueService]}, - add: {providers: [{provide: ValueService, useClass: FakeValueService}]}, - - // Or replace them all (this component has only one provider) - // set: { providers: [{ provide: ValueService, useClass: FakeValueService }] }, - }) - .createComponent(TestProvidersComponent); - - fixture.detectChanges(); - expect(fixture).toHaveText('injected value: faked value', 'text'); - - // Explore the providerTokens - const tokens = fixture.debugElement.providerTokens; - expect(tokens).withContext('component ctor').toContain(fixture.componentInstance.constructor); - expect(tokens).withContext('TestProvidersComp').toContain(TestProvidersComponent); - expect(tokens).withContext('ValueService').toContain(ValueService); - }); - - it("should override TestViewProvidersComp's ValueService viewProvider", () => { - const fixture = TestBed.configureTestingModule({ - imports: [TestViewProvidersComponent], - }) - .overrideComponent(TestViewProvidersComponent, { - // remove: { viewProviders: [ValueService]}, - // add: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] - // }, - - // Or replace them all (this component has only one viewProvider) - set: {viewProviders: [{provide: ValueService, useClass: FakeValueService}]}, - }) - .createComponent(TestViewProvidersComponent); - - fixture.detectChanges(); - expect(fixture).toHaveText('injected value: faked value'); - }); - - it("injected provider should not be same as component's provider", () => { - // TestComponent is parent of TestProvidersComponent - @Component({ - template: '', - imports: [TestProvidersComponent], - }) - class TestComponent {} - - // 3 levels of ValueService provider: module, TestComponent, TestProvidersComponent - const fixture = TestBed.configureTestingModule({ - imports: [TestComponent, TestProvidersComponent], - providers: [ValueService], - }) - .overrideComponent(TestComponent, { - set: {providers: [{provide: ValueService, useValue: {}}]}, - }) - .overrideComponent(TestProvidersComponent, { - set: {providers: [{provide: ValueService, useClass: FakeValueService}]}, - }) - .createComponent(TestComponent); - - let testBedProvider!: ValueService; - - // `inject` uses TestBed's injector - inject([ValueService], (s: ValueService) => (testBedProvider = s))(); - const tcProvider = fixture.debugElement.injector.get(ValueService) as ValueService; - const tpcProvider = fixture.debugElement.children[0].injector.get( - ValueService, - ) as FakeValueService; - - expect(testBedProvider).withContext('testBed/tc not same providers').not.toBe(tcProvider); - expect(testBedProvider).withContext('testBed/tpc not same providers').not.toBe(tpcProvider); - - expect(testBedProvider instanceof ValueService) - .withContext('testBedProvider is ValueService') - .toBe(true); - expect(tcProvider) - .withContext('tcProvider is {}') - .toEqual({} as ValueService); - expect(tpcProvider instanceof FakeValueService) - .withContext('tpcProvider is FakeValueService') - .toBe(true); - }); - - it('can access template local variables as references', () => { - const fixture = TestBed.configureTestingModule({ - imports: [ - ShellComponent, - NeedsContentComponent, - Child1Component, - Child2Component, - Child3Component, - ], - }) - .overrideComponent(ShellComponent, { - set: { - selector: 'test-shell', - imports: [NeedsContentComponent, Child1Component, Child2Component, Child3Component], - template: ` - - - - - -
!
-
- `, - }, - }) - .createComponent(ShellComponent); - - fixture.detectChanges(); - - // NeedsContentComp is the child of ShellComp - const el = fixture.debugElement.children[0]; - const comp = el.componentInstance; - - expect(comp.children.toArray().length) - .withContext('three different child components and an ElementRef with #content') - .toBe(4); - - expect(el.references['nc']).withContext('#nc reference to component').toBe(comp); - - // #docregion custom-predicate - // Filter for DebugElements with a #content reference - const contentRefs = el.queryAll((de) => de.references['content']); - // #enddocregion custom-predicate - expect(contentRefs.length).withContext('elements w/ a #content reference').toBe(4); - }); - }); - - describe('nested (one-deep) component override', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ParentComponent, FakeChildComponent], - }).overrideComponent(ParentComponent, { - set: {imports: [FakeChildComponent]}, - }); - }); - - it('ParentComp should use Fake Child component', () => { - const fixture = TestBed.createComponent(ParentComponent); - fixture.detectChanges(); - expect(fixture).toHaveText('Parent(Fake Child)'); - }); - }); - - describe('nested (two-deep) component override', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ParentComponent, FakeChildWithGrandchildComponent, FakeGrandchildComponent], - }).overrideComponent(ParentComponent, { - set: {imports: [FakeChildWithGrandchildComponent, FakeGrandchildComponent]}, - }); - }); - - it('should use Fake Grandchild component', () => { - const fixture = TestBed.createComponent(ParentComponent); - fixture.detectChanges(); - expect(fixture).toHaveText('Parent(Fake Child(Fake Grandchild))'); - }); - }); -}); -////////// Fakes /////////// - -@Component({ - selector: 'child-1', - template: 'Fake Child', -}) -class FakeChildComponent {} - -@Component({ - selector: 'grandchild-1', - template: 'Fake Grandchild', -}) -class FakeGrandchildComponent {} - -@Component({ - selector: 'child-1', - imports: [FakeGrandchildComponent], - template: 'Fake Child()', -}) -class FakeChildWithGrandchildComponent {} - -@Injectable() -class FakeValueService extends ValueService { - override value = 'faked value'; -} diff --git a/adev/src/content/examples/testing/src/app/demo/demo.ts b/adev/src/content/examples/testing/src/app/demo/demo.ts deleted file mode 100755 index e78dcce2eb3..00000000000 --- a/adev/src/content/examples/testing/src/app/demo/demo.ts +++ /dev/null @@ -1,337 +0,0 @@ -/* eslint-disable @angular-eslint/directive-selector, guard-for-in, @angular-eslint/no-input-rename - */ -import { - Component, - ContentChildren, - Directive, - EventEmitter, - HostBinding, - HostListener, - inject, - Injectable, - input, - output, - OnChanges, - OnDestroy, - OnInit, - Pipe, - PipeTransform, - SimpleChanges, - signal, -} from '@angular/core'; -import {FormsModule} from '@angular/forms'; -import {of} from 'rxjs'; -import {delay} from 'rxjs/operators'; - -import {sharedImports} from '../shared/shared'; - -////////// The App: Services and Components for the tests. ////////////// - -export interface Hero { - name: string; -} - -////////// Services /////////////// -@Injectable() -export class ValueService { - value = 'real value'; - - getValue() { - return this.value; - } - setValue(value: string) { - this.value = value; - } - - getObservableValue() { - return of('observable value'); - } - - getPromiseValue() { - return Promise.resolve('promise value'); - } - - getObservableDelayValue() { - return of('observable delay value').pipe(delay(10)); - } -} - -// #docregion MasterService -@Injectable() -export class MasterService { - public valueService = inject(ValueService); - getValue() { - return this.valueService.getValue(); - } -} -// #enddocregion MasterService - -/////////// Pipe //////////////// -/* - * Reverse the input string. - */ -@Pipe({name: 'reverse'}) -export class ReversePipe implements PipeTransform { - transform(s: string) { - let r = ''; - for (let i = s.length; i; ) { - r += s[--i]; - } - return r; - } -} - -//////////// Components ///////////// -@Component({ - selector: 'bank-account', - template: ` Bank Name: {{ bank() }} Account Id: {{ id() }} `, -}) -export class BankAccountComponent { - bank = input(''); - id = input('', {alias: 'account'}); -} - -/** A component with attributes, styles, classes, and property setting */ -@Component({ - selector: 'bank-account-parent', - template: ` - - `, - imports: [BankAccountComponent], -}) -export class BankAccountParentComponent { - width = 200; - color = 'red'; - isClosed = true; -} - -// #docregion LightswitchComp -@Component({ - selector: 'lightswitch-comp', - template: ` - {{ message }}`, -}) -export class LightswitchComponent { - isOn = false; - clicked() { - this.isOn = !this.isOn; - } - get message() { - return `The light is ${this.isOn ? 'On' : 'Off'}`; - } -} -// #enddocregion LightswitchComp - -@Component({ - selector: 'child-1', - template: 'Child-1({{text()}})', -}) -export class Child1Component { - text = input('Original'); -} - -@Component({ - selector: 'child-2', - template: '
Child-2({{text()}})
', -}) -export class Child2Component { - text = input(''); -} - -@Component({ - selector: 'child-3', - template: '
Child-3({{text}})
', -}) -export class Child3Component { - text = input(''); -} - -@Component({ - selector: 'input-comp', - template: '', - imports: [FormsModule], -}) -export class InputComponent { - name = signal('John'); -} - -@Component({ - selector: 'input-value-comp', - template: ` Name: {{ name }} `, -}) -export class InputValueBinderComponent { - name = 'Sally'; // initial value -} - -@Component({ - selector: 'parent-comp', - imports: [Child1Component], - template: 'Parent()', -}) -export class ParentComponent {} - -@Component({ - selector: 'io-comp', - template: - '', -}) -export class IoComponent { - readonly hero = input.required(); - readonly selected = output(); - - click() { - this.selected.emit(this.hero); - } -} - -@Component({ - selector: 'io-parent-comp', - template: ` - @if (!selectedHero) { -

Click to select a hero

- } - @if (selectedHero) { -

The selected hero is {{ selectedHero.name }}

- } - @for (hero of heroes; track hero) { - - } - `, - imports: [IoComponent, sharedImports], -}) -export class IoParentComponent { - heroes: Hero[] = [{name: 'Bob'}, {name: 'Carol'}, {name: 'Ted'}, {name: 'Alice'}]; - selectedHero!: Hero; - onSelect(hero: Hero) { - this.selectedHero = hero; - } -} - -@Component({ - selector: 'my-if-comp', - template: 'MyIf(@if (showMore) {More})', - imports: [sharedImports], -}) -export class MyIfComponent { - showMore = false; -} - -@Component({ - selector: 'my-service-comp', - template: 'injected value: {{valueService.value}}', - providers: [ValueService], -}) -export class TestProvidersComponent { - public valueService = inject(ValueService); -} - -@Component({ - selector: 'my-service-comp', - template: 'injected value: {{valueService.value}}', - viewProviders: [ValueService], -}) -export class TestViewProvidersComponent { - public valueService = inject(ValueService); -} - -@Component({ - selector: 'external-template-comp', - templateUrl: './demo-external-template.html', -}) -export class ExternalTemplateComponent { - private service = inject(ValueService, {optional: true}); - - serviceValue = this.service?.getValue() ?? ''; -} - -@Component({ - selector: 'comp-w-ext-comp', - imports: [ExternalTemplateComponent], - template: ` -

comp-w-ext-comp

- - `, -}) -export class InnerCompWithExternalTemplateComponent {} - -@Component({selector: 'needs-content', template: ''}) -export class NeedsContentComponent { - // children with #content local variable - @ContentChildren('content') children: any; -} - -@Component({ - selector: 'reverse-pipe-comp', - template: ` - - {{ text | reverse }} - `, - imports: [ReversePipe, FormsModule], -}) -export class ReversePipeComponent { - text = 'my dog has fleas.'; -} - -@Component({ - imports: [NeedsContentComponent], - template: '
Replace Me
', -}) -export class ShellComponent {} - -@Component({ - selector: 'demo-comp', - template: ` -

Specs Demo

- -
-

Input/Output Component

- -
-

External Template Component

- -
-

Component With External Template Component

- -
-

Reverse Pipe

- -
-

InputValueBinder Directive

- -
-

Button Component

- -
-

Needs Content

- - - - - -
!
-
- `, - imports: [ - Child1Component, - Child2Component, - Child3Component, - ExternalTemplateComponent, - InnerCompWithExternalTemplateComponent, - InputValueBinderComponent, - IoParentComponent, - LightswitchComponent, - NeedsContentComponent, - ReversePipeComponent, - ], -}) -export class DemoComponent {} -//////// Aggregations //////////// - -export const demoProviders = [MasterService, ValueService]; diff --git a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.css b/adev/src/content/examples/testing/src/app/hero/hero-detail.component.css deleted file mode 100644 index 29c084dbe5c..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.css +++ /dev/null @@ -1,29 +0,0 @@ -label { - display: inline-block; - width: 3em; - margin: 0.5em 0; - color: #607d8b; - font-weight: bold; -} -input { - height: 2em; - font-size: 1em; - padding-left: 0.4em; -} -button { - margin-top: 20px; - font-family: Arial, sans-serif; - background-color: #eee; - border: none; - padding: 5px 10px; - border-radius: 4px; - cursor: pointer; -} -button:hover { - background-color: #cfd8dc; -} -button:disabled { - background-color: #eee; - color: #ccc; - cursor: auto; -} diff --git a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.html b/adev/src/content/examples/testing/src/app/hero/hero-detail.component.html deleted file mode 100644 index dde10397611..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.html +++ /dev/null @@ -1,15 +0,0 @@ - -@if (hero) { -
-

- {{ hero.name | titlecase }} Details -

-
id: {{ hero.id }}
-
- - -
- - -
-} diff --git a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.spec.ts b/adev/src/content/examples/testing/src/app/hero/hero-detail.component.spec.ts deleted file mode 100755 index cc4dce5f609..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.spec.ts +++ /dev/null @@ -1,310 +0,0 @@ -// #docplaster -import {HttpClient, HttpHandler, provideHttpClient} from '@angular/common/http'; -import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing'; -import {fakeAsync, TestBed, tick} from '@angular/core/testing'; -import {provideRouter, Router} from '@angular/router'; -import {RouterTestingHarness} from '@angular/router/testing'; - -import {asyncData, click} from '../../testing'; -import {Hero} from '../model/hero'; -import {sharedImports} from '../shared/shared'; - -import {HeroDetailComponent} from './hero-detail.component'; -import {HeroDetailService} from './hero-detail.service'; -import {HeroListComponent} from './hero-list.component'; - -////// Testing Vars ////// -let component: HeroDetailComponent; -let harness: RouterTestingHarness; -let page: Page; - -////// Tests ////// -describe('HeroDetailComponent', () => { - describe('with HeroModule setup', heroModuleSetup); - describe('when override its provided HeroDetailService', overrideSetup); - describe('with FormsModule setup', formsModuleSetup); - describe('with SharedModule setup', sharedModuleSetup); -}); - -/////////////////// - -const testHero = getTestHeroes()[0]; -function overrideSetup() { - // #docregion hds-spy - class HeroDetailServiceSpy { - testHero: Hero = {...testHero}; - - /* emit cloned test hero */ - getHero = jasmine - .createSpy('getHero') - .and.callFake(() => asyncData(Object.assign({}, this.testHero))); - - /* emit clone of test hero, with changes merged in */ - saveHero = jasmine - .createSpy('saveHero') - .and.callFake((hero: Hero) => asyncData(Object.assign(this.testHero, hero))); - } - - // #enddocregion hds-spy - - // #docregion setup-override - beforeEach(async () => { - await TestBed.configureTestingModule( - Object.assign({}, appConfig, { - imports: [HeroDetailComponent, HeroListComponent], - providers: [ - provideRouter([ - {path: 'heroes', component: HeroListComponent}, - {path: 'heroes/:id', component: HeroDetailComponent}, - ]), - HttpClient, - HttpHandler, - // HeroDetailService at this level is IRRELEVANT! - {provide: HeroDetailService, useValue: {}}, - ], - }), - ) - // #docregion override-component-method - .overrideComponent(HeroDetailComponent, { - set: {providers: [{provide: HeroDetailService, useClass: HeroDetailServiceSpy}]}, - }); - // #enddocregion override-component-method - }); - // #enddocregion setup-override - - // #docregion override-tests - let hdsSpy: HeroDetailServiceSpy; - - beforeEach(async () => { - harness = await RouterTestingHarness.create(); - component = await harness.navigateByUrl(`/heroes/${testHero.id}`, HeroDetailComponent); - page = new Page(); - // get the component's injected HeroDetailServiceSpy - hdsSpy = harness.routeDebugElement!.injector.get(HeroDetailService) as any; - - harness.detectChanges(); - }); - - it('should have called `getHero`', () => { - expect(hdsSpy.getHero.calls.count()) - .withContext('getHero called once') - .toBe(1, 'getHero called once'); - }); - - it("should display stub hero's name", () => { - expect(page.nameDisplay.textContent).toBe(hdsSpy.testHero.name); - }); - - it('should save stub hero change', fakeAsync(() => { - const origName = hdsSpy.testHero.name; - const newName = 'New Name'; - - page.nameInput.value = newName; - - page.nameInput.dispatchEvent(new Event('input')); // tell Angular - - expect(component.hero.name).withContext('component hero has new name').toBe(newName); - expect(hdsSpy.testHero.name).withContext('service hero unchanged before save').toBe(origName); - - click(page.saveBtn); - expect(hdsSpy.saveHero.calls.count()).withContext('saveHero called once').toBe(1); - - tick(); // wait for async save to complete - expect(hdsSpy.testHero.name).withContext('service hero has new name after save').toBe(newName); - expect(TestBed.inject(Router).url).toEqual('/heroes'); - })); -} -// #enddocregion override-tests - -//////////////////// -import {getTestHeroes} from '../model/testing/test-hero.service'; - -const firstHero = getTestHeroes()[0]; - -function heroModuleSetup() { - // #docregion setup-hero-module - beforeEach(async () => { - await TestBed.configureTestingModule( - Object.assign({}, appConfig, { - imports: [HeroDetailComponent, HeroListComponent], - providers: [ - provideRouter([ - {path: 'heroes/:id', component: HeroDetailComponent}, - {path: 'heroes', component: HeroListComponent}, - ]), - provideHttpClient(), - provideHttpClientTesting(), - ], - }), - ); - }); - // #enddocregion setup-hero-module - - // #docregion route-good-id - describe('when navigate to existing hero', () => { - let expectedHero: Hero; - - beforeEach(async () => { - expectedHero = firstHero; - await createComponent(expectedHero.id); - }); - // #docregion selected-tests - it("should display that hero's name", () => { - expect(page.nameDisplay.textContent).toBe(expectedHero.name); - }); - // #enddocregion route-good-id - - it('should navigate when click cancel', () => { - click(page.cancelBtn); - expect(TestBed.inject(Router).url).toEqual(`/heroes/${expectedHero.id}`); - }); - - it('should save when click save but not navigate immediately', () => { - click(page.saveBtn); - expect(TestBed.inject(HttpTestingController).expectOne({method: 'PUT', url: 'api/heroes'})); - expect(TestBed.inject(Router).url).toEqual('/heroes/41'); - }); - - it('should navigate when click save and save resolves', fakeAsync(() => { - click(page.saveBtn); - tick(); // wait for async save to complete - expect(TestBed.inject(Router).url).toEqual('/heroes/41'); - })); - - // #docregion title-case-pipe - it('should convert hero name to Title Case', async () => { - harness.fixture.autoDetectChanges(); - // get the name's input and display elements from the DOM - const hostElement: HTMLElement = harness.routeNativeElement!; - const nameInput: HTMLInputElement = hostElement.querySelector('input')!; - const nameDisplay: HTMLElement = hostElement.querySelector('span')!; - - // simulate user entering a new name into the input box - nameInput.value = 'quick BROWN fOx'; - - // Dispatch a DOM event so that Angular learns of input value change. - nameInput.dispatchEvent(new Event('input')); - - // Wait for Angular to update the display binding through the title pipe - await harness.fixture.whenStable(); - - expect(nameDisplay.textContent).toBe('Quick Brown Fox'); - }); - // #enddocregion selected-tests - - // #enddocregion title-case-pipe - }); - - // #docregion route-bad-id - describe('when navigate to non-existent hero id', () => { - beforeEach(async () => { - await createComponent(999); - }); - - it('should try to navigate back to hero list', () => { - expect(TestBed.inject(Router).url).toEqual('/heroes'); - }); - }); - // #enddocregion route-bad-id -} - -///////////////////// -import {FormsModule} from '@angular/forms'; -import {TitleCasePipe} from '../shared/title-case.pipe'; -import {appConfig} from '../app.config'; - -function formsModuleSetup() { - // #docregion setup-forms-module - beforeEach(async () => { - await TestBed.configureTestingModule( - Object.assign({}, appConfig, { - imports: [FormsModule, HeroDetailComponent, TitleCasePipe], - providers: [ - provideHttpClient(), - provideHttpClientTesting(), - provideRouter([{path: 'heroes/:id', component: HeroDetailComponent}]), - ], - }), - ); - }); - // #enddocregion setup-forms-module - - it("should display 1st hero's name", async () => { - const expectedHero = firstHero; - await createComponent(expectedHero.id).then(() => { - expect(page.nameDisplay.textContent).toBe(expectedHero.name); - }); - }); -} - -/////////////////////// - -function sharedModuleSetup() { - // #docregion setup-shared-module - beforeEach(async () => { - await TestBed.configureTestingModule( - Object.assign({}, appConfig, { - imports: [HeroDetailComponent, sharedImports], - providers: [ - provideRouter([{path: 'heroes/:id', component: HeroDetailComponent}]), - provideHttpClient(), - provideHttpClientTesting(), - ], - }), - ); - }); - // #enddocregion setup-shared-module - - it("should display 1st hero's name", async () => { - const expectedHero = firstHero; - await createComponent(expectedHero.id).then(() => { - expect(page.nameDisplay.textContent).toBe(expectedHero.name); - }); - }); -} - -/////////// Helpers ///// - -/** Create the HeroDetailComponent, initialize it, set test variables */ -// #docregion create-component -async function createComponent(id: number) { - harness = await RouterTestingHarness.create(); - component = await harness.navigateByUrl(`/heroes/${id}`, HeroDetailComponent); - page = new Page(); - - const request = TestBed.inject(HttpTestingController).expectOne(`api/heroes/?id=${id}`); - const hero = getTestHeroes().find((h) => h.id === Number(id)); - request.flush(hero ? [hero] : []); - harness.detectChanges(); -} -// #enddocregion create-component - -// #docregion page -class Page { - // getter properties wait to query the DOM until called. - get buttons() { - return this.queryAll('button'); - } - get saveBtn() { - return this.buttons[0]; - } - get cancelBtn() { - return this.buttons[1]; - } - get nameDisplay() { - return this.query('span'); - } - get nameInput() { - return this.query('input'); - } - - //// query helpers //// - private query(selector: string): T { - return harness.routeNativeElement!.querySelector(selector)! as T; - } - - private queryAll(selector: string): T[] { - return harness.routeNativeElement!.querySelectorAll(selector) as any as T[]; - } -} -// #enddocregion page diff --git a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.ts b/adev/src/content/examples/testing/src/app/hero/hero-detail.component.ts deleted file mode 100755 index c7e1d51293a..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-detail.component.ts +++ /dev/null @@ -1,64 +0,0 @@ -// #docplaster -import {Component, inject} from '@angular/core'; -import {ActivatedRoute, Router, RouterLink} from '@angular/router'; - -import {Hero} from '../model/hero'; -import {sharedImports} from '../shared/shared'; - -import {HeroDetailService} from './hero-detail.service'; - -// #docregion prototype -@Component({ - selector: 'app-hero-detail', - templateUrl: './hero-detail.component.html', - styleUrls: ['./hero-detail.component.css'], - providers: [HeroDetailService], - imports: [...sharedImports], -}) -export class HeroDetailComponent { - // #docregion inject - private heroDetailService = inject(HeroDetailService); - private route = inject(ActivatedRoute); - private router = inject(Router); - // #enddocregion inject - // #enddocregion prototype - - hero!: Hero; - - // #docregion ctor - constructor() { - // get hero when `id` param changes - this.route.paramMap.subscribe((pmap) => this.getHero(pmap.get('id'))); - } - // #enddocregion ctor - - private getHero(id: string | null): void { - // when no id or id===0, create new blank hero - if (!id) { - this.hero = {id: 0, name: ''} as Hero; - return; - } - - this.heroDetailService.getHero(id).subscribe((hero) => { - if (hero) { - this.hero = hero; - } else { - this.gotoList(); // id not found; navigate to list - } - }); - } - - save(): void { - this.heroDetailService.saveHero(this.hero).subscribe(() => this.gotoList()); - } - - cancel() { - this.gotoList(); - } - - gotoList() { - this.router.navigate(['../'], {relativeTo: this.route}); - } - // #docregion prototype -} -// #enddocregion prototype diff --git a/adev/src/content/examples/testing/src/app/hero/hero-detail.service.ts b/adev/src/content/examples/testing/src/app/hero/hero-detail.service.ts deleted file mode 100755 index 5715cc9d35e..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-detail.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {inject, Injectable} from '@angular/core'; -import {Observable} from 'rxjs'; -import {map} from 'rxjs/operators'; - -import {Hero} from '../model/hero'; -import {HeroService} from '../model/hero.service'; - -// #docregion prototype -@Injectable({providedIn: 'root'}) -export class HeroDetailService { - private heroService = inject(HeroService); - // #enddocregion prototype - - // Returns a clone which caller may modify safely - getHero(id: number | string): Observable { - if (typeof id === 'string') { - id = parseInt(id, 10); - } - return this.heroService.getHero(id).pipe( - map((hero) => (hero ? Object.assign({}, hero) : null)), // clone or null - ); - } - - saveHero(hero: Hero) { - return this.heroService.updateHero(hero); - } - // #docregion prototype -} -// #enddocregion prototype diff --git a/adev/src/content/examples/testing/src/app/hero/hero-list.component.css b/adev/src/content/examples/testing/src/app/hero/hero-list.component.css deleted file mode 100644 index 5e450c54613..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-list.component.css +++ /dev/null @@ -1,70 +0,0 @@ -.selected { - background-color: #cfd8dc !important; - color: white; -} - -.heroes { - margin: 0 0 2em 0; - list-style-type: none; - padding: 0; - width: 15em; -} - -.heroes li { - display: flex; -} - -.heroes button { - flex: 1; - cursor: pointer; - position: relative; - left: 0; - background-color: #eee; - margin: 0.5em; - padding: 0; - border-radius: 4px; - display: flex; - align-items: stretch; - height: 1.8em; -} - -.heroes button:hover { - color: #2c3a41; - background-color: #e6e6e6; - left: 0.1em; -} - -.heroes button:active { - background-color: #525252; - color: #fafafa; -} - -.heroes button.selected { - background-color: black; - color: white; -} - -.heroes button.selected:hover { - background-color: #505050; - color: white; -} - -.heroes button.selected:active { - background-color: black; - color: white; -} - -.heroes .badge { - display: inline-block; - font-size: small; - color: white; - padding: 0.8em 0.7em 0 0.7em; - background-color: #405061; - line-height: 1em; - margin-right: 0.8em; - border-radius: 4px 0 0 4px; -} - -.heroes .name { - align-self: center; -} diff --git a/adev/src/content/examples/testing/src/app/hero/hero-list.component.html b/adev/src/content/examples/testing/src/app/hero/hero-list.component.html deleted file mode 100644 index b21ff09f774..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-list.component.html +++ /dev/null @@ -1,11 +0,0 @@ -

My Heroes

-
    - @for (hero of heroes | async; track hero) { -
  • - -
  • - } -
diff --git a/adev/src/content/examples/testing/src/app/hero/hero-list.component.spec.ts b/adev/src/content/examples/testing/src/app/hero/hero-list.component.spec.ts deleted file mode 100755 index 2ba082c9ee9..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-list.component.spec.ts +++ /dev/null @@ -1,144 +0,0 @@ -import {ComponentFixture, fakeAsync, TestBed, tick, waitForAsync} from '@angular/core/testing'; - -import {By} from '@angular/platform-browser'; -import {DebugElement} from '@angular/core'; - -import {Router} from '@angular/router'; - -import {addMatchers} from '../../testing'; -import {HeroService} from '../model/hero.service'; -import {getTestHeroes, TestHeroService} from '../model/testing/test-hero.service'; - -import {HeroListComponent} from './hero-list.component'; -import {HighlightDirective} from '../shared/highlight.directive'; -import {appConfig} from '../app.config'; - -const HEROES = getTestHeroes(); - -let comp: HeroListComponent; -let fixture: ComponentFixture; -let page: Page; - -/////// Tests ////// - -describe('HeroListComponent', () => { - beforeEach(waitForAsync(() => { - addMatchers(); - const routerSpy = jasmine.createSpyObj('Router', ['navigate']); - - TestBed.configureTestingModule( - Object.assign({}, appConfig, { - providers: [ - {provide: HeroService, useClass: TestHeroService}, - {provide: Router, useValue: routerSpy}, - ], - }), - ) - - .then(createComponent); - })); - - it('should display heroes', () => { - expect(page.heroRows.length).toBeGreaterThan(0); - }); - - it('1st hero should match 1st test hero', () => { - const expectedHero = HEROES[0]; - const actualHero = page.heroRows[0].textContent; - expect(actualHero).withContext('hero.id').toContain(expectedHero.id.toString()); - expect(actualHero).withContext('hero.name').toContain(expectedHero.name); - }); - - it('should select hero on click', fakeAsync(() => { - const expectedHero = HEROES[1]; - const btn = page.heroRows[1].querySelector('button'); - - btn!.dispatchEvent(new Event('click')); - tick(); - // `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService - expect(comp.selectedHero).toEqual(expectedHero); - })); - - it('should navigate to selected hero detail on click', fakeAsync(() => { - const expectedHero = HEROES[1]; - const btn = page.heroRows[1].querySelector('button'); - - btn!.dispatchEvent(new Event('click')); - tick(); - - // should have navigated - expect(page.navSpy.calls.any()).withContext('navigate called').toBe(true); - - // composed hero detail will be URL like 'heroes/42' - // expect link array with the route path and hero id - // first argument to router.navigate is link array - const navArgs = page.navSpy.calls.first().args[0]; - expect(navArgs[0]).withContext('nav to heroes detail URL').toContain('heroes'); - expect(navArgs[1]).withContext('expected hero.id').toBe(expectedHero.id); - })); - - it('should find `HighlightDirective` with `By.directive', () => { - // #docregion by - // Can find DebugElement either by css selector or by directive - const h2 = fixture.debugElement.query(By.css('h2')); - const directive = fixture.debugElement.query(By.directive(HighlightDirective)); - // #enddocregion by - expect(h2).toBe(directive); - }); - - it('should color header with `HighlightDirective`', () => { - const h2 = page.highlightDe.nativeElement as HTMLElement; - const bgColor = h2.style.backgroundColor; - - // different browsers report color values differently - const isExpectedColor = bgColor === 'gold' || bgColor === 'rgb(255, 215, 0)'; - expect(isExpectedColor).withContext('backgroundColor').toBe(true); - }); - - it("the `HighlightDirective` is among the element's providers", () => { - expect(page.highlightDe.providerTokens) - .withContext('HighlightDirective') - .toContain(HighlightDirective); - }); -}); - -/////////// Helpers ///// - -/** Create the component and set the `page` test variables */ -function createComponent() { - fixture = TestBed.createComponent(HeroListComponent); - comp = fixture.componentInstance; - - // change detection triggers ngOnInit which gets a hero - fixture.detectChanges(); - - return fixture.whenStable().then(() => { - // got the heroes and updated component - // change detection updates the view - fixture.detectChanges(); - page = new Page(); - }); -} - -class Page { - /** Hero line elements */ - heroRows: HTMLLIElement[]; - - /** Highlighted DebugElement */ - highlightDe: DebugElement; - - /** Spy on router navigate method */ - navSpy: jasmine.Spy; - - constructor() { - const heroRowNodes = fixture.nativeElement.querySelectorAll('li'); - this.heroRows = Array.from(heroRowNodes); - - // Find the first element with an attached HighlightDirective - this.highlightDe = fixture.debugElement.query(By.directive(HighlightDirective)); - - // Get the component's injected router navigation spy - const routerSpy = fixture.debugElement.injector.get(Router); - this.navSpy = routerSpy.navigate as jasmine.Spy; - } -} diff --git a/adev/src/content/examples/testing/src/app/hero/hero-list.component.ts b/adev/src/content/examples/testing/src/app/hero/hero-list.component.ts deleted file mode 100755 index 6aff874ee90..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero-list.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Component} from '@angular/core'; -import {AsyncPipe} from '@angular/common'; -import {Router} from '@angular/router'; - -import {Observable} from 'rxjs'; - -import {Hero} from '../model/hero'; -import {HeroService} from '../model/hero.service'; -import {sharedImports} from '../shared/shared'; - -@Component({ - selector: 'app-heroes', - templateUrl: './hero-list.component.html', - styleUrls: ['./hero-list.component.css'], - imports: [AsyncPipe, sharedImports], -}) -export class HeroListComponent { - heroes: Observable; - selectedHero!: Hero; - - constructor( - private router: Router, - private heroService: HeroService, - ) { - this.heroes = this.heroService.getHeroes(); - } - - onSelect(hero: Hero) { - this.selectedHero = hero; - this.router.navigate(['../heroes', this.selectedHero.id]); - } -} diff --git a/adev/src/content/examples/testing/src/app/hero/hero.routes.ts b/adev/src/content/examples/testing/src/app/hero/hero.routes.ts deleted file mode 100755 index 1668b130448..00000000000 --- a/adev/src/content/examples/testing/src/app/hero/hero.routes.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {HeroListComponent} from './hero-list.component'; -import {HeroDetailComponent} from './hero-detail.component'; -import {Routes} from '@angular/router'; - -export default [ - {path: '', component: HeroListComponent}, - {path: ':id', component: HeroDetailComponent}, -] as Routes; diff --git a/adev/src/content/examples/testing/src/app/in-memory-data.service.ts b/adev/src/content/examples/testing/src/app/in-memory-data.service.ts deleted file mode 100644 index 23cf6475af6..00000000000 --- a/adev/src/content/examples/testing/src/app/in-memory-data.service.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {InMemoryDbService} from 'angular-in-memory-web-api'; -import {QUOTES} from './twain/twain.data'; - -// Adjust to reduce number of quotes -const maxQuotes = Infinity; // 0; - -/** Create in-memory database of heroes and quotes */ -export class InMemoryDataService implements InMemoryDbService { - createDb() { - const heroes = [ - {id: 12, name: 'Dr. Nice'}, - {id: 13, name: 'Bombasto'}, - {id: 14, name: 'Celeritas'}, - {id: 15, name: 'Magneta'}, - {id: 16, name: 'RubberMan'}, - {id: 17, name: 'Dynama'}, - {id: 18, name: 'Dr. IQ'}, - {id: 19, name: 'Magma'}, - {id: 20, name: 'Tornado'}, - ]; - - return {heroes, quotes: QUOTES.slice(0, maxQuotes)}; - } -} diff --git a/adev/src/content/examples/testing/src/app/model/hero.service.spec.ts b/adev/src/content/examples/testing/src/app/model/hero.service.spec.ts deleted file mode 100644 index 67cad203620..00000000000 --- a/adev/src/content/examples/testing/src/app/model/hero.service.spec.ts +++ /dev/null @@ -1,218 +0,0 @@ -import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; - -// Other imports -import {TestBed} from '@angular/core/testing'; -import {HttpClient, HttpResponse, HttpErrorResponse} from '@angular/common/http'; - -import {asyncData, asyncError} from '../../testing/async-observable-helpers'; - -import {Hero} from './hero'; -import {HeroService} from './hero.service'; - -describe('HeroesService (with spies)', () => { - // #docregion test-with-spies - let httpClientSpy: jasmine.SpyObj; - let heroService: HeroService; - - beforeEach(() => { - // TODO: spy on other methods too - httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']); - heroService = new HeroService(httpClientSpy); - }); - - it('should return expected heroes (HttpClient called once)', (done: DoneFn) => { - const expectedHeroes: Hero[] = [ - {id: 1, name: 'A'}, - {id: 2, name: 'B'}, - ]; - - httpClientSpy.get.and.returnValue(asyncData(expectedHeroes)); - - heroService.getHeroes().subscribe({ - next: (heroes) => { - expect(heroes).withContext('expected heroes').toEqual(expectedHeroes); - done(); - }, - error: done.fail, - }); - expect(httpClientSpy.get.calls.count()).withContext('one call').toBe(1); - }); - - it('should return an error when the server returns a 404', (done: DoneFn) => { - const errorResponse = new HttpErrorResponse({ - error: 'test 404 error', - status: 404, - statusText: 'Not Found', - }); - - httpClientSpy.get.and.returnValue(asyncError(errorResponse)); - - heroService.getHeroes().subscribe({ - next: (heroes) => done.fail('expected an error, not heroes'), - error: (error) => { - expect(error.message).toContain('test 404 error'); - done(); - }, - }); - }); - // #enddocregion test-with-spies -}); - -describe('HeroesService (with mocks)', () => { - let httpClient: HttpClient; - let httpTestingController: HttpTestingController; - let heroService: HeroService; - - beforeEach(() => { - TestBed.configureTestingModule({ - // Import the HttpClient mocking services - imports: [HttpClientTestingModule], - // Provide the service-under-test - providers: [HeroService], - }); - - // Inject the http, test controller, and service-under-test - // as they will be referenced by each test. - httpClient = TestBed.inject(HttpClient); - httpTestingController = TestBed.inject(HttpTestingController); - heroService = TestBed.inject(HeroService); - }); - - afterEach(() => { - // After every test, assert that there are no more pending requests. - httpTestingController.verify(); - }); - - /// HeroService method tests begin /// - describe('#getHeroes', () => { - let expectedHeroes: Hero[]; - - beforeEach(() => { - heroService = TestBed.inject(HeroService); - expectedHeroes = [ - {id: 1, name: 'A'}, - {id: 2, name: 'B'}, - ] as Hero[]; - }); - - it('should return expected heroes (called once)', () => { - heroService.getHeroes().subscribe({ - next: (heroes) => - expect(heroes).withContext('should return expected heroes').toEqual(expectedHeroes), - error: fail, - }); - - // HeroService should have made one request to GET heroes from expected URL - const req = httpTestingController.expectOne(heroService.heroesUrl); - expect(req.request.method).toEqual('GET'); - - // Respond with the mock heroes - req.flush(expectedHeroes); - }); - - it('should be OK returning no heroes', () => { - heroService.getHeroes().subscribe({ - next: (heroes) => - expect(heroes.length).withContext('should have empty heroes array').toEqual(0), - error: fail, - }); - - const req = httpTestingController.expectOne(heroService.heroesUrl); - req.flush([]); // Respond with no heroes - }); - - it('should turn 404 into a user-friendly error', () => { - const msg = 'Deliberate 404'; - heroService.getHeroes().subscribe({ - next: (heroes) => fail('expected to fail'), - error: (error) => expect(error.message).toContain(msg), - }); - - const req = httpTestingController.expectOne(heroService.heroesUrl); - - // respond with a 404 and the error message in the body - req.flush(msg, {status: 404, statusText: 'Not Found'}); - }); - - it('should return expected heroes (called multiple times)', () => { - heroService.getHeroes().subscribe(); - heroService.getHeroes().subscribe(); - heroService.getHeroes().subscribe({ - next: (heroes) => - expect(heroes).withContext('should return expected heroes').toEqual(expectedHeroes), - error: fail, - }); - - const requests = httpTestingController.match(heroService.heroesUrl); - expect(requests.length).withContext('calls to getHeroes()').toEqual(3); - - // Respond to each request with different mock hero results - requests[0].flush([]); - requests[1].flush([{id: 1, name: 'bob'}]); - requests[2].flush(expectedHeroes); - }); - }); - - describe('#updateHero', () => { - // Expecting the query form of URL so should not 404 when id not found - const makeUrl = (id: number) => `${heroService.heroesUrl}/?id=${id}`; - - it('should update a hero and return it', () => { - const updateHero: Hero = {id: 1, name: 'A'}; - - heroService.updateHero(updateHero).subscribe({ - next: (data) => expect(data).withContext('should return the hero').toEqual(updateHero), - error: fail, - }); - - // HeroService should have made one request to PUT hero - const req = httpTestingController.expectOne(heroService.heroesUrl); - expect(req.request.method).toEqual('PUT'); - expect(req.request.body).toEqual(updateHero); - - // Expect server to return the hero after PUT - const expectedResponse = new HttpResponse({ - status: 200, - statusText: 'OK', - body: updateHero, - }); - req.event(expectedResponse); - }); - - it('should turn 404 error into user-facing error', () => { - const msg = 'Deliberate 404'; - const updateHero: Hero = {id: 1, name: 'A'}; - heroService.updateHero(updateHero).subscribe({ - next: (heroes) => fail('expected to fail'), - error: (error) => expect(error.message).toContain(msg), - }); - - const req = httpTestingController.expectOne(heroService.heroesUrl); - - // respond with a 404 and the error message in the body - req.flush(msg, {status: 404, statusText: 'Not Found'}); - }); - - it('should turn network error into user-facing error', (done) => { - // Create mock ProgressEvent with type `error`, raised when something goes wrong at - // the network level. Connection timeout, DNS error, offline, etc. - const errorEvent = new ProgressEvent('error'); - - const updateHero: Hero = {id: 1, name: 'A'}; - heroService.updateHero(updateHero).subscribe({ - next: (heroes) => fail('expected to fail'), - error: (error) => { - expect(error).toBe(errorEvent); - done(); - }, - }); - - const req = httpTestingController.expectOne(heroService.heroesUrl); - - // Respond with mock error - req.error(errorEvent); - }); - }); - - // TODO: test other HeroService methods -}); diff --git a/adev/src/content/examples/testing/src/app/model/hero.service.ts b/adev/src/content/examples/testing/src/app/model/hero.service.ts deleted file mode 100644 index ecfbe462213..00000000000 --- a/adev/src/content/examples/testing/src/app/model/hero.service.ts +++ /dev/null @@ -1,95 +0,0 @@ -import {HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http'; -import {inject, Injectable} from '@angular/core'; -import {Observable} from 'rxjs'; -import {catchError, map, tap} from 'rxjs/operators'; - -import {Hero} from './hero'; - -const httpOptions = { - headers: new HttpHeaders({'Content-Type': 'application/json'}), -}; - -@Injectable({providedIn: 'root'}) -export class HeroService { - readonly heroesUrl = 'api/heroes'; // URL to web api - - private http = inject(HttpClient); - - /** GET heroes from the server */ - getHeroes(): Observable { - return this.http.get(this.heroesUrl).pipe( - tap((heroes) => this.log('fetched heroes')), - catchError(this.handleError('getHeroes')), - ) as Observable; - } - - /** GET hero by id. Return `undefined` when id not found */ - getHero(id: number | string): Observable { - if (typeof id === 'string') { - id = parseInt(id, 10); - } - const url = `${this.heroesUrl}/?id=${id}`; - return this.http.get(url).pipe( - map((heroes) => heroes[0]), // returns a {0|1} element array - tap((h) => { - const outcome = h ? 'fetched' : 'did not find'; - this.log(`${outcome} hero id=${id}`); - }), - catchError(this.handleError(`getHero id=${id}`)), - ); - } - - //////// Save methods ////////// - - /** POST: add a new hero to the server */ - addHero(hero: Hero): Observable { - return this.http.post(this.heroesUrl, hero, httpOptions).pipe( - tap((addedHero) => this.log(`added hero w/ id=${addedHero.id}`)), - catchError(this.handleError('addHero')), - ); - } - /** DELETE: delete the hero from the server */ - deleteHero(hero: Hero | number): Observable { - const id = typeof hero === 'number' ? hero : hero.id; - const url = `${this.heroesUrl}/${id}`; - - return this.http.delete(url, httpOptions).pipe( - tap((_) => this.log(`deleted hero id=${id}`)), - catchError(this.handleError('deleteHero')), - ); - } - - /** PUT: update the hero on the server */ - updateHero(hero: Hero): Observable { - return this.http.put(this.heroesUrl, hero, httpOptions).pipe( - tap((_) => this.log(`updated hero id=${hero.id}`)), - catchError(this.handleError('updateHero')), - ); - } - /** - * Returns a function that handles Http operation failures. - * This error handler lets the app continue to run as if no error occurred. - * - * @param operation - name of the operation that failed - */ - private handleError(operation = 'operation') { - return (error: HttpErrorResponse): Observable => { - // TODO: send the error to remote logging infrastructure - console.error(error); // log to console instead - - // If a native error is caught, do not transform it. We only want to - // transform response errors that are not wrapped in an `Error`. - if (error.error instanceof Event) { - throw error.error; - } - - const message = `server returned code ${error.status} with body "${error.error}"`; - // TODO: better job of transforming error for user consumption - throw new Error(`${operation} failed: ${message}`); - }; - } - - private log(message: string) { - console.log('HeroService: ' + message); - } -} diff --git a/adev/src/content/examples/testing/src/app/model/hero.ts b/adev/src/content/examples/testing/src/app/model/hero.ts deleted file mode 100644 index a61b497759b..00000000000 --- a/adev/src/content/examples/testing/src/app/model/hero.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Hero { - id: number; - name: string; -} diff --git a/adev/src/content/examples/testing/src/app/model/index.ts b/adev/src/content/examples/testing/src/app/model/index.ts deleted file mode 100644 index 694c333a879..00000000000 --- a/adev/src/content/examples/testing/src/app/model/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './hero'; -export * from './hero.service'; -export * from './user.service'; diff --git a/adev/src/content/examples/testing/src/app/model/testing/http-client.spec.ts b/adev/src/content/examples/testing/src/app/model/testing/http-client.spec.ts deleted file mode 100644 index 21dcd3143f6..00000000000 --- a/adev/src/content/examples/testing/src/app/model/testing/http-client.spec.ts +++ /dev/null @@ -1,162 +0,0 @@ -// Http testing module and mocking controller -import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; - -// Other imports -import {TestBed} from '@angular/core/testing'; -import {HttpClient, HttpErrorResponse} from '@angular/common/http'; - -import {HttpHeaders} from '@angular/common/http'; - -interface Data { - name: string; -} - -const testUrl = '/data'; - -describe('HttpClient testing', () => { - let httpClient: HttpClient; - let httpTestingController: HttpTestingController; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [HttpClientTestingModule], - }); - - // Inject the http service and test controller for each test - httpClient = TestBed.inject(HttpClient); - httpTestingController = TestBed.inject(HttpTestingController); - }); - - afterEach(() => { - // After every test, assert that there are no more pending requests. - httpTestingController.verify(); - }); - - /// Tests begin /// - it('can test HttpClient.get', () => { - const testData: Data = {name: 'Test Data'}; - - // Make an HTTP GET request - httpClient.get(testUrl).subscribe((data) => - // When observable resolves, result should match test data - expect(data).toEqual(testData), - ); - - // The following `expectOne()` will match the request's URL. - // If no requests or multiple requests matched that URL - // `expectOne()` would throw. - const req = httpTestingController.expectOne('/data'); - - // Assert that the request is a GET. - expect(req.request.method).toEqual('GET'); - - // Respond with mock data, causing Observable to resolve. - // Subscribe callback asserts that correct data was returned. - req.flush(testData); - - // Finally, assert that there are no outstanding requests. - httpTestingController.verify(); - }); - - it('can test HttpClient.get with matching header', () => { - const testData: Data = {name: 'Test Data'}; - - // Make an HTTP GET request with specific header - httpClient - .get(testUrl, { - headers: new HttpHeaders({Authorization: 'my-auth-token'}), - }) - .subscribe((data) => expect(data).toEqual(testData)); - - // Find request with a predicate function. - // Expect one request with an authorization header - const req = httpTestingController.expectOne((request) => request.headers.has('Authorization')); - req.flush(testData); - }); - - it('can test multiple requests', () => { - const testData: Data[] = [{name: 'bob'}, {name: 'carol'}, {name: 'ted'}, {name: 'alice'}]; - - // Make three requests in a row - httpClient - .get(testUrl) - .subscribe((d) => expect(d.length).withContext('should have no data').toEqual(0)); - - httpClient - .get(testUrl) - .subscribe((d) => - expect(d).withContext('should be one element array').toEqual([testData[0]]), - ); - - httpClient - .get(testUrl) - .subscribe((d) => expect(d).withContext('should be expected data').toEqual(testData)); - - // get all pending requests that match the given URL - const requests = httpTestingController.match(testUrl); - expect(requests.length).toEqual(3); - - // Respond to each request with different results - requests[0].flush([]); - requests[1].flush([testData[0]]); - requests[2].flush(testData); - }); - - it('can test for 404 error', () => { - const emsg = 'deliberate 404 error'; - - httpClient.get(testUrl).subscribe({ - next: (data) => fail('should have failed with the 404 error'), - error: (error: HttpErrorResponse) => { - expect(error.status).withContext('status').toEqual(404); - expect(error.error).withContext('message').toEqual(emsg); - }, - }); - - const req = httpTestingController.expectOne(testUrl); - - // Respond with mock error - req.flush(emsg, {status: 404, statusText: 'Not Found'}); - }); - - it('can test for network error', (done) => { - // Create mock ProgressEvent with type `error`, raised when something goes wrong at - // the network level. Connection timeout, DNS error, offline, etc. - const errorEvent = new ProgressEvent('error'); - - httpClient.get(testUrl).subscribe({ - next: (data) => fail('should have failed with the network error'), - error: (error: HttpErrorResponse) => { - expect(error.error).toBe(errorEvent); - done(); - }, - }); - - const req = httpTestingController.expectOne(testUrl); - - // Respond with mock error - req.error(errorEvent); - }); - - it('httpTestingController.verify should fail if HTTP response not simulated', () => { - // Sends request - httpClient.get('some/api').subscribe(); - - // verify() should fail because haven't handled the pending request. - expect(() => httpTestingController.verify()).toThrow(); - - // Now get and flush the request so that afterEach() doesn't fail - const req = httpTestingController.expectOne('some/api'); - req.flush(null); - }); - - // Proves that verify in afterEach() really would catch error - // if test doesn't simulate the HTTP response. - // - // Must disable this test because can't catch an error in an afterEach(). - // Uncomment if you want to confirm that afterEach() does the job. - // it('afterEach() should fail when HTTP response not simulated',() => { - // // Sends request which is never handled by this test - // httpClient.get('some/api').subscribe(); - // }); -}); diff --git a/adev/src/content/examples/testing/src/app/model/testing/index.ts b/adev/src/content/examples/testing/src/app/model/testing/index.ts deleted file mode 100644 index 898f64c2783..00000000000 --- a/adev/src/content/examples/testing/src/app/model/testing/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './test-hero.service'; diff --git a/adev/src/content/examples/testing/src/app/model/testing/test-hero.service.ts b/adev/src/content/examples/testing/src/app/model/testing/test-hero.service.ts deleted file mode 100644 index c93a3122a8a..00000000000 --- a/adev/src/content/examples/testing/src/app/model/testing/test-hero.service.ts +++ /dev/null @@ -1,63 +0,0 @@ -import {Injectable} from '@angular/core'; - -import {Observable} from 'rxjs'; -import {asyncData} from '../../../testing'; - -import {map} from 'rxjs/operators'; - -// re-export for tester convenience -export {Hero} from '../hero'; -export {HeroService} from '../hero.service'; -export {getTestHeroes} from './test-heroes'; - -import {Hero} from '../hero'; -import {HeroService} from '../hero.service'; -import {getTestHeroes} from './test-heroes'; - -@Injectable() -/** - * FakeHeroService pretends to make real http requests. - * implements only as much of HeroService as is actually consumed by the app - */ -export class TestHeroService extends HeroService { - constructor() { - // This is a fake testing service that won't be making HTTP - // requests so we can pass in `null` as the HTTP client. - super(null!); - } - - heroes = getTestHeroes(); - lastResult!: Observable; // result from last method call - - override addHero(hero: Hero): Observable { - throw new Error('Method not implemented.'); - } - - override deleteHero(hero: number | Hero): Observable { - throw new Error('Method not implemented.'); - } - - override getHeroes(): Observable { - return (this.lastResult = asyncData(this.heroes)); - } - - override getHero(id: number | string): Observable { - if (typeof id === 'string') { - id = parseInt(id, 10); - } - const hero = this.heroes.find((h) => h.id === id); - this.lastResult = asyncData(hero); - return this.lastResult; - } - - override updateHero(hero: Hero): Observable { - return (this.lastResult = this.getHero(hero.id).pipe( - map((h) => { - if (h) { - return Object.assign(h, hero); - } - throw new Error(`Hero ${hero.id} not found`); - }), - )); - } -} diff --git a/adev/src/content/examples/testing/src/app/model/testing/test-heroes.ts b/adev/src/content/examples/testing/src/app/model/testing/test-heroes.ts deleted file mode 100644 index 709ec3212de..00000000000 --- a/adev/src/content/examples/testing/src/app/model/testing/test-heroes.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {Hero} from '../hero'; - -/** return fresh array of test heroes */ -export function getTestHeroes(): Hero[] { - return [ - {id: 41, name: 'Bob'}, - {id: 42, name: 'Carol'}, - {id: 43, name: 'Ted'}, - {id: 44, name: 'Alice'}, - {id: 45, name: 'Speedy'}, - {id: 46, name: 'Stealthy'}, - ]; -} diff --git a/adev/src/content/examples/testing/src/app/model/user.service.ts b/adev/src/content/examples/testing/src/app/model/user.service.ts deleted file mode 100644 index d66826f7f46..00000000000 --- a/adev/src/content/examples/testing/src/app/model/user.service.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {Injectable, signal} from '@angular/core'; - -@Injectable({providedIn: 'root'}) -export class UserService { - isLoggedIn = signal(true); - user = signal({name: 'Sam Spade'}); -} diff --git a/adev/src/content/examples/testing/src/app/shared/canvas.component.spec.ts b/adev/src/content/examples/testing/src/app/shared/canvas.component.spec.ts deleted file mode 100755 index 3d8f0006427..00000000000 --- a/adev/src/content/examples/testing/src/app/shared/canvas.component.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -// #docplaster -// #docregion without-toBlob-macrotask -import {fakeAsync, TestBed, tick} from '@angular/core/testing'; - -import {CanvasComponent} from './canvas.component'; - -describe('CanvasComponent', () => { - // #enddocregion without-toBlob-macrotask - // #docregion enable-toBlob-macrotask - beforeEach(() => { - (window as any).__zone_symbol__FakeAsyncTestMacroTask = [ - { - source: 'HTMLCanvasElement.toBlob', - callbackArgs: [{size: 200}], - }, - ]; - }); - // #enddocregion enable-toBlob-macrotask - // #docregion without-toBlob-macrotask - it('should be able to generate blob data from canvas', fakeAsync(() => { - const fixture = TestBed.createComponent(CanvasComponent); - const canvasComp = fixture.componentInstance; - - fixture.detectChanges(); - expect(canvasComp.blobSize).toBe(0); - - tick(); - expect(canvasComp.blobSize).toBeGreaterThan(0); - })); -}); -// #enddocregion without-toBlob-macrotask diff --git a/adev/src/content/examples/testing/src/app/shared/canvas.component.ts b/adev/src/content/examples/testing/src/app/shared/canvas.component.ts deleted file mode 100755 index 90a23b7acf8..00000000000 --- a/adev/src/content/examples/testing/src/app/shared/canvas.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -// #docplaster -// #docregion import-canvas-patch -// Import patch to make async `HTMLCanvasElement` methods (such as `.toBlob()`) Zone.js-aware. -// Either import in `polyfills.ts` (if used in more than one places in the app) or in the component -// file using `HTMLCanvasElement` (if it is only used in a single file). -import 'zone.js/plugins/zone-patch-canvas'; -// #enddocregion import-canvas-patch -// #docregion main -import {Component, AfterViewInit, ViewChild, ElementRef} from '@angular/core'; - -@Component({ - selector: 'sample-canvas', - template: '', -}) -export class CanvasComponent implements AfterViewInit { - blobSize = 0; - @ViewChild('sampleCanvas') sampleCanvas!: ElementRef; - - ngAfterViewInit() { - const canvas: HTMLCanvasElement = this.sampleCanvas.nativeElement; - const context = canvas.getContext('2d')!; - - context.clearRect(0, 0, 200, 200); - context.fillStyle = '#FF1122'; - context.fillRect(0, 0, 200, 200); - - canvas.toBlob((blob) => { - this.blobSize = blob?.size ?? 0; - }); - } -} -// #enddocregion main diff --git a/adev/src/content/examples/testing/src/app/shared/highlight.directive.spec.ts b/adev/src/content/examples/testing/src/app/shared/highlight.directive.spec.ts deleted file mode 100755 index ffc340fd347..00000000000 --- a/adev/src/content/examples/testing/src/app/shared/highlight.directive.spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -import {Component, DebugElement} from '@angular/core'; -import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {By} from '@angular/platform-browser'; - -import {HighlightDirective} from './highlight.directive'; - -// #docregion test-component -@Component({ - template: `

Something Yellow

-

The Default (Gray)

-

No Highlight

- `, - imports: [HighlightDirective], -}) -class TestComponent {} -// #enddocregion test-component - -describe('HighlightDirective', () => { - let fixture: ComponentFixture; - let des: DebugElement[]; // the three elements w/ the directive - let bareH2: DebugElement; // the

w/o the directive - - // #docregion selected-tests - beforeEach(() => { - fixture = TestBed.configureTestingModule({ - imports: [HighlightDirective, TestComponent], - }).createComponent(TestComponent); - - fixture.detectChanges(); // initial binding - - // all elements with an attached HighlightDirective - des = fixture.debugElement.queryAll(By.directive(HighlightDirective)); - - // the h2 without the HighlightDirective - bareH2 = fixture.debugElement.query(By.css('h2:not([highlight])')); - }); - - // color tests - it('should have three highlighted elements', () => { - expect(des.length).toBe(3); - }); - - it('should color 1st

background "yellow"', () => { - const bgColor = des[0].nativeElement.style.backgroundColor; - expect(bgColor).toBe('yellow'); - }); - - it('should color 2nd

background w/ default color', () => { - const dir = des[1].injector.get(HighlightDirective) as HighlightDirective; - const bgColor = des[1].nativeElement.style.backgroundColor; - expect(bgColor).toBe(dir.defaultColor); - }); - - it('should bind background to value color', () => { - // easier to work with nativeElement - const input = des[2].nativeElement as HTMLInputElement; - expect(input.style.backgroundColor).withContext('initial backgroundColor').toBe('cyan'); - - input.value = 'green'; - - // Dispatch a DOM event so that Angular responds to the input value change. - input.dispatchEvent(new Event('input')); - fixture.detectChanges(); - - expect(input.style.backgroundColor).withContext('changed backgroundColor').toBe('green'); - }); - - it('bare

should not have a customProperty', () => { - expect(bareH2.properties['customProperty']).toBeUndefined(); - }); - // #enddocregion selected-tests - - // Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future? - // // customProperty tests - // it('all highlighted elements should have a true customProperty', () => { - // const allTrue = des.map(de => !!de.properties['customProperty']).every(v => v === true); - // expect(allTrue).toBe(true); - // }); - - // injected directive - // attached HighlightDirective can be injected - it('can inject `HighlightDirective` in 1st

', () => { - const dir = des[0].injector.get(HighlightDirective); - expect(dir).toBeTruthy(); - }); - - it('cannot inject `HighlightDirective` in 3rd

', () => { - const dir = bareH2.injector.get(HighlightDirective, null); - expect(dir).toBe(null); - }); - - // DebugElement.providerTokens - // attached HighlightDirective should be listed in the providerTokens - it('should have `HighlightDirective` in 1st

providerTokens', () => { - expect(des[0].providerTokens).toContain(HighlightDirective); - }); - - it('should not have `HighlightDirective` in 3rd

providerTokens', () => { - expect(bareH2.providerTokens).not.toContain(HighlightDirective); - }); -}); diff --git a/adev/src/content/examples/testing/src/app/shared/highlight.directive.ts b/adev/src/content/examples/testing/src/app/shared/highlight.directive.ts deleted file mode 100755 index 858d3843660..00000000000 --- a/adev/src/content/examples/testing/src/app/shared/highlight.directive.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-disable @angular-eslint/directive-selector */ -// #docregion -import {Directive, ElementRef, inject, input, OnChanges} from '@angular/core'; - -@Directive({selector: '[highlight]'}) -/** - * Set backgroundColor for the attached element to highlight color - * and set the element's customProperty to true - */ -export class HighlightDirective implements OnChanges { - defaultColor = 'rgb(211, 211, 211)'; // lightgray - - bgColor = input('', {alias: 'highlight'}); - - private el = inject(ElementRef); - - constructor() { - this.el.nativeElement.style.customProperty = true; - } - - ngOnChanges() { - this.el.nativeElement.style.backgroundColor = this.bgColor || this.defaultColor; - } -} diff --git a/adev/src/content/examples/testing/src/app/shared/shared.ts b/adev/src/content/examples/testing/src/app/shared/shared.ts deleted file mode 100755 index 01bf42aa126..00000000000 --- a/adev/src/content/examples/testing/src/app/shared/shared.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {FormsModule} from '@angular/forms'; - -import {HighlightDirective} from './highlight.directive'; -import {TitleCasePipe} from './title-case.pipe'; - -export const sharedImports = [FormsModule, HighlightDirective, TitleCasePipe]; diff --git a/adev/src/content/examples/testing/src/app/shared/title-case.pipe.spec.ts b/adev/src/content/examples/testing/src/app/shared/title-case.pipe.spec.ts deleted file mode 100644 index a4501980cdb..00000000000 --- a/adev/src/content/examples/testing/src/app/shared/title-case.pipe.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -// #docplaster -// #docregion -import {TitleCasePipe} from './title-case.pipe'; - -// #docregion excerpt -describe('TitleCasePipe', () => { - // This pipe is a pure, stateless function so no need for BeforeEach - const pipe = new TitleCasePipe(); - - it('transforms "abc" to "Abc"', () => { - expect(pipe.transform('abc')).toBe('Abc'); - }); - - it('transforms "abc def" to "Abc Def"', () => { - expect(pipe.transform('abc def')).toBe('Abc Def'); - }); - - // ... more tests ... - // #enddocregion excerpt - it('leaves "Abc Def" unchanged', () => { - expect(pipe.transform('Abc Def')).toBe('Abc Def'); - }); - - it('transforms "abc-def" to "Abc-def"', () => { - expect(pipe.transform('abc-def')).toBe('Abc-def'); - }); - - it('transforms " abc def" to " Abc Def" (preserves spaces) ', () => { - expect(pipe.transform(' abc def')).toBe(' Abc Def'); - }); - // #docregion excerpt -}); -// #enddocregion excerpt diff --git a/adev/src/content/examples/testing/src/app/shared/title-case.pipe.ts b/adev/src/content/examples/testing/src/app/shared/title-case.pipe.ts deleted file mode 100755 index d0861444fc9..00000000000 --- a/adev/src/content/examples/testing/src/app/shared/title-case.pipe.ts +++ /dev/null @@ -1,12 +0,0 @@ -// #docregion -import {Pipe, PipeTransform} from '@angular/core'; - -@Pipe({name: 'titlecase', pure: true}) -/** Transform to Title Case: uppercase the first letter of the words in a string. */ -export class TitleCasePipe implements PipeTransform { - transform(input: string): string { - return input.length === 0 - ? '' - : input.replace(/\w\S*/g, (txt) => txt[0].toUpperCase() + txt.slice(1).toLowerCase()); - } -} diff --git a/adev/src/content/examples/testing/src/app/twain/quote.ts b/adev/src/content/examples/testing/src/app/twain/quote.ts deleted file mode 100644 index 293b1348801..00000000000 --- a/adev/src/content/examples/testing/src/app/twain/quote.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Quote { - id: number; - quote: string; -} diff --git a/adev/src/content/examples/testing/src/app/twain/twain.component.marbles.spec.ts b/adev/src/content/examples/testing/src/app/twain/twain.component.marbles.spec.ts deleted file mode 100755 index d69b474d4a1..00000000000 --- a/adev/src/content/examples/testing/src/app/twain/twain.component.marbles.spec.ts +++ /dev/null @@ -1,86 +0,0 @@ -// #docplaster -import {fakeAsync, ComponentFixture, TestBed, tick} from '@angular/core/testing'; - -// #docregion import-marbles -import {cold, getTestScheduler} from 'jasmine-marbles'; -// #enddocregion import-marbles - -import {TwainService} from './twain.service'; -import {TwainComponent} from './twain.component'; - -describe('TwainComponent (marbles)', () => { - let component: TwainComponent; - let fixture: ComponentFixture; - let getQuoteSpy: jasmine.Spy; - let quoteEl: HTMLElement; - let testQuote: string; - - // Helper function to get the error message element value - // An *ngIf keeps it out of the DOM until there is an error - const errorMessage = () => { - const el = fixture.nativeElement.querySelector('.error'); - return el ? el.textContent : null; - }; - - beforeEach(() => { - // Create a fake TwainService object with a `getQuote()` spy - const twainService = jasmine.createSpyObj('TwainService', ['getQuote']); - getQuoteSpy = twainService.getQuote; - - TestBed.configureTestingModule({ - imports: [TwainComponent], - providers: [{provide: TwainService, useValue: twainService}], - }); - - fixture = TestBed.createComponent(TwainComponent); - component = fixture.componentInstance; - quoteEl = fixture.nativeElement.querySelector('.twain'); - testQuote = 'Test Quote'; - }); - - // A synchronous test that simulates async behavior - // #docregion get-quote-test - it('should show quote after getQuote (marbles)', () => { - // observable test quote value and complete(), after delay - // #docregion test-quote-marbles - const q$ = cold('---x|', {x: testQuote}); - // #enddocregion test-quote-marbles - getQuoteSpy.and.returnValue(q$); - - fixture.detectChanges(); // ngOnInit() - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - - // #docregion test-scheduler-flush - getTestScheduler().flush(); // flush the observables - // #enddocregion test-scheduler-flush - - fixture.detectChanges(); // update view - - expect(quoteEl.textContent).withContext('should show quote').toBe(testQuote); - expect(errorMessage()).withContext('should not show error').toBeNull(); - }); - // #enddocregion get-quote-test - - // Still need fakeAsync() because of component's setTimeout() - // #docregion error-test - it('should display error when TwainService fails', fakeAsync(() => { - // observable error after delay - // #docregion error-marbles - const q$ = cold('---#|', null, new Error('TwainService test failure')); - // #enddocregion error-marbles - getQuoteSpy.and.returnValue(q$); - - fixture.detectChanges(); // ngOnInit() - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - - getTestScheduler().flush(); // flush the observables - tick(); // component shows error after a setTimeout() - fixture.detectChanges(); // update error message - - expect(errorMessage()) - .withContext('should display error') - .toMatch(/test failure/); - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - })); - // #enddocregion error-test -}); diff --git a/adev/src/content/examples/testing/src/app/twain/twain.component.spec.ts b/adev/src/content/examples/testing/src/app/twain/twain.component.spec.ts deleted file mode 100755 index 874c1f67728..00000000000 --- a/adev/src/content/examples/testing/src/app/twain/twain.component.spec.ts +++ /dev/null @@ -1,157 +0,0 @@ -// #docplaster -import {fakeAsync, ComponentFixture, TestBed, tick, waitForAsync} from '@angular/core/testing'; - -import {asyncData, asyncError} from '../../testing'; - -import {Subject, defer, of, throwError} from 'rxjs'; -import {last} from 'rxjs/operators'; - -import {TwainComponent} from './twain.component'; -import {TwainService} from './twain.service'; - -describe('TwainComponent', () => { - let component: TwainComponent; - let fixture: ComponentFixture; - let getQuoteSpy: jasmine.Spy; - let quoteEl: HTMLElement; - let testQuote: string; - - // Helper function to get the error message element value - // An *ngIf keeps it out of the DOM until there is an error - const errorMessage = () => { - const el = fixture.nativeElement.querySelector('.error'); - return el ? el.textContent : null; - }; - - // #docregion setup - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TwainService], - }); - testQuote = 'Test Quote'; - - // #docregion spy - // Create a fake TwainService object with a `getQuote()` spy - const twainService = TestBed.inject(TwainService); - // Make the spy return a synchronous Observable with the test data - getQuoteSpy = spyOn(twainService, 'getQuote').and.returnValue(of(testQuote)); - // #enddocregion spy - - fixture = TestBed.createComponent(TwainComponent); - fixture.autoDetectChanges(); - component = fixture.componentInstance; - quoteEl = fixture.nativeElement.querySelector('.twain'); - }); - // #enddocregion setup - - describe('when test with synchronous observable', () => { - it('should not show quote before OnInit', () => { - expect(quoteEl.textContent).withContext('nothing displayed').toBe(''); - expect(errorMessage()).withContext('should not show error element').toBeNull(); - expect(getQuoteSpy.calls.any()).withContext('getQuote not yet called').toBe(false); - }); - - // The quote would not be immediately available if the service were truly async. - // #docregion sync-test - it('should show quote after component initialized', async () => { - await fixture.whenStable(); // onInit() - - // sync spy result shows testQuote immediately after init - expect(quoteEl.textContent).toBe(testQuote); - expect(getQuoteSpy.calls.any()).withContext('getQuote called').toBe(true); - }); - // #enddocregion sync-test - - // The error would not be immediately available if the service were truly async. - // Use `fakeAsync` because the component error calls `setTimeout` - // #docregion error-test - it('should display error when TwainService fails', fakeAsync(() => { - // tell spy to return an error observable after a timeout - getQuoteSpy.and.returnValue( - defer(() => { - return new Promise((resolve, reject) => { - setTimeout(() => { - reject('TwainService test failure'); - }); - }); - }), - ); - fixture.detectChanges(); // onInit() - // sync spy errors immediately after init - - tick(); // flush the setTimeout() - - fixture.detectChanges(); // update errorMessage within setTimeout() - - expect(errorMessage()) - .withContext('should display error') - .toMatch(/test failure/); - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - })); - // #enddocregion error-test - }); - - describe('when test with asynchronous observable', () => { - beforeEach(() => { - // #docregion async-setup - // Simulate delayed observable values with the `asyncData()` helper - getQuoteSpy.and.returnValue(asyncData(testQuote)); - // #enddocregion async-setup - }); - - it('should not show quote before OnInit', () => { - expect(quoteEl.textContent).withContext('nothing displayed').toBe(''); - expect(errorMessage()).withContext('should not show error element').toBeNull(); - expect(getQuoteSpy.calls.any()).withContext('getQuote not yet called').toBe(false); - }); - - it('should still not show quote after component initialized', () => { - fixture.detectChanges(); - // getQuote service is async => still has not returned with quote - // so should show the start value, '...' - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - expect(errorMessage()).withContext('should not show error').toBeNull(); - expect(getQuoteSpy.calls.any()).withContext('getQuote called').toBe(true); - }); - - // #docregion fake-async-test - it('should show quote after getQuote (fakeAsync)', fakeAsync(() => { - fixture.detectChanges(); // ngOnInit() - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - - tick(); // flush the observable to get the quote - fixture.detectChanges(); // update view - - expect(quoteEl.textContent).withContext('should show quote').toBe(testQuote); - expect(errorMessage()).withContext('should not show error').toBeNull(); - })); - // #enddocregion fake-async-test - - // #docregion async-test - it('should show quote after getQuote (async)', async () => { - fixture.detectChanges(); // ngOnInit() - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - - await fixture.whenStable(); - // wait for async getQuote - fixture.detectChanges(); // update view with quote - expect(quoteEl.textContent).toBe(testQuote); - expect(errorMessage()).withContext('should not show error').toBeNull(); - }); - // #enddocregion async-test - - it('should display error when TwainService fails', fakeAsync(() => { - // tell spy to return an async error observable - getQuoteSpy.and.returnValue(asyncError('TwainService test failure')); - - fixture.detectChanges(); - tick(); // component shows error after a setTimeout() - fixture.detectChanges(); // update error message - - expect(errorMessage()) - .withContext('should display error') - .toMatch(/test failure/); - expect(quoteEl.textContent).withContext('should show placeholder').toBe('...'); - })); - }); -}); diff --git a/adev/src/content/examples/testing/src/app/twain/twain.component.ts b/adev/src/content/examples/testing/src/app/twain/twain.component.ts deleted file mode 100755 index c14e7fe466a..00000000000 --- a/adev/src/content/examples/testing/src/app/twain/twain.component.ts +++ /dev/null @@ -1,47 +0,0 @@ -// #docregion -import {Component, inject, OnInit, signal} from '@angular/core'; -import {AsyncPipe} from '@angular/common'; -import {sharedImports} from '../shared/shared'; - -import {Observable, of} from 'rxjs'; -import {catchError, startWith} from 'rxjs/operators'; - -import {TwainService} from './twain.service'; - -@Component({ - selector: 'twain-quote', - // #docregion template - template: `

- {{ quote | async }} -

- - @if (errorMessage()) { -

{{ errorMessage() }}

- }`, - // #enddocregion template - styles: ['.twain { font-style: italic; } .error { color: red; }'], - imports: [AsyncPipe, sharedImports], -}) -export class TwainComponent { - errorMessage = signal(''); - quote?: Observable; - - private twainService = inject(TwainService); - - constructor() { - this.getQuote(); - } - - // #docregion get-quote - getQuote() { - this.errorMessage.set(''); - this.quote = this.twainService.getQuote().pipe( - startWith('...'), - catchError((err: any) => { - this.errorMessage.set(err.message || err.toString()); - return of('...'); // reset message to placeholder - }), - ); - // #enddocregion get-quote - } -} diff --git a/adev/src/content/examples/testing/src/app/twain/twain.data.ts b/adev/src/content/examples/testing/src/app/twain/twain.data.ts deleted file mode 100644 index 9b550934c03..00000000000 --- a/adev/src/content/examples/testing/src/app/twain/twain.data.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {Quote} from './quote'; - -export const QUOTES: Quote[] = [ - 'Always do right. This will gratify some people and astonish the rest.', - 'I have never let my schooling interfere with my education.', - "Don't go around saying the world owes you a living. The world owes you nothing. It was here first.", - 'Whenever you find yourself on the side of the majority, it is time to pause and reflect.', - "If you tell the truth, you don't have to remember anything.", - 'Clothes make the man. Naked people have little or no influence on society.', - "It's not the size of the dog in the fight, it's the size of the fight in the dog.", - "Truth is stranger than fiction, but it is because Fiction is obliged to stick to possibilities; Truth isn't.", - 'The man who does not read good books has no advantage over the man who cannot read them.', - 'Get your facts first, and then you can distort them as much as you please.', -].map((q, i) => ({id: i + 1, quote: q})); diff --git a/adev/src/content/examples/testing/src/app/twain/twain.service.ts b/adev/src/content/examples/testing/src/app/twain/twain.service.ts deleted file mode 100644 index 30d9d630373..00000000000 --- a/adev/src/content/examples/testing/src/app/twain/twain.service.ts +++ /dev/null @@ -1,45 +0,0 @@ -// Mark Twain Quote service gets quotes from server -import {inject, Injectable} from '@angular/core'; -import {HttpClient, HttpErrorResponse} from '@angular/common/http'; - -import {Observable, of, throwError, Observer} from 'rxjs'; -import {concat, map, retryWhen, switchMap, take, tap} from 'rxjs/operators'; - -import {Quote} from './quote'; - -@Injectable() -export class TwainService { - private http = inject(HttpClient); - - private nextId = 1; - - getQuote(): Observable { - return Observable.create((observer: Observer) => observer.next(this.nextId++)).pipe( - // tap((id: number) => console.log(id)), - // tap((id: number) => { throw new Error('Simulated server error'); }), - - switchMap((id: number) => this.http.get(`api/quotes/${id}`)), - // tap((q : Quote) => console.log(q)), - map((q: Quote) => q.quote), - - // `errors` is observable of http.get errors - retryWhen((errors) => - errors.pipe( - switchMap((error: HttpErrorResponse) => { - if (error.status === 404) { - // Queried for quote that doesn't exist. - this.nextId = 1; // retry with quote id:1 - return of(null); // signal OK to retry - } - // Some other HTTP error. - console.error(error); - return throwError('Cannot get Twain quotes from the server'); - }), - take(2), - // If a second retry value, then didn't find id:1 and triggers the following error - concat(throwError('There are no Twain quotes')), // didn't find id:1 - ), - ), - ); - } -} diff --git a/adev/src/content/examples/testing/src/app/welcome/welcome.component.spec.ts b/adev/src/content/examples/testing/src/app/welcome/welcome.component.spec.ts deleted file mode 100755 index 149a6f91c9f..00000000000 --- a/adev/src/content/examples/testing/src/app/welcome/welcome.component.spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -// #docplaster -import {ComponentFixture, inject, TestBed} from '@angular/core/testing'; - -import {UserService} from '../model/user.service'; -import {WelcomeComponent} from './welcome.component'; - -// #docregion mock-user-service -class MockUserService { - isLoggedIn = true; - user = {name: 'Test User'}; -} -// #enddocregion mock-user-service - -describe('WelcomeComponent', () => { - let comp: WelcomeComponent; - let fixture: ComponentFixture; - let componentUserService: UserService; // the actually injected service - let userService: UserService; // the TestBed injected service - let el: HTMLElement; // the DOM element with the welcome message - - // #docregion setup - beforeEach(() => { - fixture = TestBed.createComponent(WelcomeComponent); - fixture.autoDetectChanges(); - comp = fixture.componentInstance; - - // #docregion injected-service - // UserService actually injected into the component - userService = fixture.debugElement.injector.get(UserService); - // #enddocregion injected-service - componentUserService = userService; - // #docregion inject-from-testbed - // UserService from the root injector - userService = TestBed.inject(UserService); - // #enddocregion inject-from-testbed - - // get the "welcome" element by CSS selector (e.g., by class name) - el = fixture.nativeElement.querySelector('.welcome'); - }); - // #enddocregion setup - - // #docregion tests - it('should welcome the user', async () => { - await fixture.whenStable(); - const content = el.textContent; - expect(content).withContext('"Welcome ..."').toContain('Welcome'); - expect(content).withContext('expected name').toContain('Test User'); - }); - - it('should welcome "Bubba"', async () => { - userService.user.set({name: 'Bubba'}); // welcome message hasn't been shown yet - await fixture.whenStable(); - expect(el.textContent).toContain('Bubba'); - }); - - it('should request login if not logged in', async () => { - userService.isLoggedIn.set(false); // welcome message hasn't been shown yet - await fixture.whenStable(); - const content = el.textContent; - expect(content).withContext('not welcomed').not.toContain('Welcome'); - expect(content) - .withContext('"log in"') - .toMatch(/log in/i); - }); - // #enddocregion tests - - it("should inject the component's UserService instance", inject( - [UserService], - (service: UserService) => { - expect(service).toBe(componentUserService); - }, - )); - - it('TestBed and Component UserService should be the same', () => { - expect(userService).toBe(componentUserService); - }); -}); diff --git a/adev/src/content/examples/testing/src/app/welcome/welcome.component.ts b/adev/src/content/examples/testing/src/app/welcome/welcome.component.ts deleted file mode 100755 index 03d5936d75d..00000000000 --- a/adev/src/content/examples/testing/src/app/welcome/welcome.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -// #docregion -import {Component, inject, OnInit, signal} from '@angular/core'; -import {UserService} from '../model/user.service'; - -@Component({ - selector: 'app-welcome', - template: '

{{welcome()}}

', -}) -// #docregion class -export class WelcomeComponent { - welcome = signal(''); - private userService = inject(UserService); - - constructor() { - this.welcome.set( - this.userService.isLoggedIn() ? 'Welcome, ' + this.userService.user().name : 'Please log in.', - ); - } -} -// #enddocregion class diff --git a/adev/src/content/examples/testing/src/expected.ts b/adev/src/content/examples/testing/src/expected.ts deleted file mode 100644 index 5339fa97259..00000000000 --- a/adev/src/content/examples/testing/src/expected.ts +++ /dev/null @@ -1 +0,0 @@ -/* Ignore. Satisfies static analysis of router config in app.component.router.spec.ts */ diff --git a/adev/src/content/examples/testing/src/index-specs.html b/adev/src/content/examples/testing/src/index-specs.html deleted file mode 100644 index ca132f6cd05..00000000000 --- a/adev/src/content/examples/testing/src/index-specs.html +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/adev/src/content/examples/testing/src/index.html b/adev/src/content/examples/testing/src/index.html deleted file mode 100644 index 4106cb2d82e..00000000000 --- a/adev/src/content/examples/testing/src/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - App Under Test - - - - - - - - diff --git a/adev/src/content/examples/testing/src/main.ts b/adev/src/content/examples/testing/src/main.ts deleted file mode 100755 index 091b8a9b07c..00000000000 --- a/adev/src/content/examples/testing/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -// main app entry point -import {bootstrapApplication} from '@angular/platform-browser'; -import {AppComponent} from './app/app.component'; -import {appConfig} from './app/app.config'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); diff --git a/adev/src/content/examples/testing/src/test.css b/adev/src/content/examples/testing/src/test.css deleted file mode 100644 index d832553e525..00000000000 --- a/adev/src/content/examples/testing/src/test.css +++ /dev/null @@ -1 +0,0 @@ -@import '~jasmine-core/lib/jasmine-core/jasmine.css'; diff --git a/adev/src/content/examples/testing/src/testing/async-observable-helpers.ts b/adev/src/content/examples/testing/src/testing/async-observable-helpers.ts deleted file mode 100644 index d2cdd657237..00000000000 --- a/adev/src/content/examples/testing/src/testing/async-observable-helpers.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Mock async observables that return asynchronously. - * The observable either emits once and completes or errors. - * - * Must call `tick()` when test with `fakeAsync()`. - * - * THE FOLLOWING DON'T WORK - * Using `of().delay()` triggers TestBed errors; - * see https://github.com/angular/angular/issues/10127 . - * - * Using `asap` scheduler - as in `of(value, asap)` - doesn't work either. - */ -import {defer} from 'rxjs'; - -// #docregion async-data -/** - * Create async observable that emits-once and completes - * after a JS engine turn - */ -export function asyncData(data: T) { - return defer(() => Promise.resolve(data)); -} -// #enddocregion async-data - -// #docregion async-error -/** - * Create async observable error that errors - * after a JS engine turn - */ -export function asyncError(errorObject: any) { - return defer(() => Promise.reject(errorObject)); -} -// #enddocregion async-error diff --git a/adev/src/content/examples/testing/src/testing/index.ts b/adev/src/content/examples/testing/src/testing/index.ts deleted file mode 100644 index 0cf2d1cb81b..00000000000 --- a/adev/src/content/examples/testing/src/testing/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {DebugElement} from '@angular/core'; -import {ComponentFixture, tick} from '@angular/core/testing'; - -export * from './async-observable-helpers'; -export * from './jasmine-matchers'; - -///// Short utilities ///// - -/** Wait a tick, then detect changes */ -export function advance(f: ComponentFixture): void { - tick(); - f.detectChanges(); -} - -// See https://developer.mozilla.org/docs/Web/API/MouseEvent/button -// #docregion click-event -/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */ -export const ButtonClickEvents = { - left: {button: 0}, - right: {button: 2}, -}; - -/** Simulate element click. Defaults to mouse left-button click event. */ -export function click( - el: DebugElement | HTMLElement, - eventObj: any = ButtonClickEvents.left, -): void { - if (el instanceof HTMLElement) { - el.click(); - } else { - el.triggerEventHandler('click', eventObj); - } -} -// #enddocregion click-event diff --git a/adev/src/content/examples/testing/src/testing/jasmine-matchers.d.ts b/adev/src/content/examples/testing/src/testing/jasmine-matchers.d.ts deleted file mode 100644 index 8378ffb9bce..00000000000 --- a/adev/src/content/examples/testing/src/testing/jasmine-matchers.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -// TODO: fix -// declare namespace jasmine { -// interface Matchers { -// toHaveText(actual: any, expectationFailOutput?: any): jasmine.CustomMatcher; -// } -// } diff --git a/adev/src/content/examples/testing/src/testing/jasmine-matchers.ts b/adev/src/content/examples/testing/src/testing/jasmine-matchers.ts deleted file mode 100644 index c816509e492..00000000000 --- a/adev/src/content/examples/testing/src/testing/jasmine-matchers.ts +++ /dev/null @@ -1,51 +0,0 @@ -/// - -//// Jasmine Custom Matchers //// -// Be sure to extend jasmine-matchers.d.ts when adding matchers - -export function addMatchers(): void { - jasmine.addMatchers({ - toHaveText, - }); -} - -function toHaveText(): jasmine.CustomMatcher { - return { - compare: ( - actual: any, - expectedText: string, - expectationFailOutput?: any, - ): jasmine.CustomMatcherResult => { - const actualText = elementText(actual); - const pass = actualText.indexOf(expectedText) > -1; - const message = pass ? '' : composeMessage(); - return {pass, message}; - - function composeMessage() { - const a = actualText.length < 100 ? actualText : actualText.slice(0, 100) + '...'; - const efo = expectationFailOutput ? ` '${expectationFailOutput}'` : ''; - return `Expected element to have text content '${expectedText}' instead of '${a}'${efo}`; - } - }, - }; -} - -function elementText(n: any): string { - if (n instanceof Array) { - return n.map(elementText).join(''); - } - - if (n.nodeType === Node.COMMENT_NODE) { - return ''; - } - - if (n.nodeType === Node.ELEMENT_NODE && n.hasChildNodes()) { - return elementText(Array.prototype.slice.call(n.childNodes)); - } - - if (n.nativeElement) { - n = n.nativeElement; - } - - return n.textContent; -} diff --git a/adev/src/content/examples/testing/stackblitz.json b/adev/src/content/examples/testing/stackblitz.json deleted file mode 100644 index c8d925daaa2..00000000000 --- a/adev/src/content/examples/testing/stackblitz.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "description": "Heroes Test App", - "files": [ - "src/index.html", - "src/main.ts", - "src/test.ts", - "src/styles.css", - "src/test.css", - "e2e/src/**/*.ts", - "src/app/**/*.css", - "src/app/**/*.html", - "src/app/**/*.ts", - "src/app/**/*.spec.ts", - "src/testing/**/*.ts", - "src/expected.ts", - "karma.conf.js" - ], - "tags": [ - "testing" - ], - "devDependencies": [ - "jasmine-core", - "jasmine-marbles" - ] -} diff --git a/adev/src/content/guide/routing/router-reference.md b/adev/src/content/guide/routing/router-reference.md index 29849e977a2..9df1c923412 100644 --- a/adev/src/content/guide/routing/router-reference.md +++ b/adev/src/content/guide/routing/router-reference.md @@ -64,7 +64,9 @@ The browser uses the `` value to prefix relative URLs when referencin Add the `` element just after the `` tag. If the `app` folder is the application root, as it is for this application, set the `href` value in `index.html` as shown here. - +```html + +``` ### HTML5 URLs and the `` diff --git a/adev/src/content/guide/routing/router-tutorial.md b/adev/src/content/guide/routing/router-tutorial.md deleted file mode 100644 index d816c1e74a0..00000000000 --- a/adev/src/content/guide/routing/router-tutorial.md +++ /dev/null @@ -1,276 +0,0 @@ -# Using Angular routes in a single-page application - -This tutorial describes how to build a single-page application, SPA that uses multiple Angular routes. - -In a Single Page Application \(SPA\), all of your application's functions exist in a single HTML page. -As users access your application's features, the browser needs to render only the parts that matter to the user, instead of loading a new page. -This pattern can significantly improve your application's user experience. - -To define how users navigate through your application, you use routes. -Add routes to define how users navigate from one part of your application to another. -You can also configure routes to guard against unexpected or unauthorized behavior. - -## Objectives - -- Organize a sample application's features into modules. -- Define how to navigate to a component. -- Pass information to a component using a parameter. -- Structure routes by nesting several routes. -- Check whether users can access a route. -- Control whether the application can discard unsaved changes. -- Improve performance by pre-fetching route data and lazy loading feature modules. -- Require specific criteria to load components. - -## Create a sample application - -Using the Angular CLI, create a new application, _angular-router-sample_. -This application will have two components: _crisis-list_ and _heroes-list_. - -1. Create a new Angular project, _angular-router-sample_. - - ```shell - ng new angular-router-sample - ``` - - When prompted with `Would you like to add Angular routing?`, select `N`. - - When prompted with `Which stylesheet format would you like to use?`, select `CSS`. - - After a few moments, a new project, `angular-router-sample`, is ready. - -1. From your terminal, navigate to the `angular-router-sample` directory. -1. Create a component, _crisis-list_. - -```shell -ng generate component crisis-list -``` - -1. In your code editor, locate the file, `crisis-list.component.html` and replace the placeholder content with the following HTML. - - - -1. Create a second component, _heroes-list_. - -```shell -ng generate component heroes-list -``` - -1. In your code editor, locate the file, `heroes-list.component.html` and replace the placeholder content with the following HTML. - - - -1. In your code editor, open the file, `app.component.html` and replace its contents with the following HTML. - - - -1. Verify that your new application runs as expected by running the `ng serve` command. - -```shell -ng serve -``` - -1. Open a browser to `http://localhost:4200`. - - You should see a single web page, consisting of a title and the HTML of your two components. - -## Define your routes - -In this section, you'll define two routes: - -- The route `/crisis-center` opens the `crisis-center` component. -- The route `/heroes-list` opens the `heroes-list` component. - -A route definition is a JavaScript object. -Each route typically has two properties. -The first property, `path`, is a string that specifies the URL path for the route. -The second property, `component`, is a string that specifies what component your application should display for that path. - -1. From your code editor, create and open the `app.routes.ts` file. -1. Create and export a routes list for your application: - - ```ts - import {Routes} from '@angular/router'; - - export const routes = []; - ``` - -1. Add two routes for your first two components: - - ```ts - {path: 'crisis-list', component: CrisisListComponent}, - {path: 'heroes-list', component: HeroesListComponent}, - ``` - -This routes list is an array of JavaScript objects, with each object defining the properties of a route. - -## Import `provideRouter` from `@angular/router` - -Routing lets you display specific views of your application depending on the URL path. -To add this functionality to your sample application, you need to update the `app.config.ts` file to use the router providers function, `provideRouter`. -You import this provider function from `@angular/router`. - -1. From your code editor, open the `app.config.ts` file. -1. Add the following import statements: - - ```ts - import {provideRouter} from '@angular/router'; - import {routes} from './app.routes'; - ``` - -1. Update the providers in the `appConfig`: - - ```ts - providers: [provideRouter(routes)]; - ``` - -For `NgModule` based applications, put the `provideRouter` in the `providers` list of the `AppModule`, or whichever module is passed to `bootstrapModule` in the application. - -## Update your component with `router-outlet` - -At this point, you have defined two routes for your application. -However, your application still has both the `crisis-list` and `heroes-list` components hard-coded in your `app.component.html` template. -For your routes to work, you need to update your template to dynamically load a component based on the URL path. - -To implement this functionality, you add the `router-outlet` directive to your template file. - -1. From your code editor, open the `app.component.html` file. -1. Delete the following lines. - - - -1. Add the `router-outlet` directive. - - - -1. Add `RouterOutlet` to the imports of the `AppComponent` in `app.component.ts` - - ```ts - imports: [RouterOutlet], - ``` - -View your updated application in your browser. -You should see only the application title. -To view the `crisis-list` component, add `crisis-list` to the end of the path in your browser's address bar. -For example: - - -http://localhost:4200/crisis-list - - -Notice that the `crisis-list` component displays. -Angular is using the route you defined to dynamically load the component. -You can load the `heroes-list` component the same way: - - -http://localhost:4200/heroes-list - - -## Control navigation with UI elements - -Currently, your application supports two routes. -However, the only way to use those routes is for the user to manually type the path in the browser's address bar. -In this section, you'll add two links that users can click to navigate between the `heroes-list` and `crisis-list` components. -You'll also add some CSS styles. -While these styles are not required, they make it easier to identify the link for the currently-displayed component. -You'll add that functionality in the next section. - -1. Open the `app.component.html` file and add the following HTML below the title. - - - - This HTML uses an Angular directive, `routerLink`. - This directive connects the routes you defined to your template files. - -1. Add the `RouterLink` directive to the imports list of `AppComponent` in `app.component.ts`. - -1. Open the `app.component.css` file and add the following styles. - - - -If you view your application in the browser, you should see these two links. -When you click on a link, the corresponding component appears. - -## Identify the active route - -While users can navigate your application using the links you added in the previous section, they don't have a straightforward way to identify what the active route is. -Add this functionality using Angular's `routerLinkActive` directive. - -1. From your code editor, open the `app.component.html` file. -1. Update the anchor tags to include the `routerLinkActive` directive. - - - -1. Add the `RouterLinkActive` directive to the `imports` list of `AppComponent` in `app.component.ts`. - -View your application again. -As you click one of the buttons, the style for that button updates automatically, identifying the active component to the user. -By adding the `routerLinkActive` directive, you inform your application to apply a specific CSS class to the active route. -In this tutorial, that CSS class is `activebutton`, but you could use any class that you want. - -Note that we are also specifying a value for the `routerLinkActive`'s `ariaCurrentWhenActive`. This makes sure that visually impaired users (which may not perceive the different styling being applied) can also identify the active button. For more information see the Accessibility Best Practices [Active links identification section](/best-practices/a11y#active-links-identification). - -## Adding a redirect - -In this step of the tutorial, you add a route that redirects the user to display the `/heroes-list` component. - -1. From your code editor, open the `app.routes.ts` file. -1. Update the `routes` section as follows. - - ```ts - {path: '', redirectTo: '/heroes-list', pathMatch: 'full'}, - ``` - - Notice that this new route uses an empty string as its path. - In addition, it replaces the `component` property with two new ones: - - | Properties | Details | - | :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | - | `redirectTo` | This property instructs Angular to redirect from an empty path to the `heroes-list` path. | - | `pathMatch` | This property instructs Angular on how much of the URL to match. For this tutorial, you should set this property to `full`. This strategy is recommended when you have an empty string for a path. For more information about this property, see the [Route API documentation](api/router/Route). | - -Now when you open your application, it displays the `heroes-list` component by default. - -## Adding a 404 page - -It is possible for a user to try to access a route that you have not defined. -To account for this behavior, the best practice is to display a 404 page. -In this section, you'll create a 404 page and update your route configuration to show that page for any unspecified routes. - -1. From the terminal, create a new component, `PageNotFound`. - -```shell -ng generate component page-not-found -``` - -1. From your code editor, open the `page-not-found.component.html` file and replace its contents with the following HTML. - - - -1. Open the `app.routes.ts` file and add the following route to the routes list: - - ```ts - {path: '**', component: PageNotFoundComponent} - ``` - - The new route uses a path, `**`. - This path is how Angular identifies a wildcard route. - Any route that does not match an existing route in your configuration will use this route. - -IMPORTANT: Notice that the wildcard route is placed at the end of the array. -The order of your routes is important, as Angular applies routes in order and uses the first match it finds. - -Try navigating to a non-existing route on your application, such as `http://localhost:4200/powers`. -This route doesn't match anything defined in your `app.routes.ts` file. -However, because you defined a wildcard route, the application automatically displays your `PageNotFound` component. - -## Next steps - -At this point, you have a basic application that uses Angular's routing feature to change what components the user can see based on the URL address. -You have extended these features to include a redirect, as well as a wildcard route to display a custom 404 page. - -For more information about routing, see the following topics: - - - - - diff --git a/adev/src/context/llms-list.md b/adev/src/context/llms-list.md index ef49ca28e4d..a379f90ffa3 100644 --- a/adev/src/context/llms-list.md +++ b/adev/src/context/llms-list.md @@ -74,7 +74,6 @@ adev/src/content/guide/routing/show-routes-with-outlets.md adev/src/content/guide/routing/navigate-to-routes.md adev/src/content/guide/routing/read-route-state.md adev/src/content/guide/routing/common-router-tasks.md -adev/src/content/guide/routing/router-tutorial.md adev/src/content/guide/routing/routing-with-urlmatcher.md ## SSR diff --git a/packages.bzl b/packages.bzl index 8dc4f0de752..15d70cff5d7 100644 --- a/packages.bzl +++ b/packages.bzl @@ -72,23 +72,6 @@ DOCS_ENTRYPOINTS = [ "core/src/util", "core/testing", "elements", - "examples/common", - "examples/core", - "examples/core/di/ts/forward_ref", - "examples/core/testing/ts", - "examples/forms", - "examples/platform-browser", - "examples/router/activated-route", - "examples/router/testing", - "examples/router", - "examples/service-worker/push", - "examples/service-worker/registration-options", - "examples/test-utils", - "examples/testing", - "examples/upgrade/static/ts/full", - "examples/upgrade/static/ts/lite", - "examples/upgrade/static/ts/lite-multi", - "examples/upgrade/static/ts/lite-multi-shared", "forms", "localize", "localize/init", @@ -107,8 +90,4 @@ DOCS_ENTRYPOINTS = [ "router/testing", "router/upgrade", "service-worker", - "upgrade", - "upgrade/src/common", - "upgrade/static", - "upgrade/static/testing", ] diff --git a/packages/examples/injection-token/src/main.ts b/packages/examples/injection-token/src/main.ts index 7740aac8014..0041028d6f2 100644 --- a/packages/examples/injection-token/src/main.ts +++ b/packages/examples/injection-token/src/main.ts @@ -6,7 +6,6 @@ * found in the LICENSE file at https://angular.dev/license */ -// TODO: Add unit tests for this file. /* eslint-disable @angular-eslint/no-output-native */ // #docregion import {Injector, InjectionToken} from '@angular/core'; diff --git a/packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts b/packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts deleted file mode 100644 index 2c0498748e7..00000000000 --- a/packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @license - * Copyright Google LLC 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.dev/license - */ - -import {Component, NgModule} from '@angular/core'; -import {BrowserModule, platformBrowser} from '@angular/platform-browser'; - -@Component({ - selector: 'my-component', - template: 'text', - standalone: false, -}) -class MyAppComponent {} -@NgModule({imports: [BrowserModule], bootstrap: [MyAppComponent]}) -class AppModule {} -platformBrowser().bootstrapModule(AppModule);