Timeout

Because expectSaga runs sagas asynchronously, it has a default timeout in case your saga runs too long. This is needed for sagas that have multiple asynchronous actions, that have infinite loops, or that use saga helpers like takeEvery. expectSaga will cancel your saga if it times out and print a warning message.

function* mainSaga() {
  while (true) {
    const action = yield take('READY');
    yield put({ type: 'DATA', payload: action.payload });
  }
}

it('times out', () => {
  return expectSaga(mainSaga)
    .put({ type: 'DATA', payload: 42 })
    .dispatch({ type: 'READY', payload: 42 })

    // saga never terminates on its own
    // implicit timeout of 250ms will cancel saga
    // and print warning message to console
    .run();
});

Silencing Warnings

The warning message is typically useful if a saga without an infinite loop is taking too long. If you have a saga with an infinite loop, though, you will want it to time out. Therefore, to silence the warning message, you can call the silentRun method instead. It functions the same as the run method but suppresses timeout warnings from Redux Saga Test Plan. NOTE: this will not suppress any timeout warnings from your test runner (e.g. Jest).

it('can be silenced', () => {
  return expectSaga(mainSaga)
    .put({ type: 'DATA', payload: 42 })
    .dispatch({ type: 'READY', payload: 42 })

    // no warning message will be printed
    // this is useful if you expect the saga to time out
    .silentRun();
});

The old method of silencing timeouts by passing a silenceTimeout option into run is still available, but you're encouraged to use the cleaner silentRun method.

it('can be silenced', () => {
  return expectSaga(mainSaga)
    .put({ type: 'DATA', payload: 42 })
    .dispatch({ type: 'READY', payload: 42 })

    // still works, but more to type
    .run({ silenceTimeout: true });
});

Adjusting Timeout

Instead of silencing warnings, you can adjust the timeout length. The default timeout length is 250 milliseconds. You can change the default timeout by setting the DEFAULT_TIMEOUT property of expectSaga in milliseconds.

expectSaga.DEFAULT_TIMEOUT = 500; // set it to 500ms

If you want to override the timeout for a particular test case, then you can pass in a timeout length to the run (or silentRun) method.

const delay = time => new Promise(resolve => setTimeout(resolve, time));

function* mainSaga() {
  yield call(delay, 300);
  yield put({ type: 'HELLO' });
}

it('can have a different timeout length', () => {
  return expectSaga(mainSaga)
    .put({ type: 'HELLO' })

    // saga will take at least 300ms,
    // so time out after 500ms to be safe
    .run(500);
});

Alternatively, you can opt out of the timeout behavior and force expectSaga to wait until your saga is done on its own by passing in false to the run method. WARNING: this won't work with sagas with infinite loops because the saga will never finish on its own.

it('never times out', () => {
  return expectSaga(mainSaga)
    .put({ type: 'HELLO' })

    // wait until the saga finishes on its own
    .run(false);
});

results matching ""

    No results matching ""