preface

In the previous article, we have learned a lot of knowledge about single test. In this article, we will add a knowledge point to test functions related to timer. In js setTimeout setInterval clearTimeout clearTimeout, clearInterval these are very important API, occasionally used in our development, generally use the react of course they will try to avoid these, Unless it's really necessary. We also need the ability to respond to these timer apis to test the timer.Copy the code

Writing a Timeout component

Since none of our previous components used timers, we will write a component that uses timers and create a todo-Timer component in the Components directory

import { useState, useEffect } from "react"; export default function TodoTimer() { const [todoContent, setTodoContent] = useState(""); UseEffect () => {const timerId = setTimeout(() => {setTodoContent(" delay the content after 1s "); }, 1000); return () => { clearTimeout(timerId); }; } []); return <span>{todoContent}</span>; }Copy the code

This component starts the timer with setTimeout, starts the timer after initialization, changes the content and renders it to the view for 1s, and finally clearTimeout clears the side effects to see the effect. Introduced in app.tsx, you can see the content changes after 1s

Write a Timeout single test

As before we will create the corresponding single test file in the components/__tests__ directory and name it todo-timer.test.tsx

import { act, render } from "@testing-library/react"; import TodoTimer from ".. /todo-timer"; Describe (" test TodoTimer component ", () => {it(" correct running of timer ", async () => {jest. UseFakeTimers (); const { queryByText } = render(<TodoTimer />); act(() => { jest.runAllTimers(); }); Const element = queryByText(" delay content for 1s "); expect(element).not.toBeNull(); }); });Copy the code

Let’s run this single test

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

Here we use two new jest apis, which we’ll briefly explain

  • Jest. UseFakeTimers (): simulates the execution of the timer without waiting for the specified time
  • Jest. RunAllTimers (): Executes all timers

Here we use these two apis to run timers, because in practical applications, the waiting time of our timers may be very long, and our single test purpose is to ensure that our input and output meet expectations. It is not meaningful and unrealistic to wait by the events set by the timer. So we can run the execution of the analog timer directly through these two apis. The next step is to determine if there is any output on the page that meets expectations, basically as we did before.

Writing the Interval component

We wrote a setTimeout example above, and here we add a setIntervael example, creating a todo-interval component

import { useState, useEffect } from "react"; export default function TodoInterval({ callback }: { callback: () => void }) { const [todoContent, setTodoContent] = useState(""); UseEffect (() => {const timerId = setInterval(() => {setTodoContent(" delay content after 1s "); callback(); }, 1000); return () => { clearInterval(timerId); }; }, [callback]); return <span>{todoContent}</span>; }Copy the code

Unlike the timeout component above, we have added a callback, which is called when the timer takes effect

Write Interval single test

import { act, render } from "@testing-library/react"; import TodoInterval from ".. /todo-interval"; Describe (" test TodoInterval component ", () => {it(" run timer correctly ", async () => {jest. UseFakeTimers (); const callback = jest.fn(); render(<TodoInterval callback={callback} />); act(() => { jest.runOnlyPendingTimers(); }); expect(callback).toBeCalled(); }); });Copy the code

Here, we added a new API, jest. RunOnlyPendingTimers (); And the difference between this and runAllTimer is that this API is mainly used to deal with cases where there are loop timers, like setTimeout nested setTimeout or setInterval and look at the result

At the end

Series of articles: Learn how to use the React component. Learn how to use the React component. Use fireEvent Mock code Repository: github.com/liyixun/rea… mock code repository: mock code repository: github.com/liyixun/rea…