繁体   English   中英

Jest 无法在未安装的组件上执行 React state 更新 + 应将反应 state 更新打包成行为

[英]Jest can't perform a React state update on an unmounted component + react state updates should be wrapped into act

所以我正在尝试测试表单输入。 首先表单应该显示一个错误,然后在输入一个值后,用户单击一个按钮,错误应该被删除。
我想我明白为什么会这样,但我不知道如何测试这个功能。

我有条件地呈现错误消息并更新 state 所以我知道这可能就是为什么它告诉我将我的测试包装在act()中。 我还告诉模拟服务器发送错误 state 并且我想可能是因为我覆盖了初始处理程序,它只会以我定义的错误 state 响应。 那也不行。

我不确定如何准确地测试它,因为我是测试新手。 我真的很感激任何帮助。

这里是测试 function:

it('clears validation error after username field is updated', async () => {
  let validationError;
  server.use(generateValidationError('username', 'Username cannot be null'));
  setup();

  await act(async () => {
    userEvent.click(button);
    validationError = await screen.findByText('Username cannot be null');
    userEvent.type(usernameInput, 'username001');
    userEvent.click(button);
    expect(validationError).not.toBeInTheDocument();
  });
});

由于在组件中设置 state 或异步执行某些操作可能需要“一些时间”,因此您应该将您的情况视为潜在的类似承诺的情况。

为确保您的测试始终等待发生的任何更改,您可以使用waitFor方法并使用您的代码添加回调 function 以检查一些 state。 这是来自React 测试库

it('clears validation error after username field is updated', async () => {
  let validationError;
  server.use(generateValidationError('username', 'Username cannot be null'));
  setup();

  await act(async () => {
    userEvent.click(button);
    userEvent.type(usernameInput, 'username001');
    userEvent.click(button);

    await waitFor(async () => {
      validationError = await screen.findByText('Username cannot be null');
      expect(validationError).not.toBeInTheDocument();
    });
  });
});

小费
当您断言包含 DOM 元素的内容时,在您执行某些操作后始终 select 该元素(在您的情况下更改验证 state 在您的情况下单击按钮后)。

在上面的代码中,我根据上述提示更改了该选择器的 position。

在方法方面,我会:

  1. 测试错误最初是可见的
  2. 点击按钮
  3. 测试错误已消失

如果要使用act() ,通常将断言放在其 function 主体之外,请参阅https://reactjs.org/docs/testing-recipes.html#act

我什至不确定您是否需要act() 官方测试库文档中的示例似乎可以满足您的需求:

这真是个愚蠢的错误。 我遇到的第一个错误是因为我在成功提交后隐藏了我的表单。 因此该组件将卸载,然后我将无法对其进行测试。 我通过分别测试每个字段并确保它没有成功提交表单来找到解决方法。

通过修复上述错误,我不再需要使用 act() 了,因为我没有收到任何开玩笑的错误。 之后测试顺利通过。

it.each`
      field         | message                      | label
      ${'username'} | ${'Username cannot be null'} | ${'Username'}
      ${'email'}    | ${'Email cannot be null'}    | ${'Email'}
      ${'password'} | ${'Password cannot be null'} | ${'Password'}
    `(
      'clears validation error after $field field is updated',
      async ({ field, message, label }) => {
        server.use(generateValidationError(field, message));
        setup();
        userEvent.click(button);
        const validationError = await screen.findByText(message);
        const inputByLabel = screen.getByLabelText(label);
        userEvent.type(
          inputByLabel,
          label === 'Email' ? 'user@testuser.com' : 'username001'
        );
        //this line was needed to stop the form from submitting
        userEvent.type(confirmPasswordInput, 'newpassword');
        userEvent.click(button);
        await waitFor(() => {
          expect(validationError).not.toBeInTheDocument();
        });
      }
    );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM