假计时器不适用于最新版本的用户事件?
Fake timers doesn't work with latest version of user-event?
以下是我想测试的自定义挂钩:
import { useEffect, useState } from "react";
export const useAlert = () => {
const [alert, setAlert] = useState(null);
useEffect(() => {
let timerId = setTimeout(() => {
console.log("Timeout, removing alert from DOM");
setAlert(null);
}, 200);
return () => clearTimeout(timerId);
}, [alert]);
return {
renderAlert: alert ? alert : null,
setAlert,
};
};
它只是允许一个组件设置警报并在 300 毫秒后自动清除它。
这是对上述挂钩的工作测试
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useAlert } from "../components/useAlert";
// jest.useFakeTimers();
function FakeComponent() {
const { renderAlert, setAlert } = useAlert();
return (
<div>
<button onClick={() => setAlert("fake alert")}>Set Alert</button>
<p>{renderAlert}</p>
</div>
);
}
test("testing", async () => {
const user = userEvent.setup();
render(<FakeComponent />);
const button = screen.getByRole("button", { name: /set alert/i });
await user.click(button);
expect(screen.getByText(/fake alert/i)).toBeInTheDocument();
await waitFor(() => {
expect(screen.queryByText(/fake alert/i)).not.toBeInTheDocument();
});
});
我的疑问是我想在测试中使用 jest 的假计时器,但如果我取消注释行 jest.useFakeTimers()
,测试会中断,说测试超时,因为默认超时值为 5000 毫秒,请考虑增加如果它是一个长 运行 测试超时。
我不明白为什么会这样,请大家帮忙!
要在 @testing-library/user-event
的最新版本中使用假计时器,您需要在设置 userEvent
时配置 advanceTimers
选项 (docs):
const user = userEvent.setup({
advanceTimers: () => jest.runOnlyPendingTimers(),
});
这是您更新后的测试:
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useAlert } from "../components/useAlert";
jest.useFakeTimers();
function FakeComponent() {
const { renderAlert, setAlert } = useAlert();
return (
<div>
<button onClick={() => setAlert("fake alert")}>Set Alert</button>
<p>{renderAlert}</p>
</div>
);
}
test("testing", async () => {
const user = userEvent.setup({
advanceTimers: () => jest.runOnlyPendingTimers(),
});
render(<FakeComponent />);
const button = screen.getByRole("button", { name: /set alert/i });
await user.click(button);
expect(screen.getByText(/fake alert/i)).toBeInTheDocument();
act(() => jest.runAllTimers());
expect(screen.queryByText(/fake alert/i)).toBeNull();
});
以下是我想测试的自定义挂钩:
import { useEffect, useState } from "react";
export const useAlert = () => {
const [alert, setAlert] = useState(null);
useEffect(() => {
let timerId = setTimeout(() => {
console.log("Timeout, removing alert from DOM");
setAlert(null);
}, 200);
return () => clearTimeout(timerId);
}, [alert]);
return {
renderAlert: alert ? alert : null,
setAlert,
};
};
它只是允许一个组件设置警报并在 300 毫秒后自动清除它。
这是对上述挂钩的工作测试
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useAlert } from "../components/useAlert";
// jest.useFakeTimers();
function FakeComponent() {
const { renderAlert, setAlert } = useAlert();
return (
<div>
<button onClick={() => setAlert("fake alert")}>Set Alert</button>
<p>{renderAlert}</p>
</div>
);
}
test("testing", async () => {
const user = userEvent.setup();
render(<FakeComponent />);
const button = screen.getByRole("button", { name: /set alert/i });
await user.click(button);
expect(screen.getByText(/fake alert/i)).toBeInTheDocument();
await waitFor(() => {
expect(screen.queryByText(/fake alert/i)).not.toBeInTheDocument();
});
});
我的疑问是我想在测试中使用 jest 的假计时器,但如果我取消注释行 jest.useFakeTimers()
,测试会中断,说测试超时,因为默认超时值为 5000 毫秒,请考虑增加如果它是一个长 运行 测试超时。
我不明白为什么会这样,请大家帮忙!
要在 @testing-library/user-event
的最新版本中使用假计时器,您需要在设置 userEvent
时配置 advanceTimers
选项 (docs):
const user = userEvent.setup({
advanceTimers: () => jest.runOnlyPendingTimers(),
});
这是您更新后的测试:
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useAlert } from "../components/useAlert";
jest.useFakeTimers();
function FakeComponent() {
const { renderAlert, setAlert } = useAlert();
return (
<div>
<button onClick={() => setAlert("fake alert")}>Set Alert</button>
<p>{renderAlert}</p>
</div>
);
}
test("testing", async () => {
const user = userEvent.setup({
advanceTimers: () => jest.runOnlyPendingTimers(),
});
render(<FakeComponent />);
const button = screen.getByRole("button", { name: /set alert/i });
await user.click(button);
expect(screen.getByText(/fake alert/i)).toBeInTheDocument();
act(() => jest.runAllTimers());
expect(screen.queryByText(/fake alert/i)).toBeNull();
});