pluginaweek-state_machine 0.7.6
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.
- data/CHANGELOG.rdoc +273 -0
- data/LICENSE +20 -0
- data/README.rdoc +466 -0
- data/Rakefile +98 -0
- data/examples/AutoShop_state.png +0 -0
- data/examples/Car_state.png +0 -0
- data/examples/TrafficLight_state.png +0 -0
- data/examples/Vehicle_state.png +0 -0
- data/examples/auto_shop.rb +11 -0
- data/examples/car.rb +19 -0
- data/examples/merb-rest/controller.rb +51 -0
- data/examples/merb-rest/model.rb +28 -0
- data/examples/merb-rest/view_edit.html.erb +24 -0
- data/examples/merb-rest/view_index.html.erb +23 -0
- data/examples/merb-rest/view_new.html.erb +13 -0
- data/examples/merb-rest/view_show.html.erb +17 -0
- data/examples/rails-rest/controller.rb +43 -0
- data/examples/rails-rest/migration.rb +11 -0
- data/examples/rails-rest/model.rb +23 -0
- data/examples/rails-rest/view_edit.html.erb +25 -0
- data/examples/rails-rest/view_index.html.erb +23 -0
- data/examples/rails-rest/view_new.html.erb +14 -0
- data/examples/rails-rest/view_show.html.erb +17 -0
- data/examples/traffic_light.rb +7 -0
- data/examples/vehicle.rb +31 -0
- data/init.rb +1 -0
- data/lib/state_machine.rb +429 -0
- data/lib/state_machine/assertions.rb +36 -0
- data/lib/state_machine/callback.rb +189 -0
- data/lib/state_machine/condition_proxy.rb +94 -0
- data/lib/state_machine/eval_helpers.rb +67 -0
- data/lib/state_machine/event.rb +251 -0
- data/lib/state_machine/event_collection.rb +113 -0
- data/lib/state_machine/extensions.rb +158 -0
- data/lib/state_machine/guard.rb +219 -0
- data/lib/state_machine/integrations.rb +68 -0
- data/lib/state_machine/integrations/active_record.rb +444 -0
- data/lib/state_machine/integrations/active_record/locale.rb +10 -0
- data/lib/state_machine/integrations/active_record/observer.rb +41 -0
- data/lib/state_machine/integrations/data_mapper.rb +325 -0
- data/lib/state_machine/integrations/data_mapper/observer.rb +139 -0
- data/lib/state_machine/integrations/sequel.rb +292 -0
- data/lib/state_machine/machine.rb +1431 -0
- data/lib/state_machine/machine_collection.rb +146 -0
- data/lib/state_machine/matcher.rb +123 -0
- data/lib/state_machine/matcher_helpers.rb +54 -0
- data/lib/state_machine/node_collection.rb +152 -0
- data/lib/state_machine/state.rb +249 -0
- data/lib/state_machine/state_collection.rb +112 -0
- data/lib/state_machine/transition.rb +367 -0
- data/tasks/state_machine.rake +1 -0
- data/tasks/state_machine.rb +30 -0
- data/test/classes/switch.rb +11 -0
- data/test/functional/state_machine_test.rb +941 -0
- data/test/test_helper.rb +4 -0
- data/test/unit/assertions_test.rb +40 -0
- data/test/unit/callback_test.rb +455 -0
- data/test/unit/condition_proxy_test.rb +328 -0
- data/test/unit/eval_helpers_test.rb +129 -0
- data/test/unit/event_collection_test.rb +293 -0
- data/test/unit/event_test.rb +605 -0
- data/test/unit/guard_test.rb +862 -0
- data/test/unit/integrations/active_record_test.rb +1001 -0
- data/test/unit/integrations/data_mapper_test.rb +694 -0
- data/test/unit/integrations/sequel_test.rb +486 -0
- data/test/unit/integrations_test.rb +42 -0
- data/test/unit/invalid_event_test.rb +7 -0
- data/test/unit/invalid_transition_test.rb +7 -0
- data/test/unit/machine_collection_test.rb +710 -0
- data/test/unit/machine_test.rb +1910 -0
- data/test/unit/matcher_helpers_test.rb +37 -0
- data/test/unit/matcher_test.rb +155 -0
- data/test/unit/node_collection_test.rb +207 -0
- data/test/unit/state_collection_test.rb +280 -0
- data/test/unit/state_machine_test.rb +31 -0
- data/test/unit/state_test.rb +795 -0
- data/test/unit/transition_test.rb +1113 -0
- metadata +161 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class MatcherHelpersAllTest < Test::Unit::TestCase
|
4
|
+
include StateMachine::MatcherHelpers
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@matcher = all
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_should_build_an_all_matcher
|
11
|
+
assert_equal StateMachine::AllMatcher.instance, @matcher
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class MatcherHelpersAnyTest < Test::Unit::TestCase
|
16
|
+
include StateMachine::MatcherHelpers
|
17
|
+
|
18
|
+
def setup
|
19
|
+
@matcher = any
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_build_an_all_matcher
|
23
|
+
assert_equal StateMachine::AllMatcher.instance, @matcher
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class MatcherHelpersSameTest < Test::Unit::TestCase
|
28
|
+
include StateMachine::MatcherHelpers
|
29
|
+
|
30
|
+
def setup
|
31
|
+
@matcher = same
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_should_build_a_loopback_matcher
|
35
|
+
assert_equal StateMachine::LoopbackMatcher.instance, @matcher
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class MatcherByDefaultTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@matcher = StateMachine::Matcher.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_should_have_no_values
|
9
|
+
assert_equal [], @matcher.values
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_filter_all_values
|
13
|
+
assert_equal [], @matcher.filter([:parked, :idling])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class MatcherWithValueTest < Test::Unit::TestCase
|
18
|
+
def setup
|
19
|
+
@matcher = StateMachine::Matcher.new(nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_have_values
|
23
|
+
assert_equal [nil], @matcher.values
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_should_filter_unknown_values
|
27
|
+
assert_equal [nil], @matcher.filter([nil, :parked])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class MatcherWithMultipleValuesTest < Test::Unit::TestCase
|
32
|
+
def setup
|
33
|
+
@matcher = StateMachine::Matcher.new([:parked, :idling])
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_should_have_values
|
37
|
+
assert_equal [:parked, :idling], @matcher.values
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_should_filter_unknown_values
|
41
|
+
assert_equal [:parked], @matcher.filter([:parked, :first_gear])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class AllMatcherTest < Test::Unit::TestCase
|
46
|
+
def setup
|
47
|
+
@matcher = StateMachine::AllMatcher.instance
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_should_have_no_values
|
51
|
+
assert_equal [], @matcher.values
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_should_always_match
|
55
|
+
[nil, :parked, :idling].each {|value| assert @matcher.matches?(value)}
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_should_not_filter_any_values
|
59
|
+
assert_equal [:parked, :idling], @matcher.filter([:parked, :idling])
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_should_generate_blacklist_matcher_after_subtraction
|
63
|
+
matcher = @matcher - [:parked, :idling]
|
64
|
+
assert_instance_of StateMachine::BlacklistMatcher, matcher
|
65
|
+
assert_equal [:parked, :idling], matcher.values
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_should_have_a_description
|
69
|
+
assert_equal 'all', @matcher.description
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class WhitelistMatcherTest < Test::Unit::TestCase
|
74
|
+
def setup
|
75
|
+
@matcher = StateMachine::WhitelistMatcher.new([:parked, :idling])
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_should_have_values
|
79
|
+
assert_equal [:parked, :idling], @matcher.values
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_should_filter_unknown_values
|
83
|
+
assert_equal [:parked, :idling], @matcher.filter([:parked, :idling, :first_gear])
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_should_match_known_values
|
87
|
+
assert @matcher.matches?(:parked)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_should_not_match_unknown_values
|
91
|
+
assert !@matcher.matches?(:first_gear)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_should_have_a_description
|
95
|
+
assert_equal '[:parked, :idling]', @matcher.description
|
96
|
+
|
97
|
+
matcher = StateMachine::WhitelistMatcher.new([:parked])
|
98
|
+
assert_equal ':parked', matcher.description
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class BlacklistMatcherTest < Test::Unit::TestCase
|
103
|
+
def setup
|
104
|
+
@matcher = StateMachine::BlacklistMatcher.new([:parked, :idling])
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_should_have_values
|
108
|
+
assert_equal [:parked, :idling], @matcher.values
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_should_filter_known_values
|
112
|
+
assert_equal [:first_gear], @matcher.filter([:parked, :idling, :first_gear])
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_should_match_unknown_values
|
116
|
+
assert @matcher.matches?(:first_gear)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_should_not_match_known_values
|
120
|
+
assert !@matcher.matches?(:parked)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_should_have_a_description
|
124
|
+
assert_equal 'all - [:parked, :idling]', @matcher.description
|
125
|
+
|
126
|
+
matcher = StateMachine::BlacklistMatcher.new([:parked])
|
127
|
+
assert_equal 'all - :parked', matcher.description
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class LoopbackMatcherTest < Test::Unit::TestCase
|
132
|
+
def setup
|
133
|
+
@matcher = StateMachine::LoopbackMatcher.instance
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_should_have_no_values
|
137
|
+
assert_equal [], @matcher.values
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_should_filter_all_values
|
141
|
+
assert_equal [], @matcher.filter([:parked, :idling])
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_should_match_if_from_context_is_same
|
145
|
+
assert @matcher.matches?(:parked, :from => :parked)
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_should_not_match_if_from_context_is_different
|
149
|
+
assert !@matcher.matches?(:parked, :from => :idling)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_should_have_a_description
|
153
|
+
assert_equal 'same', @matcher.description
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class NodeCollectionByDefaultTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@machine = StateMachine::Machine.new(Class.new)
|
6
|
+
@collection = StateMachine::NodeCollection.new(@machine)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_not_have_any_nodes
|
10
|
+
assert_equal 0, @collection.length
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_have_a_machine
|
14
|
+
assert_equal @machine, @collection.machine
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_index_by_name
|
18
|
+
@collection << object = Struct.new(:name).new(:parked)
|
19
|
+
assert_equal object, @collection[:parked]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NodeCollectionTest < Test::Unit::TestCase
|
24
|
+
def setup
|
25
|
+
@machine = StateMachine::Machine.new(Class.new)
|
26
|
+
@collection = StateMachine::NodeCollection.new(@machine)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_raise_exception_if_invalid_option_specified
|
30
|
+
exception = assert_raise(ArgumentError) { StateMachine::NodeCollection.new(@machine, :invalid => true) }
|
31
|
+
assert_equal 'Invalid key(s): invalid', exception.message
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_should_raise_exception_on_lookup_if_invalid_index_specified
|
35
|
+
exception = assert_raise(ArgumentError) { @collection[:something, :invalid] }
|
36
|
+
assert_equal 'Invalid index: :invalid', exception.message
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_raise_exception_on_fetch_if_invalid_index_specified
|
40
|
+
exception = assert_raise(ArgumentError) { @collection.fetch(:something, :invalid) }
|
41
|
+
assert_equal 'Invalid index: :invalid', exception.message
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class NodeCollectionAfterBeingCopiedTest < Test::Unit::TestCase
|
46
|
+
def setup
|
47
|
+
machine = StateMachine::Machine.new(Class.new)
|
48
|
+
@collection = StateMachine::NodeCollection.new(machine)
|
49
|
+
@collection << @parked = Struct.new(:name).new(:parked)
|
50
|
+
|
51
|
+
@copied_collection = @collection.dup
|
52
|
+
@copied_collection << @idling = Struct.new(:name).new(:idling)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_should_not_modify_the_original_list
|
56
|
+
assert_equal 1, @collection.length
|
57
|
+
assert_equal 2, @copied_collection.length
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_not_modify_the_indices
|
61
|
+
assert_nil @collection[:idling]
|
62
|
+
assert_equal @idling, @copied_collection[:idling]
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_should_copy_each_node
|
66
|
+
assert_not_same @parked, @copied_collection[:parked]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class NodeCollectionWithoutIndicesTest < Test::Unit::TestCase
|
71
|
+
def setup
|
72
|
+
machine = StateMachine::Machine.new(Class.new)
|
73
|
+
@collection = StateMachine::NodeCollection.new(machine, :index => {})
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_should_allow_adding_node
|
77
|
+
@collection << Object.new
|
78
|
+
assert_equal 1, @collection.length
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_should_not_allow_keys_retrieval
|
82
|
+
exception = assert_raise(ArgumentError) { @collection.keys }
|
83
|
+
assert_equal 'No indices configured', exception.message
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_should_not_allow_lookup
|
87
|
+
@collection << object = Object.new
|
88
|
+
exception = assert_raise(ArgumentError) { @collection[0] }
|
89
|
+
assert_equal 'No indices configured', exception.message
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_should_not_allow_fetching
|
93
|
+
@collection << object = Object.new
|
94
|
+
exception = assert_raise(ArgumentError) { @collection.fetch(0) }
|
95
|
+
assert_equal 'No indices configured', exception.message
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class NodeCollectionWithIndicesTest < Test::Unit::TestCase
|
100
|
+
def setup
|
101
|
+
machine = StateMachine::Machine.new(Class.new)
|
102
|
+
@collection = StateMachine::NodeCollection.new(machine, :index => [:name, :value])
|
103
|
+
|
104
|
+
@object = Struct.new(:name, :value).new(:parked, 1)
|
105
|
+
@collection << @object
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_should_use_first_index_by_default_on_key_retrieval
|
109
|
+
assert_equal [:parked], @collection.keys
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_should_allow_customizing_index_for_key_retrieval
|
113
|
+
assert_equal [1], @collection.keys(:value)
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_should_use_first_index_by_default_on_lookup
|
117
|
+
assert_equal @object, @collection[:parked]
|
118
|
+
assert_nil @collection[1]
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_should_allow_customizing_index_on_lookup
|
122
|
+
assert_equal @object, @collection[1, :value]
|
123
|
+
assert_nil @collection[:parked, :value]
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_should_use_first_index_by_default_on_fetch
|
127
|
+
assert_equal @object, @collection.fetch(:parked)
|
128
|
+
exception = assert_raise(IndexError) { @collection.fetch(1) }
|
129
|
+
assert_equal '1 is an invalid name', exception.message
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_should_allow_customizing_index_on_fetch
|
133
|
+
assert_equal @object, @collection.fetch(1, :value)
|
134
|
+
exception = assert_raise(IndexError) { @collection.fetch(:parked, :value) }
|
135
|
+
assert_equal ':parked is an invalid value', exception.message
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class NodeCollectionWithNodesTest < Test::Unit::TestCase
|
140
|
+
def setup
|
141
|
+
machine = StateMachine::Machine.new(Class.new)
|
142
|
+
@collection = StateMachine::NodeCollection.new(machine)
|
143
|
+
|
144
|
+
@klass = Struct.new(:name, :machine)
|
145
|
+
@parked = @klass.new(:parked, machine)
|
146
|
+
@idling = @klass.new(:idling, machine)
|
147
|
+
|
148
|
+
@collection << @parked
|
149
|
+
@collection << @idling
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_should_be_able_to_enumerate
|
153
|
+
order = []
|
154
|
+
@collection.each {|object| order << object}
|
155
|
+
|
156
|
+
assert_equal [@parked, @idling], order
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_should_be_able_to_access_by_index
|
160
|
+
assert_equal @parked, @collection.at(0)
|
161
|
+
assert_equal @idling, @collection.at(1)
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_should_deep_copy_machine_changes
|
165
|
+
new_machine = StateMachine::Machine.new(Class.new)
|
166
|
+
@collection.machine = new_machine
|
167
|
+
|
168
|
+
assert_equal new_machine, @collection.machine
|
169
|
+
assert_equal new_machine, @parked.machine
|
170
|
+
assert_equal new_machine, @idling.machine
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class NodeCollectionAfterUpdateTest < Test::Unit::TestCase
|
175
|
+
def setup
|
176
|
+
machine = StateMachine::Machine.new(Class.new)
|
177
|
+
@collection = StateMachine::NodeCollection.new(machine, :index => [:name, :value])
|
178
|
+
|
179
|
+
@klass = Struct.new(:name, :value)
|
180
|
+
@parked = @klass.new(:parked, 1)
|
181
|
+
@idling = @klass.new(:idling, 2)
|
182
|
+
|
183
|
+
@collection << @parked << @idling
|
184
|
+
|
185
|
+
@parked.name = :parking
|
186
|
+
@parked.value = 0
|
187
|
+
@collection.update(@parked)
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_should_not_change_the_index
|
191
|
+
assert_equal @parked, @collection.at(0)
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_should_not_duplicate_in_the_collection
|
195
|
+
assert_equal 2, @collection.length
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_should_add_each_indexed_key
|
199
|
+
assert_equal @parked, @collection[:parking]
|
200
|
+
assert_equal @parked, @collection[0, :value]
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_should_remove_each_old_indexed_key
|
204
|
+
assert_nil @collection[:parked]
|
205
|
+
assert_nil @collection[1, :value]
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class StateCollectionByDefaultTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@machine = StateMachine::Machine.new(Class.new)
|
6
|
+
@states = StateMachine::StateCollection.new(@machine)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_not_have_any_nodes
|
10
|
+
assert_equal 0, @states.length
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_have_a_machine
|
14
|
+
assert_equal @machine, @states.machine
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_be_empty_by_priority
|
18
|
+
assert_equal [], @states.by_priority
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class StateCollectionTest < Test::Unit::TestCase
|
23
|
+
def setup
|
24
|
+
@klass = Class.new
|
25
|
+
@machine = StateMachine::Machine.new(@klass)
|
26
|
+
@states = StateMachine::StateCollection.new(@machine)
|
27
|
+
|
28
|
+
@states << @nil = StateMachine::State.new(@machine, nil)
|
29
|
+
@states << @parked = StateMachine::State.new(@machine, :parked)
|
30
|
+
@states << @idling = StateMachine::State.new(@machine, :idling)
|
31
|
+
|
32
|
+
@object = @klass.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_index_by_name
|
36
|
+
assert_equal @parked, @states[:parked, :name]
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_index_by_name_by_default
|
40
|
+
assert_equal @parked, @states[:parked]
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_index_by_value
|
44
|
+
assert_equal @parked, @states['parked', :value]
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_not_match_if_value_does_not_match
|
48
|
+
assert !@states.matches?(@object, :parked)
|
49
|
+
assert !@states.matches?(@object, :idling)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_should_match_if_value_matches
|
53
|
+
assert @states.matches?(@object, nil)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_raise_exception_if_matching_invalid_state
|
57
|
+
assert_raise(IndexError) { @states.matches?(@object, :invalid) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_find_state_for_object_if_value_is_known
|
61
|
+
@object.state = 'parked'
|
62
|
+
assert_equal @parked, @states.match(@object)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_should_find_bang_state_for_object_if_value_is_known
|
66
|
+
@object.state = 'parked'
|
67
|
+
assert_equal @parked, @states.match!(@object)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_should_not_find_state_for_object_with_unknown_value
|
71
|
+
@object.state = 'invalid'
|
72
|
+
assert_nil @states.match(@object)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_should_raise_exception_if_finding_bang_state_for_object_with_unknown_value
|
76
|
+
@object.state = 'invalid'
|
77
|
+
exception = assert_raise(ArgumentError) { @states.match!(@object) }
|
78
|
+
assert_equal '"invalid" is not a known state value', exception.message
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class StateCollectionWithCustomStateValuesTest < Test::Unit::TestCase
|
83
|
+
def setup
|
84
|
+
@klass = Class.new
|
85
|
+
@machine = StateMachine::Machine.new(@klass)
|
86
|
+
@states = StateMachine::StateCollection.new(@machine)
|
87
|
+
|
88
|
+
@states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
|
89
|
+
|
90
|
+
@object = @klass.new
|
91
|
+
@object.state = 1
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_should_match_if_value_matches
|
95
|
+
assert @states.matches?(@object, :parked)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_should_not_match_if_value_does_not_match
|
99
|
+
@object.state = 2
|
100
|
+
assert !@states.matches?(@object, :parked)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_should_find_state_for_object_if_value_is_known
|
104
|
+
assert_equal @state, @states.match(@object)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class StateCollectionWithStateMatchersTest < Test::Unit::TestCase
|
109
|
+
def setup
|
110
|
+
@klass = Class.new
|
111
|
+
@machine = StateMachine::Machine.new(@klass)
|
112
|
+
@states = StateMachine::StateCollection.new(@machine)
|
113
|
+
|
114
|
+
@states << @state = StateMachine::State.new(@machine, :parked, :if => lambda {|value| !value.nil?})
|
115
|
+
|
116
|
+
@object = @klass.new
|
117
|
+
@object.state = 1
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_should_match_if_value_matches
|
121
|
+
assert @states.matches?(@object, :parked)
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_should_not_match_if_value_does_not_match
|
125
|
+
@object.state = nil
|
126
|
+
assert !@states.matches?(@object, :parked)
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_should_find_state_for_object_if_value_is_known
|
130
|
+
assert_equal @state, @states.match(@object)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class StateCollectionWithInitialStateTest < Test::Unit::TestCase
|
135
|
+
def setup
|
136
|
+
@machine = StateMachine::Machine.new(Class.new)
|
137
|
+
@states = StateMachine::StateCollection.new(@machine)
|
138
|
+
|
139
|
+
@states << @parked = StateMachine::State.new(@machine, :parked)
|
140
|
+
@states << @idling = StateMachine::State.new(@machine, :idling)
|
141
|
+
|
142
|
+
@parked.initial = true
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_should_order_state_before_transition_states
|
146
|
+
@machine.event :ignite do
|
147
|
+
transition :to => :idling
|
148
|
+
end
|
149
|
+
assert_equal [@parked, @idling], @states.by_priority
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_should_order_state_before_states_with_behaviors
|
153
|
+
@idling.context do
|
154
|
+
def speed
|
155
|
+
0
|
156
|
+
end
|
157
|
+
end
|
158
|
+
assert_equal [@parked, @idling], @states.by_priority
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_should_order_state_before_other_states
|
162
|
+
assert_equal [@parked, @idling], @states.by_priority
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_should_order_state_before_callback_states
|
166
|
+
@machine.before_transition :from => :idling, :do => lambda {}
|
167
|
+
assert_equal [@parked, @idling], @states.by_priority
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class StateCollectionWithStateBehaviorsTest < Test::Unit::TestCase
|
172
|
+
def setup
|
173
|
+
@machine = StateMachine::Machine.new(Class.new)
|
174
|
+
@states = StateMachine::StateCollection.new(@machine)
|
175
|
+
|
176
|
+
@states << @parked = StateMachine::State.new(@machine, :parked)
|
177
|
+
@states << @idling = StateMachine::State.new(@machine, :idling)
|
178
|
+
|
179
|
+
@idling.context do
|
180
|
+
def speed
|
181
|
+
0
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_should_order_states_after_initial_state
|
187
|
+
@parked.initial = true
|
188
|
+
assert_equal [@parked, @idling], @states.by_priority
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_should_order_states_after_transition_states
|
192
|
+
@machine.event :ignite do
|
193
|
+
transition :from => :parked
|
194
|
+
end
|
195
|
+
assert_equal [@parked, @idling], @states.by_priority
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_should_order_states_before_other_states
|
199
|
+
assert_equal [@idling, @parked], @states.by_priority
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_should_order_state_before_callback_states
|
203
|
+
@machine.before_transition :from => :parked, :do => lambda {}
|
204
|
+
assert_equal [@idling, @parked], @states.by_priority
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
class StateCollectionWithEventTransitionsTest < Test::Unit::TestCase
|
209
|
+
def setup
|
210
|
+
@machine = StateMachine::Machine.new(Class.new)
|
211
|
+
@states = StateMachine::StateCollection.new(@machine)
|
212
|
+
|
213
|
+
@states << @parked = StateMachine::State.new(@machine, :parked)
|
214
|
+
@states << @idling = StateMachine::State.new(@machine, :idling)
|
215
|
+
|
216
|
+
@machine.event :ignite do
|
217
|
+
transition :to => :idling
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_should_order_states_after_initial_state
|
222
|
+
@parked.initial = true
|
223
|
+
assert_equal [@parked, @idling], @states.by_priority
|
224
|
+
end
|
225
|
+
|
226
|
+
def test_should_order_states_before_states_with_behaviors
|
227
|
+
@parked.context do
|
228
|
+
def speed
|
229
|
+
0
|
230
|
+
end
|
231
|
+
end
|
232
|
+
assert_equal [@idling, @parked], @states.by_priority
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_should_order_states_before_other_states
|
236
|
+
assert_equal [@idling, @parked], @states.by_priority
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_should_order_state_before_callback_states
|
240
|
+
@machine.before_transition :from => :parked, :do => lambda {}
|
241
|
+
assert_equal [@idling, @parked], @states.by_priority
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
class StateCollectionWithTransitionCallbacksTest < Test::Unit::TestCase
|
246
|
+
def setup
|
247
|
+
@machine = StateMachine::Machine.new(Class.new)
|
248
|
+
@states = StateMachine::StateCollection.new(@machine)
|
249
|
+
|
250
|
+
@states << @parked = StateMachine::State.new(@machine, :parked)
|
251
|
+
@states << @idling = StateMachine::State.new(@machine, :idling)
|
252
|
+
|
253
|
+
@machine.before_transition :to => :idling, :do => lambda {}
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_should_order_states_after_initial_state
|
257
|
+
@parked.initial = true
|
258
|
+
assert_equal [@parked, @idling], @states.by_priority
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_should_order_states_after_transition_states
|
262
|
+
@machine.event :ignite do
|
263
|
+
transition :from => :parked
|
264
|
+
end
|
265
|
+
assert_equal [@parked, @idling], @states.by_priority
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_should_order_states_after_states_with_behaviors
|
269
|
+
@parked.context do
|
270
|
+
def speed
|
271
|
+
0
|
272
|
+
end
|
273
|
+
end
|
274
|
+
assert_equal [@parked, @idling], @states.by_priority
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_should_order_states_after_other_states
|
278
|
+
assert_equal [@parked, @idling], @states.by_priority
|
279
|
+
end
|
280
|
+
end
|