reactjs 解决React测试库中的act()警告

snz8szmq  于 2023-06-29  发布在  React
关注(0)|答案(1)|浏览(120)

我正在尝试测试我的组件,测试通过了,但是我不断收到关于终端中正在更新的状态片段的act警告:“警告:测试中对Bird的更新未包含在act(...)中。“
该警告是指const handleRemoveBird = () => { setShowModal(true); };状态更新。
这是不是与连接到Modal组件的状态有关,并且它在测试之外更新?如果是这种情况(或不是),我需要等待/等待什么来修复行为警告?
我的测试:

import { screen, waitFor } from "@testing-library/react";
import user from "@testing-library/user-event";
import { renderWithProviders } from "../utils/utils-for-tests";
import Bird from "../components/Bird";

const modalContainerMock = document.createElement("div");
modalContainerMock.setAttribute("class", "modal-container");
document.body.appendChild(modalContainerMock);

const birdImgMock = jest.mock("../../components/BirdImg", () => {
  return () => {
    return "Bird Img Component";
  };
});

const renderComponent = (bird) => {
  renderWithProviders(<Bird bird={bird} />);
};

const bird = {
  id: "1",
  name: "blue tit",
  number: "5",
};

test("shows modal before removal", async () => {
  renderComponent(bird);
  const removeButton = await screen.findByTestId(`removeButton-${bird.id}`);
  expect(removeButton).toBeInTheDocument();

  user.click(removeButton);

  await waitFor(() => {
    expect(screen.getByTestId("modal")).toBeInTheDocument();
  });
});
...

我的组件:

import { useState } from "react";
import { RxCross2 } from "react-icons/rx";
import { useRemoveBirdMutation } from "../store";
import Panel from "./Panel";
import Button from "./Button";
import Modal from "./Modal";
import Sightings from "./Sightings";
import BirdImg from "./BirdImg";

function Bird({ bird }) {
  const [removeBird, removeBirdResults] = useRemoveBirdMutation();
  const [showModal, setShowModal] = useState(false);

  const handleRemoveBird = () => {
    setShowModal(true);
  };
  const handleClose = () => {
    setShowModal(false);
  };
  const handleDelete = () => {
    removeBird(bird);
    setShowModal(false);
  };

  const actionBar = (
    <>
      <Button primary onClick={handleClose}>
        Keep
      </Button>

      <Button secondary onClick={handleDelete}>
        Delete
      </Button>
    </>
  );

  const modal = (
    <Modal actionBar={actionBar} onClose={handleClose}>
      <p>Are you sure you want to delete this bird?</p>
    </Modal>
  );
  return (
    <>
      <Panel
        primary
        data-testid="bird"
        key={bird.id}
        className="grid grid-cols-5 md:gap-5"
      >
        <div className="col-span-2">
          <BirdImg name={bird.name} />
        </div>

        <div className="col-span-2 grid content-around -ml-4 md:-ml-8">
          <h4 className="capitalize text-lg font-bold md:text-3xl ">
            {bird.name}
          </h4>
          <div>
            <Sightings bird={bird} />
          </div>
        </div>
        <div className="col-span-1 justify-self-end">
          <Button
            onClick={handleRemoveBird}
            remove
            loading={removeBirdResults.isLoading}
            data-testid={`removeButton-${bird.id}`}
          >
            <RxCross2 />
          </Button>
        </div>
      </Panel>
      {showModal && modal}
    </>
  );
}
export default Bird;
xuo3flqw

xuo3flqw1#

一个对我有用的解决方案,你可能需要把click事件 Package 在waitFor里面。

test("shows modal before removal", async () => {
  renderComponent(bird);
  const removeButton = await screen.findByTestId(`removeButton-${bird.id}`);
  expect(removeButton).toBeInTheDocument();

  await waitFor(async () => {
    await user.click(removeButton);
  });

  expect(screen.getByTestId("modal")).toBeInTheDocument();
});

相关问题