修订完testing

This commit is contained in:
Zhicheng Wang 2017-04-15 23:19:41 +08:00
parent 4b7daad85b
commit 04c77dc05a
6 changed files with 168 additions and 33 deletions

View File

@ -8,13 +8,13 @@
"prerelease": [ "prerelease": [
"local" "local"
], ],
"build": "sha.3271832", "build": "sha.4b7daad",
"version": "4.0.0-local", "version": "4.0.0-local",
"codeName": "snapshot", "codeName": "snapshot",
"isSnapshot": true, "isSnapshot": true,
"full": "4.0.0-local+sha.3271832", "full": "4.0.0-local+sha.4b7daad",
"branch": "master", "branch": "master",
"commitSHA": "32718328dc513900bdec26f78bf7b7547d1703d8" "commitSHA": "4b7daad85b1fd6c97002652c840b560291bfce2b"
}, },
"sections": [] "sections": []
} }

View File

@ -1200,7 +1200,6 @@ a(id="find-parent")
a #known-parent a #known-parent
:marked :marked
### Find a parent component of known type ### Find a parent component of known type
### 找到已知类型的父组件 ### 找到已知类型的父组件
@ -1214,7 +1213,9 @@ a #known-parent
在下面的例子中,父组件`AlexComponent`有几个子组件,包括`CathyComponent`: 在下面的例子中,父组件`AlexComponent`有几个子组件,包括`CathyComponent`:
a(id='alex') a(id='alex')
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-1','parent-finder.component.ts (AlexComponent v.1)')(format='.') +makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-1','parent-finder.component.ts (AlexComponent v.1)')(format='.')
:marked :marked
*Cathy* reports whether or not she has access to *Alex* *Cathy* reports whether or not she has access to *Alex*
after injecting an `AlexComponent` into her constructor: after injecting an `AlexComponent` into her constructor:

View File

@ -8,13 +8,13 @@
"prerelease": [ "prerelease": [
"local" "local"
], ],
"build": "sha.3271832", "build": "sha.4b7daad",
"version": "4.0.0-local", "version": "4.0.0-local",
"codeName": "snapshot", "codeName": "snapshot",
"isSnapshot": true, "isSnapshot": true,
"full": "4.0.0-local+sha.3271832", "full": "4.0.0-local+sha.4b7daad",
"branch": "master", "branch": "master",
"commitSHA": "32718328dc513900bdec26f78bf7b7547d1703d8" "commitSHA": "4b7daad85b1fd6c97002652c840b560291bfce2b"
}, },
"sections": [] "sections": []
} }

View File

@ -81,7 +81,9 @@ a#toc
[内置结构型指令](#structural-directives) [内置结构型指令](#structural-directives)
* [NgIf](#ngIf) * [NgIf](#ngIf)
* [NgFor](#ngFor) * [NgFor](#ngFor)
* [Template input variables](#template-input-variables) * [Template input variables](#template-input-variables)
[模板输入变量](#template-input-variables) [模板输入变量](#template-input-variables)
@ -124,8 +126,7 @@ a#html
:marked :marked
## HTML in templates ## HTML in templates
## 模板中的HTML
## HTML
HTML is the language of the Angular template. HTML is the language of the Angular template.
Almost all HTML syntax is valid template syntax. Almost all HTML syntax is valid template syntax.
@ -214,7 +215,7 @@ a#interpolation
表面上看,我们在元素标签之间插入了结果和对标签的属性进行了赋值。 表面上看,我们在元素标签之间插入了结果和对标签的属性进行了赋值。
这样思考起来很方便,并且这个误解很少给我们带来麻烦。 这样思考起来很方便,并且这个误解很少给我们带来麻烦。
但严格来讲这是不对的。插值表达式是一个特殊的语法Angular 把它转换成了[属性绑定](#property-binding),后面将会解释这一点。 但严格来讲这是不对的。插值表达式是一个特殊的语法Angular 把它转换成了[属性绑定](#property-binding)[后面](#property-binding-or-interpolation-)将会解释这一点。
But first, let's take a closer look at template expressions and statements. But first, let's take a closer look at template expressions and statements.
@ -329,7 +330,9 @@ a#expression-context
a(href="#toc") back to top a(href="#toc") back to top
a(href="#toc") 回到顶部 a(href="#toc") 回到顶部
a#no-side-effectsa#expression-guidelines a#no-side-effects
a#expression-guidelines
:marked :marked
### Expression guidelines ### Expression guidelines
@ -700,8 +703,13 @@ table
:marked :marked
You still create a structure and initialize attribute values this way in Angular templates. You still create a structure and initialize attribute values this way in Angular templates.
在 Angular 模板中,我们仍使用同样的方式来创建结构和初始化 attribute 值。Then you learn to create new elements with components that encapsulate HTML 在 Angular 模板中,我们仍使用同样的方式来创建结构和初始化 attribute 值。
and drop them into templates as if they were native HTML elements.然后,用封装了 HTML 的组件创建新元素,并把它们当作原生 HTML 元素在模板中使用。
Then you learn to create new elements with components that encapsulate HTML
and drop them into templates as if they were native HTML elements.
然后,用封装了 HTML 的组件创建新元素,并把它们当作原生 HTML 元素在模板中使用。
+makeExample('template-syntax/ts/src/app/app.component.html', 'hero-detail-1')(format=".") +makeExample('template-syntax/ts/src/app/app.component.html', 'hero-detail-1')(format=".")
:marked :marked
@ -823,12 +831,17 @@ table
.callout.is-helpful .callout.is-helpful
header A world without attributes header A world without attributes
header 没有 attribute 的世界 header 没有 attribute 的世界
:marked :marked
In the world of Angular, the only role of attributes is to initialize element and directive state. In the world of Angular, the only role of attributes is to initialize element and directive state.
When you write a data binding, you're dealing exclusively with properties and eventsof the target object. When you write a data binding, you're dealing exclusively with properties and eventsof the target object.
HTML attributes effectively disappear.在 Angular 的世界中attribute 唯一的作用是用来初始化元素和指令的状态。 HTML attributes effectively disappear.
在 Angular 的世界中attribute 唯一的作用是用来初始化元素和指令的状态。
当进行数据绑定时,只是在与元素和指令的 property 和事件打交道,而 attribute 就完全靠边站了。 当进行数据绑定时,只是在与元素和指令的 property 和事件打交道,而 attribute 就完全靠边站了。
:marked :marked
With this model firmly in mind, read on to learn about binding targets. With this model firmly in mind, read on to learn about binding targets.
@ -943,8 +956,11 @@ a#property-binding
当要把视图元素的属性 (property) 设置为[模板表达式](#template-expressions)时,就要写模板的**属性 (property) 绑定**。 当要把视图元素的属性 (property) 设置为[模板表达式](#template-expressions)时,就要写模板的**属性 (property) 绑定**。
The most common property binding sets an element property to a component property value. An example is The most common property binding sets an element property to a component property value. An example is
binding the `src` property of an image element to a component's `heroImageUrl` property:最常用的属性绑定是把元素属性设置为组件属性的值。 binding the `src` property of an image element to a component's `heroImageUrl` property:
最常用的属性绑定是把元素属性设置为组件属性的值。
下面这个例子中image 元素的`src`属性会被绑定到组件的`heroImageUrl`属性上: 下面这个例子中image 元素的`src`属性会被绑定到组件的`heroImageUrl`属性上:
+makeExample('template-syntax/ts/src/app/app.component.html', 'property-binding-1')(format=".") +makeExample('template-syntax/ts/src/app/app.component.html', 'property-binding-1')(format=".")
:marked :marked
@ -1043,9 +1059,12 @@ a#property-binding
:marked :marked
Technically, Angular is matching the name to a directive [input](#inputs-outputs), Technically, Angular is matching the name to a directive [input](#inputs-outputs),
one of the property names listed in the directive's `inputs` array or a property decorated with `@Input()`. one of the property names listed in the directive's `inputs` array or a property decorated with `@Input()`.
Such inputs map to the directive's own properties.严格来说Angular 正在匹配指令的[输入属性](#inputs-outputs)的名字。 Such inputs map to the directive's own properties.
严格来说Angular 正在匹配指令的[输入属性](#inputs-outputs)的名字。
这个名字是指令的`inputs`数组中所列的名字,或者是带有`@Input()`装饰器的属性。 这个名字是指令的`inputs`数组中所列的名字,或者是带有`@Input()`装饰器的属性。
这些输入属性被映射为指令自己的属性。 这些输入属性被映射为指令自己的属性。
:marked :marked
If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error. If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error.
@ -1089,7 +1108,12 @@ a#property-binding
模板表达式应该返回目标属性所需类型的值。 模板表达式应该返回目标属性所需类型的值。
如果目标属性想要个字符串,就返回字符串。 如果目标属性想要个字符串,就返回字符串。
如果目标属性想要个数字,就返回数字。 如果目标属性想要个数字,就返回数字。
如果目标属性想要个对象就返回对象。The `hero` property of the `HeroDetail` component expects a `Hero` object, which is exactly what you're sending in the property binding:`HeroDetail`组件的`hero`属性想要一个`Hero`对象,那就在属性绑定中精确地给它一个`Hero`对象: 如果目标属性想要个对象,就返回对象。
The `hero` property of the `HeroDetail` component expects a `Hero` object, which is exactly what you're sending in the property binding:
`HeroDetail`组件的`hero`属性想要一个`Hero`对象,那就在属性绑定中精确地给它一个`Hero`对象:
+makeExample('template-syntax/ts/src/app/app.component.html', 'property-binding-4')(format=".") +makeExample('template-syntax/ts/src/app/app.component.html', 'property-binding-4')(format=".")
:marked :marked
@ -1271,7 +1295,10 @@ code-example(language="html").
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr> <tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
:marked :marked
And you get this error:会得到这个错误: And you get this error:
会得到这个错误:
code-example(format="nocode"). code-example(format="nocode").
Template parse errors: Template parse errors:
Can't bind to 'colspan' since it isn't a known native property Can't bind to 'colspan' since it isn't a known native property

View File

@ -154,6 +154,7 @@ a#top
* <live-example embedded-style>The sample application to be tested</live-example>. * <live-example embedded-style>The sample application to be tested</live-example>.
* <live-example plnkr="app-specs" embedded-style>All specs that test the sample application</live-example>. * <live-example plnkr="app-specs" embedded-style>All specs that test the sample application</live-example>.
* <live-example plnkr="bag-specs" embedded-style>A grab bag of additional specs</live-example>. * <live-example plnkr="bag-specs" embedded-style>A grab bag of additional specs</live-example>.
a(href="#top").to-top Back to top a(href="#top").to-top Back to top
a(href="#top").to-top 回到顶部 a(href="#top").to-top 回到顶部
@ -206,7 +207,9 @@ a#tools-and-tech
You can write and run Angular tests with a variety of tools and technologies. You can write and run Angular tests with a variety of tools and technologies.
This guide describes specific choices that are known to work well. This guide describes specific choices that are known to work well.
你可以用多种工具和技术来编写和运行Angular测试程序。本章介绍了一些大家已经知道能良好工作的选择。 你可以用多种工具和技术来编写和运行Angular测试程序。本章介绍了一些大家已经知道能良好工作的选择。
table(width="100%") table(width="100%")
col(width="20%") col(width="20%")
col(width="80%") col(width="80%")
@ -359,9 +362,11 @@ a#run-karma
### Run with karma ### Run with karma
### 运行Karma ### 运行Karma
Compile and run it in karma from the command line using the following command: Compile and run it in karma from the command line using the following command:
使用下面的命令从命令行中编译并在`Karma`中运行上面的测试程序。 使用下面的命令从命令行中编译并在`Karma`中运行上面的测试程序。
code-example(format="." language="bash"). code-example(format="." language="bash").
npm test npm test
:marked :marked
@ -608,8 +613,10 @@ a#component-fixture
A _predicate_ is a function that returns a boolean. A _predicate_ is a function that returns a boolean.
A query predicate receives a `DebugElement` and returns `true` if the element meets the selection criteria. A query predicate receives a `DebugElement` and returns `true` if the element meets the selection criteria.
**predicate**是返回布尔值的函数。 **predicate**是返回布尔值的函数。
predicate查询接受`DebugElement`参数,如果元素符合选择条件便返回`true`。 predicate查询接受`DebugElement`参数,如果元素符合选择条件便返回`true`。
:marked :marked
The **`By`** class is an Angular testing utility that produces useful predicates. The **`By`** class is an Angular testing utility that produces useful predicates.
Its `By.css` static method produces a Its `By.css` static method produces a
@ -696,14 +703,19 @@ a#auto-detect-changes
Some testers prefer that the Angular test environment run change detection automatically. Some testers prefer that the Angular test environment run change detection automatically.
That's possible by configuring the `TestBed` with the `ComponentFixtureAutoDetect` provider . That's possible by configuring the `TestBed` with the `ComponentFixtureAutoDetect` provider .
First import itfrom the testing utility library : First import itfrom the testing utility library :
+makeExample('testing/ts/src/app/banner.component.detect-changes.spec.ts', 'import-ComponentFixtureAutoDetect', 'src/app/banner.component.detect-changes.spec.ts (import)')(format='.') +makeExample('testing/ts/src/app/banner.component.detect-changes.spec.ts', 'import-ComponentFixtureAutoDetect', 'src/app/banner.component.detect-changes.spec.ts (import)')(format='.')
:marked :marked
Then add it to the `providers` array of the testing module configuration: Then add it to the `providers` array of the testing module configuration:
+makeExample('testing/ts/src/app/banner.component.detect-changes.spec.ts', 'auto-detect', 'src/app/banner.component.detect-changes.spec.ts (AutoDetect)')(format='.') +makeExample('testing/ts/src/app/banner.component.detect-changes.spec.ts', 'auto-detect', 'src/app/banner.component.detect-changes.spec.ts (AutoDetect)')(format='.')
:marked :marked
Here are three tests that illustrate how automatic change detection works. Here are three tests that illustrate how automatic change detection works.
+makeExample('testing/ts/src/app/banner.component.detect-changes.spec.ts', 'auto-detect-tests', 'src/app/banner.component.detect-changes.spec.ts (AutoDetect Tests)')(format='.') +makeExample('testing/ts/src/app/banner.component.detect-changes.spec.ts', 'auto-detect-tests', 'src/app/banner.component.detect-changes.spec.ts (AutoDetect Tests)')(format='.')
:marked :marked
The first test shows the benefit of automatic change detection. The first test shows the benefit of automatic change detection.
@ -854,6 +866,7 @@ a#component-with-dependency
## Test a component with a dependency ## Test a component with a dependency
## 测试有依赖的组件 ## 测试有依赖的组件
Components often have service dependencies. Components often have service dependencies.
The `WelcomeComponent` displays a welcome message to the logged in user. The `WelcomeComponent` displays a welcome message to the logged in user.
@ -870,11 +883,14 @@ a#component-with-dependency
`WelcomeComponent`有与服务进行交互的决策逻辑这样的逻辑让这个组件值得测试。下面是spec文件的测试模块配置`src/app/welcome.component.spec.ts` `WelcomeComponent`有与服务进行交互的决策逻辑这样的逻辑让这个组件值得测试。下面是spec文件的测试模块配置`src/app/welcome.component.spec.ts`
+makeExample('testing/ts/src/app/welcome.component.spec.ts', 'config-test-module', 'src/app/welcome.component.spec.ts')(format='.') +makeExample('testing/ts/src/app/welcome.component.spec.ts', 'config-test-module', 'src/app/welcome.component.spec.ts')(format='.')
:marked :marked
This time, in addition to declaring the _component-under-test_, This time, in addition to declaring the _component-under-test_,
the configuration adds a `UserService` provider to the `providers` list. the configuration adds a `UserService` provider to the `providers` list.
But not the real `UserService`. But not the real `UserService`.
这次,在测试配置里不但声明了被测试的组件,而且在`providers`数组中添加了`UserService`依赖。但不是真实的`UserService`。 这次,在测试配置里不但声明了被测试的组件,而且在`providers`数组中添加了`UserService`依赖。但不是真实的`UserService`。
a#service-test-doubles a#service-test-doubles
:marked :marked
### Provide service test doubles ### Provide service test doubles
@ -1051,9 +1067,14 @@ a#component-with-async-service
It is sufficient to see within `ngOnInit` that `twainService.getQuote` returns a promise, which means it is asynchronous. It is sufficient to see within `ngOnInit` that `twainService.getQuote` returns a promise, which means it is asynchronous.
`TwainService`的实现细节现在并不重要。 `TwainService`的实现细节现在并不重要。
`ngOnInit`的`twainService.getQuote`返回承诺所以显然它是异步的。In general, tests should not make calls to remote servers. `ngOnInit`的`twainService.getQuote`返回承诺,所以显然它是异步的。
They should emulate such calls. The setup in this `src/app/shared/twain.component.spec.ts` shows one way to do that: 一般来讲,测试程序不应该向远程服务器发请求。
In general, tests should not make calls to remote servers.
They should emulate such calls. The setup in this `src/app/shared/twain.component.spec.ts` shows one way to do that:
一般来讲,测试程序不应该向远程服务器发请求。
它们应该仿真这样的请求。`src/app/shared/twain.component.spec.ts`里的配置是其中一种伪造方法: 它们应该仿真这样的请求。`src/app/shared/twain.component.spec.ts`里的配置是其中一种伪造方法:
+makeExample('testing/ts/src/app/shared/twain.component.spec.ts', 'setup', 'src/app/shared/twain.component.spec.ts (setup)')(format='.') +makeExample('testing/ts/src/app/shared/twain.component.spec.ts', 'setup', 'src/app/shared/twain.component.spec.ts (setup)')(format='.')
a#service-spy a#service-spy
@ -1070,6 +1091,7 @@ a#service-spy
但是与其伪造服务对象,它注入了真实的服务(参见测试模块的`providers`并用Jasmine的`spy`替换关键的`getQuote`方法。 但是与其伪造服务对象,它注入了真实的服务(参见测试模块的`providers`并用Jasmine的`spy`替换关键的`getQuote`方法。
+makeExample('testing/ts/src/app/shared/twain.component.spec.ts', 'spy')(format='.') +makeExample('testing/ts/src/app/shared/twain.component.spec.ts', 'spy')(format='.')
:marked :marked
The spy is designed such that any call to `getQuote` receives an immediately resolved promise with a test quote. The spy is designed such that any call to `getQuote` receives an immediately resolved promise with a test quote.
The spy bypasses the actual `getQuote` method and therefore does not contact the server. The spy bypasses the actual `getQuote` method and therefore does not contact the server.
@ -1109,8 +1131,10 @@ a#sync-tests
Neither test can prove that a value from the service is displayed. Neither test can prove that a value from the service is displayed.
The quote itself has not arrived, despite the fact that the spy returns a resolved promise. The quote itself has not arrived, despite the fact that the spy returns a resolved promise.
两者都不能证明被显示的值是服务提供的。 两者都不能证明被显示的值是服务提供的。
虽然spy返回了解析的承诺名言本身还没有到来。 虽然spy返回了解析的承诺名言本身还没有到来。
This test must wait at least one full turn of the JavaScript engine before the This test must wait at least one full turn of the JavaScript engine before the
value becomes available. The test must become _asynchronous_. value becomes available. The test must become _asynchronous_.
@ -1120,7 +1144,7 @@ a#async
:marked :marked
### The _async_ function in _it_ ### The _async_ function in _it_
## **it**里的**async**函数方法 ### **it**里的**async**函数方法
Notice the `async` in the third test. Notice the `async` in the third test.
@ -1149,7 +1173,7 @@ a#when-stable
:marked :marked
### _whenStable_ ### _whenStable_
## **whenStable** ### **whenStable**
The test must wait for the `getQuote` promise to resolve in the next turn of the JavaScript engine. The test must wait for the `getQuote` promise to resolve in the next turn of the JavaScript engine.
@ -1184,7 +1208,7 @@ a#fake-async
:marked :marked
### The _fakeAsync_ function ### The _fakeAsync_ function
## **fakeAsync**函数方法 ### **fakeAsync**函数方法
The fourth test verifies the same component behavior in a different way. The fourth test verifies the same component behavior in a different way.
@ -1224,7 +1248,8 @@ a#tick
:marked :marked
### The _tick_ function ### The _tick_ function
## **tick**函数 ### **tick**函数
The `tick` function is one of the Angular testing utilities and a companion to `fakeAsync`. The `tick` function is one of the Angular testing utilities and a companion to `fakeAsync`.
You can only call it within a `fakeAsync` body. You can only call it within a `fakeAsync` body.
@ -1252,6 +1277,7 @@ a#tick
a#jasmine-done a#jasmine-done
:marked :marked
### _jasmine.done_ ### _jasmine.done_
While the `async` and `fakeAsync` functions greatly While the `async` and `fakeAsync` functions greatly
simplify Angular asynchronous testing, simplify Angular asynchronous testing,
you can still fall back to the traditional Jasmine asynchronous testing technique. you can still fall back to the traditional Jasmine asynchronous testing technique.
@ -1268,7 +1294,9 @@ a#jasmine-done
Here is a `done` version of the previous two tests: Here is a `done` version of the previous two tests:
下面是上面两个测试程序的`done`版本: 下面是上面两个测试程序的`done`版本:
+makeExample('testing/ts/src/app/shared/twain.component.spec.ts', 'done-test', 'src/app/shared/twain.component.spec.ts (done test)')(format='.') +makeExample('testing/ts/src/app/shared/twain.component.spec.ts', 'done-test', 'src/app/shared/twain.component.spec.ts (done test)')(format='.')
:marked :marked
Although there is no direct access to the `getQuote` promise inside `TwainComponent`, Although there is no direct access to the `getQuote` promise inside `TwainComponent`,
the spy has direct access, which makes it possible to wait for `getQuote` to finish. the spy has direct access, which makes it possible to wait for `getQuote` to finish.
@ -1293,6 +1321,7 @@ a#component-with-input-output
## Test a component with inputs and outputs ## Test a component with inputs and outputs
## 测试带有导入inputs和导出outputs的组件 ## 测试带有导入inputs和导出outputs的组件
A component with inputs and outputs typically appears inside the view template of a host component. A component with inputs and outputs typically appears inside the view template of a host component.
The host uses a property binding to set the input property and an event binding to The host uses a property binding to set the input property and an event binding to
listen to events raised by the output property. listen to events raised by the output property.
@ -1322,12 +1351,15 @@ a#component-with-input-output
:marked :marked
The `DashboardHeroComponent` appears in an `*ngFor` repeater, which sets each component's `hero` input property The `DashboardHeroComponent` appears in an `*ngFor` repeater, which sets each component's `hero` input property
to the looping value and listens for the component's `selected` event. to the looping value and listens for the component's `selected` event.
`DashboardHeroComponent`在`*ngFor`循环中出现,设置每个组件的`hero`input属性到迭代的值并监听组件的`selected`事件。 `DashboardHeroComponent`在`*ngFor`循环中出现,设置每个组件的`hero`input属性到迭代的值并监听组件的`selected`事件。
Here's the component's definition: Here's the component's definition:
下面是组件的定义: 下面是组件的定义:
+makeExample('testing/ts/src/app/dashboard/dashboard-hero.component.ts', 'component', 'src/app/dashboard/dashboard-hero.component.ts (component)')(format='.') +makeExample('testing/ts/src/app/dashboard/dashboard-hero.component.ts', 'component', 'src/app/dashboard/dashboard-hero.component.ts (component)')(format='.')
:marked :marked
While testing a component this simple has little intrinsic value, it's worth knowing how. While testing a component this simple has little intrinsic value, it's worth knowing how.
You can use one of these approaches: You can use one of these approaches:
@ -1411,7 +1443,9 @@ a#dashboard-standalone
它验证了英雄名字通过绑定被传递到模板了。这里有个额外步骤。模板将英雄名字传给Angular的`UpperCasePipe` 它验证了英雄名字通过绑定被传递到模板了。这里有个额外步骤。模板将英雄名字传给Angular的`UpperCasePipe`
所以测试程序必须使用大写名字来匹配元素的值: 所以测试程序必须使用大写名字来匹配元素的值:
+makeExample('testing/ts/src/app/dashboard/dashboard-hero.component.html')(format='.') +makeExample('testing/ts/src/app/dashboard/dashboard-hero.component.html')(format='.')
:marked :marked
.alert.is-helpful .alert.is-helpful
:marked :marked
@ -1437,12 +1471,16 @@ a#dashboard-standalone
The `heroEl` is a `DebugElement` that represents the hero `<div>`. The `heroEl` is a `DebugElement` that represents the hero `<div>`.
The test calls `triggerEventHandler` with the "click" event name. The test calls `triggerEventHandler` with the "click" event name.
The "click" event binding responds by calling `DashboardHeroComponent.click()`. The "click" event binding responds by calling `DashboardHeroComponent.click()`.
`heroEl`是个`DebugElement`,它代表了英雄所在的`<div>`。 `heroEl`是个`DebugElement`,它代表了英雄所在的`<div>`。
测试程序用"click"事件名字来调用`triggerEventHandler`。 测试程序用"click"事件名字来调用`triggerEventHandler`。
调用`DashboardHeroComponent.click()`时,"click"事件绑定作出响应。 调用`DashboardHeroComponent.click()`时,"click"事件绑定作出响应。
If the component behaves as expected, `click()` tells the component's `selected` property to emit the `hero` object, If the component behaves as expected, `click()` tells the component's `selected` property to emit the `hero` object,
the test detects that value through its subscription to `selected`, and the test should pass. the test detects that value through its subscription to `selected`, and the test should pass.
如果组件想期待的那样工作,`click()`通知组件的`selected`属性发出`hero`对象,测试程序通过订阅`selected`事件而检测到这个值,所以测试应该成功。
如果组件像期待的那样工作,`click()`通知组件的`selected`属性就会发出`hero`对象,测试程序通过订阅`selected`事件而检测到这个值,所以测试应该成功。
a#trigger-event-handler a#trigger-event-handler
:marked :marked
### _triggerEventHandler_ ### _triggerEventHandler_
@ -1484,6 +1522,7 @@ a#click-helper
点击按钮、链接或者任意HTML元素是很常见的测试任务。 点击按钮、链接或者任意HTML元素是很常见的测试任务。
把**click触发**过程封装到辅助方法中可以简化这个任务,比如下面的`click`辅助方法: 把**click触发**过程封装到辅助方法中可以简化这个任务,比如下面的`click`辅助方法:
+makeExample('testing/ts/src/testing/index.ts', 'click-event', 'testing/index.ts (click helper)')(format='.') +makeExample('testing/ts/src/testing/index.ts', 'click-event', 'testing/index.ts (click helper)')(format='.')
:marked :marked
@ -1618,6 +1657,7 @@ a#routed-component
Fortunately, the `DashboardComponent` isn't doing much with the `Router` Fortunately, the `DashboardComponent` isn't doing much with the `Router`
幸运的是,`DashbaordComponent`没有使用`Router`做很多事情。 幸运的是,`DashbaordComponent`没有使用`Router`做很多事情。
+makeExample('testing/ts/src/app/dashboard/dashboard.component.ts', 'goto-detail', 'src/app/dashboard/dashboard.component.ts (goToDetail)')(format='.') +makeExample('testing/ts/src/app/dashboard/dashboard.component.ts', 'goto-detail', 'src/app/dashboard/dashboard.component.ts (goToDetail)')(format='.')
:marked :marked
@ -1628,17 +1668,22 @@ a#routed-component
通常都是这样的。原则上,你测试的是组件,不是路由器,应该只关心在指定的条件下,组件是否导航到正确的地址。 通常都是这样的。原则上,你测试的是组件,不是路由器,应该只关心在指定的条件下,组件是否导航到正确的地址。
用模拟类来替换路由器是一种简单的方案。下面的代码应该可以: 用模拟类来替换路由器是一种简单的方案。下面的代码应该可以:
+makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'router-stub', 'src/app/dashboard/dashboard.component.spec.ts (Router Stub)')(format='.') +makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'router-stub', 'src/app/dashboard/dashboard.component.spec.ts (Router Stub)')(format='.')
:marked :marked
Now set up the testing module with the test stubs for the `Router` and `HeroService`, and Now set up the testing module with the test stubs for the `Router` and `HeroService`, and
create a test instance of the `DashboardComponent` for subsequent testing. create a test instance of the `DashboardComponent` for subsequent testing.
现在我们来利用`Router`和`HeroService`的测试stub类来配置测试模块并为接下来的测试创建`DashboardComponent`的测试实例。 现在我们来利用`Router`和`HeroService`的测试stub类来配置测试模块并为接下来的测试创建`DashboardComponent`的测试实例。
+makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'compile-and-create-body', 'src/app/dashboard/dashboard.component.spec.ts (compile and create)')(format='.') +makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'compile-and-create-body', 'src/app/dashboard/dashboard.component.spec.ts (compile and create)')(format='.')
:marked :marked
The following test clicks the displayed hero and confirms (with the help of a spy) that `Router.navigateByUrl` is called with the expected url. The following test clicks the displayed hero and confirms (with the help of a spy) that `Router.navigateByUrl` is called with the expected url.
下面的测试程序点击显示的英雄并利用spy来确认`Router.navigateByUrl`被调用了而且传进的url是所期待的值。 下面的测试程序点击显示的英雄并利用spy来确认`Router.navigateByUrl`被调用了而且传进的url是所期待的值。
+makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'navigate-test', 'src/app/dashboard/dashboard.component.spec.ts (navigate test)')(format='.') +makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'navigate-test', 'src/app/dashboard/dashboard.component.spec.ts (navigate test)')(format='.')
@ -1651,7 +1696,9 @@ a#inject
Notice the `inject` function in the second `it` argument. Notice the `inject` function in the second `it` argument.
注意第二个`it`参数里面的`inject`函数。 注意第二个`it`参数里面的`inject`函数。
+makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'inject')(format='.') +makeExample('testing/ts/src/app/dashboard/dashboard.component.spec.ts', 'inject')(format='.')
:marked :marked
The `inject` function is one of the Angular testing utilities. The `inject` function is one of the Angular testing utilities.
It injects services into the test function where you can alter, spy on, and manipulate them. It injects services into the test function where you can alter, spy on, and manipulate them.
@ -1673,7 +1720,9 @@ a#inject
.callout.is-important .callout.is-important
header inject uses the TestBed Injector header inject uses the TestBed Injector
header 使用TestBed注入器来注入 header 使用TestBed注入器来注入
:marked :marked
The `inject` function uses the current `TestBed` injector and can only return services provided at that level. The `inject` function uses the current `TestBed` injector and can only return services provided at that level.
It does not return services from component providers. It does not return services from component providers.
@ -1895,12 +1944,14 @@ a#page-object
figure.image-display figure.image-display
img(src='/resources/images/devguide/testing/hero-detail.component.png' alt="HeroDetailComponent in action") img(src='/resources/images/devguide/testing/hero-detail.component.png' alt="HeroDetailComponent in action")
:marked :marked
But there's already plenty of template complexity. But there's already plenty of template complexity.
但是它已经有很多模板复杂性。 但是它已经有很多模板复杂性。
+makeExample('testing/ts/src/app/hero/hero-detail.component.html', '', 'src/app/hero/hero-detail.component.html')(format='.') +makeExample('testing/ts/src/app/hero/hero-detail.component.html', '', 'src/app/hero/hero-detail.component.html')(format='.')
:marked :marked
To fully exercise the component, the test needs a lot of setup: To fully exercise the component, the test needs a lot of setup:
@ -2014,6 +2065,7 @@ a#import-module
One approach is to configure the testing module from the individual pieces as in this example: One approach is to configure the testing module from the individual pieces as in this example:
一种方法是在测试模块中一一配置,就像这样: 一种方法是在测试模块中一一配置,就像这样:
+makeExample('testing/ts/src/app/hero/hero-detail.component.spec.ts', 'setup-forms-module', 'src/app/hero/hero-detail.component.spec.ts (FormsModule setup)')(format='.') +makeExample('testing/ts/src/app/hero/hero-detail.component.spec.ts', 'setup-forms-module', 'src/app/hero/hero-detail.component.spec.ts (FormsModule setup)')(format='.')
:marked :marked
@ -2043,6 +2095,7 @@ a#feature-module-import
`HeroDetailComponent`是`HeroModule`[特征模块](ngmodule.html#feature-modules)的一部分,它组合了更多互相依赖的部件,包括`SharedModule`。 `HeroDetailComponent`是`HeroModule`[特征模块](ngmodule.html#feature-modules)的一部分,它组合了更多互相依赖的部件,包括`SharedModule`。
试试下面这个导入`HeroModule`的测试配置: 试试下面这个导入`HeroModule`的测试配置:
+makeExample('testing/ts/src/app/hero/hero-detail.component.spec.ts', 'setup-hero-module', 'src/app/hero/hero-detail.component.spec.ts (HeroModule setup)')(format='.') +makeExample('testing/ts/src/app/hero/hero-detail.component.spec.ts', 'setup-hero-module', 'src/app/hero/hero-detail.component.spec.ts (HeroModule setup)')(format='.')
:marked :marked
@ -2287,12 +2340,17 @@ a#stub-component
* The real `RouterOutlet` is complex and errors easily. * The real `RouterOutlet` is complex and errors easily.
The `RouterOutletStubComponent` (in `testing/router-stubs.ts`) is safely inert. The `RouterOutletStubComponent` (in `testing/router-stubs.ts`) is safely inert.
真实的`RouterOutlet`很复杂而且容易出错。
真实的`RouterOutlet`很复杂而且容易出错。
`testing/router-stubs.ts`里的`RouterOutletStubComponent`是安全的替代品。 `testing/router-stubs.ts`里的`RouterOutletStubComponent`是安全的替代品。
The component stubs are essential. The component stubs are essential.
Without them, the Angular compiler doesn't recognize the `<app-welcome>` and `<router-outlet>` tags Without them, the Angular compiler doesn't recognize the `<app-welcome>` and `<router-outlet>` tags
and throws an error. 组件stub替代品很关键。 and throws an error.
组件stub替代品很关键。
没有它们Angular编译器无法识别`<app-welcome`和`<router-outlet>`标签,抛出错误。 没有它们Angular编译器无法识别`<app-welcome`和`<router-outlet>`标签,抛出错误。
a#router-link-stub a#router-link-stub
:marked :marked
### Stubbing the _RouterLink_ ### Stubbing the _RouterLink_
@ -2353,9 +2411,11 @@ a#app-component-tests
It works hard to appear useful when in fact it It works hard to appear useful when in fact it
tests the `RouterLinkStubDirective` rather than the _component_. tests the `RouterLinkStubDirective` rather than the _component_.
This is a common failing of directive stubs. This is a common failing of directive stubs.
本例中的“click”测试程序其实毫无价值。 本例中的“click”测试程序其实毫无价值。
它显得很有用,但是事实上,它测试的是`RouterLinkStubDirective`,而非测试组件。 它显得很有用,但是事实上,它测试的是`RouterLinkStubDirective`,而非测试组件。
这是指令stub的通病。 这是指令stub的通病。
It has a legitimate purpose in this guide. It has a legitimate purpose in this guide.
It demonstrates how to find a `RouterLink` element, click it, and inspect a result, It demonstrates how to find a `RouterLink` element, click it, and inspect a result,
without engaging the full router machinery. without engaging the full router machinery.
@ -2393,9 +2453,15 @@ a#why-stubbed-routerlink-tests
A _different_ battery of tests can explore whether the application navigates as expected A _different_ battery of tests can explore whether the application navigates as expected
in the presence of conditions that influence guards such as whether the user is authenticated and authorized. in the presence of conditions that influence guards such as whether the user is authenticated and authorized.
不同的测试程序可以探索在不同条件下(比如像检查用户是否认证),该应用是否和期望的那样导航。
.alert.is-helpful .alert.is-helpful
:marked A future guide update will explain how to write such tests with the `RouterTestingModule`.不同的测试程序可以探索在不同条件下(比如像检查用户是否认证),该应用是否和期望的那样导航。 :marked
未来本章的更新将介绍如何使用`RouterTestingModule`来编写这样的测试程序。 A future guide update will explain how to write such tests with the `RouterTestingModule`.
未来本章的更新将介绍如何使用`RouterTestingModule`来编写这样的测试程序。
a(href="#top").to-top Back to top a(href="#top").to-top Back to top
a(href="#top").to-top 回到顶部 a(href="#top").to-top 回到顶部
.l-hr .l-hr
@ -2408,7 +2474,9 @@ a#shallow-component-test
The [previous setup](#stub-component) declared the `BannerComponent` and stubbed two other components The [previous setup](#stub-component) declared the `BannerComponent` and stubbed two other components
for _no reason other than to avoid a compiler error_. for _no reason other than to avoid a compiler error_.
[以前的配置](#stub-component)声明了`BannerComponent`并stub伪造了两个其它组件**仅仅是为了避免编译错误,不是为别的原因**。 [以前的配置](#stub-component)声明了`BannerComponent`并stub伪造了两个其它组件**仅仅是为了避免编译错误,不是为别的原因**。
Without them, the Angular compiler doesn't recognize the `<app-banner>`, `<app-welcome>` and `<router-outlet>` tags Without them, the Angular compiler doesn't recognize the `<app-banner>`, `<app-welcome>` and `<router-outlet>` tags
in the [_app.component.html_](#app-component-html) template and throws an error. in the [_app.component.html_](#app-component-html) template and throws an error.
@ -2417,17 +2485,20 @@ a#shallow-component-test
Add `NO_ERRORS_SCHEMA` to the testing module's `schemas` metadata Add `NO_ERRORS_SCHEMA` to the testing module's `schemas` metadata
to tell the compiler to ignore unrecognized elements and attributes. to tell the compiler to ignore unrecognized elements and attributes.
You no longer have to declare irrelevant components and directives. You no longer have to declare irrelevant components and directives.
添加`NO_ERRORS_SCHEMA`到测试模块的`schemas`元数据中,告诉编译器忽略不认识的元素和属性。 添加`NO_ERRORS_SCHEMA`到测试模块的`schemas`元数据中,告诉编译器忽略不认识的元素和属性。
这样你不再需要声明无关组件和指令。 这样你不再需要声明无关组件和指令。
These tests are ***shallow*** because they only "go deep" into the components you want to test. These tests are ***shallow*** because they only "go deep" into the components you want to test.
Here is a setup, with `import` statements, that demonstrates the improved simplicity of _shallow_ tests, relative to the stubbing setup. Here is a setup, with `import` statements, that demonstrates the improved simplicity of _shallow_ tests, relative to the stubbing setup.
这些测试程序比较**浅**,因为它们只“深入”到你要测试的组件。 这些测试程序比较**浅**,因为它们只“深入”到你要测试的组件。
这里是一套配置(拥有`import`语句体现了相比使用stub伪造的配置来说**浅**测试程序的简单性。 这里是一套配置(拥有`import`语句体现了相比使用stub伪造的配置来说**浅**测试程序的简单性。
+makeTabs('testing/ts/src/app/app.component.spec.ts, testing/ts/src/app/app.component.spec.ts', +makeTabs('testing/ts/src/app/app.component.spec.ts, testing/ts/src/app/app.component.spec.ts',
'setup-schemas, setup-stubs-w-imports', 'setup-schemas, setup-stubs-w-imports',
'src/app/app.component.spec.ts (NO_ERRORS_SCHEMA), src/app/app.component.spec.ts (Stubs)')(format='.') 'src/app/app.component.spec.ts (NO_ERRORS_SCHEMA), src/app/app.component.spec.ts (Stubs)')(format='.')
:marked :marked
The _only_ declarations are the _component-under-test_ (`AppComponent`) and the `RouterLinkStubDirective` The _only_ declarations are the _component-under-test_ (`AppComponent`) and the `RouterLinkStubDirective`
that contributes actively to the tests. that contributes actively to the tests.
@ -2485,7 +2556,9 @@ a#attribute-directive
Finding and testing all components that use the directive is tedious, brittle, and almost as unlikely to afford full coverage. Finding and testing all components that use the directive is tedious, brittle, and almost as unlikely to afford full coverage.
但是,测试单一的用例一般无法探索该指令的全部能力。 但是,测试单一的用例一般无法探索该指令的全部能力。
查找和测试所有使用该指令的组件非常繁琐和脆弱,并且通常无法覆盖所有组件。[Isolated unit tests](#isolated-unit-tests) might be helpful, 查找和测试所有使用该指令的组件非常繁琐和脆弱,并且通常无法覆盖所有组件。
[Isolated unit tests](#isolated-unit-tests) might be helpful,
but attribute directives like this one tend to manipulate the DOM. but attribute directives like this one tend to manipulate the DOM.
Isolated unit tests don't touch the DOMand, therefore , Isolated unit tests don't touch the DOMand, therefore ,
do not inspire confidence in the directive's efficacy. do not inspire confidence in the directive's efficacy.
@ -2690,7 +2763,9 @@ a#services-with-dependencies
+makeExample('testing/ts/src/app/bag/bag.no-testbed.spec.ts', 'DependentService', 'src/app/bag/bag.no-testbed.spec.ts') +makeExample('testing/ts/src/app/bag/bag.no-testbed.spec.ts', 'DependentService', 'src/app/bag/bag.no-testbed.spec.ts')
:marked :marked
The first test creates a `FancyService` with `new` and passes it to the `DependentService` constructor. The first test creates a `FancyService` with `new` and passes it to the `DependentService` constructor.
第一个测试程序使用`new`创建`FancyService`实例,并将它传递给`DependentService`构造函数。 第一个测试程序使用`new`创建`FancyService`实例,并将它传递给`DependentService`构造函数。
However, it's rarely that simple. The injected service can be difficult to create or control. However, it's rarely that simple. The injected service can be difficult to create or control.
You can mock the dependency, use a dummy value, or stub the pertinent service method You can mock the dependency, use a dummy value, or stub the pertinent service method
with a substitute method that 's easy to control. with a substitute method that 's easy to control.
@ -2720,15 +2795,19 @@ a#isolated-pipe-tests
The `transform` implementation rarely interacts with the DOM. The `transform` implementation rarely interacts with the DOM.
Most pipes have no dependence on Angular other than the `@Pipe` Most pipes have no dependence on Angular other than the `@Pipe`
metadata and an interface. metadata and an interface.
管道类有一个方法,`transform`,用来转换输入值到输出值。 管道类有一个方法,`transform`,用来转换输入值到输出值。
`transform`的实现很少与DOM交互。 `transform`的实现很少与DOM交互。
除了`@Pipe`元数据和一个接口外大部分管道不依赖Angular。 除了`@Pipe`元数据和一个接口外大部分管道不依赖Angular。
Consider a `TitleCasePipe` that capitalizes the first letter of each word. Consider a `TitleCasePipe` that capitalizes the first letter of each word.
Here's a naive implementation with a regular expression. Here's a naive implementation with a regular expression.
假设`TitleCasePipe`将每个单词的第一个字母变成大写。 假设`TitleCasePipe`将每个单词的第一个字母变成大写。
下面是使用正则表达式实现的简单代码: 下面是使用正则表达式实现的简单代码:
+makeExample('testing/ts/src/app/shared/title-case.pipe.ts', '', 'src/app/shared/title-case.pipe.ts')(format='.') +makeExample('testing/ts/src/app/shared/title-case.pipe.ts', '', 'src/app/shared/title-case.pipe.ts')(format='.')
:marked :marked
Anything that uses a regular expression is worth testing thoroughly. Anything that uses a regular expression is worth testing thoroughly.
Use simple Jasmine to explore the expected cases and the edge cases. Use simple Jasmine to explore the expected cases and the edge cases.
@ -2743,6 +2822,7 @@ a#write-tests
### Write Angular tests too ### Write Angular tests too
#### 同时也编写Angular测试 #### 同时也编写Angular测试
These are tests of the pipe _in isolation_. These are tests of the pipe _in isolation_.
They can't tell if the `TitleCasePipe` is working properly as applied in the application components. They can't tell if the `TitleCasePipe` is working properly as applied in the application components.
@ -2752,6 +2832,7 @@ a#write-tests
Consider adding component tests such as this one: Consider adding component tests such as this one:
考虑像这样添加组件测试程序: 考虑像这样添加组件测试程序:
+makeExample('testing/ts/src/app/hero/hero-detail.component.spec.ts', 'title-case-pipe', 'src/app/hero/hero-detail.component.spec.ts (pipe test)') +makeExample('testing/ts/src/app/hero/hero-detail.component.spec.ts', 'title-case-pipe', 'src/app/hero/hero-detail.component.spec.ts (pipe test)')
a#isolated-component-tests a#isolated-component-tests
@ -2769,12 +2850,15 @@ a#isolated-component-tests
Consider this `ButtonComp` component. Consider this `ButtonComp` component.
考虑这个`ButtonComp`组件。 考虑这个`ButtonComp`组件。
+makeExample('testing/ts/src/app/bag/bag.ts', 'ButtonComp', 'src/app/bag/bag.ts (ButtonComp)')(format='.') +makeExample('testing/ts/src/app/bag/bag.ts', 'ButtonComp', 'src/app/bag/bag.ts (ButtonComp)')(format='.')
:marked :marked
The following Angular test demonstrates that clicking a button in the template leads The following Angular test demonstrates that clicking a button in the template leads
to an update of the on-screen message. to an update of the on-screen message.
下面的Angular测试演示点击模板里的按钮后引起了屏幕上的消息的更新。 下面的Angular测试演示点击模板里的按钮后引起了屏幕上的消息的更新。
+makeExample('testing/ts/src/app/bag/bag.spec.ts', 'ButtonComp', 'src/app/bag/bag.spec.ts (ButtonComp)')(format='.') +makeExample('testing/ts/src/app/bag/bag.spec.ts', 'ButtonComp', 'src/app/bag/bag.spec.ts (ButtonComp)')(format='.')
:marked :marked
@ -2903,8 +2987,10 @@ table
:marked :marked
When a `fakeAsync` test ends with pending timer event _tasks_ (queued `setTimeOut` and `setInterval` callbacks), When a `fakeAsync` test ends with pending timer event _tasks_ (queued `setTimeOut` and `setInterval` callbacks),
the test fails with a clear error message. the test fails with a clear error message.
当`fakeAsync`测试程序以正在运行的计时器事件**任务**(排队中的`setTimeOut`和`setInterval`的回调)结束时, 当`fakeAsync`测试程序以正在运行的计时器事件**任务**(排队中的`setTimeOut`和`setInterval`的回调)结束时,
测试会失败,并显示一条明确的错误信息。 测试会失败,并显示一条明确的错误信息。
In general, a test should end with no queued tasks. In general, a test should end with no queued tasks.
When pending timer tasks are expected, call `discardPeriodicTasks` to flush the _task_ queue When pending timer tasks are expected, call `discardPeriodicTasks` to flush the _task_ queue
and avoid the error. and avoid the error.
@ -2918,7 +3004,9 @@ table
:marked :marked
When a `fakeAsync` test ends with pending _micro-tasks_ such as unresolved promises, When a `fakeAsync` test ends with pending _micro-tasks_ such as unresolved promises,
the test fails with a clear error message. the test fails with a clear error message.
当`fakeAsync`测试程序以待执行**微任务**(比如未解析的承诺)结束时,测试会失败并显示明确的错误信息。 当`fakeAsync`测试程序以待执行**微任务**(比如未解析的承诺)结束时,测试会失败并显示明确的错误信息。
In general, a test should wait for micro-tasks to finish. In general, a test should wait for micro-tasks to finish.
When pending microtasks are expected, call `flushMicrotasks` to flush the _micro-task_ queue When pending microtasks are expected, call `flushMicrotasks` to flush the _micro-task_ queue
and avoid the error. and avoid the error.
@ -2993,7 +3081,9 @@ code-example(format="." language="javascript").
a#testbed-methods a#testbed-methods
:marked :marked
The `TestBed` API consists of static class methods that either update or reference a _global_ instance of the`TestBed`. The `TestBed` API consists of static class methods that either update or reference a _global_ instance of the`TestBed`.
`TestBed`的API包含了一系列静态类方法它们更新或者引用**全局**的`TestBed`实例。 `TestBed`的API包含了一系列静态类方法它们更新或者引用**全局**的`TestBed`实例。
Internally, all static methods cover methods of the current runtime `TestBed` instance , Internally, all static methods cover methods of the current runtime `TestBed` instance ,
which is also returned by the `getTestBed()` function. which is also returned by the `getTestBed()` function.
@ -3006,6 +3096,7 @@ a#testbed-methods
Here are the most important static methods, in order of likely utility. Here are the most important static methods, in order of likely utility.
这里列出了最重要的静态方法,以使用频率排序: 这里列出了最重要的静态方法,以使用频率排序:
table table
tr tr
th th
@ -3021,12 +3112,15 @@ table
The testing shims (`karma-test-shim`, `browser-test-shim`) The testing shims (`karma-test-shim`, `browser-test-shim`)
establish the [initial test environment](##testbed-initTestEnvironment) and a default testing module. establish the [initial test environment](##testbed-initTestEnvironment) and a default testing module.
The default testing module is configured with basic declaratives and some Angular service substitutes that every tester needs. The default testing module is configured with basic declaratives and some Angular service substitutes that every tester needs.
测试垫片(`karma-test-shim`, `browser-test-shim`)创建了[初始测试环境](##testbed-initTestEnvironment)和默认测试模块。 测试垫片(`karma-test-shim`, `browser-test-shim`)创建了[初始测试环境](##testbed-initTestEnvironment)和默认测试模块。
默认测试模块是使用基本声明和一些Angular服务替代品它们是所有测试程序都需要的。 默认测试模块是使用基本声明和一些Angular服务替代品它们是所有测试程序都需要的。
Call `configureTestingModule` to refine the testing module configuration for a particular set of tests Call `configureTestingModule` to refine the testing module configuration for a particular set of tests
by adding and removing imports, declarations (of components, directives, and pipes), and providers. by adding and removing imports, declarations (of components, directives, and pipes), and providers.
调用`configureTestingModule`来为一套特定的测试定义测试模块配置,添加和删除导入、(组件、指令和管道的)声明和服务提供商。 调用`configureTestingModule`来为一套特定的测试定义测试模块配置,添加和删除导入、(组件、指令和管道的)声明和服务提供商。
tr tr
td(style="vertical-align: top") <code>compileComponents</code> td(style="vertical-align: top") <code>compileComponents</code>
td td
@ -3181,7 +3275,9 @@ a#component-fixture-properties
#### _ComponentFixture_的属性 #### _ComponentFixture_的属性
Here are the most important properties for testers, in order of likely utility. Here are the most important properties for testers, in order of likely utility.
下面是对测试最重要的属性,以使用频率排序: 下面是对测试最重要的属性,以使用频率排序:
table table
tr tr
th th
@ -3398,7 +3494,9 @@ table
td td
:marked :marked
The element's own component instance, if it has one. The element's own component instance, if it has one.
元素自己的组件实例(如果有)。 tr
元素自己的组件实例(如果有)。
tr
td(style="vertical-align: top") <code>context</code> td(style="vertical-align: top") <code>context</code>
td td
:marked :marked

View File

@ -406,20 +406,27 @@ a(id="common-configuration")
.l-main-section .l-main-section
:marked :marked
### Common configuration ### Common configuration
### 通用配置 ### 通用配置
Developers typically have separate configurations for development, production, and test environments. Developers typically have separate configurations for development, production, and test environments.
All three have a lot of configuration in common. All three have a lot of configuration in common.
开发、生产、测试等不同的环境通常会分开配置,但实际上这些配置也有很多地方是通用的。 开发、生产、测试等不同的环境通常会分开配置,但实际上这些配置也有很多地方是通用的。
Gather the common configuration in a file called `webpack.common.js`. Gather the common configuration in a file called `webpack.common.js`.
我们可以把这些通用的配置收归到一个文件,命名为`webpack.common.js`。 我们可以把这些通用的配置收归到一个文件,命名为`webpack.common.js`。
+makeExample('webpack/ts/config/webpack.common.js', null, 'config/webpack.common.js')(format=".") +makeExample('webpack/ts/config/webpack.common.js', null, 'config/webpack.common.js')(format=".")
a#inside-webpack-commonjs a#inside-webpack-commonjs
:marked :marked
### Inside _webpack.common.js_ ### Inside _webpack.common.js_
### webpack.common.js解读 Webpack is a NodeJS-based tool that reads configuration from a JavaScript commonjs module file.
### webpack.common.js解读
Webpack is a NodeJS-based tool that reads configuration from a JavaScript commonjs module file.
Webpack是基于NodeJS的一个工具它能够从一个*commonjs*规范的JavaScript模块文件里读取配置。 Webpack是基于NodeJS的一个工具它能够从一个*commonjs*规范的JavaScript模块文件里读取配置。
@ -449,7 +456,9 @@ a#common-entries
#### _entry_ #### _entry_
The first export is the `entry` object: The first export is the `entry` object:
如上所述,第一个导出的对象是*entries* 如上所述,第一个导出的对象是*entries*
+makeExample('webpack/ts/config/webpack.common.js', 'entries', 'config/webpack.common.js')(format=".") +makeExample('webpack/ts/config/webpack.common.js', 'entries', 'config/webpack.common.js')(format=".")
:marked :marked