Testing Your Subscriptions

Run it like a Function

Since subscriptions are just functions, you should easily be able to execute them. The signature of every subscription is (...params) => (dispatch) => cleanUpFn, so we know how to get the code to execute, and how to stop it, so what's preventing us from doing that? Let's take this subscription as an example:

mySubscription.js
const mySubscription = (delay, effectFn) => dispatch => {
const handle = setInterval(effects.thunk, delay, effectFn);
return () => {
clearInterval(handle);
};
};
module.exports = { mySubscription };

Maybe a test could look something like this:

mySubscription.spec.js
const { mySubscription } = require('./mySubscription.js');
const sinon = require('sinonjs');
describe('mySubscription', () => {
it('creates an interval', () => {
expect.assertions(1);
sinon.spyOn(global, 'setInterval');
const cleanup = mySubscription(1000, sinon.fake())(sinon.fake());
expect(global.setInterval.mock.calls).toHaveLength(1);
cleanup();
setInterval.restore();
});
});

End to End Testing

Calling your subscription in a test can get you fairly far, but the real test is when your application expects some sort of payload from your subscription.

myApplication.spec.js
const { app, effects } = require('ferp');
const { init, update } = require('./myApplication.js');
const { mySubscription } = require('./mySubscription.js');
const testify = (update, isSuccessful, done) => (message, state) => {
if (isSuccessful(message, state)) {
expect(true).toEqual(true);
done();
}
return update(message, state);
};
describe('myApplication', () => {
it('runs an effect from mySubscription', (done) => {
const testEffect = () => ({ type: 'DONE' });
const cleanup = app({
init,
update: testify(update, ((message) => message.type === 'DONE'), done),
subscribe: state => [
[mySubscription, 1000, testEffect],
],
});
});
});