使用反应测试库和React-Router V6测试重定向时,DOM DO不会更新

发布于 2025-02-04 12:05:10 字数 2160 浏览 3 评论 0原文

当用户单击按钮时,我正在尝试测试重定向页面(我不想使用用户jest.mock())。 我根据test-test-react-library文档:

import { FC, ReactElement, ReactNode } from "react";
import { render, RenderOptions } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import userEvent from "@testing-library/user-event";

const WrapperProviders: FC<{ children: ReactNode }> = ({ children }) => {
  return <BrowserRouter>{children}</BrowserRouter>;
};

const customRender = (
  ui: ReactElement,
  { route = "/" } = {},
  options?: Omit<RenderOptions, "wrapper">
) => {
  window.history.pushState({}, "Home Page", route);
  return {
    user: userEvent.setup(),
    ...render(ui, { wrapper: WrapperProviders, ...options })
  };
};

export * from "@testing-library/react";
export { customRender as render };
export type RenderType = ReturnType<typeof customRender>;

homepage.tsx:

import { useNavigate } from "react-router-dom";

export default function HomePage() {
  const navigate = useNavigate();

  const handleClick = () => navigate("/other");
  return (
    <>
      <h3>HomePage</h3>
      <button onClick={handleClick}>Redirect</button>
    </>
  );
}

shomepage.tsx:

export default function Other() {
  return <h3>Other</h3>;
}

homepage.test.tsx:

import { render, RenderType } from "./customRender";
import HomePage from "./HomePage";
import "@testing-library/jest-dom/extend-expect";

describe("HomePage", () => {
  let wrapper: RenderType;
  beforeEach(() => {
    wrapper = render(<HomePage />, { route: "/" });
  });

  test.only("Should redirects to other page", async () => {
    const { getByText, user } = wrapper;

    expect(getByText(/homepage/i)).toBeInTheDocument();

    const button = getByText(/redirect/i);
    expect(button).toBeInTheDocument();
    user.click(button);
    expect(getByText(/other/i)).toBeInTheDocument();
  });
});

在我运行测试时,它失败,并且页面未更新在dom。 开玩笑是否不支持页面的重新渲染并更新DOM?还是该测试范围不在测试范围内?

I'm trying to test the redirection page when the user clicks on the button (I don't want to user jest.mock()).
I created the wrapper according to test-react-library documentation:

import { FC, ReactElement, ReactNode } from "react";
import { render, RenderOptions } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import userEvent from "@testing-library/user-event";

const WrapperProviders: FC<{ children: ReactNode }> = ({ children }) => {
  return <BrowserRouter>{children}</BrowserRouter>;
};

const customRender = (
  ui: ReactElement,
  { route = "/" } = {},
  options?: Omit<RenderOptions, "wrapper">
) => {
  window.history.pushState({}, "Home Page", route);
  return {
    user: userEvent.setup(),
    ...render(ui, { wrapper: WrapperProviders, ...options })
  };
};

export * from "@testing-library/react";
export { customRender as render };
export type RenderType = ReturnType<typeof customRender>;

HomePage.tsx:

import { useNavigate } from "react-router-dom";

export default function HomePage() {
  const navigate = useNavigate();

  const handleClick = () => navigate("/other");
  return (
    <>
      <h3>HomePage</h3>
      <button onClick={handleClick}>Redirect</button>
    </>
  );
}

Other.tsx:

export default function Other() {
  return <h3>Other</h3>;
}

HomePage.test.tsx:

import { render, RenderType } from "./customRender";
import HomePage from "./HomePage";
import "@testing-library/jest-dom/extend-expect";

describe("HomePage", () => {
  let wrapper: RenderType;
  beforeEach(() => {
    wrapper = render(<HomePage />, { route: "/" });
  });

  test.only("Should redirects to other page", async () => {
    const { getByText, user } = wrapper;

    expect(getByText(/homepage/i)).toBeInTheDocument();

    const button = getByText(/redirect/i);
    expect(button).toBeInTheDocument();
    user.click(button);
    expect(getByText(/other/i)).toBeInTheDocument();
  });
});

When I run the test, it fails and the page is not updated in the dom.
Does jest-dom does not support the re-render of the page and update the DOM? Or this test out of scope of the testing-library ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

走走停停 2025-02-11 12:05:10

从代码中,我可以看到您只是在渲染主页组件,并且在该组件内部您没有任何逻辑可以根据路由更改呈现新组件(我想您有那个另一个组件上的逻辑)。这就是为什么当您单击按钮时,您没有看到其他组件呈现的。

在这种情况下,我建议您仅在 window.location 对象上做出所需的断言。因此,在模拟单击按钮之后,您可以执行以下操作:

expect(window.location.pathname).toBe("/other");

From the code I can see that you are just rendering the HomePage component and inside of that component you don't have any logic that renders a new component based on the route changes (I suppose that you have that logic on another component). That's why when you click on the button you are not seeing the Other component rendered.

In this case I would suggest you to only make the assertions you need on the window.location object. So after you simulate the click on the button you can do:

expect(window.location.pathname).toBe("/other");
过气美图社 2025-02-11 12:05:10

我更新了自定义渲染并为其添加历史记录:

const WrapperProviders: FC<{ children: ReactNode }> = ({ children }) => {
  return <BrowserRouter>{children}</BrowserRouter>;
};

const customRender = (
  ui: ReactElement,
  { route = "/",
    history = createMemoryHistory({initialEntries: [route]}),
   } = {},
  options?: Omit<RenderOptions, "wrapper">
) => {
  return {
    user: userEvent.setup(),
    ...render( <Router location={history.location} navigator={history}>
         ui
        </Router>
     , { wrapper: WrapperProviders, ...options })

  };
};

现在测试通过:

describe("HomePage", () => {
  let wrapper: RenderType;
  beforeEach(() => {
    wrapper = render(<HomePage />, { route: "/" });
  });

  test.only("Should redirects to other page", async () => {
    const { getByText, user, history } = wrapper;

    expect(getByText(/homepage/i)).toBeInTheDocument();

    const button = getByText(/redirect/i);
    expect(button).toBeInTheDocument();
    await user.click(button);
    expect(history.location.pathname).toBe('/other');
});

I updated the custom render and add a history for it:

const WrapperProviders: FC<{ children: ReactNode }> = ({ children }) => {
  return <BrowserRouter>{children}</BrowserRouter>;
};

const customRender = (
  ui: ReactElement,
  { route = "/",
    history = createMemoryHistory({initialEntries: [route]}),
   } = {},
  options?: Omit<RenderOptions, "wrapper">
) => {
  return {
    user: userEvent.setup(),
    ...render( <Router location={history.location} navigator={history}>
         ui
        </Router>
     , { wrapper: WrapperProviders, ...options })

  };
};

and the test now passes:

describe("HomePage", () => {
  let wrapper: RenderType;
  beforeEach(() => {
    wrapper = render(<HomePage />, { route: "/" });
  });

  test.only("Should redirects to other page", async () => {
    const { getByText, user, history } = wrapper;

    expect(getByText(/homepage/i)).toBeInTheDocument();

    const button = getByText(/redirect/i);
    expect(button).toBeInTheDocument();
    await user.click(button);
    expect(history.location.pathname).toBe('/other');
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文