preface

In the previous article, we mainly studied various scenarios about react component mono tests. We can cover the basic scenarios of react component mono tests. Today, we will add a new concept: snapshot tests.

A snapshot of the test

Before, can we to review articles have mentioned the effect of single measurement as well as on research and development process of some benefits, here we are, for example, can appear some modules in the practical project we write is not good then for code refactoring, renovation is completed we need for our refactoring or after transforming the function of the smoke tests, The snapshot test is also an effective means to ensure smoke in a single test. Snapshot testing is a very useful tool if we want to make sure that there are no additional changes to our UI. The typical approach is to save a snapshot file after rendering the UI component, and check whether the snapshot file matches the snapshot file saved on the side of the single test. If the two snapshot files do not match, the test is considered to have failed, and there may be additional changes made, or the UI component has been updated to a new version.

Write a new component

Let’s create a new todo-Content folder in the Components directory for the components we use for snapshot testing

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

The component content

import { Card, Input } from "antd";

const { TextArea } = Input;

interface TodoContentProps {
  title: string;
  content: string;
}

export default function TodoContent({ title, content }: TodoContentProps) {
  return (
    <Card title={title} style={{ width: 300 }}>
      <TextArea rows={4} value={content} />
    </Card>
  );
}
Copy the code

Called in app.tsx

<TodoContent title=" This is the title "content=" This is a very long content..." />Copy the code

PNPM start PNPM start

A snapshot of the preliminary

As in the previous example, we write a single test for the TodoContent component and create a single test file todo-content.test.tsx for the component in the SRC/Components /__tests__ directory

import { render } from "@testing-library/react"; import TodoContent from ".. /todo-content"; Const TITLE = "This is a TITLE "; Const CONTENT = "This is a CONTENT "; Describe (" test TodoContent", () => {it(" correctly render TodoContent component ", () => { const { queryByText } = render( <TodoContent title={TITLE} content={CONTENT} /> ); const titleElement = queryByText(TITLE); const contentElement = queryByText(CONTENT); expect(titleElement).not.toBeNull(); expect(titleElement).toBeInTheDocument(); expect(contentElement).not.toBeNull(); expect(contentElement).toBeInTheDocument(); }); Const {asFragment} = render(<TodoContent title={title} content={content} />); expect(asFragment()).toMatchSnapshot(); }); });Copy the code

Run the single test

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

Look at the effect

When we look at the sibling of our single test file, __snapshots__ already appears and a todo-content.test.tsx.snap is generated

Take a look at the contents of the snapshot

// Jest Snapshot v1, https://goo.gl/fbAQLP exports[' tests TodoContent to match snapshot 1 '] = '<DocumentFragment> <div class="ant-card ant-card-bordered" style="width: 300px;" > <div class="ant-card-head" > <div class="ant-card-head-wrapper" > <div class="ant-card-head-title" > This is a title </div> </div> <div class="ant-card-body" > <textarea class="ant-input" rows="4" > This is a content </textarea> </div> </div> </DocumentFragment> `;Copy the code

You can see that according to our Render component a DOM structure is then created and saved, since it is run for the first time, there is no matching snapshot. Let’s take a look at the single test we just wrote. We use the asFragment method after render. From this method we generate a document-like structure and then the assertion part. We match the snapshot with the toMatchSnapshot method. We change the parameters of our component and rerun the single test

Const {asFragment} = render(<TodoContent title={title} content=" /> ");Copy the code

Rerun the single test to see the results

In addition to this common component input, we can change the component’s style and change the width to 400 to see if the snapshot matches

<Card title={title} style={{ width: 400 }}>
  <TextArea rows={4} value={content} />
</Card>
Copy the code

It can be seen that at this time our snapshot matching is also failed, and in the error message is also clearly indicated that we failed to match the style, which also gives us the direction of modification

Update the snapshot

As we can see from the above example, when we wrote the single test, our Snap was generated during the first run. Some of our changes were actually fine, but the match was always wrong because the snapshot was not updated. Jest’s updateSnapshot command is used to update the snapshot. In package.json, we add a command to update the snapshot

"updateSnapshot": "react-scripts test --updateSnapshot"
Copy the code

Run this command

At this point we look at our snapshot file and the width style we changed has been correctly updated to the snapshot file

Inline snapshot

Inline snapshot in the author’s actual application this is basically unused, more common is the above situation, directly generated a snapshot file, inline snapshot and ordinary snapshot (.snap file) performance is the same, but the snapshot value will be automatically written into the source code. This means you can benefit from automatically generated snapshots without having to switch to an extra generated snapshot file to make sure the values are correct.

Please refer to the official documentation for details

Customizing snapshot content

In the above code, we are using a snippet to save a snapshot. In fact, we can customize the contents of the snapshot, in addition to the above snippet, such as JSON, or object strings, etc., can be our custom snapshot content

Let’s write a single test of custom snapshot content

Describe (" test snapshot content of custom object ", () => {it(" match snapshot correctly ", () => {const user = {name: "eason", age: 18,}; expect(user).toMatchSnapshot({ name: "eason", age: 18, }); }); });Copy the code

Then run the single test to generate the snapshot file

As you can see, we generated our snapshot files in a customized way, which gives us a lot of flexibility

Some experience

  1. Think of the snapshot file as code, and the generated snapshot file should also be submitted as a commit
  2. Use reasonable snapshot descriptions to describe your tests and snapshots well. The best description name is to write out what is expected to be returned. This made it easier for us to validate the snapshot during code review and let anyone know that the snapshot was out of date before making changes to the code.

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…