spree-state_machine 2.0.0.beta1
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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +12 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +502 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +1246 -0
- data/Rakefile +20 -0
- data/examples/AutoShop_state.png +0 -0
- data/examples/Car_state.png +0 -0
- data/examples/Gemfile +5 -0
- data/examples/Gemfile.lock +14 -0
- data/examples/TrafficLight_state.png +0 -0
- data/examples/Vehicle_state.png +0 -0
- data/examples/auto_shop.rb +13 -0
- data/examples/car.rb +21 -0
- data/examples/doc/AutoShop.html +2856 -0
- data/examples/doc/AutoShop_state.png +0 -0
- data/examples/doc/Car.html +919 -0
- data/examples/doc/Car_state.png +0 -0
- data/examples/doc/TrafficLight.html +2230 -0
- data/examples/doc/TrafficLight_state.png +0 -0
- data/examples/doc/Vehicle.html +7921 -0
- data/examples/doc/Vehicle_state.png +0 -0
- data/examples/doc/_index.html +136 -0
- data/examples/doc/class_list.html +47 -0
- data/examples/doc/css/common.css +1 -0
- data/examples/doc/css/full_list.css +55 -0
- data/examples/doc/css/style.css +322 -0
- data/examples/doc/file_list.html +46 -0
- data/examples/doc/frames.html +13 -0
- data/examples/doc/index.html +136 -0
- data/examples/doc/js/app.js +205 -0
- data/examples/doc/js/full_list.js +173 -0
- data/examples/doc/js/jquery.js +16 -0
- data/examples/doc/method_list.html +734 -0
- data/examples/doc/top-level-namespace.html +105 -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 +7 -0
- data/examples/rails-rest/model.rb +23 -0
- data/examples/rails-rest/view__form.html.erb +34 -0
- data/examples/rails-rest/view_edit.html.erb +6 -0
- data/examples/rails-rest/view_index.html.erb +25 -0
- data/examples/rails-rest/view_new.html.erb +5 -0
- data/examples/rails-rest/view_show.html.erb +19 -0
- data/examples/traffic_light.rb +9 -0
- data/examples/vehicle.rb +33 -0
- data/lib/state_machine/assertions.rb +36 -0
- data/lib/state_machine/branch.rb +225 -0
- data/lib/state_machine/callback.rb +236 -0
- data/lib/state_machine/core.rb +7 -0
- data/lib/state_machine/core_ext/class/state_machine.rb +5 -0
- data/lib/state_machine/core_ext.rb +2 -0
- data/lib/state_machine/error.rb +13 -0
- data/lib/state_machine/eval_helpers.rb +87 -0
- data/lib/state_machine/event.rb +257 -0
- data/lib/state_machine/event_collection.rb +141 -0
- data/lib/state_machine/extensions.rb +149 -0
- data/lib/state_machine/graph.rb +92 -0
- data/lib/state_machine/helper_module.rb +17 -0
- data/lib/state_machine/initializers/rails.rb +25 -0
- data/lib/state_machine/initializers.rb +4 -0
- data/lib/state_machine/integrations/active_model/locale.rb +11 -0
- data/lib/state_machine/integrations/active_model/observer.rb +33 -0
- data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
- data/lib/state_machine/integrations/active_model/versions.rb +31 -0
- data/lib/state_machine/integrations/active_model.rb +585 -0
- data/lib/state_machine/integrations/active_record/locale.rb +20 -0
- data/lib/state_machine/integrations/active_record/versions.rb +123 -0
- data/lib/state_machine/integrations/active_record.rb +525 -0
- data/lib/state_machine/integrations/base.rb +100 -0
- data/lib/state_machine/integrations.rb +121 -0
- data/lib/state_machine/machine.rb +2287 -0
- data/lib/state_machine/machine_collection.rb +74 -0
- data/lib/state_machine/macro_methods.rb +522 -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 +222 -0
- data/lib/state_machine/path.rb +120 -0
- data/lib/state_machine/path_collection.rb +90 -0
- data/lib/state_machine/state.rb +297 -0
- data/lib/state_machine/state_collection.rb +112 -0
- data/lib/state_machine/state_context.rb +138 -0
- data/lib/state_machine/transition.rb +470 -0
- data/lib/state_machine/transition_collection.rb +245 -0
- data/lib/state_machine/version.rb +3 -0
- data/lib/state_machine/yard/handlers/base.rb +32 -0
- data/lib/state_machine/yard/handlers/event.rb +25 -0
- data/lib/state_machine/yard/handlers/machine.rb +344 -0
- data/lib/state_machine/yard/handlers/state.rb +25 -0
- data/lib/state_machine/yard/handlers/transition.rb +47 -0
- data/lib/state_machine/yard/handlers.rb +12 -0
- data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
- data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
- data/lib/state_machine/yard/templates.rb +3 -0
- data/lib/state_machine/yard.rb +8 -0
- data/lib/state_machine.rb +8 -0
- data/lib/yard-state_machine.rb +2 -0
- data/state_machine.gemspec +22 -0
- data/test/files/en.yml +17 -0
- data/test/files/switch.rb +15 -0
- data/test/functional/state_machine_test.rb +1066 -0
- data/test/test_helper.rb +7 -0
- data/test/unit/assertions_test.rb +40 -0
- data/test/unit/branch_test.rb +969 -0
- data/test/unit/callback_test.rb +704 -0
- data/test/unit/error_test.rb +43 -0
- data/test/unit/eval_helpers_test.rb +270 -0
- data/test/unit/event_collection_test.rb +398 -0
- data/test/unit/event_test.rb +1196 -0
- data/test/unit/graph_test.rb +98 -0
- data/test/unit/helper_module_test.rb +17 -0
- data/test/unit/integrations/active_model_test.rb +1245 -0
- data/test/unit/integrations/active_record_test.rb +2551 -0
- data/test/unit/integrations/base_test.rb +104 -0
- data/test/unit/integrations_test.rb +71 -0
- data/test/unit/invalid_event_test.rb +20 -0
- data/test/unit/invalid_parallel_transition_test.rb +18 -0
- data/test/unit/invalid_transition_test.rb +115 -0
- data/test/unit/machine_collection_test.rb +603 -0
- data/test/unit/machine_test.rb +3395 -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 +362 -0
- data/test/unit/path_collection_test.rb +266 -0
- data/test/unit/path_test.rb +485 -0
- data/test/unit/state_collection_test.rb +352 -0
- data/test/unit/state_context_test.rb +441 -0
- data/test/unit/state_machine_test.rb +31 -0
- data/test/unit/state_test.rb +1101 -0
- data/test/unit/transition_collection_test.rb +2168 -0
- data/test/unit/transition_test.rb +1558 -0
- metadata +264 -0
@@ -0,0 +1,1101 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class StateByDefaultTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@machine = StateMachine::Machine.new(Class.new)
|
6
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_have_a_machine
|
10
|
+
assert_equal @machine, @state.machine
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_have_a_name
|
14
|
+
assert_equal :parked, @state.name
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_have_a_qualified_name
|
18
|
+
assert_equal :parked, @state.qualified_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_should_have_a_human_name
|
22
|
+
assert_equal 'parked', @state.human_name
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_should_use_stringify_the_name_as_the_value
|
26
|
+
assert_equal 'parked', @state.value
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_not_be_initial
|
30
|
+
assert !@state.initial
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_not_have_a_matcher
|
34
|
+
assert_nil @state.matcher
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_should_not_have_any_methods
|
38
|
+
expected = {}
|
39
|
+
assert_equal expected, @state.context_methods
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class StateTest < Test::Unit::TestCase
|
44
|
+
def setup
|
45
|
+
@machine = StateMachine::Machine.new(Class.new)
|
46
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_should_raise_exception_if_invalid_option_specified
|
50
|
+
exception = assert_raise(ArgumentError) {StateMachine::State.new(@machine, :parked, :invalid => true)}
|
51
|
+
assert_equal 'Invalid key(s): invalid', exception.message
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_should_allow_changing_machine
|
55
|
+
new_machine = StateMachine::Machine.new(Class.new)
|
56
|
+
@state.machine = new_machine
|
57
|
+
assert_equal new_machine, @state.machine
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_allow_changing_value
|
61
|
+
@state.value = 1
|
62
|
+
assert_equal 1, @state.value
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_should_allow_changing_initial
|
66
|
+
@state.initial = true
|
67
|
+
assert @state.initial
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_should_allow_changing_matcher
|
71
|
+
matcher = lambda {}
|
72
|
+
@state.matcher = matcher
|
73
|
+
assert_equal matcher, @state.matcher
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_should_allow_changing_human_name
|
77
|
+
@state.human_name = 'stopped'
|
78
|
+
assert_equal 'stopped', @state.human_name
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_should_use_pretty_inspect
|
82
|
+
assert_equal '#<StateMachine::State name=:parked value="parked" initial=false>', @state.inspect
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class StateWithoutNameTest < Test::Unit::TestCase
|
87
|
+
def setup
|
88
|
+
@klass = Class.new
|
89
|
+
@machine = StateMachine::Machine.new(@klass)
|
90
|
+
@machine.states << @state = StateMachine::State.new(@machine, nil)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_should_have_a_nil_name
|
94
|
+
assert_nil @state.name
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_should_have_a_nil_qualified_name
|
98
|
+
assert_nil @state.qualified_name
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_should_have_an_empty_human_name
|
102
|
+
assert_equal 'nil', @state.human_name
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_should_have_a_nil_value
|
106
|
+
assert_nil @state.value
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_should_not_redefine_nil_predicate
|
110
|
+
object = @klass.new
|
111
|
+
assert !object.nil?
|
112
|
+
assert !object.respond_to?('?')
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_should_have_a_description
|
116
|
+
assert_equal 'nil', @state.description
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_should_have_a_description_using_human_name
|
120
|
+
assert_equal 'nil', @state.description(:human_name => true)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class StateWithNameTest < Test::Unit::TestCase
|
125
|
+
def setup
|
126
|
+
@klass = Class.new
|
127
|
+
@machine = StateMachine::Machine.new(@klass)
|
128
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_should_have_a_name
|
132
|
+
assert_equal :parked, @state.name
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_should_have_a_qualified_name
|
136
|
+
assert_equal :parked, @state.name
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_should_have_a_human_name
|
140
|
+
assert_equal 'parked', @state.human_name
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_should_use_stringify_the_name_as_the_value
|
144
|
+
assert_equal 'parked', @state.value
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_should_match_stringified_name
|
148
|
+
assert @state.matches?('parked')
|
149
|
+
assert !@state.matches?('idling')
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_should_not_include_value_in_description
|
153
|
+
assert_equal 'parked', @state.description
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_should_allow_using_human_name_in_description
|
157
|
+
@state.human_name = 'Parked'
|
158
|
+
assert_equal 'Parked', @state.description(:human_name => true)
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_should_define_predicate
|
162
|
+
assert @klass.new.respond_to?(:parked?)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class StateWithNilValueTest < Test::Unit::TestCase
|
167
|
+
def setup
|
168
|
+
@klass = Class.new
|
169
|
+
@machine = StateMachine::Machine.new(@klass)
|
170
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => nil)
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_should_have_a_name
|
174
|
+
assert_equal :parked, @state.name
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_should_have_a_nil_value
|
178
|
+
assert_nil @state.value
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_should_match_nil_values
|
182
|
+
assert @state.matches?(nil)
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_should_have_a_description
|
186
|
+
assert_equal 'parked (nil)', @state.description
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_should_have_a_description_with_human_name
|
190
|
+
@state.human_name = 'Parked'
|
191
|
+
assert_equal 'Parked (nil)', @state.description(:human_name => true)
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_should_define_predicate
|
195
|
+
object = @klass.new
|
196
|
+
assert object.respond_to?(:parked?)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
class StateWithSymbolicValueTest < Test::Unit::TestCase
|
201
|
+
def setup
|
202
|
+
@klass = Class.new
|
203
|
+
@machine = StateMachine::Machine.new(@klass)
|
204
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => :parked)
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_should_use_custom_value
|
208
|
+
assert_equal :parked, @state.value
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_should_not_include_value_in_description
|
212
|
+
assert_equal 'parked', @state.description
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_should_allow_human_name_in_description
|
216
|
+
@state.human_name = 'Parked'
|
217
|
+
assert_equal 'Parked', @state.description(:human_name => true)
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_should_match_symbolic_value
|
221
|
+
assert @state.matches?(:parked)
|
222
|
+
assert !@state.matches?('parked')
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_should_define_predicate
|
226
|
+
object = @klass.new
|
227
|
+
assert object.respond_to?(:parked?)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
class StateWithIntegerValueTest < Test::Unit::TestCase
|
232
|
+
def setup
|
233
|
+
@klass = Class.new
|
234
|
+
@machine = StateMachine::Machine.new(@klass)
|
235
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_should_use_custom_value
|
239
|
+
assert_equal 1, @state.value
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_should_include_value_in_description
|
243
|
+
assert_equal 'parked (1)', @state.description
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_should_allow_human_name_in_description
|
247
|
+
@state.human_name = 'Parked'
|
248
|
+
assert_equal 'Parked (1)', @state.description(:human_name => true)
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_should_match_integer_value
|
252
|
+
assert @state.matches?(1)
|
253
|
+
assert !@state.matches?(2)
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_should_define_predicate
|
257
|
+
object = @klass.new
|
258
|
+
assert object.respond_to?(:parked?)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
class StateWithLambdaValueTest < Test::Unit::TestCase
|
263
|
+
def setup
|
264
|
+
@klass = Class.new
|
265
|
+
@args = nil
|
266
|
+
@machine = StateMachine::Machine.new(@klass)
|
267
|
+
@value = lambda {|*args| @args = args; :parked}
|
268
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @value)
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_should_use_evaluated_value_by_default
|
272
|
+
assert_equal :parked, @state.value
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_should_allow_access_to_original_value
|
276
|
+
assert_equal @value, @state.value(false)
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_should_include_masked_value_in_description
|
280
|
+
assert_equal 'parked (*)', @state.description
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_should_not_pass_in_any_arguments
|
284
|
+
@state.value
|
285
|
+
assert_equal [], @args
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_should_define_predicate
|
289
|
+
object = @klass.new
|
290
|
+
assert object.respond_to?(:parked?)
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_should_match_evaluated_value
|
294
|
+
assert @state.matches?(:parked)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
class StateWithCachedLambdaValueTest < Test::Unit::TestCase
|
299
|
+
def setup
|
300
|
+
@klass = Class.new
|
301
|
+
@machine = StateMachine::Machine.new(@klass)
|
302
|
+
@dynamic_value = lambda {'value'}
|
303
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value, :cache => true)
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_should_be_caching
|
307
|
+
assert @state.cache
|
308
|
+
end
|
309
|
+
|
310
|
+
def test_should_evaluate_value
|
311
|
+
assert_equal 'value', @state.value
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_should_only_evaluate_value_once
|
315
|
+
value = @state.value
|
316
|
+
assert_same value, @state.value
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_should_update_value_index_for_state_collection
|
320
|
+
@state.value
|
321
|
+
assert_equal @state, @machine.states['value', :value]
|
322
|
+
assert_nil @machine.states[@dynamic_value, :value]
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
class StateWithoutCachedLambdaValueTest < Test::Unit::TestCase
|
327
|
+
def setup
|
328
|
+
@klass = Class.new
|
329
|
+
@machine = StateMachine::Machine.new(@klass)
|
330
|
+
@dynamic_value = lambda {'value'}
|
331
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value)
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_should_not_be_caching
|
335
|
+
assert !@state.cache
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_should_evaluate_value_each_time
|
339
|
+
value = @state.value
|
340
|
+
assert_not_same value, @state.value
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_should_not_update_value_index_for_state_collection
|
344
|
+
@state.value
|
345
|
+
assert_nil @machine.states['value', :value]
|
346
|
+
assert_equal @state, @machine.states[@dynamic_value, :value]
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
class StateWithMatcherTest < Test::Unit::TestCase
|
351
|
+
def setup
|
352
|
+
@klass = Class.new
|
353
|
+
@args = nil
|
354
|
+
@machine = StateMachine::Machine.new(@klass)
|
355
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :if => lambda {|value| value == 1})
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_should_not_match_actual_value
|
359
|
+
assert !@state.matches?('parked')
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_should_match_evaluated_block
|
363
|
+
assert @state.matches?(1)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
class StateWithHumanNameTest < Test::Unit::TestCase
|
368
|
+
def setup
|
369
|
+
@klass = Class.new
|
370
|
+
@machine = StateMachine::Machine.new(@klass)
|
371
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => 'stopped')
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_should_use_custom_human_name
|
375
|
+
assert_equal 'stopped', @state.human_name
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
class StateWithDynamicHumanNameTest < Test::Unit::TestCase
|
380
|
+
def setup
|
381
|
+
@klass = Class.new
|
382
|
+
@machine = StateMachine::Machine.new(@klass)
|
383
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => lambda {|state, object| ['stopped', object]})
|
384
|
+
end
|
385
|
+
|
386
|
+
def test_should_use_custom_human_name
|
387
|
+
human_name, klass = @state.human_name
|
388
|
+
assert_equal 'stopped', human_name
|
389
|
+
assert_equal @klass, klass
|
390
|
+
end
|
391
|
+
|
392
|
+
def test_should_allow_custom_class_to_be_passed_through
|
393
|
+
human_name, klass = @state.human_name(1)
|
394
|
+
assert_equal 'stopped', human_name
|
395
|
+
assert_equal 1, klass
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_should_not_cache_value
|
399
|
+
assert_not_same @state.human_name, @state.human_name
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
class StateInitialTest < Test::Unit::TestCase
|
404
|
+
def setup
|
405
|
+
@machine = StateMachine::Machine.new(Class.new)
|
406
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => true)
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_should_be_initial
|
410
|
+
assert @state.initial
|
411
|
+
assert @state.initial?
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
class StateNotInitialTest < Test::Unit::TestCase
|
416
|
+
def setup
|
417
|
+
@machine = StateMachine::Machine.new(Class.new)
|
418
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => false)
|
419
|
+
end
|
420
|
+
|
421
|
+
def test_should_not_be_initial
|
422
|
+
assert !@state.initial
|
423
|
+
assert !@state.initial?
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
class StateFinalTest < Test::Unit::TestCase
|
428
|
+
def setup
|
429
|
+
@machine = StateMachine::Machine.new(Class.new)
|
430
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
431
|
+
end
|
432
|
+
|
433
|
+
def test_should_be_final_without_input_transitions
|
434
|
+
assert @state.final?
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_should_be_final_with_input_transitions
|
438
|
+
@machine.event :park do
|
439
|
+
transition :idling => :parked
|
440
|
+
end
|
441
|
+
|
442
|
+
assert @state.final?
|
443
|
+
end
|
444
|
+
|
445
|
+
def test_should_be_final_with_loopback
|
446
|
+
@machine.event :ignite do
|
447
|
+
transition :parked => same
|
448
|
+
end
|
449
|
+
|
450
|
+
assert @state.final?
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
class StateNotFinalTest < Test::Unit::TestCase
|
455
|
+
def setup
|
456
|
+
@machine = StateMachine::Machine.new(Class.new)
|
457
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
458
|
+
end
|
459
|
+
|
460
|
+
def test_should_not_be_final_with_outgoing_whitelist_transitions
|
461
|
+
@machine.event :ignite do
|
462
|
+
transition :parked => :idling
|
463
|
+
end
|
464
|
+
|
465
|
+
assert !@state.final?
|
466
|
+
end
|
467
|
+
|
468
|
+
def test_should_not_be_final_with_outgoing_all_transitions
|
469
|
+
@machine.event :ignite do
|
470
|
+
transition all => :idling
|
471
|
+
end
|
472
|
+
|
473
|
+
assert !@state.final?
|
474
|
+
end
|
475
|
+
|
476
|
+
def test_should_not_be_final_with_outgoing_blacklist_transitions
|
477
|
+
@machine.event :ignite do
|
478
|
+
transition all - :first_gear => :idling
|
479
|
+
end
|
480
|
+
|
481
|
+
assert !@state.final?
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
class StateWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
|
486
|
+
def setup
|
487
|
+
require 'stringio'
|
488
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
489
|
+
|
490
|
+
@superclass = Class.new do
|
491
|
+
def parked?
|
492
|
+
0
|
493
|
+
end
|
494
|
+
end
|
495
|
+
@klass = Class.new(@superclass)
|
496
|
+
@machine = StateMachine::Machine.new(@klass)
|
497
|
+
@machine.state :parked
|
498
|
+
@object = @klass.new
|
499
|
+
end
|
500
|
+
|
501
|
+
def test_should_not_override_state_predicate
|
502
|
+
assert_equal 0, @object.parked?
|
503
|
+
end
|
504
|
+
|
505
|
+
def test_should_output_warning
|
506
|
+
assert_equal "Instance method \"parked?\" is already defined in #{@superclass.to_s}, use generic helper instead or set StateMachine::Machine.ignore_method_conflicts = true.\n", $stderr.string
|
507
|
+
end
|
508
|
+
|
509
|
+
def teardown
|
510
|
+
$stderr = @original_stderr
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
class StateWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
|
515
|
+
def setup
|
516
|
+
require 'stringio'
|
517
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
518
|
+
|
519
|
+
@klass = Class.new do
|
520
|
+
def parked?
|
521
|
+
0
|
522
|
+
end
|
523
|
+
end
|
524
|
+
@machine = StateMachine::Machine.new(@klass)
|
525
|
+
@machine.state :parked
|
526
|
+
@object = @klass.new
|
527
|
+
end
|
528
|
+
|
529
|
+
def test_should_not_override_state_predicate
|
530
|
+
assert_equal 0, @object.parked?
|
531
|
+
end
|
532
|
+
|
533
|
+
def test_should_still_allow_super_chaining
|
534
|
+
@klass.class_eval do
|
535
|
+
def parked?
|
536
|
+
super
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
assert_equal false, @object.parked?
|
541
|
+
end
|
542
|
+
|
543
|
+
def test_should_not_output_warning
|
544
|
+
assert_equal '', $stderr.string
|
545
|
+
end
|
546
|
+
|
547
|
+
def teardown
|
548
|
+
$stderr = @original_stderr
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
class StateWithConflictingMachineTest < Test::Unit::TestCase
|
553
|
+
def setup
|
554
|
+
require 'stringio'
|
555
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
556
|
+
|
557
|
+
@klass = Class.new
|
558
|
+
@state_machine = StateMachine::Machine.new(@klass, :state)
|
559
|
+
@state_machine.states << @state = StateMachine::State.new(@state_machine, :parked)
|
560
|
+
end
|
561
|
+
|
562
|
+
def test_should_output_warning_if_using_different_attribute
|
563
|
+
@status_machine = StateMachine::Machine.new(@klass, :status)
|
564
|
+
@status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
|
565
|
+
|
566
|
+
assert_equal "State :parked for :status is already defined in :state\n", $stderr.string
|
567
|
+
end
|
568
|
+
|
569
|
+
def test_should_not_output_warning_if_using_same_attribute
|
570
|
+
@status_machine = StateMachine::Machine.new(@klass, :status, :attribute => :state)
|
571
|
+
@status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
|
572
|
+
|
573
|
+
assert_equal '', $stderr.string
|
574
|
+
end
|
575
|
+
|
576
|
+
def test_should_not_output_warning_if_using_different_namespace
|
577
|
+
@status_machine = StateMachine::Machine.new(@klass, :status, :namespace => 'alarm')
|
578
|
+
@status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
|
579
|
+
|
580
|
+
assert_equal '', $stderr.string
|
581
|
+
end
|
582
|
+
|
583
|
+
def teardown
|
584
|
+
$stderr = @original_stderr
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
class StateWithConflictingMachineNameTest < Test::Unit::TestCase
|
589
|
+
def setup
|
590
|
+
require 'stringio'
|
591
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
592
|
+
|
593
|
+
@klass = Class.new
|
594
|
+
@state_machine = StateMachine::Machine.new(@klass, :state)
|
595
|
+
end
|
596
|
+
|
597
|
+
def test_should_output_warning_if_name_conflicts
|
598
|
+
StateMachine::State.new(@state_machine, :state)
|
599
|
+
assert_equal "Instance method \"state?\" is already defined in #{@klass} :state instance helpers, use generic helper instead or set StateMachine::Machine.ignore_method_conflicts = true.\n", $stderr.string
|
600
|
+
end
|
601
|
+
|
602
|
+
def teardown
|
603
|
+
$stderr = @original_stderr
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
class StateWithNamespaceTest < Test::Unit::TestCase
|
608
|
+
def setup
|
609
|
+
@klass = Class.new
|
610
|
+
@machine = StateMachine::Machine.new(@klass, :namespace => 'alarm')
|
611
|
+
@machine.states << @state = StateMachine::State.new(@machine, :active)
|
612
|
+
@object = @klass.new
|
613
|
+
end
|
614
|
+
|
615
|
+
def test_should_have_a_name
|
616
|
+
assert_equal :active, @state.name
|
617
|
+
end
|
618
|
+
|
619
|
+
def test_should_have_a_qualified_name
|
620
|
+
assert_equal :alarm_active, @state.qualified_name
|
621
|
+
end
|
622
|
+
|
623
|
+
def test_should_namespace_predicate
|
624
|
+
assert @object.respond_to?(:alarm_active?)
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
class StateAfterBeingCopiedTest < Test::Unit::TestCase
|
629
|
+
def setup
|
630
|
+
@machine = StateMachine::Machine.new(Class.new)
|
631
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
632
|
+
@copied_state = @state.dup
|
633
|
+
end
|
634
|
+
|
635
|
+
def test_should_not_have_the_context
|
636
|
+
state_context = nil
|
637
|
+
@state.context { state_context = self }
|
638
|
+
|
639
|
+
copied_state_context = nil
|
640
|
+
@copied_state.context { copied_state_context = self }
|
641
|
+
|
642
|
+
assert_not_same state_context, copied_state_context
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
class StateWithContextTest < Test::Unit::TestCase
|
647
|
+
def setup
|
648
|
+
@klass = Class.new
|
649
|
+
@machine = StateMachine::Machine.new(@klass)
|
650
|
+
@ancestors = @klass.ancestors
|
651
|
+
@machine.states << @state = StateMachine::State.new(@machine, :idling)
|
652
|
+
|
653
|
+
context = nil
|
654
|
+
speed_method = nil
|
655
|
+
rpm_method = nil
|
656
|
+
@result = @state.context do
|
657
|
+
context = self
|
658
|
+
|
659
|
+
def speed
|
660
|
+
0
|
661
|
+
end
|
662
|
+
speed_method = instance_method(:speed)
|
663
|
+
|
664
|
+
def rpm
|
665
|
+
1000
|
666
|
+
end
|
667
|
+
rpm_method = instance_method(:rpm)
|
668
|
+
end
|
669
|
+
|
670
|
+
@context = context
|
671
|
+
@speed_method = speed_method
|
672
|
+
@rpm_method = rpm_method
|
673
|
+
end
|
674
|
+
|
675
|
+
def test_should_return_true
|
676
|
+
assert_equal true, @result
|
677
|
+
end
|
678
|
+
|
679
|
+
def test_should_include_new_module_in_owner_class
|
680
|
+
assert_not_equal @ancestors, @klass.ancestors
|
681
|
+
assert_equal [@context], @klass.ancestors - @ancestors
|
682
|
+
end
|
683
|
+
|
684
|
+
def test_should_define_each_context_method_in_owner_class
|
685
|
+
%w(speed rpm).each {|method| assert @klass.method_defined?(method)}
|
686
|
+
end
|
687
|
+
|
688
|
+
def test_should_define_aliased_context_method_in_owner_class
|
689
|
+
%w(speed rpm).each {|method| assert @klass.method_defined?("__state_idling_#{method}_#{@context.object_id}__")}
|
690
|
+
end
|
691
|
+
|
692
|
+
def test_should_not_use_context_methods_as_owner_class_methods
|
693
|
+
assert_not_equal @speed_method, @state.context_methods[:speed]
|
694
|
+
assert_not_equal @rpm_method, @state.context_methods[:rpm]
|
695
|
+
end
|
696
|
+
|
697
|
+
def test_should_use_context_methods_as_aliased_owner_class_methods
|
698
|
+
assert_equal @speed_method, @state.context_methods[:"__state_idling_speed_#{@context.object_id}__"]
|
699
|
+
assert_equal @rpm_method, @state.context_methods[:"__state_idling_rpm_#{@context.object_id}__"]
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
class StateWithMultipleContextsTest < Test::Unit::TestCase
|
704
|
+
def setup
|
705
|
+
@klass = Class.new
|
706
|
+
@machine = StateMachine::Machine.new(@klass)
|
707
|
+
@ancestors = @klass.ancestors
|
708
|
+
@machine.states << @state = StateMachine::State.new(@machine, :idling)
|
709
|
+
|
710
|
+
context = nil
|
711
|
+
speed_method = nil
|
712
|
+
@state.context do
|
713
|
+
context = self
|
714
|
+
def speed
|
715
|
+
0
|
716
|
+
end
|
717
|
+
|
718
|
+
speed_method = instance_method(:speed)
|
719
|
+
end
|
720
|
+
@context = context
|
721
|
+
@speed_method = speed_method
|
722
|
+
|
723
|
+
rpm_method = nil
|
724
|
+
@state.context do
|
725
|
+
def rpm
|
726
|
+
1000
|
727
|
+
end
|
728
|
+
|
729
|
+
rpm_method = instance_method(:rpm)
|
730
|
+
end
|
731
|
+
@rpm_method = rpm_method
|
732
|
+
end
|
733
|
+
|
734
|
+
def test_should_include_new_module_in_owner_class
|
735
|
+
assert_not_equal @ancestors, @klass.ancestors
|
736
|
+
assert_equal [@context], @klass.ancestors - @ancestors
|
737
|
+
end
|
738
|
+
|
739
|
+
def test_should_define_each_context_method_in_owner_class
|
740
|
+
%w(speed rpm).each {|method| assert @klass.method_defined?(method)}
|
741
|
+
end
|
742
|
+
|
743
|
+
def test_should_define_aliased_context_method_in_owner_class
|
744
|
+
%w(speed rpm).each {|method| assert @klass.method_defined?("__state_idling_#{method}_#{@context.object_id}__")}
|
745
|
+
end
|
746
|
+
|
747
|
+
def test_should_not_use_context_methods_as_owner_class_methods
|
748
|
+
assert_not_equal @speed_method, @state.context_methods[:speed]
|
749
|
+
assert_not_equal @rpm_method, @state.context_methods[:rpm]
|
750
|
+
end
|
751
|
+
|
752
|
+
def test_should_use_context_methods_as_aliased_owner_class_methods
|
753
|
+
assert_equal @speed_method, @state.context_methods[:"__state_idling_speed_#{@context.object_id}__"]
|
754
|
+
assert_equal @rpm_method, @state.context_methods[:"__state_idling_rpm_#{@context.object_id}__"]
|
755
|
+
end
|
756
|
+
end
|
757
|
+
|
758
|
+
class StateWithExistingContextMethodTest < Test::Unit::TestCase
|
759
|
+
def setup
|
760
|
+
@klass = Class.new do
|
761
|
+
def speed
|
762
|
+
60
|
763
|
+
end
|
764
|
+
end
|
765
|
+
@original_speed_method = @klass.instance_method(:speed)
|
766
|
+
|
767
|
+
@machine = StateMachine::Machine.new(@klass)
|
768
|
+
@machine.states << @state = StateMachine::State.new(@machine, :idling)
|
769
|
+
@state.context do
|
770
|
+
def speed
|
771
|
+
0
|
772
|
+
end
|
773
|
+
end
|
774
|
+
end
|
775
|
+
|
776
|
+
def test_should_not_override_method
|
777
|
+
assert_equal @original_speed_method, @klass.instance_method(:speed)
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
class StateWithRedefinedContextMethodTest < Test::Unit::TestCase
|
782
|
+
def setup
|
783
|
+
@klass = Class.new
|
784
|
+
@machine = StateMachine::Machine.new(@klass)
|
785
|
+
@machine.states << @state = StateMachine::State.new(@machine, 'on')
|
786
|
+
|
787
|
+
old_context = nil
|
788
|
+
old_speed_method = nil
|
789
|
+
@state.context do
|
790
|
+
old_context = self
|
791
|
+
def speed
|
792
|
+
0
|
793
|
+
end
|
794
|
+
old_speed_method = instance_method(:speed)
|
795
|
+
end
|
796
|
+
@old_context = old_context
|
797
|
+
@old_speed_method = old_speed_method
|
798
|
+
|
799
|
+
current_context = nil
|
800
|
+
current_speed_method = nil
|
801
|
+
@state.context do
|
802
|
+
current_context = self
|
803
|
+
def speed
|
804
|
+
'green'
|
805
|
+
end
|
806
|
+
current_speed_method = instance_method(:speed)
|
807
|
+
end
|
808
|
+
@current_context = current_context
|
809
|
+
@current_speed_method = current_speed_method
|
810
|
+
end
|
811
|
+
|
812
|
+
def test_should_track_latest_defined_method
|
813
|
+
assert_equal @current_speed_method, @state.context_methods[:"__state_on_speed_#{@current_context.object_id}__"]
|
814
|
+
end
|
815
|
+
|
816
|
+
def test_should_have_the_same_context
|
817
|
+
assert_equal @current_context, @old_context
|
818
|
+
end
|
819
|
+
end
|
820
|
+
|
821
|
+
class StateWithInvalidMethodCallTest < Test::Unit::TestCase
|
822
|
+
def setup
|
823
|
+
@klass = Class.new
|
824
|
+
@machine = StateMachine::Machine.new(@klass)
|
825
|
+
@ancestors = @klass.ancestors
|
826
|
+
@machine.states << @state = StateMachine::State.new(@machine, :idling)
|
827
|
+
@state.context do
|
828
|
+
def speed
|
829
|
+
0
|
830
|
+
end
|
831
|
+
end
|
832
|
+
|
833
|
+
@object = @klass.new
|
834
|
+
end
|
835
|
+
|
836
|
+
def test_should_call_method_missing_arg
|
837
|
+
assert_equal 1, @state.call(@object, :invalid, :method_missing => lambda {1})
|
838
|
+
end
|
839
|
+
end
|
840
|
+
|
841
|
+
class StateWithValidMethodCallForDifferentStateTest < Test::Unit::TestCase
|
842
|
+
def setup
|
843
|
+
@klass = Class.new
|
844
|
+
@machine = StateMachine::Machine.new(@klass)
|
845
|
+
@ancestors = @klass.ancestors
|
846
|
+
@machine.states << @state = StateMachine::State.new(@machine, :idling)
|
847
|
+
@state.context do
|
848
|
+
def speed
|
849
|
+
0
|
850
|
+
end
|
851
|
+
end
|
852
|
+
|
853
|
+
@object = @klass.new
|
854
|
+
end
|
855
|
+
|
856
|
+
def test_should_call_method_missing_arg
|
857
|
+
assert_equal 1, @state.call(@object, :speed, :method_missing => lambda {1})
|
858
|
+
end
|
859
|
+
|
860
|
+
def test_should_raise_invalid_context_on_no_method_error
|
861
|
+
exception = assert_raise(StateMachine::InvalidContext) do
|
862
|
+
@state.call(@object, :speed, :method_missing => lambda { raise NoMethodError.new('Invalid', :speed, [])})
|
863
|
+
end
|
864
|
+
assert_equal @object, exception.object
|
865
|
+
assert_equal 'State nil for :state is not a valid context for calling #speed', exception.message
|
866
|
+
end
|
867
|
+
|
868
|
+
def test_should_raise_original_error_on_no_method_error_with_different_arguments
|
869
|
+
assert_raise(NoMethodError) do
|
870
|
+
@state.call(@object, :speed, :method_missing => lambda { raise NoMethodError.new('Invalid', :speed, [1])})
|
871
|
+
end
|
872
|
+
end
|
873
|
+
|
874
|
+
def test_should_raise_original_error_on_no_method_error_for_different_method
|
875
|
+
assert_raise(NoMethodError) do
|
876
|
+
@state.call(@object, :speed, :method_missing => lambda { raise NoMethodError.new('Invalid', :rpm, [])})
|
877
|
+
end
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
881
|
+
class StateWithValidMethodCallForCurrentStateTest < Test::Unit::TestCase
|
882
|
+
def setup
|
883
|
+
@klass = Class.new
|
884
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :idling)
|
885
|
+
@ancestors = @klass.ancestors
|
886
|
+
@state = @machine.state(:idling)
|
887
|
+
@state.context do
|
888
|
+
def speed(arg = nil)
|
889
|
+
block_given? ? [arg, yield] : arg
|
890
|
+
end
|
891
|
+
end
|
892
|
+
|
893
|
+
@object = @klass.new
|
894
|
+
end
|
895
|
+
|
896
|
+
def test_should_not_raise_an_exception
|
897
|
+
assert_nothing_raised { @state.call(@object, :speed, :method_missing => lambda {raise}) }
|
898
|
+
end
|
899
|
+
|
900
|
+
def test_should_pass_arguments_through
|
901
|
+
assert_equal 1, @state.call(@object, :speed, 1, :method_missing => lambda {})
|
902
|
+
end
|
903
|
+
|
904
|
+
def test_should_pass_blocks_through
|
905
|
+
assert_equal [nil, 1], @state.call(@object, :speed) {1}
|
906
|
+
end
|
907
|
+
|
908
|
+
def test_should_pass_both_arguments_and_blocks_through
|
909
|
+
assert_equal [1, 2], @state.call(@object, :speed, 1, :method_missing => lambda {}) {2}
|
910
|
+
end
|
911
|
+
end
|
912
|
+
|
913
|
+
if RUBY_VERSION > '1.8.7'
|
914
|
+
class StateWithValidInheritedMethodCallForCurrentStateTest < Test::Unit::TestCase
|
915
|
+
def setup
|
916
|
+
@superclass = Class.new do
|
917
|
+
def speed(arg = nil)
|
918
|
+
[arg]
|
919
|
+
end
|
920
|
+
end
|
921
|
+
@klass = Class.new(@superclass)
|
922
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :idling)
|
923
|
+
@ancestors = @klass.ancestors
|
924
|
+
@state = @machine.state(:idling)
|
925
|
+
@state.context do
|
926
|
+
def speed(arg = nil)
|
927
|
+
[arg] + super(2)
|
928
|
+
end
|
929
|
+
end
|
930
|
+
|
931
|
+
@object = @klass.new
|
932
|
+
end
|
933
|
+
|
934
|
+
def test_should_not_raise_an_exception
|
935
|
+
assert_nothing_raised { @state.call(@object, :speed, :method_missing => lambda {raise}) }
|
936
|
+
end
|
937
|
+
|
938
|
+
def test_should_be_able_to_call_super
|
939
|
+
assert_equal [1, 2], @state.call(@object, :speed, 1)
|
940
|
+
end
|
941
|
+
|
942
|
+
def test_should_allow_redefinition
|
943
|
+
@state.context do
|
944
|
+
def speed(arg = nil)
|
945
|
+
[arg] + super(3)
|
946
|
+
end
|
947
|
+
end
|
948
|
+
|
949
|
+
assert_equal [1, 3], @state.call(@object, :speed, 1)
|
950
|
+
end
|
951
|
+
end
|
952
|
+
end
|
953
|
+
|
954
|
+
begin
|
955
|
+
# Load library
|
956
|
+
require 'graphviz'
|
957
|
+
|
958
|
+
class StateDrawingTest < Test::Unit::TestCase
|
959
|
+
def setup
|
960
|
+
@machine = StateMachine::Machine.new(Class.new)
|
961
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
|
962
|
+
@machine.event :ignite do
|
963
|
+
transition :parked => :idling
|
964
|
+
end
|
965
|
+
|
966
|
+
graph = StateMachine::Graph.new('test')
|
967
|
+
@state.draw(graph)
|
968
|
+
@node = graph.get_node('parked')
|
969
|
+
end
|
970
|
+
|
971
|
+
def test_should_use_ellipse_shape
|
972
|
+
assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
|
973
|
+
end
|
974
|
+
|
975
|
+
def test_should_set_width_to_one
|
976
|
+
assert_equal '1', @node['width'].to_s.gsub('"', '')
|
977
|
+
end
|
978
|
+
|
979
|
+
def test_should_set_height_to_one
|
980
|
+
assert_equal '1', @node['height'].to_s.gsub('"', '')
|
981
|
+
end
|
982
|
+
|
983
|
+
def test_should_use_description_as_label
|
984
|
+
assert_equal 'parked (1)', @node['label'].to_s.gsub('"', '')
|
985
|
+
end
|
986
|
+
end
|
987
|
+
|
988
|
+
class StateDrawingInitialTest < Test::Unit::TestCase
|
989
|
+
def setup
|
990
|
+
@machine = StateMachine::Machine.new(Class.new)
|
991
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => true)
|
992
|
+
@machine.event :ignite do
|
993
|
+
transition :parked => :idling
|
994
|
+
end
|
995
|
+
|
996
|
+
@graph = StateMachine::Graph.new('test')
|
997
|
+
@state.draw(@graph)
|
998
|
+
@node = @graph.get_node('parked')
|
999
|
+
end
|
1000
|
+
|
1001
|
+
def test_should_use_ellipse_as_shape
|
1002
|
+
assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
def test_should_draw_edge_between_point_and_state
|
1006
|
+
assert_equal 2, @graph.node_count
|
1007
|
+
assert_equal 1, @graph.edge_count
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
class StateDrawingNilNameTest < Test::Unit::TestCase
|
1012
|
+
def setup
|
1013
|
+
@machine = StateMachine::Machine.new(Class.new)
|
1014
|
+
@machine.states << @state = StateMachine::State.new(@machine, nil)
|
1015
|
+
|
1016
|
+
graph = StateMachine::Graph.new('test')
|
1017
|
+
@state.draw(graph)
|
1018
|
+
@node = graph.get_node('nil')
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
def test_should_have_a_node
|
1022
|
+
assert_not_nil @node
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
def test_should_use_description_as_label
|
1026
|
+
assert_equal 'nil', @node['label'].to_s.gsub('"', '')
|
1027
|
+
end
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
class StateDrawingLambdaValueTest < Test::Unit::TestCase
|
1031
|
+
def setup
|
1032
|
+
@machine = StateMachine::Machine.new(Class.new)
|
1033
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :value => lambda {})
|
1034
|
+
|
1035
|
+
graph = StateMachine::Graph.new('test')
|
1036
|
+
@state.draw(graph)
|
1037
|
+
@node = graph.get_node('parked')
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
def test_should_have_a_node
|
1041
|
+
assert_not_nil @node
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
def test_should_use_description_as_label
|
1045
|
+
assert_equal 'parked (*)', @node['label'].to_s.gsub('"', '')
|
1046
|
+
end
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
class StateDrawingNonFinalTest < Test::Unit::TestCase
|
1050
|
+
def setup
|
1051
|
+
@machine = StateMachine::Machine.new(Class.new)
|
1052
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
1053
|
+
@machine.event :ignite do
|
1054
|
+
transition :parked => :idling
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
graph = StateMachine::Graph.new('test')
|
1058
|
+
@state.draw(graph)
|
1059
|
+
@node = graph.get_node('parked')
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
def test_should_use_ellipse_as_shape
|
1063
|
+
assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
|
1064
|
+
end
|
1065
|
+
end
|
1066
|
+
|
1067
|
+
class StateDrawingFinalTest < Test::Unit::TestCase
|
1068
|
+
def setup
|
1069
|
+
@machine = StateMachine::Machine.new(Class.new)
|
1070
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked)
|
1071
|
+
|
1072
|
+
graph = StateMachine::Graph.new('test')
|
1073
|
+
@state.draw(graph)
|
1074
|
+
@node = graph.get_node('parked')
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
def test_should_use_doublecircle_as_shape
|
1078
|
+
assert_equal 'doublecircle', @node['shape'].to_s.gsub('"', '')
|
1079
|
+
end
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
class StateDrawingWithHumanNameTest < Test::Unit::TestCase
|
1083
|
+
def setup
|
1084
|
+
@machine = StateMachine::Machine.new(Class.new)
|
1085
|
+
@machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => 'Parked')
|
1086
|
+
@machine.event :ignite do
|
1087
|
+
transition :parked => :idling
|
1088
|
+
end
|
1089
|
+
|
1090
|
+
graph = StateMachine::Graph.new('test')
|
1091
|
+
@state.draw(graph, :human_name => true)
|
1092
|
+
@node = graph.get_node('parked')
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
def test_should_use_description_with_human_name_as_label
|
1096
|
+
assert_equal 'Parked', @node['label'].to_s.gsub('"', '')
|
1097
|
+
end
|
1098
|
+
end
|
1099
|
+
rescue LoadError
|
1100
|
+
$stderr.puts 'Skipping GraphViz StateMachine::State tests. `gem install ruby-graphviz` >= v0.9.17 and try again.'
|
1101
|
+
end unless ENV['TRAVIS']
|