Tests
Run Tests
In order to run all tests use command:
To execute specific test(s), utilize the -t option followed by a string that must be present in the test path. This allows you to filter and run only the desired tests based on the specified criteria.
npm run test -t /Image # runs a test for Image only
Utils
To perform component testing within the package, we employ the @testing-library/react library, which leverages the underlying functionality of jest.
The configuration files are located in the ./test-utils folder. Alongside the standard configurations, we have included a ./test-utils/custom-environment.ts file. This file addresses the issue of missing window methods, like matchMedia, in the testing environment.
Additionally, we store all shared tests in this folder. There are two categories of shared tests. The first is common.tsx, which consists of tests that can be utilized independently in multiple components. The second is {component}.tsx, which includes tests specific to a particular component that can be reused in other components. For instance, ./src/components/BackgroundImage/BackgroundImage.tsx utilizes ./src/components/Image/Image.tsx as a child. Consequently, many tests for the Image component can be utilized to test the BackgroundImage component as well.
The shared tests of the second type are named after the component that possesses a lower level of abstraction.
For instance, since the Image component is a part of the BackgroundImage component, the shared test should be named image.tsx rather than background-image.tsx.
Component Test
All tests for a component are stored in the __tests__ folder. Typically, there is a single *.test.tsx file within the folder, named after the component. However, there is no strict rule that restricts the number of test files that can be present.
...
|- BackgroundImage
|- __stories__
|- __tests__
|- BackgroundImage.test.tsx
|- BackgroundImage.tsx
|- BackgroundImage.scss
...
Typically, when working with jest tests, it's common to organize them into suites. These suites serve as containers for a group of related tests. Essentially, a suite is contained within a single file and brings together all the tests associated with a specific component.
Follow the steps below to write your own test:
- Use the describe function from
Jestto define your test suites. - Inside each suite, use the test or it function to define your test cases.
- Render your component using the render function.
- Use the screen object from
@testing-library/reactto query and interact with the rendered component. - Use the
expectfunction from@testing-library/jest-domto make assertions about the rendered component.
test('Render BackgroundImage by default', async () => {
render(<BackgroundImage qa={qaId} />);
const component = screen.getByTestId(qaId);
expect(component).toBeInTheDocument();
expect(component).toBeVisible();
});
...
Rules
Roles
There are list of default roles.
const image = getByRole('img');
Although it is possible to extend the list of roles with custom ones, it is strongly discouraged due to the creation of invalid HTML code.
// Component.tsx
<div role="custom-role">
// Test.ts
const component = getByRole("custom-role");
Testing ID
Another option, you have to access any tags in a component is to add data-qa prop.
To add a data-qa attribute to elements in your components and access those elements in your tests using @testing-library/react, you can follow these steps:
- Add data-qa attributes to elements: In your component's TSX code, add the
data-qaattribute to the elements you want to target in your tests. Assign a meaningful value to the attribute that helps identify the purpose or role of the element.
const {qa} = props;
return <div data-qa="background-image">{/* Other components */}</div>;
};
- Access elements using data-qa attributes: Use the
getByTestIdor other query methods provided by@testing-library/reactto access the elements based on their data-qa attributes.
It is possible to change data-qa dinamically:
const {qa} = props;
return <div data-qa={qa}>{/* Other components */}</div>;
};
Avoid Direct Node Access
Avoiding direct Node access in testing is essential for several reasons. Testing Library methods emulate user behavior, ensuring that tests focus on the actual user experience. They encourage best practices by prioritizing output over implementation details, resulting in more resilient tests. Additionally, using Testing Library methods improves test maintainability by shielding tests from structural changes in components, enhances test readability, and makes tests more portable and reusable. Overall, this approach promotes testing best practices, improves maintainability, and ensures effective tests as your codebase evolves.
It is important to avoid direct Node access when writing tests. This means refraining from using methods like querySelector or querySelectorAll. Instead, we should rely on testing library methods such as getByRole, getByText, or getByTestId to access components.
In some cases, the prop being tested may have an impact on a deeply nested container within the component. It can be tempting to access this container using querySelector or similar methods. However, it is advised to resist this temptation and continue utilizing the recommended testing library methods for accessing and interacting with components.
screen.getByTestId(id).querySelector('p');
Shared Test
Reusing common tests ensures efficiency, consistency, and scalability in software testing, reducing duplication, improving maintenance, and promoting standardized behavior across components.
Testing common props like className, style, and others is a recurring task that appears in nearly every test scenario.
Shared test implementation:
...
test('add className', () => {
testCustomClassName<BackgroundImageProps>({
component: BackgroundImage,
props: {qa: qaId},
});
});
Tests Development
It is recommended to prefix branch names with test/... when working on test-related branches. Additionally, commits and Pull Requests can follow a naming convention such as test({ComponentName}): test for {ComponentName} added to clearly indicate the addition of tests for a specific component.