Reputation: 20047
I'm seeing some strange results when testing what I thought were simple saga's with redux-saga. Take this saga for example:
export function* initSaga() {
yield call(window.clearTimeout, runner)
yield call(PubSub.publishSync, 'RESET_CORE')
}
My mental model of the test reads, first check it called window.clearTimeout with a parameter which matches the value of runner
then test it called the publishSync
method of PubSub with the value 'RESET_CORE'
My test for the first part reads:
describe('when testing the init saga', () => {
const saga = initSaga()
const runner = null
it('first clears the draw loop for the canvas', () => {
const result = saga.next().value
const expected = call(window.clearInterval, runner)
console.log(result)
console.log(expected)
expect(result).to.deep.equal(expected)
})
})
What's frustrating is that the error message reads:
AssertionError: expected { Object (@@redux-saga/IO, CALL) } to deeply equal { Object (@@redux-saga/IO, CALL) }
And my console logs read:
console.log src\tests\sagas\simulatorSaga.test.js:25
{ '@@redux-saga/IO': true,
CALL:
{ context: null,
fn: [Function: bound stopTimer],
args: [ null ] } }
console.log src\tests\sagas\simulatorSaga.test.js:26
{ '@@redux-saga/IO': true,
CALL:
{ context: null,
fn: [Function: bound stopTimer],
args: [ null ] } }
Which to me look identical. I'm presuming there is something simple I'm missing here, some kind of deep equal object reference kind of stuff but I'm not sure bearing in mind the saga and test how I could make this any more cut down.
I'm aware that the whole window
+ pubsub
isn't exactly how saga's are meant to be used, but the app is interfacing with a canvas for running a simulation so we kind of have to do it that way.
Upvotes: 0
Views: 1149
Reputation: 13529
I know that that's what the official docs suggest but I don't like such testing. It looks a little bit like testing if redux-saga
does its job. What you are really interested in is if clearInterval
and publishSync
are executed with correct parameters. You don't care what the generator returns. So here's what I'm suggesting:
const executeSaga = function (saga) {
var result = saga.next();
while(!result.done) {
result = saga.next();
}
}
describe('when testing the init saga', () => {
const runner = null;
it('first clears the draw loop for the canvas', () => {
sinon.stub(window, 'clearInterval');
sinon.stub(PubSub, 'publishSync');
executeSaga(initSaga());
expect(window.clearInterval)
.to.be.calledOnce
.and.to.be.calledWith(runner);
expect(PubSub.publishSync)
.to.be.calledOnce
.and.to.be.calledWith('RESET_CORE');
window.clearInterval.restore();
PubSub.publishSync.restore();
})
})
It involves sinonjs
. We are stubbing both functions, run the whole saga and then expect the stubs.
Upvotes: 1