Compare commits

...

31 Commits

Author SHA1 Message Date
Dylan Hunn ee5b1cf076 release: cut the v16.2.11 release 2023-10-25 14:26:10 -07:00
Andrew Scott b79b4aca91 fix(router): RouterTestingHarness should throw if a component is expected but navigation fails (#52357)
The `RouterTestingHarness` should throw an error if the call to `navigateByUrl`
expects a component to be activated but the navigation failed.

fixes #52344

PR Close #52357
2023-10-25 11:04:24 -07:00
AleksanderBodurri 019a0f4c22 fix(core): load global utils before creating platform injector in the standalone case (#52365)
This is needed so that the providers configured on platform creation are picked up by the injector profiler.

PR Close #52365
2023-10-25 10:51:21 -07:00
AleksanderBodurri 78533324dc fix(core): get root and platform injector providers in special cases (#52365)
Previously, because the platform injector does not have a provider container, this API would fail. Now, we account for this case specifically by returning the found providers immediately, without trying to calculate their importpaths.

Also previously, in the case where a boostrapped standalone component did not import any feature modules, the environment injector connected to that bootstrapped component would be the root injector configured by `bootstrapApplication`. This injector is configured through a `providers` array instead of an `imports` array, and also does not have a provider container. Similarly to the platform case, we account this for this by returning the found providers immediately if there is no provider container for our standalone component.

PR Close #52365
2023-10-25 10:51:21 -07:00
AleksanderBodurri 54ea3b65c3 fix(core): emit provider configured event when a service is configured with providedIn (#52365)
Previously this case was missed by the default framework injector profiler. Now in ngDevMode this event emits correctly when a service is configured with `providedIn`. This includes the case where injection tokens are configured with a `providedIn`.

This commit also includes unit tests for this new case in the injector profiler.

PR Close #52365
2023-10-25 10:51:21 -07:00
Alvaro Junqueira 372dd0ab7d docs: the Component import is not being used (#52323)
PR Close #52323
2023-10-25 09:35:22 -07:00
Naaajii 3afee8716d docs(docs-infra): fix codeblock snippet for APP_INITIALIZER (#52354)
fixes broken code snippet for standalone application using APP_INITIALIZER

PR Close #52354
2023-10-25 09:34:47 -07:00
Matthieu Riegler 56c93d02b5 docs(core): fix the language code (#52352)
PR Close #52352
2023-10-25 09:32:18 -07:00
Angular Robot fd88d6a7aa docs: update Angular CLI help [16.2.x] (#52335)
Updated Angular CLI help contents.

PR Close #52335
2023-10-24 09:30:17 -07:00
cexbrayat 36873596be docs: remove test.ts file in aio (#52327)
Same as 7ba5dc87ed, but for aio
This file is not necessary since CLI v15+

PR Close #52327
2023-10-24 09:23:00 -07:00
Andrew Scott 1693846a9b test(core): fix test observing broken OnPush checkNoChanges (#52337)
The test is actually observing that OnPush results in a view not being checked
when checkNoChanges runs.

PR Close #52337
2023-10-24 09:21:52 -07:00
Emma Twersky 8239a8f19e docs: add event banner (#52334)
PR Close #52334
2023-10-23 13:40:00 -07:00
Angular Robot fbf49b5e9c build: update all non-major dependencies (#52259)
See associated pull request for more information.

PR Close #52259
2023-10-19 09:25:42 -07:00
Pawel Kozlowski bf70bf6d4f release: cut the v16.2.10 release 2023-10-18 18:46:27 +02:00
vivekkoya b4c4b42222 docs: Update BAZEL.md with correct bazelrc documentation link (#52090)
PR Close #52090
2023-10-18 18:15:02 +02:00
Quentin 2643d0a45d docs: fix typo (#52258)
Fix typo in aio/content/errors/NG05104.md file

PR Close #52258
2023-10-18 18:13:43 +02:00
Angular Robot 55e41d876d build: update scorecard action dependencies (#52126)
See associated pull request for more information.

PR Close #52126
2023-10-18 17:45:29 +02:00
Angular Robot 1a09d3e44b build: update io_bazel_rules_sass digest to 425ecaf (#52173)
See associated pull request for more information.

PR Close #52173
2023-10-18 17:37:08 +02:00
Pawel Kozlowski 2820425e38 build: update babel dependencies to v7.23.2 (#52255)
16.2.x version of #52236

PR Close #52255
2023-10-18 15:56:47 +02:00
Quentin 06ce49aeeb docs: fix typo (#52247)
Fix word: corresponding

PR Close #52247
2023-10-18 11:29:38 +02:00
Quentin d6070afdc2 docs: fix typo (#52219)
Fix word: incompatibilities

PR Close #52219
2023-10-16 18:30:45 +02:00
Andrew Miller 37e7f2d933 docs(language-service): add neovim setup to angular language service docs (#52212)
PR Close #52212
2023-10-16 18:19:11 +02:00
Osama Heykal 81018d7562 docs: add missing next steps section (#52220)
Added missing 'next steps' section in the tutorial.

PR Close #52220
2023-10-16 16:27:14 +02:00
thomas 6997c525b5 docs: add thomas laforge to GDE resources and add angularchallenges to resources (#52075)
PR Close #52075
2023-10-16 11:12:59 +02:00
Paul Gschwendtner d75eaa7375 refactor(core): remove unused helper for setting LView for reactive consumer (#52192)
This code path is never hit because the assignment of the lview happens
in `commitLViewConsumerIfHasProducers`.

PR Close #52192
2023-10-13 14:08:34 +02:00
Miroslav Foltýn 630e906747 docs(router): add clarification for behavior of paramsInheritanceStrategy: 'emptyOnly' (#52170)
Follows up to the https://github.com/angular/angular/issues/52108 which was opened due to the confusion surrounding paramsInheritanceStrategy: 'emptyOnly'.

PR Close #52170
2023-10-13 11:14:22 +02:00
Nicolas Frizzarin 25788b2919 docs: add Nicolas Frizzarin to GDE resources (#52003)
This PR add Nicolas Frizzarin to the GDE resources

docs: fix typo on description

PR Close #52003
2023-10-12 17:44:47 +02:00
Pawel Kozlowski f52eee8eb2 Revert "refactor(compiler-cli): remove MethodIdentifier type (#49611)" (#52174)
This reverts commit c2b1a242e8.

PR Close #52174
2023-10-12 12:35:49 +02:00
Matthieu Riegler 5f2a33ac58 refactor(compiler-cli): remove MethodIdentifier type (#49611)
`MethodIdentifier` is unused as is `IdentifierKind.Method`. They both can be removed.

PR Close #49611
2023-10-11 12:34:50 -07:00
Angular Robot 753792856d docs: update Angular CLI help [16.2.x] (#52169)
Updated Angular CLI help contents.

PR Close #52169
2023-10-11 12:33:29 -07:00
Angular Robot c8f87c8eff docs: update events (#52053)
Generated `events.json` with the latest events retrieved from the Firebase DB.

PR Close #52053
2023-10-11 12:18:05 -07:00
48 changed files with 812 additions and 790 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
(github.event.action == 'labeled' && github.event.label.name == 'aio: preview') ||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'aio: preview'))
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: ./.github/actions/yarn-install
- uses: angular/dev-infra/github-actions/bazel/configure-remote@0109d498b0f6aae418ed4924a5e5c65695f0ac61
@@ -13,7 +13,7 @@ jobs:
assistant_to_the_branch_manager:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- uses: angular/dev-infra/github-actions/branch-manager@0109d498b0f6aae418ed4924a5e5c65695f0ac61
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
- uses: alessbell/pull-request-comment-branch@aad01d65d6982b8eacabed5e9a684cd8ceb98da6 # v1.1
id: comment-branch
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# Specify repository as the PR branch might be from a fork.
repository: ${{steps.comment-branch.outputs.head_owner}}/${{steps.comment-branch.outputs.head_repo}}
+4 -4
View File
@@ -12,14 +12,14 @@ jobs:
labels:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: angular/dev-infra/github-actions/commit-message-based-labels@9b1adb2ad5a049ea9985734f197dca43dd4d3f1b
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: angular/dev-infra/github-actions/commit-message-based-labels@031962443584a0ac5cbd9d1c1b78b241453e4702
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
post_approval_changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: angular/dev-infra/github-actions/post-approval-changes@9b1adb2ad5a049ea9985734f197dca43dd4d3f1b
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: angular/dev-infra/github-actions/post-approval-changes@031962443584a0ac5cbd9d1c1b78b241453e4702
with:
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
+2 -2
View File
@@ -13,8 +13,8 @@ jobs:
statuses: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: angular/dev-infra/github-actions/google-internal-tests@9b1adb2ad5a049ea9985734f197dca43dd4d3f1b
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: angular/dev-infra/github-actions/google-internal-tests@031962443584a0ac5cbd9d1c1b78b241453e4702
with:
run-tests-guide-url: http://go/angular-g3sync-start
github-token: ${{ secrets.GITHUB_TOKEN }}
+3 -3
View File
@@ -25,12 +25,12 @@ jobs:
steps:
- name: 'Checkout code'
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: 'Run analysis'
uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # v2.3.0
with:
results_file: results.sarif
results_format: sarif
@@ -47,6 +47,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
uses: github/codeql-action/upload-sarif@0116bc2df50751f9724a2e35ef1f24d22f90e4e1 # v2.22.3
with:
sarif_file: results.sarif
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# Setting `persist-credentials: false` prevents the github-action account from being the
# account that is attempted to be used for authentication, instead the remote is set to
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# Setting `persist-credentials: false` prevents the github-action account from being the
# account that is attempted to be used for authentication, instead the remote is set to
+20
View File
@@ -1,3 +1,23 @@
<a name="16.2.11"></a>
# 16.2.11 (2023-10-25)
### core
| Commit | Type | Description |
| -- | -- | -- |
| [54ea3b65c3](https://github.com/angular/angular/commit/54ea3b65c35254b220054541f2fbc52384486156) | fix | emit provider configured event when a service is configured with `providedIn` ([#52365](https://github.com/angular/angular/pull/52365)) |
| [78533324dc](https://github.com/angular/angular/commit/78533324dcda2e884fbe489aaa6b37fa9a6fadbc) | fix | get root and platform injector providers in special cases ([#52365](https://github.com/angular/angular/pull/52365)) |
| [019a0f4c22](https://github.com/angular/angular/commit/019a0f4c225d6bb6f741b37bf272b62899fe1f69) | fix | load global utils before creating platform injector in the standalone case ([#52365](https://github.com/angular/angular/pull/52365)) |
### router
| Commit | Type | Description |
| -- | -- | -- |
| [b79b4aca91](https://github.com/angular/angular/commit/b79b4aca914aefda1605fc8d069ac8d84283f1b3) | fix | `RouterTestingHarness` should throw if a component is expected but navigation fails ([#52357](https://github.com/angular/angular/pull/52357)) |
<!-- CHANGELOG SPLIT MARKER -->
<a name="16.2.10"></a>
# 16.2.10 (2023-10-18)
<!-- CHANGELOG SPLIT MARKER -->
<a name="16.2.9"></a>
# 16.2.9 (2023-10-11)
### forms
+3 -3
View File
@@ -194,10 +194,10 @@ cldr_xml_data_repository(
# sass rules
http_archive(
name = "io_bazel_rules_sass",
sha256 = "923b2c470e981b6e96b17e5b9ec7a6141eab808d52ebffdbd94695f5a42a5184",
strip_prefix = "rules_sass-9a327e5badc3fdd5141479410675c356133e1e41",
sha256 = "7a90567717c3417a23ff4b21963a698a6e9aa669ac9e682121ea33f218a2816a",
strip_prefix = "rules_sass-425ecafa8268bc013d684216363fe75bc802323e",
urls = [
"https://github.com/bazelbuild/rules_sass/archive/9a327e5badc3fdd5141479410675c356133e1e41.zip",
"https://github.com/bazelbuild/rules_sass/archive/425ecafa8268bc013d684216363fe75bc802323e.zip",
],
)
-1
View File
@@ -215,7 +215,6 @@
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"webWorkerTsConfig": "tsconfig.worker.json",
+1 -1
View File
@@ -1,4 +1,4 @@
{
"branchName": "refs/heads/16.2.x",
"sha": "99ff60cdfe5ca0a8b9ad6bf77ac60a929a27de38"
"sha": "36adedc25c729e418ce3984b9f94bc32a1ff8a38"
}
+1 -1
View File
@@ -160,7 +160,7 @@
{
"name": "output-path",
"type": "string",
"description": "The full path for the new output directory, relative to the current workspace.\nBy default, writes output to a folder named dist/ in the current project."
"description": "The full path for the new output directory, relative to the current workspace."
},
{
"name": "poll",
+3 -3
View File
@@ -31,7 +31,7 @@
{
"name": "from",
"type": "string",
"description": "Version from which to migrate from. Only available with a single package being updated, and only with 'migrate-only'."
"description": "Version from which to migrate from. Only available when a single package is updated, and only with 'migrate-only'."
},
{
"name": "help",
@@ -46,7 +46,7 @@
{
"name": "name",
"type": "string",
"description": "The name of the migration to run. Only available with a single package being updated, and only with 'migrate-only' option."
"description": "The name of the migration to run. Only available when a single package is updated."
},
{
"name": "next",
@@ -71,7 +71,7 @@
{
"name": "to",
"type": "string",
"description": "Version up to which to apply migrations. Only available with a single package being updated, and only with 'migrate-only' option. Requires 'from' to be specified. Default to the installed version detected."
"description": "Version up to which to apply migrations. Only available when a single package is updated, and only with 'migrate-only' option. Requires 'from' to be specified. Default to the installed version detected."
},
{
"name": "verbose",
+2 -2
View File
@@ -3,9 +3,9 @@
@shortDescription Root element was not found during bootstrap.
@description
Boostraped components are defined in the `bootstrap` property of an `@NgModule` decorator or as the first parameter of `boopstrapApplication` for standalone components.
Bootstrapped components are defined in the `bootstrap` property of an `@NgModule` decorator or as the first parameter of `bootstrapApplication` for standalone components.
This error happens when Angular tries to boostrap one of these components but cannot find its corresponing node in the DOM.
This error happens when Angular tries to bootstrap one of these components but cannot find its corresponding node in the DOM.
@debugging
+1 -1
View File
@@ -166,7 +166,7 @@ Avoiding the use of modules with non-local side effects (outside of polyfills) i
### Long build times when using Sass combined with pnpm or yarn PnP
Applications may have increased build times due to the need to workaround Sass resolution incompabilities when using either the pnpm or Yarn PnP package managers.
Applications may have increased build times due to the need to workaround Sass resolution incompatibilities when using either the pnpm or Yarn PnP package managers.
Sass files with `@import` or `@use` directives referencing a package when using either of these package managers can trigger the performance problem.
An alternative workaround that alleviates the build time increases is in development and will be available before the build system moves to stable status.
+26 -1
View File
@@ -141,6 +141,31 @@ This lets the Angular Language Service provide diagnostics and completions in `.
Either directly install the "Eclipse IDE for Web and JavaScript developers" package which comes with the Angular Language Server included, or from other Eclipse IDE packages, use Help &gt; Eclipse Marketplace to find and install [Eclipse Wild Web Developer](https://marketplace.eclipse.org/content/wild-web-developer-html-css-javascript-typescript-nodejs-angular-json-yaml-kubernetes-xml).
### Neovim
1. [Setup coc.nvim](https://github.com/neoclide/coc.nvim)
2. [Configure the Angular Language Service](https://github.com/iamcco/coc-angular/issues/70#issuecomment-1616340751)
```
{
"languageserver": {
"angular": {
"command": "ngserver",
"args": [
"--stdio",
"--tsProbeLocations",
"/usr/local/lib/node_modules/typescript/lib",
"--ngProbeLocations",
"/usr/local/lib/node_modules/@angular/language-server/bin"
],
"filetypes": ["ts", "typescript", "html"],
"trace.server.verbosity": "verbose"
}
}
}
```
## How the Language Service works
When you use an editor with a language service, the editor starts a separate language-service process and communicates with it through an [RPC](https://en.wikipedia.org/wiki/Remote_procedure_call), using the [Language Server Protocol](https://microsoft.github.io/language-server-protocol).
@@ -168,4 +193,4 @@ The Angular Language Services then looks at `data.---` within its context, asks
<!-- end links -->
@reviewed 2022-02-28
@reviewed 2022-02-28
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 KiB

+16
View File
@@ -779,6 +779,14 @@
"bio": "I'm Software Senior Developer. With more than 8 years of professional software development experience focusing in Web Development, Tech Management and skills for problem-solving. I'm passionate about sharing my knowledge with the community about Web Development and I do this through code contributions, videos, conferences, articles and, creating online content therefore I got recognized by Google like an GDE (Google Developer Expert) in Angular and by Microsoft like an MVP (Most Value Professional).",
"groups": ["GDE"]
},
"nicoss54": {
"name": "Nicolas Frizzarin",
"picture": "nicolasfrizzarin.jpeg",
"twitter": "Nicooss54",
"website": "https://dev.to/nicoss54",
"bio": "Google Developer Expert in Web Technologies and Angular and OpenJs Foundation Member, Nicolas is a FontEnd specialist and user Interface Designer from Metz, France. He works as a Developer Advocate and Senior Staff Engineer at Sfeir Luxembourg. His daily mission is to help teams to make robust, powerful and beautiful web applications. Besides that, Nicolas is a speaker, and likes to contribute to the community by giving talks, trainings, writing articles or participating in open source projects.",
"groups": ["GDE"]
},
"nirkaufman": {
"name": "Nir Kaufman",
"picture": "nirkaufman.jpg",
@@ -987,6 +995,14 @@
"bio": "Owner and trainer at Ultimate Angular. Lives in England, UK. Has a love for teaching, OSS and speaking at conferences. Google Developer Expert for Web Technologies and Angular.",
"groups": ["GDE"]
},
"thomaslaforge": {
"name": "Thomas Laforge",
"picture": "thomaslaforge.png",
"twitter": "laforge_toma",
"website": "https://thomaslaforge.dev/home",
"bio": "Thomas is a contractor with a strong passion for frontend development, specifically focusing on Angular. He is the creator and maintainer of Angular Challenges, a platform that gathers multiple challenges to help you improve your skills in Angular.",
"groups": ["GDE"]
},
"tomastrajan": {
"name": "Tomas Trajan",
"picture": "tomastrajan.jpg",
+24
View File
@@ -1217,6 +1217,18 @@
},
"name": "GraphQL SF"
},
{
"date": {
"start": "2023-09-26"
},
"name": "IJS New York"
},
{
"date": {
"start": "2023-10-03"
},
"name": "Angular London Meetup"
},
{
"date": {
"start": "2023-10-05"
@@ -1229,6 +1241,18 @@
},
"name": "All Things Open"
},
{
"date": {
"start": "2023-10-26"
},
"name": "Connect.tech"
},
{
"date": {
"start": "2023-10-27"
},
"name": "REFACTR.tech"
},
{
"date": {
"start": "2023-11-08"
+7 -2
View File
@@ -665,9 +665,9 @@
"logo": ""
},
"butter-cms": {
"title":"How to integrate ButterCMS into Angular 2+ App",
"title": "How to integrate ButterCMS into Angular 2+ App",
"desc": "Integrate a Headless CMS into your Angular App, create blog posts and pages",
"url":"https://medium.com/orlyknop/how-to-integrate-buttercms-into-angular-2-app-a1baaa51402",
"url": "https://medium.com/orlyknop/how-to-integrate-buttercms-into-angular-2-app-a1baaa51402",
"logo": ""
},
"angular-projects": {
@@ -822,6 +822,11 @@
"desc": "Want to learn #Angular, but not sure where to start? Check out this in-depth “Angular for Beginners Course“ created by Angular #GDE @SantoshYadavDev.",
"title": "Angular for Beginners Course",
"url": "https://youtu.be/3qBXWUpoPHo"
},
"angular-challenges": {
"desc": "Learn angular its ecosystem and open-source by practising on real-life examples.",
"title": "Angular Challenges",
"url": "https://angular-challenges.vercel.app/"
}
}
},
@@ -102,4 +102,8 @@ Here's the application in action:
</div>
## Next steps
* [Create a new project](tutorial/tour-of-heroes/toh-pt0)
@reviewed 2022-05-16
+2 -2
View File
@@ -110,7 +110,7 @@
"dgeni": "^0.4.14",
"dgeni-packages": "^0.30.0",
"entities": "^4.0.0",
"eslint": "8.50.0",
"eslint": "8.51.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-jasmine": "4.1.3",
"eslint-plugin-jsdoc": "46.8.2",
@@ -144,7 +144,7 @@
"lunr": "^2.3.9",
"npm-run-all": "^4.1.5",
"protractor": "~7.0.0",
"puppeteer-core": "21.3.6",
"puppeteer-core": "21.3.8",
"rehype-slug": "^4.0.1",
"remark": "^12.0.0",
"remark-html": "^13.0.0",
+4 -4
View File
@@ -11,11 +11,11 @@
<header>
<mat-toolbar #appToolbar color="primary" class="app-toolbar no-print" [class.transitioning]="isTransitioning">
<mat-toolbar-row class="notification-container">
<aio-notification notificationId="survey-august-2023" expirationDate="2023-10-08" [dismissOnContentClick]="true" (dismissed)="notificationDismissed()">
<a href="https://goo.gle/angular-devsat-q3-2023">
<aio-notification notificationId="angular-event" expirationDate="2023-11-08" [dismissOnContentClick]="true" (dismissed)="notificationDismissed()">
<a href="https://goo.gle/angular-event">
<mat-icon class="icon" svgIcon="insert_comment" aria-label="Announcement"></mat-icon>
<span class="message">Help Angular by taking a <strong>quick survey</strong>!</span>
<span class="action-button">Go to survey</span>
<span class="message">We have a lot to share, tune in on November 6th!</span>
<span class="action-button">Join us live</span>
</a>
</aio-notification>
</mat-toolbar-row>
-14
View File
@@ -1,14 +0,0 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
+2 -2
View File
@@ -57,8 +57,8 @@
"@types/angular-resource": "^1.5.17",
"@types/angular-route": "^1.7.2",
"@types/express": "^4.17.13",
"@types/jasmine": "~4.3.0",
"@types/jquery": "3.5.20",
"@types/jasmine": "~5.1.0",
"@types/jquery": "3.5.23",
"@types/node": "^16.11.35",
"canonical-path": "1.0.0",
"concurrently": "^8.0.0",
+8 -8
View File
@@ -1844,15 +1844,15 @@
dependencies:
"@types/node" "*"
"@types/jasmine@~4.3.0":
version "4.3.5"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-4.3.5.tgz#05c6b401c041b8a4f3303c3a58c9580aac2b898c"
integrity sha512-9YHUdvuNDDRJYXZwHqSsO72Ok0vmqoJbNn73ttyITQp/VA60SarnZ+MPLD37rJAhVoKp+9BWOvJP5tHIRfZylQ==
"@types/jasmine@~5.1.0":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-5.1.1.tgz#7d2a2a983e1e822858ea9e30d90e11a3fe408fc0"
integrity sha512-qL4GoZHHJl1JQ0vK31OtXMfkfGxYJnysmYz9kk0E8j5W96ThKykBF90uD3PcVmQUAzulbsaus2eFiBhCH5itfw==
"@types/jquery@3.5.20":
version "3.5.20"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.20.tgz#a23eece847591c7aaa47c52d6910052af473df4e"
integrity sha512-UI+EGhgYD4LdSZ8gaiziFqXYIIB38VQSDsnAs8jL/div7FGrzrShx4HKCykVzk3tPfiIlusdNP9Wi3G60LCF2Q==
"@types/jquery@3.5.23":
version "3.5.23"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.23.tgz#f99f08533ad5a5c4cb1d0dc131ecf5e2a73eb182"
integrity sha512-LwtD05mlY8iPF/1aB8dOZaYhRDothbHA7csnAxhyqMnQxj90Fo3J4nPhmHiA0OMTwHhjwZdE1Lpd6UK+b+C6Bw==
dependencies:
"@types/sizzle" "*"
-3
View File
@@ -7,9 +7,6 @@
"node"
]
},
"files": [
"src/test.ts",
],
"include": [
"src/testing/**/*.ts",
"src/**/*.spec.ts",
+18 -18
View File
@@ -2038,10 +2038,10 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@eslint/js@8.50.0":
version "8.50.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.50.0.tgz#9e93b850f0f3fa35f5fa59adfd03adae8488e484"
integrity sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==
"@eslint/js@8.51.0":
version "8.51.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.51.0.tgz#6d419c240cfb2b66da37df230f7e7eef801c32fa"
integrity sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==
"@google-cloud/paginator@^4.0.0":
version "4.0.1"
@@ -5287,10 +5287,10 @@ chrome-trace-event@^1.0.2:
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
chromium-bidi@0.4.28:
version "0.4.28"
resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.28.tgz#05befef4f3f19003198237245780d1c60e6f4dbc"
integrity sha512-2HZ74QlAApJrEwcGlU/sUu0s4VS+FI3CJ09Toc9aE9VemMyhHZXeaROQgJKNRaYMUTUx6qIv1cLBs3F+vfgjSw==
chromium-bidi@0.4.31:
version "0.4.31"
resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.31.tgz#a28c4329880706e61ff07ed49aed22e6d04e17d1"
integrity sha512-OtvEg2JMRQrHsmLx4FV3u1Hf9waYxB5PmL+yM0HkFpc9H2x3TMbUqS+GP2/fC4399hzOO+EQF8uVU43By9ILag==
dependencies:
mitt "3.0.1"
urlpattern-polyfill "9.0.0"
@@ -6946,15 +6946,15 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint@8.50.0:
version "8.50.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.50.0.tgz#2ae6015fee0240fcd3f83e1e25df0287f487d6b2"
integrity sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==
eslint@8.51.0:
version "8.51.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.51.0.tgz#4a82dae60d209ac89a5cff1604fea978ba4950f3"
integrity sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.6.1"
"@eslint/eslintrc" "^2.1.2"
"@eslint/js" "8.50.0"
"@eslint/js" "8.51.0"
"@humanwhocodes/config-array" "^0.11.11"
"@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8"
@@ -11898,13 +11898,13 @@ pupa@^2.1.1:
dependencies:
escape-goat "^2.0.0"
puppeteer-core@21.3.6:
version "21.3.6"
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.3.6.tgz#5507fafb790692ff887e368de71a1c5a0d08af1e"
integrity sha512-ZH6tjTdRXwW2fx5W3jBbG+yUVQdDfZW1kjfwvWwMzsnKEli5ZwV70Zp97GOebHQHrK8zM3vX5VqI9sd48c9PnQ==
puppeteer-core@21.3.8:
version "21.3.8"
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.3.8.tgz#7ac4879c9f73e8426431d8ca4c58680e517a4b08"
integrity sha512-yv12E/+zZ7Lei5tJB4sUkSrsuqKibuYpYxLGbmtLUjjYIqGE5HKz9OUI2I/RFHEvF+pHi2bTbv5bWydeCGJ6Mw==
dependencies:
"@puppeteer/browsers" "1.7.1"
chromium-bidi "0.4.28"
chromium-bidi "0.4.31"
cross-fetch "4.0.0"
debug "4.3.4"
devtools-protocol "0.0.1179426"
+1 -1
View File
@@ -33,7 +33,7 @@ want Bazel to create several symlinks in your project directory
`.bazelrc` file.
[GitHub]: https://github.com/bazelbuild/rules_typescript
[bazelrc doc]: https://bazel.build/versions/master/docs/bazel-user-manual.html#bazelrc
[bazelrc doc]: https://bazel.build/run/bazelrc
## Building Angular
+16 -16
View File
@@ -1,6 +1,6 @@
{
"name": "angular-srcs",
"version": "16.2.9",
"version": "16.2.11",
"private": true,
"description": "Angular - a web framework for modern web apps",
"homepage": "https://github.com/angular/angular",
@@ -53,14 +53,14 @@
"@angular/cdk": "16.2.0-next.4",
"@angular/cli": "16.2.0-next.3",
"@angular/material": "16.2.0-next.4",
"@babel/cli": "7.22.5",
"@babel/core": "7.22.5",
"@babel/generator": "7.22.5",
"@babel/parser": "7.22.5",
"@babel/preset-env": "7.22.5",
"@babel/template": "7.22.5",
"@babel/traverse": "7.22.5",
"@babel/types": "7.22.5",
"@babel/cli": "7.23.0",
"@babel/core": "7.23.2",
"@babel/generator": "7.23.0",
"@babel/parser": "7.23.0",
"@babel/preset-env": "7.23.2",
"@babel/template": "7.22.15",
"@babel/traverse": "7.23.2",
"@babel/types": "7.23.0",
"@bazel/concatjs": "5.8.1",
"@bazel/esbuild": "5.8.1",
"@bazel/jasmine": "5.8.1",
@@ -81,17 +81,17 @@
"@types/babel__template": "7.4.1",
"@types/babel__traverse": "7.20.1",
"@types/bluebird": "^3.5.27",
"@types/chrome": "^0.0.246",
"@types/chrome": "^0.0.248",
"@types/convert-source-map": "^2.0.0",
"@types/diff": "^5.0.0",
"@types/dom-view-transitions": "^1.0.1",
"@types/hammerjs": "2.0.42",
"@types/jasmine": "^4.0.0",
"@types/hammerjs": "2.0.43",
"@types/jasmine": "^5.0.0",
"@types/jasmine-ajax": "^3.3.1",
"@types/jasminewd2": "^2.0.8",
"@types/node": "^16.11.7",
"@types/selenium-webdriver": "3.0.7",
"@types/selenium-webdriver4": "npm:@types/selenium-webdriver@4.1.17",
"@types/selenium-webdriver4": "npm:@types/selenium-webdriver@4.1.18",
"@types/semver": "^7.3.4",
"@types/shelljs": "^0.8.6",
"@types/systemjs": "6.13.3",
@@ -127,7 +127,7 @@
"karma-jasmine": "^5.0.0",
"karma-requirejs": "^1.1.0",
"karma-sourcemap-loader": "^0.4.0",
"magic-string": "0.30.4",
"magic-string": "0.30.5",
"memo-decorator": "^2.0.1",
"ngx-flamegraph": "0.0.12",
"nodejs-websocket": "^1.7.2",
@@ -139,7 +139,7 @@
"rollup-plugin-sourcemaps": "^0.6.3",
"rxjs": "^6.6.7",
"selenium-webdriver": "3.5.0",
"selenium-webdriver4": "npm:selenium-webdriver@4.13.0",
"selenium-webdriver4": "npm:selenium-webdriver@4.14.0",
"semver-dsl": "^1.0.1",
"shelljs": "^0.8.5",
"source-map": "0.7.4",
@@ -206,6 +206,6 @@
"resolutions": {
"**/graceful-fs": "4.2.11",
"**/https-proxy-agent": "7.0.2",
"**/saucelabs": "7.2.2"
"**/saucelabs": "7.4.0"
}
}
@@ -58,7 +58,7 @@ export abstract class LocationStrategy {
* with a base href value, so that the DI framework can supply the dependency anywhere in the app.
*
* ```typescript
* import {Component, NgModule} from '@angular/core';
* import {NgModule} from '@angular/core';
* import {APP_BASE_HREF} from '@angular/common';
*
* @NgModule({
+1 -1
View File
@@ -43,7 +43,7 @@
}
},
"dependencies": {
"@babel/core": "7.22.5",
"@babel/core": "7.23.2",
"@jridgewell/sourcemap-codec": "^1.4.14",
"reflect-metadata": "^0.1.2",
"chokidar": "^3.0.0",
@@ -65,7 +65,7 @@ in two ways:
For example, a directive's selector may be determined via an imported constant:
```typescript=
```typescript
import {Directive} from '@angular/core';
import {DIR_SELECTOR} from './selectors';
@@ -138,7 +138,7 @@ never a reference from a component to its NgModule, or any of its directive or p
In code, this looks like:
```typescript=
```typescript
// dir.ts
@Directive({selector: '[dir]'})
export class Dir {}
@@ -161,7 +161,7 @@ export class Mod {}
Here, `Cmp` never directly imports or refers to `Dir`, but it _does_ consume the directive in its
template. During emit, `Cmp` would receive a `directiveDefs` array:
```typescript=
```typescript
// cmp.js
import * as i1 from './dir';
+2 -1
View File
@@ -108,7 +108,7 @@ import {isPromise, isSubscribable} from './util/lang';
* ```
*
* ### Example with standalone application
*
* ```
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
* return () => httpClient.get("https://someUrl.com/api/user")
* .pipe(
@@ -127,6 +127,7 @@ import {isPromise, isSubscribable} from './util/lang';
* },
* ],
* });
* ```
*
* @publicApi
*/
+2 -2
View File
@@ -188,10 +188,10 @@ function createOrReusePlatformInjector(providers: StaticProvider[] = []): Inject
// is already bootstrapped and no additional actions are required.
if (_platformInjector) return _platformInjector;
publishDefaultGlobalUtils();
// Otherwise, setup a new platform injector and run platform initializers.
const injector = createPlatformInjector(providers);
_platformInjector = injector;
publishDefaultGlobalUtils();
publishSignalConfiguration();
runPlatformInitializers(injector);
return injector;
@@ -1283,7 +1283,7 @@ export function internalProvideZoneChangeDetection(ngZoneFactory: () => NgZone):
* `BootstrapOptions` instead.
*
* @usageNotes
* ```typescript=
* ```typescript
* bootstrapApplication(MyApp, {providers: [
* provideZoneChangeDetection({eventCoalescing: true}),
* ]});
+8 -1
View File
@@ -28,7 +28,7 @@ import {catchInjectorError, convertToBitFlags, injectArgs, NG_TEMP_TOKEN_PATH, s
import {INJECTOR} from './injector_token';
import {getInheritedInjectableDef, getInjectableDef, InjectorType, ɵɵInjectableDeclaration} from './interface/defs';
import {InjectFlags, InjectOptions} from './interface/injector';
import {ClassProvider, ConstructorProvider, EnvironmentProviders, InternalEnvironmentProviders, isEnvironmentProviders, Provider, StaticClassProvider} from './interface/provider';
import {ClassProvider, ConstructorProvider, EnvironmentProviders, InternalEnvironmentProviders, isEnvironmentProviders, Provider, StaticClassProvider, TypeProvider} from './interface/provider';
import {INJECTOR_DEF_TYPES} from './internal_tokens';
import {NullInjector} from './null_injector';
import {isExistingProvider, isFactoryProvider, isTypeProvider, isValueProvider, SingleProvider} from './provider_collection';
@@ -271,6 +271,13 @@ export class R3Injector extends EnvironmentInjector {
if (def && this.injectableDefInScope(def)) {
// Found an injectable def and it's scoped to this injector. Pretend as if it was here
// all along.
if (ngDevMode) {
runInInjectorProfilerContext(this, token as Type<T>, () => {
emitProviderConfiguredEvent(token as TypeProvider);
});
}
record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET);
} else {
record = null;
@@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import type {FactoryProvider} from '../../di';
import {resolveForwardRef} from '../../di/forward_ref';
import {InjectionToken} from '../../di/injection_token';
import type {Injector} from '../../di/injector';
@@ -86,7 +87,7 @@ export interface ProviderRecord {
/**
* DI token that this provider is configuring
*/
token: Type<unknown>;
token: Type<unknown>|InjectionToken<unknown>;
/**
* Determines if provider is configured as view provider.
@@ -192,20 +193,39 @@ function injectorProfiler(event: InjectorProfilerEvent): void {
* Emits an InjectorProfilerEventType.ProviderConfigured to the injector profiler. The data in the
* emitted event includes the raw provider, as well as the token that provider is providing.
*
* @param provider A provider object
* @param eventProvider A provider object
*/
export function emitProviderConfiguredEvent(
provider: SingleProvider, isViewProvider: boolean = false): void {
eventProvider: SingleProvider, isViewProvider: boolean = false): void {
!ngDevMode && throwError('Injector profiler should never be called in production mode');
let token;
// if the provider is a TypeProvider (typeof provider is function) then the token is the
// provider itself
if (typeof eventProvider === 'function') {
token = eventProvider;
}
// if the provider is an injection token, then the token is the injection token.
else if (eventProvider instanceof InjectionToken) {
token = eventProvider;
}
// in all other cases we can access the token via the `provide` property of the provider
else {
token = resolveForwardRef(eventProvider.provide);
}
let provider = eventProvider;
// Injection tokens may define their own default provider which gets attached to the token itself
// as `ɵprov`. In this case, we want to emit the provider that is attached to the token, not the
// token itself.
if (eventProvider instanceof InjectionToken) {
provider = eventProvider.ɵprov as FactoryProvider || eventProvider;
}
injectorProfiler({
type: InjectorProfilerEventType.ProviderConfigured,
context: getInjectorProfilerContext(),
providerRecord: {
token: typeof provider === 'function' ? provider : resolveForwardRef(provider.provide),
provider,
isViewProvider
}
providerRecord: {token, provider, isViewProvider}
});
}
@@ -17,12 +17,6 @@ export interface ReactiveLViewConsumer extends ReactiveNode {
lView: LView|null;
}
export function setLViewForConsumer(node: ReactiveLViewConsumer, lView: LView): void {
(typeof ngDevMode === 'undefined' || ngDevMode) &&
assertEqual(node.lView, null, 'Consumer already associated with a view.');
node.lView = lView;
}
/**
* Create a new template consumer pointing at the specified LView.
* Sometimes, a previously created consumer may be reused, in order to save on allocations. In that
@@ -151,6 +151,12 @@ function getProviderImportsContainer(injector: Injector): Type<unknown>|null {
return null;
}
// In standalone applications, the root environment injector created by bootstrapApplication
// may have no associated "instance".
if (defTypeRef.instance === null) {
return null;
}
return defTypeRef.instance.constructor;
}
@@ -351,13 +357,29 @@ function walkProviderTreeToDiscoverImportPaths(
* @returns an array of objects representing the providers of the given injector
*/
function getEnvironmentInjectorProviders(injector: EnvironmentInjector): ProviderRecord[] {
const providerRecords = getFrameworkDIDebugData().resolverToProviders.get(injector) ?? [];
// platform injector has no provider imports container so can we skip trying to
// find import paths
if (isPlatformInjector(injector)) {
return providerRecords;
}
const providerImportsContainer = getProviderImportsContainer(injector);
if (providerImportsContainer === null) {
// There is a special case where the bootstrapped component does not
// import any NgModules. In this case the environment injector connected to
// that component is the root injector, which does not have a provider imports
// container (and thus no concept of module import paths). Therefore we simply
// return the provider records as is.
if (isRootInjector(injector)) {
return providerRecords;
}
throwError('Could not determine where injector providers were configured.');
}
const providerToPath = getProviderImportPaths(providerImportsContainer);
const providerRecords = getFrameworkDIDebugData().resolverToProviders.get(injector) ?? [];
return providerRecords.map(providerRecord => {
let importPath = providerToPath.get(providerRecord.provider) ?? [providerImportsContainer];
@@ -374,6 +396,14 @@ function getEnvironmentInjectorProviders(injector: EnvironmentInjector): Provide
});
}
function isPlatformInjector(injector: Injector) {
return injector instanceof R3Injector && injector.scopes.has('platform');
}
function isRootInjector(injector: Injector) {
return injector instanceof R3Injector && injector.scopes.has('root');
}
/**
* Gets the providers configured on an injector.
*
@@ -71,44 +71,30 @@ describe('change detection', () => {
@Component({
template: `
<button (click)="noop()">Trigger change detection</button>
<div>{{increment('componentView')}}</div>
<ng-template #vm="vm" viewManipulation>{{increment('embeddedView')}}</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
class App {
increment(counter: 'componentView'|'embeddedView') {
counters[counter]++;
}
noop() {}
}
TestBed.configureTestingModule({declarations: [App, ViewManipulation]});
const fixture = TestBed.createComponent(App);
const vm: ViewManipulation = fixture.debugElement.childNodes[2].references['vm'];
const button = fixture.nativeElement.querySelector('button');
const vm: ViewManipulation = fixture.debugElement.childNodes[1].references['vm'];
const viewRef = vm.insertIntoVcRef();
fixture.detectChanges();
expect(counters).toEqual({componentView: 1, embeddedView: 1});
button.click();
fixture.detectChanges();
expect(counters).toEqual({componentView: 2, embeddedView: 2});
viewRef.detach();
button.click();
fixture.detectChanges();
expect(counters).toEqual({componentView: 3, embeddedView: 2});
expect(counters).toEqual({componentView: 2, embeddedView: 0});
// Re-attach the view to ensure that the process can be reversed.
viewRef.reattach();
button.click();
fixture.detectChanges();
expect(counters).toEqual({componentView: 4, embeddedView: 3});
expect(counters).toEqual({componentView: 4, embeddedView: 2});
});
it('should not detect changes in child component views while they are detached', () => {
@@ -209,6 +209,83 @@ describe('setProfiler', () => {
expect(((myServiceProviderConfiguredEvent!.providerRecord)?.provider as ClassProvider).multi)
.toBeTrue();
});
it('should emit correct DI events when service providers are configured with providedIn', () => {
@Injectable({providedIn: 'root'})
class RootService {
}
@Injectable({providedIn: 'platform'})
class PlatformService {
}
const providedInRootInjectionToken = new InjectionToken(
'providedInRootInjectionToken', {providedIn: 'root', factory: () => 'hello world'});
const providedInPlatformToken = new InjectionToken(
'providedInPlatformToken', {providedIn: 'platform', factory: () => 'hello world'});
@Component({
selector: 'my-comp',
template: 'hello world',
})
class MyComponent {
rootService = inject(RootService);
platformService = inject(PlatformService);
fromRoot = inject(providedInRootInjectionToken);
fromPlatform = inject(providedInPlatformToken);
}
TestBed.configureTestingModule({declarations: [MyComponent]});
TestBed.createComponent(MyComponent);
// MyService should have been configured
const rootServiceProviderConfiguredEvent = searchForProfilerEvent<ProviderConfiguredEvent>(
providerConfiguredEvents, (event) => event.providerRecord.token === RootService);
expect(rootServiceProviderConfiguredEvent).toBeTruthy();
expect(rootServiceProviderConfiguredEvent!.context).toBeTruthy();
expect(rootServiceProviderConfiguredEvent!.context!.injector).toBeInstanceOf(R3Injector);
expect((rootServiceProviderConfiguredEvent!.context!.injector as R3Injector).scopes.has('root'))
.toBeTrue();
const platformServiceProviderConfiguredEvent = searchForProfilerEvent<ProviderConfiguredEvent>(
providerConfiguredEvents, (event) => event.providerRecord.token === PlatformService);
expect(platformServiceProviderConfiguredEvent).toBeTruthy();
expect(platformServiceProviderConfiguredEvent!.context).toBeTruthy();
expect(platformServiceProviderConfiguredEvent!.context!.injector).toBeInstanceOf(R3Injector);
expect((platformServiceProviderConfiguredEvent!.context!.injector as R3Injector)
.scopes.has('platform'))
.toBeTrue();
const providedInRootInjectionTokenProviderConfiguredEvent =
searchForProfilerEvent<ProviderConfiguredEvent>(
providerConfiguredEvents,
(event) => event.providerRecord.token === providedInRootInjectionToken);
expect(providedInRootInjectionTokenProviderConfiguredEvent).toBeTruthy();
expect(providedInRootInjectionTokenProviderConfiguredEvent!.context).toBeTruthy();
expect(providedInRootInjectionTokenProviderConfiguredEvent!.context!.injector)
.toBeInstanceOf(R3Injector);
expect((providedInRootInjectionTokenProviderConfiguredEvent!.context!.injector as R3Injector)
.scopes.has('root'))
.toBeTrue();
expect(providedInRootInjectionTokenProviderConfiguredEvent!.providerRecord.token)
.toBe(providedInRootInjectionToken);
const providedInPlatformTokenProviderConfiguredEvent =
searchForProfilerEvent<ProviderConfiguredEvent>(
providerConfiguredEvents,
(event) => event.providerRecord.token === providedInPlatformToken);
expect(providedInPlatformTokenProviderConfiguredEvent).toBeTruthy();
expect(providedInPlatformTokenProviderConfiguredEvent!.context).toBeTruthy();
expect(providedInPlatformTokenProviderConfiguredEvent!.context!.injector)
.toBeInstanceOf(R3Injector);
expect((providedInPlatformTokenProviderConfiguredEvent!.context!.injector as R3Injector)
.scopes.has('platform'))
.toBeTrue();
expect(providedInPlatformTokenProviderConfiguredEvent!.providerRecord.token)
.toBe(providedInPlatformToken);
});
});
describe('getInjectorProviders', () => {
+1 -1
View File
@@ -34,7 +34,7 @@
"./fesm2022/init.mjs"
],
"dependencies": {
"@babel/core": "7.22.5",
"@babel/core": "7.23.2",
"fast-glob": "3.3.0",
"yargs": "^17.2.1"
},
+5 -2
View File
@@ -85,8 +85,11 @@ export interface RouterConfigOptions {
/**
* Defines how the router merges parameters, data, and resolved data from parent to child
* routes. By default ('emptyOnly'), inherits parent parameters only for
* path-less or component-less routes.
* routes.
*
* By default ('emptyOnly'), a route inherits the parent route's parameters when the route itself
* has an empty path (meaning its configured with path: '') or when the parent route doesn't have
* any component set.
*
* Set to 'always' to enable unconditional inheritance of parent parameters.
*
@@ -155,6 +155,10 @@ export class RouterTestingHarness {
}
return activatedComponent as T;
} else {
if (requiredRoutedComponentType !== undefined) {
throw new Error(`Unexpected routed component type. Expected ${
requiredRoutedComponentType.name} but the navigation did not activate any component.`);
}
return null;
}
}
@@ -100,6 +100,20 @@ describe('navigateForTest', () => {
await expectAsync(harness.navigateByUrl('/123', OtherCmp)).toBeRejected();
});
it('throws an error if navigation fails but expected a component instance', async () => {
@Component({standalone: true, template: ''})
class TestCmp {
}
TestBed.configureTestingModule({
providers: [
provideRouter([{path: '**', canActivate: [() => false], component: TestCmp}]),
]
});
const harness = await RouterTestingHarness.create();
await expectAsync(harness.navigateByUrl('/123', TestCmp)).toBeRejected();
});
it('waits for redirects using router.navigate', async () => {
@Component({standalone: true, template: 'test'})
class TestCmp {
+459 -649
View File
File diff suppressed because it is too large Load Diff