aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/utils')
-rw-r--r--src/features/utils/ActionBinding.js29
-rw-r--r--src/features/utils/FeatureStore.js47
-rw-r--r--src/features/utils/FeatureStore.test.js92
3 files changed, 154 insertions, 14 deletions
diff --git a/src/features/utils/ActionBinding.js b/src/features/utils/ActionBinding.js
new file mode 100644
index 000000000..497aa071b
--- /dev/null
+++ b/src/features/utils/ActionBinding.js
@@ -0,0 +1,29 @@
1export default class ActionBinding {
2 action;
3
4 isActive = false;
5
6 constructor(action) {
7 this.action = action;
8 }
9
10 start() {
11 if (!this.isActive) {
12 const { action } = this;
13 action[0].listen(action[1]);
14 this.isActive = true;
15 }
16 }
17
18 stop() {
19 if (this.isActive) {
20 const { action } = this;
21 action[0].off(action[1]);
22 this.isActive = false;
23 }
24 }
25}
26
27export const createActionBindings = actions => (
28 actions.map(a => new ActionBinding(a))
29);
diff --git a/src/features/utils/FeatureStore.js b/src/features/utils/FeatureStore.js
index 66b66a104..0bc10e176 100644
--- a/src/features/utils/FeatureStore.js
+++ b/src/features/utils/FeatureStore.js
@@ -1,21 +1,40 @@
1import Reaction from '../../stores/lib/Reaction';
2
3export class FeatureStore { 1export class FeatureStore {
4 _actions = null; 2 _actions = [];
3
4 _reactions = [];
5
6 stop() {
7 this._stopActions();
8 this._stopReactions();
9 }
10
11 // ACTIONS
12
13 _registerActions(actions) {
14 this._actions = actions;
15 this._startActions();
16 }
5 17
6 _reactions = null; 18 _startActions(actions = this._actions) {
19 actions.forEach(a => a.start());
20 }
21
22 _stopActions(actions = this._actions) {
23 actions.forEach(a => a.stop());
24 }
25
26 // REACTIONS
27
28 _registerReactions(reactions) {
29 this._reactions = reactions;
30 this._startReactions();
31 }
7 32
8 _listenToActions(actions) { 33 _startReactions(reactions = this._reactions) {
9 if (this._actions) this._actions.forEach(a => a[0].off(a[1])); 34 reactions.forEach(r => r.start());
10 this._actions = [];
11 actions.forEach(a => this._actions.push(a));
12 this._actions.forEach(a => a[0].listen(a[1]));
13 } 35 }
14 36
15 _startReactions(reactions) { 37 _stopReactions(reactions = this._reactions) {
16 if (this._reactions) this._reactions.forEach(r => r.stop()); 38 reactions.forEach(r => r.stop());
17 this._reactions = [];
18 reactions.forEach(r => this._reactions.push(new Reaction(r)));
19 this._reactions.forEach(r => r.start());
20 } 39 }
21} 40}
diff --git a/src/features/utils/FeatureStore.test.js b/src/features/utils/FeatureStore.test.js
new file mode 100644
index 000000000..92308bf52
--- /dev/null
+++ b/src/features/utils/FeatureStore.test.js
@@ -0,0 +1,92 @@
1import PropTypes from 'prop-types';
2import { observable } from 'mobx';
3import { FeatureStore } from './FeatureStore';
4import { createActionsFromDefinitions } from '../../actions/lib/actions';
5import { createActionBindings } from './ActionBinding';
6import { createReactions } from '../../stores/lib/Reaction';
7
8const actions = createActionsFromDefinitions({
9 countUp: {},
10}, PropTypes.checkPropTypes);
11
12class TestFeatureStore extends FeatureStore {
13 @observable count = 0;
14
15 reactionInvokedCount = 0;
16
17 start() {
18 this._registerActions(createActionBindings([
19 [actions.countUp, this._countUp],
20 ]));
21 this._registerReactions(createReactions([
22 this._countReaction,
23 ]));
24 }
25
26 _countUp = () => {
27 this.count += 1;
28 };
29
30 _countReaction = () => {
31 this.reactionInvokedCount += 1;
32 }
33}
34
35describe('FeatureStore', () => {
36 let store = null;
37
38 beforeEach(() => {
39 store = new TestFeatureStore();
40 });
41
42 describe('registering actions', () => {
43 it('starts the actions', () => {
44 store.start();
45 actions.countUp();
46 expect(store.count).toBe(1);
47 });
48 it('starts the reactions', () => {
49 store.start();
50 actions.countUp();
51 expect(store.reactionInvokedCount).toBe(1);
52 });
53 });
54
55 describe('stopping the store', () => {
56 it('stops the actions', () => {
57 store.start();
58 actions.countUp();
59 store.stop();
60 actions.countUp();
61 expect(store.count).toBe(1);
62 });
63 it('stops the reactions', () => {
64 store.start();
65 actions.countUp();
66 store.stop();
67 store.count += 1;
68 expect(store.reactionInvokedCount).toBe(1);
69 });
70 });
71
72 describe('toggling the store', () => {
73 it('restarts the actions correctly', () => {
74 store.start();
75 actions.countUp();
76 store.stop();
77 actions.countUp();
78 store.start();
79 actions.countUp();
80 expect(store.count).toBe(2);
81 });
82 it('restarts the reactions correctly', () => {
83 store.start();
84 actions.countUp();
85 store.stop();
86 actions.countUp();
87 store.start();
88 actions.countUp();
89 expect(store.count).toBe(2);
90 });
91 });
92});