Background
I'm trying to write a saga to handle polling when a certain view is open, and I want to cancel the polling when the view is closed. This is pretty much the textbook example from the docs! In the course of writing a test for it, I ran into the following problem.
Problem
When I introduce a delay and try to mock it with a fake timer, the generator does not yield
on the second loop and the test fails. However, the code will log loop 0
and loop 1
, so I know it is entering the loop a second time.
If I use a real delay, the test passes!
Is this expected? Am I losing my mind?
import { runSaga } from "redux-saga";
import { call, delay } from "redux-saga/effects";
import sinon from "sinon";
describe("faking the delay", () => {
it("should loop more than once", async () => {
let i = 0;
const clock = sinon.useFakeTimers();
const spy = jest.fn().mockReturnValue(true);
function* loop() {
while (true) {
console.log("loop %d", i);
yield call(spy);
// yield delay(1);
yield new Promise(resolve => setTimeout(resolve, 1));
i++;
}
}
await runSaga({}, loop, spy);
expect(spy).toBeCalledTimes(1);
// await new Promise(resolve => setTimeout(resolve, 1));
clock.tick(1)
clock.tick(1)
expect(spy).toBeCalledTimes(2); // FAILS
clock.restore();
});
});