State

You can test your saga's integration with your reducer and store state via the withState, withReducer, and hasFinalState methods.

Static State via withState

For static state, you can just use the withState method to allow select effects to work. You can also use providers for this.

const storeState = {
  data: {
    foo: 'bar',
  },
};

function getData(state) {
  return state.data;
}

function* saga() {
  const data = yield select(getData);
  yield put({ type: 'DATA', payload: data });
}

it('can take store state', () => {
  return expectSaga(saga)
    .withState(storeState)
    .put({ type: 'DATA', payload: storeState.data })
    .run();
});

Dynamic State via withReducer

For state that might change, you can use the withReducer method. It takes two arguments: your reducer and optional initial state. If you don't supply the initial state, then withReducer will extract it by passing an initial action into your reducer like Redux.

Any select effects will reflect state changes where appropriate. More importantly, you can test your store state after the saga completes via hasFinalState.

const initialDog = {
  name: 'Tucker',
  age: 11,
};

function dogReducer(state = initialDog, action) {
  if (action.type === 'HAVE_BIRTHDAY') {
    return {
      ...state,
      age: state.age + 1,
    };
  }

  return state;
}

function* saga() {
  yield put({ type: 'HAVE_BIRTHDAY' });
}

it('handles reducers when not supplying initial state', () => {
  return expectSaga(saga)
    .withReducer(dogReducer)
    .hasFinalState({
      name: 'Tucker',
      age: 12, // <-- age in store state changed
    })
    .run();
});

it('handles reducers when supplying initial state', () => {
  return expectSaga(saga)
    .withReducer(dogReducer, initialDog)
    .hasFinalState({
      name: 'Tucker',
      age: 12, // <-- age in store state changed
    })
    .run();
});

Exposed Store State

The Promise returned from run resolves with a storeState object that you can inspect for more fine-grained testing.

it('exposes the store state', () => {
  return expectSaga(saga)
    .withReducer(dogReducer, initialDog)
    .run()
    .then((result) => {
      expect(result.storeState).toEqual({
        name: 'Tucker',
        age: 12, // <-- age in store state changed
      });
    });
});

it('exposes the store state using async/await', async () => {
  const { storeState } = await expectSaga(saga)
    .withReducer(dogReducer, initialDog)
    .run();

  expect(storeState).toEqual({
    name: 'Tucker',
    age: 12, // <-- age in store state changed
  });
});

results matching ""

    No results matching ""