Skip to content

Latest commit

 

History

History
193 lines (134 loc) · 7.36 KB

UNIT_TESTING.md

File metadata and controls

193 lines (134 loc) · 7.36 KB

Unit Tests

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.

Structuring Tests

Tests should be properly structured. Checkout the following examples.

Example

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.

Steps

  1. Create a __tests__ under features/admin.applications.v1/components.
  2. Create a file with the pattern <FILE_NAME>.test.<FILE_EXTENSION> inside the __tests__ folder. (In this case applications-list.test.tsx).

Folder Structure

features
└── admin.applications.v1
    ├── __tests__
    ├── components
    |       └── __tests__
    |       |       └── applications-list.test.tsx
    |       └── applications-list.tsx
    └── applications-page.tsx

Writing Tests

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.

Identifying Elements in DOM

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.

Example: Assert on components with getByTestId.

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.

Example: Inheriting data-componentid

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

Testing API Calls

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 Testing

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.

Running the test suite

Following are few of the useful commands that you can use to run the existing unit tests for modules.

Run the full test suite

# From project root.
pnpm test

Run the full test suite in watch mode

# From project root.
pnpm test:watch

Run Tests for a specific test file

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

Run Tests for a specific test file in watch mode

# From features root
npx jest --watch features/admin.applications.v1/__tests__/applications-page.test.tsx

Run Tests for an individual module

Run pnpm test:unit from inside a module to run all unit tests for a specific module.

Code Coverage

We use Codecov to track code coverage.

Generate coverage report

# From the root of the project.
pnpm test:unit:coverage

References