Part 2 – Testing: Adding unit tests to components

The original link

The component library is now maintained by our team

The introduction

In the first part, we built the infrastructure of the project based on create-React-app. For a component library, not only should there be simple and useful components, but the quality of each component is also crucial. Unit testing is an effective way to improve software quality. In this article, you will not only complete the configuration of unit testing in previous projects, but also walk you through the world of unit testing

The tutorial section

This article, the second in the series, is unit testing

  • Part 1: Undo a background project from 0 to 1
  • Part two: Adding unit tests to components
  • Part three: Project packaging and publishing to NPM

2020 is here. Do I still need unit tests?

First, let me tell you a little secret. I’m not a big fan of unit testing. It is time consuming, and refactoring the project can become laborious. Also, unit tests don’t have a clear boundary, and sometimes you feel like you haven’t written enough unit tests. Also, unit testing doesn’t make your code bug-free, even if your test coverage is 💯 %.

Fortunately, the cost of unit testing is coming down for React applications.

Excellent TypeScript

First, after TypeScript came along, we didn’t need to write most of our unit tests.

For a simple example, here’s a TypeScript implementation:

type Props = {
  name: string;
};
Copy the code

Here is the unit test version:

import React from 'react';
import Component from './Component';
test('does not do something completely embarassing if I forgot to pass a name', () => {
  const { getByText } = render(<Component />);
  expect(getByText('Name: ')).not.toBeInTheDocument();
});
Copy the code

So with the advent of TypeScript’s type system, this part of unit testing is no longer necessary.

ESLint and Prettier

Eslint analyzes code and checks it against a set of rules. It also sounds a lot like a test. Prettier can constrain code style according to a set of rules. And, as you write code, work with the editor to get instant feedback.

Write tests as users do

The techniques mentioned above improve the quality of software from the perspective of language, code quality and code style, but do not use our software as a user. After all, only the developer knows how to use the software.

In addition to writing documentation, comments, and demos. Unit testing is also more like an instruction manual for the software, providing security for the use of the software.

As described in the React documentation, this article is just about rendering component trees, rendering them in a simplified test environment and doing assertion checks on their output.

Technology stack

  • Jest: JavaScript testing framework.
  • Testing-library /react: Convert the react component to a Dom node for testing, instead of a rendered instance of the React component, which can be used as an Enzyme instead.
  • Ts-jest: is a TypeScript preprocessor that supports jEST source mapping and allows you to test projects written in TypeScript using JEST.
  • Jest-html-reporter: a library that generates test reports.

Project configuration

Because the react-app-Rewired tool was previously used as the Cli tool, it was limited to the version of Jest. As a result, some libraries will lock the version when the dependency is installed below.

NPM I -d [email protected] @types/jest [email protected] jest-html-reporter @testing-library/ reacte@babel /preset-env @babel/preset-reactCopy the code

In order to use these installed dependencies, package.json needs to be modified, adding tests, and validation before submission.

. "scripts": { + "test": "jest --no-cache", } ... "lint-staged": { "*.{js,ts,tsx}": [ "eslint --fix src/**/*.{ts,tsx}", + "jest --bail --coverage --findRelatedTests", "git add ." ], "*.{md,css,html,less}": [ "prettier --write", "git add ." ] }Copy the code

Finally, you need to add a configuration file to Jest: jest.config.js

module.exports = { preset: 'ts-jest', transform: { '^.+\\.tsx? $': 'ts-jest', }, globals: { 'ts-jest': { babelConfig: { presets: ['@babel/preset-env', '@babel/preset-react'], }, }, }, testEnvironment: 'jsdom', testMatch: [ '<rootDir>/src/**/__tests__/**/*.{ts,tsx,js,jsx,mjs}', '<rootDir>/src/**/?(*.)(spec|test).{ts,tsx,js,jsx,mjs}', ], Reporters: ['default', ['./node_modules/ jest-html-Reporter ', {pageTitle: 'Test report ',},],], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], collectCoverage: true, collectCoverageFrom: ['app/react/**/*.{ts,tsx}', '!app/react/__tests__/api/api-test-helpers.ts'], };Copy the code

Write test cases

Here, I need to add a test case to the EmptyLine I added earlier.

empty-line/index.tsx
import './style/index.less';
import EmptyLine from './EmptyLine';

export default EmptyLine;
Copy the code
empty-line/EmptyLine.tsx
import React from 'react'; export interface IEmptyLineProps { height? : number; } const EmptyLine = ({ height = 20 }: IEmptyLineProps) => { return <div className="d-empty-line" style={{ height }} />; }; export default EmptyLine;Copy the code
empty-line/test/index.test.tsx
import React from 'react'; import { create, act } from 'react-test-renderer'; import EmptyLine from '.. /EmptyLine'; Test (' default render height normal ', () => {const emptyLine = create(< emptyLine />).tojson (); expect(emptyLine? .props.style).toEqual( expect.objectContaining({ height: 20, }), ); }); Test (' custom height render normal ', () => {let emptyLine: any; act(() => { emptyLine = create(<EmptyLine height={30} />); }); expect(emptyLine.toJSON()? .props.style).toEqual( expect.objectContaining({ height: 30, }), ); });Copy the code

Below are two common use scenarios for EmptyLine, both covered in our unit tests.

Note that styles are not introduced in the emptyline.tsx component here, but in the index.tsx sibling. Because the styles are not supported to be introduced during testing, there will be problems.

Run NPM run test to see the result:

When we commit the code, a test report is also generated in the root directory:

conclusion

At this point, we have added testing capabilities to the component library. Our component library has also become more secure and superior. Finally, stay tuned for chapter 3 when we talk about how to pack and upload to NPM.