I cannot seem to be able to spy on setTimeout
and clearTimeout
in my Jasmine tests, which are being run through Karma.
I have tried variations on all of this
spyOn(window, 'setTimeout').and.callFake(()=>{});
spyOn(global, 'setTimeout').and.callFake(()=>{});
spyOn(window, 'clearTimeout').and.callThrough();
clock = jasmine.clock();
clock.install();
spyOn(clock, 'setTimeout').and.callThrough();
runMyCode();
expect(window.setTimeout).toHaveBeenCalled(); // no
expect(global.setTimeout).toHaveBeenCalled(); // nope
expect(window.clearTimeout).toHaveBeenCalled(); // no again
expect(clock.setTimeout).toHaveBeenCalled(); // and no
In every case, I can confirm that setTimeout
and clearTimeout
have been invoked in runMyCode
, but instead I always get Expected spy setTimeout to have been called.
For window
, clearly this is because the test and the runner (the Karma window) are in different frames (so why should I expect anything different). But because of this, I can't see any way to confirm that these global functions have been invoked.
I know that I can use jasmine.clock()
to confirm that timeout/interval callbacks have been invoked, but it looks like I can't watch setTimeout
itself. And confirming that clearTimeout
has been called simply isn't possible.
At this point, the only thing I can think of is to add a separate layer of abstraction to wrap setTimeout
and clearTimeout
or to inject the functions as dependencies, which I've done before, but I think is weird.
I was able to get it to work like this:
spyOn(window, 'setTimeout');
runMyCode();
expect(setTimeout).toHaveBeenCalled();
Just remove the 'window' object from the setTimeout call.
For those looking for a Jest solution, it has dedicated fake timer functions (which are also spyable).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With