API
Angular Testing Library
re-exports everything from DOM Testing Library
as well as the render
method.
The following re-exports are patched to make them easier to use with Angular:
- The events on
fireEvent
automatically invoke a change detection cycle after the event has been fired - The
findBy
queries automatically invoke a change detection cycle before the query is invoked function - The
waitFor
functions automatically invoke a change detection cycle before invoking the callback function
render
With Angular Testing Library, the component can be rendered in two ways, via the component's type or with a template.
By default,
render
also imports theNoopAnimationsModule
.
Type
To render a component, you need to pass component's type to the render
method. For components that don't use other parts of your application (for example design modules or services), rendering a component can be as simple as the following example.
await render(AppComponent)
template
Instead of passing the component's type as first argument, you can also provide a template. This practice is required to render directives but can also be applied to components, it might even be more useful. The directive's (or component's) type must then be added to the declarations
.
example with directive:
await render('<div appSpoiler></div>', {
declarations: [SpoilerDirective],
})
example with component:
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
An object to set @Input
or input()
properties of the component.
default : {}
await render(AppComponent, {
inputs: {
counterValue: 10,
// explicitly define aliases using `aliasedInput`
...aliasedInput('someAlias', 'someValue'),
},
})
on
An object with callbacks to subscribe to EventEmitters
and Observables
of the component.
default : {}
// 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
A collection of components, directives and pipes needed to render the component. For example, nested components of the component.
For more info see the Angular docs.
default : []
example:
await render(AppComponent, {
declarations: [CustomerDetailComponent, ButtonComponent],
})
deferBlockBehavior
Set the defer blocks behavior.
For more info see the Angular docs
default : undefined
(uses DeferBlockBehavior.Manual
, which is different from the Angular default of DeferBlockBehavior.Playthrough
)
example:
await render(AppComponent, {
deferBlockBehavior: DeferBlockBehavior.Playthrough,
})
deferBlockStates
Set the initial state of a deferrable blocks in a component.
For more info see the Angular docs
default : undefined
(uses the Angular default, which is DeferBlockState.Placeholder
)
example:
await render(FixtureComponent, {
deferBlockStates: DeferBlockState.Loading,
})
componentProviders
A collection of providers needed to render the component via Dependency Injection.
These will be provided at the component level. To inject dependencies at the module level, use providers
.
For more info see the Angular docs.
default : []
example:
await render(AppComponent, {
componentProviders: [AppComponentService],
})
componentImports
A collection of imports to override a standalone component's imports with.
default : undefined
example:
await render(AppComponent, {
componentImports: [MockChildComponent],
})
childComponentOverrides
Collection of child component specified providers to override with.
default : undefined
example:
await render(AppComponent, {
childComponentOverrides: [
{
component: ChildOfAppComponent,
providers: [{provide: ChildService, useValue: {hello: 'world'}}],
},
],
})
detectChangesOnRender
Invokes detectChanges
after the component is rendered.
default : true
example:
await render(AppComponent, {detectChangesOnRender: false})
autoDetectChanges
Automatically detect changes as a "real" running component would do. For example, runs a change detection cycle when an event has occured.
default : true
example:
await render(AppComponent, {
autoDetectChanges: false,
})
excludeComponentDeclaration
Exclude the component to be automatically be added as a declaration. This is needed when the component is declared in an imported module, for example with SCAMs.
default : false
example:
await render(AppComponent, {
imports: [AppModule], // a module that includes AppComponent
excludeComponentDeclaration: true,
})
imports
A collection of imports needed to render the component, for example, shared modules. Adds NoopAnimationsModule
by default if BrowserAnimationsModule
isn't added to the collection
For more info see the Angular docs.
default : [NoopAnimationsModule]
example:
await render(AppComponent, {
imports: [AppSharedModule, MaterialModule],
})
providers
A collection of providers needed to render the component via Dependency Injection.
These will be provided at the module level. To inject dependencies at the component level, use componentProviders
.
For more info see the Angular docs.
default : []
example:
await render(AppComponent, {
providers: [
CustomersService,
{
provide: MAX_CUSTOMERS_TOKEN,
useValue: 10,
},
],
})
queries
Queries to bind. Overrides the default set from DOM Testing Library unless merged.
default : undefined
example:
await render(AppComponent, {
queries: {...queries, ...customQueries},
})
routes
The route configuration to set up the router service via RouterTestingModule.withRoutes
. For more info see the Angular Routes docs.
default : []
example:
await render(AppComponent, {
declarations: [ChildComponent],
routes: [
{
path: '',
children: [
{
path: 'child/:id',
component: ChildComponent,
},
],
},
],
})
schemas
A collection of schemas needed to render the component. Allowed values are NO_ERRORS_SCHEMA
and CUSTOM_ELEMENTS_SCHEMA
.
For more info see the Angular docs.
default : []
example:
await render(AppComponent, {
schemas: [NO_ERRORS_SCHEMA],
})
removeAngularAttributes
Removes the Angular attributes (ng-version, and root-id) from the fixture.
default : false
example:
await render(AppComponent, {
removeAngularAttributes: true,
})
componentInputs
(deprecated)
componentInputs
An object to set @Input
properties of the component. Uses setInput
to set the input property. Throws if the component property is not annotated with the @Input
attribute.
default : {}
example:
await render(AppComponent, {
componentInputs: {
counterValue: 10,
},
})
componentOutputs
(deprecated)
componentOutputs
An object to set @Output
properties of the component.
default : {}
example:
await render(AppComponent, {
componentOutputs: {
clicked: (value) => { ... }
}
})
componentProperties
(deprecated)
componentProperties
An object to set @Input
and @Output
properties of the component. Doesn't have a fine-grained control as inputs
and on
.
default : {}
example:
await render(AppComponent, {
componentProperties: {
// an input
counterValue: 10,
// an output
send: (value) => { ... }
// a public property
name: 'Tim'
}
})
RenderResult
container
The containing DOM node of your rendered Angular Component. This is a regular DOM node, so you can call container.querySelector
etc. to inspect the children.
debug
Prints out the component's DOM with syntax highlighting. Accepts an optional parameter, to print out a specific DOM node.
const {debug} = await render(AppComponent)
debug()
rerender
Changes the input properties of the existing component instance by following Angular component lifecycle events (i.e. ngOnChanges
is called). Input properties that are not defined are cleared.
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()
Using partialUpdate
, only the newly provided properties will be updated. Other input properties that aren't provided won't be cleared.
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
Trigger a change detection cycle for the component.
For more info see the Angular docs.
debugElement
The Angular DebugElement
of the component.
For more info see the Angular docs.
fixture
The Angular ComponentFixture
of the component.
For more info see the Angular docs.
const {fixture} = await render(AppComponent)
// componentInstance is typed as AppComponent
const componentInstance = fixture.componentInstance
🚨 If you find yourself using
fixture
to access the component's internal values you should reconsider! This probable means, you're testing implementation details.
navigate
Accepts a DOM element or a path as parameter. If an element is passed, navigate
will navigate to the href
value of the element. If a path is passed, navigate
will navigate to the path.
const { navigate } = await render(AppComponent, {
routes: [...]
})
await navigate(component.getByLabelText('To details'))
await navigate('details/3')
...queries
The most important feature of render
is that the queries from DOM Testing Library are automatically returned with their first argument bound to the component under test.
See Queries for a complete list.
example:
const {getByText, queryByLabelText} = await render(AppComponent)
screen.getByRole('heading', {
name: /api/i,
})
queryByLabelText(/First name/i')
renderDeferBlock
To test Deferrable views, you can make use of renderDeferBlock
. renderDeferBlock
will set the desired defer state for a specific deferrable block. The default value of a deferrable view is Placeholder
, but you can also set the initial state while rendering the component.
const {renderDeferBlock} = await render(FixtureComponent, {
deferBlockStates: DeferBlockState.Loading,
})
expect(screen.getByText(/loading/i)).toBeInTheDocument()
await renderDeferBlock(DeferBlockState.Complete)
expect(screen.getByText(/completed/i)).toBeInTheDocument()