/test/unit/transition_collection_test.rb
Ruby | 2168 lines | 1698 code | 470 blank | 0 comment | 5 complexity | 3638f008300badb989470bf2bc75098c MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
- class TransitionCollectionTest < Test::Unit::TestCase
- def test_should_raise_exception_if_invalid_option_specified
- exception = assert_raise(ArgumentError) {StateMachine::TransitionCollection.new([], :invalid => true)}
- assert_equal 'Invalid key(s): invalid', exception.message
- end
-
- def test_should_raise_exception_if_multiple_transitions_for_same_attribute_specified
- @klass = Class.new
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked)
- @machine.state :parked, :idling
- @machine.event :ignite
-
- @object = @klass.new
-
- exception = assert_raise(ArgumentError) do
- StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ])
- end
- assert_equal 'Cannot perform multiple transitions in parallel for the same state machine attribute', exception.message
- end
- end
- class TransitionCollectionByDefaultTest < Test::Unit::TestCase
- def setup
- @transitions = StateMachine::TransitionCollection.new
- end
-
- def test_should_not_skip_actions
- assert !@transitions.skip_actions
- end
-
- def test_should_not_skip_after
- assert !@transitions.skip_after
- end
-
- def test_should_use_transaction
- assert @transitions.use_transaction
- end
-
- def test_should_be_empty
- assert @transitions.empty?
- end
- end
- class TransitionCollectionEmptyWithoutBlockTest < Test::Unit::TestCase
- def setup
- @transitions = StateMachine::TransitionCollection.new
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
- end
- class TransitionCollectionEmptyWithBlockTest < Test::Unit::TestCase
- def setup
- @transitions = StateMachine::TransitionCollection.new
- end
-
- def test_should_raise_exception_if_perform_raises_exception
- assert_raise(ArgumentError) { @transitions.perform { raise ArgumentError } }
- end
-
- def test_should_use_block_result_if_non_boolean
- assert_equal 1, @transitions.perform { 1 }
- end
-
- def test_should_use_block_result_if_false
- assert_equal false, @transitions.perform { false }
- end
-
- def test_should_use_block_reslut_if_nil
- assert_equal nil, @transitions.perform { nil }
- end
- end
- class TransitionCollectionInvalidTest < Test::Unit::TestCase
- def setup
- @transitions = StateMachine::TransitionCollection.new([false])
- end
-
- def test_should_be_empty
- assert @transitions.empty?
- end
-
- def test_should_not_succeed
- assert_equal false, @transitions.perform
- end
-
- def test_should_not_run_perform_block
- ran_block = false
- @transitions.perform { ran_block = true }
- assert !ran_block
- end
- end
- class TransitionCollectionPartialInvalidTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_accessor :ran_transaction
- end
-
- @callbacks = []
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked)
- @machine.state :idling
- @machine.event :ignite
- @machine.before_transition {@callbacks << :before}
- @machine.after_transition {@callbacks << :after}
- @machine.around_transition {|block| @callbacks << :around_before; block.call; @callbacks << :around_after}
-
- class << @machine
- def within_transaction(object)
- object.ran_transaction = true
- end
- end
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
- false
- ])
- end
-
- def test_should_not_store_invalid_values
- assert_equal 1, @transitions.length
- end
-
- def test_should_not_succeed
- assert_equal false, @transitions.perform
- end
-
- def test_should_not_start_transaction
- assert !@object.ran_transaction
- end
-
- def test_should_not_run_perform_block
- ran_block = false
- @transitions.perform { ran_block = true }
- assert !ran_block
- end
-
- def test_should_not_run_before_callbacks
- assert !@callbacks.include?(:before)
- end
-
- def test_should_not_persist_states
- assert_equal 'parked', @object.state
- end
-
- def test_should_not_run_after_callbacks
- assert !@callbacks.include?(:after)
- end
-
- def test_should_not_run_around_callbacks_before_yield
- assert !@callbacks.include?(:around_before)
- end
-
- def test_should_not_run_around_callbacks_after_yield
- assert !@callbacks.include?(:around_after)
- end
- end
- class TransitionCollectionValidTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :persisted
-
- def initialize
- @persisted = nil
- super
- @persisted = []
- end
-
- def state=(value)
- @persisted << 'state' if @persisted
- @state = value
- end
-
- def status=(value)
- @persisted << 'status' if @persisted
- @status = value
- end
- end
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked)
- @state.state :idling
- @state.event :ignite
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
-
- @result = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ]).perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_persist_each_state
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_persist_in_order
- assert_equal ['state', 'status'], @object.persisted
- end
-
- def test_should_store_results_in_transitions
- assert_nil @state_transition.result
- assert_nil @status_transition.result
- end
- end
- class TransitionCollectionWithoutTransactionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_accessor :ran_transaction
- end
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked)
- @machine.state :idling
- @machine.event :ignite
-
- class << @machine
- def within_transaction(object)
- object.ran_transaction = true
- end
- end
-
- @object = @klass.new
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ], :transaction => false)
- @transitions.perform
- end
-
- def test_should_not_run_within_transaction
- assert !@object.ran_transaction
- end
- end
- class TransitionCollectionWithTransactionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_accessor :running_transaction, :cancelled_transaction
- end
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked)
- @machine.state :idling
- @machine.event :ignite
-
- class << @machine
- def within_transaction(object)
- object.running_transaction = true
- object.cancelled_transaction = yield == false
- object.running_transaction = false
- end
- end
-
- @object = @klass.new
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ], :transaction => true)
- end
-
- def test_should_run_before_callbacks_within_transaction
- @machine.before_transition {|object| @in_transaction = object.running_transaction}
- @transitions.perform
-
- assert @in_transaction
- end
-
- def test_should_run_action_within_transaction
- @transitions.perform { @in_transaction = @object.running_transaction }
-
- assert @in_transaction
- end
-
- def test_should_run_after_callbacks_within_transaction
- @machine.after_transition {|object| @in_transaction = object.running_transaction}
- @transitions.perform
-
- assert @in_transaction
- end
-
- def test_should_cancel_the_transaction_on_before_halt
- @machine.before_transition {throw :halt}
-
- @transitions.perform
- assert @object.cancelled_transaction
- end
-
- def test_should_cancel_the_transaction_on_action_failure
- @transitions.perform { false }
- assert @object.cancelled_transaction
- end
-
- def test_should_not_cancel_the_transaction_on_after_halt
- @machine.after_transition {throw :halt}
-
- @transitions.perform
- assert !@object.cancelled_transaction
- end
- end
- class TransitionCollectionWithEmptyActionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
-
- @object.state = 'idling'
- @object.status = 'second_gear'
-
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_store_results_in_transitions
- assert_nil @state_transition.result
- assert_nil @status_transition.result
- end
- end
- class TransitionCollectionWithSkippedActionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :actions
-
- def save_state
- (@actions ||= []) << :save_state
- :save_state
- end
-
- def save_status
- (@actions ||= []) << :save_status
- :save_status
- end
- end
-
- @callbacks = []
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
- @state.state :idling
- @state.event :ignite
- @state.before_transition {@callbacks << :state_before}
- @state.after_transition {@callbacks << :state_after}
- @state.around_transition {|block| @callbacks << :state_around_before; block.call; @callbacks << :state_around_after}
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
- @status.state :second_gear
- @status.event :shift_up
- @status.before_transition {@callbacks << :status_before}
- @status.after_transition {@callbacks << :status_after}
- @status.around_transition {|block| @callbacks << :status_around_before; block.call; @callbacks << :status_around_after}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ], :actions => false)
- @result = @transitions.perform
- end
-
- def test_should_skip_actions
- assert_equal true, @transitions.skip_actions
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_not_run_actions
- assert_nil @object.actions
- end
-
- def test_should_store_results_in_transitions
- assert_nil @state_transition.result
- assert_nil @status_transition.result
- end
-
- def test_should_run_all_callbacks
- assert_equal [:state_before, :state_around_before, :status_before, :status_around_before, :status_around_after, :status_after, :state_around_after, :state_after], @callbacks
- end
- end
- class TransitionCollectionWithSkippedActionsAndBlockTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
- @machine.state :idling
- @machine.event :ignite
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ], :actions => false)
- @result = @transitions.perform { @ran_block = true; 1 }
- end
-
- def test_should_succeed
- assert_equal 1, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- end
-
- def test_should_run_block
- assert @ran_block
- end
-
- def test_should_store_results_in_transitions
- assert_equal 1, @state_transition.result
- end
- end
- class TransitionCollectionWithDuplicateActionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :actions
-
- def save
- (@actions ||= []) << :save
- :save
- end
- end
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal :save, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_run_action_once
- assert_equal [:save], @object.actions
- end
-
- def test_should_store_results_in_transitions
- assert_equal :save, @state_transition.result
- assert_equal :save, @status_transition.result
- end
- end
- class TransitionCollectionWithDifferentActionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :actions
-
- def save_state
- (@actions ||= []) << :save_state
- :save_state
- end
-
- def save_status
- (@actions ||= []) << :save_status
- :save_status
- end
- end
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
- end
-
- def test_should_succeed
- assert_equal true, @transitions.perform
- end
-
- def test_should_persist_states
- @transitions.perform
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_run_actions_in_order
- @transitions.perform
- assert_equal [:save_state, :save_status], @object.actions
- end
-
- def test_should_store_results_in_transitions
- @transitions.perform
- assert_equal :save_state, @state_transition.result
- assert_equal :save_status, @status_transition.result
- end
-
- def test_should_not_halt_if_action_fails_for_first_transition
- @klass.class_eval do
- remove_method :save_state
- def save_state
- (@actions ||= []) << :save_state
- false
- end
- end
-
-
- assert_equal false, @transitions.perform
- assert_equal [:save_state, :save_status], @object.actions
- end
-
- def test_should_halt_if_action_fails_for_second_transition
- @klass.class_eval do
- remove_method :save_status
- def save_status
- (@actions ||= []) << :save_status
- false
- end
- end
-
- assert_equal false, @transitions.perform
- assert_equal [:save_state, :save_status], @object.actions
- end
-
- def test_should_rollback_if_action_errors_for_first_transition
- @klass.class_eval do
- remove_method :save_state
- def save_state
- raise ArgumentError
- end
- end
-
- begin; @transitions.perform; rescue; end
- assert_equal 'parked', @object.state
- assert_equal 'first_gear', @object.status
- end
-
- def test_should_rollback_if_action_errors_for_second_transition
- @klass.class_eval do
- remove_method :save_status
- def save_status
- raise ArgumentError
- end
- end
-
- begin; @transitions.perform; rescue; end
- assert_equal 'parked', @object.state
- assert_equal 'first_gear', @object.status
- end
-
- def test_should_not_run_after_callbacks_if_action_fails_for_first_transition
- @klass.class_eval do
- remove_method :save_state
- def save_state
- false
- end
- end
-
- @callbacks = []
- @state.after_transition { @callbacks << :state_after }
- @state.around_transition {|block| block.call; @callbacks << :state_around }
- @status.after_transition { @callbacks << :status_after }
- @status.around_transition {|block| block.call; @callbacks << :status_around }
-
- @transitions.perform
- assert_equal [], @callbacks
- end
-
- def test_should_not_run_after_callbacks_if_action_fails_for_second_transition
- @klass.class_eval do
- remove_method :save_status
- def save_status
- false
- end
- end
-
- @callbacks = []
- @state.after_transition { @callbacks << :state_after }
- @state.around_transition {|block| block.call; @callbacks << :state_around }
- @status.after_transition { @callbacks << :status_after }
- @status.around_transition {|block| block.call; @callbacks << :status_around }
-
- @transitions.perform
- assert_equal [], @callbacks
- end
-
- def test_should_run_after_failure_callbacks_if_action_fails_for_first_transition
- @klass.class_eval do
- remove_method :save_state
- def save_state
- false
- end
- end
-
- @callbacks = []
- @state.after_failure { @callbacks << :state_after }
- @status.after_failure { @callbacks << :status_after }
-
- @transitions.perform
- assert_equal [:status_after, :state_after], @callbacks
- end
-
- def test_should_run_after_failure_callbacks_if_action_fails_for_second_transition
- @klass.class_eval do
- remove_method :save_status
- def save_status
- false
- end
- end
-
- @callbacks = []
- @state.after_failure { @callbacks << :state_after }
- @status.after_failure { @callbacks << :status_after }
-
- @transitions.perform
- assert_equal [:status_after, :state_after], @callbacks
- end
- end
- class TransitionCollectionWithMixedActionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- def save
- true
- end
- end
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_store_results_in_transitions
- assert_equal true, @state_transition.result
- assert_nil @status_transition.result
- end
- end
- class TransitionCollectionWithBlockTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :actions
-
- def save
- (@actions ||= []) << :save
- end
- end
-
- @state = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
- @transitions = StateMachine::TransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
- @result = @transitions.perform { 1 }
- end
-
- def test_should_succeed
- assert_equal 1, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_not_run_machine_actions
- assert_nil @object.actions
- end
-
- def test_should_use_result_as_transition_result
- assert_equal 1, @state_transition.result
- assert_equal 1, @status_transition.result
- end
- end
- class TransitionCollectionWithActionFailedTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- def save
- false
- end
- end
- @before_count = 0
- @around_before_count = 0
- @after_count = 0
- @around_after_count = 0
- @failure_count = 0
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @machine.state :idling
- @machine.event :ignite
-
- @machine.before_transition {@before_count += 1}
- @machine.after_transition {@after_count += 1}
- @machine.around_transition {|block| @around_before_count += 1; block.call; @around_after_count += 1}
- @machine.after_failure {@failure_count += 1}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ])
- @result = @transitions.perform
- end
-
- def test_should_not_succeed
- assert_equal false, @result
- end
-
- def test_should_not_persist_state
- assert_equal 'parked', @object.state
- end
-
- def test_should_run_before_callbacks
- assert_equal 1, @before_count
- end
-
- def test_should_run_around_callbacks_before_yield
- assert_equal 1, @around_before_count
- end
-
- def test_should_not_run_after_callbacks
- assert_equal 0, @after_count
- end
-
- def test_should_not_run_around_callbacks
- assert_equal 0, @around_after_count
- end
-
- def test_should_run_failure_callbacks
- assert_equal 1, @failure_count
- end
- end
- class TransitionCollectionWithActionErrorTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- def save
- raise ArgumentError
- end
- end
- @before_count = 0
- @around_before_count = 0
- @after_count = 0
- @around_after_count = 0
- @failure_count = 0
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @machine.state :idling
- @machine.event :ignite
-
- @machine.before_transition {@before_count += 1}
- @machine.after_transition {@after_count += 1}
- @machine.around_transition {|block| @around_before_count += 1; block.call; @around_after_count += 1}
- @machine.after_failure {@failure_count += 1}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ])
-
- @raised = true
- begin
- @transitions.perform
- @raised = false
- rescue ArgumentError
- end
- end
-
- def test_should_not_catch_exception
- assert @raised
- end
-
- def test_should_not_persist_state
- assert_equal 'parked', @object.state
- end
-
- def test_should_run_before_callbacks
- assert_equal 1, @before_count
- end
-
- def test_should_run_around_callbacks_before_yield
- assert_equal 1, @around_before_count
- end
-
- def test_should_not_run_after_callbacks
- assert_equal 0, @after_count
- end
-
- def test_should_not_run_around_callbacks_after_yield
- assert_equal 0, @around_after_count
- end
-
- def test_should_not_run_failure_callbacks
- assert_equal 0, @failure_count
- end
- end
- class TransitionCollectionWithCallbacksTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :saved
-
- def save
- @saved = true
- end
- end
-
- @before_callbacks = []
- @after_callbacks = []
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
- @state.before_transition {@before_callbacks << :state_before}
- @state.after_transition {@after_callbacks << :state_after}
- @state.around_transition {|block| @before_callbacks << :state_around; block.call; @after_callbacks << :state_around}
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status.state :second_gear
- @status.event :shift_up
- @status.before_transition {@before_callbacks << :status_before}
- @status.after_transition {@after_callbacks << :status_after}
- @status.around_transition {|block| @before_callbacks << :status_around; block.call; @after_callbacks << :status_around}
-
- @object = @klass.new
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
- end
-
- def test_should_run_before_callbacks_in_order
- @transitions.perform
- assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
- end
-
- def test_should_halt_if_before_callback_halted_for_first_transition
- @state.before_transition {throw :halt}
-
- assert_equal false, @transitions.perform
- assert_equal [:state_before, :state_around], @before_callbacks
- end
-
- def test_should_halt_if_before_callback_halted_for_second_transition
- @status.before_transition {throw :halt}
-
- assert_equal false, @transitions.perform
- assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
- end
-
- def test_should_halt_if_around_callback_halted_before_yield_for_first_transition
- @state.around_transition {throw :halt}
-
- assert_equal false, @transitions.perform
- assert_equal [:state_before, :state_around], @before_callbacks
- end
-
- def test_should_halt_if_around_callback_halted_before_yield_for_second_transition
- @status.around_transition {throw :halt}
-
- assert_equal false, @transitions.perform
- assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
- end
-
- def test_should_run_after_callbacks_in_reverse_order
- @transitions.perform
- assert_equal [:status_around, :status_after, :state_around, :state_after], @after_callbacks
- end
-
- def test_should_not_halt_if_after_callback_halted_for_first_transition
- @state.after_transition {throw :halt}
-
- assert_equal true, @transitions.perform
- assert_equal [:status_around, :status_after, :state_around, :state_after], @after_callbacks
- end
-
- def test_should_not_halt_if_around_callback_halted_for_second_transition
- @status.around_transition {|block| block.call; throw :halt}
-
- assert_equal true, @transitions.perform
- assert_equal [:state_around, :state_after], @after_callbacks
- end
- def test_should_run_before_callbacks_before_persisting_the_state
- @state.before_transition {|object| @before_state = object.state}
- @state.around_transition {|object, transition, block| @around_state = object.state; block.call}
- @transitions.perform
-
- assert_equal 'parked', @before_state
- assert_equal 'parked', @around_state
- end
-
- def test_should_persist_state_before_running_action
- @klass.class_eval do
- attr_reader :saved_on_persist
-
- def state=(value)
- @state = value
- @saved_on_persist = saved
- end
- end
-
- @transitions.perform
- assert !@object.saved_on_persist
- end
-
- def test_should_persist_state_before_running_action_block
- @klass.class_eval do
- attr_writer :saved
- attr_reader :saved_on_persist
-
- def state=(value)
- @state = value
- @saved_on_persist = saved
- end
- end
-
- @transitions.perform { @object.saved = true }
- assert !@object.saved_on_persist
- end
-
- def test_should_run_after_callbacks_after_running_the_action
- @state.after_transition {|object| @after_saved = object.saved}
- @state.around_transition {|object, transition, block| block.call; @around_saved = object.saved}
- @transitions.perform
-
- assert @after_saved
- assert @around_saved
- end
- end
- class TransitionCollectionWithBeforeCallbackHaltTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :saved
-
- def save
- @saved = true
- end
- end
- @before_count = 0
- @after_count = 0
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @machine.state :idling
- @machine.event :ignite
-
- @machine.before_transition {@before_count += 1; throw :halt}
- @machine.before_transition {@before_count += 1}
- @machine.after_transition {@after_count += 1}
- @machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ])
- @result = @transitions.perform
- end
-
- def test_should_not_succeed
- assert_equal false, @result
- end
-
- def test_should_not_persist_state
- assert_equal 'parked', @object.state
- end
-
- def test_should_not_run_action
- assert !@object.saved
- end
-
- def test_should_not_run_further_before_callbacks
- assert_equal 1, @before_count
- end
-
- def test_should_not_run_after_callbacks
- assert_equal 0, @after_count
- end
- end
- class TransitionCollectionWithAfterCallbackHaltTest < Test::Unit::TestCase
- def setup
- @klass = Class.new do
- attr_reader :saved
-
- def save
- @saved = true
- end
- end
- @before_count = 0
- @after_count = 0
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @machine.state :idling
- @machine.event :ignite
-
- @machine.before_transition {@before_count += 1}
- @machine.after_transition {@after_count += 1; throw :halt}
- @machine.after_transition {@after_count += 1}
- @machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ])
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_persist_state
- assert_equal 'idling', @object.state
- end
-
- def test_should_run_before_callbacks
- assert_equal 2, @before_count
- end
-
- def test_should_not_run_further_after_callbacks
- assert_equal 2, @after_count
- end
- end
- class TransitionCollectionWithSkippedAfterCallbacksTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @callbacks = []
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked)
- @machine.state :idling
- @machine.event :ignite
- @machine.after_transition {@callbacks << :after}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ], :after => false)
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_not_run_after_callbacks
- assert !@callbacks.include?(:after)
- end
-
- def test_should_run_after_callbacks_on_subsequent_perform
- StateMachine::TransitionCollection.new([@transition]).perform
- assert @callbacks.include?(:after)
- end
- end
- if StateMachine::Transition.pause_supported?
- class TransitionCollectionWithSkippedAfterCallbacksAndAroundCallbacksTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @callbacks = []
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked)
- @machine.state :idling
- @machine.event :ignite
- @machine.around_transition {|block| @callbacks << :around_before; block.call; @callbacks << :around_after}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ], :after => false)
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_not_run_around_callbacks_after_yield
- assert !@callbacks.include?(:around_after)
- end
-
- def test_should_run_around_callbacks_after_yield_on_subsequent_perform
- StateMachine::TransitionCollection.new([@transition]).perform
- assert @callbacks.include?(:around_after)
- end
-
- def test_should_not_rerun_around_callbacks_before_yield_on_subsequent_perform
- @callbacks = []
- StateMachine::TransitionCollection.new([@transition]).perform
-
- assert !@callbacks.include?(:around_before)
- end
- end
- else
- class TransitionCollectionWithSkippedAfterCallbacksAndAroundCallbacksTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @callbacks = []
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked)
- @machine.state :idling
- @machine.event :ignite
- @machine.around_transition {|block| @callbacks << :around_before; block.call; @callbacks << :around_after}
-
- @object = @klass.new
-
- @transitions = StateMachine::TransitionCollection.new([
- @transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- ], :after => false)
- end
-
- def test_should_raise_exception
- assert_raise(ArgumentError) { @transitions.perform }
- end
- end
- end
- class TransitionCollectionWithActionHookBaseTest < Test::Unit::TestCase
- def setup
- @superclass = Class.new do
- def save
- true
- end
- end
-
- @klass = Class.new(@superclass) do
- attr_reader :saved, :state_on_save, :state_event_on_save, :state_event_transition_on_save
-
- def save
- @saved = true
- @state_on_save = state
- @state_event_on_save = state_event
- @state_event_transition_on_save = state_event_transition
- super
- end
- end
-
- @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @machine.state :idling
- @machine.event :ignite
-
- @object = @klass.new
-
- @transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- end
-
- def default_test
- end
- end
- class TransitionCollectionWithActionHookAndSkippedActionTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
- @result = StateMachine::TransitionCollection.new([@transition], :actions => false).perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_not_run_action
- assert !@object.saved
- end
- end
- class TransitionCollectionWithActionHookAndSkippedAfterCallbacksTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
- @result = StateMachine::TransitionCollection.new([@transition], :after => false).perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_run_action
- assert @object.saved
- end
-
- def test_should_have_already_persisted_when_running_action
- assert_equal 'idling', @object.state_on_save
- end
-
- def test_should_not_have_event_during_action
- assert_nil @object.state_event_on_save
- end
-
- def test_should_not_write_event
- assert_nil @object.state_event
- end
-
- def test_should_not_have_event_transition_during_save
- assert_nil @object.state_event_transition_on_save
- end
-
- def test_should_not_write_event_attribute
- assert_nil @object.send(:state_event_transition)
- end
- end
- class TransitionCollectionWithActionHookAndBlockTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
- @result = StateMachine::TransitionCollection.new([@transition]).perform { true }
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_not_run_action
- assert !@object.saved
- end
- end
- class TransitionCollectionWithActionHookInvalidTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
- @result = StateMachine::TransitionCollection.new([@transition, nil]).perform
- end
-
- def test_should_not_succeed
- assert_equal false, @result
- end
-
- def test_should_not_run_action
- assert !@object.saved
- end
- end
- class TransitionCollectionWithActionHookWithNilActionTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
-
- @machine = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
- @machine.state :second_gear
- @machine.event :shift_up
-
- @result = StateMachine::TransitionCollection.new([@transition, StateMachine::Transition.new(@object, @machine, :shift_up, :first_gear, :second_gear)]).perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_run_action
- assert @object.saved
- end
-
- def test_should_have_already_persisted_when_running_action
- assert_equal 'idling', @object.state_on_save
- end
-
- def test_should_not_have_event_during_action
- assert_nil @object.state_event_on_save
- end
-
- def test_should_not_write_event
- assert_nil @object.state_event
- end
-
- def test_should_not_have_event_transition_during_save
- assert_nil @object.state_event_transition_on_save
- end
-
- def test_should_not_write_event_attribute
- assert_nil @object.send(:state_event_transition)
- end
- end
- class TransitionCollectionWithActionHookWithDifferentActionsTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
-
- @klass.class_eval do
- def save_status
- true
- end
- end
-
- @machine = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
- @machine.state :second_gear
- @machine.event :shift_up
-
- @result = StateMachine::TransitionCollection.new([@transition, StateMachine::Transition.new(@object, @machine, :shift_up, :first_gear, :second_gear)]).perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_run_action
- assert @object.saved
- end
-
- def test_should_have_already_persisted_when_running_action
- assert_equal 'idling', @object.state_on_save
- end
-
- def test_should_not_have_event_during_action
- assert_nil @object.state_event_on_save
- end
-
- def test_should_not_write_event
- assert_nil @object.state_event
- end
-
- def test_should_not_have_event_transition_during_save
- assert_nil @object.state_event_transition_on_save
- end
-
- def test_should_not_write_event_attribute
- assert_nil @object.send(:state_event_transition)
- end
- end
- class TransitionCollectionWithActionHookTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
- @result = StateMachine::TransitionCollection.new([@transition]).perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_run_action
- assert @object.saved
- end
-
- def test_should_not_have_already_persisted_when_running_action
- assert_equal 'parked', @object.state_on_save
- end
-
- def test_should_persist
- assert_equal 'idling', @object.state
- end
-
- def test_should_not_have_event_during_action
- assert_nil @object.state_event_on_save
- end
-
- def test_should_not_write_event
- assert_nil @object.state_event
- end
-
- def test_should_have_event_transition_during_action
- assert_equal @transition, @object.state_event_transition_on_save
- end
-
- def test_should_not_write_event_transition
- assert_nil @object.send(:state_event_transition)
- end
-
- def test_should_mark_event_transition_as_transient
- assert @transition.transient?
- end
- end
- class TransitionCollectionWithActionHookMultipleTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
-
- @status_machine = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status_machine.state :second_gear
- @status_machine.event :shift_up
-
- @klass.class_eval do
- attr_reader :status_on_save, :status_event_on_save, :status_event_transition_on_save
-
- remove_method :save
- def save
- @saved = true
- @state_on_save = state
- @state_event_on_save = state_event
- @state_event_transition_on_save = state_event_transition
- @status_on_save = status
- @status_event_on_save = status_event
- @status_event_transition_on_save = status_event_transition
- super
- 1
- end
- end
-
- @object = @klass.new
- @state_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
- @status_transition = StateMachine::Transition.new(@object, @status_machine, :shift_up, :first_gear, :second_gear)
-
- @result = StateMachine::TransitionCollection.new([@state_transition, @status_transition]).perform
- end
-
- def test_should_succeed
- assert_equal 1, @result
- end
-
- def test_should_run_action
- assert @object.saved
- end
-
- def test_should_not_have_already_persisted_when_running_action
- assert_equal 'parked', @object.state_on_save
- assert_equal 'first_gear', @object.status_on_save
- end
-
- def test_should_persist
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_not_have_events_during_action
- assert_nil @object.state_event_on_save
- assert_nil @object.status_event_on_save
- end
-
- def test_should_not_write_events
- assert_nil @object.state_event
- assert_nil @object.status_event
- end
-
- def test_should_have_event_transitions_during_action
- assert_equal @state_transition, @object.state_event_transition_on_save
- assert_equal @status_transition, @object.status_event_transition_on_save
- end
-
- def test_should_not_write_event_transitions
- assert_nil @object.send(:state_event_transition)
- assert_nil @object.send(:status_event_transition)
- end
-
- def test_should_mark_event_transitions_as_transient
- assert @state_transition.transient?
- assert @status_transition.transient?
- end
- end
- class TransitionCollectionWithActionHookErrorTest < TransitionCollectionWithActionHookBaseTest
- def setup
- super
-
- @superclass.class_eval do
- remove_method :save
- def save
- raise ArgumentError
- end
- end
-
- begin; StateMachine::TransitionCollection.new([@transition]).perform; rescue; end
- end
-
- def test_should_not_write_event
- assert_nil @object.state_event
- end
-
- def test_should_not_write_event_transition
- assert_nil @object.send(:state_event_transition)
- end
- end
- class AttributeTransitionCollectionByDefaultTest < Test::Unit::TestCase
- def setup
- @transitions = StateMachine::AttributeTransitionCollection.new
- end
-
- def test_should_skip_actions
- assert @transitions.skip_actions
- end
-
- def test_should_not_skip_after
- assert !@transitions.skip_after
- end
-
- def test_should_not_use_transaction
- assert !@transitions.use_transaction
- end
-
- def test_should_be_empty
- assert @transitions.empty?
- end
- end
- class AttributeTransitionCollectionWithEventsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
- @object.state_event = 'ignite'
- @object.status_event = 'shift_up'
-
- @transitions = StateMachine::AttributeTransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_clear_events
- assert_nil @object.state_event
- assert_nil @object.status_event
- end
-
- def test_should_not_write_event_transitions
- assert_nil @object.send(:state_event_transition)
- assert_nil @object.send(:status_event_transition)
- end
- end
- class AttributeTransitionCollectionWithEventTransitionsTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
- @object.send(:state_event_transition=, @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling))
- @object.send(:status_event_transition=, @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear))
-
- @transitions = StateMachine::AttributeTransitionCollection.new([@state_transition, @status_transition])
- @result = @transitions.perform
- end
-
- def test_should_succeed
- assert_equal true, @result
- end
-
- def test_should_persist_states
- assert_equal 'idling', @object.state
- assert_equal 'second_gear', @object.status
- end
-
- def test_should_not_write_events
- assert_nil @object.state_event
- assert_nil @object.status_event
- end
-
- def test_should_clear_event_transitions
- assert_nil @object.send(:state_event_transition)
- assert_nil @object.send(:status_event_transition)
- end
- end
- class AttributeTransitionCollectionWithActionFailedTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
- @object.state_event = 'ignite'
- @object.status_event = 'shift_up'
-
- @transitions = StateMachine::AttributeTransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
- @result = @transitions.perform { false }
- end
-
- def test_should_not_succeed
- assert_equal false, @result
- end
-
- def test_should_not_persist_states
- assert_equal 'parked', @object.state
- assert_equal 'first_gear', @object.status
- end
-
- def test_should_not_clear_events
- assert_equal :ignite, @object.state_event
- assert_equal :shift_up, @object.status_event
- end
-
- def test_should_not_write_event_transitions
- assert_nil @object.send(:state_event_transition)
- assert_nil @object.send(:status_event_transition)
- end
- end
- class AttributeTransitionCollectionWithActionErrorTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
- @state.state :idling
- @state.event :ignite
-
- @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
- @status.state :second_gear
- @status.event :shift_up
-
- @object = @klass.new
- @object.state_event = 'ignite'
- @object.status_event = 'shift_up'
-
- @transitions = StateMachine::AttributeTransitionCollection.new([
- @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
- @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
- ])
-
- begin; @transitions.perform { raise ArgumentError }; rescue; end
- end
-
- def test_should_not_persist_states
- assert_equal 'parked', @object.state
- assert_equal 'first_gear', @object.status
- end
-
- def test_should_not_clear_events
- assert_equal :ignite, @object.state_event
- assert_equal :shift_up, @object.status_event
- end
-
- def test_should_not_write_event_transitions
- assert_nil @object.send(:state_event_transition)
- assert_nil @object.send(:status_event_transition)
- end
- end
- class AttributeTransitionCollectionWithCallbacksTest < Test::Unit::TestCase
- def setup
- @klass = Class.new
-
- @state = StateMachine::Machine.new(@klass, :initial => :par…
Large files files are truncated, but you can click here to view the full file