Frontend testing

Libraries

PermaplanT uses the Vitest testing framework.

React Test Renderer, React Testing Library and User Event are available as companion libraries.

Types and organization of test

We distinguish three different kinds of tests in the frontend of PermaplanT.

  • Render tests
  • DOM tests
  • Logic tests

Each of these test-types may be used for unit testing or integration testing.

All tests related to a component can be found under the same directory in <component name>.test.tsx

Render tests

Render tests make use of React Test Renderer to check if a components layout has unexpectedly changed by transforming it to plain html. Since most components are made up of other sub-components, most tests of this kind are considered to be integration tests.

After a new render test is run for the first time, React Test Renderer will record a snapshot of the selected component and store it in the __snapshots__ subfolder. If the same component renders differently in the future, e.g. because a subcomponent was changed, the test will fail.

To fix the issue, the programmer has to decide if the changes are intentional and then either fix the issue, or regenerate the affected snapshots using:

npm run test -- --updateSnapshot

DOM tests

DOM tests are used to test a components response to user interaction. In the current test setup this is accomplished using a simulated DOM provided by React Testing Library and js-dom. This makes it possible to run these tests even when a browser is not available (e.g. as part of the CI-pipeline).

If possible, User Event should be used to mock user input.

Logic Tests

The remaining tests are used to test our helper functions and in general code that is not tied to the DOM.

Vitest provides plenty of APIs that can be used to mock functions for this purpose.

Mocking API requests should be done with MSW. There is an example of this in src/__test_utils__/msw_handlers/plants.ts. The gist is, MSW intercepts all requests, for which a handler is defined returns the handler's response instead of the backend's.