2010-08-27 16:35:26 -04:00
|
|
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2008-01-07 14:11:38 -05:00
|
|
|
|
|
|
|
describe AASM, '- class level definitions' do
|
2008-04-14 15:57:34 -04:00
|
|
|
it 'should define a class level aasm_initial_state() method on its including class' do
|
2008-02-21 12:59:28 -05:00
|
|
|
Foo.should respond_to(:aasm_initial_state)
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
|
2008-04-14 15:57:34 -04:00
|
|
|
it 'should define a class level aasm_state() method on its including class' do
|
2008-02-21 12:59:28 -05:00
|
|
|
Foo.should respond_to(:aasm_state)
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
|
2008-04-14 15:57:34 -04:00
|
|
|
it 'should define a class level aasm_event() method on its including class' do
|
2008-02-21 12:59:28 -05:00
|
|
|
Foo.should respond_to(:aasm_event)
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-04-14 15:57:34 -04:00
|
|
|
it 'should define a class level aasm_states() method on its including class' do
|
|
|
|
Foo.should respond_to(:aasm_states)
|
|
|
|
end
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-04-14 15:57:34 -04:00
|
|
|
it 'should define a class level aasm_states_for_select() method on its including class' do
|
|
|
|
Foo.should respond_to(:aasm_states_for_select)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should define a class level aasm_events() method on its including class' do
|
|
|
|
Foo.should respond_to(:aasm_events)
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2011-09-16 11:12:10 -04:00
|
|
|
describe "naming" do
|
|
|
|
it "work for valid" do
|
|
|
|
Argument.aasm_states.should include(:invalid)
|
|
|
|
Argument.aasm_states.should include(:valid)
|
|
|
|
|
|
|
|
argument = Argument.new
|
|
|
|
argument.invalid?.should be_true
|
|
|
|
argument.aasm_current_state.should == :invalid
|
|
|
|
|
|
|
|
argument.valid!
|
|
|
|
argument.valid?.should be_true
|
|
|
|
argument.aasm_current_state.should == :valid
|
|
|
|
end
|
|
|
|
end
|
2008-04-14 15:57:34 -04:00
|
|
|
|
2008-11-05 11:06:36 -05:00
|
|
|
describe AASM, '- subclassing' do
|
2009-08-08 09:36:19 -04:00
|
|
|
it 'should have the parent states' do
|
|
|
|
Foo.aasm_states.each do |state|
|
|
|
|
FooTwo.aasm_states.should include(state)
|
2008-11-05 11:06:36 -05:00
|
|
|
end
|
|
|
|
end
|
2009-12-01 06:28:52 -05:00
|
|
|
|
2009-08-08 09:36:19 -04:00
|
|
|
it 'should not add the child states to the parent machine' do
|
|
|
|
Foo.aasm_states.should_not include(:foo)
|
2008-10-09 18:55:45 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2008-04-14 15:57:34 -04:00
|
|
|
describe AASM, '- aasm_states_for_select' do
|
2008-05-29 10:05:50 -04:00
|
|
|
it "should return a select friendly array of states in the form of [['Friendly name', 'state_name']]" do
|
|
|
|
Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
|
2008-04-14 15:57:34 -04:00
|
|
|
end
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
describe AASM, '- instance level definitions' do
|
|
|
|
before(:each) do
|
|
|
|
@foo = Foo.new
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should define a state querying instance method on including class' do
|
|
|
|
@foo.should respond_to(:open?)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should define an event! inance method' do
|
|
|
|
@foo.should respond_to(:close!)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe AASM, '- initial states' do
|
|
|
|
before(:each) do
|
|
|
|
@foo = Foo.new
|
|
|
|
@bar = Bar.new
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should set the initial state' do
|
2008-01-08 09:39:00 -05:00
|
|
|
@foo.aasm_current_state.should == :open
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it '#open? should be initially true' do
|
|
|
|
@foo.open?.should be_true
|
|
|
|
end
|
|
|
|
|
|
|
|
it '#closed? should be initially false' do
|
|
|
|
@foo.closed?.should be_false
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should use the first state defined if no initial state is given' do
|
2008-01-08 09:39:00 -05:00
|
|
|
@bar.aasm_current_state.should == :read
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
2009-05-27 20:32:02 -04:00
|
|
|
|
2009-02-26 12:06:43 -05:00
|
|
|
it 'should determine initial state from the Proc results' do
|
|
|
|
Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages
|
|
|
|
Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired
|
|
|
|
end
|
2008-01-07 14:11:38 -05:00
|
|
|
end
|
2008-02-21 10:16:08 -05:00
|
|
|
|
2008-04-29 01:27:56 -04:00
|
|
|
describe AASM, '- event firing with persistence' do
|
2008-02-21 10:16:08 -05:00
|
|
|
it 'should fire the Event' do
|
|
|
|
foo = Foo.new
|
|
|
|
|
|
|
|
Foo.aasm_events[:close].should_receive(:fire).with(foo)
|
|
|
|
foo.close!
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should update the current state' do
|
|
|
|
foo = Foo.new
|
|
|
|
foo.close!
|
|
|
|
|
|
|
|
foo.aasm_current_state.should == :closed
|
|
|
|
end
|
|
|
|
|
2008-05-20 15:27:35 -04:00
|
|
|
it 'should call the success callback if one was provided' do
|
|
|
|
foo = Foo.new
|
|
|
|
|
|
|
|
foo.should_receive(:success_callback)
|
|
|
|
|
|
|
|
foo.close!
|
|
|
|
end
|
|
|
|
|
2008-02-21 11:08:55 -05:00
|
|
|
it 'should attempt to persist if aasm_write_state is defined' do
|
2008-02-21 10:16:08 -05:00
|
|
|
foo = Foo.new
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-02-21 11:08:55 -05:00
|
|
|
def foo.aasm_write_state
|
2008-02-21 10:16:08 -05:00
|
|
|
end
|
|
|
|
|
2008-02-21 11:08:55 -05:00
|
|
|
foo.should_receive(:aasm_write_state)
|
2008-02-21 10:16:08 -05:00
|
|
|
|
|
|
|
foo.close!
|
|
|
|
end
|
2008-10-03 11:22:51 -04:00
|
|
|
|
2008-10-03 13:22:26 -04:00
|
|
|
it 'should return true if aasm_write_state is defined and returns true' do
|
|
|
|
foo = Foo.new
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-10-03 13:22:26 -04:00
|
|
|
def foo.aasm_write_state(state)
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
foo.close!.should be_true
|
|
|
|
end
|
|
|
|
|
2008-10-03 11:22:51 -04:00
|
|
|
it 'should return false if aasm_write_state is defined and returns false' do
|
|
|
|
foo = Foo.new
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-10-03 13:15:39 -04:00
|
|
|
def foo.aasm_write_state(state)
|
2008-10-03 11:22:51 -04:00
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
foo.close!.should be_false
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should not update the aasm_current_state if the write fails" do
|
|
|
|
foo = Foo.new
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-10-03 11:22:51 -04:00
|
|
|
def foo.aasm_write_state
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
foo.should_receive(:aasm_write_state)
|
|
|
|
|
|
|
|
foo.close!
|
|
|
|
foo.aasm_current_state.should == :open
|
|
|
|
end
|
2008-02-21 10:16:08 -05:00
|
|
|
end
|
2008-02-21 11:08:55 -05:00
|
|
|
|
2008-04-29 01:27:56 -04:00
|
|
|
describe AASM, '- event firing without persistence' do
|
|
|
|
it 'should fire the Event' do
|
|
|
|
foo = Foo.new
|
|
|
|
|
|
|
|
Foo.aasm_events[:close].should_receive(:fire).with(foo)
|
|
|
|
foo.close
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should update the current state' do
|
|
|
|
foo = Foo.new
|
|
|
|
foo.close
|
|
|
|
|
|
|
|
foo.aasm_current_state.should == :closed
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should attempt to persist if aasm_write_state is defined' do
|
|
|
|
foo = Foo.new
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-04-29 01:27:56 -04:00
|
|
|
def foo.aasm_write_state
|
|
|
|
end
|
|
|
|
|
2010-06-29 11:58:35 -04:00
|
|
|
foo.should_receive(:aasm_write_state_without_persistence).twice
|
2008-04-29 01:27:56 -04:00
|
|
|
|
|
|
|
foo.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2008-02-21 11:08:55 -05:00
|
|
|
describe AASM, '- persistence' do
|
|
|
|
it 'should read the state if it has not been set and aasm_read_state is defined' do
|
|
|
|
foo = Foo.new
|
|
|
|
def foo.aasm_read_state
|
|
|
|
end
|
|
|
|
|
|
|
|
foo.should_receive(:aasm_read_state)
|
|
|
|
|
|
|
|
foo.aasm_current_state
|
|
|
|
end
|
|
|
|
end
|
2008-03-02 07:33:37 -05:00
|
|
|
|
|
|
|
describe AASM, '- getting events for a state' do
|
|
|
|
it '#aasm_events_for_current_state should use current state' do
|
|
|
|
foo = Foo.new
|
|
|
|
foo.should_receive(:aasm_current_state)
|
|
|
|
foo.aasm_events_for_current_state
|
|
|
|
end
|
|
|
|
|
|
|
|
it '#aasm_events_for_current_state should use aasm_events_for_state' do
|
|
|
|
foo = Foo.new
|
|
|
|
foo.stub!(:aasm_current_state).and_return(:foo)
|
|
|
|
foo.should_receive(:aasm_events_for_state).with(:foo)
|
|
|
|
foo.aasm_events_for_current_state
|
|
|
|
end
|
|
|
|
end
|
2008-03-02 07:52:46 -05:00
|
|
|
|
|
|
|
describe AASM, '- event callbacks' do
|
2009-12-01 05:59:48 -05:00
|
|
|
describe "with an error callback defined" do
|
2009-12-01 06:28:52 -05:00
|
|
|
before do
|
2009-12-02 05:43:49 -05:00
|
|
|
class Foo
|
|
|
|
aasm_event :safe_close, :success => :success_callback, :error => :error_callback do
|
|
|
|
transitions :to => :closed, :from => [:open]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-12-01 06:28:52 -05:00
|
|
|
@foo = Foo.new
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should run error_callback if an exception is raised and error_callback defined" do
|
|
|
|
def @foo.error_callback(e)
|
2009-12-01 05:59:48 -05:00
|
|
|
end
|
2009-12-01 06:28:52 -05:00
|
|
|
@foo.stub!(:enter).and_raise(e=StandardError.new)
|
|
|
|
@foo.should_receive(:error_callback).with(e)
|
2009-12-02 05:43:49 -05:00
|
|
|
@foo.safe_close!
|
2009-12-01 06:28:52 -05:00
|
|
|
end
|
|
|
|
|
2009-12-02 05:43:49 -05:00
|
|
|
it "should raise NoMethodError if exceptionis raised and error_callback is declared but not defined" do
|
|
|
|
@foo.stub!(:enter).and_raise(StandardError)
|
|
|
|
lambda{@foo.safe_close!}.should raise_error(NoMethodError)
|
|
|
|
end
|
2011-09-16 11:12:10 -04:00
|
|
|
|
2009-12-02 05:43:49 -05:00
|
|
|
it "should propagate an error if no error callback is declared" do
|
|
|
|
@foo.stub!(:enter).and_raise("Cannot enter safe")
|
2011-09-16 11:12:10 -04:00
|
|
|
lambda{@foo.close!}.should raise_error(StandardError, "Cannot enter safe")
|
2009-12-01 06:28:52 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
describe "with aasm_event_fired defined" do
|
|
|
|
before do
|
|
|
|
@foo = Foo.new
|
|
|
|
def @foo.aasm_event_fired(event, from, to)
|
|
|
|
end
|
2008-03-02 07:52:46 -05:00
|
|
|
end
|
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
it 'should call it for successful bang fire' do
|
|
|
|
@foo.should_receive(:aasm_event_fired).with(:close, :open, :closed)
|
|
|
|
@foo.close!
|
2008-10-03 13:15:39 -04:00
|
|
|
end
|
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
it 'should call it for successful non-bang fire' do
|
|
|
|
@foo.should_receive(:aasm_event_fired)
|
|
|
|
@foo.close
|
2008-10-03 13:15:39 -04:00
|
|
|
end
|
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
it 'should not call it for failing bang fire' do
|
2011-11-25 19:10:05 -05:00
|
|
|
@foo.stub!(:aasm_set_current_state_with_persistence).and_return(false)
|
2009-04-09 01:23:02 -04:00
|
|
|
@foo.should_not_receive(:aasm_event_fired)
|
|
|
|
@foo.close!
|
2008-05-30 19:33:27 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
describe "with aasm_event_failed defined" do
|
|
|
|
before do
|
|
|
|
@foo = Foo.new
|
|
|
|
def @foo.aasm_event_failed(event, from)
|
|
|
|
end
|
2008-03-02 07:52:46 -05:00
|
|
|
end
|
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
it 'should call it when transition failed for bang fire' do
|
|
|
|
@foo.should_receive(:aasm_event_failed).with(:null, :open)
|
|
|
|
@foo.null!
|
2008-05-30 19:33:27 -04:00
|
|
|
end
|
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
it 'should call it when transition failed for non-bang fire' do
|
|
|
|
@foo.should_receive(:aasm_event_failed).with(:null, :open)
|
|
|
|
@foo.null
|
|
|
|
end
|
2008-05-30 19:33:27 -04:00
|
|
|
|
2009-04-09 01:23:02 -04:00
|
|
|
it 'should not call it if persist fails for bang fire' do
|
2011-11-25 19:10:05 -05:00
|
|
|
@foo.stub!(:aasm_set_current_state_with_persistence).and_return(false)
|
2009-04-09 01:23:02 -04:00
|
|
|
@foo.should_receive(:aasm_event_failed)
|
|
|
|
@foo.close!
|
|
|
|
end
|
2008-05-30 19:33:27 -04:00
|
|
|
end
|
2008-03-02 07:52:46 -05:00
|
|
|
end
|
|
|
|
|
2008-05-31 18:08:12 -04:00
|
|
|
describe AASM, '- state actions' do
|
|
|
|
it "should call enter when entering state" do
|
|
|
|
foo = Foo.new
|
|
|
|
foo.should_receive(:enter)
|
|
|
|
|
|
|
|
foo.close
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should call exit when exiting state" do
|
|
|
|
foo = Foo.new
|
|
|
|
foo.should_receive(:exit)
|
2008-03-02 07:52:46 -05:00
|
|
|
|
2008-05-31 18:08:12 -04:00
|
|
|
foo.close
|
|
|
|
end
|
|
|
|
end
|
2008-06-01 17:48:17 -04:00
|
|
|
|
|
|
|
|
|
|
|
describe Baz do
|
|
|
|
it "should have the same states as it's parent" do
|
|
|
|
Baz.aasm_states.should == Bar.aasm_states
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should have the same events as it's parent" do
|
|
|
|
Baz.aasm_events.should == Bar.aasm_events
|
|
|
|
end
|
|
|
|
end
|
2008-06-04 00:44:25 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
describe ChetanPatil do
|
|
|
|
it 'should transition to specified next state (sleeping to showering)' do
|
|
|
|
cp = ChetanPatil.new
|
|
|
|
cp.wakeup! :showering
|
2009-01-29 12:19:48 -05:00
|
|
|
|
2008-06-04 00:44:25 -04:00
|
|
|
cp.aasm_current_state.should == :showering
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should transition to specified next state (sleeping to working)' do
|
|
|
|
cp = ChetanPatil.new
|
|
|
|
cp.wakeup! :working
|
|
|
|
|
|
|
|
cp.aasm_current_state.should == :working
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should transition to default (first or showering) state' do
|
|
|
|
cp = ChetanPatil.new
|
|
|
|
cp.wakeup!
|
|
|
|
|
|
|
|
cp.aasm_current_state.should == :showering
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should transition to default state when on_transition invoked' do
|
|
|
|
cp = ChetanPatil.new
|
|
|
|
cp.dress!(nil, 'purple', 'dressy')
|
|
|
|
|
|
|
|
cp.aasm_current_state.should == :working
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should call on_transition method with args' do
|
|
|
|
cp = ChetanPatil.new
|
|
|
|
cp.wakeup! :showering
|
|
|
|
|
|
|
|
cp.should_receive(:wear_clothes).with('blue', 'jeans')
|
|
|
|
cp.dress! :working, 'blue', 'jeans'
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should call on_transition proc' do
|
|
|
|
cp = ChetanPatil.new
|
|
|
|
cp.wakeup! :showering
|
|
|
|
|
|
|
|
cp.should_receive(:wear_clothes).with('purple', 'slacks')
|
|
|
|
cp.dress!(:dating, 'purple', 'slacks')
|
|
|
|
end
|
2009-01-29 12:19:48 -05:00
|
|
|
|
|
|
|
it 'should call on_transition with an array of methods' do
|
|
|
|
cp = ChetanPatil.new
|
|
|
|
cp.wakeup! :showering
|
|
|
|
cp.should_receive(:condition_hair)
|
|
|
|
cp.should_receive(:fix_hair)
|
|
|
|
cp.dress!(:prettying_up)
|
|
|
|
end
|
2008-06-04 00:44:25 -04:00
|
|
|
end
|