1 // ==========================================================================
  2 // SC.Statechart Unit Test
  3 // ==========================================================================
  4 /*globals SC */
  5 
  6 var statechart = null;
  7 
  8 // ..........................................................
  9 // CONTENT CHANGING
 10 // 
 11 
 12 module("SC.Statechart: No Concurrent States - Goto State Asynchronous Tests", {
 13   setup: function() {
 14     
 15     var StateMixin = {
 16       
 17       counter: 0,
 18       
 19       foo: function() {
 20         this.set('counter', this.get('counter') + 1);
 21         this.resumeGotoState();
 22       },
 23       
 24       enterState: function() {
 25         return this.performAsync('foo');
 26       },
 27       
 28       exitState: function() {
 29         return this.performAsync(function() { this.foo(); });
 30       }
 31     };
 32   
 33     statechart = SC.Statechart.create({
 34       
 35       monitorIsActive: YES,
 36       
 37       rootState: SC.State.design({
 38         
 39         initialSubstate: 'a',
 40         
 41         a: SC.State.design(),
 42         
 43         b: SC.State.design({
 44           
 45           methodInvoked: null,
 46           
 47           enterState: function() {
 48             return this.performAsync('foo');
 49           },
 50           
 51           exitState: function() {
 52             return this.performAsync('bar');
 53           },
 54           
 55           foo: function(arg1, arg2) {
 56             this.set('methodInvoked', 'foo');
 57           },
 58 
 59           bar: function(arg1, arg2) {
 60             this.set('methodInvoked', 'bar');
 61           }
 62           
 63         }),
 64         
 65         c: SC.State.design(StateMixin, {
 66           
 67           initialSubstate: 'd',
 68           
 69           d: SC.State.design(StateMixin, {
 70             
 71             initialSubstate: 'e',
 72             
 73             e: SC.State.design(StateMixin)
 74             
 75           })
 76           
 77         })
 78         
 79       })
 80       
 81     });
 82     
 83     statechart.initStatechart();
 84   },
 85   
 86   teardown: function() {
 87     statechart.destroy();
 88   }
 89 });
 90 
 91 test("go to state b", function() {
 92   var stateB = statechart.getState('b'),
 93       monitor = statechart.get('monitor');
 94   
 95   monitor.reset();
 96   
 97   equals(statechart.get('gotoStateActive'), NO, "statechart should not have active gotoState");
 98   equals(statechart.get('gotoStateSuspended'), NO, "statechart should not have active gotoState suspended");
 99   
100   statechart.gotoState(stateB);
101   
102   equals(statechart.get('gotoStateActive'), YES, "statechart should have active gotoState");
103   equals(statechart.get('gotoStateSuspended'), YES, "statechart should have active gotoState suspended");
104   
105   statechart.resumeGotoState();
106   
107   equals(statechart.get('gotoStateActive'), NO, "statechart should not have active gotoState");
108   equals(statechart.get('gotoStateSuspended'), NO, "statechart should not have active gotoState suspended");
109   
110   equals(monitor.matchSequence().begin().exited('a').entered('b').end(), true, 'sequence should be exited[a], entered[b]');
111   equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
112   equals(statechart.stateIsCurrentState('a'), false, 'current state should not be a');
113   equals(statechart.stateIsCurrentState('b'), true, 'current state should be b');
114   equals(stateB.get('methodInvoked'), 'foo', "state b should have invoked method foo");
115 });
116 
117 test("go to state b and then back to state a", function() {
118   var stateA = statechart.getState('a'),
119       stateB = statechart.getState('b'),
120       monitor = statechart.get('monitor');
121   
122   statechart.gotoState(stateB);
123   statechart.resumeGotoState();
124   
125   monitor.reset();
126   
127   statechart.gotoState(stateA);
128   
129   equals(statechart.get('gotoStateActive'), YES, "statechart should have active gotoState");
130   equals(statechart.get('gotoStateSuspended'), YES, "statechart should have active gotoState suspended");
131   
132   statechart.resumeGotoState();
133   
134   equals(statechart.get('gotoStateActive'), NO, "statechart should not have active gotoState");
135   equals(statechart.get('gotoStateSuspended'), NO, "statechart should not have active gotoState suspended");
136   
137   equals(monitor.matchSequence().begin().exited('b').entered('a').end(), true, 'sequence should be exited[b], entered[a]');
138   equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
139   equals(statechart.stateIsCurrentState('a'), true, 'current state should be a');
140   equals(statechart.stateIsCurrentState('b'), false, 'current state should not be b');
141   equals(stateB.get('methodInvoked'), 'bar', "state b should have invoked method bar");
142 });
143 
144 test("go to state c", function() {
145   var stateC = statechart.getState('c'),
146       stateD = statechart.getState('d'),
147       stateE = statechart.getState('e'),
148       monitor = statechart.get('monitor');
149   
150   monitor.reset();
151   
152   statechart.gotoState(stateC);
153   
154   equals(statechart.get('gotoStateActive'), NO, "statechart should not have active gotoState");
155   equals(statechart.get('gotoStateSuspended'), NO, "statechart should not have active gotoState suspended");
156   
157   equals(monitor.matchSequence().begin().exited('a').entered('c', 'd', 'e').end(), true, 
158         'sequence should be exited[a], entered[c, d, e]');
159   equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
160   equals(statechart.stateIsCurrentState('a'), false, 'current state should not be a');
161   equals(statechart.stateIsCurrentState('e'), true, 'current state should be e');
162   equals(stateC.get('counter'), 1, 'state c counter should be 1');
163   equals(stateD.get('counter'), 1, 'state d counter should be 1');
164   equals(stateE.get('counter'), 1, 'state e counter should be 1');
165 });
166 
167 test("go to state c and then back to state a", function() {
168   var stateA = statechart.getState('a'),
169       stateC = statechart.getState('c'),
170       stateD = statechart.getState('d'),
171       stateE = statechart.getState('e'),
172       monitor = statechart.get('monitor');
173   
174   statechart.gotoState(stateC);
175   
176   monitor.reset();
177   
178   statechart.gotoState(stateA);
179   
180   equals(statechart.get('gotoStateActive'), NO, "statechart should not have active gotoState");
181   equals(statechart.get('gotoStateSuspended'), NO, "statechart should not have active gotoState suspended");
182   
183   equals(monitor.matchSequence().begin().exited('e', 'd', 'c').entered('a').end(), true, 
184         'sequence should be exited[e, d, c], entered[a]');
185   equals(statechart.get('currentStateCount'), 1, 'current state count should be 1');
186   equals(statechart.stateIsCurrentState('a'), true, 'current state should be a');
187   equals(statechart.stateIsCurrentState('e'), false, 'current state should not be e');
188   equals(stateC.get('counter'), 2, 'state c counter should be 2');
189   equals(stateD.get('counter'), 2, 'state d counter should be 2');
190   equals(stateE.get('counter'), 2, 'state e counter should be 2');
191 });