如何使用react-testing-library和jest测试链接

Jua*_*llo 5 reactjs jestjs react-router-dom react-testing-library

正在努力学习测试。使用测试库、Jest、React-Router v6 和 Typescript。我正在尝试找出如何测试链接。我一直在到处寻找解决方案,但找不到。使用 React-Router v6。代码如下所示(链接只是带有 href 的常规元素),只是想确保用户到达新页面(在本例中是来自忘记密码页面的登录页面)。

//omitted imports but imported all appropriate items from below

describe('ForgotPassword', () => {
  test('User can navigate to login screen', async () => {
    render(
      <MemoryRouter initialEntries={['/forgot-password' ]}>
        <ForgotPassword />
      </MemoryRouter>)

    userEvent.click(screen.getByRole('link', { name: 'Back to Login' }))

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Login' })).toBeInTheDocument()
    })
  })

//also tried:

describe('ForgotPassword', () => {
  test('User can navigate to login screen', async () => {
    render(
      <MemoryRouter initialEntries={['/forgot-password' ]}>
        <Routes>
            <Route path='/forgot-password' component={<ForgotPassword />} />
            <Route path='/login' component={<Login />} />
        <Routes>
      </MemoryRouter>)

    userEvent.click(screen.getByRole('link', { name: 'Back to Login' }))

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Login' })).toBeInTheDocument()
    })
  })

//also tried the following:

const history = createMemoryHistory({ initialEntries: ['/home'] });
    const { getByText } = render(
      <Router history={history}>
        <ButtonLogin />
      </Router>
    );

got a TS error: Property 'history' does not exist on type 'IntrinsicAttributes & RouterProps'.

//also tried using fireEvent instead of userEvent
Run Code Online (Sandbox Code Playgroud)

lor*_*mer 6

@exaucae 的答案对于普通人来说是完美的LinkreloadDocument如果您在 中使用Link,您的测试将失败,并且控制台将显示一条错误,内容为“错误:未实现:导航(哈希更改除外)”。

我想在链接中使用reloadDocument,以便在用户导航时刷新我的整个应用程序。以下是我测试这些链接的方法。这不是我更愿意测试它们的方式,但它让我确信这些链接正在工作。

// NavMenu.tsx
import React from "react";
import { Link } from "react-router-dom";

export const NavMenu = () => {
    return (
        <div data-testid={"nav-menu"}>
            <Link reloadDocument to={"/some-page"}>Some Page</Link>
        </div>
    );
};


// NavMenu.test.tsx
import { NavMenu } from "./NavMenu";
import { render, screen } from "@testing-library/react";
import React from "react";
import { MemoryRouter, Route, Routes } from "react-router-dom";

describe(NavMenu.name, () => {
    test("should link", () => {
        render(
            <MemoryRouter>
                <Routes>
                    <Route path="/" element={<NavMenu/>}/>
                </Routes>
            </MemoryRouter>,
        );
        const links: HTMLAnchorElement[] = screen.getAllByRole("link");

        expect(links[0].textContent).toEqual("Some Page");
        expect(links[0].href).toContain("/some-page");
    });
Run Code Online (Sandbox Code Playgroud)

我还将围绕调用实现我自己的包装器,它总是Link具有. 这样,任何其他想要添加链接的开发人员都可以遵循该模式并使用 a ,而不必考虑它是否刷新。RefreshingLinkreloadDocumentNavMenuRefreshingLink


exa*_*cae 3

你的第二次尝试几乎很好。你必须在react-router v6.x中将componentprop更改为element


describe('ForgotPassword', () => {
  test('User can navigate to login screen', async () => {

    function ForgotPassword() {
      return (
        <div>
          <h1>Home</h1>
          <Link to="../login">Back to Login</Link>
        </div>
      );
    }
    render(
      <MemoryRouter initialEntries={['/forgot-password' ]}>
        <Routes>
            <Route path='/forgot-password' element={<ForgotPassword/>} />
            <Route path='/login' element={<h1>Login</h1>} />
        <Routes>
      </MemoryRouter>)

    userEvent.click(screen.getByRole('link', { name: 'Back to Login' }))

    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Login' })).toBeInTheDocument()
    })
  })
})
Run Code Online (Sandbox Code Playgroud)

注意:每当有疑问时,React-router-dom的内部测试是获得提示的好方法。