我正在尝试使用点击处理程序来测试自毁组件的卸载。点击处理程序使用setTimeout更新useState。
但是,我的测试失败了,但是我希望它能通过。我尝试使用诸如AdvanceTimersByTime()之类的开玩笑的模拟计时器,但是它不起作用。如果我在setTimeout之外调用setState,则测试通过。
component.js
const DangerMsg = ({ duration, onAnimDurationEnd, children }) => {
const [isVisible, setVisible] = useState(false);
const [sectionClass, setSectionClass] = useState(classes.container);
function handleAnimation() {
setSectionClass(classes.containerAnimated);
let timer = setTimeout(() => {
setVisible(false);
}, 300);
return clearTimeout(timer);
}
useEffect(() => {
let timer1;
let timer2;
function animate() {
if (onAnimDurationEnd) {
setSectionClass(classes.containerAnimated);
timer2 = setTimeout(() => {
setVisible(false);
}, 300);
} else {
setVisible(false);
}
}
if (children) {
setVisible(true);
}
if (duration) {
timer1 = setTimeout(() => {
animate();
}, duration);
}
return () => {
clearTimeout(timer1);
clearTimeout(timer2);
};
}, [children, duration, onAnimDurationEnd]);
return (
<>
{isVisible ? (
<section className={sectionClass} data-test="danger-msg">
<div className={classes.inner}>
{children}
<button
className={classes.btn}
onClick={() => handleAnimation()}
data-test="btn"
>
×
</button>
</div>
</section>
) : null}
</>
);
};
导出默认DangerMsg;
test.js
it("should NOT render on click", async () => {
jest.useFakeTimers();
const { useState } = jest.requireActual("react");
useStateMock.mockImplementation(useState);
// useEffect not called on shallow
component = mount(
<DangerMsg>
<div></div>
</DangerMsg>
);
const btn = findByTestAttr(component, "btn");
btn.simulate("click");
jest.advanceTimersByTime(400);
const wrapper = findByTestAttr(component, "danger-msg");
expect(wrapper).toHaveLength(0);
});
注意,我在模拟useState实现,因为在其他测试中,我使用了自定义useState模拟。
答案 0 :(得分:1)
不使用酶,而是使用testing-library/react
,所以这是部分解决方案。以下测试按预期通过:
test("display loader after 1 second", () => {
jest.useFakeTimers(); // mock timers
const { queryByRole } = render(
<AssetsMap {...defaultProps} isLoading={true} />
);
act(() => {
jest.runAllTimers(); // trigger setTimeout
});
const loader = queryByRole("progressbar");
expect(loader).toBeTruthy();
});
我直接运行计时器,但按时间前进应该会得到类似的结果。