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,728 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class CallbackTest < Test::Unit::TestCase
4
+ def test_should_raise_exception_if_invalid_type_specified
5
+ exception = assert_raise(ArgumentError) { StateMachine::Callback.new(:invalid) {} }
6
+ assert_equal 'Type must be :before, :after, or :around', exception.message
7
+ end
8
+
9
+ def test_should_not_raise_exception_if_using_before_type
10
+ assert_nothing_raised { StateMachine::Callback.new(:before) {} }
11
+ end
12
+
13
+ def test_should_not_raise_exception_if_using_after_type
14
+ assert_nothing_raised { StateMachine::Callback.new(:after) {} }
15
+ end
16
+
17
+ def test_should_not_raise_exception_if_using_around_type
18
+ assert_nothing_raised { StateMachine::Callback.new(:around) {} }
19
+ end
20
+
21
+ def test_should_raise_exception_if_no_methods_specified
22
+ exception = assert_raise(ArgumentError) { StateMachine::Callback.new(:before) }
23
+ assert_equal 'Method(s) for callback must be specified', exception.message
24
+ end
25
+
26
+ def test_should_not_raise_exception_if_method_specified_in_do_option
27
+ assert_nothing_raised { StateMachine::Callback.new(:before, :do => :run) }
28
+ end
29
+
30
+ def test_should_not_raise_exception_if_method_specified_as_argument
31
+ assert_nothing_raised { StateMachine::Callback.new(:before, :run) }
32
+ end
33
+
34
+ def test_should_not_raise_exception_if_method_specified_as_block
35
+ assert_nothing_raised { StateMachine::Callback.new(:before, :run) {} }
36
+ end
37
+
38
+ def test_should_not_raise_exception_if_implicit_option_specified
39
+ assert_nothing_raised { StateMachine::Callback.new(:before, :do => :run, :invalid => :valid) }
40
+ end
41
+
42
+ def test_should_not_bind_to_objects
43
+ assert !StateMachine::Callback.bind_to_object
44
+ end
45
+
46
+ def test_should_not_have_a_terminator
47
+ assert_nil StateMachine::Callback.terminator
48
+ end
49
+ end
50
+
51
+ class CallbackByDefaultTest < Test::Unit::TestCase
52
+ def setup
53
+ @callback = StateMachine::Callback.new(:before) {}
54
+ end
55
+
56
+ def test_should_have_type
57
+ assert_equal :before, @callback.type
58
+ end
59
+
60
+ def test_should_not_have_a_terminator
61
+ assert_nil @callback.terminator
62
+ end
63
+
64
+ def test_should_have_a_guard_with_all_matcher_requirements
65
+ assert_equal StateMachine::AllMatcher.instance, @callback.guard.event_requirement
66
+ assert_equal StateMachine::AllMatcher.instance, @callback.guard.state_requirements.first[:from]
67
+ assert_equal StateMachine::AllMatcher.instance, @callback.guard.state_requirements.first[:to]
68
+ end
69
+
70
+ def test_should_not_have_any_known_states
71
+ assert_equal [], @callback.known_states
72
+ end
73
+ end
74
+
75
+ class CallbackWithMethodArgumentTest < Test::Unit::TestCase
76
+ def setup
77
+ @callback = StateMachine::Callback.new(:before, lambda {|*args| @args = args})
78
+
79
+ @object = Object.new
80
+ @result = @callback.call(@object)
81
+ end
82
+
83
+ def test_should_be_successful
84
+ assert @result
85
+ end
86
+
87
+ def test_should_call_with_empty_context
88
+ assert_equal [@object], @args
89
+ end
90
+ end
91
+
92
+ class CallbackWithMultipleMethodArgumentsTest < Test::Unit::TestCase
93
+ def setup
94
+ @callback = StateMachine::Callback.new(:before, :run_1, :run_2)
95
+
96
+ class << @object = Object.new
97
+ attr_accessor :callbacks
98
+
99
+ def run_1
100
+ (@callbacks ||= []) << :run_1
101
+ end
102
+
103
+ def run_2
104
+ (@callbacks ||= []) << :run_2
105
+ end
106
+ end
107
+
108
+ @result = @callback.call(@object)
109
+ end
110
+
111
+ def test_should_be_successful
112
+ assert @result
113
+ end
114
+
115
+ def test_should_call_each_callback_in_order
116
+ assert_equal [:run_1, :run_2], @object.callbacks
117
+ end
118
+ end
119
+
120
+ class CallbackWithDoMethodTest < Test::Unit::TestCase
121
+ def setup
122
+ @callback = StateMachine::Callback.new(:before, :do => lambda {|*args| @args = args})
123
+
124
+ @object = Object.new
125
+ @result = @callback.call(@object)
126
+ end
127
+
128
+ def test_should_be_successful
129
+ assert @result
130
+ end
131
+
132
+ def test_should_call_with_empty_context
133
+ assert_equal [@object], @args
134
+ end
135
+ end
136
+
137
+ class CallbackWithMultipleDoMethodsTest < Test::Unit::TestCase
138
+ def setup
139
+ @callback = StateMachine::Callback.new(:before, :do => [:run_1, :run_2])
140
+
141
+ class << @object = Object.new
142
+ attr_accessor :callbacks
143
+
144
+ def run_1
145
+ (@callbacks ||= []) << :run_1
146
+ end
147
+
148
+ def run_2
149
+ (@callbacks ||= []) << :run_2
150
+ end
151
+ end
152
+
153
+ @result = @callback.call(@object)
154
+ end
155
+
156
+ def test_should_be_successful
157
+ assert @result
158
+ end
159
+
160
+ def test_should_call_each_callback_in_order
161
+ assert_equal [:run_1, :run_2], @object.callbacks
162
+ end
163
+ end
164
+
165
+ class CallbackWithBlockTest < Test::Unit::TestCase
166
+ def setup
167
+ @callback = StateMachine::Callback.new(:before) do |*args|
168
+ @args = args
169
+ end
170
+
171
+ @object = Object.new
172
+ @result = @callback.call(@object)
173
+ end
174
+
175
+ def test_should_be_successful
176
+ assert @result
177
+ end
178
+
179
+ def test_should_call_with_empty_context
180
+ assert_equal [@object], @args
181
+ end
182
+ end
183
+
184
+ class CallbackWithMixedMethodsTest < Test::Unit::TestCase
185
+ def setup
186
+ @callback = StateMachine::Callback.new(:before, :run_argument, :do => :run_do) do |object|
187
+ object.callbacks << :block
188
+ end
189
+
190
+ class << @object = Object.new
191
+ attr_accessor :callbacks
192
+
193
+ def run_argument
194
+ (@callbacks ||= []) << :argument
195
+ end
196
+
197
+ def run_do
198
+ (@callbacks ||= []) << :do
199
+ end
200
+ end
201
+
202
+ @result = @callback.call(@object)
203
+ end
204
+
205
+ def test_should_be_successful
206
+ assert @result
207
+ end
208
+
209
+ def test_should_call_each_callback_in_order
210
+ assert_equal [:argument, :do, :block], @object.callbacks
211
+ end
212
+ end
213
+
214
+ class CallbackWithExplicitRequirementsTest < Test::Unit::TestCase
215
+ def setup
216
+ @object = Object.new
217
+ @callback = StateMachine::Callback.new(:before, :from => :parked, :to => :idling, :on => :ignite, :do => lambda {})
218
+ end
219
+
220
+ def test_should_call_with_empty_context
221
+ assert @callback.call(@object, {})
222
+ end
223
+
224
+ def test_should_not_call_if_from_not_included
225
+ assert !@callback.call(@object, :from => :idling)
226
+ end
227
+
228
+ def test_should_not_call_if_to_not_included
229
+ assert !@callback.call(@object, :to => :parked)
230
+ end
231
+
232
+ def test_should_not_call_if_on_not_included
233
+ assert !@callback.call(@object, :on => :park)
234
+ end
235
+
236
+ def test_should_call_if_all_requirements_met
237
+ assert @callback.call(@object, :from => :parked, :to => :idling, :on => :ignite)
238
+ end
239
+
240
+ def test_should_include_in_known_states
241
+ assert_equal [:parked, :idling], @callback.known_states
242
+ end
243
+ end
244
+
245
+ class CallbackWithImplicitRequirementsTest < Test::Unit::TestCase
246
+ def setup
247
+ @object = Object.new
248
+ @callback = StateMachine::Callback.new(:before, :parked => :idling, :on => :ignite, :do => lambda {})
249
+ end
250
+
251
+ def test_should_call_with_empty_context
252
+ assert @callback.call(@object, {})
253
+ end
254
+
255
+ def test_should_not_call_if_from_not_included
256
+ assert !@callback.call(@object, :from => :idling)
257
+ end
258
+
259
+ def test_should_not_call_if_to_not_included
260
+ assert !@callback.call(@object, :to => :parked)
261
+ end
262
+
263
+ def test_should_not_call_if_on_not_included
264
+ assert !@callback.call(@object, :on => :park)
265
+ end
266
+
267
+ def test_should_call_if_all_requirements_met
268
+ assert @callback.call(@object, :from => :parked, :to => :idling, :on => :ignite)
269
+ end
270
+
271
+ def test_should_include_in_known_states
272
+ assert_equal [:parked, :idling], @callback.known_states
273
+ end
274
+ end
275
+
276
+ class CallbackWithIfConditionTest < Test::Unit::TestCase
277
+ def setup
278
+ @object = Object.new
279
+ end
280
+
281
+ def test_should_call_if_true
282
+ callback = StateMachine::Callback.new(:before, :if => lambda {true}, :do => lambda {})
283
+ assert callback.call(@object)
284
+ end
285
+
286
+ def test_should_not_call_if_false
287
+ callback = StateMachine::Callback.new(:before, :if => lambda {false}, :do => lambda {})
288
+ assert !callback.call(@object)
289
+ end
290
+ end
291
+
292
+ class CallbackWithUnlessConditionTest < Test::Unit::TestCase
293
+ def setup
294
+ @object = Object.new
295
+ end
296
+
297
+ def test_should_call_if_false
298
+ callback = StateMachine::Callback.new(:before, :unless => lambda {false}, :do => lambda {})
299
+ assert callback.call(@object)
300
+ end
301
+
302
+ def test_should_not_call_if_true
303
+ callback = StateMachine::Callback.new(:before, :unless => lambda {true}, :do => lambda {})
304
+ assert !callback.call(@object)
305
+ end
306
+ end
307
+
308
+ class CallbackWithoutTerminatorTest < Test::Unit::TestCase
309
+ def setup
310
+ @object = Object.new
311
+ end
312
+
313
+ def test_should_not_halt_if_result_is_false
314
+ callback = StateMachine::Callback.new(:before, :do => lambda {false}, :terminator => nil)
315
+ assert_nothing_thrown { callback.call(@object) }
316
+ end
317
+ end
318
+
319
+ class CallbackWithTerminatorTest < Test::Unit::TestCase
320
+ def setup
321
+ @object = Object.new
322
+ end
323
+
324
+ def test_should_not_halt_if_terminator_does_not_match
325
+ callback = StateMachine::Callback.new(:before, :do => lambda {false}, :terminator => lambda {|result| result == true})
326
+ assert_nothing_thrown { callback.call(@object) }
327
+ end
328
+
329
+ def test_should_halt_if_terminator_matches
330
+ callback = StateMachine::Callback.new(:before, :do => lambda {false}, :terminator => lambda {|result| result == false})
331
+ assert_throws(:halt) { callback.call(@object) }
332
+ end
333
+
334
+ def test_should_halt_if_terminator_matches_any_method
335
+ callback = StateMachine::Callback.new(:before, :do => [lambda {true}, lambda {false}], :terminator => lambda {|result| result == false})
336
+ assert_throws(:halt) { callback.call(@object) }
337
+ end
338
+ end
339
+
340
+ class CallbackWithoutArgumentsTest < Test::Unit::TestCase
341
+ def setup
342
+ @callback = StateMachine::Callback.new(:before, :do => lambda {|object| @arg = object})
343
+
344
+ @object = Object.new
345
+ @callback.call(@object, {}, 1, 2, 3)
346
+ end
347
+
348
+ def test_should_call_method_with_object_as_argument
349
+ assert_equal @object, @arg
350
+ end
351
+ end
352
+
353
+ class CallbackWithArgumentsTest < Test::Unit::TestCase
354
+ def setup
355
+ @callback = StateMachine::Callback.new(:before, :do => lambda {|*args| @args = args})
356
+
357
+ @object = Object.new
358
+ @callback.call(@object, {}, 1, 2, 3)
359
+ end
360
+
361
+ def test_should_call_method_with_all_arguments
362
+ assert_equal [@object, 1, 2, 3], @args
363
+ end
364
+ end
365
+
366
+ class CallbackWithUnboundMethodTest < Test::Unit::TestCase
367
+ def setup
368
+ @callback = StateMachine::Callback.new(:before, :do => lambda {|*args| @context = args.unshift(self)})
369
+
370
+ @object = Object.new
371
+ @callback.call(@object, {}, 1, 2, 3)
372
+ end
373
+
374
+ def test_should_call_method_outside_the_context_of_the_object
375
+ assert_equal [self, @object, 1, 2, 3], @context
376
+ end
377
+ end
378
+
379
+ class CallbackWithBoundMethodTest < Test::Unit::TestCase
380
+ def setup
381
+ @object = Object.new
382
+ end
383
+
384
+ def test_should_call_method_within_the_context_of_the_object_for_block_methods
385
+ context = nil
386
+ callback = StateMachine::Callback.new(:before, :do => lambda {|*args| context = [self] + args}, :bind_to_object => true)
387
+ callback.call(@object, {}, 1, 2, 3)
388
+
389
+ assert_equal [@object, 1, 2, 3], context
390
+ end
391
+
392
+ def test_should_ignore_option_for_symbolic_methods
393
+ class << @object
394
+ attr_reader :context
395
+
396
+ def after_ignite(*args)
397
+ @context = args
398
+ end
399
+ end
400
+
401
+ callback = StateMachine::Callback.new(:before, :do => :after_ignite, :bind_to_object => true)
402
+ callback.call(@object)
403
+
404
+ assert_equal [], @object.context
405
+ end
406
+
407
+ def test_should_ignore_option_for_string_methods
408
+ callback = StateMachine::Callback.new(:before, :do => '[1, 2, 3]', :bind_to_object => true)
409
+ assert callback.call(@object)
410
+ end
411
+ end
412
+
413
+ class CallbackWithMultipleBoundMethodsTest < Test::Unit::TestCase
414
+ def setup
415
+ @object = Object.new
416
+
417
+ first_context = nil
418
+ second_context = nil
419
+
420
+ @callback = StateMachine::Callback.new(:before, :do => [lambda {first_context = self}, lambda {second_context = self}], :bind_to_object => true)
421
+ @callback.call(@object)
422
+
423
+ @first_context = first_context
424
+ @second_context = second_context
425
+ end
426
+
427
+ def test_should_call_each_method_within_the_context_of_the_object
428
+ assert_equal @object, @first_context
429
+ assert_equal @object, @second_context
430
+ end
431
+ end
432
+
433
+ class CallbackWithApplicationBoundObjectTest < Test::Unit::TestCase
434
+ def setup
435
+ @original_bind_to_object = StateMachine::Callback.bind_to_object
436
+ StateMachine::Callback.bind_to_object = true
437
+
438
+ context = nil
439
+ @callback = StateMachine::Callback.new(:before, :do => lambda {|*args| context = self})
440
+
441
+ @object = Object.new
442
+ @callback.call(@object)
443
+ @context = context
444
+ end
445
+
446
+ def test_should_call_method_within_the_context_of_the_object
447
+ assert_equal @object, @context
448
+ end
449
+
450
+ def teardown
451
+ StateMachine::Callback.bind_to_object = @original_bind_to_object
452
+ end
453
+ end
454
+
455
+ class CallbackWithBoundMethodAndArgumentsTest < Test::Unit::TestCase
456
+ def setup
457
+ @object = Object.new
458
+ end
459
+
460
+ def test_should_include_single_argument_if_specified
461
+ context = nil
462
+ callback = StateMachine::Callback.new(:before, :do => lambda {|arg1| context = [arg1]}, :bind_to_object => true)
463
+ callback.call(@object, {}, 1)
464
+ assert_equal [1], context
465
+ end
466
+
467
+ def test_should_include_multiple_arguments_if_specified
468
+ context = nil
469
+ callback = StateMachine::Callback.new(:before, :do => lambda {|arg1, arg2, arg3| context = [arg1, arg2, arg3]}, :bind_to_object => true)
470
+ callback.call(@object, {}, 1, 2, 3)
471
+ assert_equal [1, 2, 3], context
472
+ end
473
+
474
+ def test_should_include_arguments_if_splat_used
475
+ context = nil
476
+ callback = StateMachine::Callback.new(:before, :do => lambda {|*args| context = args}, :bind_to_object => true)
477
+ callback.call(@object, {}, 1, 2, 3)
478
+ assert_equal [1, 2, 3], context
479
+ end
480
+ end
481
+
482
+ class CallbackWithApplicationTerminatorTest < Test::Unit::TestCase
483
+ def setup
484
+ @original_terminator = StateMachine::Callback.bind_to_object
485
+ StateMachine::Callback.terminator = lambda {|result| result == false}
486
+
487
+ @object = Object.new
488
+ end
489
+
490
+ def test_should_not_halt_if_terminator_does_not_match
491
+ callback = StateMachine::Callback.new(:before, :do => lambda {true})
492
+ assert_nothing_thrown { callback.call(@object) }
493
+ end
494
+
495
+ def test_should_halt_if_terminator_matches
496
+ callback = StateMachine::Callback.new(:before, :do => lambda {false})
497
+ assert_throws(:halt) { callback.call(@object) }
498
+ end
499
+
500
+ def teardown
501
+ StateMachine::Callback.bind_to_object = @original_bind_to_object
502
+ end
503
+ end
504
+
505
+ class CallbackWithAroundTypeAndBlockTest < Test::Unit::TestCase
506
+ def setup
507
+ @object = Object.new
508
+ @callbacks = []
509
+ end
510
+
511
+ def test_should_evaluate_before_without_after
512
+ callback = StateMachine::Callback.new(:around, lambda {|*args| block = args.pop; @args = args; block.call})
513
+ assert callback.call(@object)
514
+ assert_equal [@object], @args
515
+ end
516
+
517
+ def test_should_evaluate_after_without_before
518
+ callback = StateMachine::Callback.new(:around, lambda {|*args| block = args.pop; block.call; @args = args})
519
+ assert callback.call(@object)
520
+ assert_equal [@object], @args
521
+ end
522
+
523
+ def test_should_halt_if_not_yielded
524
+ callback = StateMachine::Callback.new(:around, lambda {|block|})
525
+ assert_throws(:halt) { callback.call(@object) }
526
+ end
527
+
528
+ def test_should_call_block_after_before
529
+ callback = StateMachine::Callback.new(:around, lambda {|block| @callbacks << :before; block.call})
530
+ assert callback.call(@object) { @callbacks << :block }
531
+ assert_equal [:before, :block], @callbacks
532
+ end
533
+
534
+ def test_should_call_block_before_after
535
+ @callbacks = []
536
+ callback = StateMachine::Callback.new(:around, lambda {|block| block.call; @callbacks << :after})
537
+ assert callback.call(@object) { @callbacks << :block }
538
+ assert_equal [:block, :after], @callbacks
539
+ end
540
+
541
+ def test_should_halt_if_block_halts
542
+ callback = StateMachine::Callback.new(:around, lambda {|block| block.call; @callbacks << :after})
543
+ assert_throws(:halt) { callback.call(@object) { throw :halt } }
544
+ assert_equal [], @callbacks
545
+ end
546
+ end
547
+
548
+ class CallbackWithAroundTypeAndMultipleMethodsTest < Test::Unit::TestCase
549
+ def setup
550
+ @callback = StateMachine::Callback.new(:around, :run_1, :run_2)
551
+
552
+ class << @object = Object.new
553
+ attr_accessor :before_callbacks
554
+ attr_accessor :after_callbacks
555
+
556
+ def run_1
557
+ (@before_callbacks ||= []) << :run_1
558
+ yield
559
+ (@after_callbacks ||= []) << :run_1
560
+ end
561
+
562
+ def run_2
563
+ (@before_callbacks ||= []) << :run_2
564
+ yield
565
+ (@after_callbacks ||= []) << :run_2
566
+ end
567
+ end
568
+ end
569
+
570
+ def test_should_succeed
571
+ assert @callback.call(@object)
572
+ end
573
+
574
+ def test_should_evaluate_before_callbacks_in_order
575
+ @callback.call(@object)
576
+ assert_equal [:run_1, :run_2], @object.before_callbacks
577
+ end
578
+
579
+ def test_should_evaluate_after_callbacks_in_reverse_order
580
+ @callback.call(@object)
581
+ assert_equal [:run_2, :run_1], @object.after_callbacks
582
+ end
583
+
584
+ def test_should_call_block_after_before_callbacks
585
+ @callback.call(@object) { (@object.before_callbacks ||= []) << :block }
586
+ assert_equal [:run_1, :run_2, :block], @object.before_callbacks
587
+ end
588
+
589
+ def test_should_call_block_before_after_callbacks
590
+ @callback.call(@object) { (@object.after_callbacks ||= []) << :block }
591
+ assert_equal [:block, :run_2, :run_1], @object.after_callbacks
592
+ end
593
+
594
+ def test_should_halt_if_first_doesnt_yield
595
+ class << @object
596
+ def run_1
597
+ (@before_callbacks ||= []) << :run_1
598
+ end
599
+ end
600
+
601
+ catch(:halt) do
602
+ @callback.call(@object) { (@object.before_callbacks ||= []) << :block }
603
+ end
604
+
605
+ assert_equal [:run_1], @object.before_callbacks
606
+ assert_nil @object.after_callbacks
607
+ end
608
+
609
+ def test_should_halt_if_last_doesnt_yield
610
+ class << @object
611
+ def run_2
612
+ (@before_callbacks ||= []) << :run_2
613
+ end
614
+ end
615
+
616
+ catch(:halt) { @callback.call(@object) }
617
+ assert_equal [:run_1, :run_2], @object.before_callbacks
618
+ assert_nil @object.after_callbacks
619
+ end
620
+
621
+ def test_should_not_evaluate_further_methods_if_after_halts
622
+ class << @object
623
+ def run_2
624
+ (@before_callbacks ||= []) << :run_2
625
+ yield
626
+ (@after_callbacks ||= []) << :run_2
627
+ throw :halt
628
+ end
629
+ end
630
+
631
+ catch(:halt) { @callback.call(@object) }
632
+ assert_equal [:run_1, :run_2], @object.before_callbacks
633
+ assert_equal [:run_2], @object.after_callbacks
634
+ end
635
+ end
636
+
637
+ class CallbackWithAroundTypeAndArgumentsTest < Test::Unit::TestCase
638
+ def setup
639
+ @object = Object.new
640
+ end
641
+
642
+ def test_should_include_object_if_specified
643
+ callback = StateMachine::Callback.new(:around, lambda {|object, block| @args = [object]; block.call})
644
+ callback.call(@object)
645
+ assert_equal [@object], @args
646
+ end
647
+
648
+ def test_should_include_arguments_if_specified
649
+ callback = StateMachine::Callback.new(:around, lambda {|object, arg1, arg2, arg3, block| @args = [object, arg1, arg2, arg3]; block.call})
650
+ callback.call(@object, {}, 1, 2, 3)
651
+ assert_equal [@object, 1, 2, 3], @args
652
+ end
653
+
654
+ def test_should_include_arguments_if_splat_used
655
+ callback = StateMachine::Callback.new(:around, lambda {|*args| block = args.pop; @args = args; block.call})
656
+ callback.call(@object, {}, 1, 2, 3)
657
+ assert_equal [@object, 1, 2, 3], @args
658
+ end
659
+ end
660
+
661
+ class CallbackWithAroundTypeAndTerminatorTest < Test::Unit::TestCase
662
+ def setup
663
+ @object = Object.new
664
+ end
665
+
666
+ def test_should_not_halt_if_terminator_does_not_match
667
+ callback = StateMachine::Callback.new(:around, :do => lambda {|block| block.call(false); false}, :terminator => lambda {|result| result == true})
668
+ assert_nothing_thrown { callback.call(@object) }
669
+ end
670
+
671
+ def test_should_not_halt_if_terminator_matches
672
+ callback = StateMachine::Callback.new(:around, :do => lambda {|block| block.call(false); false}, :terminator => lambda {|result| result == false})
673
+ assert_nothing_thrown { callback.call(@object) }
674
+ end
675
+ end
676
+
677
+ class CallbackWithAroundTypeAndBoundMethodTest < Test::Unit::TestCase
678
+ def setup
679
+ @object = Object.new
680
+ end
681
+
682
+ def test_should_call_method_within_the_context_of_the_object
683
+ context = nil
684
+ callback = StateMachine::Callback.new(:around, :do => lambda {|block| context = self; block.call}, :bind_to_object => true)
685
+ callback.call(@object, {}, 1, 2, 3)
686
+
687
+ assert_equal @object, context
688
+ end
689
+
690
+ def test_should_include_arguments_if_specified
691
+ context = nil
692
+ callback = StateMachine::Callback.new(:around, :do => lambda {|*args| block = args.pop; context = args; block.call}, :bind_to_object => true)
693
+ callback.call(@object, {}, 1, 2, 3)
694
+
695
+ assert_equal [1, 2, 3], context
696
+ end
697
+ end
698
+
699
+ class CallbackSuccessMatcherTest < Test::Unit::TestCase
700
+ def setup
701
+ @object = Object.new
702
+ end
703
+
704
+ def test_should_match_if_not_specified
705
+ callback = StateMachine::Callback.new(:before) {}
706
+ assert callback.matches_success?(true)
707
+ end
708
+
709
+ def test_should_match_if_true_and_not_including_failures
710
+ callback = StateMachine::Callback.new(:before, :include_failures => false) {}
711
+ assert callback.matches_success?(true)
712
+ end
713
+
714
+ def test_should_match_if_true_and_including_failures
715
+ callback = StateMachine::Callback.new(:before, :include_failures => true) {}
716
+ assert callback.matches_success?(true)
717
+ end
718
+
719
+ def test_should_not_match_if_false_and_not_including_failures
720
+ callback = StateMachine::Callback.new(:before, :include_failures => false) {}
721
+ assert !callback.matches_success?(false)
722
+ end
723
+
724
+ def test_Should_match_if_false_and_including_failures
725
+ callback = StateMachine::Callback.new(:before, :include_failures => true) {}
726
+ assert callback.matches_success?(false)
727
+ end
728
+ end