preface
In the last article we have had a preliminary experience of component single test, next we will add some common cases for component single test
Determine the style
In react Component, it is common to use some fields to control some styles, or pass in some styles through props. We need to check whether these styles are correctly rendered through single test
Modify the components
Add an optional containerStyle parameter to the TodoHeader component that controls the style of the outermost container
import "./index.css"; Interface TodoHeaderProps {// Title: string; containerStyle? : React.CSSProperties; } export default function TodoHeader({ title, containerStyle }: TodoHeaderProps) { return ( <div className="report-header" style={containerStyle}> <span className="title" data-testid="todo-header-title"> {title} </span> </div> ); }Copy the code
Call modify, add style input parameter
<TodoHeader title=" This is a title "containerStyle={{border: "1px solid blue"}} />Copy the code
Let’s run this to see the effect, PNPM start, and see that the border style is rendered correctly
A single measurement to write
It (' correctly render containerStyle ', () => {const borderStyle = "1px solid blue"; const containerStyle: CSSProperties = { border: borderStyle, }; Const {container} = render(<TodoHeader title=" title "containerStyle={container style} />); expect(container.children[0]).toHaveStyle(`border: ${borderStyle}`); });Copy the code
Here we use an API, toHaveStyle, to determine if our style has been rendered. Because our style is mounted on the top div, we simply use container. Children [0] to fetch the div. Of course it can be changed to the same method we used in the last article. Then let’s execute the test case
pnpm test src/components/__tests__/todo-header.test.tsx
Copy the code
The results are as follows:
Let’s try the failure case. Now if we change the style, let’s see if the use case will fail. Here we change the style of the input parameter to 2px
It (' correctly render containerStyle ', () => {const borderStyle = "1px solid blue"; const containerStyle: CSSProperties = { border: "2px solid blue", }; Const {container} = render(<TodoHeader title=" title "containerStyle={container style} />); expect(container.children[0]).toHaveStyle(`border: ${borderStyle}`); });Copy the code
The expected and received use-cases did not pass the expected and received use-cases did not pass the expected and received use-cases did not pass the expected and received use-cases did not pass the use-cases
Determine the field control style
In a real project, we would pass in some fields and then display different styles. The most common is to display different styles in various states. Here we simulate this scenario
Modify the components
Rewrite the previous code and add an isFinish field to display different backgrounds
import "./index.css"; Interface TodoHeaderProps {// Title: string; // The outermost containerStyle? : React.CSSProperties; // Whether to finish isFinish? : boolean; } export default function TodoHeader({ title, containerStyle, isFinish = false, }: TodoHeaderProps) { return ( <div className="report-header" style={containerStyle}> <span className="title" data-testid="todo-header-title" style={{ background: isFinish ? "red" : "white" }} > {title} </span> </div> ); }Copy the code
Change the call entry code to see the effect, you can see the effect is there (style what not to mock, after all, just to do a single test write)
<TodoHeader title=" This is a title "containerStyle={{border: "1px solid blue"}} isFinish={true} />Copy the code
A single measurement to write
GetByTestId and toHaveStyle to get you started
() => {const {getByTestId} = render(<TodoHeader title=" title "isFinish={true} />); const element = getByTestId("todo-header-title"); expect(element).toHaveStyle(`background: red`); });Copy the code
The results
And don’t forget here, we also have a case where it’s false, because ourisFinish
Boolean, only true or false, we have tested the true case above, let’s make sure that the false case also works
() => {const {getByTestId} = render(<TodoHeader title=" title "isFinish={false} />); const element = getByTestId("todo-header-title"); expect(element).toHaveStyle(`background: white`); });Copy the code
The results
Determine properties
In the React Component, it is also common to set attributes to elements, such as passing in the image URL and displaying it correctly in the component. In this case, we can write tests
Rewrite the component
We’re going to add an additional iconUrl entry, and if it comes in we’re going to display it with the IMG tag, look at the code
import "./index.css"; Interface TodoHeaderProps {// Title: string; // The outermost containerStyle? : React.CSSProperties; // Whether to finish isFinish? : boolean; // Icon link iconUrl? : string; } export default function TodoHeader({ title, containerStyle, iconUrl, isFinish = false, }: TodoHeaderProps) { return ( <div className="report-header" style={containerStyle}> {iconUrl && <img src={iconUrl} />} <span className="title" data-testid="todo-header-title" style={{ background: isFinish ? "red" : "white" }} > {title} </span> </div> ); }Copy the code
A single measurement to write
We’re using toHaveAttribute, so you have to pay attention to the input to this API, and we’re using waitFor, so we’re not going to go into that, we’re going to talk about it in more detail
It (` render correct figure mark `, async () = > {const iconUrl = "http://www.abc.com/test.png"; Const {container} = render(<TodoHeader title=" title "iconUrl={iconUrl} />); await waitFor(() => { const imgElement = container.querySelector("img"); expect(imgElement).not.toBeNull(); expect(imgElement).toHaveAttribute("src", iconUrl); }); });Copy the code
The results
Judgment of the children
Children is also relatively common in the component, which gives the component more functions similar to slots. Here is a brief description of my method to judge children. In fact, the idea is relatively simple, but after passing in children, I can judge whether it can be displayed normally by obtaining elements
Rewrite the component
Increased the entry of children using PropsWithChildren directly to show children
import "./index.css"; import { PropsWithChildren } from "react"; Interface TodoHeaderProps {// Title: string; // The outermost containerStyle? : React.CSSProperties; // Whether to finish isFinish? : boolean; // Icon link iconUrl? : string; } export default function TodoHeader({ title, containerStyle, iconUrl, isFinish = false, children, }: PropsWithChildren<TodoHeaderProps>) { return ( <div className="report-header" style={containerStyle}> {iconUrl && <img src={iconUrl} />} <span className="title" data-testid="todo-header-title" style={{ background: isFinish ? "red" : "white" }} > {title} </span> {children} </div> ); }Copy the code
A single measurement to write
It (' render children correctly ', async () => {const id = "childrenId"; Const text = "This is a copy "; Const {getByTestId} = render(<TodoHeader title=" title "> <span data-testid={id}>{text}</span> </TodoHeader>); const childElement = getByTestId(id); expect(childElement).toHaveTextContent(text); });Copy the code
The results
Judge ReactNode
Similar to children, the judgment methods are basically the same
Rewrite the component
import "./index.css"; import { PropsWithChildren, ReactNode } from "react"; Interface TodoHeaderProps {// Title: string; // The outermost containerStyle? : React.CSSProperties; // Whether to finish isFinish? : boolean; // Icon link iconUrl? : string; // Additional information extraInfo? : ReactNode; } export default function TodoHeader({ title, containerStyle, iconUrl, isFinish = false, children, extraInfo, }: PropsWithChildren<TodoHeaderProps>) { return ( <div className="report-header" style={containerStyle}> {iconUrl && <img src={iconUrl} />} <span className="title" data-testid="todo-header-title" style={{ background: isFinish ? "red" : "white" }} > {title} </span> <span className="extra">{extraInfo}</span> {children} </div> ); }Copy the code
A single measurement to write
It (' render extraInfo correctly ', async () => {const id = "extraId"; Const text = "This is a copy "; Const {getByTestId} = render(<TodoHeader title=" "extraInfo={<span data-testid={id}>{text}</span>} />); const childElement = getByTestId(id); expect(childElement).toHaveTextContent(text); });Copy the code
The results
At the end
This blog post has supplemented some of the component tests in other cases and put some of my own experience into the demo. The complete code can be seen in the COMMIT
Series of articles: Learn how to react with fireEvent. Learn how to react with fireEvent. Learn how to react with fireEvent. Github.com/liyixun/rea…