state_machine 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +17 -0
- data/LICENSE +1 -1
- data/README.rdoc +162 -23
- data/Rakefile +3 -18
- data/lib/state_machine.rb +3 -4
- data/lib/state_machine/callback.rb +65 -13
- data/lib/state_machine/eval_helpers.rb +20 -4
- data/lib/state_machine/initializers.rb +4 -0
- data/lib/state_machine/initializers/merb.rb +1 -0
- data/lib/state_machine/initializers/rails.rb +7 -0
- data/lib/state_machine/integrations.rb +21 -6
- data/lib/state_machine/integrations/active_model.rb +414 -0
- data/lib/state_machine/integrations/active_model/locale.rb +11 -0
- data/lib/state_machine/integrations/{active_record → active_model}/observer.rb +7 -7
- data/lib/state_machine/integrations/active_record.rb +65 -129
- data/lib/state_machine/integrations/active_record/locale.rb +4 -11
- data/lib/state_machine/integrations/data_mapper.rb +24 -6
- data/lib/state_machine/integrations/data_mapper/observer.rb +36 -0
- data/lib/state_machine/integrations/mongo_mapper.rb +295 -0
- data/lib/state_machine/integrations/sequel.rb +33 -7
- data/lib/state_machine/machine.rb +121 -23
- data/lib/state_machine/machine_collection.rb +12 -103
- data/lib/state_machine/transition.rb +125 -164
- data/lib/state_machine/transition_collection.rb +244 -0
- data/lib/tasks/state_machine.rb +12 -15
- data/test/functional/state_machine_test.rb +11 -1
- data/test/unit/callback_test.rb +305 -32
- data/test/unit/eval_helpers_test.rb +103 -1
- data/test/unit/event_test.rb +2 -1
- data/test/unit/guard_test.rb +2 -1
- data/test/unit/integrations/active_model_test.rb +909 -0
- data/test/unit/integrations/active_record_test.rb +1542 -1292
- data/test/unit/integrations/data_mapper_test.rb +1369 -1041
- data/test/unit/integrations/mongo_mapper_test.rb +1349 -0
- data/test/unit/integrations/sequel_test.rb +1214 -985
- data/test/unit/integrations_test.rb +8 -0
- data/test/unit/machine_collection_test.rb +140 -513
- data/test/unit/machine_test.rb +212 -10
- data/test/unit/state_test.rb +2 -1
- data/test/unit/transition_collection_test.rb +2098 -0
- data/test/unit/transition_test.rb +704 -552
- metadata +16 -3
data/test/unit/machine_test.rb
CHANGED
@@ -69,6 +69,10 @@ class MachineByDefaultTest < Test::Unit::TestCase
|
|
69
69
|
assert_equal 'cannot transition via "park"', @machine.generate_message(:invalid_transition, [[:event, :park]])
|
70
70
|
end
|
71
71
|
|
72
|
+
def test_should_not_be_extended_by_the_active_model_integration
|
73
|
+
assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::ActiveModel)
|
74
|
+
end
|
75
|
+
|
72
76
|
def test_should_not_be_extended_by_the_active_record_integration
|
73
77
|
assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::ActiveRecord)
|
74
78
|
end
|
@@ -77,6 +81,10 @@ class MachineByDefaultTest < Test::Unit::TestCase
|
|
77
81
|
assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::DataMapper)
|
78
82
|
end
|
79
83
|
|
84
|
+
def test_should_not_be_extended_by_the_mongo_mapper_integration
|
85
|
+
assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::MongoMapper)
|
86
|
+
end
|
87
|
+
|
80
88
|
def test_should_not_be_extended_by_the_sequel_integration
|
81
89
|
assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::Sequel)
|
82
90
|
end
|
@@ -216,6 +224,12 @@ class MachineWithStaticInitialStateTest < Test::Unit::TestCase
|
|
216
224
|
assert_equal 'parked', @machine.initial_state(object).value
|
217
225
|
end
|
218
226
|
|
227
|
+
def test_should_write_to_attribute_when_initializing_state
|
228
|
+
object = @klass.allocate
|
229
|
+
@machine.initialize_state(object)
|
230
|
+
assert_equal 'parked', object.state
|
231
|
+
end
|
232
|
+
|
219
233
|
def test_should_set_initial_on_state_object
|
220
234
|
assert @machine.state(:parked).initial
|
221
235
|
end
|
@@ -276,6 +290,13 @@ class MachineWithDynamicInitialStateTest < Test::Unit::TestCase
|
|
276
290
|
assert_equal :idling, @machine.initial_state(@object).name
|
277
291
|
end
|
278
292
|
|
293
|
+
def test_should_write_to_attribute_when_initializing_state
|
294
|
+
object = @klass.allocate
|
295
|
+
object.initial_state = :parked
|
296
|
+
@machine.initialize_state(object)
|
297
|
+
assert_equal 'parked', object.state
|
298
|
+
end
|
299
|
+
|
279
300
|
def test_should_set_initial_state_on_created_object
|
280
301
|
assert_equal 'default', @object.state
|
281
302
|
end
|
@@ -435,7 +456,39 @@ class MachineWithIntegrationTest < Test::Unit::TestCase
|
|
435
456
|
end
|
436
457
|
end
|
437
458
|
|
438
|
-
class
|
459
|
+
class MachineWithActionUndefinedTest < Test::Unit::TestCase
|
460
|
+
def setup
|
461
|
+
@klass = Class.new
|
462
|
+
@machine = StateMachine::Machine.new(@klass, :action => :save)
|
463
|
+
@object = @klass.new
|
464
|
+
end
|
465
|
+
|
466
|
+
def test_should_define_an_event_attribute_reader
|
467
|
+
assert @object.respond_to?(:state_event)
|
468
|
+
end
|
469
|
+
|
470
|
+
def test_should_define_an_event_attribute_writer
|
471
|
+
assert @object.respond_to?(:state_event=)
|
472
|
+
end
|
473
|
+
|
474
|
+
def test_should_define_an_event_transition_attribute_reader
|
475
|
+
assert @object.respond_to?(:state_event_transition)
|
476
|
+
end
|
477
|
+
|
478
|
+
def test_should_define_an_event_transition_attribute_writer
|
479
|
+
assert @object.respond_to?(:state_event_transition=)
|
480
|
+
end
|
481
|
+
|
482
|
+
def test_should_not_define_action
|
483
|
+
assert !@object.respond_to?(:save)
|
484
|
+
end
|
485
|
+
|
486
|
+
def test_should_not_mark_action_helper_as_defined
|
487
|
+
assert !@machine.action_helper_defined?
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
class MachineWithActionDefinedInClassTest < Test::Unit::TestCase
|
439
492
|
def setup
|
440
493
|
@klass = Class.new do
|
441
494
|
def save
|
@@ -461,11 +514,27 @@ class MachineWithActionTest < Test::Unit::TestCase
|
|
461
514
|
def test_should_define_an_event_transition_attribute_writer
|
462
515
|
assert @object.respond_to?(:state_event_transition=)
|
463
516
|
end
|
517
|
+
|
518
|
+
def test_should_not_define_action
|
519
|
+
assert !@klass.ancestors.any? {|ancestor| ancestor != @klass && ancestor.method_defined?(:save)}
|
520
|
+
end
|
521
|
+
|
522
|
+
def test_should_not_mark_action_helper_as_defined
|
523
|
+
assert !@machine.action_helper_defined?
|
524
|
+
end
|
464
525
|
end
|
465
526
|
|
466
|
-
class
|
527
|
+
class MachineWithActionDefinedInIncludedModuleTest < Test::Unit::TestCase
|
467
528
|
def setup
|
468
|
-
@
|
529
|
+
@mod = mod = Module.new do
|
530
|
+
def save
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
@klass = Class.new do
|
535
|
+
include mod
|
536
|
+
end
|
537
|
+
|
469
538
|
@machine = StateMachine::Machine.new(@klass, :action => :save)
|
470
539
|
@object = @klass.new
|
471
540
|
end
|
@@ -486,8 +555,121 @@ class MachineWithActionUndefinedTest < Test::Unit::TestCase
|
|
486
555
|
assert @object.respond_to?(:state_event_transition=)
|
487
556
|
end
|
488
557
|
|
489
|
-
def
|
490
|
-
assert
|
558
|
+
def test_should_define_action
|
559
|
+
assert @klass.ancestors.any? {|ancestor| ![@klass, @mod].include?(ancestor) && ancestor.method_defined?(:save)}
|
560
|
+
end
|
561
|
+
|
562
|
+
def test_should_keep_action_public
|
563
|
+
assert @klass.public_method_defined?(:save)
|
564
|
+
end
|
565
|
+
|
566
|
+
def test_should_mark_action_helper_as_defined
|
567
|
+
assert @machine.action_helper_defined?
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
class MachineWithActionDefinedInSuperclassTest < Test::Unit::TestCase
|
572
|
+
def setup
|
573
|
+
@superclass = Class.new do
|
574
|
+
def save
|
575
|
+
end
|
576
|
+
end
|
577
|
+
@klass = Class.new(@superclass)
|
578
|
+
|
579
|
+
@machine = StateMachine::Machine.new(@klass, :action => :save)
|
580
|
+
@object = @klass.new
|
581
|
+
end
|
582
|
+
|
583
|
+
def test_should_define_an_event_attribute_reader
|
584
|
+
assert @object.respond_to?(:state_event)
|
585
|
+
end
|
586
|
+
|
587
|
+
def test_should_define_an_event_attribute_writer
|
588
|
+
assert @object.respond_to?(:state_event=)
|
589
|
+
end
|
590
|
+
|
591
|
+
def test_should_define_an_event_transition_attribute_reader
|
592
|
+
assert @object.respond_to?(:state_event_transition)
|
593
|
+
end
|
594
|
+
|
595
|
+
def test_should_define_an_event_transition_attribute_writer
|
596
|
+
assert @object.respond_to?(:state_event_transition=)
|
597
|
+
end
|
598
|
+
|
599
|
+
def test_should_define_action
|
600
|
+
assert @klass.ancestors.any? {|ancestor| ![@klass, @superclass].include?(ancestor) && ancestor.method_defined?(:save)}
|
601
|
+
end
|
602
|
+
|
603
|
+
def test_should_keep_action_public
|
604
|
+
assert @klass.public_method_defined?(:save)
|
605
|
+
end
|
606
|
+
|
607
|
+
def test_should_mark_action_helper_as_defined
|
608
|
+
assert @machine.action_helper_defined?
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
class MachineWithPrivateActionTest < Test::Unit::TestCase
|
613
|
+
def setup
|
614
|
+
@superclass = Class.new do
|
615
|
+
private
|
616
|
+
def save
|
617
|
+
end
|
618
|
+
end
|
619
|
+
@klass = Class.new(@superclass)
|
620
|
+
|
621
|
+
@machine = StateMachine::Machine.new(@klass, :action => :save)
|
622
|
+
@object = @klass.new
|
623
|
+
end
|
624
|
+
|
625
|
+
def test_should_define_an_event_attribute_reader
|
626
|
+
assert @object.respond_to?(:state_event)
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_should_define_an_event_attribute_writer
|
630
|
+
assert @object.respond_to?(:state_event=)
|
631
|
+
end
|
632
|
+
|
633
|
+
def test_should_define_an_event_transition_attribute_reader
|
634
|
+
assert @object.respond_to?(:state_event_transition)
|
635
|
+
end
|
636
|
+
|
637
|
+
def test_should_define_an_event_transition_attribute_writer
|
638
|
+
assert @object.respond_to?(:state_event_transition=)
|
639
|
+
end
|
640
|
+
|
641
|
+
def test_should_define_action
|
642
|
+
assert @klass.ancestors.any? {|ancestor| ![@klass, @superclass].include?(ancestor) && ancestor.private_method_defined?(:save)}
|
643
|
+
end
|
644
|
+
|
645
|
+
def test_should_keep_action_private
|
646
|
+
assert @klass.private_method_defined?(:save)
|
647
|
+
end
|
648
|
+
|
649
|
+
def test_should_mark_action_helper_as_defined
|
650
|
+
assert @machine.action_helper_defined?
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
class MachineWithActionAlreadyOverriddenTest < Test::Unit::TestCase
|
655
|
+
def setup
|
656
|
+
@superclass = Class.new do
|
657
|
+
def save
|
658
|
+
end
|
659
|
+
end
|
660
|
+
@klass = Class.new(@superclass)
|
661
|
+
|
662
|
+
StateMachine::Machine.new(@klass, :action => :save)
|
663
|
+
@machine = StateMachine::Machine.new(@klass, :status, :action => :save)
|
664
|
+
@object = @klass.new
|
665
|
+
end
|
666
|
+
|
667
|
+
def test_should_not_redefine_action
|
668
|
+
assert_equal 1, @klass.ancestors.select {|ancestor| ![@klass, @superclass].include?(ancestor) && ancestor.method_defined?(:save)}.length
|
669
|
+
end
|
670
|
+
|
671
|
+
def test_should_mark_action_helper_as_defined
|
672
|
+
assert @machine.action_helper_defined?
|
491
673
|
end
|
492
674
|
end
|
493
675
|
|
@@ -595,6 +777,7 @@ class MachineAfterBeingCopiedTest < Test::Unit::TestCase
|
|
595
777
|
@machine.event(:ignite) {}
|
596
778
|
@machine.before_transition(lambda {})
|
597
779
|
@machine.after_transition(lambda {})
|
780
|
+
@machine.around_transition(lambda {})
|
598
781
|
|
599
782
|
@copied_machine = @machine.clone
|
600
783
|
end
|
@@ -1407,17 +1590,22 @@ class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
|
|
1407
1590
|
def test_should_invoke_callbacks_during_transition
|
1408
1591
|
@machine.before_transition lambda {|object| object.callbacks << 'before'}
|
1409
1592
|
@machine.after_transition lambda {|object| object.callbacks << 'after'}
|
1593
|
+
@machine.around_transition lambda {|object, transition, block| object.callbacks << 'before_around'; block.call; object.callbacks << 'after_around'}
|
1410
1594
|
|
1411
1595
|
@event.fire(@object)
|
1412
|
-
assert_equal %w(before after), @object.callbacks
|
1596
|
+
assert_equal %w(before before_around after_around after), @object.callbacks
|
1413
1597
|
end
|
1414
1598
|
|
1415
1599
|
def test_should_allow_multiple_callbacks
|
1416
1600
|
@machine.before_transition lambda {|object| object.callbacks << 'before1'}, lambda {|object| object.callbacks << 'before2'}
|
1417
1601
|
@machine.after_transition lambda {|object| object.callbacks << 'after1'}, lambda {|object| object.callbacks << 'after2'}
|
1602
|
+
@machine.around_transition(
|
1603
|
+
lambda {|object, transition, block| object.callbacks << 'before_around1'; block.call; object.callbacks << 'after_around1'},
|
1604
|
+
lambda {|object, transition, block| object.callbacks << 'before_around2'; block.call; object.callbacks << 'after_around2'}
|
1605
|
+
)
|
1418
1606
|
|
1419
1607
|
@event.fire(@object)
|
1420
|
-
assert_equal %w(before1 before2 after1 after2), @object.callbacks
|
1608
|
+
assert_equal %w(before1 before2 before_around1 before_around2 after_around2 after_around1 after1 after2), @object.callbacks
|
1421
1609
|
end
|
1422
1610
|
|
1423
1611
|
def test_should_allow_multiple_callbacks_with_requirements
|
@@ -1425,9 +1613,19 @@ class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
|
|
1425
1613
|
@machine.before_transition lambda {|object| object.callbacks << 'before_idling1'}, lambda {|object| object.callbacks << 'before_idling2'}, :from => :idling
|
1426
1614
|
@machine.after_transition lambda {|object| object.callbacks << 'after_parked1'}, lambda {|object| object.callbacks << 'after_parked2'}, :from => :parked
|
1427
1615
|
@machine.after_transition lambda {|object| object.callbacks << 'after_idling1'}, lambda {|object| object.callbacks << 'after_idling2'}, :from => :idling
|
1616
|
+
@machine.around_transition(
|
1617
|
+
lambda {|object, transition, block| object.callbacks << 'before_around_parked1'; block.call; object.callbacks << 'after_around_parked1'},
|
1618
|
+
lambda {|object, transition, block| object.callbacks << 'before_around_parked2'; block.call; object.callbacks << 'after_around_parked2'},
|
1619
|
+
:from => :parked
|
1620
|
+
)
|
1621
|
+
@machine.around_transition(
|
1622
|
+
lambda {|object, transition, block| object.callbacks << 'before_around_idling1'; block.call; object.callbacks << 'after_around_idling1'},
|
1623
|
+
lambda {|object, transition, block| object.callbacks << 'before_around_idling2'; block.call; object.callbacks << 'after_around_idling2'},
|
1624
|
+
:from => :idling
|
1625
|
+
)
|
1428
1626
|
|
1429
1627
|
@event.fire(@object)
|
1430
|
-
assert_equal %w(before_parked1 before_parked2 after_parked1 after_parked2), @object.callbacks
|
1628
|
+
assert_equal %w(before_parked1 before_parked2 before_around_parked1 before_around_parked2 after_around_parked2 after_around_parked1 after_parked1 after_parked2), @object.callbacks
|
1431
1629
|
end
|
1432
1630
|
|
1433
1631
|
def test_should_support_from_requirement
|
@@ -1489,14 +1687,16 @@ class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
|
|
1489
1687
|
def test_should_track_states_defined_in_transition_callbacks
|
1490
1688
|
@machine.before_transition :parked => :idling, :do => lambda {}
|
1491
1689
|
@machine.after_transition :first_gear => :second_gear, :do => lambda {}
|
1690
|
+
@machine.around_transition :third_gear => :fourth_gear, :do => lambda {}
|
1492
1691
|
|
1493
|
-
assert_equal [:parked, :idling, :first_gear, :second_gear], @machine.states.map {|state| state.name}
|
1692
|
+
assert_equal [:parked, :idling, :first_gear, :second_gear, :third_gear, :fourth_gear], @machine.states.map {|state| state.name}
|
1494
1693
|
end
|
1495
1694
|
|
1496
1695
|
def test_should_not_duplicate_states_defined_in_multiple_event_transitions
|
1497
1696
|
@machine.before_transition :parked => :idling, :do => lambda {}
|
1498
1697
|
@machine.after_transition :first_gear => :second_gear, :do => lambda {}
|
1499
1698
|
@machine.after_transition :parked => :idling, :do => lambda {}
|
1699
|
+
@machine.around_transition :parked => :idling, :do => lambda {}
|
1500
1700
|
|
1501
1701
|
assert_equal [:parked, :idling, :first_gear, :second_gear], @machine.states.map {|state| state.name}
|
1502
1702
|
end
|
@@ -1754,6 +1954,7 @@ class MachineFinderWithExistingMachineOnSuperclassTest < Test::Unit::TestCase
|
|
1754
1954
|
@base_machine.event(:ignite) {}
|
1755
1955
|
@base_machine.before_transition(lambda {})
|
1756
1956
|
@base_machine.after_transition(lambda {})
|
1957
|
+
@base_machine.around_transition(lambda {})
|
1757
1958
|
|
1758
1959
|
@klass = Class.new(@base_class)
|
1759
1960
|
@machine = StateMachine::Machine.find_or_create(@klass, :status) {}
|
@@ -1835,6 +2036,7 @@ end
|
|
1835
2036
|
begin
|
1836
2037
|
# Load library
|
1837
2038
|
require 'rubygems'
|
2039
|
+
gem 'ruby-graphviz', '>=0.9.0'
|
1838
2040
|
require 'graphviz'
|
1839
2041
|
|
1840
2042
|
class MachineDrawingTest < Test::Unit::TestCase
|
@@ -2003,5 +2205,5 @@ begin
|
|
2003
2205
|
end
|
2004
2206
|
end
|
2005
2207
|
rescue LoadError
|
2006
|
-
$stderr.puts 'Skipping GraphViz StateMachine::Machine tests. `gem install ruby-graphviz` and try again.'
|
2208
|
+
$stderr.puts 'Skipping GraphViz StateMachine::Machine tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
|
2007
2209
|
end
|
data/test/unit/state_test.rb
CHANGED
@@ -666,6 +666,7 @@ end
|
|
666
666
|
begin
|
667
667
|
# Load library
|
668
668
|
require 'rubygems'
|
669
|
+
gem 'ruby-graphviz', '>=0.9.0'
|
669
670
|
require 'graphviz'
|
670
671
|
|
671
672
|
class StateDrawingTest < Test::Unit::TestCase
|
@@ -790,5 +791,5 @@ begin
|
|
790
791
|
end
|
791
792
|
end
|
792
793
|
rescue LoadError
|
793
|
-
$stderr.puts 'Skipping GraphViz StateMachine::State tests. `gem install ruby-graphviz` and try again.'
|
794
|
+
$stderr.puts 'Skipping GraphViz StateMachine::State tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
|
794
795
|
end
|
@@ -0,0 +1,2098 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
class TransitionCollectionTest < Test::Unit::TestCase
|
4
|
+
def test_should_raise_exception_if_invalid_option_specified
|
5
|
+
exception = assert_raise(ArgumentError) {StateMachine::TransitionCollection.new([], :invalid => true)}
|
6
|
+
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_raise_exception_if_multiple_transitions_for_same_attribute_specified
|
10
|
+
@klass = Class.new
|
11
|
+
|
12
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
13
|
+
@machine.state :parked, :idling
|
14
|
+
@machine.event :ignite
|
15
|
+
|
16
|
+
@object = @klass.new
|
17
|
+
|
18
|
+
exception = assert_raise(ArgumentError) do
|
19
|
+
StateMachine::TransitionCollection.new([
|
20
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
|
21
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
22
|
+
])
|
23
|
+
end
|
24
|
+
assert_equal 'Cannot perform multiple transitions in parallel for the same state machine attribute', exception.message
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class TransitionCollectionByDefaultTest < Test::Unit::TestCase
|
29
|
+
def setup
|
30
|
+
@transitions = StateMachine::TransitionCollection.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_not_skip_actions
|
34
|
+
assert !@transitions.skip_actions
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_should_not_skip_after
|
38
|
+
assert !@transitions.skip_after
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_should_use_transaction
|
42
|
+
assert @transitions.use_transaction
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_should_be_empty
|
46
|
+
assert @transitions.empty?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class TransitionCollectionEmptyWithoutBlockTest < Test::Unit::TestCase
|
51
|
+
def setup
|
52
|
+
@transitions = StateMachine::TransitionCollection.new
|
53
|
+
@result = @transitions.perform
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_should_succeed
|
57
|
+
assert_equal true, @result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
class TransitionCollectionEmptyWithBlockTest < Test::Unit::TestCase
|
63
|
+
def setup
|
64
|
+
@transitions = StateMachine::TransitionCollection.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_should_raise_exception_if_perform_raises_exception
|
68
|
+
assert_raise(ArgumentError) { @transitions.perform { raise ArgumentError } }
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_should_use_block_result_if_non_boolean
|
72
|
+
assert_equal 1, @transitions.perform { 1 }
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_should_use_block_result_if_false
|
76
|
+
assert_equal false, @transitions.perform { false }
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_should_use_block_reslut_if_nil
|
80
|
+
assert_equal nil, @transitions.perform { nil }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class TransitionCollectionInvalidTest < Test::Unit::TestCase
|
85
|
+
def setup
|
86
|
+
@transitions = StateMachine::TransitionCollection.new([false])
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_should_be_empty
|
90
|
+
assert @transitions.empty?
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_should_not_succeed
|
94
|
+
assert_equal false, @transitions.perform
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_should_not_run_perform_block
|
98
|
+
ran_block = false
|
99
|
+
@transitions.perform { ran_block = true }
|
100
|
+
assert !ran_block
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class TransitionCollectionPartialInvalidTest < Test::Unit::TestCase
|
105
|
+
def setup
|
106
|
+
@klass = Class.new do
|
107
|
+
attr_accessor :ran_transaction
|
108
|
+
end
|
109
|
+
|
110
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
111
|
+
@machine.state :idling
|
112
|
+
@machine.event :ignite
|
113
|
+
@machine.before_transition {@ran_before = true}
|
114
|
+
@machine.after_transition {@ran_after = true}
|
115
|
+
@machine.around_transition {|block| @ran_around_before = true; block.call; @ran_around_after = true}
|
116
|
+
|
117
|
+
class << @machine
|
118
|
+
def within_transaction(object)
|
119
|
+
object.ran_transaction = true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
@object = @klass.new
|
124
|
+
|
125
|
+
@transitions = StateMachine::TransitionCollection.new([
|
126
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
|
127
|
+
false
|
128
|
+
])
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_should_not_store_invalid_values
|
132
|
+
assert_equal 1, @transitions.length
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_should_not_succeed
|
136
|
+
assert_equal false, @transitions.perform
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_should_not_start_transaction
|
140
|
+
assert !@object.ran_transaction
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_should_not_run_perform_block
|
144
|
+
ran_block = false
|
145
|
+
@transitions.perform { ran_block = true }
|
146
|
+
assert !ran_block
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_should_not_run_before_callbacks
|
150
|
+
assert !@ran_before
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_should_not_persist_states
|
154
|
+
assert_equal 'parked', @object.state
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_should_not_run_after_callbacks
|
158
|
+
assert !@ran_after
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_should_not_run_around_callbacks_before_yield
|
162
|
+
assert !@ran_around_before
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_should_not_run_around_callbacks_after_yield
|
166
|
+
assert !@ran_around_after
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class TransitionCollectionValidTest < Test::Unit::TestCase
|
171
|
+
def setup
|
172
|
+
@klass = Class.new do
|
173
|
+
attr_reader :persisted
|
174
|
+
|
175
|
+
def initialize
|
176
|
+
super
|
177
|
+
@persisted = []
|
178
|
+
end
|
179
|
+
|
180
|
+
def state=(value)
|
181
|
+
@persisted << 'state' if @persisted
|
182
|
+
@state = value
|
183
|
+
end
|
184
|
+
|
185
|
+
def status=(value)
|
186
|
+
@persisted << 'status' if @persisted
|
187
|
+
@status = value
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked)
|
192
|
+
@state.state :idling
|
193
|
+
@state.event :ignite
|
194
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
|
195
|
+
@status.state :second_gear
|
196
|
+
@status.event :shift_up
|
197
|
+
|
198
|
+
@object = @klass.new
|
199
|
+
|
200
|
+
@result = StateMachine::TransitionCollection.new([
|
201
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
202
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
203
|
+
]).perform
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_should_succeed
|
207
|
+
assert_equal true, @result
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_should_persist_each_state
|
211
|
+
assert_equal 'idling', @object.state
|
212
|
+
assert_equal 'second_gear', @object.status
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_should_persist_in_order
|
216
|
+
assert_equal ['state', 'status'], @object.persisted
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_should_store_results_in_transitions
|
220
|
+
assert_nil @state_transition.result
|
221
|
+
assert_nil @status_transition.result
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
class TransitionCollectionWithoutTransactionsTest < Test::Unit::TestCase
|
226
|
+
def setup
|
227
|
+
@klass = Class.new do
|
228
|
+
attr_accessor :ran_transaction
|
229
|
+
end
|
230
|
+
|
231
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
232
|
+
@machine.state :idling
|
233
|
+
@machine.event :ignite
|
234
|
+
|
235
|
+
class << @machine
|
236
|
+
def within_transaction(object)
|
237
|
+
object.ran_transaction = true
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
@object = @klass.new
|
242
|
+
@transitions = StateMachine::TransitionCollection.new([
|
243
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
244
|
+
], :transaction => false)
|
245
|
+
@transitions.perform
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_should_not_run_within_transaction
|
249
|
+
assert !@object.ran_transaction
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
class TransitionCollectionWithTransactionsTest < Test::Unit::TestCase
|
254
|
+
def setup
|
255
|
+
@klass = Class.new do
|
256
|
+
attr_accessor :running_transaction, :cancelled_transaction
|
257
|
+
end
|
258
|
+
|
259
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
260
|
+
@machine.state :idling
|
261
|
+
@machine.event :ignite
|
262
|
+
|
263
|
+
class << @machine
|
264
|
+
def within_transaction(object)
|
265
|
+
object.running_transaction = true
|
266
|
+
object.cancelled_transaction = yield == false
|
267
|
+
object.running_transaction = false
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
@object = @klass.new
|
272
|
+
@transitions = StateMachine::TransitionCollection.new([
|
273
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
274
|
+
], :transaction => true)
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_should_run_before_callbacks_within_transaction
|
278
|
+
@machine.before_transition {|object| @in_transaction = object.running_transaction}
|
279
|
+
@transitions.perform
|
280
|
+
|
281
|
+
assert @in_transaction
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_should_run_action_within_transaction
|
285
|
+
@transitions.perform { @in_transaction = @object.running_transaction }
|
286
|
+
|
287
|
+
assert @in_transaction
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_should_run_after_callbacks_within_transaction
|
291
|
+
@machine.after_transition {|object| @in_transaction = object.running_transaction}
|
292
|
+
@transitions.perform
|
293
|
+
|
294
|
+
assert @in_transaction
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_should_cancel_the_transaction_on_before_halt
|
298
|
+
@machine.before_transition {throw :halt}
|
299
|
+
|
300
|
+
@transitions.perform
|
301
|
+
assert @object.cancelled_transaction
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_should_cancel_the_transaction_on_action_failure
|
305
|
+
@transitions.perform { false }
|
306
|
+
assert @object.cancelled_transaction
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_should_not_cancel_the_transaction_on_after_halt
|
310
|
+
@machine.after_transition {throw :halt}
|
311
|
+
|
312
|
+
@transitions.perform
|
313
|
+
assert !@object.cancelled_transaction
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
class TransitionCollectionWithEmptyActionsTest < Test::Unit::TestCase
|
318
|
+
def setup
|
319
|
+
@klass = Class.new
|
320
|
+
|
321
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked)
|
322
|
+
@state.state :idling
|
323
|
+
@state.event :ignite
|
324
|
+
|
325
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
|
326
|
+
@status.state :second_gear
|
327
|
+
@status.event :shift_up
|
328
|
+
|
329
|
+
@object = @klass.new
|
330
|
+
|
331
|
+
@transitions = StateMachine::TransitionCollection.new([
|
332
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
333
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
334
|
+
])
|
335
|
+
|
336
|
+
@object.state = 'idling'
|
337
|
+
@object.status = 'second_gear'
|
338
|
+
|
339
|
+
@result = @transitions.perform
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_should_succeed
|
343
|
+
assert_equal true, @result
|
344
|
+
end
|
345
|
+
|
346
|
+
def test_should_persist_states
|
347
|
+
assert_equal 'idling', @object.state
|
348
|
+
assert_equal 'second_gear', @object.status
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_should_store_results_in_transitions
|
352
|
+
assert_nil @state_transition.result
|
353
|
+
assert_nil @status_transition.result
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
class TransitionCollectionWithSkippedActionsTest < Test::Unit::TestCase
|
358
|
+
def setup
|
359
|
+
@klass = Class.new do
|
360
|
+
attr_reader :actions
|
361
|
+
|
362
|
+
def save_state
|
363
|
+
(@actions ||= []) << :save_state
|
364
|
+
:save_state
|
365
|
+
end
|
366
|
+
|
367
|
+
def save_status
|
368
|
+
(@actions ||= []) << :save_status
|
369
|
+
:save_status
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
@callbacks = []
|
374
|
+
|
375
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
|
376
|
+
@state.state :idling
|
377
|
+
@state.event :ignite
|
378
|
+
@state.before_transition {@callbacks << :state_before}
|
379
|
+
@state.after_transition {@callbacks << :state_after}
|
380
|
+
@state.around_transition {|block| @callbacks << :state_around_before; block.call; @callbacks << :state_around_after}
|
381
|
+
|
382
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
|
383
|
+
@status.state :second_gear
|
384
|
+
@status.event :shift_up
|
385
|
+
@status.before_transition {@callbacks << :status_before}
|
386
|
+
@status.after_transition {@callbacks << :status_after}
|
387
|
+
@status.around_transition {|block| @callbacks << :status_around_before; block.call; @callbacks << :status_around_after}
|
388
|
+
|
389
|
+
@object = @klass.new
|
390
|
+
|
391
|
+
@transitions = StateMachine::TransitionCollection.new([
|
392
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
393
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
394
|
+
], :actions => false)
|
395
|
+
@result = @transitions.perform
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_should_skip_actions
|
399
|
+
assert_equal true, @transitions.skip_actions
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_should_succeed
|
403
|
+
assert_equal true, @result
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_should_persist_states
|
407
|
+
assert_equal 'idling', @object.state
|
408
|
+
assert_equal 'second_gear', @object.status
|
409
|
+
end
|
410
|
+
|
411
|
+
def test_should_not_run_actions
|
412
|
+
assert_nil @object.actions
|
413
|
+
end
|
414
|
+
|
415
|
+
def test_should_store_results_in_transitions
|
416
|
+
assert_nil @state_transition.result
|
417
|
+
assert_nil @status_transition.result
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_should_run_all_callbacks
|
421
|
+
assert_equal [:state_before, :state_around_before, :status_before, :status_around_before, :status_around_after, :status_after, :state_around_after, :state_after], @callbacks
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
class TransitionCollectionWithSkippedActionsAndBlockTest < Test::Unit::TestCase
|
426
|
+
def setup
|
427
|
+
@klass = Class.new
|
428
|
+
|
429
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
|
430
|
+
@machine.state :idling
|
431
|
+
@machine.event :ignite
|
432
|
+
|
433
|
+
@object = @klass.new
|
434
|
+
|
435
|
+
@transitions = StateMachine::TransitionCollection.new([
|
436
|
+
@state_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
437
|
+
], :actions => false)
|
438
|
+
@result = @transitions.perform { @ran_block = true; 1 }
|
439
|
+
end
|
440
|
+
|
441
|
+
def test_should_succeed
|
442
|
+
assert_equal 1, @result
|
443
|
+
end
|
444
|
+
|
445
|
+
def test_should_persist_states
|
446
|
+
assert_equal 'idling', @object.state
|
447
|
+
end
|
448
|
+
|
449
|
+
def test_should_run_block
|
450
|
+
assert @ran_block
|
451
|
+
end
|
452
|
+
|
453
|
+
def test_should_store_results_in_transitions
|
454
|
+
assert_equal 1, @state_transition.result
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
class TransitionCollectionWithDuplicateActionsTest < Test::Unit::TestCase
|
459
|
+
def setup
|
460
|
+
@klass = Class.new do
|
461
|
+
attr_reader :actions
|
462
|
+
|
463
|
+
def save
|
464
|
+
(@actions ||= []) << :save
|
465
|
+
:save
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
470
|
+
@state.state :idling
|
471
|
+
@state.event :ignite
|
472
|
+
|
473
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
474
|
+
@status.state :second_gear
|
475
|
+
@status.event :shift_up
|
476
|
+
|
477
|
+
@object = @klass.new
|
478
|
+
|
479
|
+
@transitions = StateMachine::TransitionCollection.new([
|
480
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
481
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
482
|
+
])
|
483
|
+
@result = @transitions.perform
|
484
|
+
end
|
485
|
+
|
486
|
+
def test_should_succeed
|
487
|
+
assert_equal :save, @result
|
488
|
+
end
|
489
|
+
|
490
|
+
def test_should_persist_states
|
491
|
+
assert_equal 'idling', @object.state
|
492
|
+
assert_equal 'second_gear', @object.status
|
493
|
+
end
|
494
|
+
|
495
|
+
def test_should_run_action_once
|
496
|
+
assert_equal [:save], @object.actions
|
497
|
+
end
|
498
|
+
|
499
|
+
def test_should_store_results_in_transitions
|
500
|
+
assert_equal :save, @state_transition.result
|
501
|
+
assert_equal :save, @status_transition.result
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
class TransitionCollectionWithDifferentActionsTest < Test::Unit::TestCase
|
506
|
+
def setup
|
507
|
+
@klass = Class.new do
|
508
|
+
attr_reader :actions
|
509
|
+
|
510
|
+
def save_state
|
511
|
+
(@actions ||= []) << :save_state
|
512
|
+
:save_state
|
513
|
+
end
|
514
|
+
|
515
|
+
def save_status
|
516
|
+
(@actions ||= []) << :save_status
|
517
|
+
:save_status
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
|
522
|
+
@state.state :idling
|
523
|
+
@state.event :ignite
|
524
|
+
|
525
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
|
526
|
+
@status.state :second_gear
|
527
|
+
@status.event :shift_up
|
528
|
+
|
529
|
+
@object = @klass.new
|
530
|
+
|
531
|
+
@transitions = StateMachine::TransitionCollection.new([
|
532
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
533
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
534
|
+
])
|
535
|
+
end
|
536
|
+
|
537
|
+
def test_should_succeed
|
538
|
+
assert_equal true, @transitions.perform
|
539
|
+
end
|
540
|
+
|
541
|
+
def test_should_persist_states
|
542
|
+
@transitions.perform
|
543
|
+
assert_equal 'idling', @object.state
|
544
|
+
assert_equal 'second_gear', @object.status
|
545
|
+
end
|
546
|
+
|
547
|
+
def test_should_run_actions_in_order
|
548
|
+
@transitions.perform
|
549
|
+
assert_equal [:save_state, :save_status], @object.actions
|
550
|
+
end
|
551
|
+
|
552
|
+
def test_should_store_results_in_transitions
|
553
|
+
@transitions.perform
|
554
|
+
assert_equal :save_state, @state_transition.result
|
555
|
+
assert_equal :save_status, @status_transition.result
|
556
|
+
end
|
557
|
+
|
558
|
+
def test_should_not_halt_if_action_fails_for_first_transition
|
559
|
+
@klass.class_eval do
|
560
|
+
def save_state
|
561
|
+
(@actions ||= []) << :save_state
|
562
|
+
false
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
|
567
|
+
assert_equal false, @transitions.perform
|
568
|
+
assert_equal [:save_state, :save_status], @object.actions
|
569
|
+
end
|
570
|
+
|
571
|
+
def test_should_halt_if_action_fails_for_second_transition
|
572
|
+
@klass.class_eval do
|
573
|
+
def save_status
|
574
|
+
(@actions ||= []) << :save_status
|
575
|
+
false
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
assert_equal false, @transitions.perform
|
580
|
+
assert_equal [:save_state, :save_status], @object.actions
|
581
|
+
end
|
582
|
+
|
583
|
+
def test_should_rollback_if_action_errors_for_first_transition
|
584
|
+
@klass.class_eval do
|
585
|
+
def save_state
|
586
|
+
raise ArgumentError
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
begin; @transitions.perform; rescue; end
|
591
|
+
assert_equal 'parked', @object.state
|
592
|
+
assert_equal 'first_gear', @object.status
|
593
|
+
end
|
594
|
+
|
595
|
+
def test_should_rollback_if_action_errors_for_second_transition
|
596
|
+
@klass.class_eval do
|
597
|
+
def save_status
|
598
|
+
raise ArgumentError
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
begin; @transitions.perform; rescue; end
|
603
|
+
assert_equal 'parked', @object.state
|
604
|
+
assert_equal 'first_gear', @object.status
|
605
|
+
end
|
606
|
+
|
607
|
+
def test_should_not_run_after_callbacks_if_action_fails_for_first_transition
|
608
|
+
@klass.class_eval do
|
609
|
+
def save_state
|
610
|
+
false
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
614
|
+
@callbacks = []
|
615
|
+
@state.after_transition { @callbacks << :state_after }
|
616
|
+
@state.around_transition {|block| block.call; @callbacks << :state_around }
|
617
|
+
@status.after_transition { @callbacks << :status_after }
|
618
|
+
@status.around_transition {|block| block.call; @callbacks << :status_around }
|
619
|
+
|
620
|
+
@transitions.perform
|
621
|
+
assert_equal [], @callbacks
|
622
|
+
end
|
623
|
+
|
624
|
+
def test_should_not_run_after_callbacks_if_action_fails_for_second_transition
|
625
|
+
@klass.class_eval do
|
626
|
+
def save_status
|
627
|
+
false
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
@callbacks = []
|
632
|
+
@state.after_transition { @callbacks << :state_after }
|
633
|
+
@state.around_transition {|block| block.call; @callbacks << :state_around }
|
634
|
+
@status.after_transition { @callbacks << :status_after }
|
635
|
+
@status.around_transition {|block| block.call; @callbacks << :status_around }
|
636
|
+
|
637
|
+
@transitions.perform
|
638
|
+
assert_equal [], @callbacks
|
639
|
+
end
|
640
|
+
|
641
|
+
def test_should_run_after_failure_callbacks_if_action_fails_for_first_transition
|
642
|
+
@klass.class_eval do
|
643
|
+
def save_state
|
644
|
+
false
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
@callbacks = []
|
649
|
+
@state.after_transition(:include_failures => true) { @callbacks << :state_after }
|
650
|
+
@state.around_transition(:include_failures => true) {|block| block.call; @callbacks << :state_around }
|
651
|
+
@status.after_transition(:include_failures => true) { @callbacks << :status_after }
|
652
|
+
@status.around_transition(:include_failures => true) {|block| block.call; @callbacks << :status_around }
|
653
|
+
|
654
|
+
@transitions.perform
|
655
|
+
assert_equal [:status_around, :status_after, :state_around, :state_after], @callbacks
|
656
|
+
end
|
657
|
+
|
658
|
+
def test_should_run_after_failure_callbacks_if_action_fails_for_second_transition
|
659
|
+
@klass.class_eval do
|
660
|
+
def save_status
|
661
|
+
false
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
@callbacks = []
|
666
|
+
@state.after_transition(:include_failures => true) { @callbacks << :state_after }
|
667
|
+
@state.around_transition(:include_failures => true) {|block| block.call; @callbacks << :state_around }
|
668
|
+
@status.after_transition(:include_failures => true) { @callbacks << :status_after }
|
669
|
+
@status.around_transition(:include_failures => true) {|block| block.call; @callbacks << :status_around }
|
670
|
+
|
671
|
+
@transitions.perform
|
672
|
+
assert_equal [:status_around, :status_after, :state_around, :state_after], @callbacks
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
class TransitionCollectionWithMixedActionsTest < Test::Unit::TestCase
|
677
|
+
def setup
|
678
|
+
@klass = Class.new do
|
679
|
+
def save
|
680
|
+
true
|
681
|
+
end
|
682
|
+
end
|
683
|
+
|
684
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
685
|
+
@state.state :idling
|
686
|
+
@state.event :ignite
|
687
|
+
|
688
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
|
689
|
+
@status.state :second_gear
|
690
|
+
@status.event :shift_up
|
691
|
+
|
692
|
+
@object = @klass.new
|
693
|
+
|
694
|
+
@transitions = StateMachine::TransitionCollection.new([
|
695
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
696
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
697
|
+
])
|
698
|
+
@result = @transitions.perform
|
699
|
+
end
|
700
|
+
|
701
|
+
def test_should_succeed
|
702
|
+
assert_equal true, @result
|
703
|
+
end
|
704
|
+
|
705
|
+
def test_should_persist_states
|
706
|
+
assert_equal 'idling', @object.state
|
707
|
+
assert_equal 'second_gear', @object.status
|
708
|
+
end
|
709
|
+
|
710
|
+
def test_should_store_results_in_transitions
|
711
|
+
assert_equal true, @state_transition.result
|
712
|
+
assert_nil @status_transition.result
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
class TransitionCollectionWithBlockTest < Test::Unit::TestCase
|
717
|
+
def setup
|
718
|
+
@klass = Class.new do
|
719
|
+
attr_reader :actions
|
720
|
+
|
721
|
+
def save
|
722
|
+
(@actions ||= []) << :save
|
723
|
+
end
|
724
|
+
end
|
725
|
+
|
726
|
+
@state = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
|
727
|
+
@state.state :idling
|
728
|
+
@state.event :ignite
|
729
|
+
|
730
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
731
|
+
@status.state :second_gear
|
732
|
+
@status.event :shift_up
|
733
|
+
|
734
|
+
@object = @klass.new
|
735
|
+
@transitions = StateMachine::TransitionCollection.new([
|
736
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
737
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
738
|
+
])
|
739
|
+
@result = @transitions.perform { 1 }
|
740
|
+
end
|
741
|
+
|
742
|
+
def test_should_succeed
|
743
|
+
assert_equal 1, @result
|
744
|
+
end
|
745
|
+
|
746
|
+
def test_should_persist_states
|
747
|
+
assert_equal 'idling', @object.state
|
748
|
+
assert_equal 'second_gear', @object.status
|
749
|
+
end
|
750
|
+
|
751
|
+
def test_should_not_run_machine_actions
|
752
|
+
assert_nil @object.actions
|
753
|
+
end
|
754
|
+
|
755
|
+
def test_should_use_result_as_transition_result
|
756
|
+
assert_equal 1, @state_transition.result
|
757
|
+
assert_equal 1, @status_transition.result
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
class TransitionCollectionWithActionFailedTest < Test::Unit::TestCase
|
762
|
+
def setup
|
763
|
+
@klass = Class.new do
|
764
|
+
def save
|
765
|
+
false
|
766
|
+
end
|
767
|
+
end
|
768
|
+
@before_count = 0
|
769
|
+
@around_before_count = 0
|
770
|
+
@after_count = 0
|
771
|
+
@around_after_count = 0
|
772
|
+
|
773
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
774
|
+
@machine.state :idling
|
775
|
+
@machine.event :ignite
|
776
|
+
|
777
|
+
@machine.before_transition {@before_count += 1}
|
778
|
+
@machine.after_transition {@after_count += 1}
|
779
|
+
@machine.after_transition(:include_failures => true) {@after_count += 1}
|
780
|
+
@machine.around_transition {|block| @around_before_count += 1; block.call; @around_after_count += 1}
|
781
|
+
@machine.around_transition(:include_failures => true) {|block| @around_before_count += 1; block.call; @around_after_count += 1}
|
782
|
+
|
783
|
+
@object = @klass.new
|
784
|
+
|
785
|
+
@transitions = StateMachine::TransitionCollection.new([
|
786
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
787
|
+
])
|
788
|
+
@result = @transitions.perform
|
789
|
+
end
|
790
|
+
|
791
|
+
def test_should_not_succeed
|
792
|
+
assert_equal false, @result
|
793
|
+
end
|
794
|
+
|
795
|
+
def test_should_not_persist_state
|
796
|
+
assert_equal 'parked', @object.state
|
797
|
+
end
|
798
|
+
|
799
|
+
def test_should_run_before_callbacks
|
800
|
+
assert_equal 1, @before_count
|
801
|
+
end
|
802
|
+
|
803
|
+
def test_should_run_around_callbacks_before_yield
|
804
|
+
assert_equal 2, @around_before_count
|
805
|
+
end
|
806
|
+
|
807
|
+
def test_should_only_run_after_callbacks_that_include_failures
|
808
|
+
assert_equal 1, @after_count
|
809
|
+
end
|
810
|
+
|
811
|
+
def test_should_only_run_around_callbacks_after_yield_that_include_failures
|
812
|
+
assert_equal 1, @around_after_count
|
813
|
+
end
|
814
|
+
end
|
815
|
+
|
816
|
+
class TransitionCollectionWithActionErrorTest < Test::Unit::TestCase
|
817
|
+
def setup
|
818
|
+
@klass = Class.new do
|
819
|
+
def save
|
820
|
+
raise ArgumentError
|
821
|
+
end
|
822
|
+
end
|
823
|
+
@before_count = 0
|
824
|
+
@around_before_count = 0
|
825
|
+
@after_count = 0
|
826
|
+
@around_after_count = 0
|
827
|
+
|
828
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
829
|
+
@machine.state :idling
|
830
|
+
@machine.event :ignite
|
831
|
+
|
832
|
+
@machine.before_transition {@before_count += 1}
|
833
|
+
@machine.after_transition {@after_count += 1}
|
834
|
+
@machine.after_transition(:include_failures => true) {@after_count += 1}
|
835
|
+
@machine.around_transition {|block| @around_before_count += 1; block.call; @around_after_count += 1}
|
836
|
+
@machine.around_transition(:include_failures => true) {|block| @around_before_count += 1; block.call; @around_after_count += 1}
|
837
|
+
|
838
|
+
@object = @klass.new
|
839
|
+
|
840
|
+
@transitions = StateMachine::TransitionCollection.new([
|
841
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
842
|
+
])
|
843
|
+
|
844
|
+
@raised = true
|
845
|
+
begin
|
846
|
+
@transitions.perform
|
847
|
+
@raised = false
|
848
|
+
rescue ArgumentError
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
def test_should_not_catch_exception
|
853
|
+
assert @raised
|
854
|
+
end
|
855
|
+
|
856
|
+
def test_should_not_persist_state
|
857
|
+
assert_equal 'parked', @object.state
|
858
|
+
end
|
859
|
+
|
860
|
+
def test_should_run_before_callbacks
|
861
|
+
assert_equal 1, @before_count
|
862
|
+
end
|
863
|
+
|
864
|
+
def test_should_run_around_callbacks_before_yield
|
865
|
+
assert_equal 2, @around_before_count
|
866
|
+
end
|
867
|
+
|
868
|
+
def test_should_not_run_after_callbacks
|
869
|
+
assert_equal 0, @after_count
|
870
|
+
end
|
871
|
+
|
872
|
+
def test_should_not_run_around_callbacks_after_yield
|
873
|
+
assert_equal 0, @around_after_count
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
class TransitionCollectionWithCallbacksTest < Test::Unit::TestCase
|
878
|
+
def setup
|
879
|
+
@klass = Class.new do
|
880
|
+
attr_reader :saved
|
881
|
+
|
882
|
+
def save
|
883
|
+
@saved = true
|
884
|
+
end
|
885
|
+
end
|
886
|
+
|
887
|
+
@before_callbacks = []
|
888
|
+
@after_callbacks = []
|
889
|
+
|
890
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
891
|
+
@state.state :idling
|
892
|
+
@state.event :ignite
|
893
|
+
@state.before_transition {@before_callbacks << :state_before}
|
894
|
+
@state.after_transition(:include_failures => true) {@after_callbacks << :state_after}
|
895
|
+
@state.around_transition(:include_failures => true) {|block| @before_callbacks << :state_around; block.call; @after_callbacks << :state_around}
|
896
|
+
|
897
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
898
|
+
@status.state :second_gear
|
899
|
+
@status.event :shift_up
|
900
|
+
@status.before_transition {@before_callbacks << :status_before}
|
901
|
+
@status.after_transition(:include_failures => true) {@after_callbacks << :status_after}
|
902
|
+
@status.around_transition(:include_failures => true) {|block| @before_callbacks << :status_around; block.call; @after_callbacks << :status_around}
|
903
|
+
|
904
|
+
@object = @klass.new
|
905
|
+
@transitions = StateMachine::TransitionCollection.new([
|
906
|
+
StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
907
|
+
StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
908
|
+
])
|
909
|
+
end
|
910
|
+
|
911
|
+
def test_should_run_before_callbacks_in_order
|
912
|
+
@transitions.perform
|
913
|
+
assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
|
914
|
+
end
|
915
|
+
|
916
|
+
def test_should_halt_if_before_callback_halted_for_first_transition
|
917
|
+
@state.before_transition {throw :halt}
|
918
|
+
|
919
|
+
assert_equal false, @transitions.perform
|
920
|
+
assert_equal [:state_before, :state_around], @before_callbacks
|
921
|
+
end
|
922
|
+
|
923
|
+
def test_should_halt_if_before_callback_halted_for_second_transition
|
924
|
+
@status.before_transition {throw :halt}
|
925
|
+
|
926
|
+
assert_equal false, @transitions.perform
|
927
|
+
assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
|
928
|
+
end
|
929
|
+
|
930
|
+
def test_should_halt_if_around_callback_halted_before_yield_for_first_transition
|
931
|
+
@state.around_transition {throw :halt}
|
932
|
+
|
933
|
+
assert_equal false, @transitions.perform
|
934
|
+
assert_equal [:state_before, :state_around], @before_callbacks
|
935
|
+
end
|
936
|
+
|
937
|
+
def test_should_halt_if_around_callback_halted_before_yield_for_second_transition
|
938
|
+
@status.around_transition {throw :halt}
|
939
|
+
|
940
|
+
assert_equal false, @transitions.perform
|
941
|
+
assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
|
942
|
+
end
|
943
|
+
|
944
|
+
def test_should_run_after_callbacks_in_reverse_order
|
945
|
+
@transitions.perform
|
946
|
+
assert_equal [:status_around, :status_after, :state_around, :state_after], @after_callbacks
|
947
|
+
end
|
948
|
+
|
949
|
+
def test_should_not_halt_if_after_callback_halted_for_first_transition
|
950
|
+
@state.after_transition(:include_failures => true) {throw :halt}
|
951
|
+
|
952
|
+
assert_equal true, @transitions.perform
|
953
|
+
assert_equal [:status_around, :status_after, :state_around, :state_after], @after_callbacks
|
954
|
+
end
|
955
|
+
|
956
|
+
def test_should_not_halt_if_around_callback_halted_for_second_transition
|
957
|
+
@status.around_transition(:include_failures => true) {|block| block.call; throw :halt}
|
958
|
+
|
959
|
+
assert_equal true, @transitions.perform
|
960
|
+
assert_equal [:state_around, :state_after], @after_callbacks
|
961
|
+
end
|
962
|
+
|
963
|
+
def test_should_run_before_callbacks_before_persisting_the_state
|
964
|
+
@state.before_transition {|object| @before_state = object.state}
|
965
|
+
@state.around_transition {|object, transition, block| @around_state = object.state; block.call}
|
966
|
+
@transitions.perform
|
967
|
+
|
968
|
+
assert_equal 'parked', @before_state
|
969
|
+
assert_equal 'parked', @around_state
|
970
|
+
end
|
971
|
+
|
972
|
+
def test_should_persist_state_before_running_action
|
973
|
+
@klass.class_eval do
|
974
|
+
attr_reader :saved_on_persist
|
975
|
+
|
976
|
+
def state=(value)
|
977
|
+
@state = value
|
978
|
+
@saved_on_persist = @saved
|
979
|
+
end
|
980
|
+
end
|
981
|
+
|
982
|
+
@transitions.perform
|
983
|
+
assert !@object.saved_on_persist
|
984
|
+
end
|
985
|
+
|
986
|
+
def test_should_persist_state_before_running_action_block
|
987
|
+
@klass.class_eval do
|
988
|
+
attr_writer :saved
|
989
|
+
attr_reader :saved_on_persist
|
990
|
+
|
991
|
+
def state=(value)
|
992
|
+
@state = value
|
993
|
+
@saved_on_persist = @saved
|
994
|
+
end
|
995
|
+
end
|
996
|
+
|
997
|
+
@transitions.perform { @object.saved = true }
|
998
|
+
assert !@object.saved_on_persist
|
999
|
+
end
|
1000
|
+
|
1001
|
+
def test_should_run_after_callbacks_after_running_the_action
|
1002
|
+
@state.after_transition {|object| @after_saved = object.saved}
|
1003
|
+
@state.around_transition {|object, transition, block| block.call; @around_saved = object.saved}
|
1004
|
+
@transitions.perform
|
1005
|
+
|
1006
|
+
assert @after_saved
|
1007
|
+
assert @around_saved
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
class TransitionCollectionWithBeforeCallbackHaltTest < Test::Unit::TestCase
|
1012
|
+
def setup
|
1013
|
+
@klass = Class.new do
|
1014
|
+
attr_reader :saved
|
1015
|
+
|
1016
|
+
def save
|
1017
|
+
@saved = true
|
1018
|
+
end
|
1019
|
+
end
|
1020
|
+
@before_count = 0
|
1021
|
+
@after_count = 0
|
1022
|
+
|
1023
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1024
|
+
@machine.state :idling
|
1025
|
+
@machine.event :ignite
|
1026
|
+
|
1027
|
+
@machine.before_transition {@before_count += 1; throw :halt}
|
1028
|
+
@machine.before_transition {@before_count += 1}
|
1029
|
+
@machine.after_transition {@after_count += 1}
|
1030
|
+
@machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
|
1031
|
+
|
1032
|
+
@object = @klass.new
|
1033
|
+
|
1034
|
+
@transitions = StateMachine::TransitionCollection.new([
|
1035
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1036
|
+
])
|
1037
|
+
@result = @transitions.perform
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
def test_should_not_succeed
|
1041
|
+
assert_equal false, @result
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
def test_should_not_persist_state
|
1045
|
+
assert_equal 'parked', @object.state
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
def test_should_not_run_action
|
1049
|
+
assert !@object.saved
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
def test_should_not_run_further_before_callbacks
|
1053
|
+
assert_equal 1, @before_count
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
def test_should_not_run_after_callbacks
|
1057
|
+
assert_equal 0, @after_count
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
class TransitionCollectionWithAfterCallbackHaltTest < Test::Unit::TestCase
|
1062
|
+
def setup
|
1063
|
+
@klass = Class.new do
|
1064
|
+
attr_reader :saved
|
1065
|
+
|
1066
|
+
def save
|
1067
|
+
@saved = true
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
@before_count = 0
|
1071
|
+
@after_count = 0
|
1072
|
+
|
1073
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1074
|
+
@machine.state :idling
|
1075
|
+
@machine.event :ignite
|
1076
|
+
|
1077
|
+
@machine.before_transition {@before_count += 1}
|
1078
|
+
@machine.after_transition {@after_count += 1; throw :halt}
|
1079
|
+
@machine.after_transition {@after_count += 1}
|
1080
|
+
@machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
|
1081
|
+
|
1082
|
+
@object = @klass.new
|
1083
|
+
|
1084
|
+
@transitions = StateMachine::TransitionCollection.new([
|
1085
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1086
|
+
])
|
1087
|
+
@result = @transitions.perform
|
1088
|
+
end
|
1089
|
+
|
1090
|
+
def test_should_succeed
|
1091
|
+
assert_equal true, @result
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
def test_should_persist_state
|
1095
|
+
assert_equal 'idling', @object.state
|
1096
|
+
end
|
1097
|
+
|
1098
|
+
def test_should_run_before_callbacks
|
1099
|
+
assert_equal 2, @before_count
|
1100
|
+
end
|
1101
|
+
|
1102
|
+
def test_should_not_run_further_after_callbacks
|
1103
|
+
assert_equal 2, @after_count
|
1104
|
+
end
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
class TransitionCollectionWithSkippedAfterCallbacksTest < Test::Unit::TestCase
|
1108
|
+
def setup
|
1109
|
+
@klass = Class.new
|
1110
|
+
|
1111
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
1112
|
+
@machine.state :idling
|
1113
|
+
@machine.event :ignite
|
1114
|
+
@machine.after_transition {@ran_after = true}
|
1115
|
+
@machine.around_transition {|block| @ran_around_before = true; block.call; @ran_around_after = true}
|
1116
|
+
|
1117
|
+
@object = @klass.new
|
1118
|
+
|
1119
|
+
@transitions = StateMachine::TransitionCollection.new([
|
1120
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1121
|
+
], :after => false)
|
1122
|
+
@result = @transitions.perform
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
def test_should_succeed
|
1126
|
+
assert_equal true, @result
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
def test_should_not_run_after_callbacks
|
1130
|
+
assert !@ran_after
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
def test_should_not_run_around_callbacks_after_yield
|
1134
|
+
assert !@ran_around_after
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
def test_should_run_after_callbacks_on_subsequent_perform
|
1138
|
+
StateMachine::TransitionCollection.new([@transition]).perform
|
1139
|
+
assert @ran_after
|
1140
|
+
end
|
1141
|
+
|
1142
|
+
def test_should_run_around_callbacks_after_yield_on_subsequent_perform
|
1143
|
+
StateMachine::TransitionCollection.new([@transition]).perform
|
1144
|
+
assert @ran_around_after
|
1145
|
+
end
|
1146
|
+
|
1147
|
+
def test_should_not_rerun_around_callbacks_before_yield_on_subsequent_perform
|
1148
|
+
@ran_around_before = false
|
1149
|
+
StateMachine::TransitionCollection.new([@transition]).perform
|
1150
|
+
|
1151
|
+
assert !@ran_around_before
|
1152
|
+
end
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
class TransitionCollectionWithActionHelperBaseTest < Test::Unit::TestCase
|
1156
|
+
def setup
|
1157
|
+
@superclass = Class.new do
|
1158
|
+
def save
|
1159
|
+
true
|
1160
|
+
end
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
@klass = Class.new(@superclass) do
|
1164
|
+
attr_reader :saved, :state_on_save, :state_event_on_save, :state_event_transition_on_save
|
1165
|
+
|
1166
|
+
def save
|
1167
|
+
@saved = true
|
1168
|
+
@state_on_save = state
|
1169
|
+
@state_event_on_save = state_event
|
1170
|
+
@state_event_transition_on_save = state_event_transition
|
1171
|
+
super
|
1172
|
+
end
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1176
|
+
@machine.state :idling
|
1177
|
+
@machine.event :ignite
|
1178
|
+
|
1179
|
+
@object = @klass.new
|
1180
|
+
|
1181
|
+
@transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
def default_test
|
1185
|
+
end
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
class TransitionCollectionWithActionHelperAndSkippedActionTest < TransitionCollectionWithActionHelperBaseTest
|
1189
|
+
def setup
|
1190
|
+
super
|
1191
|
+
@result = StateMachine::TransitionCollection.new([@transition], :actions => false).perform
|
1192
|
+
end
|
1193
|
+
|
1194
|
+
def test_should_succeed
|
1195
|
+
assert_equal true, @result
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
def test_should_not_run_action
|
1199
|
+
assert !@object.saved
|
1200
|
+
end
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
class TransitionCollectionWithActionHelperAndSkippedAfterCallbacksTest < TransitionCollectionWithActionHelperBaseTest
|
1204
|
+
def setup
|
1205
|
+
super
|
1206
|
+
@result = StateMachine::TransitionCollection.new([@transition], :after => false).perform
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
def test_should_succeed
|
1210
|
+
assert_equal true, @result
|
1211
|
+
end
|
1212
|
+
|
1213
|
+
def test_should_run_action
|
1214
|
+
assert @object.saved
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
def test_should_have_already_persisted_when_running_action
|
1218
|
+
assert_equal 'idling', @object.state_on_save
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
def test_should_not_have_event_during_action
|
1222
|
+
assert_nil @object.state_event_on_save
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
def test_should_not_write_event
|
1226
|
+
assert_nil @object.state_event
|
1227
|
+
end
|
1228
|
+
|
1229
|
+
def test_should_not_have_event_transition_during_save
|
1230
|
+
assert_nil @object.state_event_transition_on_save
|
1231
|
+
end
|
1232
|
+
|
1233
|
+
def test_should_not_write_event_attribute
|
1234
|
+
assert_nil @object.send(:state_event_transition)
|
1235
|
+
end
|
1236
|
+
end
|
1237
|
+
|
1238
|
+
class TransitionCollectionWithActionHelperAndBlockTest < TransitionCollectionWithActionHelperBaseTest
|
1239
|
+
def setup
|
1240
|
+
super
|
1241
|
+
@result = StateMachine::TransitionCollection.new([@transition]).perform { true }
|
1242
|
+
end
|
1243
|
+
|
1244
|
+
def test_should_succeed
|
1245
|
+
assert_equal true, @result
|
1246
|
+
end
|
1247
|
+
|
1248
|
+
def test_should_not_run_action
|
1249
|
+
assert !@object.saved
|
1250
|
+
end
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
class TransitionCollectionWithActionHelperInvalidTest < TransitionCollectionWithActionHelperBaseTest
|
1254
|
+
def setup
|
1255
|
+
super
|
1256
|
+
@result = StateMachine::TransitionCollection.new([@transition, nil]).perform
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
def test_should_not_succeed
|
1260
|
+
assert_equal false, @result
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
def test_should_not_run_action
|
1264
|
+
assert !@object.saved
|
1265
|
+
end
|
1266
|
+
end
|
1267
|
+
|
1268
|
+
class TransitionCollectionWithActionHelperWithNilActionTest < TransitionCollectionWithActionHelperBaseTest
|
1269
|
+
def setup
|
1270
|
+
super
|
1271
|
+
|
1272
|
+
@machine = StateMachine::Machine.new(@klass, :status, :initial => :parked)
|
1273
|
+
@machine.state :idling
|
1274
|
+
@machine.event :ignite
|
1275
|
+
|
1276
|
+
@result = StateMachine::TransitionCollection.new([@transition, StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)]).perform
|
1277
|
+
end
|
1278
|
+
|
1279
|
+
def test_should_succeed
|
1280
|
+
assert_equal true, @result
|
1281
|
+
end
|
1282
|
+
|
1283
|
+
def test_should_run_action
|
1284
|
+
assert @object.saved
|
1285
|
+
end
|
1286
|
+
|
1287
|
+
def test_should_have_already_persisted_when_running_action
|
1288
|
+
assert_equal 'idling', @object.state_on_save
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
def test_should_not_have_event_during_action
|
1292
|
+
assert_nil @object.state_event_on_save
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
def test_should_not_write_event
|
1296
|
+
assert_nil @object.state_event
|
1297
|
+
end
|
1298
|
+
|
1299
|
+
def test_should_not_have_event_transition_during_save
|
1300
|
+
assert_nil @object.state_event_transition_on_save
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
def test_should_not_write_event_attribute
|
1304
|
+
assert_nil @object.send(:state_event_transition)
|
1305
|
+
end
|
1306
|
+
end
|
1307
|
+
|
1308
|
+
class TransitionCollectionWithActionHelperWithDifferentActionsTest < TransitionCollectionWithActionHelperBaseTest
|
1309
|
+
def setup
|
1310
|
+
super
|
1311
|
+
|
1312
|
+
@klass.class_eval do
|
1313
|
+
def save_status
|
1314
|
+
true
|
1315
|
+
end
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
@machine = StateMachine::Machine.new(@klass, :status, :initial => :parked, :action => :save_status)
|
1319
|
+
@machine.state :idling
|
1320
|
+
@machine.event :ignite
|
1321
|
+
|
1322
|
+
@result = StateMachine::TransitionCollection.new([@transition, StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)]).perform
|
1323
|
+
end
|
1324
|
+
|
1325
|
+
def test_should_succeed
|
1326
|
+
assert_equal true, @result
|
1327
|
+
end
|
1328
|
+
|
1329
|
+
def test_should_run_action
|
1330
|
+
assert @object.saved
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
def test_should_have_already_persisted_when_running_action
|
1334
|
+
assert_equal 'idling', @object.state_on_save
|
1335
|
+
end
|
1336
|
+
|
1337
|
+
def test_should_not_have_event_during_action
|
1338
|
+
assert_nil @object.state_event_on_save
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
def test_should_not_write_event
|
1342
|
+
assert_nil @object.state_event
|
1343
|
+
end
|
1344
|
+
|
1345
|
+
def test_should_not_have_event_transition_during_save
|
1346
|
+
assert_nil @object.state_event_transition_on_save
|
1347
|
+
end
|
1348
|
+
|
1349
|
+
def test_should_not_write_event_attribute
|
1350
|
+
assert_nil @object.send(:state_event_transition)
|
1351
|
+
end
|
1352
|
+
end
|
1353
|
+
|
1354
|
+
class TransitionCollectionWithActionHelperTest < TransitionCollectionWithActionHelperBaseTest
|
1355
|
+
def setup
|
1356
|
+
super
|
1357
|
+
@result = StateMachine::TransitionCollection.new([@transition]).perform
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
def test_should_succeed
|
1361
|
+
assert_equal true, @result
|
1362
|
+
end
|
1363
|
+
|
1364
|
+
def test_should_run_action
|
1365
|
+
assert @object.saved
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
def test_should_not_have_already_persisted_when_running_action
|
1369
|
+
assert_equal 'parked', @object.state_on_save
|
1370
|
+
end
|
1371
|
+
|
1372
|
+
def test_should_persist
|
1373
|
+
assert_equal 'idling', @object.state
|
1374
|
+
end
|
1375
|
+
|
1376
|
+
def test_should_not_have_event_during_action
|
1377
|
+
assert_nil @object.state_event_on_save
|
1378
|
+
end
|
1379
|
+
|
1380
|
+
def test_should_not_write_event
|
1381
|
+
assert_nil @object.state_event
|
1382
|
+
end
|
1383
|
+
|
1384
|
+
def test_should_have_event_transition_during_action
|
1385
|
+
assert_equal @transition, @object.state_event_transition_on_save
|
1386
|
+
end
|
1387
|
+
|
1388
|
+
def test_should_not_write_event_transition
|
1389
|
+
assert_nil @object.send(:state_event_transition)
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
def test_should_mark_event_transition_as_transient
|
1393
|
+
assert @transition.transient?
|
1394
|
+
end
|
1395
|
+
end
|
1396
|
+
|
1397
|
+
class TransitionCollectionWithActionHelperMultipleTest < TransitionCollectionWithActionHelperBaseTest
|
1398
|
+
def setup
|
1399
|
+
super
|
1400
|
+
|
1401
|
+
@status_machine = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
1402
|
+
@status_machine.state :second_gear
|
1403
|
+
@status_machine.event :shift_up
|
1404
|
+
|
1405
|
+
@klass.class_eval do
|
1406
|
+
attr_reader :status_on_save, :status_event_on_save, :status_event_transition_on_save
|
1407
|
+
|
1408
|
+
def save
|
1409
|
+
@saved = true
|
1410
|
+
@state_on_save = state
|
1411
|
+
@state_event_on_save = state_event
|
1412
|
+
@state_event_transition_on_save = state_event_transition
|
1413
|
+
@status_on_save = status
|
1414
|
+
@status_event_on_save = status_event
|
1415
|
+
@status_event_transition_on_save = status_event_transition
|
1416
|
+
super
|
1417
|
+
1
|
1418
|
+
end
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
@object = @klass.new
|
1422
|
+
@state_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1423
|
+
@status_transition = StateMachine::Transition.new(@object, @status_machine, :shift_up, :first_gear, :second_gear)
|
1424
|
+
|
1425
|
+
@result = StateMachine::TransitionCollection.new([@state_transition, @status_transition]).perform
|
1426
|
+
end
|
1427
|
+
|
1428
|
+
def test_should_succeed
|
1429
|
+
assert_equal 1, @result
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
def test_should_run_action
|
1433
|
+
assert @object.saved
|
1434
|
+
end
|
1435
|
+
|
1436
|
+
def test_should_not_have_already_persisted_when_running_action
|
1437
|
+
assert_equal 'parked', @object.state_on_save
|
1438
|
+
assert_equal 'first_gear', @object.status_on_save
|
1439
|
+
end
|
1440
|
+
|
1441
|
+
def test_should_persist
|
1442
|
+
assert_equal 'idling', @object.state
|
1443
|
+
assert_equal 'second_gear', @object.status
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
def test_should_not_have_events_during_action
|
1447
|
+
assert_nil @object.state_event_on_save
|
1448
|
+
assert_nil @object.status_event_on_save
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
def test_should_not_write_events
|
1452
|
+
assert_nil @object.state_event
|
1453
|
+
assert_nil @object.status_event
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
def test_should_have_event_transitions_during_action
|
1457
|
+
assert_equal @state_transition, @object.state_event_transition_on_save
|
1458
|
+
assert_equal @status_transition, @object.status_event_transition_on_save
|
1459
|
+
end
|
1460
|
+
|
1461
|
+
def test_should_not_write_event_transitions
|
1462
|
+
assert_nil @object.send(:state_event_transition)
|
1463
|
+
assert_nil @object.send(:status_event_transition)
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
def test_should_mark_event_transitions_as_transient
|
1467
|
+
assert @state_transition.transient?
|
1468
|
+
assert @status_transition.transient?
|
1469
|
+
end
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
class TransitionCollectionWithActionHelperErrorTest < TransitionCollectionWithActionHelperBaseTest
|
1473
|
+
def setup
|
1474
|
+
super
|
1475
|
+
|
1476
|
+
@superclass.class_eval do
|
1477
|
+
def save
|
1478
|
+
raise ArgumentError
|
1479
|
+
end
|
1480
|
+
end
|
1481
|
+
|
1482
|
+
begin; StateMachine::TransitionCollection.new([@transition]).perform; rescue; end
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
def test_should_not_write_event
|
1486
|
+
assert_nil @object.state_event
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
def test_should_not_write_event_transition
|
1490
|
+
assert_nil @object.send(:state_event_transition)
|
1491
|
+
end
|
1492
|
+
end
|
1493
|
+
|
1494
|
+
class AttributeTransitionCollectionByDefaultTest < Test::Unit::TestCase
|
1495
|
+
def setup
|
1496
|
+
@transitions = StateMachine::AttributeTransitionCollection.new
|
1497
|
+
end
|
1498
|
+
|
1499
|
+
def test_should_skip_actions
|
1500
|
+
assert @transitions.skip_actions
|
1501
|
+
end
|
1502
|
+
|
1503
|
+
def test_should_not_skip_after
|
1504
|
+
assert !@transitions.skip_after
|
1505
|
+
end
|
1506
|
+
|
1507
|
+
def test_should_not_use_transaction
|
1508
|
+
assert !@transitions.use_transaction
|
1509
|
+
end
|
1510
|
+
|
1511
|
+
def test_should_be_empty
|
1512
|
+
assert @transitions.empty?
|
1513
|
+
end
|
1514
|
+
end
|
1515
|
+
|
1516
|
+
class AttributeTransitionCollectionWithEventsTest < Test::Unit::TestCase
|
1517
|
+
def setup
|
1518
|
+
@klass = Class.new
|
1519
|
+
|
1520
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1521
|
+
@state.state :idling
|
1522
|
+
@state.event :ignite
|
1523
|
+
|
1524
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
1525
|
+
@status.state :second_gear
|
1526
|
+
@status.event :shift_up
|
1527
|
+
|
1528
|
+
@object = @klass.new
|
1529
|
+
@object.state_event = 'ignite'
|
1530
|
+
@object.status_event = 'shift_up'
|
1531
|
+
|
1532
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1533
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
1534
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
1535
|
+
])
|
1536
|
+
@result = @transitions.perform
|
1537
|
+
end
|
1538
|
+
|
1539
|
+
def test_should_succeed
|
1540
|
+
assert_equal true, @result
|
1541
|
+
end
|
1542
|
+
|
1543
|
+
def test_should_persist_states
|
1544
|
+
assert_equal 'idling', @object.state
|
1545
|
+
assert_equal 'second_gear', @object.status
|
1546
|
+
end
|
1547
|
+
|
1548
|
+
def test_should_clear_events
|
1549
|
+
assert_nil @object.state_event
|
1550
|
+
assert_nil @object.status_event
|
1551
|
+
end
|
1552
|
+
|
1553
|
+
def test_should_not_write_event_transitions
|
1554
|
+
assert_nil @object.send(:state_event_transition)
|
1555
|
+
assert_nil @object.send(:status_event_transition)
|
1556
|
+
end
|
1557
|
+
end
|
1558
|
+
|
1559
|
+
class AttributeTransitionCollectionWithEventTransitionsTest < Test::Unit::TestCase
|
1560
|
+
def setup
|
1561
|
+
@klass = Class.new
|
1562
|
+
|
1563
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1564
|
+
@state.state :idling
|
1565
|
+
@state.event :ignite
|
1566
|
+
|
1567
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
1568
|
+
@status.state :second_gear
|
1569
|
+
@status.event :shift_up
|
1570
|
+
|
1571
|
+
@object = @klass.new
|
1572
|
+
@object.send(:state_event_transition=, @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling))
|
1573
|
+
@object.send(:status_event_transition=, @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear))
|
1574
|
+
|
1575
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([@state_transition, @status_transition])
|
1576
|
+
@result = @transitions.perform
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
def test_should_succeed
|
1580
|
+
assert_equal true, @result
|
1581
|
+
end
|
1582
|
+
|
1583
|
+
def test_should_persist_states
|
1584
|
+
assert_equal 'idling', @object.state
|
1585
|
+
assert_equal 'second_gear', @object.status
|
1586
|
+
end
|
1587
|
+
|
1588
|
+
def test_should_not_write_events
|
1589
|
+
assert_nil @object.state_event
|
1590
|
+
assert_nil @object.status_event
|
1591
|
+
end
|
1592
|
+
|
1593
|
+
def test_should_clear_event_transitions
|
1594
|
+
assert_nil @object.send(:state_event_transition)
|
1595
|
+
assert_nil @object.send(:status_event_transition)
|
1596
|
+
end
|
1597
|
+
end
|
1598
|
+
|
1599
|
+
class AttributeTransitionCollectionWithActionFailedTest < Test::Unit::TestCase
|
1600
|
+
def setup
|
1601
|
+
@klass = Class.new
|
1602
|
+
|
1603
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1604
|
+
@state.state :idling
|
1605
|
+
@state.event :ignite
|
1606
|
+
|
1607
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
1608
|
+
@status.state :second_gear
|
1609
|
+
@status.event :shift_up
|
1610
|
+
|
1611
|
+
@object = @klass.new
|
1612
|
+
@object.state_event = 'ignite'
|
1613
|
+
@object.status_event = 'shift_up'
|
1614
|
+
|
1615
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1616
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
1617
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
1618
|
+
])
|
1619
|
+
@result = @transitions.perform { false }
|
1620
|
+
end
|
1621
|
+
|
1622
|
+
def test_should_not_succeed
|
1623
|
+
assert_equal false, @result
|
1624
|
+
end
|
1625
|
+
|
1626
|
+
def test_should_not_persist_states
|
1627
|
+
assert_equal 'parked', @object.state
|
1628
|
+
assert_equal 'first_gear', @object.status
|
1629
|
+
end
|
1630
|
+
|
1631
|
+
def test_should_not_clear_events
|
1632
|
+
assert_equal :ignite, @object.state_event
|
1633
|
+
assert_equal :shift_up, @object.status_event
|
1634
|
+
end
|
1635
|
+
|
1636
|
+
def test_should_not_write_event_transitions
|
1637
|
+
assert_nil @object.send(:state_event_transition)
|
1638
|
+
assert_nil @object.send(:status_event_transition)
|
1639
|
+
end
|
1640
|
+
end
|
1641
|
+
|
1642
|
+
class AttributeTransitionCollectionWithActionErrorTest < Test::Unit::TestCase
|
1643
|
+
def setup
|
1644
|
+
@klass = Class.new
|
1645
|
+
|
1646
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1647
|
+
@state.state :idling
|
1648
|
+
@state.event :ignite
|
1649
|
+
|
1650
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
1651
|
+
@status.state :second_gear
|
1652
|
+
@status.event :shift_up
|
1653
|
+
|
1654
|
+
@object = @klass.new
|
1655
|
+
@object.state_event = 'ignite'
|
1656
|
+
@object.status_event = 'shift_up'
|
1657
|
+
|
1658
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1659
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
1660
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
1661
|
+
])
|
1662
|
+
|
1663
|
+
begin; @transitions.perform { raise ArgumentError }; rescue; end
|
1664
|
+
end
|
1665
|
+
|
1666
|
+
def test_should_not_persist_states
|
1667
|
+
assert_equal 'parked', @object.state
|
1668
|
+
assert_equal 'first_gear', @object.status
|
1669
|
+
end
|
1670
|
+
|
1671
|
+
def test_should_not_clear_events
|
1672
|
+
assert_equal :ignite, @object.state_event
|
1673
|
+
assert_equal :shift_up, @object.status_event
|
1674
|
+
end
|
1675
|
+
|
1676
|
+
def test_should_not_write_event_transitions
|
1677
|
+
assert_nil @object.send(:state_event_transition)
|
1678
|
+
assert_nil @object.send(:status_event_transition)
|
1679
|
+
end
|
1680
|
+
end
|
1681
|
+
|
1682
|
+
class AttributeTransitionCollectionWithCallbacksTest < Test::Unit::TestCase
|
1683
|
+
def setup
|
1684
|
+
@klass = Class.new
|
1685
|
+
|
1686
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1687
|
+
@state.state :idling
|
1688
|
+
@state.event :ignite
|
1689
|
+
|
1690
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
1691
|
+
@status.state :second_gear
|
1692
|
+
@status.event :shift_up
|
1693
|
+
|
1694
|
+
@object = @klass.new
|
1695
|
+
|
1696
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1697
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
1698
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
1699
|
+
])
|
1700
|
+
end
|
1701
|
+
|
1702
|
+
def test_should_not_have_events_during_before_callbacks
|
1703
|
+
@state.before_transition {|object, transition| @before_state_event = object.state_event }
|
1704
|
+
@state.around_transition {|object, transition, block| @around_state_event = object.state_event; block.call }
|
1705
|
+
@transitions.perform
|
1706
|
+
|
1707
|
+
assert_nil @before_state_event
|
1708
|
+
assert_nil @around_state_event
|
1709
|
+
end
|
1710
|
+
|
1711
|
+
def test_should_not_have_events_during_action
|
1712
|
+
@transitions.perform { @state_event = @object.state_event }
|
1713
|
+
|
1714
|
+
assert_nil @state_event
|
1715
|
+
end
|
1716
|
+
|
1717
|
+
def test_should_not_have_events_during_after_callbacks
|
1718
|
+
@state.after_transition {|object, transition| @after_state_event = object.state_event }
|
1719
|
+
@state.around_transition {|object, transition, block| block.call; @around_state_event = object.state_event }
|
1720
|
+
@transitions.perform
|
1721
|
+
|
1722
|
+
assert_nil @state_event
|
1723
|
+
end
|
1724
|
+
|
1725
|
+
def test_should_not_have_event_transitions_during_before_callbacks
|
1726
|
+
@state.before_transition {|object, transition| @state_event_transition = object.send(:state_event_transition) }
|
1727
|
+
@transitions.perform
|
1728
|
+
|
1729
|
+
assert_nil @state_event_transition
|
1730
|
+
end
|
1731
|
+
|
1732
|
+
def test_should_not_have_event_transitions_during_action
|
1733
|
+
@transitions.perform { @state_event_transition = @object.send(:state_event_transition) }
|
1734
|
+
|
1735
|
+
assert_nil @state_event_transition
|
1736
|
+
end
|
1737
|
+
|
1738
|
+
def test_should_not_have_event_transitions_during_after_callbacks
|
1739
|
+
@state.after_transition {|object, transition| @after_state_event_transition = object.send(:state_event_transition) }
|
1740
|
+
@state.around_transition {|object, transition, block| block.call; @around_state_event_transition = object.send(:state_event_transition) }
|
1741
|
+
@transitions.perform
|
1742
|
+
|
1743
|
+
assert_nil @after_state_event_transition
|
1744
|
+
assert_nil @around_state_event_transition
|
1745
|
+
end
|
1746
|
+
end
|
1747
|
+
|
1748
|
+
class AttributeTransitionCollectionWithBeforeCallbackHaltTest < Test::Unit::TestCase
|
1749
|
+
def setup
|
1750
|
+
@klass = Class.new
|
1751
|
+
|
1752
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1753
|
+
@machine.state :idling
|
1754
|
+
@machine.event :ignite
|
1755
|
+
|
1756
|
+
@machine.before_transition {throw :halt}
|
1757
|
+
|
1758
|
+
@object = @klass.new
|
1759
|
+
@object.state_event = 'ignite'
|
1760
|
+
|
1761
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1762
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1763
|
+
])
|
1764
|
+
@result = @transitions.perform
|
1765
|
+
end
|
1766
|
+
|
1767
|
+
def test_should_not_succeed
|
1768
|
+
assert_equal false, @result
|
1769
|
+
end
|
1770
|
+
|
1771
|
+
def test_should_not_clear_event
|
1772
|
+
assert_equal :ignite, @object.state_event
|
1773
|
+
end
|
1774
|
+
|
1775
|
+
def test_should_not_write_event_transition
|
1776
|
+
assert_nil @object.send(:state_event_transition)
|
1777
|
+
end
|
1778
|
+
end
|
1779
|
+
|
1780
|
+
class AttributeTransitionCollectionWithBeforeCallbackErrorTest < Test::Unit::TestCase
|
1781
|
+
def setup
|
1782
|
+
@klass = Class.new
|
1783
|
+
|
1784
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1785
|
+
@machine.state :idling
|
1786
|
+
@machine.event :ignite
|
1787
|
+
|
1788
|
+
@machine.before_transition {raise ArgumentError}
|
1789
|
+
|
1790
|
+
@object = @klass.new
|
1791
|
+
@object.state_event = 'ignite'
|
1792
|
+
|
1793
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1794
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1795
|
+
])
|
1796
|
+
begin; @transitions.perform; rescue; end
|
1797
|
+
end
|
1798
|
+
|
1799
|
+
def test_should_not_clear_event
|
1800
|
+
assert_equal :ignite, @object.state_event
|
1801
|
+
end
|
1802
|
+
|
1803
|
+
def test_should_not_write_event_transition
|
1804
|
+
assert_nil @object.send(:state_event_transition)
|
1805
|
+
end
|
1806
|
+
end
|
1807
|
+
|
1808
|
+
class AttributeTransitionCollectionWithAroundCallbackBeforeYieldHaltTest < Test::Unit::TestCase
|
1809
|
+
def setup
|
1810
|
+
@klass = Class.new
|
1811
|
+
|
1812
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1813
|
+
@machine.state :idling
|
1814
|
+
@machine.event :ignite
|
1815
|
+
|
1816
|
+
@machine.around_transition {throw :halt}
|
1817
|
+
|
1818
|
+
@object = @klass.new
|
1819
|
+
@object.state_event = 'ignite'
|
1820
|
+
|
1821
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1822
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1823
|
+
])
|
1824
|
+
@result = @transitions.perform
|
1825
|
+
end
|
1826
|
+
|
1827
|
+
def test_should_not_succeed
|
1828
|
+
assert_equal false, @result
|
1829
|
+
end
|
1830
|
+
|
1831
|
+
def test_should_not_clear_event
|
1832
|
+
assert_equal :ignite, @object.state_event
|
1833
|
+
end
|
1834
|
+
|
1835
|
+
def test_should_not_write_event_transition
|
1836
|
+
assert_nil @object.send(:state_event_transition)
|
1837
|
+
end
|
1838
|
+
end
|
1839
|
+
|
1840
|
+
class AttributeTransitionCollectionWithAroundAfterYieldCallbackErrorTest < Test::Unit::TestCase
|
1841
|
+
def setup
|
1842
|
+
@klass = Class.new
|
1843
|
+
|
1844
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1845
|
+
@machine.state :idling
|
1846
|
+
@machine.event :ignite
|
1847
|
+
|
1848
|
+
@machine.before_transition {raise ArgumentError}
|
1849
|
+
|
1850
|
+
@object = @klass.new
|
1851
|
+
@object.state_event = 'ignite'
|
1852
|
+
|
1853
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1854
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1855
|
+
])
|
1856
|
+
begin; @transitions.perform; rescue; end
|
1857
|
+
end
|
1858
|
+
|
1859
|
+
def test_should_not_clear_event
|
1860
|
+
assert_equal :ignite, @object.state_event
|
1861
|
+
end
|
1862
|
+
|
1863
|
+
def test_should_not_write_event_transition
|
1864
|
+
assert_nil @object.send(:state_event_transition)
|
1865
|
+
end
|
1866
|
+
end
|
1867
|
+
|
1868
|
+
class AttributeTransitionCollectionWithSkippedAfterCallbacksTest < Test::Unit::TestCase
|
1869
|
+
def setup
|
1870
|
+
@klass = Class.new
|
1871
|
+
|
1872
|
+
@state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1873
|
+
@state.state :idling
|
1874
|
+
@state.event :ignite
|
1875
|
+
|
1876
|
+
@status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
|
1877
|
+
@status.state :second_gear
|
1878
|
+
@status.event :shift_up
|
1879
|
+
|
1880
|
+
@object = @klass.new
|
1881
|
+
@object.state_event = 'ignite'
|
1882
|
+
@object.status_event = 'shift_up'
|
1883
|
+
|
1884
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1885
|
+
@state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
|
1886
|
+
@status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
|
1887
|
+
], :after => false)
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
def test_should_clear_events
|
1891
|
+
@transitions.perform
|
1892
|
+
assert_nil @object.state_event
|
1893
|
+
assert_nil @object.status_event
|
1894
|
+
end
|
1895
|
+
|
1896
|
+
def test_should_write_event_transitions_if_success
|
1897
|
+
@transitions.perform { true }
|
1898
|
+
assert_equal @state_transition, @object.send(:state_event_transition)
|
1899
|
+
assert_equal @status_transition, @object.send(:status_event_transition)
|
1900
|
+
end
|
1901
|
+
|
1902
|
+
def test_should_not_write_event_transitions_if_failed
|
1903
|
+
@transitions.perform { false }
|
1904
|
+
assert_nil @object.send(:state_event_transition)
|
1905
|
+
assert_nil @object.send(:status_event_transition)
|
1906
|
+
end
|
1907
|
+
end
|
1908
|
+
|
1909
|
+
class AttributeTransitionCollectionWithAfterCallbackHaltTest < Test::Unit::TestCase
|
1910
|
+
def setup
|
1911
|
+
@klass = Class.new
|
1912
|
+
|
1913
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1914
|
+
@machine.state :idling
|
1915
|
+
@machine.event :ignite
|
1916
|
+
|
1917
|
+
@machine.after_transition {throw :halt}
|
1918
|
+
|
1919
|
+
@object = @klass.new
|
1920
|
+
@object.state_event = 'ignite'
|
1921
|
+
|
1922
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1923
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1924
|
+
])
|
1925
|
+
@result = @transitions.perform
|
1926
|
+
end
|
1927
|
+
|
1928
|
+
def test_should_succeed
|
1929
|
+
assert_equal true, @result
|
1930
|
+
end
|
1931
|
+
|
1932
|
+
def test_should_clear_event
|
1933
|
+
assert_nil @object.state_event
|
1934
|
+
end
|
1935
|
+
|
1936
|
+
def test_should_not_write_event_transition
|
1937
|
+
assert_nil @object.send(:state_event_transition)
|
1938
|
+
end
|
1939
|
+
end
|
1940
|
+
|
1941
|
+
class AttributeTransitionCollectionWithAfterCallbackErrorTest < Test::Unit::TestCase
|
1942
|
+
def setup
|
1943
|
+
@klass = Class.new
|
1944
|
+
|
1945
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1946
|
+
@machine.state :idling
|
1947
|
+
@machine.event :ignite
|
1948
|
+
|
1949
|
+
@machine.after_transition {raise ArgumentError}
|
1950
|
+
|
1951
|
+
@object = @klass.new
|
1952
|
+
@object.state_event = 'ignite'
|
1953
|
+
|
1954
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1955
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1956
|
+
])
|
1957
|
+
begin; @transitions.perform; rescue; end
|
1958
|
+
end
|
1959
|
+
|
1960
|
+
def test_should_clear_event
|
1961
|
+
assert_nil @object.state_event
|
1962
|
+
end
|
1963
|
+
|
1964
|
+
def test_should_not_write_event_transition
|
1965
|
+
assert_nil @object.send(:state_event_transition)
|
1966
|
+
end
|
1967
|
+
end
|
1968
|
+
|
1969
|
+
class AttributeTransitionCollectionWithAroundCallbackAfterYieldHaltTest < Test::Unit::TestCase
|
1970
|
+
def setup
|
1971
|
+
@klass = Class.new
|
1972
|
+
|
1973
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
1974
|
+
@machine.state :idling
|
1975
|
+
@machine.event :ignite
|
1976
|
+
|
1977
|
+
@machine.around_transition {|block| block.call; throw :halt}
|
1978
|
+
|
1979
|
+
@object = @klass.new
|
1980
|
+
@object.state_event = 'ignite'
|
1981
|
+
|
1982
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
1983
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
1984
|
+
])
|
1985
|
+
@result = @transitions.perform
|
1986
|
+
end
|
1987
|
+
|
1988
|
+
def test_should_succeed
|
1989
|
+
assert_equal true, @result
|
1990
|
+
end
|
1991
|
+
|
1992
|
+
def test_should_clear_event
|
1993
|
+
assert_nil @object.state_event
|
1994
|
+
end
|
1995
|
+
|
1996
|
+
def test_should_not_write_event_transition
|
1997
|
+
assert_nil @object.send(:state_event_transition)
|
1998
|
+
end
|
1999
|
+
end
|
2000
|
+
|
2001
|
+
class AttributeTransitionCollectionWithAfterCallbackErrorTest < Test::Unit::TestCase
|
2002
|
+
def setup
|
2003
|
+
@klass = Class.new
|
2004
|
+
|
2005
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
2006
|
+
@machine.state :idling
|
2007
|
+
@machine.event :ignite
|
2008
|
+
|
2009
|
+
@machine.around_transition {|block| block.call; raise ArgumentError}
|
2010
|
+
|
2011
|
+
@object = @klass.new
|
2012
|
+
@object.state_event = 'ignite'
|
2013
|
+
|
2014
|
+
@transitions = StateMachine::AttributeTransitionCollection.new([
|
2015
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
2016
|
+
])
|
2017
|
+
begin; @transitions.perform; rescue; end
|
2018
|
+
end
|
2019
|
+
|
2020
|
+
def test_should_clear_event
|
2021
|
+
assert_nil @object.state_event
|
2022
|
+
end
|
2023
|
+
|
2024
|
+
def test_should_not_write_event_transition
|
2025
|
+
assert_nil @object.send(:state_event_transition)
|
2026
|
+
end
|
2027
|
+
end
|
2028
|
+
|
2029
|
+
class AttributeTransitionCollectionMarshallingTest < Test::Unit::TestCase
|
2030
|
+
def setup
|
2031
|
+
@klass = Class.new
|
2032
|
+
self.class.const_set('Example', @klass)
|
2033
|
+
|
2034
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
|
2035
|
+
@machine.state :idling
|
2036
|
+
@machine.event :ignite
|
2037
|
+
|
2038
|
+
@object = @klass.new
|
2039
|
+
@object.state_event = 'ignite'
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
def test_should_marshal_during_before_callbacks
|
2043
|
+
@machine.before_transition {|object, transition| Marshal.dump(object)}
|
2044
|
+
assert_nothing_raised do
|
2045
|
+
transitions(:after => false).perform { true }
|
2046
|
+
transitions.perform { true }
|
2047
|
+
end
|
2048
|
+
end
|
2049
|
+
|
2050
|
+
def test_should_marshal_during_action
|
2051
|
+
assert_nothing_raised do
|
2052
|
+
transitions(:after => false).perform do
|
2053
|
+
Marshal.dump(@object)
|
2054
|
+
true
|
2055
|
+
end
|
2056
|
+
|
2057
|
+
transitions.perform do
|
2058
|
+
Marshal.dump(@object)
|
2059
|
+
true
|
2060
|
+
end
|
2061
|
+
end
|
2062
|
+
end
|
2063
|
+
|
2064
|
+
def test_should_marshal_during_after_callbacks
|
2065
|
+
@machine.after_transition {|object, transition| Marshal.dump(object)}
|
2066
|
+
assert_nothing_raised do
|
2067
|
+
transitions(:after => false).perform { true }
|
2068
|
+
transitions.perform { true }
|
2069
|
+
end
|
2070
|
+
end
|
2071
|
+
|
2072
|
+
def test_should_marshal_during_around_callbacks_before_yield
|
2073
|
+
@machine.around_transition {|object, transition, block| Marshal.dump(object); block.call}
|
2074
|
+
assert_nothing_raised do
|
2075
|
+
transitions(:after => false).perform { true }
|
2076
|
+
transitions.perform { true }
|
2077
|
+
end
|
2078
|
+
end
|
2079
|
+
|
2080
|
+
def test_should_marshal_during_around_callbacks_after_yield
|
2081
|
+
@machine.around_transition {|object, transition, block| block.call; Marshal.dump(object)}
|
2082
|
+
assert_nothing_raised do
|
2083
|
+
transitions(:after => false).perform { true }
|
2084
|
+
transitions.perform { true }
|
2085
|
+
end
|
2086
|
+
end
|
2087
|
+
|
2088
|
+
def teardown
|
2089
|
+
self.class.send(:remove_const, 'Example')
|
2090
|
+
end
|
2091
|
+
|
2092
|
+
private
|
2093
|
+
def transitions(options = {})
|
2094
|
+
StateMachine::AttributeTransitionCollection.new([
|
2095
|
+
StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
|
2096
|
+
], options)
|
2097
|
+
end
|
2098
|
+
end
|