Are you ready to dive into the world of testing your Angular applications? We’ve got just the tool for you: Angular Testing Library. In this article, we’ll introduce you to this utility that will revolutionize your testing practices and make your life as a developer so much easier. So, let’s get started!

What is Testing Library?

First things first, let’s clarify what Testing Library is all about. It’s not your typical testing framework; instead, it’s a comprehensive set of utilities designed to complement the testing framework of your choice (though we highly recommend Jest). Its main focus is on testing your application from the user’s perspective, steering clear of implementation details. With Testing Library, you can write maintainable tests, develop with confidence, and ensure accessibility by default.

Testing Library consists of a core called DOM Testing Library and various plugin libraries for different technologies. Since we’re all about Angular here, let’s talk about Angular Testing Library. This library provides specific APIs and functionalities tailored for working with Angular components.

Getting Started: A Quick Setup Guide

Once you’ve set up your Angular project, we need to make a few adjustments.
We should uninstall Karma and Jasmine, then install Jest and Testing Library. If you’re not sure how, check out this guide:
Guide – Install Jest and Angular Testing Library

If everything went well, we can now write our first test with Angular Testing Library.

About Angular Testing Library API

The Angular Testing Library is a very lightweight solution for testing Angular components. It provides light utility functions on top of DOM Testing Library.

To create a test, we’ll utilize the render function. This function takes two parameters: the component class or template, and an object with render options where we specify inputs and outputs values, components, modules, services, pipes, and anything else necessary for testing the component and its children.

Once you’ve set everything up, the render function returns an object with various useful methods to use in your tests. You can see more about this here.

Let’s see a basic example:

it(‘should create the component’, async() => {
const result = await render(MyComponent, {
declarations: [
MyComponent,
SomeChildComponent
],
imports: [
…MODULES_REQUIRED
],
providers: [
{
provide: MyService,
useValue: MyServiceMock
}
]
});
expect(result.fixture.componentInstance).toBeTruthy();
});

The Power of DOM Testing Library

Now that you have a grasp of Angular Testing Library, let’s talk about its core counterpart: DOM Testing Library. This lightweight solution focuses on testing DOM nodes, whether you’re using JSDOM or testing directly in the browser. It provides convenient utility functions that enable you to query the DOM just like a user would. By mimicking user interactions, you can ensure accessibility and gain confidence in your application’s functionality.

Let’s Explore the World of Queries

Queries are the methods that Testing Library gives you to find elements on the page. There are several types of queries: “get”, “find” and “query”, the difference between them is whether the query will throw an error if no element is found or if it will return a Promise and retry, depending on what page content you are selecting, different queries may be more or less appropriate.

Types of queries

Type of Query 0 Matches 1 Match >1 Matches Retry (Async/Await)
Single Element
getBy… Throw error Return element Throw error No
queryBy… Return null Return element Throw error No
findBy… Throw error Return element Throw error Yes
Multiple Elements
getAllBy… Throw error Return array Return array No
queryAllBy… Return [] Return array Return array No
findAllBy… Throw error Return array Return array Yes

Queries priority

Based on the Guiding Principles, your test should resemble how users interact with your code as much as possible. Taking this into account, the priority recommendation for the use of queries is:

  1. Queries Accessible to Everyone: Queries that reflect the experience of visual/mouse users as well as those that use assistive technology
    1. …ByRole: This can be used to query every element that is exposed in the accessibility tree. There’s not much you can’t get with this (if you can’t, it’s possible your UI is inaccessible). Most often, this will be used with the name option like so: getByRole(‘button’, {name: /submit/i}).
    2. …ByLabelText: This method is really good for form fields. When navigating through a website form, users find elements using label text.
    3. …ByPlaceholderText: A placeholder is not a substitute for a label. But if that’s all you have, then it’s better than alternatives.
    4. …ByText: Outside of forms, text content is the main way users find elements. This method can be used to find non-interactive elements like divs, spans, and paragraphs.
    5. …ByDisplayValue: The current value of a form element can be useful when navigating a page with filled-in values.
  2. Semantic Queries: HTML5 and ARIA compliant selectors. Note that the user experience of interacting with these attributes varies greatly across browsers and assistive technology.
    1. …ByAltText: If your element is one which supports alt text (img, area, input, and any custom element), then you can use this to find that element.
    2. …ByTitle: The title attribute is not consistently read by screenreaders, and is not visible by default for sighted users
  3. Test IDs
    1. …ByTestId: Since they are not visible or audible to users, we recommend using them only when you can’t match by role, text, or when it simply doesn’t make sense otherwise.

Learn more about queries and the options that each one accepts to optimize the querings here.

User Events

Testing user interactions is vital, and that’s where user-event comes into play. It’s a companion library for Testing Library that simulates user interactions by dispatching events, just as they would occur in a real browser. Let’s explore some of the user-event APIs:

  • Pointer: Simulate interactions with pointer devices, such as press and move.
  • Keyboard: It allows you to simulate interactions with a keyboard. It accepts a string describing the key actions.
  • Clipboard: Simulate copy, cut, and paste interactions.
  • Utility: Simulate interactions like clear, type, and upload. These may not have one-to-one equivalents in real user interactions.
  • Convenience: These APIs are shortcuts for equivalent calls to the underlying pointer() and keyboard() APIs (click, double click, hover, unhover, etc).

By leveraging user-event, you can ensure your application behaves as expected when users interact with it.

Get Engaged with Angular Testing Library!

Congratulations! You’ve taken the first step towards efficient testing with Angular Testing Library. We’ve covered the basics of this tool, from installation to writing your first test. We’ve also explored the power of DOM Testing Library, querying, and user events. Dive deeper into the documentation, experiment with different queries, and start building tests that truly reflect your users’ experiences.