Skip to content

Commit

Permalink
Add specs for new behavior, experiment with error matching
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswoodrich committed Oct 22, 2015
1 parent b6d5a0d commit 9702bf7
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 13 deletions.
2 changes: 1 addition & 1 deletion lib/aasm/core/event.rb
Expand Up @@ -73,7 +73,7 @@ def transitions(definitions=nil, &block)
end

def failed_callbacks
@transitions.flat_map(&:failures)
transitions.flat_map(&:failures)
end

private
Expand Down
4 changes: 3 additions & 1 deletion lib/aasm/core/transition.rb
Expand Up @@ -57,7 +57,9 @@ def invoke_callbacks_compatible_with_guard(code, record, args, options={})
failures << code unless result
result
when Proc
code.arity == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code)
result = (code.arity == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code))
failures << code.source_location.join('#') unless result
result
when Array
if options[:guard]
# invoke guard callbacks
Expand Down
53 changes: 42 additions & 11 deletions spec/unit/callback_multiple_spec.rb
@@ -1,6 +1,16 @@
require 'spec_helper'
Dir[File.dirname(__FILE__) + "/../models/callbacks/*.rb"].sort.each { |f| require File.expand_path(f) }

def safe_error(callback = nil)
error = nil
begin
yield
rescue Exception => e
error = e
return error
end
end

describe 'callbacks for the new DSL' do

it "be called in order" do
Expand Down Expand Up @@ -47,9 +57,13 @@
expect(callback).to_not receive(:after_enter_closed)
expect(callback).to_not receive(:after_event)

expect {
callback.left_close!
}.to raise_error(AASM::InvalidTransition)
error = safe_error { callback.left_close! }

expect(error.class).to eq AASM::InvalidTransition
expect(error.message).to eq(
"Event 'left_close' cannot transition from 'open'. Failed callback(s): [:after_transition, :event_guard]."
)

end

it "handles private callback methods as well" do
Expand Down Expand Up @@ -85,9 +99,12 @@
expect(callback).to_not receive(:after_event)
end

expect {
callback.left_close!
}.to raise_error(AASM::InvalidTransition)
error = safe_error { callback.left_close! }

expect(error.class).to eq AASM::InvalidTransition
expect(error.message).to eq(
"Event 'left_close' cannot transition from 'open'. Failed callback(s): [:after_transition, :event_guard, :transition_guard]."
)
end

it "does not run transition_guard twice for multiple permitted transitions" do
Expand Down Expand Up @@ -133,9 +150,10 @@
expect(callback).to_not receive(:after_enter_closed)
expect(callback).to_not receive(:after)

expect {
callback.close!
}.to raise_error(AASM::InvalidTransition)
error = safe_error(callback) { callback.close! }

expect(error.class).to eq AASM::InvalidTransition
expect(error.message).to eq "Event 'close' cannot transition from 'open'. Failed callback(s): [\"/Users/woodrich/Dropbox/personal/aasm/spec/models/callbacks/guard_within_block_multiple.rb#30\"]."
end
end

Expand Down Expand Up @@ -277,12 +295,25 @@ def @foo.aasm_event_failed(event, from); end

it 'should call it when transition failed for bang fire' do
expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
expect {@foo.null!}.to raise_error(AASM::InvalidTransition)
#expect {@foo.null!}.to raise_error(AASM::InvalidTransition)

error = safe_error { @foo.null! }

expect(error.class).to eq AASM::InvalidTransition
expect(error.message).to eq(
"Event 'null' cannot transition from 'open'. Failed callback(s): [:always_false]."
)

end

it 'should call it when transition failed for non-bang fire' do
expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
expect {@foo.null}.to raise_error(AASM::InvalidTransition)
error = safe_error { @foo.null }

expect(error.class).to eq AASM::InvalidTransition
expect(error.message).to eq(
"Event 'null' cannot transition from 'open'. Failed callback(s): [:always_false]."
)
end

it 'should not call it if persist fails for bang fire' do
Expand Down
29 changes: 29 additions & 0 deletions spec/unit/event_spec.rb
Expand Up @@ -109,6 +109,35 @@
expect(event.fire(obj, {}, nil, 'arg1', 'arg2')).to eq(:closed)
end

context 'when given a gaurd proc' do
it 'should have access to callback failures in the transitions' do
event = AASM::Core::Event.new(:graduate, state_machine) do
transitions :to => :alumni, :from => [:student, :applicant],
:guard => Proc.new { 1 + 1 == 3 }
end
line_number = __LINE__ - 2
obj = double('object', :aasm => double('aasm', :current_state => :student))

event.fire(obj, {}, nil)
expect(event.failed_callbacks).to eq ["#{__FILE__}##{line_number}"]
end
end

context 'when given a guard symbol' do
it 'should have access to callback failures in the transitions' do
event = AASM::Core::Event.new(:graduate, state_machine) do
transitions :to => :alumni, :from => [:student, :applicant],
guard: :paid_tuition?
end

obj = double('object', :aasm => double('aasm', :current_state => :student))
allow(obj).to receive(:paid_tuition?).and_return(false)

event.fire(obj, {}, nil)
expect(event.failed_callbacks).to eq [:paid_tuition?]
end
end

end

describe 'should fire callbacks' do
Expand Down
11 changes: 11 additions & 0 deletions spec/unit/transition_spec.rb
Expand Up @@ -145,6 +145,17 @@
expect(st.allowed?(obj)).to be false
end

it 'should add the name of the failed method calls to the failures instance var' do
opts = {:from => 'foo', :to => 'bar', :guard => :test}
st = AASM::Core::Transition.new(event, opts)

obj = double('object')
expect(obj).to receive(:test)

st.allowed?(obj)
expect(st.failures).to eq [:test]
end

it 'should call the method on the object if unless is a symbol' do
opts = {:from => 'foo', :to => 'bar', :unless => :test}
st = AASM::Core::Transition.new(event, opts)
Expand Down

0 comments on commit 9702bf7

Please sign in to comment.