diff --git a/spec/models/complex_multiple_example.rb b/spec/models/complex_multiple_example.rb new file mode 100644 index 00000000..e6c52826 --- /dev/null +++ b/spec/models/complex_multiple_example.rb @@ -0,0 +1,132 @@ +class ComplexMultipleExample + include AASM + + attr_accessor :activation_code, :activated_at, :deleted_at + + aasm(:left) do + state :passive + state :pending, :initial => true, :before_enter => :make_activation_code + state :active, :before_enter => :do_activate + state :suspended + state :deleted, :before_enter => :do_delete#, :exit => :do_undelete + state :waiting + + event :register do + transitions :from => :passive, :to => :pending do + guard do + can_register? + end + end + end + + event :activate do + transitions :from => :pending, :to => :active + end + + event :suspend do + transitions :from => [:passive, :pending, :active], :to => :suspended + end + + event :delete do + transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted + end + + # a dummy event that can never happen + event :unpassify do + transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false } + end + + event :unsuspend do + transitions :from => :suspended, :to => :active, :guard => Proc.new { has_activated? } + transitions :from => :suspended, :to => :pending, :guard => :has_activation_code? + transitions :from => :suspended, :to => :passive + end + + event :wait do + transitions :from => :suspended, :to => :waiting, :guard => :if_polite? + end + end + + # aasm(:right) do + # state :passive + # state :pending, :initial => true, :before_enter => :make_activation_code + # state :active, :before_enter => :do_activate + # state :suspended + # state :deleted, :before_enter => :do_delete#, :exit => :do_undelete + # state :waiting + + # event :register do + # transitions :from => :passive, :to => :pending do + # guard do + # can_register? + # end + # end + # end + + # event :activate do + # transitions :from => :pending, :to => :active + # end + + # event :suspend do + # transitions :from => [:passive, :pending, :active], :to => :suspended + # end + + # event :delete do + # transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted + # end + + # # a dummy event that can never happen + # event :unpassify do + # transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false } + # end + + # event :unsuspend do + # transitions :from => :suspended, :to => :active, :guard => Proc.new { has_activated? } + # transitions :from => :suspended, :to => :pending, :guard => :has_activation_code? + # transitions :from => :suspended, :to => :passive + # end + + # event :wait do + # transitions :from => :suspended, :to => :waiting, :guard => :if_polite? + # end + # end # right + + def initialize + # the AR backend uses a before_validate_on_create :aasm_ensure_initial_state + # lets do something similar here for testing purposes. + aasm(:left).enter_initial_state + end + + def make_activation_code + @activation_code = 'moo' + end + + def do_activate + @activated_at = Time.now + @activation_code = nil + end + + def do_delete + @deleted_at = Time.now + end + + def do_undelete + @deleted_at = false + end + + def can_register? + true + end + + def has_activated? + !!@activated_at + end + + def has_activation_code? + !!@activation_code + end + + def if_polite?(phrase = nil) + phrase == :please + end +end diff --git a/spec/unit/complex_multiple_example_spec.rb b/spec/unit/complex_multiple_example_spec.rb new file mode 100644 index 00000000..31c06f13 --- /dev/null +++ b/spec/unit/complex_multiple_example_spec.rb @@ -0,0 +1,84 @@ +require 'spec_helper' + +describe 'on initialization' do + let(:auth) {ComplexMultipleExample.new} + + it 'should be in the pending state' do + expect(auth.aasm(:left).current_state).to eq(:pending) + end + + it 'should have an activation code' do + expect(auth.has_activation_code?).to be_truthy + expect(auth.activation_code).not_to be_nil + end +end + +describe 'when being unsuspended' do + let(:auth) {ComplexMultipleExample.new} + + it 'should be able to be unsuspended' do + auth.activate! + auth.suspend! + expect(auth.may_unsuspend?).to be true + end + + it 'should not be able to be unsuspended into active' do + auth.suspend! + expect(auth.may_unsuspend?(:active)).not_to be true + end + + it 'should be able to be unsuspended into active if polite' do + auth.suspend! + expect(auth.may_wait?(:waiting, :please)).to be true + auth.wait!(nil, :please) + end + + it 'should not be able to be unsuspended into active if not polite' do + auth.suspend! + expect(auth.may_wait?(:waiting)).not_to be true + expect(auth.may_wait?(:waiting, :rude)).not_to be true + expect {auth.wait!(nil, :rude)}.to raise_error(AASM::InvalidTransition) + expect {auth.wait!}.to raise_error(AASM::InvalidTransition) + end + + it 'should not be able to be unpassified' do + auth.activate! + auth.suspend! + auth.unsuspend! + + expect(auth.may_unpassify?).not_to be true + expect {auth.unpassify!}.to raise_error(AASM::InvalidTransition) + end + + it 'should be active if previously activated' do + auth.activate! + auth.suspend! + auth.unsuspend! + + expect(auth.aasm(:left).current_state).to eq(:active) + end + + it 'should be pending if not previously activated, but an activation code is present' do + auth.suspend! + auth.unsuspend! + + expect(auth.aasm(:left).current_state).to eq(:pending) + end + + it 'should be passive if not previously activated and there is no activation code' do + auth.activation_code = nil + auth.suspend! + auth.unsuspend! + + expect(auth.aasm(:left).current_state).to eq(:passive) + end + + it "should be able to fire known events" do + expect(auth.aasm(:left).may_fire_event?(:activate)).to be true + end + + it "should not be able to fire unknown events" do + expect(auth.aasm(:left).may_fire_event?(:unknown)).to be false + end + +end