stateful.rb 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +137 -0
  3. data/Gemfile +2 -0
  4. data/README.md +309 -0
  5. data/lib/Stateful/Sequel/ClassMethods.rb +117 -0
  6. data/lib/Stateful/Sequel.rb +30 -0
  7. data/lib/Stateful/VERSION.rb +1 -1
  8. data/lib/Stateful.rb +4 -1
  9. data/stateful.rb.gemspec +42 -0
  10. data/test/ActiveRecord/WithColumnName.rb +159 -0
  11. data/test/ActiveRecord/WithExplicitDeterministicEventOrdering.rb +159 -0
  12. data/test/ActiveRecord/WithExplicitGlobalNonDeterministicEventOrdering.rb +165 -0
  13. data/test/ActiveRecord/WithExplicitGlobalNonDeterministicEventOrderingAndInitialStateBlock.rb +163 -0
  14. data/test/ActiveRecord/WithExplicitNonDeterministicEventOrdering.rb +161 -0
  15. data/test/ActiveRecord/WithInitialStateBlock.rb +157 -0
  16. data/test/ActiveRecord/WithMultipleFinalStates.rb +188 -0
  17. data/test/ActiveRecord/WithMultipleStateMachines.rb +221 -0
  18. data/test/ActiveRecord/WithMultipleStateMachinesAndStatefulBlock.rb +223 -0
  19. data/test/ActiveRecord/WithPersistenceNonSpecificExtend.rb +159 -0
  20. data/test/ActiveRecord/WithPersistenceNonSpecificExtendAndStatefulBlock.rb +161 -0
  21. data/test/ActiveRecord/WithPersistenceSpecificExtend.rb +159 -0
  22. data/test/ActiveRecord/WithPersistenceSpecificExtendAndStatefulBlock.rb +161 -0
  23. data/test/ActiveRecord/test_helper.rb +9 -0
  24. data/test/ActiveRecord.rb +5 -0
  25. data/test/Poro/WithExplicitDeterministicEventOrdering.rb +147 -0
  26. data/test/Poro/WithExplicitGlobalNonDeterministicEventOrdering.rb +153 -0
  27. data/test/Poro/WithExplicitGlobalNonDeterministicEventOrderingAndInitialStateBlock.rb +151 -0
  28. data/test/Poro/WithExplicitNonDeterministicEventOrdering.rb +149 -0
  29. data/test/Poro/WithInitialStateBlock.rb +145 -0
  30. data/test/Poro/WithMultipleFinalStates.rb +176 -0
  31. data/test/Poro/WithMultipleStateMachines.rb +192 -0
  32. data/test/Poro/WithMultipleStateMachinesAndStatefulBlock.rb +194 -0
  33. data/test/Poro/WithPersistenceNonSpecificExtend.rb +147 -0
  34. data/test/Poro/WithPersistenceNonSpecificExtendAndStatefulBlock.rb +149 -0
  35. data/test/Poro/WithPersistenceSpecificExtend.rb +147 -0
  36. data/test/Poro/WithPersistenceSpecificExtendAndStatefulBlock.rb +149 -0
  37. data/test/Poro/WithVariableName.rb +147 -0
  38. data/test/Poro.rb +5 -0
  39. data/test/Sequel/WithColumnName.rb +154 -0
  40. data/test/Sequel/WithExplicitDeterministicEventOrdering.rb +154 -0
  41. data/test/Sequel/WithExplicitGlobalNonDeterministicEventOrdering.rb +160 -0
  42. data/test/Sequel/WithExplicitGlobalNonDeterministicEventOrderingAndInitialStateBlock.rb +158 -0
  43. data/test/Sequel/WithExplicitNonDeterministicEventOrdering.rb +156 -0
  44. data/test/Sequel/WithInitialStateBlock.rb +152 -0
  45. data/test/Sequel/WithMultipleFinalStates.rb +183 -0
  46. data/test/Sequel/WithMultipleStateMachines.rb +216 -0
  47. data/test/Sequel/WithMultipleStateMachinesAndStatefulBlock.rb +218 -0
  48. data/test/Sequel/WithPersistenceNonSpecificExtend.rb +154 -0
  49. data/test/Sequel/WithPersistenceNonSpecificExtendAndStatefulBlock.rb +156 -0
  50. data/test/Sequel/WithPersistenceSpecificExtend.rb +154 -0
  51. data/test/Sequel/WithPersistenceSpecificExtendAndStatefulBlock.rb +156 -0
  52. data/test/Sequel/test_helper.rb +5 -0
  53. data/test/Sequel.rb +5 -0
  54. data/test/Stateful.rb +15 -0
  55. metadata +69 -4
@@ -0,0 +1,176 @@
1
+ # test/Poro/WithMultipleFinalStates.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+
9
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
10
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
11
+
12
+ require 'Stateful'
13
+
14
+ class PoroMachine7
15
+ extend Stateful
16
+
17
+ initial_state :initial_state do
18
+ on :an_event => :next_state
19
+ on :another_event => :final_state0
20
+ end
21
+
22
+ state :next_state do
23
+ on :yet_another_event => :final_state1
24
+ end
25
+
26
+ final_state :final_state0, :final_state1
27
+ end
28
+
29
+ describe Stateful::Poro do
30
+ let(:machine){PoroMachine7.new}
31
+
32
+ it "must have an initial state" do
33
+ _(machine.initial_state).wont_be_nil
34
+ end
35
+
36
+ it "must have a final state (if one has been specified)" do
37
+ if PoroMachine7.final_state?
38
+ _(machine.final_state).wont_be_nil
39
+ end
40
+ end
41
+
42
+ context "initial_state" do
43
+ it "must have an initial state before any events occur" do
44
+ _(machine.initial_state?).must_equal true
45
+ end
46
+
47
+ it "must have an initial state consistent with what is given" do
48
+ _(machine.initial_state).must_equal PoroMachine7.stateful_state_machine.initial_state
49
+ end
50
+
51
+ it "must have an initial state with name as per the name given" do
52
+ _(machine.initial_state.name).must_equal :initial_state
53
+ end
54
+
55
+ it "must not be in the final state (assuming that initial and final are different states)" do
56
+ _(machine.final_state?).must_equal false
57
+ end
58
+
59
+ it "must know what it's next state is given an event name" do
60
+ _(machine.next_state(:an_event)).must_equal PoroMachine7.stateful_state_machine.find(:next_state)
61
+ _(machine.next_state(:another_event)).must_equal PoroMachine7.stateful_state_machine.find(:final_state0)
62
+ end
63
+
64
+ it "must have an intial state which has as set of transitions to other states" do
65
+ _(machine.transitions.class).must_equal Array
66
+ end
67
+
68
+ it "must have two transitions to other states" do
69
+ _(machine.transitions.size).must_equal 2
70
+ end
71
+
72
+ it "must know what transitions are available and in what order they are presented" do
73
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state0]]
74
+ end
75
+
76
+ it "must be active" do
77
+ _(machine.active?).must_equal true
78
+ end
79
+ end
80
+
81
+ context "next_state" do
82
+ before do
83
+ machine.an_event
84
+ end
85
+
86
+ it "must not be in the initial state" do
87
+ _(machine.initial_state?).must_equal false
88
+ end
89
+
90
+ it "must not be in a final state" do
91
+ _(machine.final_state?).must_equal false
92
+ end
93
+
94
+ it "must be in the next_state state" do
95
+ _(machine.current_state.name).must_equal :next_state
96
+ _(machine.next_state?).must_equal true
97
+ end
98
+
99
+ it "must have a set of transitions to other states" do
100
+ _(machine.transitions.class).must_equal Array
101
+ end
102
+
103
+ it "must have one transition to other states" do
104
+ _(machine.transitions.size).must_equal 1
105
+ end
106
+
107
+ it "must know what transitions are available" do
108
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:yet_another_event, :final_state1]]
109
+ end
110
+
111
+ it "must be active" do
112
+ _(machine.active?).must_equal true
113
+ end
114
+ end
115
+
116
+ context "final_state0" do
117
+ before do
118
+ machine.another_event
119
+ end
120
+
121
+ it "must have a final state" do
122
+ _(machine.final_state?).must_equal true
123
+ end
124
+
125
+ it "must have a final state consistent with what is given" do
126
+ _(PoroMachine7.stateful_state_machine.final_states).must_include machine.final_state
127
+ end
128
+
129
+ it "must have a state with name as per the name given" do
130
+ _(machine.current_state.name).must_equal :final_state0
131
+ end
132
+
133
+ it "must not be in the initial state (assuming that initial and final are different states)" do
134
+ _(machine.initial_state?).must_equal false
135
+ end
136
+
137
+ it "must have no transitions" do
138
+ _(machine.transitions.empty?).must_equal true
139
+ end
140
+
141
+ it "must not be active" do
142
+ _(machine.active?).must_equal false
143
+ end
144
+ end
145
+
146
+ context "final_state1" do
147
+ before do
148
+ machine.an_event
149
+ machine.yet_another_event
150
+ end
151
+
152
+ it "must have a final state" do
153
+ _(machine.final_state?).must_equal true
154
+ end
155
+
156
+ it "must have a final state consistent with what is given" do
157
+ _(PoroMachine7.stateful_state_machine.final_states).must_include machine.final_state
158
+ end
159
+
160
+ it "must have a state with name as per the name given" do
161
+ _(machine.current_state.name).must_equal :final_state1
162
+ end
163
+
164
+ it "must not be in the initial state (assuming that initial and final are different states)" do
165
+ _(machine.initial_state?).must_equal false
166
+ end
167
+
168
+ it "must have no transitions" do
169
+ _(machine.transitions.empty?).must_equal true
170
+ end
171
+
172
+ it "must not be active" do
173
+ _(machine.active?).must_equal false
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,192 @@
1
+ # test/Poro/WithMultipleStateMachines.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+
9
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
10
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
11
+
12
+ require 'Stateful'
13
+
14
+ class PoroMachine11
15
+ extend Stateful
16
+
17
+ state_machine :fulfilment do
18
+ initial_state :pending do
19
+ on :items_collected => :ready
20
+ end
21
+
22
+ state :ready do
23
+ on :dispatch => :dispatched
24
+ end
25
+
26
+ final_state :dispatched
27
+ end
28
+
29
+ state_machine :payment do
30
+ initial_state :unpaid do
31
+ on :pay => :paid
32
+ end
33
+
34
+ state :paid do
35
+ on :refund => :refunded
36
+ end
37
+
38
+ final_state :refunded
39
+ end
40
+ end
41
+
42
+ describe Stateful::Poro do
43
+ let(:machine){PoroMachine11.new}
44
+
45
+ context "initial states" do
46
+ it "must be in the fulfilment initial state" do
47
+ _(machine.fulfilment_initial_state?).must_equal true
48
+ end
49
+
50
+ it "must be in the payment initial state" do
51
+ _(machine.payment_initial_state?).must_equal true
52
+ end
53
+
54
+ it "must have the correct fulfilment state name" do
55
+ _(machine.fulfilment_state.name).must_equal :pending
56
+ end
57
+
58
+ it "must have the correct payment state name" do
59
+ _(machine.payment_state.name).must_equal :unpaid
60
+ end
61
+
62
+ it "must have fulfilment transitions" do
63
+ _(machine.fulfilment_transitions.size).must_equal 1
64
+ _(machine.fulfilment_transitions.first.event_name).must_equal :items_collected
65
+ end
66
+
67
+ it "must have payment transitions" do
68
+ _(machine.payment_transitions.size).must_equal 1
69
+ _(machine.payment_transitions.first.event_name).must_equal :pay
70
+ end
71
+
72
+ it "must not be in a fulfilment final state" do
73
+ _(machine.fulfilment_final_state?).must_equal false
74
+ end
75
+
76
+ it "must not be in a payment final state" do
77
+ _(machine.payment_final_state?).must_equal false
78
+ end
79
+
80
+ it "must have domain predicates" do
81
+ _(machine.pending?).must_equal true
82
+ _(machine.unpaid?).must_equal true
83
+ end
84
+ end
85
+
86
+ context "independent state transitions" do
87
+ before do
88
+ machine.pay
89
+ end
90
+
91
+ it "must still be in the fulfilment initial state" do
92
+ _(machine.fulfilment_initial_state?).must_equal true
93
+ _(machine.pending?).must_equal true
94
+ end
95
+
96
+ it "must have advanced the payment state" do
97
+ _(machine.payment_state.name).must_equal :paid
98
+ _(machine.paid?).must_equal true
99
+ end
100
+
101
+ it "must not be in the payment initial state" do
102
+ _(machine.payment_initial_state?).must_equal false
103
+ end
104
+ end
105
+
106
+ context "both machines advanced" do
107
+ before do
108
+ machine.items_collected
109
+ machine.pay
110
+ end
111
+
112
+ it "must be in the ready fulfilment state" do
113
+ _(machine.fulfilment_state.name).must_equal :ready
114
+ _(machine.ready?).must_equal true
115
+ end
116
+
117
+ it "must be in the paid payment state" do
118
+ _(machine.payment_state.name).must_equal :paid
119
+ _(machine.paid?).must_equal true
120
+ end
121
+
122
+ it "must have correct fulfilment transitions" do
123
+ _(machine.fulfilment_transitions.size).must_equal 1
124
+ _(machine.fulfilment_transitions.first.event_name).must_equal :dispatch
125
+ end
126
+
127
+ it "must have correct payment transitions" do
128
+ _(machine.payment_transitions.size).must_equal 1
129
+ _(machine.payment_transitions.first.event_name).must_equal :refund
130
+ end
131
+ end
132
+
133
+ context "fulfilment final state" do
134
+ before do
135
+ machine.items_collected
136
+ machine.dispatch
137
+ end
138
+
139
+ it "must be in the fulfilment final state" do
140
+ _(machine.fulfilment_final_state?).must_equal true
141
+ _(machine.dispatched?).must_equal true
142
+ end
143
+
144
+ it "must have no fulfilment transitions" do
145
+ _(machine.fulfilment_transitions.empty?).must_equal true
146
+ end
147
+ end
148
+
149
+ context "payment final state" do
150
+ before do
151
+ machine.pay
152
+ machine.refund
153
+ end
154
+
155
+ it "must be in the payment final state" do
156
+ _(machine.payment_final_state?).must_equal true
157
+ _(machine.refunded?).must_equal true
158
+ end
159
+
160
+ it "must have no payment transitions" do
161
+ _(machine.payment_transitions.empty?).must_equal true
162
+ end
163
+ end
164
+
165
+ context "active?" do
166
+ it "must be active when all machines are in initial states" do
167
+ _(machine.active?).must_equal true
168
+ end
169
+
170
+ it "must be active when one machine has reached final state" do
171
+ machine.items_collected
172
+ machine.dispatch
173
+ _(machine.fulfilment_final_state?).must_equal true
174
+ _(machine.active?).must_equal true
175
+ end
176
+
177
+ it "must not be active when all machines have reached final states" do
178
+ machine.items_collected
179
+ machine.dispatch
180
+ machine.pay
181
+ machine.refund
182
+ _(machine.active?).must_equal false
183
+ end
184
+
185
+ it "must be able to check a specific machine" do
186
+ machine.items_collected
187
+ machine.dispatch
188
+ _(machine.active?(:fulfilment)).must_equal false
189
+ _(machine.active?(:payment)).must_equal true
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,194 @@
1
+ # test/Poro/WithMultipleStateMachinesAndStatefulBlock.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+
9
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
10
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
11
+
12
+ require 'Stateful'
13
+
14
+ class PoroMachine12
15
+ extend Stateful
16
+
17
+ stateful do
18
+ state_machine :fulfilment do
19
+ initial_state :pending do
20
+ on :items_collected => :ready
21
+ end
22
+
23
+ state :ready do
24
+ on :dispatch => :dispatched
25
+ end
26
+
27
+ final_state :dispatched
28
+ end
29
+
30
+ state_machine :payment do
31
+ initial_state :unpaid do
32
+ on :pay => :paid
33
+ end
34
+
35
+ state :paid do
36
+ on :refund => :refunded
37
+ end
38
+
39
+ final_state :refunded
40
+ end
41
+ end
42
+ end
43
+
44
+ describe Stateful::Poro do
45
+ let(:machine){PoroMachine12.new}
46
+
47
+ context "initial states" do
48
+ it "must be in the fulfilment initial state" do
49
+ _(machine.fulfilment_initial_state?).must_equal true
50
+ end
51
+
52
+ it "must be in the payment initial state" do
53
+ _(machine.payment_initial_state?).must_equal true
54
+ end
55
+
56
+ it "must have the correct fulfilment state name" do
57
+ _(machine.fulfilment_state.name).must_equal :pending
58
+ end
59
+
60
+ it "must have the correct payment state name" do
61
+ _(machine.payment_state.name).must_equal :unpaid
62
+ end
63
+
64
+ it "must have fulfilment transitions" do
65
+ _(machine.fulfilment_transitions.size).must_equal 1
66
+ _(machine.fulfilment_transitions.first.event_name).must_equal :items_collected
67
+ end
68
+
69
+ it "must have payment transitions" do
70
+ _(machine.payment_transitions.size).must_equal 1
71
+ _(machine.payment_transitions.first.event_name).must_equal :pay
72
+ end
73
+
74
+ it "must not be in a fulfilment final state" do
75
+ _(machine.fulfilment_final_state?).must_equal false
76
+ end
77
+
78
+ it "must not be in a payment final state" do
79
+ _(machine.payment_final_state?).must_equal false
80
+ end
81
+
82
+ it "must have domain predicates" do
83
+ _(machine.pending?).must_equal true
84
+ _(machine.unpaid?).must_equal true
85
+ end
86
+ end
87
+
88
+ context "independent state transitions" do
89
+ before do
90
+ machine.pay
91
+ end
92
+
93
+ it "must still be in the fulfilment initial state" do
94
+ _(machine.fulfilment_initial_state?).must_equal true
95
+ _(machine.pending?).must_equal true
96
+ end
97
+
98
+ it "must have advanced the payment state" do
99
+ _(machine.payment_state.name).must_equal :paid
100
+ _(machine.paid?).must_equal true
101
+ end
102
+
103
+ it "must not be in the payment initial state" do
104
+ _(machine.payment_initial_state?).must_equal false
105
+ end
106
+ end
107
+
108
+ context "both machines advanced" do
109
+ before do
110
+ machine.items_collected
111
+ machine.pay
112
+ end
113
+
114
+ it "must be in the ready fulfilment state" do
115
+ _(machine.fulfilment_state.name).must_equal :ready
116
+ _(machine.ready?).must_equal true
117
+ end
118
+
119
+ it "must be in the paid payment state" do
120
+ _(machine.payment_state.name).must_equal :paid
121
+ _(machine.paid?).must_equal true
122
+ end
123
+
124
+ it "must have correct fulfilment transitions" do
125
+ _(machine.fulfilment_transitions.size).must_equal 1
126
+ _(machine.fulfilment_transitions.first.event_name).must_equal :dispatch
127
+ end
128
+
129
+ it "must have correct payment transitions" do
130
+ _(machine.payment_transitions.size).must_equal 1
131
+ _(machine.payment_transitions.first.event_name).must_equal :refund
132
+ end
133
+ end
134
+
135
+ context "fulfilment final state" do
136
+ before do
137
+ machine.items_collected
138
+ machine.dispatch
139
+ end
140
+
141
+ it "must be in the fulfilment final state" do
142
+ _(machine.fulfilment_final_state?).must_equal true
143
+ _(machine.dispatched?).must_equal true
144
+ end
145
+
146
+ it "must have no fulfilment transitions" do
147
+ _(machine.fulfilment_transitions.empty?).must_equal true
148
+ end
149
+ end
150
+
151
+ context "payment final state" do
152
+ before do
153
+ machine.pay
154
+ machine.refund
155
+ end
156
+
157
+ it "must be in the payment final state" do
158
+ _(machine.payment_final_state?).must_equal true
159
+ _(machine.refunded?).must_equal true
160
+ end
161
+
162
+ it "must have no payment transitions" do
163
+ _(machine.payment_transitions.empty?).must_equal true
164
+ end
165
+ end
166
+
167
+ context "active?" do
168
+ it "must be active when all machines are in initial states" do
169
+ _(machine.active?).must_equal true
170
+ end
171
+
172
+ it "must be active when one machine has reached final state" do
173
+ machine.items_collected
174
+ machine.dispatch
175
+ _(machine.fulfilment_final_state?).must_equal true
176
+ _(machine.active?).must_equal true
177
+ end
178
+
179
+ it "must not be active when all machines have reached final states" do
180
+ machine.items_collected
181
+ machine.dispatch
182
+ machine.pay
183
+ machine.refund
184
+ _(machine.active?).must_equal false
185
+ end
186
+
187
+ it "must be able to check a specific machine" do
188
+ machine.items_collected
189
+ machine.dispatch
190
+ _(machine.active?(:fulfilment)).must_equal false
191
+ _(machine.active?(:payment)).must_equal true
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,147 @@
1
+ # test/Poro/WithPersistenceNonSpecificExtend.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+
9
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
10
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
11
+
12
+ require 'Stateful'
13
+
14
+ class PoroMachine0
15
+ extend Stateful
16
+
17
+ initial_state :initial_state
18
+
19
+ state :initial_state do
20
+ on :an_event => :next_state
21
+ on :another_event => :final_state
22
+ end
23
+
24
+ state :next_state do
25
+ on :yet_another_event => :final_state
26
+ end
27
+
28
+ final_state :final_state
29
+ end
30
+
31
+ describe Stateful::Poro do
32
+ let(:machine){PoroMachine0.new}
33
+
34
+ it "must have an initial state" do
35
+ _(machine.initial_state).wont_be_nil
36
+ end
37
+
38
+ it "must have a final state (if one has been specified)" do
39
+ if PoroMachine0.final_state?
40
+ _(machine.final_state).wont_be_nil
41
+ end
42
+ end
43
+
44
+ context "initial_state" do
45
+ it "must have an initial state before any events occur" do
46
+ _(machine.initial_state?).must_equal true
47
+ end
48
+
49
+ it "must have an initial state consistent with what is given" do
50
+ _(machine.initial_state).must_equal PoroMachine0.stateful_state_machine.initial_state
51
+ end
52
+
53
+ it "must have an initial state with name as per the name given" do
54
+ _(machine.initial_state.name).must_equal :initial_state
55
+ end
56
+
57
+ it "must not be in the final state (assuming that initial and final are different states)" do
58
+ _(machine.final_state?).must_equal false
59
+ end
60
+
61
+ it "must know what it's next state is given an event name" do
62
+ _(machine.next_state(:an_event)).must_equal PoroMachine0.stateful_state_machine.find(:next_state)
63
+ _(machine.next_state(:another_event)).must_equal PoroMachine0.stateful_state_machine.find(:final_state)
64
+ end
65
+
66
+ it "must have an intial state which has as set of transitions to other states" do
67
+ _(machine.transitions.class).must_equal Array
68
+ end
69
+
70
+ it "must have two transitions to other states" do
71
+ _(machine.transitions.size).must_equal 2
72
+ end
73
+
74
+ it "must know what transitions are available" do
75
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state]]
76
+ end
77
+
78
+ it "must be active" do
79
+ _(machine.active?).must_equal true
80
+ end
81
+ end
82
+
83
+ context "next_state" do
84
+ before do
85
+ machine.an_event
86
+ end
87
+
88
+ it "must not be in the initial state" do
89
+ _(machine.initial_state?).must_equal false
90
+ end
91
+
92
+ it "must not be in the final state" do
93
+ _(machine.final_state?).must_equal false
94
+ end
95
+
96
+ it "must be in the next_state state" do
97
+ _(machine.current_state.name).must_equal :next_state
98
+ _(machine.next_state?).must_equal true
99
+ end
100
+
101
+ it "must have a set of transitions to other states" do
102
+ _(machine.transitions.class).must_equal Array
103
+ end
104
+
105
+ it "must have one transition to other states" do
106
+ _(machine.transitions.size).must_equal 1
107
+ end
108
+
109
+ it "must know what transitions are available" do
110
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:yet_another_event, :final_state]]
111
+ end
112
+
113
+ it "must be active" do
114
+ _(machine.active?).must_equal true
115
+ end
116
+ end
117
+
118
+ context "final_state" do
119
+ before do
120
+ machine.another_event
121
+ end
122
+
123
+ it "must have a final state" do
124
+ _(machine.final_state?).must_equal true
125
+ end
126
+
127
+ it "must have a final state consistent with what is given" do
128
+ _(machine.final_state).must_equal PoroMachine0.stateful_state_machine.final_state
129
+ end
130
+
131
+ it "must have a state with name as per the name given" do
132
+ _(machine.current_state.name).must_equal :final_state
133
+ end
134
+
135
+ it "must not be in the initial state (assuming that initial and final are different states)" do
136
+ _(machine.initial_state?).must_equal false
137
+ end
138
+
139
+ it "must have no transitions" do
140
+ _(machine.transitions.empty?).must_equal true
141
+ end
142
+
143
+ it "must not be active" do
144
+ _(machine.active?).must_equal false
145
+ end
146
+ end
147
+ end