Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/helpers/updateState.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de

function updateState(machine, state) {
var newState;
var oldState;

if (typeof state === 'undefined') return;
if (typeof state === 'string' || typeof state === 'number') {
Expand All @@ -33,10 +34,21 @@ function updateState(machine, state) {
throw new Error((0, _constants.ERROR_UNCOVERED_STATE)(newState.name));
}

var handler = machine.transitions[machine.state.name]['_exit'];
if (typeof handler === 'function') {
handler.apply(machine, [machine, newState.name]);
}

(0, _handleMiddleware2.default)(_constants.MIDDLEWARE_STATE_WILL_CHANGE, machine);

oldState = machine.state;
machine.state = newState;

var handler = machine.transitions[newState.name]['_entry'];
if (typeof handler === 'function') {
handler.apply(machine, [machine, oldState.name]);
}

(0, _handleMiddleware2.default)(_constants.MIDDLEWARE_PROCESS_STATE_CHANGE, machine);
}
module.exports = exports['default'];
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "stent",
"version": "8.0.0",
"name": "platform28-stent",
"version": "8.0.1",
"description": "Stent is combining the ideas of redux with the concept of state machines",
"main": "lib",
"scripts": {
Expand Down
50 changes: 25 additions & 25 deletions reports/test-results.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<testsuite name="Mocha Tests" tests="89" failures="0" errors="0" skipped="0" timestamp="Sat, 21 Mar 2020 10:14:31 GMT" time="1.147">
<testcase classname="Given the createMachine factory when passing invalid configuration" name="should throw errors if state or transitions are missing" time="0.002"/>
<testcase classname="Given the createMachine factory when we create a machine without a name" name="it should automatically generate a name and allow the creation" time="0.002"/>
<testsuite name="Mocha Tests" tests="89" failures="0" errors="0" skipped="0" timestamp="Mon, 20 Apr 2020 06:40:35 GMT" time="0.21">
<testcase classname="Given the createMachine factory when passing invalid configuration" name="should throw errors if state or transitions are missing" time="0.001"/>
<testcase classname="Given the createMachine factory when we create a machine without a name" name="it should automatically generate a name and allow the creation" time="0.001"/>
<testcase classname="Given the createMachine factory when we create a machine without a state" name="it should throw an error" time="0"/>
<testcase classname="Given the createMachine factory when we create a machine using the shorter syntax" name="it should create a working machine" time="0"/>
<testcase classname="Given the createMachine factory when we dispatch an action" name="it should handle the action" time="0.001"/>
Expand All @@ -17,47 +17,47 @@
<testcase classname="Given the call helper when calling it with a non-function argument" name="should catch the error and transition to Failure state with a meaningful error message" time="0.002"/>
<testcase classname="Given the connect helper when using connect" name="should allow mapping to machines" time="0.001"/>
<testcase classname="Given the connect helper when using connect" name="should add only one middleware" time="0"/>
<testcase classname="Given the connect helper when using connect and when we update the state of the mapped machine/s" name="should fire the mapping function" time="0.001"/>
<testcase classname="Given the connect helper when using connect and when we update the state of the mapped machine/s" name="should fire the mapping function" time="0"/>
<testcase classname="Given the connect helper when using connect and we use `mapOnce`" name="should fire the mapping only once" time="0"/>
<testcase classname="Given the connect helper when using connect and we use `mapSilent`" name="should fire the mapping only when the machine changes its state" time="0"/>
<testcase classname="Given the connect helper when using connect and we pass no mapping function" name="should still do the connecting" time="0"/>
<testcase classname="Given the connect helper when using connect and we have two mappers" name="should call them only if the machine that they are connected transitions" time="0.001"/>
<testcase classname="Given the connect helper when using connect and we have a middleware attached" name="should call the proper middleware hook" time="0"/>
<testcase classname="Given the connect helper when using connect and we have a middleware attached" name="should call the proper middleware hook" time="0.001"/>
<testcase classname="Given the connect helper when using connect and we destroy a machine" name="should remove the machine from any mapping" time="0.001"/>
<testcase classname="Given the connect helper when we use the `disconnect` function" name="should detach the mapping" time="0.001"/>
<testcase classname="Given the connect helper when we use the `disconnect` function and we have a middleware attached" name="should call the proper middleware hook" time="0"/>
<testcase classname="Given the handleAction function when we add a handler which is not expected" name="should throw an error" time="0.001"/>
<testcase classname="Given the handleAction function when we add a handler which is not expected" name="should throw an error" time="0"/>
<testcase classname="Given the handleAction function when dispatching an action which is missing in the current state" name="should silently do nothing and NOT throw an error (handleAction returns false)" time="0"/>
<testcase classname="Given the handleAction function when there is nothing for the current state" name="should return false" time="0"/>
<testcase classname="Given the handleAction function when we transition to a state which has no actions or it is undefined" name="should throw an error if there is no such a state defined" time="0"/>
<testcase classname="Given the handleAction function when we transition to a state which has no actions or it is undefined" name="should throw an error if there the state has no actions inside" time="0"/>
<testcase classname="Given the handleAction function when we transition to a state which has no actions or it is undefined" name="should throw an error if there the state has no actions inside" time="0.001"/>
<testcase classname="Given the handleAction function when the handler is a string" name="should change the state of the machine to that string" time="0"/>
<testcase classname="Given the handleAction function when the handler is an object" name="should change the state of the machine to that object" time="0"/>
<testcase classname="Given the handleAction function when the handler is a function" name="should call the handler with the machine and the given payload" time="0"/>
<testcase classname="Given the handleAction function when the handler is a function" name="should update the state" time="0"/>
<testcase classname="Given the handleAction function when the handler is a function" name="should update the state even if a string is returned" time="0"/>
<testcase classname="Given the handleAction function when the handler is a function" name="should update the state even if a string is returned" time="0.001"/>
<testcase classname="Given the handleAction function when the handler is a generator" name="should change the state if we return a string" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator" name="should change the state if we yield a primitive" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator" name="should change the state if we yield an object" time="0.001"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper" name="should execute the function" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator" name="should change the state if we yield an object" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper" name="should execute the function" time="0.001"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper" name="should execute the function and return the result if any" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper" name="should execute the function with proper parameters" time="0.001"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper and when the function returns a promise" name="should return the value of the resolved promise" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper and when the function returns a promise" name="should throw an error if the promise is rejected" time="0.001"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper when the function returns another generator" name="should iterate through that inner generator" time="0.001"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper and when the function returns a promise" name="should throw an error if the promise is rejected" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper when the function returns another generator" name="should iterate through that inner generator" time="0"/>
<testcase classname="Given the handleAction function when the handler is a generator and we use the call helper when the function returns another generator" name="should handle errors properly through the generator chain" time="0.001"/>
<testcase classname="Given the handleAction function when we have middlewares registered" name="should fire the middleware/s if an action is dispatched and after that" time="0.001"/>
<testcase classname="Given the handleAction function when we have middlewares registered" name="should pass the machine as context" time="0"/>
<testcase classname="Given the handleAction function when we have middlewares registered" name="should skip to the next middleware if there is no appropriate hook defined" time="0"/>
<testcase classname="Given the handleAction function when we have middlewares registered" name="should skip to the next middleware if there is no appropriate hook defined" time="0.001"/>
<testcase classname="Given the handleAction function when we have middlewares registered" name="should fire the middleware/s when the state is changed" time="0"/>
<testcase classname="Given the handleActionLatest helper and we fire same action twice within the same state" name="should kill the first generator and its processes leaving only the new one working" time="0.033"/>
<testcase classname="Given the handleGenerator helper when we run the same generator again and we want to cancel the first one" name="should cancel the second generator" time="0.033"/>
<testcase classname="Given the handleActionLatest helper and we fire same action twice within the same state" name="should kill the first generator and its processes leaving only the new one working" time="0.035"/>
<testcase classname="Given the handleGenerator helper when we run the same generator again and we want to cancel the first one" name="should cancel the second generator" time="0.032"/>
<testcase classname="Given the registerMethods helper when registering methods" name="should create methods dynamically (based on states and actions)" time="0.001"/>
<testcase classname="Given the registerMethods helper when registering methods" name="should dispatch an action with the given payload" time="0"/>
<testcase classname="Given the registerMethods helper when registering methods" name="should check if the machine is in a particular state" time="0.001"/>
<testcase classname="Given the registerMethods helper when registering methods" name="should check if the machine is in a particular state" time="0"/>
<testcase classname="Given the registerMethods helper when registering methods" name="should check if particular transition is allowed" time="0"/>
<testcase classname="Given the registerMethods helper when registering methods when some of the transitions match the word `name`, `transition` or `state`" name="should throw an error if name is used" time="0"/>
<testcase classname="Given the registerMethods helper when registering methods when some of the transitions match the word `name`, `transition` or `state`" name="should throw an error if transitions is used" time="0.001"/>
<testcase classname="Given the registerMethods helper when registering methods when some of the transitions match the word `name`, `transition` or `state`" name="should throw an error if transitions is used" time="0"/>
<testcase classname="Given the registerMethods helper when registering methods when some of the transitions match the word `name`, `transition` or `state`" name="should throw an error if state is used" time="0"/>
<testcase classname="Given the registerMethods helper when registering methods when some of the transitions match the word `name`, `transition` or `state`" name="should throw an error if destroy is used" time="0.001"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;run&quot; to &quot;run&quot;" time="0"/>
Expand All @@ -66,24 +66,24 @@
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;the answer is 42&quot; to &quot;theAnswerIs42&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;Hello World&quot; to &quot;helloWorld&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;get-data-from-there&quot; to &quot;getDataFromThere&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;another_mixed example-of^% a method&quot; to &quot;anotherMixedExampleOfAMethod&quot;" time="0.001"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;another_mixed example-of^% a method&quot; to &quot;anotherMixedExampleOfAMethod&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;startProcess&quot; to &quot;startProcess&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;start Pro ceSs&quot; to &quot;startProCeSs&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;/initializing&quot; to &quot;initializing&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;/initializing/&quot; to &quot;initializing&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;/initializing/stage-one&quot; to &quot;initializingStageOne&quot;" time="0"/>
<testcase classname="Given the toCamelCase helper when using toCamelCase" name="should transform &quot;/initializing/stage_one&quot; to &quot;initializingStageOne&quot;" time="0"/>
<testcase classname="Given the validateConfig helper function when validating config" name="should throw errors if state or transitions are missing" time="0.001"/>
<testcase classname="Given the validateState helper when using validateState" name="throw an error if the state has no &quot;name&quot; property inside" time="0"/>
<testcase classname="Given the Logger middleware when using Logger with function and string as a handler" name="should log to the console" time="0"/>
<testcase classname="Given the Logger middleware when using the Logger with a generator function" name="should log every step of the generator" time="0.002"/>
<testcase classname="Given the connect React helper when connecting a component" name="should call our mapping function" time="0.032"/>
<testcase classname="Given the connect React helper when connecting a component" name="should map machines state and actions properly" time="0.005"/>
<testcase classname="Given the validateConfig helper function when validating config" name="should throw errors if state or transitions are missing" time="0"/>
<testcase classname="Given the validateState helper when using validateState" name="throw an error if the state has no &quot;name&quot; property inside" time="0.001"/>
<testcase classname="Given the Logger middleware when using Logger with function and string as a handler" name="should log to the console" time="0.001"/>
<testcase classname="Given the Logger middleware when using the Logger with a generator function" name="should log every step of the generator" time="0.001"/>
<testcase classname="Given the connect React helper when connecting a component" name="should call our mapping function" time="0.025"/>
<testcase classname="Given the connect React helper when connecting a component" name="should map machines state and actions properly" time="0.007"/>
<testcase classname="Given the connect React helper when connecting a component" name="should get re-rendered if a machine's state is changed" time="0.007"/>
<testcase classname="Given the connect React helper when connecting a component" name="should NOT get re-rendered if mapped with `mapOnce`" time="0.002"/>
<testcase classname="Given the connect React helper when connecting a component when we update the state of the machine many times in a single frame" name="should trigger the mapping function many times" time="0.002"/>
<testcase classname="Given the connect React helper when unmounting the component" name="should detach from the machines" time="0.004"/>
<testcase classname="Given the connect React helper when we connect without mapping" name="should render correctly" time="0.001"/>
<testcase classname="Given the connect React helper when we connect without mapping" name="should render correctly" time="0.002"/>
<testcase classname="Given the connect React helper when we use mapSilent" name="should only call the mapping function when the machine changes its state" time="0.002"/>
<testcase classname="Given the connect React helper and we have a middleware attached" name="should call the proper hooks" time="0.001"/>
<testcase classname="Given the connect React helper and we have a middleware attached and we destroy a machine" name="should call the proper hooks" time="0"/>
Expand Down
16 changes: 15 additions & 1 deletion src/helpers/updateState.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {

export default function updateState(machine, state) {
var newState;
var oldState;

if (typeof state === 'undefined') return;
if (typeof state === 'string' || typeof state === 'number') {
Expand All @@ -24,10 +25,23 @@ export default function updateState(machine, state) {
throw new Error(ERROR_UNCOVERED_STATE(newState.name));
}

var handler = machine.transitions[machine.state.name]['_exit'];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use @exit and @enter instead of _exit and _entry. It seems more intuitive for me. What you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not tied to any specific terminology. We could use @exit and @enter - but I see the @ symbol potentially being potentially problematic. The _ was more based on my understanding of the convention being used in JS to represent 'private' members/methods.

if (typeof handler === 'function')
{
handler.apply(machine,[machine, newState.name]);
}

handleMiddleware(MIDDLEWARE_STATE_WILL_CHANGE, machine);

oldState = machine.state;
machine.state = newState;

var handler = machine.transitions[newState.name]['_entry'];
if (typeof handler === 'function')
{
handler.apply(machine,[machine, oldState.name]);
}

handleMiddleware(MIDDLEWARE_PROCESS_STATE_CHANGE, machine);

}
}
Loading