Skip to content

Commit

Permalink
Added a wrapper to manage un-handled epic error
Browse files Browse the repository at this point in the history
  • Loading branch information
MV88 committed May 3, 2017
1 parent 68ef8a8 commit dc36737
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 4 deletions.
18 changes: 15 additions & 3 deletions web/client/utils/PluginsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,24 @@ const pluginsMergeProps = (stateProps, dispatchProps, ownProps) => {
const {pluginCfg, ...otherProps} = ownProps;
return assign({}, otherProps, stateProps, dispatchProps, pluginCfg || {});
};

/**
* default wrapper for the epics.
* @param epic the epic to wrap
* @return the epic wrapped with error catch and re-subscribe functionalities.S
* @memberof utils.PluginsUtils
*/
const defaultEpicWrapper = epic => (...args) =>
epic(...args).catch((error, source) => {
setTimeout(() => { throw error; }, 0);
return source;
});
/**
* Utilities to manage plugins
* @class
* @memberof utils
*/
const PluginsUtils = {
defaultEpicWrapper,
/**
* Produces the reducers from the plugins, combined with other plugins
* @param {array} plugins the plugins
Expand All @@ -163,11 +174,12 @@ const PluginsUtils = {
* Produces the rootEpic for the plugins, combined with other epics passed as 2nd argument
* @param {array} plugins the plugins
* @param {function[]} [epics] the epics to add to the plugins' ones
* @param {function} [epicWrapper] returns a function that wraps the epic
* @return {function} the rootEpic, obtained combining plugins' epics and the other epics passed as argument.
*/
combineEpics: (plugins, epics = {}) => {
combineEpics: (plugins, epics = {}, epicWrapper = defaultEpicWrapper) => {
const pluginEpics = assign({}, getEpics(plugins), epics);
return combineEpics( ...Object.keys(pluginEpics).map(k => pluginEpics[k]));
return combineEpics( ...Object.keys(pluginEpics).map(k => pluginEpics[k]).map(epicWrapper));
},
getReducers,
filterState,
Expand Down
44 changes: 43 additions & 1 deletion web/client/utils/__tests__/PluginUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,23 @@ const expect = require('expect');
const PluginsUtils = require('../PluginsUtils');
const assign = require('object-assign');
const MapSearchPlugin = require('../../plugins/MapSearch');
const Rx = require('rxjs');
const { ActionsObservable } = require('redux-observable');

const epicTest = (epic, count, action, callback, state = {}) => {
const actions = new Rx.Subject();
const actions$ = new ActionsObservable(actions);
const store = { getState: () => state };
epic(actions$, store)
.take(count)
.toArray()
.subscribe(callback);
if (action.length) {
action.map(act => actions.next(act));
} else {
actions.next(action);
}
};
describe('PluginsUtils', () => {
beforeEach((done) => {
document.body.innerHTML = '<div id="container"></div>';
Expand Down Expand Up @@ -80,10 +96,36 @@ describe('PluginsUtils', () => {
});
it('combineEpics', () => {
const plugins = {MapSearchPlugin: MapSearchPlugin};
const appEpics = {appEpics: (actions$) => actions$.ofType('TEST_ACTION').map({type: "NEW_ACTION_TEST"})};
const appEpics = {appEpics: (actions$) => actions$.ofType('TEST_ACTION').map(() => ({type: "NEW_ACTION_TEST"}))};
const epics = PluginsUtils.combineEpics(plugins, appEpics);
expect(typeof epics ).toEqual('function');
});
it('combineEpics with defaultEpicWrapper', (done) => {
const plugins = {MapSearchPlugin: MapSearchPlugin};
const appEpics = {
appEpics: (actions$) => actions$.filter( a => a.type === 'TEST_ACTION').map(() => ({type: "RESPONSE"})),
appEpics2: (actions$) => actions$.filter( a => a.type === 'TEST_ACTION1').map(() => {throw new Error(); })};
const epics = PluginsUtils.combineEpics(plugins, appEpics);
expect(typeof epics ).toEqual('function');
epicTest(epics, 1, [{type: 'TEST_ACTION1'}, {type: 'TEST_ACTION'}], actions => {
expect(actions.length).toBe(1);
expect(actions[0].type).toBe("RESPONSE");
done();
});
});

it('combineEpics with custom wrapper', (done) => {
const plugins = {MapSearchPlugin: MapSearchPlugin};
let counter = 0;
const appEpics = {
appEpics: (actions$) => actions$.filter( a => a.type === 'TEST_ACTION').map(() => ({type: "RESPONSE"}))};
const epics = PluginsUtils.combineEpics(plugins, appEpics, epic => (...args) => {counter++; return epic(...args); });
epicTest( epics, 1, [{type: 'TEST_ACTION1'}, {type: 'TEST_ACTION'}], () => {
expect(counter).toBe(1);
done();
});
});

it('connect', () => {
const MyComponent = (props) => <div>{props.test}</div>;
const Connected = PluginsUtils.connect((state) => ({test: state.test}), {})(MyComponent);
Expand Down

0 comments on commit dc36737

Please sign in to comment.