模拟的 useNavigate for Jest 似乎没有更新路径

问题描述 投票:0回答:1

我有一个多步骤表单,目前正在编写一个玩笑测试来检查用户是否可以按预期从步骤 1 移动到步骤 2。 在测试中,我可以看到 currentStep 状态随着标题的变化而更新,但表单元素保持不变。

应该发生的是,navigate() 应该将用户移动到步骤 2,这将显示 /step2 的新路径和新的表单元素。

我可以看到 useNavigate 已被称为它只是没有更新路径,我不知道为什么。

这是我开玩笑地调用的提交函数:

const onSubmit = () => {
    nextStep();
    navigate(`step${currentStep + 1}`);
  };

nextStep 工作正常,记录 currentStep 显示为 1,但导航似乎没有触发。 测试如下:

test('Move to the next step after form field is valid & submitted', async () => {
    render(
      // manually updating this to step2 shows the correct step in the form
      <MemoryRouter initialEntries={['/signup/step1']}>
        <Routes>
          <Route
            path="/signup/*"
            element={
              <Form/>
            }
          />
        </Routes>
      </MemoryRouter>,
    );

    await fillUserInfo();

    await clickSubmit();

    await waitFor(() => {
      expect(screen.getByText('Step2')).toBeInTheDocument();
      screen.debug();
    });
  });

就像我之前所说的那样,Step2 文本显示为根据 nextStep() 中控制的 currentStep 状态进行更新,因此该测试显示为有效,但当我在此处放置 screen.debug 时,实际的表单元素仍然是 step1。

环顾了一下SO和更大的网络,我所能找到的只是人们检查useNavigate是否被调用,我可以确认它被调用,但我正在尝试更新实际路径。

您也可以从我在测试中的评论中看到,手动更新步骤2的路径会显示正确的表单元素。

所以我想我的第一个问题是,这是否可能,如果可能,我错过了什么?

编辑:- 每个步骤都会传递一个 onSubmit 属性。 (上面提到过)

现在我已经停止像德鲁那样嘲笑 useNavigate 表明我看到了一个新错误:

ReferenceError: Request is not defined
   // Move to next step
   NextStep();
   navigate(`step${currentStep + 1}`);  
   ^
 };

这看起来我的整个问题都改变了。我可以看到我正确渲染了 Step1 并单击提交,从这个新错误我想我必须模拟请求?再次环顾四周,但到目前为止我找到的所有答案都与 Node 或 Next 相关。 作为参考,我目前正在使用节点 v18^

reactjs jestjs react-router-dom
1个回答
0
投票

在整理我的测试时,我设法使其正常工作。

所以最初我是像这样嘲笑 useNavigate 并试图让我的表单在单击继续后移至步骤2。

 jest.mock('react-router-dom', () => ({
   ...jest.requireActual('react-router-dom'),
   useNavigate: () => jest.fn(),
 }));

这在测试中不起作用,但如果我手动将测试路径从步骤 1 更新到步骤 2,它会显示步骤 2 组件。

<MemoryRouter initialEntries={['/signup/step1']}>
    ...
<MemoryRouter initialEntries={['/signup/step2']}>
    ...

无法理解为什么会这样,我认为这一定与我设置路由并在 Jest 中渲染它们的方式有关,所以我在测试文件的全局级别设置了 pathsConfig,如下所示:

 const routesConfig = [
   {
     path: '/signup/*',
     element: <RegisterForm />,
     children: [
       { path: 'step1', element: <Step1 /> },
       { path: 'step2', element: <Step2 /> },
     ],
   },
 ];

并在测试中将其呈现出来,如下所示:

 const router = createMemoryRouter(routesConfig, {
       initialEntries: ['/signup/step1'],
     });

     render(<RouterProvider router={router} />);

这是 Drew 介入并建议我不要嘲笑 useNavigate 的地方(再次感谢)。 这开始让我的测试看起来像是在工作,但现在我在请求方面遇到了错误,这导致我来到这里:https://github.com/remix-run/react-router/issues/9508

不幸的是,这也没有帮助,最终我只是想再次测试 MemoryRouter 的原始用法,而不是模拟 useNavigate,现在它可以工作了!

这是完整的工作测试:

import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Form from 'Signup/Form';
import { MemoryRouter, Routes, Route } from 'react-router-dom';

test('Moves to step2 when Next button is clicked', async () => {
    render(
      <MemoryRouter initialEntries={['/signup/step1']}>
        <Routes>
          <Route
            path="/signup/*"
            element={<RegisterForm/>}
          />
        </Routes>
      </MemoryRouter>,
    );

    const UserType = screen.getByLabelText('New User');
    userEvent.type(UserType, 'checked');

    const nextButton = screen.getByText('Next');
    userEvent.click(nextButton);

    await waitFor(() => {
      expect(screen.getByText('Step2')).toBeInTheDocument();
    });
  });

讲了很多,希望对以后的其他人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.