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
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
An object to set @Output
properties of the component.
default : {}
example:
await render(AppComponent, {
componentOutputs: {
clicked: (value) => { ... }
}
})
componentProperties
An object to set @Input
and @Output
properties of the component. Doesn't
have a fine-grained control as componentInputs
and componentOutputs
.
default : {}
example:
await render(AppComponent, {
componentProperties: {
// an input
counterValue: 10,
// an output
send: (value) => { ... }
// a public property
name: 'Tim'
}
})
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],
})
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,
})
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()
change
Change the input of the component. This calls detectChanges
after the props
are updated.
const {change} = await render(Counter, {
componentProperties: {count: 4, name: 'Sarah'},
})
expect(screen.getByTestId('count-value').textContent).toBe('4')
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
change({count: 7})
// count updated to 7
expect(screen.getByTestId('count-value').textContent).toBe('7')
// name keeps the same value
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
rerender
Create and render a new instance of the component. Input properties that are not defined are cleared. To keep them use change.
const {rerender} = await render(Counter, {
componentProperties: {count: 4, name: 'Sarah'},
})
expect(screen.getByTestId('count-value').textContent).toBe('4')
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
await rerender({count: 7})
// count 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()
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')