state_machines 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/README.md +25 -0
  4. data/Rakefile +10 -1
  5. data/lib/state_machines/branch.rb +0 -4
  6. data/lib/state_machines/core.rb +23 -5
  7. data/lib/state_machines/error.rb +81 -2
  8. data/lib/state_machines/event.rb +2 -20
  9. data/lib/state_machines/event_collection.rb +25 -27
  10. data/lib/state_machines/extensions.rb +34 -34
  11. data/lib/state_machines/integrations.rb +98 -90
  12. data/lib/state_machines/integrations/base.rb +11 -60
  13. data/lib/state_machines/matcher.rb +0 -2
  14. data/lib/state_machines/node_collection.rb +0 -2
  15. data/lib/state_machines/path_collection.rb +0 -2
  16. data/lib/state_machines/state.rb +0 -3
  17. data/lib/state_machines/state_collection.rb +17 -19
  18. data/lib/state_machines/state_context.rb +1 -6
  19. data/lib/state_machines/transition.rb +0 -56
  20. data/lib/state_machines/version.rb +1 -1
  21. data/spec/spec_helper.rb +1 -0
  22. data/spec/state_machines/assertions_spec.rb +31 -0
  23. data/spec/state_machines/branch_spec.rb +827 -0
  24. data/spec/state_machines/callbacks_spec.rb +706 -0
  25. data/spec/state_machines/errors_spec.rb +1 -0
  26. data/spec/state_machines/event_collection_spec.rb +401 -0
  27. data/spec/state_machines/event_spec.rb +1140 -0
  28. data/spec/{helpers → state_machines}/helper_spec.rb +0 -0
  29. data/spec/state_machines/integration_base_spec.rb +12 -0
  30. data/spec/state_machines/integration_spec.rb +132 -0
  31. data/spec/state_machines/invalid_event_spec.rb +19 -0
  32. data/spec/state_machines/invalid_parallel_transition_spec.rb +18 -0
  33. data/spec/state_machines/invalid_transition_spec.rb +114 -0
  34. data/spec/state_machines/machine_collection_spec.rb +606 -0
  35. data/spec/{machine_spec.rb → state_machines/machine_spec.rb} +11 -2
  36. data/spec/{matcher_helpers_spec.rb → state_machines/matcher_helpers_spec.rb} +0 -0
  37. data/spec/{matcher_spec.rb → state_machines/matcher_spec.rb} +0 -0
  38. data/spec/{node_collection_spec.rb → state_machines/node_collection_spec.rb} +0 -0
  39. data/spec/{path_collection_spec.rb → state_machines/path_collection_spec.rb} +0 -0
  40. data/spec/{path_spec.rb → state_machines/path_spec.rb} +0 -0
  41. data/spec/{state_collection_spec.rb → state_machines/state_collection_spec.rb} +0 -0
  42. data/spec/{state_context_spec.rb → state_machines/state_context_spec.rb} +0 -0
  43. data/spec/{state_machine_spec.rb → state_machines/state_machine_spec.rb} +0 -0
  44. data/spec/{state_spec.rb → state_machines/state_spec.rb} +0 -0
  45. data/spec/{transition_collection_spec.rb → state_machines/transition_collection_spec.rb} +0 -0
  46. data/spec/{transition_spec.rb → state_machines/transition_spec.rb} +0 -0
  47. data/spec/support/migration_helpers.rb +9 -0
  48. data/state_machines.gemspec +3 -1
  49. metadata +68 -45
  50. data/lib/state_machines/yard.rb +0 -8
  51. data/spec/errors/default_spec.rb +0 -14
  52. data/spec/errors/with_message_spec.rb +0 -39
@@ -0,0 +1,706 @@
1
+ require 'spec_helper'
2
+
3
+ describe StateMachines::Callback do
4
+
5
+ context 'Default' do
6
+ it 'should_raise_exception_if_invalid_type_specified' do
7
+ assert_raise(ArgumentError) { StateMachines::Callback.new(:invalid) {} }
8
+ end
9
+
10
+ it 'should_not_raise_exception_if_using_before_type' do
11
+ assert_nothing_raised { StateMachines::Callback.new(:before) {} }
12
+ end
13
+
14
+ it 'should_not_raise_exception_if_using_after_type' do
15
+ assert_nothing_raised { StateMachines::Callback.new(:after) {} }
16
+ end
17
+
18
+ it 'should_not_raise_exception_if_using_around_type' do
19
+ assert_nothing_raised { StateMachines::Callback.new(:around) {} }
20
+ end
21
+
22
+ it 'should_not_raise_exception_if_using_failure_type' do
23
+ assert_nothing_raised { StateMachines::Callback.new(:failure) {} }
24
+ end
25
+
26
+ it 'should_raise_exception_if_no_methods_specified' do
27
+ assert_raise(ArgumentError) { StateMachines::Callback.new(:before) }
28
+ end
29
+
30
+ it 'should_not_raise_exception_if_method_specified_in_do_option' do
31
+ assert_nothing_raised { StateMachines::Callback.new(:before, :do => :run) }
32
+ end
33
+
34
+ it 'should_not_raise_exception_if_method_specified_as_argument' do
35
+ assert_nothing_raised { StateMachines::Callback.new(:before, :run) }
36
+ end
37
+
38
+ it 'should_not_raise_exception_if_method_specified_as_block' do
39
+ assert_nothing_raised { StateMachines::Callback.new(:before, :run) {} }
40
+ end
41
+
42
+ it 'should_not_raise_exception_if_implicit_option_specified' do
43
+ assert_nothing_raised { StateMachines::Callback.new(:before, :do => :run, :invalid => :valid) }
44
+ end
45
+
46
+ it 'should_not_bind_to_objects' do
47
+ assert !StateMachines::Callback.bind_to_object
48
+ end
49
+
50
+ it 'should_not_have_a_terminator' do
51
+ assert_nil StateMachines::Callback.terminator
52
+ end
53
+ end
54
+
55
+ context 'ByDefault' do
56
+ before(:each) do
57
+ @callback = StateMachines::Callback.new(:before) {}
58
+ end
59
+
60
+ it 'should_have_type' do
61
+ assert_equal :before, @callback.type
62
+ end
63
+
64
+ it 'should_not_have_a_terminator' do
65
+ assert_nil @callback.terminator
66
+ end
67
+
68
+ it 'should_have_a_branch_with_all_matcher_requirements' do
69
+ assert_equal StateMachines::AllMatcher.instance, @callback.branch.event_requirement
70
+ assert_equal StateMachines::AllMatcher.instance, @callback.branch.state_requirements.first[:from]
71
+ assert_equal StateMachines::AllMatcher.instance, @callback.branch.state_requirements.first[:to]
72
+ end
73
+
74
+ it 'should_not_have_any_known_states' do
75
+ assert_equal [], @callback.known_states
76
+ end
77
+ end
78
+
79
+ context 'WithMethodArgument' do
80
+ before(:each) do
81
+ @callback = StateMachines::Callback.new(:before, lambda {|*args| @args = args})
82
+
83
+ @object = Object.new
84
+ @result = @callback.call(@object)
85
+ end
86
+
87
+ it 'should_be_successful' do
88
+ assert @result
89
+ end
90
+
91
+ it 'should_call_with_empty_context' do
92
+ assert_equal [@object], @args
93
+ end
94
+ end
95
+
96
+ context 'WithMultipleMethodArguments' do
97
+ before(:each) do
98
+ @callback = StateMachines::Callback.new(:before, :run_1, :run_2)
99
+
100
+ class << @object = Object.new
101
+ attr_accessor :callbacks
102
+
103
+ def run_1
104
+ (@callbacks ||= []) << :run_1
105
+ end
106
+
107
+ def run_2
108
+ (@callbacks ||= []) << :run_2
109
+ end
110
+ end
111
+
112
+ @result = @callback.call(@object)
113
+ end
114
+
115
+ it 'should_be_successful' do
116
+ assert @result
117
+ end
118
+
119
+ it 'should_call_each_callback_in_order' do
120
+ assert_equal [:run_1, :run_2], @object.callbacks
121
+ end
122
+ end
123
+
124
+ context 'WithDoMethod' do
125
+ before(:each) do
126
+ @callback = StateMachines::Callback.new(:before, :do => lambda {|*args| @args = args})
127
+
128
+ @object = Object.new
129
+ @result = @callback.call(@object)
130
+ end
131
+
132
+ it 'should_be_successful' do
133
+ assert @result
134
+ end
135
+
136
+ it 'should_call_with_empty_context' do
137
+ assert_equal [@object], @args
138
+ end
139
+ end
140
+
141
+ context 'WithMultipleDoMethods' do
142
+ before(:each) do
143
+ @callback = StateMachines::Callback.new(:before, :do => [:run_1, :run_2])
144
+
145
+ class << @object = Object.new
146
+ attr_accessor :callbacks
147
+
148
+ def run_1
149
+ (@callbacks ||= []) << :run_1
150
+ end
151
+
152
+ def run_2
153
+ (@callbacks ||= []) << :run_2
154
+ end
155
+ end
156
+
157
+ @result = @callback.call(@object)
158
+ end
159
+
160
+ it 'should_be_successful' do
161
+ assert @result
162
+ end
163
+
164
+ it 'should_call_each_callback_in_order' do
165
+ assert_equal [:run_1, :run_2], @object.callbacks
166
+ end
167
+ end
168
+
169
+ context 'WithBlock' do
170
+ before(:each) do
171
+ @callback = StateMachines::Callback.new(:before) do |*args|
172
+ @args = args
173
+ end
174
+
175
+ @object = Object.new
176
+ @result = @callback.call(@object)
177
+ end
178
+
179
+ it 'should_be_successful' do
180
+ assert @result
181
+ end
182
+
183
+ it 'should_call_with_empty_context' do
184
+ assert_equal [@object], @args
185
+ end
186
+ end
187
+
188
+ context 'WithMixedMethods' do
189
+ before(:each) do
190
+ @callback = StateMachines::Callback.new(:before, :run_argument, :do => :run_do) do |object|
191
+ object.callbacks << :block
192
+ end
193
+
194
+ class << @object = Object.new
195
+ attr_accessor :callbacks
196
+
197
+ def run_argument
198
+ (@callbacks ||= []) << :argument
199
+ end
200
+
201
+ def run_do
202
+ (@callbacks ||= []) << :do
203
+ end
204
+ end
205
+
206
+ @result = @callback.call(@object)
207
+ end
208
+
209
+ it 'should_be_successful' do
210
+ assert @result
211
+ end
212
+
213
+ it 'should_call_each_callback_in_order' do
214
+ assert_equal [:argument, :do, :block], @object.callbacks
215
+ end
216
+ end
217
+
218
+ context 'WithExplicitRequirements' do
219
+ before(:each) do
220
+ @object = Object.new
221
+ @callback = StateMachines::Callback.new(:before, :from => :parked, :to => :idling, :on => :ignite, :do => lambda {})
222
+ end
223
+
224
+ it 'should_call_with_empty_context' do
225
+ assert @callback.call(@object, {})
226
+ end
227
+
228
+ it 'should_not_call_if_from_not_included' do
229
+ assert !@callback.call(@object, :from => :idling)
230
+ end
231
+
232
+ it 'should_not_call_if_to_not_included' do
233
+ assert !@callback.call(@object, :to => :parked)
234
+ end
235
+
236
+ it 'should_not_call_if_on_not_included' do
237
+ assert !@callback.call(@object, :on => :park)
238
+ end
239
+
240
+ it 'should_call_if_all_requirements_met' do
241
+ assert @callback.call(@object, :from => :parked, :to => :idling, :on => :ignite)
242
+ end
243
+
244
+ it 'should_include_in_known_states' do
245
+ assert_equal [:parked, :idling], @callback.known_states
246
+ end
247
+ end
248
+
249
+ context 'WithImplicitRequirements' do
250
+ before(:each) do
251
+ @object = Object.new
252
+ @callback = StateMachines::Callback.new(:before, :parked => :idling, :on => :ignite, :do => lambda {})
253
+ end
254
+
255
+ it 'should_call_with_empty_context' do
256
+ assert @callback.call(@object, {})
257
+ end
258
+
259
+ it 'should_not_call_if_from_not_included' do
260
+ assert !@callback.call(@object, :from => :idling)
261
+ end
262
+
263
+ it 'should_not_call_if_to_not_included' do
264
+ assert !@callback.call(@object, :to => :parked)
265
+ end
266
+
267
+ it 'should_not_call_if_on_not_included' do
268
+ assert !@callback.call(@object, :on => :park)
269
+ end
270
+
271
+ it 'should_call_if_all_requirements_met' do
272
+ assert @callback.call(@object, :from => :parked, :to => :idling, :on => :ignite)
273
+ end
274
+
275
+ it 'should_include_in_known_states' do
276
+ assert_equal [:parked, :idling], @callback.known_states
277
+ end
278
+ end
279
+
280
+ context 'WithIfCondition' do
281
+ before(:each) do
282
+ @object = Object.new
283
+ end
284
+
285
+ it 'should_call_if_true' do
286
+ callback = StateMachines::Callback.new(:before, :if => lambda {true}, :do => lambda {})
287
+ assert callback.call(@object)
288
+ end
289
+
290
+ it 'should_not_call_if_false' do
291
+ callback = StateMachines::Callback.new(:before, :if => lambda {false}, :do => lambda {})
292
+ assert !callback.call(@object)
293
+ end
294
+ end
295
+
296
+ context 'WithUnlessCondition' do
297
+ before(:each) do
298
+ @object = Object.new
299
+ end
300
+
301
+ it 'should_call_if_false' do
302
+ callback = StateMachines::Callback.new(:before, :unless => lambda {false}, :do => lambda {})
303
+ assert callback.call(@object)
304
+ end
305
+
306
+ it 'should_not_call_if_true' do
307
+ callback = StateMachines::Callback.new(:before, :unless => lambda {true}, :do => lambda {})
308
+ assert !callback.call(@object)
309
+ end
310
+ end
311
+
312
+ context 'WithoutTerminator' do
313
+ before(:each) do
314
+ @object = Object.new
315
+ end
316
+
317
+ it 'should_not_halt_if_result_is_false' do
318
+ callback = StateMachines::Callback.new(:before, :do => lambda {false}, :terminator => nil)
319
+ assert_nothing_thrown { callback.call(@object) }
320
+ end
321
+ end
322
+
323
+ context 'WithTerminator' do
324
+ before(:each) do
325
+ @object = Object.new
326
+ end
327
+
328
+ it 'should_not_halt_if_terminator_does_not_match' do
329
+ callback = StateMachines::Callback.new(:before, :do => lambda {false}, :terminator => lambda {|result| result == true})
330
+ assert_nothing_thrown { callback.call(@object) }
331
+ end
332
+
333
+ it 'should_halt_if_terminator_matches' do
334
+ callback = StateMachines::Callback.new(:before, :do => lambda {false}, :terminator => lambda {|result| result == false})
335
+ assert_throws(:halt) { callback.call(@object) }
336
+ end
337
+
338
+ it 'should_halt_if_terminator_matches_any_method' do
339
+ callback = StateMachines::Callback.new(:before, :do => [lambda {true}, lambda {false}], :terminator => lambda {|result| result == false})
340
+ assert_throws(:halt) { callback.call(@object) }
341
+ end
342
+ end
343
+
344
+ context 'WithoutArguments' do
345
+ before(:each) do
346
+ @callback = StateMachines::Callback.new(:before, :do => lambda {|object| @arg = object})
347
+
348
+ @object = Object.new
349
+ @callback.call(@object, {}, 1, 2, 3)
350
+ end
351
+
352
+ it 'should_call_method_with_object_as_argument' do
353
+ assert_equal @object, @arg
354
+ end
355
+ end
356
+
357
+ context 'WithArguments' do
358
+ before(:each) do
359
+ @callback = StateMachines::Callback.new(:before, :do => lambda {|*args| @args = args})
360
+
361
+ @object = Object.new
362
+ @callback.call(@object, {}, 1, 2, 3)
363
+ end
364
+
365
+ it 'should_call_method_with_all_arguments' do
366
+ assert_equal [@object, 1, 2, 3], @args
367
+ end
368
+ end
369
+
370
+ context 'WithUnboundMethod' do
371
+ before(:each) do
372
+ @callback = StateMachines::Callback.new(:before, :do => lambda {|*args| @context = args.unshift(self)})
373
+
374
+ @object = Object.new
375
+ @callback.call(@object, {}, 1, 2, 3)
376
+ end
377
+
378
+ it 'should_call_method_outside_the_context_of_the_object' do
379
+ assert_equal [self, @object, 1, 2, 3], @context
380
+ end
381
+ end
382
+
383
+ context 'WithBoundMethod' do
384
+ before(:each) do
385
+ @object = Object.new
386
+ end
387
+
388
+ it 'should_call_method_within_the_context_of_the_object_for_block_methods' do
389
+ context = nil
390
+ callback = StateMachines::Callback.new(:before, :do => lambda {|*args| context = [self] + args}, :bind_to_object => true)
391
+ callback.call(@object, {}, 1, 2, 3)
392
+
393
+ assert_equal [@object, 1, 2, 3], context
394
+ end
395
+
396
+ it 'should_ignore_option_for_symbolic_methods' do
397
+ class << @object
398
+ attr_reader :context
399
+
400
+ def after_ignite(*args)
401
+ @context = args
402
+ end
403
+ end
404
+
405
+ callback = StateMachines::Callback.new(:before, :do => :after_ignite, :bind_to_object => true)
406
+ callback.call(@object)
407
+
408
+ assert_equal [], @object.context
409
+ end
410
+
411
+ it 'should_ignore_option_for_string_methods' do
412
+ callback = StateMachines::Callback.new(:before, :do => '[1, 2, 3]', :bind_to_object => true)
413
+ assert callback.call(@object)
414
+ end
415
+ end
416
+
417
+ context 'WithMultipleBoundMethods' do
418
+ before(:each) do
419
+ @object = Object.new
420
+
421
+ first_context = nil
422
+ second_context = nil
423
+
424
+ @callback = StateMachines::Callback.new(:before, :do => [lambda {first_context = self}, lambda {second_context = self}], :bind_to_object => true)
425
+ @callback.call(@object)
426
+
427
+ @first_context = first_context
428
+ @second_context = second_context
429
+ end
430
+
431
+ it 'should_call_each_method_within_the_context_of_the_object' do
432
+ assert_equal @object, @first_context
433
+ assert_equal @object, @second_context
434
+ end
435
+ end
436
+
437
+ context 'WithApplicationBoundObject' do
438
+ before(:each) do
439
+ @original_bind_to_object = StateMachines::Callback.bind_to_object
440
+ StateMachines::Callback.bind_to_object = true
441
+
442
+ context = nil
443
+ @callback = StateMachines::Callback.new(:before, :do => lambda {|*args| context = self})
444
+
445
+ @object = Object.new
446
+ @callback.call(@object)
447
+ @context = context
448
+ end
449
+
450
+ it 'should_call_method_within_the_context_of_the_object' do
451
+ assert_equal @object, @context
452
+ end
453
+
454
+ after(:each) do
455
+ StateMachines::Callback.bind_to_object = @original_bind_to_object
456
+ end
457
+ end
458
+
459
+ context 'WithBoundMethodAndArguments' do
460
+ before(:each) do
461
+ @object = Object.new
462
+ end
463
+
464
+ it 'should_include_single_argument_if_specified' do
465
+ context = nil
466
+ callback = StateMachines::Callback.new(:before, :do => lambda {|arg1| context = [arg1]}, :bind_to_object => true)
467
+ callback.call(@object, {}, 1)
468
+ assert_equal [1], context
469
+ end
470
+
471
+ it 'should_include_multiple_arguments_if_specified' do
472
+ context = nil
473
+ callback = StateMachines::Callback.new(:before, :do => lambda {|arg1, arg2, arg3| context = [arg1, arg2, arg3]}, :bind_to_object => true)
474
+ callback.call(@object, {}, 1, 2, 3)
475
+ assert_equal [1, 2, 3], context
476
+ end
477
+
478
+ it 'should_include_arguments_if_splat_used' do
479
+ context = nil
480
+ callback = StateMachines::Callback.new(:before, :do => lambda {|*args| context = args}, :bind_to_object => true)
481
+ callback.call(@object, {}, 1, 2, 3)
482
+ assert_equal [1, 2, 3], context
483
+ end
484
+ end
485
+
486
+ context 'WithApplicationTerminator' do
487
+ before(:each) do
488
+ @original_terminator = StateMachines::Callback.terminator
489
+ StateMachines::Callback.terminator = lambda {|result| result == false}
490
+
491
+ @object = Object.new
492
+ end
493
+
494
+ it 'should_not_halt_if_terminator_does_not_match' do
495
+ callback = StateMachines::Callback.new(:before, :do => lambda {true})
496
+ assert_nothing_thrown { callback.call(@object) }
497
+ end
498
+
499
+ it 'should_halt_if_terminator_matches' do
500
+ callback = StateMachines::Callback.new(:before, :do => lambda {false})
501
+ assert_throws(:halt) { callback.call(@object) }
502
+ end
503
+
504
+ def teardown
505
+ StateMachines::Callback.terminator = @original_terminator
506
+ end
507
+ end
508
+
509
+ context 'WithAroundTypeAndBlock' do
510
+ before(:each) do
511
+ @object = Object.new
512
+ @callbacks = []
513
+ end
514
+
515
+ it 'should_evaluate_before_without_after' do
516
+ callback = StateMachines::Callback.new(:around, lambda {|*args| block = args.pop; @args = args; block.call})
517
+ assert callback.call(@object)
518
+ assert_equal [@object], @args
519
+ end
520
+
521
+ it 'should_evaluate_after_without_before' do
522
+ callback = StateMachines::Callback.new(:around, lambda {|*args| block = args.pop; block.call; @args = args})
523
+ assert callback.call(@object)
524
+ assert_equal [@object], @args
525
+ end
526
+
527
+ it 'should_halt_if_not_yielded' do
528
+ callback = StateMachines::Callback.new(:around, lambda {|block|})
529
+ assert_throws(:halt) { callback.call(@object) }
530
+ end
531
+
532
+ it 'should_call_block_after_before' do
533
+ callback = StateMachines::Callback.new(:around, lambda {|block| @callbacks << :before; block.call})
534
+ assert callback.call(@object) { @callbacks << :block }
535
+ assert_equal [:before, :block], @callbacks
536
+ end
537
+
538
+ it 'should_call_block_before_after' do
539
+ @callbacks = []
540
+ callback = StateMachines::Callback.new(:around, lambda {|block| block.call; @callbacks << :after})
541
+ assert callback.call(@object) { @callbacks << :block }
542
+ assert_equal [:block, :after], @callbacks
543
+ end
544
+
545
+ it 'should_halt_if_block_halts' do
546
+ callback = StateMachines::Callback.new(:around, lambda {|block| block.call; @callbacks << :after})
547
+ assert_throws(:halt) { callback.call(@object) { throw :halt } }
548
+ assert_equal [], @callbacks
549
+ end
550
+ end
551
+
552
+ context 'WithAroundTypeAndMultipleMethods' do
553
+ before(:each) do
554
+ @callback = StateMachines::Callback.new(:around, :run_1, :run_2)
555
+
556
+ class << @object = Object.new
557
+ attr_accessor :before_callbacks
558
+ attr_accessor :after_callbacks
559
+
560
+ def run_1
561
+ (@before_callbacks ||= []) << :run_1
562
+ yield
563
+ (@after_callbacks ||= []) << :run_1
564
+ end
565
+
566
+ def run_2
567
+ (@before_callbacks ||= []) << :run_2
568
+ yield
569
+ (@after_callbacks ||= []) << :run_2
570
+ end
571
+ end
572
+ end
573
+
574
+ it 'should_succeed' do
575
+ assert @callback.call(@object)
576
+ end
577
+
578
+ it 'should_evaluate_before_callbacks_in_order' do
579
+ @callback.call(@object)
580
+ assert_equal [:run_1, :run_2], @object.before_callbacks
581
+ end
582
+
583
+ it 'should_evaluate_after_callbacks_in_reverse_order' do
584
+ @callback.call(@object)
585
+ assert_equal [:run_2, :run_1], @object.after_callbacks
586
+ end
587
+
588
+ it 'should_call_block_after_before_callbacks' do
589
+ @callback.call(@object) { (@object.before_callbacks ||= []) << :block }
590
+ assert_equal [:run_1, :run_2, :block], @object.before_callbacks
591
+ end
592
+
593
+ it 'should_call_block_before_after_callbacks' do
594
+ @callback.call(@object) { (@object.after_callbacks ||= []) << :block }
595
+ assert_equal [:block, :run_2, :run_1], @object.after_callbacks
596
+ end
597
+
598
+ it 'should_halt_if_first_doesnt_yield' do
599
+ class << @object
600
+ remove_method :run_1
601
+ def run_1
602
+ (@before_callbacks ||= []) << :run_1
603
+ end
604
+ end
605
+
606
+ catch(:halt) do
607
+ @callback.call(@object) { (@object.before_callbacks ||= []) << :block }
608
+ end
609
+
610
+ assert_equal [:run_1], @object.before_callbacks
611
+ assert_nil @object.after_callbacks
612
+ end
613
+
614
+ it 'should_halt_if_last_doesnt_yield' do
615
+ class << @object
616
+ remove_method :run_2
617
+ def run_2
618
+ (@before_callbacks ||= []) << :run_2
619
+ end
620
+ end
621
+
622
+ catch(:halt) { @callback.call(@object) }
623
+ assert_equal [:run_1, :run_2], @object.before_callbacks
624
+ assert_nil @object.after_callbacks
625
+ end
626
+
627
+ it 'should_not_evaluate_further_methods_if_after_halts' do
628
+ class << @object
629
+ remove_method :run_2
630
+ def run_2
631
+ (@before_callbacks ||= []) << :run_2
632
+ yield
633
+ (@after_callbacks ||= []) << :run_2
634
+ throw :halt
635
+ end
636
+ end
637
+
638
+ catch(:halt) { @callback.call(@object) }
639
+ assert_equal [:run_1, :run_2], @object.before_callbacks
640
+ assert_equal [:run_2], @object.after_callbacks
641
+ end
642
+ end
643
+
644
+ context 'WithAroundTypeAndArguments' do
645
+ before(:each) do
646
+ @object = Object.new
647
+ end
648
+
649
+ it 'should_include_object_if_specified' do
650
+ callback = StateMachines::Callback.new(:around, lambda {|object, block| @args = [object]; block.call})
651
+ callback.call(@object)
652
+ assert_equal [@object], @args
653
+ end
654
+
655
+ it 'should_include_arguments_if_specified' do
656
+ callback = StateMachines::Callback.new(:around, lambda {|object, arg1, arg2, arg3, block| @args = [object, arg1, arg2, arg3]; block.call})
657
+ callback.call(@object, {}, 1, 2, 3)
658
+ assert_equal [@object, 1, 2, 3], @args
659
+ end
660
+
661
+ it 'should_include_arguments_if_splat_used' do
662
+ callback = StateMachines::Callback.new(:around, lambda {|*args| block = args.pop; @args = args; block.call})
663
+ callback.call(@object, {}, 1, 2, 3)
664
+ assert_equal [@object, 1, 2, 3], @args
665
+ end
666
+ end
667
+
668
+ context 'WithAroundTypeAndTerminator' do
669
+ before(:each) do
670
+ @object = Object.new
671
+ end
672
+
673
+ it 'should_not_halt_if_terminator_does_not_match' do
674
+ callback = StateMachines::Callback.new(:around, :do => lambda {|block| block.call(false); false}, :terminator => lambda {|result| result == true})
675
+ assert_nothing_thrown { callback.call(@object) }
676
+ end
677
+
678
+ it 'should_not_halt_if_terminator_matches' do
679
+ callback = StateMachines::Callback.new(:around, :do => lambda {|block| block.call(false); false}, :terminator => lambda {|result| result == false})
680
+ assert_nothing_thrown { callback.call(@object) }
681
+ end
682
+ end
683
+
684
+ context 'WithAroundTypeAndBoundMethod' do
685
+ before(:each) do
686
+ @object = Object.new
687
+ end
688
+
689
+ it 'should_call_method_within_the_context_of_the_object' do
690
+ context = nil
691
+ callback = StateMachines::Callback.new(:around, :do => lambda {|block| context = self; block.call}, :bind_to_object => true)
692
+ callback.call(@object, {}, 1, 2, 3)
693
+
694
+ assert_equal @object, context
695
+ end
696
+
697
+ it 'should_include_arguments_if_specified' do
698
+ context = nil
699
+ callback = StateMachines::Callback.new(:around, :do => lambda {|*args| block = args.pop; context = args; block.call}, :bind_to_object => true)
700
+ callback.call(@object, {}, 1, 2, 3)
701
+
702
+ assert_equal [1, 2, 3], context
703
+ end
704
+ end
705
+
706
+ end