Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在jest中测试延迟事件处理程序?_Javascript_Reactjs_Testing_Jestjs_React Testing Library - Fatal编程技术网

Javascript 如何在jest中测试延迟事件处理程序?

Javascript 如何在jest中测试延迟事件处理程序?,javascript,reactjs,testing,jestjs,react-testing-library,Javascript,Reactjs,Testing,Jestjs,React Testing Library,我有一个函数应该在不久的将来执行,我想用jest测试它,但不知道如何正确地执行。实际上,我正在使用React+测试React库,但我认为这不会改变任何事情。 函数本身如下: let start; const holdClick = (el, delayedClickHandler, time = 0) => { if (time === 0) return delayedClickHandler(); let counter = 0; function countToExec

我有一个函数应该在不久的将来执行,我想用jest测试它,但不知道如何正确地执行。实际上,我正在使用React+测试React库,但我认为这不会改变任何事情。
函数本身如下:

let start;
const holdClick = (el, delayedClickHandler, time = 0) => {
  if (time === 0) return delayedClickHandler();
  let counter = 0;
  function countToExecute() {
    if (counter === time) delayedClickHandler();
    else {
      start = requestAnimationFrame(countToExecute);
      counter += 1;
    }
  }

  start = window.requestAnimationFrame(countToExecute);

  el.ontouchend = () => {
    window.cancelAnimationFrame(start);
  };
};
我的组件

function Component() {
  const [clicked, setClicked] = useState(false);

  return (
    <span
      // data attribute must be changed to "active" after 30 ticks
      data-testid={clicked ? 'active' : 'static'}
      onTouchStart={e => holdClick(e.target, () => setClicked(true), 30)}
    >
      click me
    </span>
  );
}
test('execute delayed click', () => {
  beforeEach(() => {
    jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb => cb());
  });

  const { getByTestId } = render(<App />);
  const el = getByTestId('static');

  fireEvent.click(el);

  jest.useFakeTimers();
  setTimeout(() => {
    expect(el).toHaveAttribute('data-testid', 'active');
  }, 10000);
  jest.runAllTimers();
});
函数组件(){
const[clicked,setClicked]=useState(false);
返回(
holdClick(例如,target,()=>setClicked(true),30)}
>
点击我
);
}
和我的测试

function Component() {
  const [clicked, setClicked] = useState(false);

  return (
    <span
      // data attribute must be changed to "active" after 30 ticks
      data-testid={clicked ? 'active' : 'static'}
      onTouchStart={e => holdClick(e.target, () => setClicked(true), 30)}
    >
      click me
    </span>
  );
}
test('execute delayed click', () => {
  beforeEach(() => {
    jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb => cb());
  });

  const { getByTestId } = render(<App />);
  const el = getByTestId('static');

  fireEvent.click(el);

  jest.useFakeTimers();
  setTimeout(() => {
    expect(el).toHaveAttribute('data-testid', 'active');
  }, 10000);
  jest.runAllTimers();
});
test('执行延迟点击',()=>{
在每个之前(()=>{
spyOn(窗口'requestAnimationFrame').mockImplementation(cb=>cb());
});
const{getByTestId}=render();
const el=getByTestId('static');
fireEvent。单击(el);
开玩笑。使用faketimers();
设置超时(()=>{
expect(el).toHaveAttribute('data-testid','active');
}, 10000);
jest.runAllTimers();
});


我猜问题出在
requestAnimationFrame
中,但正如我前面提到的,我几乎不知道如何解决这个问题。我试图添加
jest.spyOn(窗口,'requestAnimationFrame').mockImplementation(cb=>cb())但它没有改变任何东西因此我想知道是否有一种解决方案不需要对
窗口
对象进行麻烦的模拟。

首先,您的回调设置在
onTouchStart
属性上,这意味着您需要触发
touchStart
事件才能触发它

fireEvent.touchStart(el);
其次,在
countToExecute
函数中,在调用
requestAnimationFrame
之前,应增加
计数器
变量。否则,
计数器将永远无法增加

函数countToExecute(){
如果(计数器==时间){
delayedClickHandler();
}否则{
计数器+=1;
开始=请求动画帧(countToExecute);
}
}
然后,您的测试应该如下所示:

test('执行延迟点击',()=>{
spyOn(窗口'requestAnimationFrame').mockImplementation(cb=>cb());
const{getByTestId}=render();
const el=getByTestId('static');
fireEvent.touchStart(el);
expect(el).toHaveAttribute('data-testid','active');
});

哦,我忘记了重构和更改单击触摸屏。你们的代码实际上对我有效,但老实说,我不明白为什么在动画请求之前增加计数器会产生这种差异。这段代码在浏览器中运行得很好,计数器也会增加,那么在节点环境中会发生什么呢?此模拟是否应该返回范围内更新了计数器的计数器执行功能?我的意思是它无论如何都必须增加,不是吗?原始的
requestAnimationFrame
在每次重新绘制(每个“勾号”)时调用它的回调,但在测试中它会立即调用,因为我们在模拟它。进行此更改不应影响实际行为,而且在逻辑上也有意义,因为您希望确保在再次执行
countToExecute
之前增加
counter
。哦,这正是我所想的。谢谢你的解释!