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,161 @@
1
+ # test/ActiveRecord/WithPersistenceNonSpecificExtendAndStatefulBlock.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+
9
+ require_relative './test_helper'
10
+
11
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
12
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
13
+
14
+ require 'Stateful'
15
+
16
+ class CreateTableMachines < ActiveRecord::Migration[6.0]
17
+ def change
18
+ create_table :active_record_machine1s do |t|
19
+ t.string :current_state
20
+ end
21
+ end
22
+ end
23
+
24
+ class ActiveRecordMachine1 < ActiveRecord::Base
25
+ extend Stateful
26
+
27
+ stateful do
28
+ initial_state :initial_state
29
+
30
+ state :initial_state do
31
+ on :an_event => :next_state
32
+ on :another_event => :final_state
33
+ end
34
+
35
+ state :next_state do
36
+ on :yet_another_event => :final_state
37
+ end
38
+
39
+ final_state :final_state
40
+ end
41
+ end
42
+
43
+ CreateTableMachines.new.change
44
+
45
+ describe Stateful::ActiveRecord do
46
+ let(:machine){ActiveRecordMachine1.create}
47
+
48
+ it "must have an initial state" do
49
+ _(machine.initial_state).wont_be_nil
50
+ end
51
+
52
+ it "must have a final state (if one has been specified)" do
53
+ if ActiveRecordMachine1.final_state?
54
+ _(machine.final_state).wont_be_nil
55
+ end
56
+ end
57
+
58
+ context "initial_state" do
59
+ it "must have an initial state before any events occur" do
60
+ _(machine.initial_state?).must_equal true
61
+ end
62
+
63
+ it "must have an initial state consistent with what is given" do
64
+ _(machine.initial_state).must_equal ActiveRecordMachine1.stateful_state_machine.initial_state
65
+ end
66
+
67
+ it "must have an initial state with name as per the name given" do
68
+ _(machine.initial_state.name).must_equal :initial_state
69
+ end
70
+
71
+ it "must not be in the final state (assuming that initial and final are different states)" do
72
+ _(machine.final_state?).must_equal false
73
+ end
74
+
75
+ it "must know what it's next state is given an event name" do
76
+ _(machine.next_state(:an_event)).must_equal ActiveRecordMachine1.stateful_state_machine.find(:next_state)
77
+ _(machine.next_state(:another_event)).must_equal ActiveRecordMachine1.stateful_state_machine.find(:final_state)
78
+ end
79
+
80
+ it "must have an intial state which has as set of transitions to other states" do
81
+ _(machine.transitions.class).must_equal Array
82
+ end
83
+
84
+ it "must have two transitions to other states" do
85
+ _(machine.transitions.size).must_equal 2
86
+ end
87
+
88
+ it "must know what transitions are available" do
89
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state]]
90
+ end
91
+
92
+ it "must be active" do
93
+ _(machine.active?).must_equal true
94
+ end
95
+ end
96
+
97
+ context "next_state" do
98
+ before do
99
+ machine.an_event
100
+ end
101
+
102
+ it "must not be in the initial state" do
103
+ _(machine.initial_state?).must_equal false
104
+ end
105
+
106
+ it "must not be in the final state" do
107
+ _(machine.final_state?).must_equal false
108
+ end
109
+
110
+ it "must be in the next_state state" do
111
+ _(machine.current_state.name).must_equal :next_state
112
+ _(machine.next_state?).must_equal true
113
+ end
114
+
115
+ it "must have a set of transitions to other states" do
116
+ _(machine.transitions.class).must_equal Array
117
+ end
118
+
119
+ it "must have one transition to other states" do
120
+ _(machine.transitions.size).must_equal 1
121
+ end
122
+
123
+ it "must know what transitions are available" do
124
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:yet_another_event, :final_state]]
125
+ end
126
+
127
+ it "must be active" do
128
+ _(machine.active?).must_equal true
129
+ end
130
+ end
131
+
132
+ context "final_state" do
133
+ before do
134
+ machine.another_event
135
+ end
136
+
137
+ it "must have a final state" do
138
+ _(machine.final_state?).must_equal true
139
+ end
140
+
141
+ it "must have a final state consistent with what is given" do
142
+ _(machine.final_state).must_equal ActiveRecordMachine1.stateful_state_machine.final_state
143
+ end
144
+
145
+ it "must have a state with name as per the name given" do
146
+ _(machine.current_state.name).must_equal :final_state
147
+ end
148
+
149
+ it "must not be in the initial state (assuming that initial and final are different states)" do
150
+ _(machine.initial_state?).must_equal false
151
+ end
152
+
153
+ it "must have no transitions" do
154
+ _(machine.transitions.empty?).must_equal true
155
+ end
156
+
157
+ it "must not be active" do
158
+ _(machine.active?).must_equal false
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,159 @@
1
+ # test/ActiveRecord/WithPersistenceSpecificExtend.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+
9
+ require_relative './test_helper'
10
+
11
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
12
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
13
+
14
+ require 'Stateful/ActiveRecord'
15
+
16
+ class CreateTableMachines < ActiveRecord::Migration[6.0]
17
+ def change
18
+ create_table :active_record_machine2s do |t|
19
+ t.string :current_state
20
+ end
21
+ end
22
+ end
23
+
24
+ class ActiveRecordMachine2 < ActiveRecord::Base
25
+ extend Stateful::ActiveRecord
26
+
27
+ initial_state :initial_state
28
+
29
+ state :initial_state do
30
+ on :an_event => :next_state
31
+ on :another_event => :final_state
32
+ end
33
+
34
+ state :next_state do
35
+ on :yet_another_event => :final_state
36
+ end
37
+
38
+ final_state :final_state
39
+ end
40
+
41
+ CreateTableMachines.new.change
42
+
43
+ describe Stateful::ActiveRecord do
44
+ let(:machine){ActiveRecordMachine2.create}
45
+
46
+ it "must have an initial state" do
47
+ _(machine.initial_state).wont_be_nil
48
+ end
49
+
50
+ it "must have a final state (if one has been specified)" do
51
+ if ActiveRecordMachine2.final_state?
52
+ _(machine.final_state).wont_be_nil
53
+ end
54
+ end
55
+
56
+ context "initial_state" do
57
+ it "must have an initial state before any events occur" do
58
+ _(machine.initial_state?).must_equal true
59
+ end
60
+
61
+ it "must have an initial state consistent with what is given" do
62
+ _(machine.initial_state).must_equal ActiveRecordMachine2.stateful_state_machine.initial_state
63
+ end
64
+
65
+ it "must have an initial state with name as per the name given" do
66
+ _(machine.initial_state.name).must_equal :initial_state
67
+ end
68
+
69
+ it "must not be in the final state (assuming that initial and final are different states)" do
70
+ _(machine.final_state?).must_equal false
71
+ end
72
+
73
+ it "must know what it's next state is given an event name" do
74
+ _(machine.next_state(:an_event)).must_equal ActiveRecordMachine2.stateful_state_machine.find(:next_state)
75
+ _(machine.next_state(:another_event)).must_equal ActiveRecordMachine2.stateful_state_machine.find(:final_state)
76
+ end
77
+
78
+ it "must have an intial state which has as set of transitions to other states" do
79
+ _(machine.transitions.class).must_equal Array
80
+ end
81
+
82
+ it "must have two transitions to other states" do
83
+ _(machine.transitions.size).must_equal 2
84
+ end
85
+
86
+ it "must know what transitions are available" do
87
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state]]
88
+ end
89
+
90
+ it "must be active" do
91
+ _(machine.active?).must_equal true
92
+ end
93
+ end
94
+
95
+ context "next_state" do
96
+ before do
97
+ machine.an_event
98
+ end
99
+
100
+ it "must not be in the initial state" do
101
+ _(machine.initial_state?).must_equal false
102
+ end
103
+
104
+ it "must not be in the final state" do
105
+ _(machine.final_state?).must_equal false
106
+ end
107
+
108
+ it "must be in the next_state state" do
109
+ _(machine.current_state.name).must_equal :next_state
110
+ _(machine.next_state?).must_equal true
111
+ end
112
+
113
+ it "must have a set of transitions to other states" do
114
+ _(machine.transitions.class).must_equal Array
115
+ end
116
+
117
+ it "must have one transition to other states" do
118
+ _(machine.transitions.size).must_equal 1
119
+ end
120
+
121
+ it "must know what transitions are available" do
122
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:yet_another_event, :final_state]]
123
+ end
124
+
125
+ it "must be active" do
126
+ _(machine.active?).must_equal true
127
+ end
128
+ end
129
+
130
+ context "final_state" do
131
+ before do
132
+ machine.another_event
133
+ end
134
+
135
+ it "must have a final state" do
136
+ _(machine.final_state?).must_equal true
137
+ end
138
+
139
+ it "must have a final state consistent with what is given" do
140
+ _(machine.final_state).must_equal ActiveRecordMachine2.stateful_state_machine.final_state
141
+ end
142
+
143
+ it "must have a state with name as per the name given" do
144
+ _(machine.current_state.name).must_equal :final_state
145
+ end
146
+
147
+ it "must not be in the initial state (assuming that initial and final are different states)" do
148
+ _(machine.initial_state?).must_equal false
149
+ end
150
+
151
+ it "must have no transitions" do
152
+ _(machine.transitions.empty?).must_equal true
153
+ end
154
+
155
+ it "must not be active" do
156
+ _(machine.active?).must_equal false
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,161 @@
1
+ # test/ActiveRecord/WithPersistenceSpecificExtendAndStatefulBlock.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+
9
+ require_relative './test_helper'
10
+
11
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
12
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
13
+
14
+ require 'Stateful/ActiveRecord'
15
+
16
+ class CreateTableMachines < ActiveRecord::Migration[6.0]
17
+ def change
18
+ create_table :active_record_machine3s do |t|
19
+ t.string :current_state
20
+ end
21
+ end
22
+ end
23
+
24
+ class ActiveRecordMachine3 < ActiveRecord::Base
25
+ extend Stateful::ActiveRecord
26
+
27
+ stateful do
28
+ initial_state :initial_state
29
+
30
+ state :initial_state do
31
+ on :an_event => :next_state
32
+ on :another_event => :final_state
33
+ end
34
+
35
+ state :next_state do
36
+ on :yet_another_event => :final_state
37
+ end
38
+
39
+ final_state :final_state
40
+ end
41
+ end
42
+
43
+ CreateTableMachines.new.change
44
+
45
+ describe Stateful::ActiveRecord do
46
+ let(:machine){ActiveRecordMachine3.create}
47
+
48
+ it "must have an initial state" do
49
+ _(machine.initial_state).wont_be_nil
50
+ end
51
+
52
+ it "must have a final state (if one has been specified)" do
53
+ if ActiveRecordMachine3.final_state?
54
+ _(machine.final_state).wont_be_nil
55
+ end
56
+ end
57
+
58
+ context "initial_state" do
59
+ it "must have an initial state before any events occur" do
60
+ _(machine.initial_state?).must_equal true
61
+ end
62
+
63
+ it "must have an initial state consistent with what is given" do
64
+ _(machine.initial_state).must_equal ActiveRecordMachine3.stateful_state_machine.initial_state
65
+ end
66
+
67
+ it "must have an initial state with name as per the name given" do
68
+ _(machine.initial_state.name).must_equal :initial_state
69
+ end
70
+
71
+ it "must not be in the final state (assuming that initial and final are different states)" do
72
+ _(machine.final_state?).must_equal false
73
+ end
74
+
75
+ it "must know what it's next state is given an event name" do
76
+ _(machine.next_state(:an_event)).must_equal ActiveRecordMachine3.stateful_state_machine.find(:next_state)
77
+ _(machine.next_state(:another_event)).must_equal ActiveRecordMachine3.stateful_state_machine.find(:final_state)
78
+ end
79
+
80
+ it "must have an intial state which has as set of transitions to other states" do
81
+ _(machine.transitions.class).must_equal Array
82
+ end
83
+
84
+ it "must have two transitions to other states" do
85
+ _(machine.transitions.size).must_equal 2
86
+ end
87
+
88
+ it "must know what transitions are available" do
89
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state]]
90
+ end
91
+
92
+ it "must be active" do
93
+ _(machine.active?).must_equal true
94
+ end
95
+ end
96
+
97
+ context "next_state" do
98
+ before do
99
+ machine.an_event
100
+ end
101
+
102
+ it "must not be in the initial state" do
103
+ _(machine.initial_state?).must_equal false
104
+ end
105
+
106
+ it "must not be in the final state" do
107
+ _(machine.final_state?).must_equal false
108
+ end
109
+
110
+ it "must be in the next_state state" do
111
+ _(machine.current_state.name).must_equal :next_state
112
+ _(machine.next_state?).must_equal true
113
+ end
114
+
115
+ it "must have a set of transitions to other states" do
116
+ _(machine.transitions.class).must_equal Array
117
+ end
118
+
119
+ it "must have one transition to other states" do
120
+ _(machine.transitions.size).must_equal 1
121
+ end
122
+
123
+ it "must know what transitions are available" do
124
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:yet_another_event, :final_state]]
125
+ end
126
+
127
+ it "must be active" do
128
+ _(machine.active?).must_equal true
129
+ end
130
+ end
131
+
132
+ context "final_state" do
133
+ before do
134
+ machine.another_event
135
+ end
136
+
137
+ it "must have a final state" do
138
+ _(machine.final_state?).must_equal true
139
+ end
140
+
141
+ it "must have a final state consistent with what is given" do
142
+ _(machine.final_state).must_equal ActiveRecordMachine3.stateful_state_machine.final_state
143
+ end
144
+
145
+ it "must have a state with name as per the name given" do
146
+ _(machine.current_state.name).must_equal :final_state
147
+ end
148
+
149
+ it "must not be in the initial state (assuming that initial and final are different states)" do
150
+ _(machine.initial_state?).must_equal false
151
+ end
152
+
153
+ it "must have no transitions" do
154
+ _(machine.transitions.empty?).must_equal true
155
+ end
156
+
157
+ it "must not be active" do
158
+ _(machine.active?).must_equal false
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,9 @@
1
+ # test/ActiveRecord/test_helper.rb
2
+
3
+ require 'active_record'
4
+ require 'sqlite3'
5
+
6
+ ActiveRecord::Base.establish_connection(
7
+ adapter: 'sqlite3',
8
+ database: ':memory:'
9
+ )
@@ -0,0 +1,5 @@
1
+ # test/ActiveRecord.rb
2
+
3
+ test_dir = File.dirname(File.expand_path(__FILE__))
4
+ active_record_specs = Dir[File.join(test_dir, 'ActiveRecord', '**', '*.rb')]
5
+ active_record_specs.each{|spec| require spec}
@@ -0,0 +1,147 @@
1
+ # test/Poro/WithExplicitDeterministicEventOrdering.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 PoroMachine5
15
+ extend Stateful
16
+
17
+ initial_state :initial_state, deterministic: true do
18
+ on :an_event => :next_state
19
+ on :another_event => :final_state
20
+ end
21
+
22
+ state :next_state do
23
+ on :yet_another_event => :final_state
24
+ end
25
+
26
+ final_state :final_state
27
+ end
28
+
29
+ describe Stateful::Poro do
30
+ let(:machine){PoroMachine5.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 PoroMachine5.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 PoroMachine5.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 PoroMachine5.stateful_state_machine.find(:next_state)
61
+ _(machine.next_state(:another_event)).must_equal PoroMachine5.stateful_state_machine.find(:final_state)
62
+ end
63
+
64
+ it "must have an intial state which has a collection of transitions to other states" do
65
+ _(machine.transitions.class).must_equal Array
66
+ _(machine.transitions.all?{|transition| transition.is_a?(Stateful::Transition)}).must_equal true
67
+ end
68
+
69
+ it "must have two transitions to other states" do
70
+ _(machine.transitions.size).must_equal 2
71
+ end
72
+
73
+ it "must know what transitions are available and in what order they are presented" do
74
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state]]
75
+ end
76
+
77
+ it "must be active" do
78
+ _(machine.active?).must_equal true
79
+ end
80
+ end
81
+
82
+ context "next_state" do
83
+ before do
84
+ machine.an_event
85
+ end
86
+
87
+ it "must not be in the initial state" do
88
+ _(machine.initial_state?).must_equal false
89
+ end
90
+
91
+ it "must not be in the final state" do
92
+ _(machine.final_state?).must_equal false
93
+ end
94
+
95
+ it "must be in the next_state state" do
96
+ _(machine.current_state.name).must_equal :next_state
97
+ _(machine.next_state?).must_equal true
98
+ end
99
+
100
+ it "must have a collection of transitions to other states" do
101
+ _(machine.transitions.class).must_equal Array
102
+ _(machine.transitions.all?{|transition| transition.is_a?(Stateful::Transition)}).must_equal true
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 PoroMachine5.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