jolyonruss jolyonruss - 2 months ago 34
React JSX Question

Testing Redux Saga, using values from the action that triggers it

I have a saga that works perfectly well, I call an action and include some data, the saga gets triggered, it pulls the values out of the action, does an API call and ends with a couple of yield put's - awesome.

I'm now trying to test that saga and hitting problems, I've written a bare bones saga and test to try and narrow down where the problem is.

The Saga:

function* exampleSaga() {
while(true) {
yield take('EXAMPLE_SAGA');
console.log('what is the value inside example');
const { value } = yield take('ANOTHER_ACTION')
console.log('value', value);
yield take('THIRD_TAKE')
}
}

export { exampleSaga }


The test:

describe('Saga::Example ', function() {
it('should take EXAMPLE_SAGA ', () => {
const saga = exampleSaga()

expect(saga.next().value).to.deep.equal(take('EXAMPLE_SAGA'))
expect(saga.next({
type: 'ANOTHER_ACTION',
value: 'amazing'
}).value).to.deep.equal(take('ANOTHER_ACTION'))
expect(saga.next().value).to.deep.equal(take('THIRD_TAKE'))
})
})


What I expect is that because I'm calling next() and passing an object (a mocked up redux action) that I should be able to pull the values out of that action in the saga.

What I get is:

TypeError: Cannot read property 'value' of undefined


One of the things that's frustrating is that in my app, the saga using this syntax to get values from the action works:

const { value1, value2 } = yield take('ACTION_NAME')


The problem only occurs when I try and test the saga.

Any help is appreciated.

Answer

It works as expected. In your code you assert that saga is waiting for an action (not pushing it). Therefore you have to pass your value object to the next iteration:

// expecting that saga waits for EXAMPLE_SAGA action
expect(saga.next().value).to.deep.equal(take('EXAMPLE_SAGA'))

// pushing EXAMPLE_SAGA action and expecting that saga waits for ANOTHER_ACTION
expect(saga.next().value).to.deep.equal(take('ANOTHER_ACTION'))

// pushing ANOTHER_ACTION and expecting that saga waits for THIRD_TAKE action
expect(saga.next({
  type: 'ANOTHER_ACTION',
  value: 'amazing'
}).value).to.deep.equal(take('THIRD_TAKE'))
Comments