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()