Product Unit tests have been implemented using Jest along with React Testing Library. Make sure to write unit tests when you are working on new or existing features.
Tests should be properly structured. Checkout the following examples.
Let's say that you have a component called applications-list.tsx
at the root of features/admin.applications.v1/components
that needs to be tested.
- Create a
__tests__
underfeatures/admin.applications.v1/components
. - Create a file with the pattern
<FILE_NAME>.test.<FILE_EXTENSION>
inside the__tests__
folder. (In this caseapplications-list.test.tsx
).
features
└── admin.applications.v1
├── __tests__
├── components
| └── __tests__
| | └── applications-list.test.tsx
| └── applications-list.tsx
└── applications-page.tsx
Writing unit tests for every component that you develop is mandatory. Take a look at the following example test case where we test if the component that we are writing mounts and renders as expected.
⚠️ There are several ESLint plugins (eslint-plugin-jest-dom, eslint-plugin-testing-library) configured to make sure that developers follow the best practices. Please configure ESLint in your coding environment if you haven't already done so by following this guide.
import { render, screen } from "@wso2is/unit-testing/utils";
import React from "react";
import "@testing-library/jest-dom";
import { ApplicationList } from "../components/application-list.tsx";
describe("Test if the Application List is working as expected", () => {
it("<ApplicationList /> renders without exploding", () => {
render(<ApplicationList />);
expect(screen.getByTestId("application-list")).toBeInTheDocument();
});
});
💡 Note that we use a custom render
function here rather than from the @testing-library/react
module. The reason for
this is that we need to wrap our components with providers like Redux
etc. And doing this in every test case is a
tedious task. So we have written a custom renderer following the guide in
official documentation. @unit-testing
is a webpack alias added to avoid importing this function using relative paths.
As a practice we use data-componentid
inorder to make our tests resilient to change.
Use the getByTestId method to access with the component id.
expect(component.getByTestId("getting-started-page-layout")).toBeInTheDocument();
⛔ Never use any other selectors such as
id
,classes
, etc. to identify the elements.
If there are no data-componentid
present in the element, extend the IdentifiableComponentInterface from @wso2is/core/models
to inherit the attribute.
export interface SampleComponentInterface extends IdentifiableComponentInterface {
// Other attributes
}
export const SampleComponent: FunctionComponent<SampleComponentInterface> = (
props: SampleComponentInterface
): ReactElement => {
const {
["data-componentid"]: componentId,
// Other props
} = props;
}
⚠️ Some components might have thedata-testid
already implemented using the TestableComponentInterface. This interface and the data attribute since has been deprecated. Hence, 💥 DO NOT USE IT in new components. Refactor the usage where ever possible.
We have used msw to mock the APIs. The mock implementation root for the core can be found at <APP_ROOT>/test-configs/__mocks__/server
.
If you need to add further endpoint mocks, add them in the handlers.ts
.
Snapshot tests are a very useful tool whenever you want to make sure your UI does not change unexpectedly.
A typical snapshot test case renders a UI component, takes a snapshot, then compares it to a reference snapshot file stored alongside the test. The test will fail if the two snapshots do not match: either the change is unexpected, or the reference snapshot needs to be updated to the new version of the UI component.
import { render } from "@wso2is/unit-testing";
import React from "react";
import "@testing-library/jest-dom";
import { ApplicationList } from "../components/applications";
it("<ApplicationList /> matches snapshot", () => {
const { container } = render(<ApplicationList />);
expect(container).toMatchSnapshot();
});
For further reference, checkout the official documentation of React Testing Library.
Following are few of the useful commands that you can use to run the existing unit tests for modules.
# From project root.
pnpm test
# From project root.
pnpm test:watch
Make sure to cd to the corresponding package directory, when running an individual spec.
# From features root
npx jest features/admin.applications.v1/__tests__/applications-page.test.tsx
# From features root
npx jest --watch features/admin.applications.v1/__tests__/applications-page.test.tsx
Run pnpm test:unit
from inside a module to run all unit tests for a specific module.
We use Codecov to track code coverage.
# From the root of the project.
pnpm test:unit:coverage
- Common
- Common mistakes with React Testing Library Blog by Kent C. Dodds
- Fix the "not wrapped in act(...)" warning Blog by Kent C. Dodds
- API Mocking
- Stop mocking fetch Blog by Kent C. Dodds
- Use Mock Service Worker and Test Like a User Video Tutorial by Leigh Halliday