style: fix whitespace and indentation in the testing guide (#21669)
PR Close #21669
This commit is contained in:
parent
ebf508fcd0
commit
74518c4b2e
|
@ -6,8 +6,8 @@ This guide offers tips and techniques for unit and integration testing Angular a
|
|||
The guide presents tests of a sample CLI application that is much like the [_Tour of Heroes_ tutorial](tutorial).
|
||||
The sample application and all tests in this guide are available for inspection and experimentation:
|
||||
|
||||
* <live-example embedded-style>Sample app</live-example>
|
||||
* <live-example stackblitz="specs">Tests</live-example>
|
||||
- <live-example embedded-style>Sample app</live-example>
|
||||
- <live-example stackblitz="specs">Tests</live-example>
|
||||
|
||||
<hr>
|
||||
|
||||
|
@ -84,7 +84,7 @@ The test file extension **must be `.spec.ts`** so that tooling can identify it a
|
|||
|
||||
</div>
|
||||
|
||||
The `app.component.ts` and `app.component.spec.ts` files are siblings in the same folder.
|
||||
The `app.component.ts` and `app.component.spec.ts` files are siblings in the same folder.
|
||||
The root file names (`app.component`) are the same for both files.
|
||||
|
||||
Adopt these two conventions in your own projects for _every kind_ of test file.
|
||||
|
@ -153,7 +153,7 @@ when you use the `TestBed` testing utility to provide and create services.
|
|||
|
||||
#### Angular _TestBed_
|
||||
|
||||
The `TestBed` is the most important of the Angular testing utilities.
|
||||
The `TestBed` is the most important of the Angular testing utilities.
|
||||
The `TestBed` creates a dynamically-constructed Angular _test_ module that emulates
|
||||
an Angular [@NgModule](guide/ngmodules).
|
||||
|
||||
|
@ -403,11 +403,11 @@ respond to user input and gestures, or integrate with its parent and child compo
|
|||
None of the _class-only_ tests above can answer key questions about how the
|
||||
components actually behave on screen.
|
||||
|
||||
* Is `Lightswitch.clicked()` bound to anything such that the user can invoke it?
|
||||
* Is the `Lightswitch.message` displayed?
|
||||
* Can the user actually select the hero displayed by `DashboardHeroComponent`?
|
||||
* Is the hero name displayed as expected (i.e, in uppercase)?
|
||||
* Is the welcome message displayed by the template of `WelcomeComponent`?
|
||||
- Is `Lightswitch.clicked()` bound to anything such that the user can invoke it?
|
||||
- Is the `Lightswitch.message` displayed?
|
||||
- Can the user actually select the hero displayed by `DashboardHeroComponent`?
|
||||
- Is the hero name displayed as expected (i.e, in uppercase)?
|
||||
- Is the welcome message displayed by the template of `WelcomeComponent`?
|
||||
|
||||
These may not be troubling questions for the simple components illustrated above.
|
||||
But many components have complex interactions with the DOM elements
|
||||
|
@ -625,7 +625,7 @@ For example, the component might render first on the server as part of a strateg
|
|||
If it doesn't support `querySelector`, the previous test could fail.
|
||||
|
||||
The `DebugElement` offers query methods that work for all supported platforms.
|
||||
These query methods take a _predicate_ function that returns `true` when a node in the `DebugElement` tree matches the selection criteria.
|
||||
These query methods take a _predicate_ function that returns `true` when a node in the `DebugElement` tree matches the selection criteria.
|
||||
|
||||
You create a _predicate_ with the help of a `By` class imported from a
|
||||
library for the runtime platform. Here's the `By` import for the browser platform:
|
||||
|
@ -645,10 +645,10 @@ The following example re-implements the previous test with
|
|||
|
||||
Some noteworthy observations:
|
||||
|
||||
* The `By.css()` static method selects `DebugElement` nodes
|
||||
with a [standard CSS selector](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors "CSS selectors").
|
||||
* The query returns a `DebugElement` for the paragraph.
|
||||
* You must unwrap that result to get the paragraph element.
|
||||
- The `By.css()` static method selects `DebugElement` nodes
|
||||
with a [standard CSS selector](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors 'CSS selectors').
|
||||
- The query returns a `DebugElement` for the paragraph.
|
||||
- You must unwrap that result to get the paragraph element.
|
||||
|
||||
When you're filtering by CSS selector and only testing properties of a browser's _native element_, the `By.css` approach may be overkill.
|
||||
|
||||
|
@ -706,6 +706,7 @@ Your instinct is to write a test that immediately inspects the `<h1>` like this:
|
|||
</code-example>
|
||||
|
||||
_That test fails_ with the message:
|
||||
|
||||
```javascript
|
||||
expected '' to contain 'Test Tour of Heroes'.
|
||||
```
|
||||
|
@ -739,7 +740,6 @@ the component _before Angular initiates data binding and calls [lifecycle hooks]
|
|||
|
||||
Here's another test that changes the component's `title` property _before_ calling `fixture.detectChanges()`.
|
||||
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner.component.spec.ts"
|
||||
region="after-change">
|
||||
|
@ -1051,6 +1051,7 @@ The test must wait at least one full turn of the JavaScript engine before the
|
|||
value becomes available. The test must become _asynchronous_.
|
||||
|
||||
{@a fake-async}
|
||||
|
||||
#### Async test with _fakeAsync()_
|
||||
|
||||
The following test confirms the expected behavior when the service returns an `ErrorObservable`.
|
||||
|
@ -1061,6 +1062,7 @@ The following test confirms the expected behavior when the service returns an `E
|
|||
</code-example>
|
||||
|
||||
Note that the `it()` function receives an argument of the following form.
|
||||
|
||||
```javascript
|
||||
fakeAsync(() => { /* test body */ })`
|
||||
```
|
||||
|
@ -1261,7 +1263,6 @@ But it is occasionally necessary.
|
|||
For example, you can't call `async` or `fakeAsync` when testing
|
||||
code that involves the `intervalTimer()` or the RxJS `delay()` operator.
|
||||
|
||||
|
||||
Here are two mover versions of the previous test, written with `done()`.
|
||||
The first one subscribes to the `Observable` exposed to the template by the component's `quote` property.
|
||||
|
||||
|
@ -1393,7 +1394,6 @@ A _hot_ observable is already producing values _before_ you subscribe to it.
|
|||
The [_Router.events_](api/router/Router#events) observable,
|
||||
which reports router activity, is a _hot_ observable.
|
||||
|
||||
|
||||
RxJS marble testing is a rich subject, beyond the scope of this guide.
|
||||
Learn about it on the web, starting with the
|
||||
[official documentation](https://github.com/ReactiveX/rxjs/blob/master/doc/writing-marble-tests.md).
|
||||
|
@ -1439,9 +1439,9 @@ Here's the component's full definition:
|
|||
While testing a component this simple has little intrinsic value, it's worth knowing how.
|
||||
You can use one of these approaches:
|
||||
|
||||
* Test it as used by `DashboardComponent`.
|
||||
* Test it as a stand-alone component.
|
||||
* Test it as used by a substitute for `DashboardComponent`.
|
||||
- Test it as used by `DashboardComponent`.
|
||||
- Test it as a stand-alone component.
|
||||
- Test it as used by a substitute for `DashboardComponent`.
|
||||
|
||||
A quick look at the `DashboardComponent` constructor discourages the first approach:
|
||||
|
||||
|
@ -1561,6 +1561,7 @@ which is perfectly fine for _this component_.
|
|||
</code-example>
|
||||
|
||||
{@a click-helper}
|
||||
|
||||
#### _click()_ helper
|
||||
|
||||
Clicking a button, an anchor, or an arbitrary HTML element is a common test task.
|
||||
|
@ -1756,10 +1757,11 @@ by manipulating the `ActivatedRoute` injected into the component's constructor.
|
|||
You know how to spy on the `Router` and a data service.
|
||||
|
||||
You'll take a different approach with `ActivatedRoute` because
|
||||
* `paramMap` returns an `Observable` that can emit more than one value
|
||||
during a test.
|
||||
* You need the router helper function, `convertToParamMap()`, to create a `ParamMap`.
|
||||
* Other _routed components_ tests need a test double for `ActivatedRoute`.
|
||||
|
||||
- `paramMap` returns an `Observable` that can emit more than one value
|
||||
during a test.
|
||||
- You need the router helper function, `convertToParamMap()`, to create a `ParamMap`.
|
||||
- Other _routed components_ tests need a test double for `ActivatedRoute`.
|
||||
|
||||
These differences argue for a re-usable stub class.
|
||||
|
||||
|
@ -1778,8 +1780,8 @@ This sample puts `ActivatedRouteStub` in `testing/activated-route-stub.ts`.
|
|||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Consider writing a more capable version of this stub class with
|
||||
the [_marble testing library_](#marble-testing).
|
||||
Consider writing a more capable version of this stub class with
|
||||
the [_marble testing library_](#marble-testing).
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -1895,7 +1897,7 @@ The rest are stubs.
|
|||
|
||||
{@a no-errors-schema}
|
||||
|
||||
#### *NO\_ERRORS\_SCHEMA*
|
||||
#### _NO_ERRORS_SCHEMA_
|
||||
|
||||
In the second approach, add `NO_ERRORS_SCHEMA` to the `TestBed.schemas` metadata.
|
||||
|
||||
|
@ -1924,7 +1926,7 @@ in the component's template that matter for tests.
|
|||
|
||||
The `NO_ERRORS_SCHEMA` approach is the easier of the two but don't overuse it.
|
||||
|
||||
The `NO_ERRORS_SCHEMA` also prevents the compiler from telling you about the missing
|
||||
The `NO_ERRORS_SCHEMA` also prevents the compiler from telling you about the missing
|
||||
components and attributes that you omitted inadvertently or misspelled.
|
||||
You could waste hours chasing phantom bugs that the compiler would have caught in an instant.
|
||||
|
||||
|
@ -1997,12 +1999,12 @@ A little more setup triggers the initial data binding and gets references to the
|
|||
|
||||
Three points of special interest:
|
||||
|
||||
1. You can locate the anchor elements with an attached directive using `By.directive`.
|
||||
1. You can locate the anchor elements with an attached directive using `By.directive`.
|
||||
|
||||
1. The query returns `DebugElement` wrappers around the matching elements.
|
||||
1. The query returns `DebugElement` wrappers around the matching elements.
|
||||
|
||||
1. Each `DebugElement` exposes a dependency injector with the
|
||||
specific instance of the directive attached to that element.
|
||||
1. Each `DebugElement` exposes a dependency injector with the
|
||||
specific instance of the directive attached to that element.
|
||||
|
||||
The `AppComponent` links to validate are as follows:
|
||||
|
||||
|
@ -2077,11 +2079,11 @@ But there's plenty of template complexity even in this simple form.
|
|||
|
||||
Tests that exercise the component need ...
|
||||
|
||||
* to wait until a hero arrives before elements appear in the DOM.
|
||||
* a reference to the title text.
|
||||
* a reference to the name input box to inspect and set it.
|
||||
* references to the two buttons so they can click them.
|
||||
* spies for some of the component and router methods.
|
||||
- to wait until a hero arrives before elements appear in the DOM.
|
||||
- a reference to the title text.
|
||||
- a reference to the name input box to inspect and set it.
|
||||
- references to the two buttons so they can click them.
|
||||
- spies for some of the component and router methods.
|
||||
|
||||
Even a small form such as this one can produce a mess of tortured conditional setup and CSS element selection.
|
||||
|
||||
|
@ -2187,8 +2189,8 @@ Error: ViewDestroyedError: Attempt to use a destroyed view
|
|||
|
||||
A typical approach is to divide the setup logic into two separate `beforeEach()` functions:
|
||||
|
||||
1. An async `beforeEach()` that compiles the components
|
||||
1. A synchronous `beforeEach()` that performs the remaining setup.
|
||||
1. An async `beforeEach()` that compiles the components
|
||||
1. A synchronous `beforeEach()` that performs the remaining setup.
|
||||
|
||||
To follow this pattern, import the `async()` helper with the other testing symbols.
|
||||
|
||||
|
@ -2293,10 +2295,10 @@ which means you can also specify `providers` and `imports`.
|
|||
The `HeroDetailComponent` requires a lot of help despite its small size and simple construction.
|
||||
In addition to the support it receives from the default testing module `CommonModule`, it needs:
|
||||
|
||||
* `NgModel` and friends in the `FormsModule` to enable two-way data binding.
|
||||
* The `TitleCasePipe` from the `shared` folder.
|
||||
* Router services (which these tests are stubbing).
|
||||
* Hero data access services (also stubbed).
|
||||
- `NgModel` and friends in the `FormsModule` to enable two-way data binding.
|
||||
- The `TitleCasePipe` from the `shared` folder.
|
||||
- Router services (which these tests are stubbing).
|
||||
- Hero data access services (also stubbed).
|
||||
|
||||
One approach is to configure the testing module from the individual pieces as in this example:
|
||||
|
||||
|
@ -2423,7 +2425,7 @@ The [override metadata object](#metadata-override-object) is a generic defined a
|
|||
A metadata override object can either add-and-remove elements in metadata properties or completely reset those properties.
|
||||
This example resets the component's `providers` metadata.
|
||||
|
||||
The type parameter, `T`, is the kind of metadata you'd pass to the `@Component` decorator:
|
||||
The type parameter, `T`, is the kind of metadata you'd pass to the `@Component` decorator:
|
||||
|
||||
<code-example format="." language="javascript">
|
||||
selector?: string;
|
||||
|
@ -2523,20 +2525,20 @@ Here are some tests of this component:
|
|||
|
||||
A few techniques are noteworthy:
|
||||
|
||||
* The `By.directive` predicate is a great way to get the elements that have this directive _when their element types are unknown_.
|
||||
- The `By.directive` predicate is a great way to get the elements that have this directive _when their element types are unknown_.
|
||||
|
||||
* The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:not">`:not` pseudo-class</a>
|
||||
in `By.css('h2:not([highlight])')` helps find `<h2>` elements that _do not_ have the directive.
|
||||
`By.css('*:not([highlight])')` finds _any_ element that does not have the directive.
|
||||
- The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:not">`:not` pseudo-class</a>
|
||||
in `By.css('h2:not([highlight])')` helps find `<h2>` elements that _do not_ have the directive.
|
||||
`By.css('*:not([highlight])')` finds _any_ element that does not have the directive.
|
||||
|
||||
* `DebugElement.styles` affords access to element styles even in the absence of a real browser, thanks to the `DebugElement` abstraction.
|
||||
But feel free to exploit the `nativeElement` when that seems easier or more clear than the abstraction.
|
||||
- `DebugElement.styles` affords access to element styles even in the absence of a real browser, thanks to the `DebugElement` abstraction.
|
||||
But feel free to exploit the `nativeElement` when that seems easier or more clear than the abstraction.
|
||||
|
||||
* Angular adds a directive to the injector of the element to which it is applied.
|
||||
The test for the default color uses the injector of the second `<h2>` to get its `HighlightDirective` instance
|
||||
and its `defaultColor`.
|
||||
- Angular adds a directive to the injector of the element to which it is applied.
|
||||
The test for the default color uses the injector of the second `<h2>` to get its `HighlightDirective` instance
|
||||
and its `defaultColor`.
|
||||
|
||||
* `DebugElement.properties` affords access to the artificial custom property that is set by the directive.
|
||||
- `DebugElement.properties` affords access to the artificial custom property that is set by the directive.
|
||||
|
||||
<hr>
|
||||
|
||||
|
@ -2579,13 +2581,13 @@ Consider adding component tests such as this one:
|
|||
|
||||
Debug specs in the browser in the same way that you debug an application.
|
||||
|
||||
1. Reveal the karma browser window (hidden earlier).
|
||||
1. Click the **DEBUG** button; it opens a new browser tab and re-runs the tests.
|
||||
1. Open the browser's “Developer Tools” (`Ctrl-Shift-I` on windows; `Command-Option-I` in OSX).
|
||||
1. Pick the "sources" section.
|
||||
1. Open the `1st.spec.ts` test file (Control/Command-P, then start typing the name of the file).
|
||||
1. Set a breakpoint in the test.
|
||||
1. Refresh the browser, and it stops at the breakpoint.
|
||||
1. Reveal the karma browser window (hidden earlier).
|
||||
1. Click the **DEBUG** button; it opens a new browser tab and re-runs the tests.
|
||||
1. Open the browser's “Developer Tools” (`Ctrl-Shift-I` on windows; `Command-Option-I` in OSX).
|
||||
1. Pick the "sources" section.
|
||||
1. Open the `1st.spec.ts` test file (Control/Command-P, then start typing the name of the file).
|
||||
1. Set a breakpoint in the test.
|
||||
1. Refresh the browser, and it stops at the breakpoint.
|
||||
|
||||
<figure>
|
||||
<img src='generated/images/guide/testing/karma-1st-spec-debug.png' alt="Karma debugging">
|
||||
|
@ -2958,7 +2960,6 @@ Here are the most important static methods, in order of likely utility.
|
|||
</tr>
|
||||
</table
|
||||
|
||||
|
||||
A few of the `TestBed` instance methods are not covered by static `TestBed` _class_ methods.
|
||||
These are rarely needed.
|
||||
|
||||
|
@ -3382,9 +3383,9 @@ The following example finds all `DebugElements` with a reference to a template l
|
|||
|
||||
The Angular `By` class has three static methods for common predicates:
|
||||
|
||||
* `By.all` - return all elements.
|
||||
* `By.css(selector)` - return elements with matching CSS selectors.
|
||||
* `By.directive(directive)` - return elements that Angular matched to an instance of the directive class.
|
||||
- `By.all` - return all elements.
|
||||
- `By.css(selector)` - return elements with matching CSS selectors.
|
||||
- `By.directive(directive)` - return elements that Angular matched to an instance of the directive class.
|
||||
|
||||
<code-example path="testing/src/app/hero/hero-list.component.spec.ts" region="by" title="app/hero/hero-list.component.spec.ts" linenums="false"></code-example>
|
||||
|
||||
|
@ -3401,11 +3402,11 @@ The Angular `By` class has three static methods for common predicates:
|
|||
It's a good idea to put unit test spec files in the same folder
|
||||
as the application source code files that they test:
|
||||
|
||||
* Such tests are easy to find.
|
||||
* You see at a glance if a part of your application lacks tests.
|
||||
* Nearby tests can reveal how a part works in context.
|
||||
* When you move the source (inevitable), you remember to move the test.
|
||||
* When you rename the source file (inevitable), you remember to rename the test file.
|
||||
- Such tests are easy to find.
|
||||
- You see at a glance if a part of your application lacks tests.
|
||||
- Nearby tests can reveal how a part works in context.
|
||||
- When you move the source (inevitable), you remember to move the test.
|
||||
- When you rename the source file (inevitable), you remember to rename the test file.
|
||||
|
||||
<hr>
|
||||
|
||||
|
@ -3424,6 +3425,7 @@ Of course specs that test the test helpers belong in the `test` folder,
|
|||
next to their corresponding helper files.
|
||||
|
||||
{@a q-e2e}
|
||||
|
||||
#### Why not rely on E2E tests of DOM integration?
|
||||
|
||||
The component DOM tests described in this guide often require extensive setup and
|
||||
|
|
Loading…
Reference in New Issue