-
Notifications
You must be signed in to change notification settings - Fork 9
/
createEffectCapableStore.test.js
139 lines (112 loc) · 3.82 KB
/
createEffectCapableStore.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { assert } from 'chai';
import { spy } from 'sinon';
import { createStore } from 'redux';
import sideEffect from '../src/sideEffect';
import createEffectCapableStore from '../src/createEffectCapableStore';
describe('Create effect capable store', () => {
it('should execute all the effects in next call stack', done => {
const effect = spy();
function* reducer() {
yield sideEffect(effect, 42, 'foobar');
yield sideEffect(effect);
return 1;
}
const storeFactory = createEffectCapableStore(createStore);
const store = storeFactory(reducer);
assert.isFalse(effect.called);
setTimeout(() => {
assert.equal(effect.callCount, 2);
assert.deepEqual(effect.firstCall.args, [store.dispatch, 42, 'foobar']);
assert.deepEqual(effect.secondCall.args, [store.dispatch]);
done();
});
});
it('should allow to yield effect within action which has been dispatched through effect', done => {
const effect = spy();
function* reducer(appState = 1, action) {
if (action.type === 'first') {
yield sideEffect(dispatch => dispatch({ type: 'second' }));
} else if (action.type === 'second') {
yield sideEffect(effect, 42);
}
return appState;
}
const storeFactory = createEffectCapableStore(createStore);
const store = storeFactory(reducer);
store.dispatch({ type: 'first' });
assert.isFalse(effect.called);
setTimeout(() => {
setTimeout(() => {
assert.equal(effect.callCount, 1);
assert.deepEqual(effect.firstCall.args, [store.dispatch, 42]);
done();
});
});
});
it('should wrap the next reducer even when the replaceReducer is called', done => {
const effect = spy();
function* testingReducer(appState, action) {
if (action.type === 'foo') {
yield sideEffect(effect, 42);
}
return 1;
}
const testingStore = createEffectCapableStore(createStore)(testingReducer);
testingStore.replaceReducer(testingReducer);
testingStore.dispatch({ type: 'foo' });
setTimeout(() => {
assert.equal(effect.callCount, 1);
assert.deepEqual(effect.firstCall.args, [testingStore.dispatch, 42]);
done();
});
});
it('should ignore side effects when any action is dispatched while reducer is being replaced', done => {
const effect = spy();
function* testingReducer(appState, action) {
if (action.type === '@@redux/INIT') {
yield sideEffect(effect, 42);
}
return 1;
}
const testingStore = createEffectCapableStore(createStore)(testingReducer);
testingStore.replaceReducer(testingReducer);
setTimeout(() => {
assert.equal(effect.callCount, 1);
assert.deepEqual(effect.firstCall.args, [testingStore.dispatch, 42]);
done();
});
});
it('should return action result when dispatch is called so that middleware chain is not broken', () => {
function* reducer() {
return 1;
}
const action = { type: 'foo' };
const testingStore = createEffectCapableStore(createStore)(reducer);
const result = testingStore.dispatch(action);
assert.equal(result, action);
});
it('should not execute effects when original dispatch function is called', done => {
const effect = spy();
const returnValue = spy(() => 42);
function* testingReducer() {
yield sideEffect(effect);
return returnValue();
}
const storeEnhancer = reducer => {
const store = createStore(reducer, undefined);
return {
...store,
liftedDispatch: store.dispatch
};
};
const store = createEffectCapableStore(storeEnhancer)(testingReducer);
store.liftedDispatch({
type: 'FOO'
});
assert.equal(returnValue.callCount, 2);
setTimeout(() => {
assert.equal(effect.callCount, 1);
done();
});
});
});