preface

In the last article, we covered the basics of mono-testing and created a demo project. In this article, we will write a preliminary introduction to mono-testing the React component

Importing component libraries

Based on the project in our last blog, in order to make our demo project more beautiful and closer to our actual project, we introduce antD UI library here, and we use PNPM. Other students can use YARN or NPM according to their own habits

pnpm add antd
Copy the code

Add ANTD to package.json dependenciesIn this case, vscode will check the spelling, and you can see that the above ANTD has a wavy line. It does not affect the use of antD, but it is not comfortable to see the wavy line prompt. Here we will deal with it, open Settings, type cSpellYou can see that there are no wavy lines left

Rewrite the entrance

The content in the original entry app.tsx is the default generated content in create-React-app. We will try to introduce antD components to make the entry as close as possible to our actual project

To rewrite app.tsx, let’s get rid of the original ones and change it to something like this, which is a button in the scene and then when you click it, it says message, notice one dot here, TSX has a React from ‘React’ import by default, but when you use the React 17+ version, tsconfig does not need to import this configuration by default. Tsconfig already has this configuration when we initialize the project. Older versions may want to keep an eye on the “JSX “: “react-jsx” configuration

import "./App.css"; import { Button, message } from "antd"; import { useCallback } from "react"; Function App() {const showMessage = useCallback(() => {message.info(' show a hint '); } []); <div className="App"> <Button type="primary" onClick={showMessage}> this is a Button </Button> </div>; } export default App;Copy the code

To use the ANTD style, we need to introduce the corresponding style and rewrite the app.css to suit our needs

@import '~antd/dist/antd.css';
.App {
  text-align: center;
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
Copy the code

Take a look at the effect. The button is centered and pops up when clickedThe app.test. TSX in the original project can not be used now, because the entry file has been rewritten by us, so the app.test. TSX will report an error when running, and our vscode will also show an error when running here, let’s run it

It can be seen that the operation error occurs at this time, which also brings some enlightenment to our project. The existence of single test can ensure the accurate operation of the project, especially after we do some break change or reconstruction, single test can ensure that the new changed function can cover the previous function.

So let’s rewrite app.test.tsx

import { render, screen } from "@testing-library/react"; import App from "./App"; test("renders learn react link", () => { render(<App />); Const linkElement = screen.getByText(" This is a button "); expect(linkElement).toBeInTheDocument(); });Copy the code

Let me run it againpnpm test, at which point the run can pass

Vscode plug-in

Own local install vscode plug-in, you can refer to it

Write a component for testing

We first write a simple demonstration FC, and then write a single test of this FC, learning while transforming this component

cd src
mkdir components
cd components
mkdir todo-header
cd todo-header
touch index.tsx
touch index.css
Copy the code

We create a Components component and create our TodoHeader component in this directory index.tsx

import "./index.css"; Interface TodoHeaderProps {// Title: string; } export default function TodoHeader({ title }: TodoHeaderProps) { return ( <div className="report-header"> <span className="title">{title}</span> </div> ); }Copy the code

index.css

.todo-header {
  display: flex;
}
.title {
  font-style: normal;
  font-weight: 500;
  font-size: 16px;
  line-height: 24px;
  color: #1664ff;
}
Copy the code

Call this component from app.tsx

<TodoHeader title=" This is a title "/>Copy the code

Here we go through the component. It is simple to write first, and pass in a title title for display. Later we can continue to improve and expand the component according to the situation, and write a single test according to the various functions of the component

Let’s see what happens

Start writing a single test against the above components

First, we built a __tests__ directory under the components, used to store the components below all of the components of the corresponding single file, we correspond to the name of the component to create a todo – the header. The test. The TSX file, Then we started to write our first single test from the above component analysis. In fact, we only had one title props. Here we were trying to determine if the component was meeting our expectations by determining whether the content of the title we passed in would appear properly in our view. So with this goal we can write a set of tests and make an assertion todo-header.test.tsx

import { render, screen } from "@testing-library/react"; import TodoHeader from ".. /todo-header"; Describe (" test TodoHeader component ", () => {it(" correct render title component ", () => {const title = "test title "; render(<TodoHeader title={title} />); const titleElement = screen.getByText(title); expect(titleElement).toBeInTheDocument(); }); });Copy the code

Walk through this code

  • Describe defines a collection of related tests. In our current test file, for example, we can write all test cases related to this component in one collection
  • It is equivalent to a test case, we ensure that a test case only measures one function or one property, just as a function only does one thing
  • Render Testing – The ability provided by the library to render components
  • Screen can be understood as a queryable object provided by the testing-library, since it is common to query the entire document.body. DOM Testing Library also exports a Screen object, It contains each query that is pre-bound to Document.body
  • Expect some assertion that the element queried is from the document

So we’re done writing a very simple single test, and then we can run it

Run a single case

When we run PNPM test, we actually run the full number of test cases. When we add a single test case, we only want to run incremental or specified test cases, so that’s when we need to add parameters or configure

Run individual cases by run-time parameter

pnpm test src/components/__tests__/todo-header.test.tsx
Copy the code

Other ways to determine the correct rendering

Through queryByText

It (" Render the title component correctly by queryByTest", () => {const title = "test title "; const { queryByText } = render(<TodoHeader title={title} />); const titleElement = queryByText(title); expect(titleElement).not.toBeNull(); expect(titleElement).toBeInTheDocument(); });Copy the code

The titleElement may be null, so we assert that it is not null and that the node is in document

Through getByText

It (" Render the title component correctly by getByText", () => {const title = "test title "; const { getByText } = render(<TodoHeader title={title} />); const titleElement = getByText(title); expect(titleElement).toBeInTheDocument(); });Copy the code

Similar to queryByText, this only does not return NULL, so we do not make non-null assertions

Query by container

It (" Render the title component correctly through the container's query", () => {const title = "test title "; const { container } = render(<TodoHeader title={title} />); const titleElement = container.querySelector("span"); expect(titleElement).toHaveTextContent(title); });Copy the code

Render will return a container, and we can use the container’s querySelector method to query the corresponding node. In this case, our title property is in the span tag, and there is only one, so it’s easier to write a selector. Write span, get the node, and assert that the node’s textContent is equal to title

Query by testid

We add the data-testid property to the previous component to set our agreed ID

<div className="report-header">
  <span className="title" data-testid="todo-header-title">
    {title}
  </span>
</div>
Copy the code
It (" correctly render the title component by getByTestId", () => {const title = "Test title "; const { getByTestId } = render(<TodoHeader title={title} />); const titleElement = getByTestId("todo-header-title"); expect(titleElement).toHaveTextContent(title); });Copy the code

Complete test cases

import { render, screen } from "@testing-library/react"; import TodoHeader from ".. /todo-header"; Describe (" test TodoHeader component ", () => {it(" correct render title component ", () => {const title = "test title "; render(<TodoHeader title={title} />); const titleElement = screen.getByText(title); expect(titleElement).toBeInTheDocument(); }); It (" Render the title component correctly by queryByTest", () => {const title = "test title "; const { queryByText } = render(<TodoHeader title={title} />); const titleElement = queryByText(title); expect(titleElement).not.toBeNull(); expect(titleElement).toBeInTheDocument(); }); It (" Render the title component correctly by getByText", () => {const title = "test title "; const { getByText } = render(<TodoHeader title={title} />); const titleElement = getByText(title); expect(titleElement).toBeInTheDocument(); }); It (" Render the title component correctly through the container's query", () => {const title = "test title "; const { container } = render(<TodoHeader title={title} />); const titleElement = container.querySelector("span"); expect(titleElement).toHaveTextContent(title); }); It (" correctly render the title component by getByTestId", () => {const title = "Test title "; const { getByTestId } = render(<TodoHeader title={title} />); const titleElement = getByTestId("todo-header-title"); expect(titleElement).toHaveTextContent(title); }); });Copy the code

So let’s run the result

At the end

Due to the space problem, I will write here first. There are still many things about the single test, so I will introduce a scene and continue to supplement it later

Learn how to use the React component. Learn how to use the React component. Learn how to use the React component