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