元素已从文档中删除,但jest仍然找到了它



我已经围绕react toast ify构建了一个包装器,这样我就可以在多个地方调用它。

这是包装器的代码:

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);

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

我写了这个测试用例:

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

看起来您使用waitForElementToBeRemoved不正确。根据文献记载;第一个参数必须是元素、元素数组或返回元素或元素数组的回调">

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

首先,在浏览器中检查DOM。当您取消通知时,您可以看到元素没有立即删除。

第二,试着设置一个自定义的过渡,这样我们就可以随意调整持续时间。当您将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 });

最新更新