1
0
Fork 0
mirror of https://github.com/aasm/aasm synced 2023-03-27 23:22:41 -04:00

more tests

This commit is contained in:
Thorsten Böttger 2015-06-26 19:46:58 +12:00
parent 719dadf1ff
commit 206b1991bc
18 changed files with 750 additions and 152 deletions

View file

@ -3,7 +3,23 @@
## version 4.3
* add support for multiple state machines per class
* check all tests
* what happen's if someone accesses `aasm`, but has defined a
state machine for `aasm(:my_name)`?
* persistence
* _ActiveRecord_
* _Mongoid_
* _MongoMapper_
* _Sequel_
* documentation
* events are chained
* :default state machine won't be provided, if state machine name is used
* if used raise an error
* silence warnings?
# Changes so far
## version 4.3
* add support for multiple state machines per class
* class- and instance-level `aasm` methods accept a state machine selector
(aka the state machine _name_)
* if no selector/name is provided, `:default` will be used
* duplicate definitions of states and events will issue warnings

View file

@ -67,7 +67,7 @@ module AASM
@state_machine.add_state(name, @klass, options)
if @klass.instance_methods.include?("#{name}?")
warn "The state name #{name} is already used!"
warn "#{@klass.name}: The state name #{name} is already used!"
end
@klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
@ -86,7 +86,7 @@ module AASM
@state_machine.add_event(name, options, &block)
if @klass.instance_methods.include?("may_#{name}?".to_sym)
warn "The event name #{name} is already used!"
warn "#{@klass.name}: The event name #{name} is already used!"
end
# an addition over standard aasm so that, before firing an event, you can ask

View file

@ -86,3 +86,137 @@ class ComplexExample
phrase == :please
end
end
class ComplexExampleMultiple
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 :left_register do
transitions :from => :passive, :to => :pending do
guard do
can_register?
end
end
end
event :left_activate do
transitions :from => :pending, :to => :active
end
event :left_suspend do
transitions :from => [:passive, :pending, :active], :to => :suspended
end
event :left_delete do
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
end
# a dummy event that can never happen
event :left_unpassify do
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false }
end
event :left_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 :left_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 :right_register do
transitions :from => :passive, :to => :pending do
guard do
can_register?
end
end
end
event :right_activate do
transitions :from => :pending, :to => :active
end
event :right_suspend do
transitions :from => [:passive, :pending, :active], :to => :suspended
end
event :right_delete do
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
end
# a dummy event that can never happen
event :right_unpassify do
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false }
end
event :right_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 :right_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
aasm(:right).enter_initial_state
end
def make_activation_code
@activation_code = @activation_code ? @activation_code + '2' : '1'
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

View file

@ -1,133 +0,0 @@
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 :left_register do
transitions :from => :passive, :to => :pending do
guard do
can_register?
end
end
end
event :left_activate do
transitions :from => :pending, :to => :active
end
event :left_suspend do
transitions :from => [:passive, :pending, :active], :to => :suspended
end
event :left_delete do
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
end
# a dummy event that can never happen
event :left_unpassify do
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false }
end
event :left_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 :left_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 :right_register do
transitions :from => :passive, :to => :pending do
guard do
can_register?
end
end
end
event :right_activate do
transitions :from => :pending, :to => :active
end
event :right_suspend do
transitions :from => [:passive, :pending, :active], :to => :suspended
end
event :right_delete do
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
end
# a dummy event that can never happen
event :right_unpassify do
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false }
end
event :right_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 :right_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
aasm(:right).enter_initial_state
end
def make_activation_code
@activation_code = @activation_code ? @activation_code + '2' : '1'
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

View file

@ -34,8 +34,55 @@ class Conversation
@persister = persister
end
private
def aasm_read_state
@persister.read_state
end
def aasm_write_state(state)
@persister.write_state(state)
end
end
class ConversationMultiple
include AASM
aasm(:left) do
state :needs_attention, :initial => true
state :read
state :closed
state :awaiting_response
state :junk
event :new_message do
end
event :view do
transitions :to => :read, :from => [:needs_attention]
end
event :reply do
end
event :close do
transitions :to => :closed, :from => [:read, :awaiting_response]
end
event :junk do
transitions :to => :junk, :from => [:read]
end
event :unjunk do
end
end
def initialize(persister)
@persister = persister
end
private
def aasm_read_state
@persister.read_state
end
@ -43,5 +90,4 @@ class Conversation
def aasm_write_state(state)
@persister.write_state(state)
end
end

View file

@ -33,3 +33,60 @@ class FooTwo < Foo
state :foo
end
end
class FooMultiple
include AASM
aasm(:left) do
state :open, :initial => true, :before_exit => :before_exit
state :closed, :before_enter => :before_enter
state :final
event :close, :success => :success_callback do
transitions :from => [:open], :to => [:closed]
end
event :null do
transitions :from => [:open], :to => [:closed, :final], :guard => :always_false
end
end
aasm(:right, :column => :right) do
state :green, :initial => true
state :yellow
state :red
event :green do
transitions :from => [:yellow], :to => :green
end
event :yellow do
transitions :from => [:green, :red], :to => :yellow
end
event :red do
transitions :from => [:yellow], :to => :red
end
end
def always_false
false
end
def success_callback
end
def before_enter
end
def before_exit
end
end
class FooTwoMultiple < FooMultiple
include AASM
aasm(:left) do
state :foo
end
aasm(:right) do
state :bar
end
end

View file

@ -1,5 +1,6 @@
class FooMultiple
class FooCallbackMultiple
include AASM
aasm(:left) do
state :open, :initial => true, :before_exit => :before_exit
state :closed, :before_enter => :before_enter
@ -14,6 +15,22 @@ class FooMultiple
end
end
aasm(:right, :column => :right) do
state :green, :initial => true
state :yellow
state :red
event :green do
transitions :from => [:yellow], :to => :green
end
event :yellow do
transitions :from => [:green, :red], :to => :yellow
end
event :red do
transitions :from => [:yellow], :to => :red
end
end
def always_false
false
end
@ -26,10 +43,3 @@ class FooMultiple
def before_exit
end
end
class FooTwoMultiple < FooMultiple
include AASM
aasm(:left) do
state :foo
end
end

View file

@ -0,0 +1,48 @@
class GuardianMultiple
include AASM
aasm(:left) do
state :alpha, :initial => true
state :beta
event :use_one_guard_that_succeeds do
transitions :from => :alpha, :to => :beta, :guard => :succeed
end
event :use_one_guard_that_fails do
transitions :from => :alpha, :to => :beta, :guard => :fail
end
event :use_guards_that_succeed do
transitions :from => :alpha, :to => :beta, :guards => [:succeed, :another_succeed]
end
event :use_guards_where_the_first_fails do
transitions :from => :alpha, :to => :beta, :guards => [:succeed, :fail]
end
event :use_guards_where_the_second_fails do
transitions :from => :alpha, :to => :beta, :guards => [:fail, :succeed]
end
event :use_event_guards_that_succeed, :guards => [:succeed, :another_succeed] do
transitions :from => :alpha, :to => :beta
end
event :use_event_and_transition_guards_that_succeed, :guards => [:succeed, :another_succeed] do
transitions :from => :alpha, :to => :beta, :guards => [:more_succeed]
end
event :use_event_guards_where_the_first_fails, :guards => [:succeed, :fail] do
transitions :from => :alpha, :to => :beta
end
event :use_event_guards_where_the_second_fails, :guards => [:fail, :succeed] do
transitions :from => :alpha, :to => :beta, :guard => :another_succeed
end
event :use_event_and_transition_guards_where_third_fails, :guards => [:succeed, :another_succeed] do
transitions :from => :alpha, :to => :beta, :guards => [:fail]
end
end
def fail; false; end
def succeed; true; end
def another_succeed; true; end
def more_succeed; true; end
end

View file

@ -13,3 +13,19 @@ class InitialStateProc
def initialize(balance = 0); self.balance = balance; end
def rich?; self.balance >= RICH; end
end
class InitialStateProcMultiple
RICH = 1_000_000
attr_accessor :balance
include AASM
aasm(:left) do
state :retired
state :selling_bad_mortgages
initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
end
def initialize(balance = 0); self.balance = balance; end
def rich?; self.balance >= RICH; end
end

View file

@ -10,3 +10,16 @@ class NoInitialState
end
end
end
class NoInitialStateMultiple
include AASM
aasm(:left) do
state :read
state :ended
event :foo do
transitions :to => :ended, :from => [:read]
end
end
end

View file

@ -0,0 +1,29 @@
class ParametrisedEventMultiple
include AASM
aasm(:left) do
state :sleeping, :initial => true
state :showering
state :working
state :dating
state :prettying_up
event :wakeup do
transitions :from => :sleeping, :to => [:showering, :working]
end
event :dress do
transitions :from => :sleeping, :to => :working, :after => :wear_clothes
transitions :from => :showering, :to => [:working, :dating], :after => Proc.new { |*args| wear_clothes(*args) }
transitions :from => :showering, :to => :prettying_up, :after => [:condition_hair, :fix_hair]
end
end
def wear_clothes(shirt_color, trouser_type=nil)
end
def condition_hair
end
def fix_hair
end
end

View file

@ -9,3 +9,15 @@ class ValidStateName
end
end
end
class ValidStateNameMultiple
include AASM
aasm(:left) do
state :invalid, :initial => true
state :valid
event :valid do
transitions :to => :valid, :from => [:invalid]
end
end
end

View file

@ -185,7 +185,7 @@ end # callbacks for the new DSL
describe 'event callbacks' do
describe "with an error callback defined" do
before do
class FooMultiple
class FooCallbackMultiple
# this hack is needed to allow testing of parameters, since RSpec
# destroys a method's arity when mocked
attr_accessor :data
@ -197,7 +197,7 @@ describe 'event callbacks' do
end
end
@foo = FooMultiple.new
@foo = FooCallbackMultiple.new
end
context "error_callback defined" do

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe 'on initialization' do
let(:auth) {ComplexMultipleExample.new}
let(:auth) {ComplexExampleMultiple.new}
it 'should be in the pending state' do
expect(auth.aasm(:left).current_state).to eq(:pending)
@ -15,7 +15,7 @@ describe 'on initialization' do
end
describe 'when being unsuspended' do
let(:auth) {ComplexMultipleExample.new}
let(:auth) {ComplexExampleMultiple.new}
it 'should be able to unsuspend' do
auth.left_activate!

View file

@ -0,0 +1,73 @@
require 'spec_helper'
describe 'current event' do
let(:pe) {ParametrisedEventMultiple.new}
it 'if no event has been triggered' do
expect(pe.aasm(:left).current_event).to be_nil
end
it 'if a event has been triggered' do
pe.wakeup
expect(pe.aasm(:left).current_event).to eql :wakeup
end
it 'if no event has been triggered' do
pe.wakeup!
expect(pe.aasm(:left).current_event).to eql :wakeup!
end
end
describe 'parametrised events' do
let(:pe) {ParametrisedEventMultiple.new}
it 'should transition to specified next state (sleeping to showering)' do
pe.wakeup!(:showering)
expect(pe.aasm(:left).current_state).to eq(:showering)
end
it 'should transition to specified next state (sleeping to working)' do
pe.wakeup!(:working)
expect(pe.aasm(:left).current_state).to eq(:working)
end
it 'should transition to default (first or showering) state' do
pe.wakeup!
expect(pe.aasm(:left).current_state).to eq(:showering)
end
it 'should transition to default state when :after transition invoked' do
pe.dress!(nil, 'purple', 'dressy')
expect(pe.aasm(:left).current_state).to eq(:working)
end
it 'should call :after transition method with args' do
pe.wakeup!(:showering)
expect(pe).to receive(:wear_clothes).with('blue', 'jeans')
pe.dress!(:working, 'blue', 'jeans')
end
it 'should call :after transition proc' do
pe.wakeup!(:showering)
expect(pe).to receive(:wear_clothes).with('purple', 'slacks')
pe.dress!(:dating, 'purple', 'slacks')
end
it 'should call :after transition with an array of methods' do
pe.wakeup!(:showering)
expect(pe).to receive(:condition_hair)
expect(pe).to receive(:fix_hair)
pe.dress!(:prettying_up)
end
end
describe 'event firing without persistence' do
it 'should attempt to persist if aasm_write_state is defined' do
foo = Foo.new
def foo.aasm_write_state; end
expect(foo).to be_open
expect(foo).to receive(:aasm_write_state_without_persistence)
foo.close
end
end

View file

@ -0,0 +1,60 @@
require 'spec_helper'
describe "per-transition guards" do
let(:guardian) { GuardianMultiple.new }
it "allows the transition if the guard succeeds" do
expect { guardian.use_one_guard_that_succeeds! }.to_not raise_error
expect(guardian).to be_beta
end
it "stops the transition if the guard fails" do
expect { guardian.use_one_guard_that_fails! }.to raise_error(AASM::InvalidTransition)
expect(guardian).to be_alpha
end
it "allows the transition if all guards succeeds" do
expect { guardian.use_guards_that_succeed! }.to_not raise_error
expect(guardian).to be_beta
end
it "stops the transition if the first guard fails" do
expect { guardian.use_guards_where_the_first_fails! }.to raise_error(AASM::InvalidTransition)
expect(guardian).to be_alpha
end
it "stops the transition if the second guard fails" do
expect { guardian.use_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
expect(guardian).to be_alpha
end
end
describe "event guards" do
let(:guardian) { GuardianMultiple.new }
it "allows the transition if the event guards succeed" do
expect { guardian.use_event_guards_that_succeed! }.to_not raise_error
expect(guardian).to be_beta
end
it "allows the transition if the event and transition guards succeed" do
expect { guardian.use_event_and_transition_guards_that_succeed! }.to_not raise_error
expect(guardian).to be_beta
end
it "stops the transition if the first event guard fails" do
expect { guardian.use_event_guards_where_the_first_fails! }.to raise_error(AASM::InvalidTransition)
expect(guardian).to be_alpha
end
it "stops the transition if the second event guard fails" do
expect { guardian.use_event_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
expect(guardian).to be_alpha
end
it "stops the transition if the transition guard fails" do
expect { guardian.use_event_and_transition_guards_where_third_fails! }.to raise_error(AASM::InvalidTransition)
expect(guardian).to be_alpha
end
end

View file

@ -0,0 +1,15 @@
require 'spec_helper'
describe 'initial states' do
it 'should use the first state defined if no initial state is given' do
expect(NoInitialStateMultiple.new.aasm(:left).current_state).to eq(:read)
end
it 'should determine initial state from the Proc results' do
balance = InitialStateProcMultiple::RICH - 1
expect(InitialStateProcMultiple.new(balance).aasm(:left).current_state).to eq(:selling_bad_mortgages)
balance = InitialStateProcMultiple::RICH + 1
expect(InitialStateProcMultiple.new(balance).aasm(:left).current_state).to eq(:retired)
end
end

View file

@ -0,0 +1,202 @@
require 'spec_helper'
describe 'inspection for common cases' do
it 'should support the new DSL' do
# 1st state machine
expect(FooMultiple.aasm(:left)).to respond_to(:states)
expect(FooMultiple.aasm(:left).states.size).to eql 3
expect(FooMultiple.aasm(:left).states).to include(:open)
expect(FooMultiple.aasm(:left).states).to include(:closed)
expect(FooMultiple.aasm(:left).states).to include(:final)
expect(FooMultiple.aasm(:left)).to respond_to(:initial_state)
expect(FooMultiple.aasm(:left).initial_state).to eq(:open)
expect(FooMultiple.aasm(:left)).to respond_to(:events)
puts FooMultiple.aasm(:left).events.map(&:name).inspect
expect(FooMultiple.aasm(:left).events.size).to eql 2
expect(FooMultiple.aasm(:left).events).to include(:close)
expect(FooMultiple.aasm(:left).events).to include(:null)
# 2nd state machine
expect(FooMultiple.aasm(:right)).to respond_to(:states)
expect(FooMultiple.aasm(:right).states.size).to eql 3
expect(FooMultiple.aasm(:right).states).to include(:green)
expect(FooMultiple.aasm(:right).states).to include(:yellow)
expect(FooMultiple.aasm(:right).states).to include(:red)
expect(FooMultiple.aasm(:right)).to respond_to(:initial_state)
expect(FooMultiple.aasm(:right).initial_state).to eq(:green)
expect(FooMultiple.aasm(:right)).to respond_to(:events)
expect(FooMultiple.aasm(:right).events.size).to eql 3
expect(FooMultiple.aasm(:right).events).to include(:green)
expect(FooMultiple.aasm(:right).events).to include(:yellow)
expect(FooMultiple.aasm(:right).events).to include(:red)
end
context "instance level inspection" do
let(:foo) { FooMultiple.new }
let(:two) { FooTwoMultiple.new }
it "delivers all states" do
# 1st state machine
states = foo.aasm(:left).states
expect(states.size).to eql 3
expect(states).to include(:open)
expect(states).to include(:closed)
expect(states).to include(:final)
states = foo.aasm(:left).states(:permitted => true)
expect(states.size).to eql 1
expect(states).to include(:closed)
expect(states).not_to include(:open)
expect(states).not_to include(:final)
foo.close
expect(foo.aasm(:left).states(:permitted => true)).to be_empty
# 2nd state machine
states = foo.aasm(:right).states
expect(states.size).to eql 3
expect(states).to include(:green)
expect(states).to include(:yellow)
expect(states).to include(:red)
states = foo.aasm(:right).states(:permitted => true)
expect(states.size).to eql 1
expect(states).to include(:yellow)
expect(states).not_to include(:green)
expect(states).not_to include(:red)
foo.yellow
states = foo.aasm(:right).states(:permitted => true)
expect(states.size).to eql 2
expect(states).to include(:red)
expect(states).to include(:green)
expect(states).not_to include(:yellow)
end
it "delivers all states for subclasses" do
# 1st state machine
states = two.aasm(:left).states
expect(states.size).to eql 4
expect(states).to include(:open)
expect(states).to include(:closed)
expect(states).to include(:final)
expect(states).to include(:foo)
states = two.aasm(:left).states(:permitted => true)
expect(states.size).to eql 1
expect(states).to include(:closed)
expect(states).not_to include(:open)
two.close
expect(two.aasm(:left).states(:permitted => true)).to be_empty
# 2nd state machine
states = two.aasm(:right).states
expect(states.size).to eql 4
expect(states).to include(:green)
expect(states).to include(:yellow)
expect(states).to include(:red)
expect(states).to include(:bar)
states = two.aasm(:right).states(:permitted => true)
expect(states.size).to eql 1
expect(states).to include(:yellow)
expect(states).not_to include(:red)
expect(states).not_to include(:green)
expect(states).not_to include(:bar)
two.yellow
states = two.aasm(:right).states(:permitted => true)
expect(states.size).to eql 2
expect(states).to include(:green)
expect(states).to include(:red)
expect(states).not_to include(:yellow)
expect(states).not_to include(:bar)
end
it "delivers all events" do
# 1st state machine
events = foo.aasm(:left).events
expect(events.size).to eql 2
expect(events).to include(:close)
expect(events).to include(:null)
foo.close
expect(foo.aasm(:left).events).to be_empty
# 2nd state machine
events = foo.aasm(:right).events
expect(events.size).to eql 1
expect(events).to include(:yellow)
expect(events).not_to include(:green)
expect(events).not_to include(:red)
foo.yellow
events = foo.aasm(:right).events
expect(events.size).to eql 2
expect(events).to include(:green)
expect(events).to include(:red)
expect(events).not_to include(:yellow)
end
end
it 'should list states in the order they have been defined' do
expect(ConversationMultiple.aasm(:left).states).to eq([
:needs_attention, :read, :closed, :awaiting_response, :junk
])
end
end
describe "special cases" do
it "should support valid as state name" do
expect(ValidStateNameMultiple.aasm(:left).states).to include(:invalid)
expect(ValidStateNameMultiple.aasm(:left).states).to include(:valid)
argument = ValidStateNameMultiple.new
expect(argument.invalid?).to be_truthy
expect(argument.aasm(:left).current_state).to eq(:invalid)
argument.valid!
expect(argument.valid?).to be_truthy
expect(argument.aasm(:left).current_state).to eq(:valid)
end
end
describe 'aasm.states_for_select' do
it "should return a select friendly array of states" do
expect(FooMultiple.aasm(:left)).to respond_to(:states_for_select)
expect(FooMultiple.aasm(:left).states_for_select).to eq(
[['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']]
)
end
end
describe 'aasm.from_states_for_state' do
it "should return all from states for a state" do
expect(ComplexExampleMultiple.aasm(:left)).to respond_to(:from_states_for_state)
froms = ComplexExampleMultiple.aasm(:left).from_states_for_state(:active)
[:pending, :passive, :suspended].each {|from| expect(froms).to include(from)}
end
it "should return from states for a state for a particular transition only" do
froms = ComplexExampleMultiple.aasm(:left).from_states_for_state(:active, :transition => :left_unsuspend)
[:suspended].each {|from| expect(froms).to include(from)}
end
end
describe 'permitted events' do
let(:foo) {FooMultiple.new}
it 'work' do
expect(foo.aasm(:left).events(:permitted => true)).to include(:close)
expect(foo.aasm(:left).events(:permitted => true)).not_to include(:null)
expect(foo.aasm(:right).events(:permitted => true)).to include(:yellow)
expect(foo.aasm(:right).events(:permitted => true)).not_to include(:green)
expect(foo.aasm(:right).events(:permitted => true)).not_to include(:red)
end
end