Skip to main content

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 the NoopAnimationsModule.

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],
})

deferBlockBehavior

Set the defer blocks behavior.

For more info see the Angular docs

default : undefined (uses the Angular default, which is DeferBlockBehavior.Manual)

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,
})

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, {
componentInputs: {count: 4, name: 'Sarah'},
})

expect(screen.getByTestId('count-value').textContent).toBe('4')
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')

await rerender({componentInputs: {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, {
componentInputs: {count: 4, name: 'Sarah'},
})

expect(screen.getByTestId('count-value').textContent).toBe('4')
expect(screen.getByTestId('name-value').textContent).toBe('Sarah')

await rerender({componentInputs: {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.

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