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,149 @@
1
+ # test/Poro/WithPersistenceNonSpecificExtendAndStatefulBlock.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 PoroMachine1
15
+ extend Stateful
16
+
17
+ stateful do
18
+ initial_state :initial_state
19
+
20
+ state :initial_state do
21
+ on :an_event => :next_state
22
+ on :another_event => :final_state
23
+ end
24
+
25
+ state :next_state do
26
+ on :yet_another_event => :final_state
27
+ end
28
+
29
+ final_state :final_state
30
+ end
31
+ end
32
+
33
+ describe Stateful::Poro do
34
+ let(:machine){PoroMachine1.new}
35
+
36
+ it "must have an initial state" do
37
+ _(machine.initial_state).wont_be_nil
38
+ end
39
+
40
+ it "must have a final state (if one has been specified)" do
41
+ if PoroMachine1.final_state?
42
+ _(machine.final_state).wont_be_nil
43
+ end
44
+ end
45
+
46
+ context "initial_state" do
47
+ it "must have an initial state before any events occur" do
48
+ _(machine.initial_state?).must_equal true
49
+ end
50
+
51
+ it "must have an initial state consistent with what is given" do
52
+ _(machine.initial_state).must_equal PoroMachine1.stateful_state_machine.initial_state
53
+ end
54
+
55
+ it "must have an initial state with name as per the name given" do
56
+ _(machine.initial_state.name).must_equal :initial_state
57
+ end
58
+
59
+ it "must not be in the final state (assuming that initial and final are different states)" do
60
+ _(machine.final_state?).must_equal false
61
+ end
62
+
63
+ it "must know what it's next state is given an event name" do
64
+ _(machine.next_state(:an_event)).must_equal PoroMachine1.stateful_state_machine.find(:next_state)
65
+ _(machine.next_state(:another_event)).must_equal PoroMachine1.stateful_state_machine.find(:final_state)
66
+ end
67
+
68
+ it "must have an intial state which has as set of transitions to other states" do
69
+ _(machine.transitions.class).must_equal Array
70
+ end
71
+
72
+ it "must have two transitions to other states" do
73
+ _(machine.transitions.size).must_equal 2
74
+ end
75
+
76
+ it "must know what transitions are available" do
77
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state]]
78
+ end
79
+
80
+ it "must be active" do
81
+ _(machine.active?).must_equal true
82
+ end
83
+ end
84
+
85
+ context "next_state" do
86
+ before do
87
+ machine.an_event
88
+ end
89
+
90
+ it "must not be in the initial state" do
91
+ _(machine.initial_state?).must_equal false
92
+ end
93
+
94
+ it "must not be in the final state" do
95
+ _(machine.final_state?).must_equal false
96
+ end
97
+
98
+ it "must be in the next_state state" do
99
+ _(machine.current_state.name).must_equal :next_state
100
+ _(machine.next_state?).must_equal true
101
+ end
102
+
103
+ it "must have a set of transitions to other states" do
104
+ _(machine.transitions.class).must_equal Array
105
+ end
106
+
107
+ it "must have one transition to other states" do
108
+ _(machine.transitions.size).must_equal 1
109
+ end
110
+
111
+ it "must know what transitions are available" do
112
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:yet_another_event, :final_state]]
113
+ end
114
+
115
+ it "must be active" do
116
+ _(machine.active?).must_equal true
117
+ end
118
+ end
119
+
120
+ context "final_state" do
121
+ before do
122
+ machine.another_event
123
+ end
124
+
125
+ it "must have a final state" do
126
+ _(machine.final_state?).must_equal true
127
+ end
128
+
129
+ it "must have a final state consistent with what is given" do
130
+ _(machine.final_state).must_equal PoroMachine1.stateful_state_machine.final_state
131
+ end
132
+
133
+ it "must have a state with name as per the name given" do
134
+ _(machine.current_state.name).must_equal :final_state
135
+ end
136
+
137
+ it "must not be in the initial state (assuming that initial and final are different states)" do
138
+ _(machine.initial_state?).must_equal false
139
+ end
140
+
141
+ it "must have no transitions" do
142
+ _(machine.transitions.empty?).must_equal true
143
+ end
144
+
145
+ it "must not be active" do
146
+ _(machine.active?).must_equal false
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,147 @@
1
+ # test/Poro/WithPersistenceSpecificExtend.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/Poro'
13
+
14
+ class PoroMachine2
15
+ extend Stateful::Poro
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){PoroMachine2.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 PoroMachine2.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 PoroMachine2.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 PoroMachine2.stateful_state_machine.find(:next_state)
63
+ _(machine.next_state(:another_event)).must_equal PoroMachine2.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 PoroMachine2.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
@@ -0,0 +1,149 @@
1
+ # test/Poro/WithPersistenceSpecificExtendAndStatefulBlock.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/Poro'
13
+
14
+ class PoroMachine3
15
+ extend Stateful::Poro
16
+
17
+ stateful do
18
+ initial_state :initial_state
19
+
20
+ state :initial_state do
21
+ on :an_event => :next_state
22
+ on :another_event => :final_state
23
+ end
24
+
25
+ state :next_state do
26
+ on :yet_another_event => :final_state
27
+ end
28
+
29
+ final_state :final_state
30
+ end
31
+ end
32
+
33
+ describe Stateful::Poro do
34
+ let(:machine){PoroMachine3.new}
35
+
36
+ it "must have an initial state" do
37
+ _(machine.initial_state).wont_be_nil
38
+ end
39
+
40
+ it "must have a final state (if one has been specified)" do
41
+ if PoroMachine3.final_state?
42
+ _(machine.final_state).wont_be_nil
43
+ end
44
+ end
45
+
46
+ context "initial_state" do
47
+ it "must have an initial state before any events occur" do
48
+ _(machine.initial_state?).must_equal true
49
+ end
50
+
51
+ it "must have an initial state consistent with what is given" do
52
+ _(machine.initial_state).must_equal PoroMachine3.stateful_state_machine.initial_state
53
+ end
54
+
55
+ it "must have an initial state with name as per the name given" do
56
+ _(machine.initial_state.name).must_equal :initial_state
57
+ end
58
+
59
+ it "must not be in the final state (assuming that initial and final are different states)" do
60
+ _(machine.final_state?).must_equal false
61
+ end
62
+
63
+ it "must know what it's next state is given an event name" do
64
+ _(machine.next_state(:an_event)).must_equal PoroMachine3.stateful_state_machine.find(:next_state)
65
+ _(machine.next_state(:another_event)).must_equal PoroMachine3.stateful_state_machine.find(:final_state)
66
+ end
67
+
68
+ it "must have an intial state which has as set of transitions to other states" do
69
+ _(machine.transitions.class).must_equal Array
70
+ end
71
+
72
+ it "must have two transitions to other states" do
73
+ _(machine.transitions.size).must_equal 2
74
+ end
75
+
76
+ it "must know what transitions are available" do
77
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:an_event, :next_state], [:another_event, :final_state]]
78
+ end
79
+
80
+ it "must be active" do
81
+ _(machine.active?).must_equal true
82
+ end
83
+ end
84
+
85
+ context "next_state" do
86
+ before do
87
+ machine.an_event
88
+ end
89
+
90
+ it "must not be in the initial state" do
91
+ _(machine.initial_state?).must_equal false
92
+ end
93
+
94
+ it "must not be in the final state" do
95
+ _(machine.final_state?).must_equal false
96
+ end
97
+
98
+ it "must be in the next_state state" do
99
+ _(machine.current_state.name).must_equal :next_state
100
+ _(machine.next_state?).must_equal true
101
+ end
102
+
103
+ it "must have a set of transitions to other states" do
104
+ _(machine.transitions.class).must_equal Array
105
+ end
106
+
107
+ it "must have one transition to other states" do
108
+ _(machine.transitions.size).must_equal 1
109
+ end
110
+
111
+ it "must know what transitions are available" do
112
+ _(machine.transitions.collect{|t| [t.event_name, t.next_state_name]}).must_equal [[:yet_another_event, :final_state]]
113
+ end
114
+
115
+ it "must be active" do
116
+ _(machine.active?).must_equal true
117
+ end
118
+ end
119
+
120
+ context "final_state" do
121
+ before do
122
+ machine.another_event
123
+ end
124
+
125
+ it "must have a final state" do
126
+ _(machine.final_state?).must_equal true
127
+ end
128
+
129
+ it "must have a final state consistent with what is given" do
130
+ _(machine.final_state).must_equal PoroMachine3.stateful_state_machine.final_state
131
+ end
132
+
133
+ it "must have a state with name as per the name given" do
134
+ _(machine.current_state.name).must_equal :final_state
135
+ end
136
+
137
+ it "must not be in the initial state (assuming that initial and final are different states)" do
138
+ _(machine.initial_state?).must_equal false
139
+ end
140
+
141
+ it "must have no transitions" do
142
+ _(machine.transitions.empty?).must_equal true
143
+ end
144
+
145
+ it "must not be active" do
146
+ _(machine.active?).must_equal false
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,147 @@
1
+ # test/Poro/WithVariableName.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 PoroMachine8
15
+ @stateful_variable_name = 'status'
16
+
17
+ extend Stateful
18
+
19
+ initial_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){PoroMachine8.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 PoroMachine8.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 PoroMachine8.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 PoroMachine8.stateful_state_machine.find(:next_state)
63
+ _(machine.next_state(:another_event)).must_equal PoroMachine8.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.status.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 PoroMachine8.stateful_state_machine.final_state
129
+ end
130
+
131
+ it "must have a state with name as per the name given" do
132
+ _(machine.status.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
data/test/Poro.rb ADDED
@@ -0,0 +1,5 @@
1
+ # test/Poro.rb
2
+
3
+ test_dir = File.dirname(File.expand_path(__FILE__))
4
+ active_record_specs = Dir[File.join(test_dir, 'Poro', '**', '*.rb')]
5
+ active_record_specs.each{|spec| require spec}