-
Notifications
You must be signed in to change notification settings - Fork 27k
docs: rewrite testing docs #66203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
docs: rewrite testing docs #66203
Conversation
45cd300 to
f20b978
Compare
f20b978 to
53201b9
Compare
|
Deployed adev-preview for 4aede34 to: https://ng-dev-previews-fw--pr-angular-angular-66203-adev-prev-fsjokg4x.web.app Note: As new commits are pushed to this pull request, this link is updated after the preview is rebuilt. |
8afe565 to
fdb3d62
Compare
| <docs-code header="polyfills.ts or canvas.component.ts" path="adev/src/content/examples/testing/src/app/shared/canvas.component.ts" region="import-canvas-patch"/> | ||
| vi.useRealTimers(); // resets to regular async execution | ||
| }); | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add another example with for example timed intervals ?
|
/gemini review |
fdb3d62 to
f803733
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request does a great job of rewriting the testing documentation to align with modern practices, primarily by replacing Karma/Jasmine with Vitest and fakeAsync with native async/await. The changes significantly improve the clarity and relevance of the testing guides. I've found a few minor issues in the code examples and documentation, such as typos, incorrect API usage with signals, and inconsistencies in async test patterns. Addressing these will further enhance the quality of the documentation.
...ent/examples/forms-overview/src/app/template/favorite-color/favorite-color.component.spec.ts
Outdated
Show resolved
Hide resolved
f803733 to
22cadc1
Compare
|
/gemini review |
22cadc1 to
c9942d2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request is a significant and valuable rewrite of the Angular testing documentation, focusing on modern practices like using Vitest over Karma/Jasmine and async/await with whenStable instead of fakeAsync. The changes are comprehensive and well-executed. My review focuses on ensuring the new documentation and code examples are clear, correct, and free of issues that might confuse readers. I've identified a few areas in the code snippets, primarily within components-scenarios.md, that could be improved for clarity and correctness, and I've provided specific suggestions to address them.
99e22bc to
0a4971b
Compare
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request is a major and valuable rewrite of the testing documentation, focusing on modern practices with Vitest and signals, and moving away from Jasmine and fakeAsync. The changes are comprehensive and align well with the goal of modernizing Angular's testing story. I've found a few minor issues in the code examples, mainly related to incorrect variable names and inconsistent use of testing APIs, which I've detailed in my comments. Overall, this is a fantastic contribution.
0a4971b to
fafa78b
Compare
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request provides a comprehensive rewrite of the testing documentation, focusing on modern practices like using Vitest, whenStable, and signal-based components. The changes are a significant improvement, making the documentation more up-to-date and easier to follow. I've found one minor issue in an example for an attribute directive where a host binding seems to be incorrect. My review includes a suggestion to fix this for consistency and correctness.
fafa78b to
19c7c0f
Compare
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request is a significant rewrite of the testing documentation, focusing on migrating from Karma/Jasmine to Vitest and adopting modern Angular testing practices. The changes include replacing fakeAsync and tick with native async/await and Vitest's mock timers, using whenStable for change detection, and updating code examples to use signals and modern APIs. The documentation is now more aligned with the current state of Angular and its ecosystem.
I've found a few issues in the updated code examples within the documentation that could confuse readers or lead to incorrect test implementations. My review comments provide suggestions to fix these issues, ensuring the documentation is accurate and provides best-practice examples. The issues are mostly minor and related to incorrect API usage in test snippets.
Those rewrites focus on using Vitest instead of jasmine, drop usages of `fakeAsync`, present modern testing strategy that rely on `whenStable` more than explicit calls to `detectChanges`. fixes angular#42748, angular#48510, angular#64962, angular#65987, angular#66029, angular#66150
19c7c0f to
4aede34
Compare
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request primarily focuses on migrating Angular testing documentation and examples from fakeAsync and waitForAsync to native async/await with fixture.whenStable(), and updating examples to use Angular Signals and Vitest's mock clock features. Key changes include renaming components from ComponentNameComponent to ComponentName, updating test setups to use async/await and fixture.whenStable() instead of fakeAsync and tick()/detectChanges(), and modifying component properties to use signal() where appropriate. The documentation for forms, routing, attribute directives, basic components, and advanced component scenarios has been updated to reflect these new testing patterns and signal usage. Additionally, the migrating-to-vitest.md guide explicitly states that zone.js and fakeAsync are not supported with Vitest, reinforcing the shift to native async testing. A review comment highlights an issue in a NO_ERRORS_SCHEMA example, noting that imports: [] incorrectly removes RouterLink, which is needed for router link tests, and suggests keeping RouterLink in the imports while removing unused providers like UserAuthentication for clarity.
rainerhahnekamp
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added a few simple suggestions and comments.
In this summary, I have a few suggestions that, if considered for future iterations, might require a more comprehensive rewrite than what's currently in scope for this PR.
These are intended as constructive feedback to align the documentation with modern Angular testing practices.
Overview and Structure
I would change the overview header from "Unit testing" to "Testing". The term "unit testing" lacks a universal definition, and developers who search for "Component testing" or "Integration testing" support might look elsewhere.
It would be helpful to provide a quick overview of different testing terminology used in the industry and clarify which testing types this guide covers.
Component Testing Priority
Most Angular developers are building applications where the majority of business logic resides in the backend. In this scenario, DOM-based tests and tests for entire features (which may consist of multiple components) should be prioritized.
The arguments for this approach are already present in the "basics of component testing" chapter. However, it would be beneficial to move these arguments in the overview section, as many developers are still writing tests that focus on component instances, mock every dependency, and ignore the DOM.
Use Browser Mode APIs exclusively for component tests
I don't see using the ComponentFixture for interacting or querying the DOM as necessary anymore. Instead, all examples for testing components should use the page, userEvent objects (both vitest/browser) and expect.element when asserting DOM elements. page and expect.element make use of the E2E waiting mechanism, which means for many places, even fixture.whenStable() is not necessary anymore.
HTTP Testing
Consider avoiding examples that demonstrate how to create spies for HttpClient and just another service. Since httpResource uses HttpClient under the hood, developers shouldn't need to know which specific methods are called (e.g., httpResource calls request rather than get).
Debugging Section
The debugging section may need to be updated. To my knowledge, test debugging in Vitest is not currently supported. Please confirm whether this information is accurate or if it needs revision.
Setup Pattern
Consider using the setup function approach everywhere instead the beforeEach pattern. The setup function allows tests to customize their setup through parameters, providing more flexibility than the pre-defined context that beforeEach enforces. This approach is already documented at https://angular.dev/guide/testing/services#testing-without-beforeeach.
Fakes
The harnesses section is well-documented. Harnesses are a specialized form of fake for UI elements. Consider adding a dedicated chapter on fakes in general, as they can be valuable when you work with more complex services.
Such a chapter could also highlight that RouterTestingHarness and HttpTestingController are examples of fakes that Angular provides out of the box.
expect.poll vs. fixture.whenStable() vs. expect.element
Consider documenting expect.poll() as an alternative to fixture.whenStable(). The advantage of expect.poll() is that developers declare what they expect, and the testing framework waits for it, whereas fixture.whenStable() is more implementation-focused. From a user perspective, tests should simply verify the expected outcome, regardless of whether the operation is synchronous or asynchronous.
However, if the documentation fully commits to full browser mode (as suggested above), this discussion may be less critical. In that scenario, expect.element would be the primary approach, with the other two acting as fallbacks when needed.
Testing with Asynchronous Tasks
I do believe that this deservers its own chapters. At the moment it is part of component testing scenarios, but very often managing asynchronous tasks come with service tests as well.
| 1. Use the component instance to set the value of the `favoriteColor` property. | ||
| 1. Run change detection through the test fixture. | ||
| 1. Use the `tick()` method to simulate the passage of time within the `fakeAsync()` task. | ||
| 1. Use `await fixture.whenStable` to wait for the next rendering. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 1. Use `await fixture.whenStable` to wait for the next rendering. | |
| 1. Use `await fixture.whenStable()` to wait for the next rendering. |
|
|
||
| You will add more tests as this component evolves. | ||
| Rather than duplicate the `TestBed` configuration for each test, you refactor to pull the setup into a Jasmine `beforeEach()` and some supporting variables: | ||
| Rather than duplicate the `TestBed` configuration for each test, you refactor to pull the setup into a `beforeEach()` and some supporting variables: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about suggesting a simple setup function as alternative?
A setup function has to be called by each test but it has the advantage that it is customizable via parameters. So the test has a say in the way how the setup runs. For example, specific tests might not want to have fixture.whenStable() executed.
A setup function could then have the following signature setup(runWhenStable = true): Promise<ComponentFixture<Banner>>
| **2. Automatic search for base configuration:** | ||
| If you set `runnerConfig` to `true`, the builder will automatically search for a shared `vitest-base.config.*` file in your project and workspace roots. | ||
|
|
||
| ## `zone.js` and `fakeAsync` are not supported |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know waitForAsync is also not supported anymore.
|
|
||
| ## `zone.js` and `fakeAsync` are not supported | ||
|
|
||
| The zone.js patches are not applied when running tests with vitest. To migrate to Vitest you also need to migrate your tests to native async and vitest mock clocks. See [an example here](/components-scenarios#async-test-with-a-vitest-mock-clock) for mock clocks usages with vitest. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| The zone.js patches are not applied when running tests with vitest. To migrate to Vitest you also need to migrate your tests to native async and vitest mock clocks. See [an example here](/components-scenarios#async-test-with-a-vitest-mock-clock) for mock clocks usages with vitest. | |
| The zone.js patches are not applied when running tests with Vitest. To migrate to Vitest you also need to migrate your tests to native async and Vitest mock clocks. See [an example here](/components-scenarios#async-test-with-a-vitest-mock-clock) for mock clocks usages with Vitest. |
|
|
||
| ## `zone.js` and `fakeAsync` are not supported | ||
|
|
||
| The zone.js patches are not applied when running tests with vitest. To migrate to Vitest you also need to migrate your tests to native async and vitest mock clocks. See [an example here](/components-scenarios#async-test-with-a-vitest-mock-clock) for mock clocks usages with vitest. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock Clocks is the term, that Jasmine uses. In Jest and Vitest they are called fake timers. I didn't correct it above because renaming to fake timers would be probably require an additional PR.
| await fixture.whenStable(); | ||
|
|
||
| If you run other macro tasks such as `HTMLCanvasElement.toBlob()`, an _"Unknown macroTask scheduled in fake async test"_ error is thrown. | ||
| expect(errorMessage()).toMatch(/test failure/); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, this would be a perfect use case to use expect.poll (see my review description). it would drop the need for whenStable.
Those rewrites focus on using Vitest instead of jasmine, drop usages of
fakeAsync, present modern testing strategy that rely onwhenStablemore than explicit calls todetectChanges.fixes:
asyncFakereferencessrc/test.tswith Angular CLI, which is not generated with v21 #66029fakeAsyncfor Vitest is not supported #66150