Redux-saga: How to unit test / assert a debounced saga?

Created on 12 Aug 2016  路  1Comment  路  Source: redux-saga/redux-saga

I've made a debounced saga to fetch data for a typeahead component. I'd like to write a unit test for it. What are to steps to assert that a Saga has been debounced? Are there any examples out there? I'm completely lost at how to write a unit test for this 馃槥 .

My debounced saga:

export function* getCompanies() {
  const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
  yield call(delay, 250); // debounce getCompanies saga by 250 ms

  const searchTerm = yield select(selectSearchTerm());
  if (searchTerm === '') return; // cancel api fetch if term is empty

  // fetch companies
  const requestURL = `https://autocomplete-api.com/suggest?query=${searchTerm}`;
  const companies = yield call(request, requestURL);

  if (!companies.err) {
    yield put(loadCompanies(companies.data)); // dispatch action: load companies
  }

 return;
}


export function* getCompaniesWatcher() {
  while (yield take(FETCH_RESULTS)) {
    yield call(getCompanies);
  }
}

Most helpful comment

In fact there is a way I think, please take a look here - https://github.com/yelouafi/redux-saga/blob/master/test/sagaHelpers/takeLatest.js

It is a really similar example. If you really want to check this debouncing thing.

However you dont even need to check:

  1. use delay helper from redux-saga (import { delay } from 'redux-saga')
  2. use it exactly the same - yield call(delay, 250)
  3. just test if call effect is created with correct arguments. Effects are description to saga what should be done by it. You actually do not need to check if it happened, just if saga was ordered to do something

Also in my opinion you do not need to use yield call(getCompanies). I guess you are exporting getCompanies, so it can be tested. For me its exporting just for testing purposes which is not ideal (in my opinion). You can yield* getCompanies() so in your test (after const it = getCompaniesWatcher()) calls to it.next will be delegated in to your underlaying iterator which is the one created by getCompanies, so it can stay hidden from the outside world and still works exactly the same. However that is my personal preference.

>All comments

In fact there is a way I think, please take a look here - https://github.com/yelouafi/redux-saga/blob/master/test/sagaHelpers/takeLatest.js

It is a really similar example. If you really want to check this debouncing thing.

However you dont even need to check:

  1. use delay helper from redux-saga (import { delay } from 'redux-saga')
  2. use it exactly the same - yield call(delay, 250)
  3. just test if call effect is created with correct arguments. Effects are description to saga what should be done by it. You actually do not need to check if it happened, just if saga was ordered to do something

Also in my opinion you do not need to use yield call(getCompanies). I guess you are exporting getCompanies, so it can be tested. For me its exporting just for testing purposes which is not ideal (in my opinion). You can yield* getCompanies() so in your test (after const it = getCompaniesWatcher()) calls to it.next will be delegated in to your underlaying iterator which is the one created by getCompanies, so it can stay hidden from the outside world and still works exactly the same. However that is my personal preference.

Was this page helpful?
0 / 5 - 0 ratings