statetransition-mixin
Advanced tools
Comparing version 1.4.1 to 1.4.2
@@ -38,3 +38,3 @@ { | ||
"homepage": "https://github.com/arlac77/statetransition-mixin#readme", | ||
"version": "1.4.1" | ||
"version": "1.4.2" | ||
} |
@@ -35,3 +35,3 @@ /* jslint node: true, esnext: true */ | ||
t.initial = initialState; | ||
//t.name = `${actionName}:${t.initial}->${t.target}`; | ||
t.name = `${actionName}:${t.initial}->${t.target}`; | ||
addState(t.initial, t); | ||
@@ -73,4 +73,4 @@ addState(t.during, t); | ||
*/ | ||
stateTransitionRejection(rejected) { | ||
this.state = 'failed'; | ||
stateTransitionRejection(rejected, newState) { | ||
this.state = newState; | ||
this._transitionPromise = undefined; | ||
@@ -129,5 +129,4 @@ this._transition = undefined; | ||
*/ | ||
stateTransitionRejection(rejected) { | ||
//this.error(level => `Executing ${this._transition.name} transition leads to ${rejected}`); | ||
this.state = 'failed'; | ||
stateTransitionRejection(rejected, newState) { | ||
this.state = newState; | ||
this._transitionPromise = undefined; | ||
@@ -145,5 +144,3 @@ this._transition = undefined; | ||
*/ | ||
stateChanged(oldState, newState) { | ||
//this.trace(level => `${this} transitioned from ${oldState} -> ${newState}`); | ||
} | ||
stateChanged(oldState, newState) {} | ||
@@ -169,13 +166,11 @@ get state() { | ||
return promise.then((fullfilled, rejected) => { | ||
return promise.then(fullfilled => { | ||
clearTimeout(th); | ||
if (fullfilled) { | ||
fullfill(fullfilled); | ||
} | ||
if (rejected) { | ||
reject(rejected); | ||
} | ||
fullfill(fullfilled); | ||
}, rejected => { | ||
clearTimeout(th); | ||
reject(rejected); | ||
}) | ||
.catch(r => { | ||
clearTimeout(th); | ||
reject(r); | ||
@@ -237,2 +232,12 @@ }); | ||
if (action.initial[this.state]) { | ||
if (this._transition) { | ||
const t = this._transition; | ||
return this.stateTransitionRejection(new Error( | ||
`Terminate ${t.name} to prepare ${actionName}`), this.state). | ||
then(f => {}, r => { | ||
//console.log(`${actionName} after rejecting ${t.name}`); | ||
return this[actionName](); | ||
}); | ||
} | ||
this._transition = action.initial[this.state]; | ||
@@ -244,2 +249,7 @@ this.state = this._transition.during; | ||
resolved => { | ||
if (!this._transition) { | ||
return this.stateTransitionRejection(new Error( | ||
`Should never happen: ${this.state} and no transition coming from ${actionName}` | ||
), 'failed'); | ||
} | ||
@@ -251,3 +261,3 @@ this.state = this._transition.target; | ||
return this; | ||
}, rejected => this.stateTransitionRejection(rejected)); | ||
}, rejected => this.stateTransitionRejection(rejected, 'failed')); | ||
@@ -254,0 +264,0 @@ return this._transitionPromise; |
@@ -31,2 +31,7 @@ /* global describe, it, xit */ | ||
} | ||
}, | ||
swim: { | ||
diving: { | ||
target: "swimming" | ||
} | ||
} | ||
@@ -58,110 +63,161 @@ }); | ||
toString() { | ||
return `sample: ${this.state}` | ||
return 'ES6 class'; | ||
} | ||
} | ||
stm.defineActionMethods(StatefullClass.prototype, actions); | ||
stm.defineActionMethods(StatefullClass.prototype, actions, true); | ||
describe('states', function () { | ||
describe('static', function () { | ||
const o = new StatefullClass(10, false); | ||
describe('ES6 class', function () { | ||
checks((timeout, fail) => new StatefullClass(timeout, fail)); | ||
}); | ||
it('has initial state', function () { | ||
o.state = 'stopped'; | ||
assert.equal(o.state, 'stopped'); | ||
}); | ||
describe('plain object', function () { | ||
checks((startTime, shouldReject) => { | ||
const o = { | ||
toString() { | ||
return "plain object"; | ||
}, | ||
_start() { | ||
if (shouldReject) return Promise.reject(new Error("always reject")); | ||
it('has action methods', function () { | ||
assert.isDefined(o.stop()); | ||
assert.isDefined(o.start()); | ||
assert.isDefined(o._start()); | ||
assert.isDefined(o._stop()); | ||
}); | ||
return new Promise((f, r) => { | ||
setTimeout(() => { | ||
if (shouldReject) { | ||
r(Promise.reject(new Error("always reject"))); | ||
} else { | ||
f(this); | ||
} | ||
}, startTime); | ||
}); | ||
} | ||
}; | ||
stm.defineActionMethods(o, actions, true); | ||
stm.defineStateTransitionProperties(o, actions, "stopped"); | ||
return o; | ||
}); | ||
}); | ||
describe('start-stop', function () { | ||
const o = new StatefullClass(10, false); | ||
function checks(factory) { | ||
describe('states', function () { | ||
describe('static', function () { | ||
const o = factory(10, false); | ||
it('can be started', function (done) { | ||
o.start().then(() => { | ||
assert.equal(o.state, 'running'); | ||
done(); | ||
}, done); | ||
}); | ||
it('has initial state', function () { | ||
o.state = 'stopped'; | ||
assert.equal(o.state, 'stopped'); | ||
}); | ||
it('can be started while running', function (done) { | ||
o.start().then(() => { | ||
assert.equal(o.state, 'running'); | ||
done(); | ||
}, done); | ||
}); | ||
it('has action methods', function () { | ||
assert.isDefined(o.stop()); | ||
assert.isDefined(o.start()); | ||
assert.isDefined(o._start()); | ||
assert.isDefined(o._stop()); | ||
}); | ||
it('and stoped', function (done) { | ||
o.stop().then(() => { | ||
assert.equal(o.state, 'stopped'); | ||
done(); | ||
}, done); | ||
it('defined methods are enumerable', function () { | ||
const assigend = Object.assign({}, StatefullClass.prototype); | ||
assert.isDefined(assigend.start); | ||
}); | ||
}); | ||
}); | ||
it('can be started while starting', function (done) { | ||
const o = new StatefullClass(10, false); | ||
describe('start-stop', function () { | ||
const o = factory(10, false); | ||
o.start().then(() => {}); | ||
it('can be started', function (done) { | ||
o.start().then(() => { | ||
assert.equal(o.state, 'running'); | ||
done(); | ||
}, done); | ||
}); | ||
assert.equal(o.state, 'starting'); | ||
it('can be started while running', function (done) { | ||
o.start().then(() => { | ||
assert.equal(o.state, 'running'); | ||
done(); | ||
}, done); | ||
}); | ||
o.start().then(() => { | ||
assert.equal(o.state, 'running'); | ||
done(); | ||
}, done).catch(done); | ||
}); | ||
it('and stoped', function (done) { | ||
o.stop().then(() => { | ||
assert.equal(o.state, 'stopped'); | ||
done(); | ||
}, done); | ||
}); | ||
}); | ||
it('can be stopped while starting', function (done) { | ||
const o = new StatefullClass(100, false); | ||
it('can be started while starting', function (done) { | ||
const o = factory(10, false); | ||
o.start().then(() => {}); | ||
o.start().then(() => {}); | ||
assert.equal(o.state, 'starting'); | ||
assert.equal(o.state, 'starting'); | ||
o.stop().then(() => { | ||
assert.equal(o.state, 'stopped'); | ||
done(); | ||
}, done).catch(done); | ||
}); | ||
describe('failures', function () { | ||
it('handle timeout while starting', function (done) { | ||
const o = new StatefullClass(1000, false); | ||
o.start().then(() => {}).catch(e => { | ||
assert.equal(o.state, 'failed'); | ||
o.start().then(() => { | ||
assert.equal(o.state, 'running'); | ||
done(); | ||
}); | ||
}, done).catch(done); | ||
}); | ||
it('handle failure while starting without timeout guard', function (done) { | ||
const o = new StatefullClass(0, true); | ||
it('can be stopped while starting', function (done) { | ||
const o = factory(100, false); | ||
o.start().then((f, r) => { | ||
console.log(`${f} ${r}`); | ||
}).catch(e => { | ||
//console.log(`catch: ${e}`); | ||
assert.equal(o.state, 'failed'); | ||
o.start().then(() => {}); | ||
assert.equal(o.state, 'starting'); | ||
o.stop().then(() => { | ||
assert.equal(o.state, 'stopped'); | ||
done(); | ||
}); | ||
}, done).catch(done); | ||
}); | ||
it('handle failure while starting with timeout guard', function (done) { | ||
const o = new StatefullClass(10, true); | ||
describe('failures', function () { | ||
it('illegal transition', function (done) { | ||
const o = factory(0, false); | ||
try { | ||
o.swim().then(() => { | ||
console.log(`swimming ?`); | ||
}).catch(e => { | ||
//console.log(`swimming failed: ${e}`); | ||
assert.ok(o.state); | ||
done(); | ||
}); | ||
} catch (e) { | ||
console.log(`error: ${e}`); | ||
done(e); | ||
} | ||
}); | ||
o.start().then((f, r) => { | ||
console.log(`${f} ${r}`); | ||
}).catch(e => { | ||
//console.log(`catch: ${e}`); | ||
assert.equal(o.state, 'failed'); | ||
done(); | ||
it('handle timeout while starting', function (done) { | ||
const o = factory(1000, false); | ||
o.start().then(() => {}).catch(e => { | ||
assert.equal(o.state, 'failed'); | ||
done(); | ||
}); | ||
}); | ||
it('handle failure while starting without timeout guard', function (done) { | ||
const o = factory(0, true); | ||
o.start().then((f, r) => { | ||
console.log(`${f} ${r}`); | ||
}).catch(e => { | ||
assert.equal(o.state, 'failed'); | ||
done(); | ||
}); | ||
}); | ||
it('handle failure while starting with timeout guard', function (done) { | ||
const o = factory(10, true); | ||
o.start().then((f, r) => { | ||
console.log(`${f} ${r}`); | ||
}).catch(e => { | ||
assert.equal(o.state, 'failed'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25034
416