state_machine 1.1.2 → 1.2.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/.gitignore +7 -11
- data/.travis.yml +49 -7
- data/Appraisals +255 -87
- data/CHANGELOG.md +30 -0
- data/README.md +142 -21
- data/Rakefile +1 -11
- data/examples/Gemfile +5 -0
- data/examples/Gemfile.lock +14 -0
- data/examples/auto_shop.rb +2 -0
- data/examples/car.rb +2 -0
- data/examples/doc/AutoShop.html +2856 -0
- data/examples/doc/AutoShop_state.png +0 -0
- data/examples/doc/Car.html +919 -0
- data/examples/doc/Car_state.png +0 -0
- data/examples/doc/TrafficLight.html +2230 -0
- data/examples/doc/TrafficLight_state.png +0 -0
- data/examples/doc/Vehicle.html +7921 -0
- data/examples/doc/Vehicle_state.png +0 -0
- data/examples/doc/_index.html +136 -0
- data/examples/doc/class_list.html +47 -0
- data/examples/doc/css/common.css +1 -0
- data/examples/doc/css/full_list.css +55 -0
- data/examples/doc/css/style.css +322 -0
- data/examples/doc/file_list.html +46 -0
- data/examples/doc/frames.html +13 -0
- data/examples/doc/index.html +136 -0
- data/examples/doc/js/app.js +205 -0
- data/examples/doc/js/full_list.js +173 -0
- data/examples/doc/js/jquery.js +16 -0
- data/examples/doc/method_list.html +734 -0
- data/examples/doc/top-level-namespace.html +105 -0
- data/examples/rails-rest/migration.rb +1 -5
- data/examples/rails-rest/view__form.html.erb +34 -0
- data/examples/rails-rest/view_edit.html.erb +2 -21
- data/examples/rails-rest/view_index.html.erb +6 -4
- data/examples/rails-rest/view_new.html.erb +2 -11
- data/examples/rails-rest/view_show.html.erb +5 -3
- data/examples/traffic_light.rb +2 -0
- data/examples/vehicle.rb +2 -0
- data/gemfiles/active_model-3.0.0.gemfile.lock +9 -6
- data/gemfiles/active_model-3.0.5.gemfile.lock +10 -7
- data/gemfiles/active_model-3.1.1.gemfile.lock +12 -10
- data/gemfiles/{active_model-3.2.0.gemfile → active_model-3.2.1.gemfile} +1 -1
- data/gemfiles/{graphviz-0.9.0.gemfile → active_model-3.2.12.gemfile} +1 -1
- data/gemfiles/active_model-3.2.12.gemfile.lock +36 -0
- data/gemfiles/{active_record-3.2.0.gemfile → active_model-3.2.13.rc1.gemfile} +1 -2
- data/gemfiles/active_model-3.2.13.rc1.gemfile.lock +36 -0
- data/gemfiles/active_model-4.0.0.gemfile +9 -0
- data/gemfiles/active_model-4.0.0.gemfile.lock +78 -0
- data/gemfiles/active_record-2.0.0.gemfile +2 -1
- data/gemfiles/active_record-2.0.0.gemfile.lock +15 -6
- data/gemfiles/active_record-2.0.5.gemfile +2 -1
- data/gemfiles/active_record-2.0.5.gemfile.lock +15 -6
- data/gemfiles/active_record-2.1.0.gemfile +2 -1
- data/gemfiles/active_record-2.1.0.gemfile.lock +15 -6
- data/gemfiles/active_record-2.1.2.gemfile +2 -1
- data/gemfiles/active_record-2.1.2.gemfile.lock +15 -6
- data/gemfiles/active_record-2.2.3.gemfile +2 -1
- data/gemfiles/active_record-2.2.3.gemfile.lock +15 -6
- data/gemfiles/active_record-2.3.12.gemfile +2 -1
- data/gemfiles/active_record-2.3.12.gemfile.lock +15 -6
- data/gemfiles/active_record-2.3.5.gemfile +9 -0
- data/gemfiles/active_record-2.3.5.gemfile.lock +39 -0
- data/gemfiles/active_record-3.0.0.gemfile +2 -1
- data/gemfiles/active_record-3.0.0.gemfile.lock +18 -11
- data/gemfiles/active_record-3.0.5.gemfile +2 -1
- data/gemfiles/active_record-3.0.5.gemfile.lock +19 -12
- data/gemfiles/active_record-3.1.1.gemfile +2 -1
- data/gemfiles/active_record-3.1.1.gemfile.lock +22 -16
- data/gemfiles/active_record-3.2.12.gemfile +9 -0
- data/gemfiles/active_record-3.2.12.gemfile.lock +51 -0
- data/gemfiles/active_record-3.2.13.rc1.gemfile +9 -0
- data/gemfiles/active_record-3.2.13.rc1.gemfile.lock +51 -0
- data/gemfiles/active_record-4.0.0.gemfile +11 -0
- data/gemfiles/active_record-4.0.0.gemfile.lock +83 -0
- data/gemfiles/data_mapper-0.10.2.gemfile +1 -0
- data/gemfiles/data_mapper-0.10.2.gemfile.lock +13 -9
- data/gemfiles/data_mapper-0.9.11.gemfile +1 -0
- data/gemfiles/data_mapper-0.9.11.gemfile.lock +31 -7
- data/gemfiles/data_mapper-0.9.4.gemfile.lock +25 -14
- data/gemfiles/data_mapper-0.9.7.gemfile +1 -0
- data/gemfiles/data_mapper-0.9.7.gemfile.lock +27 -15
- data/gemfiles/data_mapper-1.0.0.gemfile.lock +20 -17
- data/gemfiles/data_mapper-1.0.1.gemfile.lock +20 -17
- data/gemfiles/data_mapper-1.0.2.gemfile.lock +20 -17
- data/gemfiles/data_mapper-1.1.0.gemfile.lock +19 -16
- data/gemfiles/data_mapper-1.2.0.gemfile.lock +19 -16
- data/gemfiles/default.gemfile.lock +8 -5
- data/gemfiles/graphviz-0.9.17.gemfile +7 -0
- data/gemfiles/graphviz-0.9.17.gemfile.lock +29 -0
- data/gemfiles/graphviz-0.9.21.gemfile.lock +7 -4
- data/gemfiles/graphviz-1.0.0.gemfile.lock +7 -4
- data/gemfiles/graphviz-1.0.3.gemfile +7 -0
- data/gemfiles/graphviz-1.0.3.gemfile.lock +29 -0
- data/gemfiles/graphviz-1.0.8.gemfile +7 -0
- data/gemfiles/graphviz-1.0.8.gemfile.lock +29 -0
- data/gemfiles/mongo_mapper-0.10.0.gemfile +1 -0
- data/gemfiles/mongo_mapper-0.10.0.gemfile.lock +14 -11
- data/gemfiles/mongo_mapper-0.11.1.gemfile +7 -0
- data/gemfiles/mongo_mapper-0.11.1.gemfile.lock +44 -0
- data/gemfiles/mongo_mapper-0.11.2.gemfile +9 -0
- data/gemfiles/mongo_mapper-0.11.2.gemfile.lock +48 -0
- data/gemfiles/mongo_mapper-0.12.0.gemfile +9 -0
- data/gemfiles/mongo_mapper-0.12.0.gemfile.lock +48 -0
- data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +7 -4
- data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +7 -4
- data/gemfiles/mongoid-2.0.0.gemfile +2 -0
- data/gemfiles/mongoid-2.0.0.gemfile.lock +22 -18
- data/gemfiles/mongoid-2.1.4.gemfile +2 -0
- data/gemfiles/mongoid-2.1.4.gemfile.lock +21 -17
- data/gemfiles/mongoid-2.2.4.gemfile +2 -0
- data/gemfiles/mongoid-2.2.4.gemfile.lock +21 -17
- data/gemfiles/mongoid-2.3.3.gemfile +2 -0
- data/gemfiles/mongoid-2.3.3.gemfile.lock +21 -17
- data/gemfiles/mongoid-2.4.0.gemfile +9 -0
- data/gemfiles/mongoid-2.4.0.gemfile.lock +47 -0
- data/gemfiles/mongoid-2.4.10.gemfile +9 -0
- data/gemfiles/mongoid-2.4.10.gemfile.lock +47 -0
- data/gemfiles/mongoid-2.5.2.gemfile +9 -0
- data/gemfiles/mongoid-2.5.2.gemfile.lock +47 -0
- data/gemfiles/mongoid-2.6.0.gemfile +9 -0
- data/gemfiles/mongoid-2.6.0.gemfile.lock +47 -0
- data/gemfiles/mongoid-3.0.0.gemfile +8 -0
- data/gemfiles/mongoid-3.0.0.gemfile.lock +45 -0
- data/gemfiles/mongoid-3.0.22.gemfile +8 -0
- data/gemfiles/mongoid-3.0.22.gemfile.lock +45 -0
- data/gemfiles/mongoid-3.1.0.gemfile +8 -0
- data/gemfiles/mongoid-3.1.0.gemfile.lock +45 -0
- data/gemfiles/sequel-2.11.0.gemfile +2 -1
- data/gemfiles/sequel-2.11.0.gemfile.lock +11 -6
- data/gemfiles/sequel-2.12.0.gemfile +2 -1
- data/gemfiles/sequel-2.12.0.gemfile.lock +11 -6
- data/gemfiles/sequel-2.8.0.gemfile +2 -1
- data/gemfiles/sequel-2.8.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.0.0.gemfile +2 -1
- data/gemfiles/sequel-3.0.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.10.0.gemfile +9 -0
- data/gemfiles/sequel-3.10.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.13.0.gemfile +2 -1
- data/gemfiles/sequel-3.13.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.14.0.gemfile +2 -1
- data/gemfiles/sequel-3.14.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.23.0.gemfile +2 -1
- data/gemfiles/sequel-3.23.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.24.0.gemfile +2 -1
- data/gemfiles/sequel-3.24.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.29.0.gemfile +2 -1
- data/gemfiles/sequel-3.29.0.gemfile.lock +11 -6
- data/gemfiles/sequel-3.34.0.gemfile +9 -0
- data/gemfiles/sequel-3.34.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.35.0.gemfile +9 -0
- data/gemfiles/sequel-3.35.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.4.0.gemfile +9 -0
- data/gemfiles/sequel-3.4.0.gemfile.lock +33 -0
- data/gemfiles/sequel-3.44.0.gemfile +9 -0
- data/gemfiles/sequel-3.44.0.gemfile.lock +33 -0
- data/lib/state_machine.rb +6 -0
- data/lib/state_machine/branch.rb +9 -8
- data/lib/state_machine/callback.rb +2 -2
- data/lib/state_machine/core.rb +10 -0
- data/lib/state_machine/core_ext.rb +1 -0
- data/lib/state_machine/eval_helpers.rb +5 -3
- data/lib/state_machine/event.rb +17 -6
- data/lib/state_machine/graph.rb +92 -0
- data/lib/state_machine/integrations.rb +13 -1
- data/lib/state_machine/integrations/active_model.rb +14 -20
- data/lib/state_machine/integrations/active_model/observer.rb +3 -3
- data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
- data/lib/state_machine/integrations/active_record.rb +52 -25
- data/lib/state_machine/integrations/active_record/locale.rb +1 -1
- data/lib/state_machine/integrations/active_record/versions.rb +1 -17
- data/lib/state_machine/integrations/base.rb +15 -6
- data/lib/state_machine/integrations/data_mapper.rb +98 -35
- data/lib/state_machine/integrations/data_mapper/versions.rb +46 -8
- data/lib/state_machine/integrations/mongo_mapper.rb +39 -12
- data/lib/state_machine/integrations/mongo_mapper/locale.rb +1 -1
- data/lib/state_machine/integrations/mongo_mapper/versions.rb +3 -20
- data/lib/state_machine/integrations/mongoid.rb +52 -14
- data/lib/state_machine/integrations/mongoid/locale.rb +1 -1
- data/lib/state_machine/integrations/mongoid/versions.rb +52 -26
- data/lib/state_machine/integrations/sequel.rb +82 -33
- data/lib/state_machine/integrations/sequel/versions.rb +19 -44
- data/lib/state_machine/machine.rb +99 -59
- data/lib/state_machine/machine_collection.rb +1 -2
- data/lib/state_machine/macro_methods.rb +29 -0
- data/lib/state_machine/node_collection.rb +1 -1
- data/lib/state_machine/state.rb +18 -10
- data/lib/state_machine/state_context.rb +2 -2
- data/lib/state_machine/transition.rb +8 -1
- data/lib/state_machine/transition_collection.rb +2 -1
- data/lib/state_machine/version.rb +1 -1
- data/lib/state_machine/yard.rb +8 -0
- data/lib/state_machine/yard/handlers.rb +12 -0
- data/lib/state_machine/yard/handlers/base.rb +32 -0
- data/lib/state_machine/yard/handlers/event.rb +25 -0
- data/lib/state_machine/yard/handlers/machine.rb +344 -0
- data/lib/state_machine/yard/handlers/state.rb +25 -0
- data/lib/state_machine/yard/handlers/transition.rb +47 -0
- data/lib/state_machine/yard/templates.rb +3 -0
- data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
- data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
- data/lib/tasks/state_machine.rb +2 -1
- data/lib/yard-state_machine.rb +2 -0
- data/state_machine.gemspec +4 -3
- data/test/files/switch.rb +4 -0
- data/test/test_helper.rb +5 -0
- data/test/unit/branch_test.rb +117 -36
- data/test/unit/callback_test.rb +5 -2
- data/test/unit/eval_helpers_test.rb +49 -1
- data/test/unit/event_collection_test.rb +3 -1
- data/test/unit/event_test.rb +182 -12
- data/test/unit/graph_test.rb +98 -0
- data/test/unit/integrations/active_model_test.rb +82 -12
- data/test/unit/integrations/active_record_test.rb +393 -37
- data/test/unit/integrations/base_test.rb +7 -2
- data/test/unit/integrations/data_mapper_test.rb +326 -72
- data/test/unit/integrations/mongo_mapper_test.rb +338 -44
- data/test/unit/integrations/mongoid_test.rb +606 -98
- data/test/unit/integrations/sequel_test.rb +429 -102
- data/test/unit/integrations_test.rb +28 -6
- data/test/unit/machine_collection_test.rb +6 -2
- data/test/unit/machine_test.rb +134 -82
- data/test/unit/node_collection_test.rb +2 -2
- data/test/unit/path_test.rb +1 -1
- data/test/unit/state_test.rb +65 -21
- data/test/unit/transition_collection_test.rb +43 -23
- data/test/unit/transition_test.rb +8 -2
- metadata +303 -221
- data/gemfiles/active_model-3.2.0.gemfile.lock +0 -32
- data/gemfiles/active_record-3.2.0.gemfile.lock +0 -43
- data/gemfiles/graphviz-0.9.0.gemfile.lock +0 -26
@@ -2,8 +2,10 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
|
2
2
|
|
3
3
|
class EventCollectionByDefaultTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@
|
5
|
+
@klass = Class.new
|
6
|
+
@machine = StateMachine::Machine.new(@klass)
|
6
7
|
@events = StateMachine::EventCollection.new(@machine)
|
8
|
+
@object = @klass.new
|
7
9
|
end
|
8
10
|
|
9
11
|
def test_should_not_have_any_nodes
|
data/test/unit/event_test.rb
CHANGED
@@ -376,11 +376,6 @@ class EventTransitionsTest < Test::Unit::TestCase
|
|
376
376
|
assert_equal [:ignite], branch.event_requirement.values
|
377
377
|
end
|
378
378
|
|
379
|
-
def test_should_not_allow_except_to_option
|
380
|
-
exception = assert_raise(ArgumentError) {@event.transition(:except_to => :parked)}
|
381
|
-
assert_equal 'Invalid key(s): except_to', exception.message
|
382
|
-
end
|
383
|
-
|
384
379
|
def test_should_not_allow_except_on_option
|
385
380
|
exception = assert_raise(ArgumentError) {@event.transition(:except_on => :ignite)}
|
386
381
|
assert_equal 'Invalid key(s): except_on', exception.message
|
@@ -398,6 +393,10 @@ class EventTransitionsTest < Test::Unit::TestCase
|
|
398
393
|
assert_nothing_raised {@event.transition(:except_from => :idling)}
|
399
394
|
end
|
400
395
|
|
396
|
+
def test_should_allow_except_to_option
|
397
|
+
assert_nothing_raised {@event.transition(:except_to => :idling)}
|
398
|
+
end
|
399
|
+
|
401
400
|
def test_should_allow_transitioning_from_a_single_state
|
402
401
|
assert @event.transition(:parked => :idling)
|
403
402
|
end
|
@@ -405,6 +404,10 @@ class EventTransitionsTest < Test::Unit::TestCase
|
|
405
404
|
def test_should_allow_transitioning_from_multiple_states
|
406
405
|
assert @event.transition([:parked, :idling] => :idling)
|
407
406
|
end
|
407
|
+
|
408
|
+
def test_should_allow_transitions_to_multiple_states
|
409
|
+
assert @event.transition(:parked => [:parked, :idling])
|
410
|
+
end
|
408
411
|
|
409
412
|
def test_should_have_transitions
|
410
413
|
branch = @event.transition(:to => :idling)
|
@@ -775,6 +778,150 @@ class EventWithTransitionWithNilToStateTest < Test::Unit::TestCase
|
|
775
778
|
end
|
776
779
|
end
|
777
780
|
|
781
|
+
class EventWithTransitionWithLoopbackStateTest < Test::Unit::TestCase
|
782
|
+
def setup
|
783
|
+
@klass = Class.new
|
784
|
+
@machine = StateMachine::Machine.new(@klass)
|
785
|
+
@machine.state :parked
|
786
|
+
|
787
|
+
@machine.events << @event = StateMachine::Event.new(@machine, :park)
|
788
|
+
@event.transition(:from => :parked, :to => StateMachine::LoopbackMatcher.instance)
|
789
|
+
|
790
|
+
@object = @klass.new
|
791
|
+
@object.state = 'parked'
|
792
|
+
end
|
793
|
+
|
794
|
+
def test_should_be_able_to_fire
|
795
|
+
assert @event.can_fire?(@object)
|
796
|
+
end
|
797
|
+
|
798
|
+
def test_should_have_a_transition
|
799
|
+
transition = @event.transition_for(@object)
|
800
|
+
assert_not_nil transition
|
801
|
+
assert_equal 'parked', transition.from
|
802
|
+
assert_equal 'parked', transition.to
|
803
|
+
assert_equal :park, transition.event
|
804
|
+
end
|
805
|
+
|
806
|
+
def test_should_fire
|
807
|
+
assert @event.fire(@object)
|
808
|
+
end
|
809
|
+
|
810
|
+
def test_should_not_change_the_current_state
|
811
|
+
@event.fire(@object)
|
812
|
+
assert_equal 'parked', @object.state
|
813
|
+
end
|
814
|
+
end
|
815
|
+
|
816
|
+
class EventWithTransitionWithBlacklistedToStateTest < Test::Unit::TestCase
|
817
|
+
def setup
|
818
|
+
@klass = Class.new
|
819
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
820
|
+
@machine.state :parked, :idling, :first_gear, :second_gear
|
821
|
+
|
822
|
+
@machine.events << @event = StateMachine::Event.new(@machine, :ignite)
|
823
|
+
@event.transition(:from => :parked, :to => StateMachine::BlacklistMatcher.new([:parked, :idling]))
|
824
|
+
|
825
|
+
@object = @klass.new
|
826
|
+
@object.state = 'parked'
|
827
|
+
end
|
828
|
+
|
829
|
+
def test_should_be_able_to_fire
|
830
|
+
assert @event.can_fire?(@object)
|
831
|
+
end
|
832
|
+
|
833
|
+
def test_should_have_a_transition
|
834
|
+
transition = @event.transition_for(@object)
|
835
|
+
assert_not_nil transition
|
836
|
+
assert_equal 'parked', transition.from
|
837
|
+
assert_equal 'first_gear', transition.to
|
838
|
+
assert_equal :ignite, transition.event
|
839
|
+
end
|
840
|
+
|
841
|
+
def test_should_allow_loopback_first_when_possible
|
842
|
+
@event.transition(:from => :second_gear, :to => StateMachine::BlacklistMatcher.new([:parked, :idling]))
|
843
|
+
@object.state = 'second_gear'
|
844
|
+
|
845
|
+
transition = @event.transition_for(@object)
|
846
|
+
assert_not_nil transition
|
847
|
+
assert_equal 'second_gear', transition.from
|
848
|
+
assert_equal 'second_gear', transition.to
|
849
|
+
assert_equal :ignite, transition.event
|
850
|
+
end
|
851
|
+
|
852
|
+
def test_should_allow_specific_transition_selection_using_to
|
853
|
+
transition = @event.transition_for(@object, :from => :parked, :to => :second_gear)
|
854
|
+
|
855
|
+
assert_not_nil transition
|
856
|
+
assert_equal 'parked', transition.from
|
857
|
+
assert_equal 'second_gear', transition.to
|
858
|
+
assert_equal :ignite, transition.event
|
859
|
+
end
|
860
|
+
|
861
|
+
def test_should_not_allow_transition_selection_if_not_matching
|
862
|
+
transition = @event.transition_for(@object, :from => :parked, :to => :parked)
|
863
|
+
assert_nil transition
|
864
|
+
end
|
865
|
+
|
866
|
+
def test_should_fire
|
867
|
+
assert @event.fire(@object)
|
868
|
+
end
|
869
|
+
|
870
|
+
def test_should_change_the_current_state
|
871
|
+
@event.fire(@object)
|
872
|
+
assert_equal 'first_gear', @object.state
|
873
|
+
end
|
874
|
+
end
|
875
|
+
|
876
|
+
class EventWithTransitionWithWhitelistedToStateTest < Test::Unit::TestCase
|
877
|
+
def setup
|
878
|
+
@klass = Class.new
|
879
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
880
|
+
@machine.state :parked, :idling, :first_gear, :second_gear
|
881
|
+
|
882
|
+
@machine.events << @event = StateMachine::Event.new(@machine, :ignite)
|
883
|
+
@event.transition(:from => :parked, :to => StateMachine::WhitelistMatcher.new([:first_gear, :second_gear]))
|
884
|
+
|
885
|
+
@object = @klass.new
|
886
|
+
@object.state = 'parked'
|
887
|
+
end
|
888
|
+
|
889
|
+
def test_should_be_able_to_fire
|
890
|
+
assert @event.can_fire?(@object)
|
891
|
+
end
|
892
|
+
|
893
|
+
def test_should_have_a_transition
|
894
|
+
transition = @event.transition_for(@object)
|
895
|
+
assert_not_nil transition
|
896
|
+
assert_equal 'parked', transition.from
|
897
|
+
assert_equal 'first_gear', transition.to
|
898
|
+
assert_equal :ignite, transition.event
|
899
|
+
end
|
900
|
+
|
901
|
+
def test_should_allow_specific_transition_selection_using_to
|
902
|
+
transition = @event.transition_for(@object, :from => :parked, :to => :second_gear)
|
903
|
+
|
904
|
+
assert_not_nil transition
|
905
|
+
assert_equal 'parked', transition.from
|
906
|
+
assert_equal 'second_gear', transition.to
|
907
|
+
assert_equal :ignite, transition.event
|
908
|
+
end
|
909
|
+
|
910
|
+
def test_should_not_allow_transition_selection_if_not_matching
|
911
|
+
transition = @event.transition_for(@object, :from => :parked, :to => :parked)
|
912
|
+
assert_nil transition
|
913
|
+
end
|
914
|
+
|
915
|
+
def test_should_fire
|
916
|
+
assert @event.fire(@object)
|
917
|
+
end
|
918
|
+
|
919
|
+
def test_should_change_the_current_state
|
920
|
+
@event.fire(@object)
|
921
|
+
assert_equal 'first_gear', @object.state
|
922
|
+
end
|
923
|
+
end
|
924
|
+
|
778
925
|
class EventWithMultipleTransitionsTest < Test::Unit::TestCase
|
779
926
|
def setup
|
780
927
|
@klass = Class.new
|
@@ -783,7 +930,7 @@ class EventWithMultipleTransitionsTest < Test::Unit::TestCase
|
|
783
930
|
|
784
931
|
@machine.events << @event = StateMachine::Event.new(@machine, :ignite)
|
785
932
|
@event.transition(:idling => :idling)
|
786
|
-
@event.transition(:parked => :idling)
|
933
|
+
@event.transition(:parked => :idling)
|
787
934
|
@event.transition(:parked => :parked)
|
788
935
|
|
789
936
|
@object = @klass.new
|
@@ -973,6 +1120,7 @@ class EventWithMarshallingTest < Test::Unit::TestCase
|
|
973
1120
|
|
974
1121
|
def test_should_marshal_during_action
|
975
1122
|
@klass.class_eval do
|
1123
|
+
remove_method :save
|
976
1124
|
def save
|
977
1125
|
Marshal.dump(self)
|
978
1126
|
end
|
@@ -1002,25 +1150,47 @@ begin
|
|
1002
1150
|
@machine = StateMachine::Machine.new(Class.new, :initial => :parked)
|
1003
1151
|
@machine.other_states(*states)
|
1004
1152
|
|
1005
|
-
graph =
|
1006
|
-
states.each {|state| graph.
|
1153
|
+
@graph = StateMachine::Graph.new('test')
|
1154
|
+
states.each {|state| @graph.add_nodes(state.to_s)}
|
1007
1155
|
|
1008
1156
|
@machine.events << @event = StateMachine::Event.new(@machine , :park)
|
1009
1157
|
@event.transition :parked => :idling
|
1010
1158
|
@event.transition :first_gear => :parked
|
1011
1159
|
@event.transition :except_from => :parked, :to => :parked
|
1012
1160
|
|
1013
|
-
@
|
1161
|
+
@event.draw(@graph)
|
1014
1162
|
end
|
1015
1163
|
|
1016
1164
|
def test_should_generate_edges_for_each_transition
|
1017
|
-
assert_equal 4, @
|
1165
|
+
assert_equal 4, @graph.edge_count
|
1018
1166
|
end
|
1019
1167
|
|
1020
1168
|
def test_should_use_event_name_for_edge_label
|
1021
|
-
assert_equal 'park', @
|
1169
|
+
assert_equal 'park', @graph.get_edge_at_index(0)['label'].to_s.gsub('"', '')
|
1170
|
+
end
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
class EventDrawingWithHumanNameTest < Test::Unit::TestCase
|
1174
|
+
def setup
|
1175
|
+
states = [:parked, :idling]
|
1176
|
+
|
1177
|
+
@machine = StateMachine::Machine.new(Class.new, :initial => :parked)
|
1178
|
+
@machine.other_states(*states)
|
1179
|
+
|
1180
|
+
graph = StateMachine::Graph.new('test')
|
1181
|
+
states.each {|state| graph.add_nodes(state.to_s)}
|
1182
|
+
|
1183
|
+
@machine.events << @event = StateMachine::Event.new(@machine , :park, :human_name => 'Park')
|
1184
|
+
@event.transition :parked => :idling
|
1185
|
+
|
1186
|
+
@event.draw(graph, :human_name => true)
|
1187
|
+
@edge = graph.get_edge_at_index(0)
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
def test_should_use_event_human_name_for_edge_label
|
1191
|
+
assert_equal 'Park', @edge['label'].to_s.gsub('"', '')
|
1022
1192
|
end
|
1023
1193
|
end
|
1024
1194
|
rescue LoadError
|
1025
|
-
$stderr.puts 'Skipping GraphViz StateMachine::Event tests. `gem install ruby-graphviz` >= v0.9.
|
1195
|
+
$stderr.puts 'Skipping GraphViz StateMachine::Event tests. `gem install ruby-graphviz` >= v0.9.17 and try again.'
|
1026
1196
|
end unless ENV['TRAVIS']
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
|
3
|
+
begin
|
4
|
+
# Load library
|
5
|
+
require 'graphviz'
|
6
|
+
|
7
|
+
class GraphDefaultTest < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
@graph = StateMachine::Graph.new('test')
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_have_a_default_font
|
13
|
+
assert_equal 'Arial', @graph.font
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_use_current_directory_for_filepath
|
17
|
+
assert_equal './test.png', @graph.file_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_have_a_default_file_format
|
21
|
+
assert_equal 'png', @graph.file_format
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_have_a_default_orientation
|
25
|
+
assert_equal 'TB', @graph[:rankdir].source
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class GraphNodesTest < Test::Unit::TestCase
|
30
|
+
def setup
|
31
|
+
@graph = StateMachine::Graph.new('test')
|
32
|
+
@node = @graph.add_nodes('parked', :shape => 'ellipse')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_return_generated_node
|
36
|
+
assert_not_nil @node
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_use_specified_name
|
40
|
+
assert_equal @node, @graph.get_node('parked')
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_use_specified_options
|
44
|
+
assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_set_default_font
|
48
|
+
assert_equal 'Arial', @node['fontname'].to_s.gsub('"', '')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class GraphEdgesTest < Test::Unit::TestCase
|
53
|
+
def setup
|
54
|
+
@graph = StateMachine::Graph.new('test')
|
55
|
+
@graph.add_nodes('parked', :shape => 'ellipse')
|
56
|
+
@graph.add_nodes('idling', :shape => 'ellipse')
|
57
|
+
@edge = @graph.add_edges('parked', 'idling', :label => 'ignite')
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_return_generated_edge
|
61
|
+
assert_not_nil @edge
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_should_use_specified_nodes
|
65
|
+
assert_equal 'parked', @edge.node_one(false)
|
66
|
+
assert_equal 'idling', @edge.node_two(false)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_should_use_specified_options
|
70
|
+
assert_equal 'ignite', @edge['label'].to_s.gsub('"', '')
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_should_set_default_font
|
74
|
+
assert_equal 'Arial', @edge['fontname'].to_s.gsub('"', '')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class GraphOutputTest < Test::Unit::TestCase
|
79
|
+
def setup
|
80
|
+
@graph_name = "test_#{rand(1000000)}"
|
81
|
+
@graph = StateMachine::Graph.new(@graph_name)
|
82
|
+
@graph.add_nodes('parked', :shape => 'ellipse')
|
83
|
+
@graph.add_nodes('idling', :shape => 'ellipse')
|
84
|
+
@graph.add_edges('parked', 'idling', :label => 'ignite')
|
85
|
+
@graph.output
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_should_save_file
|
89
|
+
assert File.exist?("./#{@graph_name}.png")
|
90
|
+
end
|
91
|
+
|
92
|
+
def teardown
|
93
|
+
FileUtils.rm Dir["./#{@graph_name}.png"]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
rescue LoadError
|
97
|
+
$stderr.puts 'Skipping GraphViz StateMachine::Graph tests. `gem install ruby-graphviz` >= v0.9.17 and try again.'
|
98
|
+
end unless ENV['TRAVIS']
|
@@ -1,7 +1,12 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
|
2
2
|
|
3
3
|
require 'active_model'
|
4
|
-
|
4
|
+
if defined?(ActiveModel::VERSION) && ActiveModel::VERSION::MAJOR >= 4
|
5
|
+
require 'rails/observers/active_model/active_model'
|
6
|
+
require 'active_model/mass_assignment_security'
|
7
|
+
else
|
8
|
+
require 'active_model/observing'
|
9
|
+
end
|
5
10
|
require 'active_support/all'
|
6
11
|
|
7
12
|
module ActiveModelTest
|
@@ -15,9 +20,9 @@ module ActiveModelTest
|
|
15
20
|
# Simple ActiveModel superclass
|
16
21
|
parent = Class.new do
|
17
22
|
def self.model_attribute(name)
|
18
|
-
define_method(name) { instance_variable_get("@#{name}") }
|
23
|
+
define_method(name) { instance_variable_defined?("@#{name}") ? instance_variable_get("@#{name}") : nil }
|
19
24
|
define_method("#{name}=") do |value|
|
20
|
-
send("#{name}_will_change!") if self.class <= ActiveModel::Dirty && value !=
|
25
|
+
send("#{name}_will_change!") if self.class <= ActiveModel::Dirty && value != send(name)
|
21
26
|
instance_variable_set("@#{name}", value)
|
22
27
|
end
|
23
28
|
end
|
@@ -92,7 +97,7 @@ module ActiveModelTest
|
|
92
97
|
end
|
93
98
|
|
94
99
|
def test_should_have_no_defaults
|
95
|
-
assert_equal
|
100
|
+
assert_equal({}, StateMachine::Integrations::ActiveModel.defaults)
|
96
101
|
end
|
97
102
|
|
98
103
|
def test_should_have_a_locale_path
|
@@ -186,8 +191,7 @@ module ActiveModelTest
|
|
186
191
|
end
|
187
192
|
|
188
193
|
def test_should_raise_exception_for_predicate_without_parameters
|
189
|
-
|
190
|
-
assert_equal 'wrong number of arguments (1 for 2)', exception.message
|
194
|
+
assert_raise(ArgumentError) { @record.state? }
|
191
195
|
end
|
192
196
|
|
193
197
|
def test_should_return_false_for_predicate_if_does_not_match_current_value
|
@@ -232,7 +236,7 @@ module ActiveModelTest
|
|
232
236
|
def setup
|
233
237
|
@model = new_model
|
234
238
|
@machine = StateMachine::Machine.new(@model, :initial => :parked, :integration => :active_model)
|
235
|
-
@machine.state
|
239
|
+
@machine.state :idling
|
236
240
|
end
|
237
241
|
|
238
242
|
def test_should_allow_nil_initial_state_when_static
|
@@ -513,11 +517,21 @@ module ActiveModelTest
|
|
513
517
|
def test_should_run_around_callbacks
|
514
518
|
before_called = false
|
515
519
|
after_called = false
|
516
|
-
|
520
|
+
ensure_called = 0
|
521
|
+
@machine.around_transition do |block|
|
522
|
+
before_called = true
|
523
|
+
begin
|
524
|
+
block.call
|
525
|
+
ensure
|
526
|
+
ensure_called += 1
|
527
|
+
end
|
528
|
+
after_called = true
|
529
|
+
end
|
517
530
|
|
518
531
|
@transition.perform
|
519
532
|
assert before_called
|
520
533
|
assert after_called
|
534
|
+
assert_equal ensure_called, 1
|
521
535
|
end
|
522
536
|
|
523
537
|
def test_should_include_transition_states_in_known_states
|
@@ -584,7 +598,7 @@ module ActiveModelTest
|
|
584
598
|
end
|
585
599
|
|
586
600
|
class MachineWithFailedAfterCallbacksTest < BaseTestCase
|
587
|
-
|
601
|
+
def setup
|
588
602
|
@callbacks = []
|
589
603
|
|
590
604
|
@model = new_model
|
@@ -727,6 +741,40 @@ module ActiveModelTest
|
|
727
741
|
end
|
728
742
|
end
|
729
743
|
|
744
|
+
class ObserverUpdateTest < BaseTestCase
|
745
|
+
def setup
|
746
|
+
@model = new_model { include ActiveModel::Observing }
|
747
|
+
@machine = StateMachine::Machine.new(@model)
|
748
|
+
@machine.state :parked, :idling
|
749
|
+
@machine.event :ignite
|
750
|
+
|
751
|
+
@record = @model.new(:state => 'parked')
|
752
|
+
@transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
|
753
|
+
|
754
|
+
@observer_update = StateMachine::Integrations::ActiveModel::ObserverUpdate.new(:before_transition, @record, @transition)
|
755
|
+
end
|
756
|
+
|
757
|
+
def test_should_have_method
|
758
|
+
assert_equal :before_transition, @observer_update.method
|
759
|
+
end
|
760
|
+
|
761
|
+
def test_should_have_object
|
762
|
+
assert_equal @record, @observer_update.object
|
763
|
+
end
|
764
|
+
|
765
|
+
def test_should_have_transition
|
766
|
+
assert_equal @transition, @observer_update.transition
|
767
|
+
end
|
768
|
+
|
769
|
+
def test_should_include_object_and_transition_in_args
|
770
|
+
assert_equal [@record, @transition], @observer_update.args
|
771
|
+
end
|
772
|
+
|
773
|
+
def test_should_use_record_class_as_class
|
774
|
+
assert_equal @model, @observer_update.class
|
775
|
+
end
|
776
|
+
end
|
777
|
+
|
730
778
|
class MachineWithObserversTest < BaseTestCase
|
731
779
|
def setup
|
732
780
|
@model = new_model { include ActiveModel::Observing }
|
@@ -750,7 +798,6 @@ module ActiveModelTest
|
|
750
798
|
:before_transition
|
751
799
|
]
|
752
800
|
|
753
|
-
notified = false
|
754
801
|
observer = new_observer(@model) do
|
755
802
|
callbacks.each do |callback|
|
756
803
|
define_method(callback) do |*args|
|
@@ -765,6 +812,31 @@ module ActiveModelTest
|
|
765
812
|
assert_equal callbacks, instance.notifications
|
766
813
|
end
|
767
814
|
|
815
|
+
def test_should_call_no_transition_callbacks_when_observers_disabled
|
816
|
+
return unless ActiveModel::VERSION::MAJOR >= 3 && ActiveModel::VERSION::MINOR >= 1
|
817
|
+
|
818
|
+
callbacks = [
|
819
|
+
:before_ignite,
|
820
|
+
:before_transition
|
821
|
+
]
|
822
|
+
|
823
|
+
observer = new_observer(@model) do
|
824
|
+
callbacks.each do |callback|
|
825
|
+
define_method(callback) do |*args|
|
826
|
+
notifications << callback
|
827
|
+
end
|
828
|
+
end
|
829
|
+
end
|
830
|
+
|
831
|
+
instance = observer.instance
|
832
|
+
|
833
|
+
@model.observers.disable(observer) do
|
834
|
+
@transition.perform
|
835
|
+
end
|
836
|
+
|
837
|
+
assert_equal [], instance.notifications
|
838
|
+
end
|
839
|
+
|
768
840
|
def test_should_pass_record_and_transition_to_before_callbacks
|
769
841
|
observer = new_observer(@model) do
|
770
842
|
def before_transition(*args)
|
@@ -809,7 +881,6 @@ module ActiveModelTest
|
|
809
881
|
:before_transition_state_from_nil
|
810
882
|
]
|
811
883
|
|
812
|
-
notified = false
|
813
884
|
observer = new_observer(@model) do
|
814
885
|
callbacks.each do |callback|
|
815
886
|
define_method(callback) do |*args|
|
@@ -833,7 +904,6 @@ module ActiveModelTest
|
|
833
904
|
:before_transition_state_to_nil
|
834
905
|
]
|
835
906
|
|
836
|
-
notified = false
|
837
907
|
observer = new_observer(@model) do
|
838
908
|
callbacks.each do |callback|
|
839
909
|
define_method(callback) do |*args|
|