title: How to test a delayed event handler with requestAnimationFrame in Jest?
body: <p>I've got a function that should be get executed in near future and I want to test it with jest but have no idea how to do this properly. Actually, I'm using <strong>React + testing react library</strong> but that doesn't change anything I suppose.
  <br>
  <strong>Here's the function itself:</strong></p>
  <pre><code>let start;
  const holdClick = (el, delayedClickHandler, time = 0) =&gt; {
    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 = () =&gt; {
      window.cancelAnimationFrame(start);
    };
  };
  </code></pre>
  <p><strong>My Component</strong></p>
  <pre><code>function Component() {
    const [clicked, setClicked] = useState(false);
  
    return (
      &lt;span
        // data attribute must be changed to &quot;active&quot; after 30 ticks
        data-testid={clicked ? 'active' : 'static'}
        onTouchStart={e =&gt; holdClick(e.target, () =&gt; setClicked(true), 30)}
      &gt;
        click me
      &lt;/span&gt;
    );
  }
  </code></pre>
  <p><strong>And my test</strong></p>
  <pre><code>test('execute delayed click', () =&gt; {
    beforeEach(() =&gt; {
      jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb =&gt; cb());
    });
  
    const { getByTestId } = render(&lt;App /&gt;);
    const el = getByTestId('static');
  
    fireEvent.click(el);
  
    jest.useFakeTimers();
    setTimeout(() =&gt; {
      expect(el).toHaveAttribute('data-testid', 'active');
    }, 10000);
    jest.runAllTimers();
  });
  </code></pre>
  <hr />
  <p>My guess is that the problem lays in <code>requestAnimationFrame</code> but as I've mentioned before, I'm pretty much clueless of any ways to fix this. I've tried to add <code>jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb =&gt; cb());</code> but it didn't change anything. <strong>So</strong> I'm wondering if there's a solution that doesn't require a troublesome mock of <code>window</code> object.</p>