元素已从文档中删除,但 jest 仍能找到它
Element is removed from document, but jest still finds it
我已经围绕 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
您似乎使用 waitForElementToBeRemoved
不正确。根据 the documentation,“第一个参数必须是一个元素、元素数组,或者 returns 一个元素或元素数组的回调。”
此外,您似乎遇到了一些超时问题。似乎动画导致元素在 DOM 中停留的时间比您预期的要长。您可以执行两个快速测试来确认这是一个问题。
首先,检查浏览器中的 DOM。当您关闭通知时,您可以看到该元素并没有立即被删除。
其次,尝试设置 custom transition 这样我们就可以调整持续时间。当您将 collapseDuration
设置为 5000
之类的内容时,吐司需要很长时间才能消失,并且测试失败。当你将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 });
我已经围绕 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
您似乎使用 waitForElementToBeRemoved
不正确。根据 the documentation,“第一个参数必须是一个元素、元素数组,或者 returns 一个元素或元素数组的回调。”
此外,您似乎遇到了一些超时问题。似乎动画导致元素在 DOM 中停留的时间比您预期的要长。您可以执行两个快速测试来确认这是一个问题。
首先,检查浏览器中的 DOM。当您关闭通知时,您可以看到该元素并没有立即被删除。
其次,尝试设置 custom transition 这样我们就可以调整持续时间。当您将 collapseDuration
设置为 5000
之类的内容时,吐司需要很长时间才能消失,并且测试失败。当你将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 });