// ========================================================================== // SC.Statechart Unit Test // ========================================================================== /*globals SC */

var statechart = null; var root, stateA, stateB, stateC, stateD, stateE, stateF, stateG, stateH; var stateI, stateJ, stateK, stateL, stateM, stateN, monitor; var allState;

module(“SC.Statechart: No Concurrent States - Goto State Tests”, {

setup: function() {

  statechart = SC.Statechart.create({

    monitorIsActive: YES,

    rootState: SC.State.design({

      initialSubstate: 'a',

      a: SC.State.design({

        initialSubstate: 'c',

        c: SC.State.design({
          initialSubstate: 'g',
          g: SC.State.design(),
          h: SC.State.design()
        }),

        d: SC.State.design({
          initialSubstate: 'i',
          i: SC.State.design(),
          j: SC.State.design()
        })

      }),

      b: SC.State.design({

        initialSubstate: 'e',

        e: SC.State.design({
          initialSubstate: 'k',
          k: SC.State.design(),
          l: SC.State.design()
        }),

        f: SC.State.design({
          initialSubstate: 'm',
          m: SC.State.design(),
          n: SC.State.design()
        })

      })

    })

  });

  statechart.initStatechart();

  monitor = statechart.get('monitor');
  root = statechart.get('rootState');
  stateA = statechart.getState('a');
  stateB = statechart.getState('b');
  stateC = statechart.getState('c');
  stateD = statechart.getState('d');
  stateE = statechart.getState('e');
  stateF = statechart.getState('f');
  stateG = statechart.getState('g');
  stateH = statechart.getState('h');
  stateI = statechart.getState('i');
  stateJ = statechart.getState('j');
  stateK = statechart.getState('k');
  stateL = statechart.getState('l');
  stateM = statechart.getState('m');
  stateN = statechart.getState('n');
},

teardown: function() {
  statechart.destroy();
  statechart = monitor = root = null;
  stateA = stateB = stateC = stateD = stateE = stateF = stateG = stateH = stateI = stateJ = null;
  stateK = stateL = stateM = stateN = null;
}

});

test(“check statechart state objects”, function() {

equals(SC.none(stateG), false, 'statechart should return a state object for state with name "g"');
equals(stateG.get('name'), 'g', 'state g should have name "g"');
equals(stateG.get('isCurrentState'), true, 'state G should be current state');
equals(stateG.stateIsCurrentSubstate('g'), true, 'state g should have current substate g');
equals(statechart.stateIsCurrentState('g'), true, 'statechart should have current state g');
equals(statechart.stateIsCurrentState(stateG), true, 'statechart should have current state g');

equals(SC.none(stateM), false, 'statechart should return a state object for state with name "m"');
equals(stateM.get('name'), 'm', 'state m should have name "m"');
equals(stateM.get('isCurrentState'), false, 'state m should not be current state');
equals(stateG.stateIsCurrentSubstate('m'), false, 'state m should not have current substate m');
equals(statechart.stateIsCurrentState('m'), false, 'statechart should not have current state m');
equals(statechart.stateIsCurrentState(stateM), false, 'statechart should not have current state m');

equals(SC.none(stateA), false, 'statechart should return a state object for state with name "a"');
equals(stateA.get('isCurrentState'), false, 'state m should not be current state');
equals(stateA.stateIsCurrentSubstate('a'), false, 'state a should not have current substate g');
equals(stateA.stateIsCurrentSubstate('c'), false, 'state a should not have current substate c');
equals(stateA.stateIsCurrentSubstate('g'), true, 'state a should have current substate g');
equals(stateA.stateIsCurrentSubstate(stateG), true, 'state a should have current substate g');
equals(stateA.stateIsCurrentSubstate(stateM), false, 'state a should not have current substate m');

var stateX = statechart.getState('x');
equals(SC.none(stateX), true, 'statechart should not have a state with name "x"');

});

test(“check statechart initialization”, function() {

equals(monitor.get('length'), 4, 'initial state sequence should be of length 4');
equals(monitor.matchSequence().begin().entered(root, 'a', 'c', 'g').end(), true, 'initial sequence should be entered[ROOT, a, c, g]');
equals(monitor.matchSequence().begin().entered(root, 'a', 'c', 'h').end(), false, 'initial sequence should not be entered[ROOT, a, c, h]');

equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('g'), true, 'current state should be g');

ok(monitor.matchEnteredStates(root, 'a', 'c', 'g'), 'states root, A, C and G should all be entered');

});

test(“go to state h”, function() {

monitor.reset();
statechart.gotoState('h');

equals(monitor.get('length'), 2, 'state sequence should be of length 2');
equals(monitor.matchSequence().begin().exited('g').entered('h').end(), true, 'sequence should be exited[g], entered[h]');
equals(monitor.matchSequence().begin().exited('h').entered('g').end(), false, 'sequence should not be exited[h], entered[g]');

equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('h'), true, 'current state should be h');

ok(monitor.matchEnteredStates(root, 'a', 'c', 'h'), 'states root, A, C and H should all be entered');

});

test(“go to states: h, d”, function() {

statechart.gotoState('h');

monitor.reset();
statechart.gotoState('d');

equals(monitor.get('length'), 4, 'state sequence should be of length 4');
equals(monitor.matchSequence().begin().exited('h', 'c').entered('d', 'i').end(), true, 'sequence should be exited[h, c], entered[d, i]');
equals(monitor.matchSequence().begin().exited('h', 'c').entered('d', 'f').end(), false, 'sequence should not be exited[h, c], entered[d, f]');
equals(monitor.matchSequence().begin().exited('g', 'c').entered('d', 'i').end(), false, 'sequence should not be exited[g, c], entered[d, f]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('i'), true, 'current state should be i');

ok(monitor.matchEnteredStates(root, 'a', 'd', 'i'), 'states root, A, D and I should all be entered');

});

test(“go to states: h, d, h”, function() {

statechart.gotoState('h');
statechart.gotoState('d');

monitor.reset();
statechart.gotoState('h');

equals(monitor.get('length'), 4, 'state sequence should be of length 4');
equals(monitor.matchSequence().begin().exited('i', 'd').entered('c', 'h').end(), true, 'sequence should be exited[i, d], entered[c, h]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('h'), true, 'current state should be h');

ok(monitor.matchEnteredStates(root, 'a', 'c', 'h'), 'states root, A, C and H should all be entered');

});

test(“go to state b”, function() {

monitor.reset();
statechart.gotoState('b');

equals(monitor.get('length'), 6, 'state sequence should be of length 6');
equals(monitor.matchSequence().begin().exited('g', 'c', 'a').entered('b', 'e', 'k').end(), true, 'sequence should be exited[g, c, a], entered[b, e, k]');
equals(monitor.matchSequence().begin().exited('g', 'a', 'c').entered('b', 'e', 'k').end(), false, 'sequence should not be exited[g, a, c], entered[b, e, k]');
equals(monitor.matchSequence().begin().exited('g', 'c', 'a').entered('b', 'k', 'e').end(), false, 'sequence should not be exited[g, c, a], entered[b, k, e]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('k'), true, 'current state should be k');

ok(monitor.matchEnteredStates(root, 'b', 'e', 'k'), 'states root, B, E and K should all be entered');

});

test(“go to state f”, function() {

monitor.reset();
statechart.gotoState('f');

equals(monitor.get('length'), 6, 'state sequence should be of length 6');
equals(monitor.matchSequence().begin().exited('g', 'c', 'a').entered('b', 'f', 'm').end(), true, 'sequence should be exited[g, c, a], entered[b, f, m]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('m'), true, 'current state should be m');

ok(monitor.matchEnteredStates(root, 'b', 'f', 'm'), 'states root, B, F and M should all be entered');

});

test(“go to state n”, function() {

monitor.reset();
statechart.gotoState('n');

equals(monitor.get('length'), 6, 'state sequence should be of length 6');
equals(monitor.matchSequence().begin().exited('g', 'c', 'a').entered('b', 'f', 'n').end(), true, 'sequence should be exited[g, c, a], entered[b, f, n]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('n'), true, 'current state should be n');

ok(monitor.matchEnteredStates(root, 'b', 'f', 'n'), 'states root, B, F and N should all be entered');

});

test(“re-enter state g”, function() {

monitor.reset();
statechart.gotoState('g');

equals(monitor.get('length'), 2, 'state sequence should be of length 2');
equals(monitor.matchSequence().begin().exited('g').entered('g').end(), true, 'sequence should be exited[g], entered[g]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('g'), true, 'current state should be g');

monitor.reset();
equals(monitor.get('length'), 0, 'state sequence should be of length 0 after monitor reset');

var state = statechart.getState('g');
state.reenter();

equals(monitor.get('length'), 2, 'state sequence should be of length 2');
equals(monitor.matchSequence().begin().exited('g').entered('g').end(), true, 'sequence should be exited[g], entered[g]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('g'), true, 'current state should be g');

ok(monitor.matchEnteredStates(root, 'a', 'c', 'g'), 'states root, A, C and G should all be entered');

});

test(“go to g state's ancestor state a”, function() {

monitor.reset();
statechart.gotoState('a');

equals(monitor.get('length'), 6, 'initial state sequence should be of length 6');
equals(monitor.matchSequence().begin().exited('g', 'c', 'a').entered('a', 'c', 'g').end(), true, 'sequence should be exited[g, c, a], entered[a, c, g]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('g'), true, 'current state should be g');

ok(monitor.matchEnteredStates(root, 'a', 'c', 'g'), 'states root, A, C and G should all be entered');

});

test(“go to state b and then go to root state”, function() {

statechart.gotoState('b');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('k'), true, 'current state should be k');

monitor.reset();
statechart.gotoState(statechart.get('rootState'));

var root = statechart.get('rootState');
equals(monitor.get('length'), 8, 'initial state sequence should be of length 6');
equals(monitor.matchSequence().begin().exited('k', 'e', 'b', root).entered(root, 'a', 'c', 'g').end(), 
      true, 'sequence should be exited[k, e, b, ROOT], entered[ROOT, a, c, g]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('g'), true, 'current state should be g');

ok(monitor.matchEnteredStates(root, 'a', 'c', 'g'), 'states root, A, C and G should all be entered');

});

test(“from state g, go to state m calling state g's gotoState”, function() {

equals(stateG.get('isCurrentState'), true, 'state g should be current state');
equals(stateM.get('isCurrentState'), false, 'state m should not be current state');

monitor.reset();
stateG.gotoState('m');

equals(monitor.get('length'), 6, 'initial state sequence should be of length 6');
equals(monitor.matchSequence().begin().exited('g', 'c', 'a').entered('b', 'f', 'm').end(), 
      true, 'sequence should be exited[g, c, a], entered[b, f, m]');
equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
equals(statechart.stateIsCurrentState('m'), true, 'current state should be m');

equals(stateG.get('isCurrentState'), false, 'state g should not be current state');
equals(stateM.get('isCurrentState'), true, 'state m should be current state');

ok(monitor.matchEnteredStates(root, 'b', 'f', 'm'), 'states root, B, F and M should all be entered');

});

test(“from state g, go to state h using 'parentState' syntax”, function() {

monitor.reset();
stateG.gotoState('h');

equals(monitor.matchSequence().begin().exited('g').entered('h').end(), 
  true, 'sequence should be exited[g], entered[h]');

});