verborghs-state_machine 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/CHANGELOG.rdoc +360 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +635 -0
  4. data/Rakefile +77 -0
  5. data/examples/AutoShop_state.png +0 -0
  6. data/examples/Car_state.png +0 -0
  7. data/examples/TrafficLight_state.png +0 -0
  8. data/examples/Vehicle_state.png +0 -0
  9. data/examples/auto_shop.rb +11 -0
  10. data/examples/car.rb +19 -0
  11. data/examples/merb-rest/controller.rb +51 -0
  12. data/examples/merb-rest/model.rb +28 -0
  13. data/examples/merb-rest/view_edit.html.erb +24 -0
  14. data/examples/merb-rest/view_index.html.erb +23 -0
  15. data/examples/merb-rest/view_new.html.erb +13 -0
  16. data/examples/merb-rest/view_show.html.erb +17 -0
  17. data/examples/rails-rest/controller.rb +43 -0
  18. data/examples/rails-rest/migration.rb +11 -0
  19. data/examples/rails-rest/model.rb +23 -0
  20. data/examples/rails-rest/view_edit.html.erb +25 -0
  21. data/examples/rails-rest/view_index.html.erb +23 -0
  22. data/examples/rails-rest/view_new.html.erb +14 -0
  23. data/examples/rails-rest/view_show.html.erb +17 -0
  24. data/examples/traffic_light.rb +7 -0
  25. data/examples/vehicle.rb +31 -0
  26. data/init.rb +1 -0
  27. data/lib/state_machine/assertions.rb +36 -0
  28. data/lib/state_machine/callback.rb +241 -0
  29. data/lib/state_machine/condition_proxy.rb +106 -0
  30. data/lib/state_machine/eval_helpers.rb +83 -0
  31. data/lib/state_machine/event.rb +267 -0
  32. data/lib/state_machine/event_collection.rb +122 -0
  33. data/lib/state_machine/extensions.rb +149 -0
  34. data/lib/state_machine/guard.rb +230 -0
  35. data/lib/state_machine/initializers/merb.rb +1 -0
  36. data/lib/state_machine/initializers/rails.rb +5 -0
  37. data/lib/state_machine/initializers.rb +4 -0
  38. data/lib/state_machine/integrations/active_model/locale.rb +11 -0
  39. data/lib/state_machine/integrations/active_model/observer.rb +45 -0
  40. data/lib/state_machine/integrations/active_model.rb +445 -0
  41. data/lib/state_machine/integrations/active_record/locale.rb +20 -0
  42. data/lib/state_machine/integrations/active_record.rb +522 -0
  43. data/lib/state_machine/integrations/data_mapper/observer.rb +175 -0
  44. data/lib/state_machine/integrations/data_mapper.rb +379 -0
  45. data/lib/state_machine/integrations/mongo_mapper.rb +309 -0
  46. data/lib/state_machine/integrations/sequel.rb +356 -0
  47. data/lib/state_machine/integrations.rb +83 -0
  48. data/lib/state_machine/machine.rb +1645 -0
  49. data/lib/state_machine/machine_collection.rb +64 -0
  50. data/lib/state_machine/matcher.rb +123 -0
  51. data/lib/state_machine/matcher_helpers.rb +54 -0
  52. data/lib/state_machine/node_collection.rb +152 -0
  53. data/lib/state_machine/state.rb +260 -0
  54. data/lib/state_machine/state_collection.rb +112 -0
  55. data/lib/state_machine/transition.rb +399 -0
  56. data/lib/state_machine/transition_collection.rb +244 -0
  57. data/lib/state_machine.rb +421 -0
  58. data/lib/tasks/state_machine.rake +1 -0
  59. data/lib/tasks/state_machine.rb +27 -0
  60. data/test/files/en.yml +9 -0
  61. data/test/files/switch.rb +11 -0
  62. data/test/functional/state_machine_test.rb +980 -0
  63. data/test/test_helper.rb +4 -0
  64. data/test/unit/assertions_test.rb +40 -0
  65. data/test/unit/callback_test.rb +728 -0
  66. data/test/unit/condition_proxy_test.rb +328 -0
  67. data/test/unit/eval_helpers_test.rb +222 -0
  68. data/test/unit/event_collection_test.rb +324 -0
  69. data/test/unit/event_test.rb +795 -0
  70. data/test/unit/guard_test.rb +909 -0
  71. data/test/unit/integrations/active_model_test.rb +956 -0
  72. data/test/unit/integrations/active_record_test.rb +1918 -0
  73. data/test/unit/integrations/data_mapper_test.rb +1814 -0
  74. data/test/unit/integrations/mongo_mapper_test.rb +1382 -0
  75. data/test/unit/integrations/sequel_test.rb +1492 -0
  76. data/test/unit/integrations_test.rb +50 -0
  77. data/test/unit/invalid_event_test.rb +7 -0
  78. data/test/unit/invalid_transition_test.rb +7 -0
  79. data/test/unit/machine_collection_test.rb +565 -0
  80. data/test/unit/machine_test.rb +2349 -0
  81. data/test/unit/matcher_helpers_test.rb +37 -0
  82. data/test/unit/matcher_test.rb +155 -0
  83. data/test/unit/node_collection_test.rb +207 -0
  84. data/test/unit/state_collection_test.rb +280 -0
  85. data/test/unit/state_machine_test.rb +31 -0
  86. data/test/unit/state_test.rb +848 -0
  87. data/test/unit/transition_collection_test.rb +2098 -0
  88. data/test/unit/transition_test.rb +1384 -0
  89. metadata +176 -0
@@ -0,0 +1,848 @@
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
+ @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.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.methods
40
+ end
41
+ end
42
+
43
+ class StateTest < Test::Unit::TestCase
44
+ def setup
45
+ @machine = StateMachine::Machine.new(Class.new)
46
+ @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 context=[]>', @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
+ @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
+ end
119
+
120
+ class StateWithNameTest < Test::Unit::TestCase
121
+ def setup
122
+ @klass = Class.new
123
+ @machine = StateMachine::Machine.new(@klass)
124
+ @state = StateMachine::State.new(@machine, :parked)
125
+ end
126
+
127
+ def test_should_have_a_name
128
+ assert_equal :parked, @state.name
129
+ end
130
+
131
+ def test_should_have_a_qualified_name
132
+ assert_equal :parked, @state.name
133
+ end
134
+
135
+ def test_should_have_a_human_name
136
+ assert_equal 'parked', @state.human_name
137
+ end
138
+
139
+ def test_should_use_stringify_the_name_as_the_value
140
+ assert_equal 'parked', @state.value
141
+ end
142
+
143
+ def test_should_match_stringified_name
144
+ assert @state.matches?('parked')
145
+ assert !@state.matches?('idling')
146
+ end
147
+
148
+ def test_should_not_include_value_in_description
149
+ assert_equal 'parked', @state.description
150
+ end
151
+
152
+ def test_should_define_predicate
153
+ assert @klass.new.respond_to?(:parked?)
154
+ end
155
+ end
156
+
157
+ class StateWithNilValueTest < Test::Unit::TestCase
158
+ def setup
159
+ @klass = Class.new
160
+ @machine = StateMachine::Machine.new(@klass)
161
+ @state = StateMachine::State.new(@machine, :parked, :value => nil)
162
+ end
163
+
164
+ def test_should_have_a_name
165
+ assert_equal :parked, @state.name
166
+ end
167
+
168
+ def test_should_have_a_nil_value
169
+ assert_nil @state.value
170
+ end
171
+
172
+ def test_should_match_nil_values
173
+ assert @state.matches?(nil)
174
+ end
175
+
176
+ def test_should_have_a_description
177
+ assert_equal 'parked (nil)', @state.description
178
+ end
179
+
180
+ def test_should_define_predicate
181
+ object = @klass.new
182
+ assert object.respond_to?(:parked?)
183
+ end
184
+ end
185
+
186
+ class StateWithSymbolicValueTest < Test::Unit::TestCase
187
+ def setup
188
+ @klass = Class.new
189
+ @machine = StateMachine::Machine.new(@klass)
190
+ @state = StateMachine::State.new(@machine, :parked, :value => :parked)
191
+ end
192
+
193
+ def test_should_use_custom_value
194
+ assert_equal :parked, @state.value
195
+ end
196
+
197
+ def test_should_not_include_value_in_description
198
+ assert_equal 'parked', @state.description
199
+ end
200
+
201
+ def test_should_match_symbolic_value
202
+ assert @state.matches?(:parked)
203
+ assert !@state.matches?('parked')
204
+ end
205
+
206
+ def test_should_define_predicate
207
+ object = @klass.new
208
+ assert object.respond_to?(:parked?)
209
+ end
210
+ end
211
+
212
+ class StateWithIntegerValueTest < Test::Unit::TestCase
213
+ def setup
214
+ @klass = Class.new
215
+ @machine = StateMachine::Machine.new(@klass)
216
+ @state = StateMachine::State.new(@machine, :parked, :value => 1)
217
+ end
218
+
219
+ def test_should_use_custom_value
220
+ assert_equal 1, @state.value
221
+ end
222
+
223
+ def test_should_include_value_in_description
224
+ assert_equal 'parked (1)', @state.description
225
+ end
226
+
227
+ def test_should_match_integer_value
228
+ assert @state.matches?(1)
229
+ assert !@state.matches?(2)
230
+ end
231
+
232
+ def test_should_define_predicate
233
+ object = @klass.new
234
+ assert object.respond_to?(:parked?)
235
+ end
236
+ end
237
+
238
+ class StateWithLambdaValueTest < Test::Unit::TestCase
239
+ def setup
240
+ @klass = Class.new
241
+ @args = nil
242
+ @machine = StateMachine::Machine.new(@klass)
243
+ @value = lambda {|*args| @args = args; :parked}
244
+ @state = StateMachine::State.new(@machine, :parked, :value => @value)
245
+ end
246
+
247
+ def test_should_use_evaluated_value_by_default
248
+ assert_equal :parked, @state.value
249
+ end
250
+
251
+ def test_should_allow_access_to_original_value
252
+ assert_equal @value, @state.value(false)
253
+ end
254
+
255
+ def test_should_include_masked_value_in_description
256
+ assert_equal 'parked (*)', @state.description
257
+ end
258
+
259
+ def test_should_not_pass_in_any_arguments
260
+ @state.value
261
+ assert_equal [], @args
262
+ end
263
+
264
+ def test_should_define_predicate
265
+ object = @klass.new
266
+ assert object.respond_to?(:parked?)
267
+ end
268
+
269
+ def test_should_match_evaluated_value
270
+ assert @state.matches?(:parked)
271
+ end
272
+ end
273
+
274
+ class StateWithCachedLambdaValueTest < Test::Unit::TestCase
275
+ def setup
276
+ @klass = Class.new
277
+ @machine = StateMachine::Machine.new(@klass)
278
+ @dynamic_value = lambda {'value'}
279
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value, :cache => true)
280
+ end
281
+
282
+ def test_should_be_caching
283
+ assert @state.cache
284
+ end
285
+
286
+ def test_should_evaluate_value
287
+ assert_equal 'value', @state.value
288
+ end
289
+
290
+ def test_should_only_evaluate_value_once
291
+ value = @state.value
292
+ assert_same value, @state.value
293
+ end
294
+
295
+ def test_should_update_value_index_for_state_collection
296
+ @state.value
297
+ assert_equal @state, @machine.states['value', :value]
298
+ assert_nil @machine.states[@dynamic_value, :value]
299
+ end
300
+ end
301
+
302
+ class StateWithoutCachedLambdaValueTest < Test::Unit::TestCase
303
+ def setup
304
+ @klass = Class.new
305
+ @machine = StateMachine::Machine.new(@klass)
306
+ @dynamic_value = lambda {'value'}
307
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value)
308
+ end
309
+
310
+ def test_should_not_be_caching
311
+ assert !@state.cache
312
+ end
313
+
314
+ def test_should_evaluate_value_each_time
315
+ value = @state.value
316
+ assert_not_same value, @state.value
317
+ end
318
+
319
+ def test_should_not_update_value_index_for_state_collection
320
+ @state.value
321
+ assert_nil @machine.states['value', :value]
322
+ assert_equal @state, @machine.states[@dynamic_value, :value]
323
+ end
324
+ end
325
+
326
+ class StateWithMatcherTest < Test::Unit::TestCase
327
+ def setup
328
+ @klass = Class.new
329
+ @args = nil
330
+ @machine = StateMachine::Machine.new(@klass)
331
+ @state = StateMachine::State.new(@machine, :parked, :if => lambda {|value| value == 1})
332
+ end
333
+
334
+ def test_should_not_match_actual_value
335
+ assert !@state.matches?('parked')
336
+ end
337
+
338
+ def test_should_match_evaluated_block
339
+ assert @state.matches?(1)
340
+ end
341
+ end
342
+
343
+ class StateWithHumanNameTest < Test::Unit::TestCase
344
+ def setup
345
+ @klass = Class.new
346
+ @machine = StateMachine::Machine.new(@klass)
347
+ @state = StateMachine::State.new(@machine, :parked, :human_name => 'stopped')
348
+ end
349
+
350
+ def test_should_use_custom_human_name
351
+ assert_equal 'stopped', @state.human_name
352
+ end
353
+ end
354
+
355
+ class StateWithDynamicHumanNameTest < Test::Unit::TestCase
356
+ def setup
357
+ @klass = Class.new
358
+ @machine = StateMachine::Machine.new(@klass)
359
+ @state = StateMachine::State.new(@machine, :parked, :human_name => lambda {|state, object| ['stopped', object]})
360
+ end
361
+
362
+ def test_should_use_custom_human_name
363
+ human_name, klass = @state.human_name
364
+ assert_equal 'stopped', human_name
365
+ assert_equal @klass, klass
366
+ end
367
+
368
+ def test_should_allow_custom_class_to_be_passed_through
369
+ human_name, klass = @state.human_name(1)
370
+ assert_equal 'stopped', human_name
371
+ assert_equal 1, klass
372
+ end
373
+
374
+ def test_should_not_cache_value
375
+ assert_not_same @state.human_name, @state.human_name
376
+ end
377
+ end
378
+
379
+ class StateInitialTest < Test::Unit::TestCase
380
+ def setup
381
+ @machine = StateMachine::Machine.new(Class.new)
382
+ @state = StateMachine::State.new(@machine, :parked, :initial => true)
383
+ end
384
+
385
+ def test_should_be_initial
386
+ assert @state.initial
387
+ assert @state.initial?
388
+ end
389
+ end
390
+
391
+ class StateNotInitialTest < Test::Unit::TestCase
392
+ def setup
393
+ @machine = StateMachine::Machine.new(Class.new)
394
+ @state = StateMachine::State.new(@machine, :parked, :initial => false)
395
+ end
396
+
397
+ def test_should_not_be_initial
398
+ assert !@state.initial
399
+ assert !@state.initial?
400
+ end
401
+ end
402
+
403
+ class StateFinalTest < Test::Unit::TestCase
404
+ def setup
405
+ @machine = StateMachine::Machine.new(Class.new)
406
+ @state = StateMachine::State.new(@machine, :parked)
407
+ end
408
+
409
+ def test_should_be_final_without_input_transitions
410
+ assert @state.final?
411
+ end
412
+
413
+ def test_should_be_final_with_input_transitions
414
+ @machine.event :park do
415
+ transition :idling => :parked
416
+ end
417
+
418
+ assert @state.final?
419
+ end
420
+
421
+ def test_should_be_final_with_loopback
422
+ @machine.event :ignite do
423
+ transition :parked => same
424
+ end
425
+
426
+ assert @state.final?
427
+ end
428
+ end
429
+
430
+ class StateNotFinalTest < Test::Unit::TestCase
431
+ def setup
432
+ @machine = StateMachine::Machine.new(Class.new)
433
+ @state = StateMachine::State.new(@machine, :parked)
434
+ end
435
+
436
+ def test_should_not_be_final_with_outgoing_whitelist_transitions
437
+ @machine.event :ignite do
438
+ transition :parked => :idling
439
+ end
440
+
441
+ assert !@state.final?
442
+ end
443
+
444
+ def test_should_not_be_final_with_outgoing_all_transitions
445
+ @machine.event :ignite do
446
+ transition all => :idling
447
+ end
448
+
449
+ assert !@state.final?
450
+ end
451
+
452
+ def test_should_not_be_final_with_outgoing_blacklist_transitions
453
+ @machine.event :ignite do
454
+ transition all - :first_gear => :idling
455
+ end
456
+
457
+ assert !@state.final?
458
+ end
459
+ end
460
+
461
+ class StateWithConflictingHelpersTest < Test::Unit::TestCase
462
+ def setup
463
+ @klass = Class.new do
464
+ def parked?
465
+ 0
466
+ end
467
+ end
468
+ @machine = StateMachine::Machine.new(@klass)
469
+ @machine.state :parked
470
+ @object = @klass.new
471
+ end
472
+
473
+ def test_should_not_redefine_state_predicate
474
+ assert_equal 0, @object.parked?
475
+ end
476
+
477
+ def test_should_allow_super_chaining
478
+ @klass.class_eval do
479
+ def parked?
480
+ super ? 1 : 0
481
+ end
482
+ end
483
+
484
+ assert_equal 0, @object.parked?
485
+ end
486
+ end
487
+
488
+ class StateWithNamespaceTest < Test::Unit::TestCase
489
+ def setup
490
+ @klass = Class.new
491
+ @machine = StateMachine::Machine.new(@klass, :namespace => 'alarm')
492
+ @state = StateMachine::State.new(@machine, :active)
493
+ @object = @klass.new
494
+ end
495
+
496
+ def test_should_have_a_name
497
+ assert_equal :active, @state.name
498
+ end
499
+
500
+ def test_should_have_a_qualified_name
501
+ assert_equal :alarm_active, @state.qualified_name
502
+ end
503
+
504
+ def test_should_namespace_predicate
505
+ assert @object.respond_to?(:alarm_active?)
506
+ end
507
+ end
508
+
509
+ class StateAfterBeingCopiedTest < Test::Unit::TestCase
510
+ def setup
511
+ @machine = StateMachine::Machine.new(Class.new)
512
+ @state = StateMachine::State.new(@machine, :parked)
513
+ @copied_state = @state.dup
514
+ end
515
+
516
+ def test_should_not_have_the_same_collection_of_methods
517
+ assert_not_same @state.methods, @copied_state.methods
518
+ end
519
+ end
520
+
521
+ class StateWithContextTest < Test::Unit::TestCase
522
+ def setup
523
+ @klass = Class.new
524
+ @machine = StateMachine::Machine.new(@klass)
525
+ @ancestors = @klass.ancestors
526
+ @state = StateMachine::State.new(@machine, :idling)
527
+
528
+ speed_method = nil
529
+ rpm_method = nil
530
+ @state.context do
531
+ def speed
532
+ 0
533
+ end
534
+ speed_method = instance_method(:speed)
535
+
536
+ def rpm
537
+ 1000
538
+ end
539
+ rpm_method = instance_method(:rpm)
540
+ end
541
+
542
+ @speed_method = speed_method
543
+ @rpm_method = rpm_method
544
+ end
545
+
546
+ def test_should_include_new_module_in_owner_class
547
+ assert_not_equal @ancestors, @klass.ancestors
548
+ assert_equal 1, @klass.ancestors.size - @ancestors.size
549
+ end
550
+
551
+ def test_should_define_each_context_method_in_owner_class
552
+ %w(speed rpm).each {|method| assert @klass.method_defined?(method)}
553
+ end
554
+
555
+ def test_should_not_use_context_methods_as_owner_class_methods
556
+ assert_not_equal @speed_method, @klass.instance_method(:speed)
557
+ assert_not_equal @rpm_method, @klass.instance_method(:rpm)
558
+ end
559
+
560
+ def test_should_include_context_methods_in_state_methods
561
+ assert_equal @speed_method, @state.methods[:speed]
562
+ assert_equal @rpm_method, @state.methods[:rpm]
563
+ end
564
+ end
565
+
566
+ class StateWithMultipleContextsTest < Test::Unit::TestCase
567
+ def setup
568
+ @klass = Class.new
569
+ @machine = StateMachine::Machine.new(@klass)
570
+ @ancestors = @klass.ancestors
571
+ @state = StateMachine::State.new(@machine, :idling)
572
+
573
+ speed_method = nil
574
+ @state.context do
575
+ def speed
576
+ 0
577
+ end
578
+
579
+ speed_method = instance_method(:speed)
580
+ end
581
+ @speed_method = speed_method
582
+
583
+ rpm_method = nil
584
+ @state.context do
585
+ def rpm
586
+ 1000
587
+ end
588
+
589
+ rpm_method = instance_method(:rpm)
590
+ end
591
+ @rpm_method = rpm_method
592
+ end
593
+
594
+ def test_should_include_new_module_in_owner_class
595
+ assert_not_equal @ancestors, @klass.ancestors
596
+ assert_equal 2, @klass.ancestors.size - @ancestors.size
597
+ end
598
+
599
+ def test_should_define_each_context_method_in_owner_class
600
+ %w(speed rpm).each {|method| assert @klass.method_defined?(method)}
601
+ end
602
+
603
+ def test_should_not_use_context_methods_as_owner_class_methods
604
+ assert_not_equal @speed_method, @klass.instance_method(:speed)
605
+ assert_not_equal @rpm_method, @klass.instance_method(:rpm)
606
+ end
607
+
608
+ def test_should_include_context_methods_in_state_methods
609
+ assert_equal @speed_method, @state.methods[:speed]
610
+ assert_equal @rpm_method, @state.methods[:rpm]
611
+ end
612
+ end
613
+
614
+ class StateWithExistingContextMethodTest < Test::Unit::TestCase
615
+ def setup
616
+ @klass = Class.new do
617
+ def speed
618
+ 60
619
+ end
620
+ end
621
+ @original_speed_method = @klass.instance_method(:speed)
622
+
623
+ @machine = StateMachine::Machine.new(@klass)
624
+ @state = StateMachine::State.new(@machine, :idling)
625
+ @state.context do
626
+ def speed
627
+ 0
628
+ end
629
+ end
630
+ end
631
+
632
+ def test_should_not_override_method
633
+ assert_equal @original_speed_method, @klass.instance_method(:speed)
634
+ end
635
+ end
636
+
637
+ class StateWithRedefinedContextMethodTest < Test::Unit::TestCase
638
+ def setup
639
+ @klass = Class.new
640
+ @machine = StateMachine::Machine.new(@klass)
641
+ @state = StateMachine::State.new(@machine, 'on')
642
+
643
+ old_speed_method = nil
644
+ @state.context do
645
+ def speed
646
+ 0
647
+ end
648
+ old_speed_method = instance_method(:speed)
649
+ end
650
+ @old_speed_method = old_speed_method
651
+
652
+ current_speed_method = nil
653
+ @state.context do
654
+ def speed
655
+ 'green'
656
+ end
657
+ current_speed_method = instance_method(:speed)
658
+ end
659
+ @current_speed_method = current_speed_method
660
+ end
661
+
662
+ def test_should_track_latest_defined_method
663
+ assert_equal @current_speed_method, @state.methods[:speed]
664
+ end
665
+ end
666
+
667
+ class StateWithInvalidMethodCallTest < Test::Unit::TestCase
668
+ def setup
669
+ @klass = Class.new
670
+ @machine = StateMachine::Machine.new(@klass)
671
+ @ancestors = @klass.ancestors
672
+ @state = StateMachine::State.new(@machine, :idling)
673
+ @state.context do
674
+ def speed
675
+ 0
676
+ end
677
+ end
678
+
679
+ @object = @klass.new
680
+ end
681
+
682
+ def test_should_call_method_missing_arg
683
+ assert_equal 1, @state.call(@object, :invalid, lambda {1})
684
+ end
685
+ end
686
+
687
+ class StateWithValidMethodCallTest < Test::Unit::TestCase
688
+ def setup
689
+ @klass = Class.new
690
+ @machine = StateMachine::Machine.new(@klass)
691
+ @ancestors = @klass.ancestors
692
+ @state = StateMachine::State.new(@machine, :idling)
693
+ @state.context do
694
+ def speed(arg = nil)
695
+ block_given? ? [arg, yield] : arg
696
+ end
697
+ end
698
+
699
+ @object = @klass.new
700
+ end
701
+
702
+ def test_should_not_raise_an_exception
703
+ assert_nothing_raised { @state.call(@object, :speed, lambda {raise}) }
704
+ end
705
+
706
+ def test_should_pass_arguments_through
707
+ assert_equal 1, @state.call(@object, :speed, lambda {}, 1)
708
+ end
709
+
710
+ def test_should_pass_blocks_through
711
+ assert_equal [nil, 1], @state.call(@object, :speed) {1}
712
+ end
713
+
714
+ def test_should_pass_both_arguments_and_blocks_through
715
+ assert_equal [1, 2], @state.call(@object, :speed, lambda {}, 1) {2}
716
+ end
717
+ end
718
+
719
+ begin
720
+ # Load library
721
+ require 'rubygems'
722
+ gem 'ruby-graphviz', '>=0.9.0'
723
+ require 'graphviz'
724
+
725
+ class StateDrawingTest < Test::Unit::TestCase
726
+ def setup
727
+ @machine = StateMachine::Machine.new(Class.new)
728
+ @machine.event :ignite do
729
+ transition :parked => :idling
730
+ end
731
+ @state = StateMachine::State.new(@machine, :parked, :value => 1)
732
+
733
+ graph = GraphViz.new('G')
734
+ @node = @state.draw(graph)
735
+ end
736
+
737
+ def test_should_use_ellipse_shape
738
+ assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
739
+ end
740
+
741
+ def test_should_set_width_to_one
742
+ assert_equal '1', @node['width'].to_s.gsub('"', '')
743
+ end
744
+
745
+ def test_should_set_height_to_one
746
+ assert_equal '1', @node['height'].to_s.gsub('"', '')
747
+ end
748
+
749
+ def test_should_use_stringified_name_as_name
750
+ assert_equal 'parked', @node.name
751
+ end
752
+
753
+ def test_should_use_description_as_label
754
+ assert_equal 'parked (1)', @node['label'].to_s.gsub('"', '')
755
+ end
756
+ end
757
+
758
+ class StateDrawingInitialTest < Test::Unit::TestCase
759
+ def setup
760
+ @machine = StateMachine::Machine.new(Class.new)
761
+ @machine.event :ignite do
762
+ transition :parked => :idling
763
+ end
764
+ @state = StateMachine::State.new(@machine, :parked, :initial => true)
765
+
766
+ @graph = GraphViz.new('G')
767
+ @node = @state.draw(@graph)
768
+ end
769
+
770
+ def test_should_use_ellipse_as_shape
771
+ assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
772
+ end
773
+
774
+ def test_should_draw_edge_between_point_and_state
775
+ assert_equal 2, @graph.node_count
776
+ assert_equal 1, @graph.edge_count
777
+ end
778
+ end
779
+
780
+ class StateDrawingNilNameTest < Test::Unit::TestCase
781
+ def setup
782
+ @machine = StateMachine::Machine.new(Class.new)
783
+ @state = StateMachine::State.new(@machine, nil)
784
+
785
+ graph = GraphViz.new('G')
786
+ @node = @state.draw(graph)
787
+ end
788
+
789
+ def test_should_use_stringified_nil_as_name
790
+ assert_equal 'nil', @node.name
791
+ end
792
+
793
+ def test_should_use_description_as_label
794
+ assert_equal 'nil', @node['label'].to_s.gsub('"', '')
795
+ end
796
+ end
797
+
798
+ class StateDrawingLambdaValueTest < Test::Unit::TestCase
799
+ def setup
800
+ @machine = StateMachine::Machine.new(Class.new)
801
+ @state = StateMachine::State.new(@machine, :parked, :value => lambda {})
802
+
803
+ graph = GraphViz.new('G')
804
+ @node = @state.draw(graph)
805
+ end
806
+
807
+ def test_should_use_stringified_name_as_name
808
+ assert_equal 'parked', @node.name
809
+ end
810
+
811
+ def test_should_use_description_as_label
812
+ assert_equal 'parked (*)', @node['label'].to_s.gsub('"', '')
813
+ end
814
+ end
815
+
816
+ class StateDrawingNonFinalTest < Test::Unit::TestCase
817
+ def setup
818
+ @machine = StateMachine::Machine.new(Class.new)
819
+ @machine.event :ignite do
820
+ transition :parked => :idling
821
+ end
822
+ @state = StateMachine::State.new(@machine, :parked)
823
+
824
+ graph = GraphViz.new('G')
825
+ @node = @state.draw(graph)
826
+ end
827
+
828
+ def test_should_use_ellipse_as_shape
829
+ assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
830
+ end
831
+ end
832
+
833
+ class StateDrawingFinalTest < Test::Unit::TestCase
834
+ def setup
835
+ @machine = StateMachine::Machine.new(Class.new)
836
+ @state = StateMachine::State.new(@machine, :parked)
837
+
838
+ graph = GraphViz.new('G')
839
+ @node = @state.draw(graph)
840
+ end
841
+
842
+ def test_should_use_doublecircle_as_shape
843
+ assert_equal 'doublecircle', @node['shape'].to_s.gsub('"', '')
844
+ end
845
+ end
846
+ rescue LoadError
847
+ $stderr.puts 'Skipping GraphViz StateMachine::State tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
848
+ end