【问题标题】:Element is removed from document, but jest still finds it元素已从文档中删除,但 jest 仍然找到它
【发布时间】:2020-11-17 19:12:57
【问题描述】:

我已经围绕 react-toastify 构建了一个包装器,以便我可以在多个地方调用它。

这是包装器的代码:

import { ReactText } from 'react';
import { toast } from 'react-toastify';

export const showNotification: (
  message: string,
  type?: 'info' | 'success' | 'warning' | 'error',
  timeOut?: number,
) => ReactText
  = (message, type = 'success', timeOut = 5000) => toast(
      message, { type, autoClose: timeOut },
    );

export const dismissNotification = (toastId: ReactText) => toast.dismiss(toastId);

现在,我正在测试我的dismissNotification 函数。

我已经写了这个测试用例:

it('dismisses notification when called', async () => {
  render(<ToastContainer />);
  const notificationId = showNotification('Test Notification', 'success', 2000);
  await waitFor(() => {
    expect(screen.getByText('Test Notification')).toBeInTheDocument();
  });
  dismissNotification(notificationId);
  await waitForElementToBeRemoved(() => {
    expect(screen.queryByText('Test Notification')).not.toBeInTheDocument();
  });
});

但最后一个测试用例总是失败,说存在带有文本 Test Notification 的 dom 节点。

实际错误:

dismisses notification when called

    expect(element).not.toBeInTheDocument()

    expected document not to contain element, found <div class="Toastify__toast-body" role="alert">Test Notification</div> instead

【问题讨论】:

    标签: reactjs jestjs react-testing-library


    【解决方案1】:

    您似乎错误地使用了waitForElementToBeRemoved。根据the documentation,“第一个参数必须是元素、元素数组或返回元素或元素数组的回调。”

    此外,您似乎遇到了一些超时问题。似乎动画导致元素在 DOM 中停留的时间比您预期的要长。您可以执行两个快速测试来确认这是一个问题。

    首先,检查浏览器中的 DOM。当您关闭通知时,您可以看到该元素并未立即删除。

    其次,尝试设置custom transition,以便我们可以调整持续时间。当您将collapseDuration 设置为5000 时,toast 需要很长时间才能消失,并且测试失败。当您将collapseDuration 设置为0 时,toast 立即消失,测试通过。

    const Zoom = cssTransition({
      enter: 'zoomIn',
      exit: 'zoomOut',
      collapseDuration: 0,
      //duration: 5000,
    });
    
    toast(message, {
      type,
      autoClose: timeOut,
      transition: Zoom,
    });
    

    所以我认为您需要修复您使用waitForElementToBeRemoved 的方式并应用自定义timeout。试试这个代码:

    await waitForElementToBeRemoved(screen.queryByText('Test Notification'), { timeout: 5000 });
    

    【讨论】:

    • 感谢您尝试回答我的问题。如果你能看到await waitForElementToBeRemoved ... 之前的行,我会打电话给dismissNotification。所以,在 1000 毫秒之前,我的通知就会消失。
    • 哦,对不起,我一定错过了。我仍然认为我的代码对你有用。只需使用timeout 删除选项对象。我现在将进行编辑。
    • 我仍然认为timeout 是个问题,因为直到动画完成后元素才会被移除。在我上面编辑的帖子中查看更多信息。
    • 是的,我成功了。你是对的,超时是问题所在。一旦我将超时时间增加到 2000 秒,测试就通过了。然后我提高了 showNotification 方法的超时时间,以确保通知被dismissNotification 函数调用而不是由于超时而解除。因此,结论是:通知完成其关闭动画的时间超过 1 秒。
    猜你喜欢
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2017-05-07
    • 2020-12-06
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    相关资源
    最近更新 更多