如何解决警告:测试中的 Slider 更新未包含在 act(...)
我在尝试使用“react-test-renderer”测试一段代码时遇到以下错误
下面是我的测试
import React from "react";
import { act,create } from "react-test-renderer";
import { Slider } from "../../../../src/components/slider/Slider";
describe("SliderComponent",() => {
// it("renders without crashing",(done) => {
// const component = create(<Slider loop={false} itemsPerPage={3} slidesCount={8} />);
// const tree = component.toJSON();
// expect(tree).toMatchSnapshot();
// component.unmount();
// done();
// });
// it("changes active item after delay",done => {
// const sliderCount = jest.fn();
// const component = create(<Slider onActiveItemChange={sliderCount} loop={true} delay={50} itemsPerPage={3}
// slidesCount={8} activeSlide={0} />);
// const tree = component.toJSON();
// expect(tree).toMatchSnapshot();
// act(() => {
// setTimeout(() => {
// expect(sliderCount).toBeCalled();
// component.unmount();
// done();
// },51);
// });
// });
// it("active item is not changed before delay",done => {
// const sliderCount = jest.fn();
// const component = create(<Slider onActiveItemChange={sliderCount} loop={true} delay={60} itemsPerPage={3}
// slidesCount={8} />);
// const tree = component.toJSON();
// expect(tree).toMatchSnapshot();
// act(() => {
// setTimeout(() => {
// expect(sliderCount.mock.calls.length).toBe(0);
// component.unmount();
// done();
// },50);
// });
// });
// it("when loop is set to false,active item is not changed after delay",done => {
// const sliderCount = jest.fn();
// const component = create(<Slider onActiveItemChange={sliderCount} loop={false} delay={20} itemsPerPage={3}
// slidesCount={8} activeSlide={0} />);
// const tree = component.toJSON();
// expect(tree).toMatchSnapshot();
// act(() => {
// setTimeout(() => {
// expect(sliderCount.mock.calls.length).toBe(0);
// component.unmount();
// done();
// },30);
// });
// });
// it('has list items that on click changes list active item',done => {
// const sliderCount = jest.fn();
// const component = create(<Slider onActiveItemChange={sliderCount} loop={false} delay={1000} itemsPerPage={3}
// slidesCount={8} activeSlide={0} />);
// const testInstance = component.root;
// act(() => {
// testInstance.findAllByType('li')[1].props.onClick();
// expect(sliderCount).toHaveBeenCalled();
// component.unmount();
// done();
// })
// });
it("loop resumes after click",done => {
const sliderCount = jest.fn();
// const component = create(<Slider onActiveItemChange={sliderCount} loop={true} delay={50} itemsPerPage={1}
// slidesCount={3} activeSlide={0} />);
act(() => {
const component = create(<Slider onActiveItemChange={sliderCount} loop={true} delay={50} itemsPerPage={1}
slidesCount={3} activeSlide={0} />);
const testInstance = component.root;
testInstance.findAllByType('li')[1].props.onClick();
setTimeout(() => {
expect(sliderCount).toBeCalled();
component.unmount();
done();
},51);
});
});
});
注释掉的测试成功通过。但是最后一次测试失败了
SliderComponent
× loop resumes after click (25 ms)
● SliderComponent › loop resumes after click
Can't access .root on unmounted test renderer
81 | const component = create(<Slider onActiveItemChange={sliderCount} loop={true} delay={50} itemsPerPage={1}
82 | slidesCount={3} activeSlide={0} />);
> 83 | const testInstance = component.root;
| ^
84 | testInstance.findAllByType('li')[1].props.onClick();
85 | setTimeout(() => {
86 | expect(sliderCount).toBeCalled();
at Object.root (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:17237:15)
at __tests__/src/components/slider/Slider.test.tsx:83:40
at batchedUpdates (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13452:12)
at act (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:15280:14)
at Object.<anonymous> (__tests__/src/components/slider/Slider.test.tsx:80:6)
如果我将代码 const component = create(<Slider onActiveItemChange={sliderCount} loop={true} delay={50} itemsPerPage={1} slidesCount={3} activeSlide={0} />);
移到 act()
函数之外,我会得到
console.error
Warning: An update to Slider inside a test was not wrapped in act(...).
When testing,code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at Slider (C:\Users\KOTIENO1\Desktop\Projects\SafcomProjects\WORK\platform-of-choice\src\components\slider\Slider.tsx:1072:5)
at printWarning (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:68:30)
at error (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:44:5)
at warnIfNotCurrentlyActingUpdatesInDEV (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:15034:9)
at dispatchAction (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7129:9)
at Object.next (src/components/slider/Slider.tsx:1192:9)
at Object.next (node_modules/rxjs/src/internal/Subscriber.ts:194:14)
at SafeSubscriber.Object.<anonymous>.Subscriber._next (node_modules/rxjs/src/internal/Subscriber.ts:119:22)
下面是我要测试的代码
import React,{ useEffect,useState } from "react";
import styled,{ css } from "styled-components";
import { BehaviorSubject,Subject,timer } from "rxjs";
import { repeatWhen,take,takeuntil,takeWhile,tap } from "rxjs/operators";
interface iSliderProps {
slidesCount: number;
activeSlide?: number;
onActiveItemChange?;
itemsPerPage?: number;
delay?: number;
interval?: number;
loop?: boolean;
}
const SliderWrapper = styled.ul`
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
//background: red;
`;
const SliderItem = styled.li`
float: left;
background: #FFF;
cursor: pointer;
margin: 0.1rem;
list-style: none;
width: 0.25rem;
height: 0.25rem;
border: 1px solid #00943C;
border-radius: 0.5rem;
${props => props.active && css`
background: #00943C;
cursor: default;
width: 1.5rem;`
}
${props => !props.active && css`
&:hover {
background: #00943C;
}
`
}
`;
export const Slider = (props: iSliderProps) => {
const {
slidesCount,activeSlide = 0,onActiveItemChange = () => {
},itemsPerPage = 1,delay = 5000,interval = 5000,loop = true
} = props;
const [currentActiveSlide,setCurrentActiveSlide] = useState(activeSlide);
const sliderCount = Math.ceil(slidesCount / itemsPerPage);
const timerStart$ = new BehaviorSubject(null);
const timerStop$ = new Subject<null>();
const timer$ = timer(delay,interval).pipe(
takeWhile(() => loop),takeuntil(timerStop$),repeatWhen(() => timerStart$)
);
useEffect(() => {
const timerSubscription = timer$.subscribe({
next: (i) => {
const nextSlide = i >= sliderCount ? i % sliderCount : i;
onActiveItemChange(nextSlide);
setCurrentActiveSlide(nextSlide);
}
});
return () => timerSubscription.unsubscribe();
},[]);
const handleSliderItemClick = (i: number) => {
setCurrentActiveSlide(i);
onActiveItemChange(i);
timerStop$.next(null);
timer(delay).pipe(
take(1),tap(() => timerStart$.next(null))
);
};
const slides = Object.keys(new Array(sliderCount).fill("")).map(id => ({ id }));
return (
<>
<SliderWrapper>
{slides.map(({ id },i) =>
<SliderItem
key={id}
aria-label={"scroll page number " + id}
onClick={() => handleSliderItemClick(i)}
active={i === currentActiveSlide}
/>)}
</SliderWrapper>
</>
);
};
我已在 When testing,code that causes React state updates should be wrapped into act 和 React Testing Library / Jest Update not wrapped in act(...) 下方进行了检查,但我似乎无法在测试中找出问题所在。
测试通过,但错误仍然存在
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。