gpt4 book ai didi

reactjs - 在 react-router 的路由内进行基于路由的测试的推荐方法

转载 作者:行者123 更新时间:2023-12-05 09:07:14 25 4
gpt4 key购买 nike

我正在我的一个项目中使用 react-testing-library,并尝试编写验证应用内路由的测试。

例如测试 AccessDenied 页面上的按钮是否会将您带回主页。

我已经能够为我的 App 组件成功编写这些类型的测试,因为它定义了所有应用程序路由。但是,如果 AccessDenied 是这些路由之一,我需要如何设置我的测试以验证单击那里的按钮会将我路由回主页?

这是一个人为的例子:

应用.tsx

<>
<Router>
<Route exact path="/" component={Home} />
<Route exact path="/access-denied" component={AccessDenied} />
</Router>
<Footer />
</>

拒绝访问.tsx

<div>
<div>Access Denied</div>
<p>You don't have permission to view the requested page</p>
<Link to="/">
<button>Go Home</button> <--- this is what i want tested
</Link>
</div>

正如我之前所说,我的测试在 App.test.tsx 中工作的原因是因为我的 App 组件在其内部定义了路由,而我的 AccessDenied 只是其中之一那些路线。但是,是否可以在我的 AccessDenied.test.tsx 测试中利用我的 App.tsx 中定义的路由器?也许我没有正确地解决这个问题?那就是我挣扎的地方。作为引用,这是我的工作 App.test.tsx 测试。

应用程序测试.tsx

describe('App', () => {
it('should allow you to navigate to login', async () => {
const history = createMemoryHistory()
const { findByTestId, getByTestId } = render(
<MockedProvider mocks={mocks} addTypename={false}>
<AuthContext.Provider
value={{
authState: AUTH_STATES.UNAUTHENTICATED,
}}
>
<Router history={history}>
<App />
</Router>
</AuthContext.Provider>
</MockedProvider>,
)

fireEvent.click(getByTestId('sidebar-login-button'))
expect(await findByTestId('login-page-login-button')).toBeInTheDocument()

fireEvent.click(getByTestId('login-page-register-button'))
expect(await findByTestId('register-page-register-button')).toBeInTheDocument()
})
})

如有任何想法或建议,我们将不胜感激!

最佳答案

如果您考虑 AccessDenied 组件的职责,它实际上并不是将用户发送到home。这就是您想要的整体行为,但组件在其中的作用只是将用户发送到 "/"。因此,在组件单元级别,测试可能看起来像这样:

import React, { FC } from "react";
import { Link, Router } from "react-router-dom";
import { fireEvent, render, screen } from "@testing-library/react";
import { createMemoryHistory } from "history";

const AccessDenied: FC = () => (
<div>
<div>Access Denied</div>
<p>You don't have permission to view the requested page</p>
<Link to="/">
<button>Go Home</button>
</Link>
</div>
);

describe("AccessDenied", () => {
it("sends the user back home", () => {
const history = createMemoryHistory({ initialEntries: ["/access-denied"] });
render(
<Router history={history}>
<AccessDenied />
</Router>
);

fireEvent.click(screen.getByText("Go Home"));

expect(history.location.pathname).toBe("/");
});
});

请注意 "/" 是默认路径,因此如果您不提供 initialEntries 测试会通过,即使点击没有做任何事情...

此时您可能会想“但是如果主页路线发生变化怎么办?”如果您将主页移动到“/home”,例如,这测试将继续通过,但应用程序将不再实际工作。这是过度依赖非常低级别的测试的常见问题,也是更高级别测试发挥作用的地方,包括:

  • 集成:渲染整个App,使用fireEvent模拟导航。这在您当前的设置中具有挑战性,因为 Router 处于 App 级别;我会将 Router 移动到 index.tsx 并在 App.tsx 中有一个 Switch,所以你可以在 MemoryRouter 中呈现 App 或使用我上面显示的 createMemoryHistory 方法(例如,我在 this starter kit 中完成了此操作)。

  • 端到端:使用浏览器驱动程序(例如 Cypress 或各种基于 Selenium 的选项)自动执行用户与应用的实际交互。

我还没有展示路由测试,但是涵盖了一个简单的 React 应用程序的这些不同级别的测试 on my blog .


在 React Router v6 中,您需要稍微更新 Router 用法(详情请参阅 "Cannot read properties of undefined (reading 'pathname')" when testing pages in the v6 React Router):

render(
<Router location={history.location} navigator={history}>
<AccessDenied />
</Router>
);

关于reactjs - 在 react-router 的路由内进行基于路由的测试的推荐方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65270992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com