@peter.naydenov/fsm-hub 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -175,7 +175,7 @@ const
175
175
  return {
176
176
  second : 'second'
177
177
  , state
178
- , 'answer' : resultResponseData
178
+ , 'answer' : resultResponseData.response
179
179
  }
180
180
  }
181
181
  }
@@ -186,17 +186,44 @@ const
186
186
 
187
187
  function showme (transitionResult) {
188
188
  console.log ( 'ShowMe' )
189
- console.log (transitionResult)
189
+ console.log ( transitionResult.answer )
190
190
  } // showme func.
191
191
 
192
192
  hub.addFsm ({ one, two })
193
193
  hub.addFunctions ( { showme })
194
194
 
195
195
  // Start!
196
- oneFsm.update ( 'activate', 'try' )
196
+ oneFsm.update ( 'activate', { response:'try'} )
197
197
 
198
198
  // Result on the screen:
199
199
  // ShowMe
200
200
  // { second: 'second', state: 'active', answer: 'try' }
201
201
 
202
- ```
202
+ ```
203
+
204
+
205
+
206
+ ## Release History
207
+
208
+
209
+
210
+ ### 1.0.4 ( 2021-04-02 )
211
+ - [x] Fix: Duplicated update callback if logic contain a chainAction.
212
+
213
+ ### 1.0.3 ( 2021-03-26 )
214
+ - [x] Massive code refactoring;
215
+ - [ ] Bug: Duplicated update callback if logic contain a chainAction.
216
+
217
+
218
+
219
+
220
+
221
+
222
+ ## Credits
223
+ '@peter.naydenov/fsm-hub' was created by Peter Naydenov.
224
+
225
+
226
+ ## License
227
+ '@peter.naydenov/fsm-hub' is released under the MIT License.
228
+
229
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peter.naydenov/fsm-hub",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "FSM orchestration and state-managment tool",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -9,13 +9,19 @@
9
9
  },
10
10
  "author": "Peter Naydenov",
11
11
  "license": "MIT",
12
- "dependencies": {},
12
+ "dependencies": {
13
+ "@peter.naydenov/stack": "1.0.0",
14
+ "ask-for-promise": "1.3.1"
15
+ },
13
16
  "devDependencies": {
14
- "@peter.naydenov/fsm": "2.2.1",
15
- "chai": "4.2.0",
16
- "expect.js": "0.3.1",
17
- "mocha": "6.1.4",
18
- "nyc": "14.1.1"
17
+ "@peter.naydenov/fsm": "2.2.4",
18
+ "chai": "4.3.6",
19
+ "mocha": "10.0.0",
20
+ "nyc": "15.1.0"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/PeterNaydenov/fsm-hub.git"
19
25
  },
20
26
  "keywords": [
21
27
  "fsm",
package/src/index.js CHANGED
@@ -1,186 +1,33 @@
1
- const Fsm = require ( '@peter.naydenov/fsm' );
2
-
3
- const // Error and warnings messages
4
- WRONG_REACTIVITY_RECORD = 'Error: Wrong reactivity record on row %s.'
5
- , REGISTERED_FSM_NAME = 'Warning: FSM "%s" is already registered.'
6
- , REGISTERED_FUNCTION_NAME = 'Warning: Function "%s" is already registered.'
7
- , MISSING_FSM = 'Warning: Fsm "%s" is not registered to the hub.'
8
- , MISSING_FN = 'Warning: Function "%s" is not registered to the hub.'
9
- ;
10
-
11
-
12
-
13
- class FsmHub {
14
-
15
- constructor ( machine, transformerLib ) {
16
- const hub = this;
17
- hub.fsm = {} // Fsm's placeholder
18
- hub.fnCallbacks = {} // Callback functions place
1
+ const
2
+ methods = require ( './methods/index' )
3
+ , msg = require ( './msg' )
4
+ , askForPromise = require ( 'ask-for-promise' )
5
+ , stack = require ( '@peter.naydenov/stack' )
6
+ ;
7
+
8
+ function FsmHub ( machine, transformerLib ) {
9
+ const
10
+ hub = this
11
+ , fnKeys = Object.keys ( methods )
12
+ ;
13
+ hub.fsm = {} // Fsm's placeholder
14
+ hub.fnCallbacks = {} // Callback functions place
19
15
  hub.debug = machine.debug || false
20
-
21
- const result = this._setTransitions ( machine, transformerLib );
22
- hub.transformers = result.transformers // Data transformation function with format 'fsm/fsmListener' or 'fsm/function'
23
- hub.subscribers = result.subscribers // List of fsm names that are listening for 'fsm/state' changes
24
- hub.actions = result.actions // Fsm action that should be applied on 'fsm/state/listener'
25
- hub.callbacks = result.callbacks // List of functional callbacks
26
- } // constructor func.
27
-
28
-
29
-
30
-
31
-
32
- _setTransitions ( {reactivity, transformers}, transformerLib={} ) {
33
- let
34
- mod = {}
35
- , subscribers = {}
36
- , actions = {}
37
- , callbacks = {}
38
- ;
39
-
40
- reactivity.forEach ( (ruleLine,i) => {
41
- const hub = this;
42
- const // ruleLine elements:
43
- fsmName = 0
44
- , onState = 1
45
- , listener = 2
46
- , listenerAct = 3
47
- , isArray = ruleLine instanceof Array
48
- ;
49
-
50
- if ( !isArray ) {
51
- hub._debuger ( WRONG_REACTIVITY_RECORD, i+1 )
52
- return
53
- }
54
-
55
- const
56
- length = ruleLine.length
57
- , hasCorrectLength = (length == 4 || length == 3 ) ? true : false
58
- ;
59
-
60
- if ( !hasCorrectLength ) {
61
- hub._debuger ( WRONG_REACTIVITY_RECORD, i+1 )
62
- return
63
- }
64
-
65
- const key = `${ruleLine[fsmName]}/${ruleLine[onState]}`; // fsmName/state
66
- if ( length == 4 ) { // ruleLine with fsm
67
- if ( !subscribers[key] ) subscribers[key] = []
68
- subscribers [key].push ( ruleLine[listener] )
69
-
70
- const actKey = `${key}/${ruleLine[listener]}`; // fsmName/state/fsmSubscriberName
71
- actions [actKey] = ruleLine[listenerAct]
72
- }
73
-
74
- if ( length == 3 ) { // ruleLine with function callback
75
- if ( !callbacks[key] ) callbacks[key] = []
76
- callbacks[key].push ( ruleLine[listener] )
77
- }
78
- }) // forEach ruleLine
79
- if ( transformers ) {
80
- Object.keys ( transformers ).forEach ( key => {
81
- const
82
- keyFn = transformers [key]
83
- , fn = transformerLib [ keyFn]
84
- ;
85
- if ( fn ) mod[key] = fn
86
- })
87
- }
88
- return { transformers: mod, subscribers, callbacks, actions }
89
- } // _setTransitions func.
90
-
91
-
92
-
93
-
94
-
95
- addFsm ( ins ) {
96
- const hub = this;
97
- Object.keys(ins).forEach ( name => {
98
- if ( hub.fsm[name] ) {
99
- hub._debuger ( REGISTERED_FSM_NAME, name )
100
- return
101
- }
102
- hub.fsm [name] = ins[name]
103
- hub.fsm [name].on ( 'update', (state, response ) => {
104
- hub._callback ( name, state, response )
105
- })
106
- })
107
- } // addFsm func.
108
-
109
-
110
-
111
-
112
-
113
- addFunctions ( ins ) {
114
- const hub = this;
115
- Object.keys(ins).forEach ( name => {
116
- if ( hub.fnCallbacks[name] ) {
117
- hub._debuger ( REGISTERED_FUNCTION_NAME, name )
118
- return
119
- }
120
- hub.fnCallbacks [name] = ins[name]
121
- })
122
- } // addFunctions func.
123
-
124
-
125
-
126
-
127
-
128
- _debuger ( str, data ) {
129
- const hub = this;
130
- if ( hub.debug ) console.log ( str, data )
131
- } // debuger func.
132
-
133
-
134
-
135
-
136
- _callback ( fsmName, state, response ) {
137
- const
138
- hub = this
139
- , itemKey = `${fsmName}/${state}`
140
- , fsmSubscriber = hub.subscribers[itemKey] || false
141
- , callbackNames = hub.callbacks[itemKey] || false
142
- , fnCallbacks = hub.fnCallbacks
143
- , act = hub.actions
144
- ;
145
- let data, wait;
146
-
147
- if ( fsmSubscriber ) {
148
- fsmSubscriber.forEach ( subscriberName => {
149
- if ( !hub.fsm[ subscriberName ] ) {
150
- hub._debuger ( MISSING_FSM, fsmSubscriber )
151
- return
152
- }
153
- const
154
- actionKey = `${itemKey}/${subscriberName}`
155
- , action = act [actionKey]
156
- , transformerKey = `${fsmName}/${subscriberName}`
157
- , transformFn = hub.transformers [transformerKey]
158
- ;
159
- if ( typeof transformFn == 'function' ) data = transformFn (state, response )
160
- else data = response
161
- hub.wait = hub.fsm [ subscriberName ].update ( action, data )
162
- })
163
- } // if fsmSubscriber
164
- if ( callbackNames ) {
165
- if ( hub.wait ) wait = hub.wait
166
- else wait = Promise.resolve ()
167
- wait.then ( () => {
168
- hub.wait = false
169
- callbackNames.forEach ( cbName => {
170
- const
171
- fn = fnCallbacks[cbName]
172
- , transformerKey = `${fsmName}/${cbName}`
173
- , transformFn = hub.transformers [ transformerKey ]
174
- ;
175
- if ( typeof transformFn == 'function' ) data = transformFn (state, response )
176
- else data = response
177
- if ( typeof fn == 'function' ) fn(data)
178
- else hub._debuger ( MISSING_FN, cbName )
179
- })
180
- })
181
- } // if fnCallback
182
- } // _callback func.
183
-
16
+ hub.cache = stack ( 'FIFO' )
17
+ hub.cacheInternal = stack ( 'FIFO' )
18
+ hub.wait = []
19
+ hub.lock = false
20
+ hub.haveInternalRequest = false
21
+ hub.reactivityTask = false
22
+ hub.askForPromise = askForPromise
23
+
24
+ fnKeys.forEach ( k => hub[k] = methods[k](hub,msg) ) // Attach methods to fsmHub
25
+
26
+ const { transformers, subscribers, actions, callbacks } = hub._setTransitions ( machine, transformerLib );
27
+ hub.transformers = transformers // Data transformation function with format 'fsm/fsmListener' or 'fsm/function'
28
+ hub.subscribers = subscribers // List of fsm names that are listening for 'fsm/state' changes
29
+ hub.actions = actions // Fsm action that should be applied on 'fsm/state/listener'
30
+ hub.callbacks = callbacks // List of functional callbacks
184
31
  } // FsmHub class
185
32
 
186
33
 
@@ -0,0 +1,69 @@
1
+ const askForPromise = require("ask-for-promise");
2
+
3
+ function _callback ( hub, msg ) {
4
+ return function _callback ( task, fsmName, state, response ) {
5
+ const
6
+ itemKey = `${fsmName}/${state}`
7
+ , fsmSubscriber = hub.subscribers[itemKey] || false
8
+ , callbackNames = hub.callbacks[itemKey] || false
9
+ , fnCallbacks = hub.fnCallbacks
10
+ , act = hub.actions
11
+ , wait = []
12
+ ;
13
+ let data;
14
+
15
+ if ( !fsmSubscriber && !callbackNames ) {
16
+ task.done ()
17
+ return
18
+ }
19
+
20
+ if ( fsmSubscriber ) {
21
+ fsmSubscriber.forEach ( subscriberName => {
22
+ if ( !hub.fsm[ subscriberName ] ) {
23
+ hub._debugger ( msg.MISSING_FSM, fsmSubscriber )
24
+ return
25
+ }
26
+ const
27
+ actionKey = `${itemKey}/${subscriberName}`
28
+ , action = act [actionKey]
29
+ , transformerKey = `${fsmName}/${subscriberName}`
30
+ , transformFn = hub.transformers [transformerKey]
31
+ ;
32
+ if ( typeof transformFn == 'function' ) data = transformFn (state, response )
33
+ else data = response
34
+
35
+ if ( !data ) data = {}
36
+ data.___internalFlag = true
37
+ const updatePromise = hub.fsm [ subscriberName ].update ( action, data );
38
+ wait.push ( updatePromise )
39
+ })
40
+ } // if fsmSubscriber
41
+
42
+ if ( callbackNames ) {
43
+ let startFunctions = askForPromise ();
44
+ wait.push ( startFunctions.promise )
45
+
46
+ callbackNames.forEach ( cbName => {
47
+ const
48
+ fn = fnCallbacks[cbName]
49
+ , transformerKey = `${fsmName}/${cbName}`
50
+ , transformFn = hub.transformers [ transformerKey ]
51
+ ;
52
+ if ( typeof transformFn == 'function' ) data = transformFn (state, response )
53
+ else data = response
54
+ if ( typeof fn == 'function' ) fn(data)
55
+ else hub._debugger ( msg.MISSING_FN, cbName )
56
+
57
+ })
58
+ startFunctions.done ()
59
+ } // if fnCallback
60
+ Promise.all ( wait ).then ( () => task.done () )
61
+ }} // _callback func.
62
+
63
+
64
+
65
+
66
+
67
+ module.exports = _callback
68
+
69
+
@@ -0,0 +1,10 @@
1
+ function _debugger ( hub ) {
2
+ return function ( str, data ) {
3
+ if ( hub.debug ) console.log ( str, data )
4
+ }} // debugger func.
5
+
6
+
7
+
8
+ module.exports = _debugger
9
+
10
+
@@ -0,0 +1,59 @@
1
+ function _setTransitions ( hub, msg ) {
2
+ return function ( {reactivity, transformers}, transformerLib={} ) {
3
+ let
4
+ mod = {}
5
+ , subscribers = {}
6
+ , actions = {}
7
+ , callbacks = {}
8
+ ;
9
+
10
+ reactivity.forEach ( (ruleLine,i) => {
11
+ const isArray = ruleLine instanceof Array;
12
+
13
+ if ( !isArray ) {
14
+ hub._debugger ( msg.WRONG_REACTIVITY_RECORD, i+1 )
15
+ return
16
+ }
17
+
18
+ const
19
+ length = ruleLine.length
20
+ , [ fsmName, onState, listener, listenerAct ]= ruleLine // RuleLine elements
21
+ , hasCorrectLength = (length == 4 || length == 3 ) ? true : false
22
+ ;
23
+
24
+ if ( !hasCorrectLength ) {
25
+ hub._debugger ( msg.WRONG_REACTIVITY_RECORD, i+1 )
26
+ return
27
+ }
28
+
29
+ const key = `${fsmName}/${onState}`; // fsmName/state
30
+ if ( length == 4 ) { // ruleLine with fsm
31
+ if ( !subscribers[key] ) subscribers[key] = []
32
+ subscribers [key].push ( listener )
33
+
34
+ const actKey = `${key}/${listener}`; // fsmName/state/fsmSubscriberName
35
+ actions [actKey] = listenerAct
36
+ }
37
+
38
+ if ( length == 3 ) { // ruleLine with function callback
39
+ if ( !callbacks[key] ) callbacks[key] = []
40
+ callbacks[key].push ( listener )
41
+ }
42
+ }) // forEach ruleLine
43
+ if ( transformers ) {
44
+ Object.keys ( transformers ).forEach ( key => {
45
+ const
46
+ keyFn = transformers [key]
47
+ , fn = transformerLib [ keyFn]
48
+ ;
49
+ if ( fn ) mod[key] = fn
50
+ })
51
+ }
52
+ return { transformers: mod, subscribers, callbacks, actions }
53
+ }} // _setTransitions func.
54
+
55
+
56
+
57
+ module.exports = _setTransitions
58
+
59
+
@@ -0,0 +1,68 @@
1
+ const askForPromise = require("ask-for-promise")
2
+
3
+ function addFsm ( hub, msg ) {
4
+ return function ( ins ) {
5
+ Object.keys(ins).forEach ( name => {
6
+ if ( hub.fsm[name] ) {
7
+ hub._debugger ( msg.REGISTERED_FSM_NAME, name )
8
+ return
9
+ }
10
+
11
+ function reactivityComplete ( isInternalRequest ) {
12
+
13
+ if ( isInternalRequest ) hub.haveInternalRequest = false
14
+ if ( hub.haveInternalRequest ) return
15
+
16
+ let
17
+ emptyInternalCache = hub.cacheInternal.isEmpty ()
18
+ , emptyCache = hub.cache.isEmpty ()
19
+ , emptyBoth = emptyCache && emptyInternalCache
20
+ ;
21
+ if ( emptyBoth ) {
22
+ hub.lock = false
23
+ return
24
+ }
25
+ let [ name, state, response ] = ( !emptyInternalCache ) ? hub.cacheInternal.pull () : hub.cache.pull ()
26
+ if ( hub.cache.isEmpty () ) hub.lock = false
27
+ if ( hub.cacheInternal.isEmpty () ) hub.haveInternalRequest = false
28
+ hubUpdateWatcher ( name, state, response )
29
+ } // reactivityComplete func.
30
+
31
+
32
+
33
+ function hubUpdateWatcher (name,state,response) {
34
+ let executeReactivity;
35
+ if ( !hub.lock ) {
36
+ hub.lock = true
37
+ executeReactivity = askForPromise ()
38
+ executeReactivity.onComplete ( z => reactivityComplete ( false ) ) // complete of external reaction
39
+ hub._callback ( executeReactivity, name, state, response )
40
+ return
41
+ }
42
+
43
+ if ( response && response.___internalFlag ) {
44
+ if ( hub.haveInternalRequest ) {
45
+ hub.cacheInternal.push ( [[ name, state, response ]])
46
+ return
47
+ }
48
+ let reactivityTask = askForPromise ();
49
+ reactivityTask.onComplete ( z => reactivityComplete ( true ) ) // complete of internal reaction
50
+ hub.haveInternalRequest = true;
51
+ hub._callback ( reactivityTask, name, state, response )
52
+ return
53
+ }
54
+ hub.cache.push ( [[ name, state, response ]])
55
+ } // hubUpdateWatcher func.
56
+
57
+
58
+
59
+ hub.fsm [name] = ins[name]
60
+ hub.fsm [name].on ( 'update', (state,response) => hubUpdateWatcher (name,state,response) )
61
+ })
62
+ }} // addFsm func.
63
+
64
+
65
+
66
+ module.exports = addFsm
67
+
68
+
@@ -0,0 +1,16 @@
1
+ function addFunctions ( hub, msg ) {
2
+ return function ( ins ) {
3
+ Object.keys(ins).forEach ( name => {
4
+ if ( hub.fnCallbacks[name] ) {
5
+ hub._debugger ( msg.REGISTERED_FUNCTION_NAME, name )
6
+ return
7
+ }
8
+ hub.fnCallbacks [name] = ins[name]
9
+ })
10
+ }} // addFunctions func.
11
+
12
+
13
+
14
+ module.exports = addFunctions
15
+
16
+
@@ -0,0 +1,23 @@
1
+ const
2
+ _setTransitions = require ( './_setTransitions' )
3
+ , _debugger = require ( './_debugger' )
4
+ , _callback = require ( './_callback' )
5
+
6
+ , addFsm = require ( './addFsm' )
7
+ , addFunctions = require ( './addFunctions' )
8
+ ;
9
+
10
+ const fn = {
11
+ _setTransitions
12
+ , _debugger
13
+ , _callback
14
+
15
+ , addFsm
16
+ , addFunctions
17
+ };
18
+
19
+
20
+
21
+ module.exports = fn
22
+
23
+
package/src/msg.js ADDED
@@ -0,0 +1,12 @@
1
+ const msg = { // Error and warnings messages
2
+ WRONG_REACTIVITY_RECORD : 'Error: Wrong reactivity record on row %s.'
3
+ , REGISTERED_FSM_NAME : 'Warning: FSM "%s" is already registered.'
4
+ , REGISTERED_FUNCTION_NAME : 'Warning: Function "%s" is already registered.'
5
+ , MISSING_FSM : 'Warning: Fsm "%s" is not registered to the hub.'
6
+ , MISSING_FN : 'Warning: Function "%s" is not registered to the hub.'
7
+ };
8
+
9
+
10
+ module.exports = msg
11
+
12
+
@@ -1,8 +1,7 @@
1
1
  const
2
2
  FsmHub = require ('../src/index.js')
3
3
  , Fsm = require ( '@peter.naydenov/fsm')
4
- , chai = require ( 'chai' )
5
- , expect = require ( 'expect.js')
4
+ , expect = require ( 'chai' ).expect
6
5
  ;
7
6
 
8
7
 
@@ -14,7 +13,7 @@ const
14
13
  , MISSING_FN = 'Warning: Function "%s" is not registered to the hub.'
15
14
  ;
16
15
 
17
- describe ( 'Finite State Machine', () => {
16
+ describe ( 'Fsm Hub', () => {
18
17
 
19
18
 
20
19
  it ( 'Hub structure', () => {
@@ -26,7 +25,7 @@ it ( 'Hub structure', () => {
26
25
  };
27
26
 
28
27
  const hub = new FsmHub ( hubDetails )
29
-
28
+
30
29
  expect ( hub ).to.have.property ( 'fsm' )
31
30
  expect ( hub ).to.have.property ('fnCallbacks')
32
31
  expect ( hub ).to.have.property ( 'transformers' )
@@ -35,7 +34,7 @@ it ( 'Hub structure', () => {
35
34
  expect ( hub ).to.have.property ( 'callbacks' )
36
35
 
37
36
  expect ( hub.subscribers ).to.have.property ( 'one/active' )
38
- expect ( hub.subscribers['one/active'] ).to.be.an.array
37
+ expect ( hub.subscribers['one/active'] ).to.be.an ( 'array' )
39
38
  expect ( hub.subscribers['one/active'][0] ).to.be.equal ( 'two' )
40
39
 
41
40
  expect ( hub.actions ).to.have.property ( 'one/active/two' )
@@ -98,7 +97,7 @@ it ( 'Add a callback function', () => {
98
97
  expect ( activeCallbacks.length ).to.be.equal ( 1 ) // function 'more' should be register only in fnCallbacks.
99
98
 
100
99
  expect ( hub.callbacks ).to.have.property ( 'two/active' )
101
- expect ( hub.callbacks['two/active']).to.be.an.array
100
+ expect ( hub.callbacks['two/active']).to.be.an ( 'array' )
102
101
  expect ( hub.callbacks['two/active'][0]).to.be.equal ( 'showme' )
103
102
 
104
103
  expect ( hub.fnCallbacks ).to.have.property ( 'showme' )
@@ -169,7 +168,7 @@ it ( 'Use hub-tranformer', done => {
169
168
 
170
169
  // Define hub
171
170
  const
172
- machine = {
171
+ hubMachine = {
173
172
  reactivity : [
174
173
  [ 'one', 'active', 'two', 'activate' ]
175
174
  , [ 'two', 'active', 'showme' ]
@@ -190,8 +189,8 @@ it ( 'Use hub-tranformer', done => {
190
189
  }
191
190
  ;
192
191
  // Initialize the hub
193
- const hub = new FsmHub ( machine, transformerLib );
194
-
192
+ const hub = new FsmHub ( hubMachine, transformerLib );
193
+
195
194
  function showme (transitionResult) {
196
195
  const {
197
196
  second
@@ -229,15 +228,15 @@ it ( 'Wrong length of reactivity record', () => {
229
228
  'two/showme' : 'simple'
230
229
  }
231
230
  };
232
- const originalDebuger = FsmHub.prototype._debuger;
233
- FsmHub.prototype._debuger = function ( str, data ) {
231
+ const originalDebugger = FsmHub.prototype._debugger;
232
+ FsmHub.prototype._debugger = function ( str, data ) {
234
233
  expect ( str ).to.be.equal ( WRONG_REACTIVITY_RECORD )
235
234
  }
236
235
  const hub = new FsmHub ( hubDetails );
237
236
 
238
237
  expect ( hub.callbacks ).to.have.property ( 'two/active' )
239
238
  expect ( hub.callbacks ['two/active'][0]).to.be.equal ( 'showme' )
240
- FsmHub.prototype._debuger = originalDebuger
239
+ FsmHub.prototype._debugger = originalDebugger
241
240
  }) // it wrong reactivity record
242
241
 
243
242
 
@@ -256,15 +255,15 @@ it ( 'Wrong type of reactivity record', () => {
256
255
  'two/showme' : 'simple'
257
256
  }
258
257
  };
259
- const originalDebuger = FsmHub.prototype._debuger;
260
- FsmHub.prototype._debuger = function ( str, data ) {
258
+ const originalDebugger = FsmHub.prototype._debugger;
259
+ FsmHub.prototype._debugger = function ( str, data ) {
261
260
  expect ( str ).to.be.equal ( WRONG_REACTIVITY_RECORD )
262
261
  }
263
262
  const hub = new FsmHub ( hubDetails );
264
263
 
265
264
  expect ( hub.callbacks ).to.have.property ( 'two/active' )
266
265
  expect ( hub.callbacks ['two/active'][0]).to.be.equal ( 'showme' )
267
- FsmHub.prototype._debuger = originalDebuger
266
+ FsmHub.prototype._debugger = originalDebugger
268
267
  }) // it wrong reactivity record
269
268
 
270
269
 
@@ -292,7 +291,7 @@ it ( 'Try to add FSM name that is already registered', () => {
292
291
  };
293
292
  // Initialize the hub
294
293
  const hub = new FsmHub ( hubDescription );
295
- hub._debuger = function ( str, data ) {
294
+ hub._debugger = function ( str, data ) {
296
295
  expect ( str ).to.be.equal ( REGISTERED_FSM_NAME )
297
296
  }
298
297
 
@@ -317,7 +316,7 @@ it ( 'Try to add function name that is already registered', () => {
317
316
  ]
318
317
  };
319
318
  const hub = new FsmHub ( machine );
320
- hub._debuger = function ( str, data ) {
319
+ hub._debugger = function ( str, data ) {
321
320
  expect ( str ).to.be.equal ( REGISTERED_FUNCTION_NAME )
322
321
  }
323
322
 
@@ -390,7 +389,7 @@ it ( 'Not registered fsm subscriber', done => {
390
389
  const hub = new FsmHub ( machine, transformerLib );
391
390
 
392
391
  hub.addFsm ({ one })
393
- hub._debuger = function ( str, data ) {
392
+ hub._debugger = function ( str, data ) {
394
393
  expect ( str ).to.be.equal ( MISSING_FSM )
395
394
  done ()
396
395
  }
@@ -448,7 +447,7 @@ it ( 'Transformer is not a function', () => {
448
447
  const hub = new FsmHub ( machine, transformerLib );
449
448
 
450
449
  hub.addFsm ({ one, two })
451
- // hub._debuger = function ( str, data ) {
450
+ // hub._debugger = function ( str, data ) {
452
451
  // expect ( str ).to.be.equal ( MISSING_FSM )
453
452
  // done ()
454
453
  // }
@@ -507,13 +506,13 @@ it ( 'Callback-function with data argument', done => {
507
506
  }
508
507
  }
509
508
  , transformerLib = {
510
- simple ( state, data ) { return `simple-${state}-${data}` }
509
+ simple ( state, data ) { return { try: `simple-${state}-${data.try}`} }
511
510
  }
512
511
  ;
513
512
  // Initialize the hub
514
513
  const hub = new FsmHub ( machine, transformerLib );
515
514
  function showme ( data ) {
516
- expect ( data ).to.equal ( 'simple-active-try' )
515
+ expect ( data.try ).to.equal ( 'simple-active-try' )
517
516
  expect ( two.state == 'active' )
518
517
  one.update ( 'stop' )
519
518
  } // showme func.
@@ -526,119 +525,28 @@ it ( 'Callback-function with data argument', done => {
526
525
  hub.addFsm ({ one, two })
527
526
  hub.addFunctions ({ showme, final })
528
527
  // Start!
529
- one.update ( 'activate', 'try' )
528
+ one.update ( 'activate', { try:'try'} )
530
529
  }) // it callback-function with data argument
531
530
 
532
531
 
533
532
 
534
533
 
534
+ it ( 'Test a Debugger', () => {
535
+ const
536
+ machine = {
537
+ reactivity : [
538
+ [ 'one', 'active', 'two', 'activate' ]
539
+ , [ 'two', 'active', 'showme' ]
540
+ ]
541
+ , debug : true
542
+ };
543
+ const hub = new FsmHub ( machine );
544
+ hub._debugger ( 'Test for %s', 'debugger' )
545
+ }) // it Test debugger
535
546
 
536
- it ( 'Check multiple systems'
537
- // , () => {
538
- // const
539
- // userDescription = {
540
- // init : 'none'
541
- // , table : [
542
- // [ 'none' , 'start' , 'inProgress' , 'setupUser' , [ 'ifSpecial', false ] ]
543
- // , [ 'inProgress' , 'ifSpecial' , 'special' , 'setupSpecialUser', [ false, 'setupNormal'] ]
544
- // , [ 'inProgress' , 'setupNormal' , 'active' , 'setupActiveUser' ]
545
- // , [ 'active' , 'test' , 'testUser' , 'setupTestUser' ]
546
- // ]
547
- // }
548
- // , screenDescription = {
549
- // init : 'none'
550
- // , table : [
551
- // [ 'none', 'start', 'browse', 'startScreen' ]
552
- // , [ 'browse', 'page', 'browse', 'loadPage' ]
553
-
554
- // , [ 'none' , 'sync', 'browse', 'syncUserState', [ 'page', false ] ]
555
- // , [ 'browse', 'sync', 'browse', 'syncUserState', [ 'page', false ] ]
556
- // ]
557
- // , stateData : {
558
- // user : 'N/A' // sync with user state
559
- // , page : 'N/A' // current active page
560
- // }
561
- // }
562
- // , hubDescription = {
563
- // reactivity : [
564
- // [ 'user' , 'none' , 'screen', 'sync' ]
565
- // , [ 'user' , 'active' , 'screen', 'sync' ]
566
- // , [ 'user', 'testUser', 'screen', 'sync' ]
567
- // ]
568
- // , transformers : {
569
- // 'user/screen' : 'transferUserState'
570
- // }
571
- // }
572
- // ;
573
-
574
- // const userLib = {
575
- // setupUser ( task, dependencies, stateData, dt) {
576
- // console.log ( 'setupUser' )
577
- // task.done ({ success : true })
578
- // } // setupUser func.
579
- // , setupSpecialUser ( task, dependencies, stateData, dt) {
580
- // console.log ( 'setupSpecialUser' )
581
- // task.done({ success : false })
582
- // } // setupSpecialUser func.
583
- // , setupActiveUser ( task, dependencies, stateData, dt) {
584
- // console.log ( 'setup Active User' )
585
- // task.done ({ success : true })
586
- // } // setupActiveUser func.
587
- // , setupTestUser ( task, dependencies, stateData, dt ) {
588
- // console.log ( 'USER: setup test user' )
589
- // task.done ({ success : true })
590
- // }
591
- // } // userLib
592
- // const screenLib = {
593
- // startScreen (task, dependencies, stateData, dt) {
594
- // console.log ( 'SCREEN: startScreen' )
595
- // task.done ({ success : true })
596
- // }
597
- // , loadPage (task, dependencies, stateData, dt) {
598
- // console.log ( `SCREEN: loadPage, user - ${stateData.user}`)
599
- // task.done ({ success : true })
600
- // }
601
- // , syncUserState (task, dependencies, stateData, dt) {
602
- // console.log ( `SCREEN: Sync user state. ${dt}`)
603
- // stateData.user = dt
604
- // task.done ({ success : true, stateData })
605
- // }
606
- // } // screenLib
607
- // const hubTransormers = {
608
- // transferUserState ( state, response ) {
609
- // return state
610
- // }
611
- // } // hubTransformers
612
-
613
- // const
614
- // user = new Fsm ( userDescription, userLib )
615
- // , screen = new Fsm ( screenDescription, screenLib )
616
- // , hub = new FsmHub ( hubDescription, hubTransormers )
617
- // ;
618
-
619
- // hub.addFsm ({ user, screen })
620
- // user.update ( 'start' )
621
- // setTimeout ( () => user.update ('test'), 300 )
622
- // }
623
- ) // it check multiple systems
624
-
625
-
626
-
627
-
628
-
629
- it ( 'Test a Debuger', () => {
630
- const
631
- machine = {
632
- reactivity : [
633
- [ 'one', 'active', 'two', 'activate' ]
634
- , [ 'two', 'active', 'showme' ]
635
- ]
636
- , debug : true
637
- };
638
- const hub = new FsmHub ( machine );
639
- hub._debuger ( 'Test for %s', 'debuger' )
640
- }) // it Test debuger
641
547
 
548
+
549
+
642
550
  }) // describe
643
551
 
644
552
 
@@ -0,0 +1,159 @@
1
+ const
2
+ FsmHub = require ('../src/index.js')
3
+ , Fsm = require ( '@peter.naydenov/fsm')
4
+ , expect = require ( 'chai' ).expect
5
+ ;
6
+
7
+ describe ( 'Fsm Hub', () => {
8
+
9
+ it ( 'Check multiple systems', done => {
10
+
11
+ /**
12
+ * Description:
13
+ * Create a 3 fsm systems - human, spy, and recorder
14
+ * - Human: Can receive good and bad news and change his mood according the news;
15
+ * - Spy: Spy on human and sends to recorder the messages that make him unhappy;
16
+ * - Recorder: Storage for bad news. When messages are 3 will stop with the recording and will call function "TimeForChange"
17
+ */
18
+
19
+ const
20
+ recorderDescription = { // Description of the recorder
21
+ init : 'empty'
22
+ , table : [
23
+ [ 'empty' , 'write' , 'used' , 'add_a_warning' ]
24
+ , [ 'used' , 'write' , 'used' , 'add_a_warning', [ 'isFull?', false ] ]
25
+ , [ 'used' , 'isFull?' , 'full' , 'check_if_full' ]
26
+ ]
27
+ , stateData : {
28
+ reasons: []
29
+ }
30
+ }
31
+ , humanDescription = { // Very weak description of human emotions. Just for testing purposes
32
+ init : 'happy'
33
+ , table : [
34
+ [ 'happy' , 'goodNews', 'happy' , 'feel_happy' ]
35
+ , [ 'happy' , 'badNews' , 'unhappy' , 'feel_bad' ]
36
+ , [ 'unhappy' , 'badNews' , 'unhappy' , 'feel_bad' ]
37
+ , [ 'unhappy' , 'goodNews', 'happy' , 'feel_bad' ]
38
+ ]
39
+ }
40
+ , spyDescription = {
41
+ init: 'positive'
42
+ , table : [
43
+ [ 'positive', 'bad' , 'negative' , 'onBad' ]
44
+ , [ 'negative', 'good' , 'positive' , 'onGood' ]
45
+ , [ 'negative', 'bad' , 'negative' , 'onBad' ]
46
+ ]
47
+ }
48
+ , hubDescription = {
49
+ reactivity : [
50
+ [ 'human' , 'unhappy' , 'spy' , 'bad' ]
51
+ , [ 'spy' , 'negative' , 'recorder' , 'write' ]
52
+ , [ 'recorder' , 'full' , 'timeForChange' ]
53
+ , [ 'recorder' , 'full' , 'test' ]
54
+ ]
55
+ , transformers : {
56
+ 'human/spy' : 'emotion2spy'
57
+ , 'spy/recorder' : 'spy2record'
58
+ }
59
+ }
60
+ ;
61
+ // Define libs
62
+ const
63
+ humanLib = {
64
+ feel_happy (task,dependencies, stateData, data ) {
65
+ task.done ({
66
+ success : true
67
+ , response : data
68
+ })
69
+ }
70
+ , feel_bad ( task, dependencies, stateData, data ) {
71
+ task.done ({
72
+ success : true
73
+ , response: data
74
+ })
75
+ }
76
+ }
77
+ , spyLib = {
78
+ onBad ( task, dependencies, stateData, data ) {
79
+ task.done ({
80
+ success : true
81
+ , response : data
82
+ })
83
+ }
84
+ , onGood ( task, dependencies, stateData, data ) {
85
+ task.done ({
86
+ success : true
87
+ , response : data
88
+ })
89
+ }
90
+ }
91
+ , recorderLib = {
92
+ add_a_warning ( task, dependencies, stateData, data ) {
93
+ const { reasons } = stateData;
94
+ if ( !reasons.includes(data.response) ) stateData.reasons.push ( data.response )
95
+ task.done ({
96
+ success : true
97
+ , stateData
98
+ , response : data
99
+ })
100
+ }
101
+ , check_if_full ( task, dependencies, stateData, data ) {
102
+ const { reasons } = stateData;
103
+ if ( reasons.length >= 3 ) task.done ({ success : true, response: data })
104
+ else task.done ({ success : false, response: data })
105
+ }
106
+ }
107
+ , hubLib = {
108
+ emotion2spy ( state,response) {
109
+ return { response }
110
+ }
111
+ , spy2record ( state, response ) { return response }
112
+ }
113
+ ;
114
+ // Define machines and the hub
115
+ const
116
+ human = new Fsm ( humanDescription , humanLib )
117
+ , spy = new Fsm ( spyDescription , spyLib )
118
+ , recorder = new Fsm ( recorderDescription, recorderLib )
119
+ , theHub = new FsmHub ( hubDescription , hubLib )
120
+ ;
121
+ let result = false
122
+
123
+
124
+ function timeForChange ( state, response ) {
125
+ result = 'DONE'
126
+ }
127
+
128
+ function test ( state, response ) {
129
+ expect ( result ).to.be.equal ( 'DONE' )
130
+ expect ( theHub.cache.isEmpty () ).to.be.true
131
+ expect ( theHub.cacheInternal.isEmpty () ).to.be.true
132
+ let rec = recorder.exportState ().stateData.reasons
133
+
134
+ expect ( rec ).to.be.an ( 'array' )
135
+ expect ( rec ).to.have.length ( 3 )
136
+ expect ( rec[0] ).to.be.equal ( 'Car crash' )
137
+ expect ( rec[1] ).to.be.equal ( 'Airplane crash' )
138
+ expect ( rec[2] ).to.be.equal ( 'Storm' )
139
+ done ()
140
+ }
141
+
142
+ theHub.addFsm ({ human, spy, recorder })
143
+ theHub.addFunctions ({ timeForChange, test })
144
+
145
+ human.update ( 'goodNews', 'friends' )
146
+ human.update ( 'badNews', 'Car crash' )
147
+ human.update ( 'badNews', 'Airplane crash' )
148
+ human.update ( 'badNews', 'Storm' )
149
+
150
+ }) // it check multiple systems
151
+
152
+
153
+
154
+
155
+
156
+
157
+ }) // describe
158
+
159
+