API
Angular Testing Library
重新导出 DOM Testing Library
中的所有内容,以及 render
方法。
以下重新导出已修补以使其更易于与 Angular 一起使用
fireEvent
上的事件在事件触发后会自动调用更改检测周期findBy
查询会在调用查询函数之前自动调用更改检测周期waitFor
函数会在调用回调函数之前自动调用更改检测周期
render
使用 Angular Testing Library,可以通过组件类型或模板两种方式渲染组件。
默认情况下,
render
还会导入NoopAnimationsModule
。
Type
要渲染组件,需要将组件类型传递给 render
方法。对于不使用应用程序其他部分的组件(例如设计模块或服务),渲染组件就像以下示例一样简单。
await render(AppComponent)
template
除了将组件类型作为第一个参数传递,还可以提供模板。这种做法是渲染指令所必需的,但也可以应用于组件,甚至可能更有用。然后必须将指令(或组件)类型添加到 declarations
中。
使用指令的示例:
await render('<div appSpoiler></div>', {
declarations: [SpoilerDirective],
})
使用组件的示例:
await render(
'<app-component [value]="47" [otherValue]="anotherValue" (sendValue)="sendValue($event)"></app-component>',
{
declarations: [AppComponent],
componentProperties: {
anotherValue: 'valueOfAnotherProperty',
sendValue: jest.fn(),
},
},
)
export async function render<ComponentType>(
component: Type<ComponentType>,
renderOptions?: RenderComponentOptions<ComponentType>,
): Promise<RenderResult<ComponentType, ComponentType>>
export async function render<WrapperType = WrapperComponent>(
template: string,
renderOptions?: RenderTemplateOptions<WrapperType>,
): Promise<RenderResult<WrapperType>>
Component RenderOptions
inputs
一个用于设置组件的 @Input
或 input()
属性的对象。
默认 : {}
await render(AppComponent, {
inputs: {
counterValue: 10,
// explicitly define aliases using `aliasedInput`
...aliasedInput('someAlias', 'someValue'),
},
})
on
一个包含回调的对象,用于订阅组件的 EventEmitters
和 Observables
。
默认 : {}
// using a manual callback
const sendValue = (value) => { ... }
// using a (jest) spy
const sendValueSpy = jest.fn()
await render(AppComponent, {
on: {
send: (value) => sendValue(value),
send: sendValueSpy
}
})
declarations
渲染组件所需的组件、指令和管道的集合。例如,组件的嵌套组件。
有关更多信息,请参阅 Angular 文档。
默认 : []
示例:
await render(AppComponent, {
declarations: [CustomerDetailComponent, ButtonComponent],
})
deferBlockBehavior
设置延迟块的行为。
有关更多信息,请参阅 Angular 文档
默认 : undefined
(使用 DeferBlockBehavior.Manual
,这与 Angular 的默认值 DeferBlockBehavior.Playthrough
不同)
示例:
await render(AppComponent, {
deferBlockBehavior: DeferBlockBehavior.Playthrough,
})
deferBlockStates
设置组件中延迟块的初始状态。
有关更多信息,请参阅 Angular 文档
默认 : undefined
(使用 Angular 的默认值,即 DeferBlockState.Placeholder
)
示例:
await render(FixtureComponent, {
deferBlockStates: DeferBlockState.Loading,
})
componentProviders
渲染组件所需的通过依赖项注入提供的提供程序集合。
这些将在组件级别提供。要以模块级别注入依赖项,请使用 providers
。
有关更多信息,请参阅 Angular 文档。
默认 : []
示例:
await render(AppComponent, {
componentProviders: [AppComponentService],
})
componentImports
一个导入集合,用于覆盖独立组件的导入。
默认 : undefined
示例:
await render(AppComponent, {
componentImports: [MockChildComponent],
})
childComponentOverrides
指定要覆盖的子组件的提供程序集合。
默认 : undefined
示例:
await render(AppComponent, {
childComponentOverrides: [
{
component: ChildOfAppComponent,
providers: [{provide: ChildService, useValue: {hello: 'world'}}],
},
],
})
detectChangesOnRender
在渲染组件后调用 detectChanges
。
默认 : true
示例:
await render(AppComponent, {detectChangesOnRender: false})
autoDetectChanges
像“真实”运行的组件一样自动检测更改。例如,在事件发生时运行更改检测周期。
默认 : true
示例:
await render(AppComponent, {
autoDetectChanges: false,
})
excludeComponentDeclaration
排除自动添加为声明的组件。当组件在导入的模块中声明时需要这样做,例如使用 SCAM。
默认 : false
示例:
await render(AppComponent, {
imports: [AppModule], // a module that includes AppComponent
excludeComponentDeclaration: true,
})
imports
渲染组件所需的导入集合,例如共享模块。如果 BrowserAnimationsModule
未添加到集合中,则默认情况下会添加 NoopAnimationsModule
有关更多信息,请参阅 Angular 文档。
默认 : [NoopAnimationsModule]
示例:
await render(AppComponent, {
imports: [AppSharedModule, MaterialModule],
})
providers
渲染组件所需的通过依赖项注入提供的提供程序集合。
这些将在模块级别提供。要以组件级别注入依赖项,请使用 componentProviders
。
有关更多信息,请参阅 Angular 文档。
默认 : []
示例:
await render(AppComponent, {
providers: [
CustomersService,
{
provide: MAX_CUSTOMERS_TOKEN,
useValue: 10,
},
],
})
queries
要绑定的查询。覆盖 DOM Testing Library 中的默认设置,除非合并。
默认 : undefined
示例:
await render(AppComponent, {
queries: {...queries, ...customQueries},
})
routes
要通过 RouterTestingModule.withRoutes
设置路由服务的路由配置。有关更多信息,请参阅 Angular 路由文档。
默认 : []
示例:
await render(AppComponent, {
declarations: [ChildComponent],
routes: [
{
path: '',
children: [
{
path: 'child/:id',
component: ChildComponent,
},
],
},
],
})
schemas
渲染组件所需的架构集合。允许的值是 NO_ERRORS_SCHEMA
和 CUSTOM_ELEMENTS_SCHEMA
。
有关更多信息,请参阅 Angular 文档。
默认 : []
示例:
await render(AppComponent, {
schemas: [NO_ERRORS_SCHEMA],
})
removeAngularAttributes
从夹具中删除 Angular 属性(ng-version 和 root-id)。
默认 : false
示例:
await render(AppComponent, {
removeAngularAttributes: true,
})
componentInputs
(已弃用)
componentInputs
一个用于设置组件 @Input
属性的对象。使用 setInput
来设置输入属性。如果组件属性没有用 @Input
属性进行注释,则会抛出错误。
默认 : {}
示例:
await render(AppComponent, {
componentInputs: {
counterValue: 10,
},
})
componentOutputs
(已弃用)
componentOutputs
一个用于设置组件 @Output
属性的对象。
默认 : {}
示例:
await render(AppComponent, {
componentOutputs: {
clicked: (value) => { ... }
}
})
componentProperties
(已弃用)
componentProperties
一个用于设置组件 @Input
和 @Output
属性的对象。没有像 inputs
和 on
那样细粒度的控制。
默认 : {}
示例:
await render(AppComponent, {
componentProperties: {
// an input
counterValue: 10,
// an output
send: (value) => { ... }
// a public property
name: 'Tim'
}
})
RenderResult
container
已渲染的 Angular 组件的包含 DOM 节点。这是一个常规 DOM 节点,因此可以调用 container.querySelector
等来检查子节点。
debug
以语法高亮的方式打印出组件的 DOM。接受一个可选参数,用于打印出特定的 DOM 节点。
const {debug} = await render(AppComponent)
debug()
rerender
通过遵循 Angular 组件生命周期事件来更改现有组件实例的输入属性(即 ngOnChanges
被调用)。未定义的输入属性将被清除。
const {rerender} = await render(Counter, {
inputs: {count: 4, name: 'Sarah'},
})
expect(screen.getByTestId('count-value').textContent).toBe('4')
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
await rerender({
inputs: {count: 7},
})
// count is updated to 7
expect(screen.getByTestId('count-value').textContent).toBe('7')
// name is undefined because it's not provided in rerender
expect(screen.getByTestId('name-value').textContent).toBeUndefined()
使用 partialUpdate
,只有新提供的属性才会被更新。未提供的其他输入属性不会被清除。
const {rerender} = await render(Counter, {
inputs: {count: 4, name: 'Sarah'},
})
expect(screen.getByTestId('count-value').textContent).toBe('4')
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
await rerender({inputs: {count: 7}, partialUpdate: true})
// count is updated to 7
expect(screen.getByTestId('count-value').textContent).toBe('7')
// name is still rendered as "Sarah" because of the partial update
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
detectChanges
触发组件的更改检测周期。
有关更多信息,请参阅 Angular 文档。
debugElement
组件的 Angular DebugElement
。
有关更多信息,请参阅 Angular 文档。
fixture
组件的 Angular ComponentFixture
。
有关更多信息,请参阅 Angular 文档。
const {fixture} = await render(AppComponent)
// componentInstance is typed as AppComponent
const componentInstance = fixture.componentInstance
🚨 如果发现自己使用
fixture
访问组件的内部值,则应该重新考虑!这可能意味着,你正在测试实现细节。
navigate
接受 DOM 元素或路径作为参数。如果传递的是元素,navigate
将导航到元素的 href
值。如果传递的是路径,navigate
将导航到该路径。
const { navigate } = await render(AppComponent, {
routes: [...]
})
await navigate(component.getByLabelText('To details'))
await navigate('details/3')
...queries
render
的最重要的功能是,来自 DOM Testing Library 的查询会自动返回,它们第一个参数绑定到正在测试的组件。
有关完整列表,请参阅 查询。
示例:
const {getByText, queryByLabelText} = await render(AppComponent)
screen.getByRole('heading', {
name: /api/i,
})
queryByLabelText(/First name/i')
renderDeferBlock
要测试 延迟视图,可以使用 renderDeferBlock
。renderDeferBlock
将为特定的延迟块设置所需的延迟状态。延迟视图的默认值为 Placeholder
,但也可以在渲染组件时设置初始状态。
const {renderDeferBlock} = await render(FixtureComponent, {
deferBlockStates: DeferBlockState.Loading,
})
expect(screen.getByText(/loading/i)).toBeInTheDocument()
await renderDeferBlock(DeferBlockState.Complete)
expect(screen.getByText(/completed/i)).toBeInTheDocument()