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

var TestState; var obj1, rootState1, stateA, stateB; var obj2, rootState2, stateC, stateD;

module(“SC.Statechart: invokeStateMethod method Tests”, {

setup: function() {
  TestState = SC.State.extend({
    testInvokedCount: 0,
    arg1: undefined,
    arg2: undefined,
    returnValue: undefined,

    testInvoked: function() {
      return this.get('testInvokedCount') > 0;
    }.property('testInvokedCount'),

    test: function(arg1, arg2) {
      this.set('testInvokedCount', this.get('testInvokedCount') + 1);
      this.set('arg1', arg1);
      this.set('arg2', arg2);
      if (this.get('returnValue') !== undefined) {
        return this.get('returnValue');
      } 
    }
  });

  obj1 = SC.Object.extend(SC.StatechartManager, {

    initialState: 'stateA',

    rootStateExample: TestState.design({
      testX: function(arg1, arg2) {
        this.set('testInvokedCount', this.get('testInvokedCount') + 1);
        this.set('arg1', arg1);
        this.set('arg2', arg2);
        if (this.get('returnValue') !== undefined) {
          return this.get('returnValue');
        } 
      }
    }),

    stateA: TestState.design(),

    stateB: TestState.design()

  });

  obj1 = obj1.create();
  rootState1 = obj1.get('rootState');
  stateA = obj1.getState('stateA');
  stateB = obj1.getState('stateB');

  obj2 = SC.Object.extend(SC.StatechartManager, {

    statesAreConcurrent: YES,

    rootStateExample: TestState.design({
      testX: function(arg1, arg2) {
        this.set('testInvokedCount', this.get('testInvokedCount') + 1);
        this.set('arg1', arg1);
        this.set('arg2', arg2);
        if (this.get('returnValue') !== undefined) {
          return this.get('returnValue');
        } 
      }
    }),

    stateC: TestState.design(),

    stateD: TestState.design()

  });

  obj2 = obj2.create();
  rootState2 = obj2.get('rootState');
  stateC = obj2.getState('stateC');
  stateD = obj2.getState('stateD');
},

teardown: function() {
  TestState = obj1 = rootState1 = stateA = stateB = null;
  obj2 = rootState2 = stateC = stateD = null;
}

});

test(“check obj1 - invoke method test1”, function() {

var result = obj1.invokeStateMethod('test1');
ok(!rootState1.get('testInvoked'), "root state test method should not have been invoked");
ok(!stateA.get('testInvoked'), "state A's test method should not have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");

});

test(“check obj1 - invoke method test, current state A, no args, no return value”, function() {

var result = obj1.invokeStateMethod('test');
equals(stateA.get('testInvokedCount'), 1, "state A's test method should have been invoked once");
equals(stateA.get('arg1'), undefined, "state A's arg1 method should be undefined");
equals(stateA.get('arg2'), undefined, "state A's arg2 method should be undefined");
equals(result, undefined, "returned result should be undefined");
ok(!rootState1.get('testInvoked'), "root state's test method should not have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");

});

test(“check obj1 - invoke method test, current state A, one args, no return value”, function() {

var result = obj1.invokeStateMethod('test', "frozen");
ok(stateA.get('testInvoked'), "state A's test method should have been invoked");
equals(stateA.get('arg1'), "frozen", "state A's arg1 method should be 'frozen'");
equals(stateA.get('arg2'), undefined, "state A's arg2 method should be undefined");
ok(!rootState1.get('testInvoked'), "root state's test method should not have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");

});

test(“check obj1 - invoke method test, current state A, two args, no return value”, function() {

var result = obj1.invokeStateMethod('test', 'frozen', 'canuck');
ok(stateA.get('testInvoked'), "state A's test method should have been invoked");
equals(stateA.get('arg1'), "frozen", "state A's arg1 method should be 'frozen'");
equals(stateA.get('arg2'), "canuck", "state A's arg2 method should be undefined");
ok(!rootState1.get('testInvoked'), "root state's test method should not have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");

});

test(“check obj1 - invoke method test, current state A, no args, return value”, function() {

stateA.set('returnValue', 100);
var result = obj1.invokeStateMethod('test');
ok(stateA.get('testInvoked'), "state A's test method should have been invoked");
equals(result, 100, "returned result should be 100");
ok(!rootState1.get('testInvoked'), "root state's test method should not have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");

});

test(“check obj1 - invoke method test, current state B, two args, return value”, function() {

stateB.set('returnValue', 100);
obj1.gotoState(stateB);
ok(stateB.get('isCurrentState'), "state B should be curren state");
var result = obj1.invokeStateMethod('test', 'frozen', 'canuck');
ok(!stateA.get('testInvoked'), "state A's test method should not have been invoked");
equals(stateB.get('testInvokedCount'), 1, "state B's test method should have been invoked once");
equals(stateB.get('arg1'), 'frozen', "state B's arg1 method should be 'frozen'");
equals(stateB.get('arg2'), 'canuck', "state B's arg2 method should be 'canuck'");
equals(result, 100, "returned result should be 100");
ok(!rootState1.get('testInvoked'), "root state's test method should not have been invoked");

});

test(“check obj1 - invoke method test, current state A, use callback”, function() {

var callbackState, callbackResult;
obj1.invokeStateMethod('test', function(state, result) {
  callbackState = state;
  callbackResult = result;
});
ok(stateA.get('testInvoked'), "state A's test method should have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");
equals(callbackState, stateA, "state should be state A");
equals(callbackResult, undefined, "result should be undefined");
ok(!rootState1.get('testInvoked'), "root state's test method should not have been invoked");

});

test(“check obj1- invoke method test, current state B, use callback”, function() {

var callbackState, callbackResult;
obj1.gotoState(stateB);
stateB.set('returnValue', 100);
obj1.invokeStateMethod('test', function(state, result) {
  callbackState = state;
  callbackResult = result;
});
ok(!stateA.get('testInvoked'), "state A's test method should not have been invoked");
ok(stateB.get('testInvoked'), "state B's test method should have been invoked");
equals(callbackState, stateB, "state should be state B");
equals(callbackResult, 100, "result should be 100");
ok(!rootState1.get('testInvoked'), "root state's test method should not have been invoked");

});

test(“check obj1 - invoke method testX”, function() {

rootState1.set('returnValue', 100);
var result = obj1.invokeStateMethod('testX');
equals(rootState1.get('testInvokedCount'), 1, "root state's testX method should not have been invoked once");
equals(result, 100, "result should have value 100");
ok(!stateA.get('testInvoked'), "state A's test method should have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");

});

test(“check obj2 - invoke method test1”, function() {

var result = obj2.invokeStateMethod('test1');
ok(!rootState2.get('testInvoked'), "root state test method should not have been invoked");
ok(!stateC.get('testInvoked'), "state A's test method should not have been invoked");
ok(!stateD.get('testInvoked'), "state B's test method should not have been invoked");

});

test(“check obj2 - invoke test, no args, no return value”, function() {

var result = obj2.invokeStateMethod('test');
equals(stateC.get('testInvokedCount'), 1, "state C's test method should have been invoked once");
equals(stateD.get('testInvokedCount'), 1, "state D's test method should have been invoked once");
ok(!rootState1.get('testInvoked'), "root state test method should not have been invoked");
equals(stateC.get('arg1'), undefined, "state C's arg1 method should be undefined");
equals(stateC.get('arg2'), undefined, "state C's arg2 method should be undefined");
equals(stateD.get('arg1'), undefined, "state D's arg1 method should be undefined");
equals(stateD.get('arg2'), undefined, "state D's arg2 method should be undefined");
equals(result, undefined, "returned result should be undefined");

});

test(“check obj2 - invoke test, two args, return value, callback”, function() {

var numCallbacks = 0,
    callbackInfo = {};
stateC.set('returnValue', 100);
stateD.set('returnValue', 200);
var result = obj2.invokeStateMethod('test', 'frozen', 'canuck', function(state, result) {
  numCallbacks += 1;
  callbackInfo['state' + numCallbacks] = state;
  callbackInfo['result' + numCallbacks] = result;
});

ok(!rootState1.get('testInvoked'), "root state test method should not have been invoked");
equals(stateC.get('testInvokedCount'), 1, "state C's test method should have been invoked once");
equals(stateD.get('testInvokedCount'), 1, "state D's test method should have been invoked once");

equals(stateC.get('arg1'), 'frozen', "state C's arg1 method should be 'frozen'");
equals(stateC.get('arg2'), 'canuck', "state C's arg2 method should be 'canuck'");

equals(stateD.get('arg1'), 'frozen', "state D's arg1 method should be 'frozen'");
equals(stateD.get('arg2'), 'canuck', "state D's arg2 method should be 'canuck'");

equals(numCallbacks, 2, "callback should have been invoked twice");
equals(callbackInfo['state1'], stateC, "first callback state arg should be state C");
equals(callbackInfo['result1'], 100, "first callback result arg should be 100");
equals(callbackInfo['state2'], stateD, "second callback state arg should be state D");
equals(callbackInfo['result2'], 200, "second callback result arg should be 200");

equals(result, undefined, "returned result should be undefined");

});

test(“check obj2 - invoke method testX”, function() {

rootState2.set('returnValue', 100);
var result = obj2.invokeStateMethod('testX');
equals(rootState2.get('testInvokedCount'), 1, "root state's testX method should not have been invoked once");
equals(result, 100, "result should have value 100");
ok(!stateA.get('testInvoked'), "state A's test method should have been invoked");
ok(!stateB.get('testInvoked'), "state B's test method should not have been invoked");

});