mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
Merge branch 'master' into aasm4
This commit is contained in:
commit
787650f4b3
24 changed files with 581 additions and 355 deletions
|
@ -16,6 +16,10 @@
|
|||
## 3.1.0 (not yet released)
|
||||
|
||||
* validating the current state (see [issue #95](https://github.com/aasm/aasm/issues/95), thanks to [@ivantsepp](https://github.com/ivantsepp))
|
||||
* allow configuring behavior of nested transactions (see [issue #107](https://github.com/aasm/aasm/issues/107))
|
||||
* support multiple guards per transition
|
||||
* support event guards (see [issue #85](https://github.com/aasm/aasm/issues/85))
|
||||
* support reading from- and to-state during on_transition callback (see [issue #100](https://github.com/aasm/aasm/issues/100))
|
||||
|
||||
## 3.0.26
|
||||
|
||||
|
|
54
README.md
54
README.md
|
@ -1,6 +1,9 @@
|
|||
# AASM - Ruby state machines
|
||||
|
||||
[![Gem Version](https://badge.fury.io/rb/aasm.png)](http://badge.fury.io/rb/aasm) [![Build Status](https://secure.travis-ci.org/aasm/aasm.png?branch=master)](http://travis-ci.org/aasm/aasm) [![Code Climate](https://codeclimate.com/github/aasm/aasm.png)](https://codeclimate.com/github/aasm/aasm) [![Coverage Status](https://coveralls.io/repos/aasm/aasm/badge.png?branch=master)](https://coveralls.io/r/aasm/aasm)
|
||||
<a href="http://badge.fury.io/rb/aasm"><img src="https://badge.fury.io/rb/aasm@2x.png" alt="Gem Version" height="18"></a>
|
||||
[![Build Status](https://secure.travis-ci.org/aasm/aasm.png?branch=master)](http://travis-ci.org/aasm/aasm)
|
||||
[![Code Climate](https://codeclimate.com/github/aasm/aasm.png)](https://codeclimate.com/github/aasm/aasm)
|
||||
[![Coverage Status](https://coveralls.io/repos/aasm/aasm/badge.png?branch=master)](https://coveralls.io/r/aasm/aasm)
|
||||
|
||||
This package contains AASM, a library for adding finite state machines to Ruby classes.
|
||||
|
||||
|
@ -149,6 +152,15 @@ In this case the `set_process` would be called with `:defagmentation` argument.
|
|||
In case of an error during the event processing the error is rescued and passed to `:error`
|
||||
callback, which can handle it or re-raise it for further propagation.
|
||||
|
||||
During the `:on_transition` callback (and reliably only then) you can access the
|
||||
originating state (the from-state) and the target state (the to state), like this:
|
||||
|
||||
```ruby
|
||||
def set_process(name)
|
||||
logger.info "from #{aasm.from_state} to #{aasm.to_state}"
|
||||
end
|
||||
```
|
||||
|
||||
### Guards
|
||||
|
||||
Let's assume you want to allow particular transitions only if a defined condition is
|
||||
|
@ -190,6 +202,24 @@ job.may_sleep? # => false
|
|||
job.sleep # => raises AASM::InvalidTransition
|
||||
```
|
||||
|
||||
You can even provide a number of guards, which all have to succeed to proceed
|
||||
|
||||
```ruby
|
||||
def walked_the_dog?; ...; end
|
||||
|
||||
event :sleep do
|
||||
transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?, :walked_the_dog?]
|
||||
end
|
||||
```
|
||||
|
||||
If you want to provide guards for all transitions withing an event, you can use event guards
|
||||
|
||||
```ruby
|
||||
event :sleep, :guards => [:walked_the_dog?] do
|
||||
transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?]
|
||||
transitions :from => :cleaning, :to => :sleeping
|
||||
end
|
||||
```
|
||||
|
||||
### ActiveRecord
|
||||
|
||||
|
@ -339,6 +369,28 @@ class Job < ActiveRecord::Base
|
|||
end
|
||||
```
|
||||
|
||||
If you want to encapsulate state changes within an own transaction, the behavior
|
||||
of this nested transaction might be confusing. Take a look at
|
||||
[ActiveRecord Nested Transactions](http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html)
|
||||
if you want to know more about this. Nevertheless, AASM by default requires a new transaction
|
||||
`transaction(:requires_new => true)`. You can override this behavior by changing
|
||||
the configuration
|
||||
|
||||
```ruby
|
||||
class Job < ActiveRecord::Base
|
||||
include AASM
|
||||
|
||||
aasm :requires_new_transaction => false do
|
||||
...
|
||||
end
|
||||
|
||||
...
|
||||
end
|
||||
```
|
||||
|
||||
which then leads to `transaction(:requires_new => false)`, the Rails default.
|
||||
|
||||
|
||||
### Column name & migration
|
||||
|
||||
As a default AASM uses the column `aasm_state` to store the states. You can override
|
||||
|
|
|
@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|||
# s.add_development_dependency 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
||||
s.add_development_dependency 'rake'
|
||||
s.add_development_dependency 'sdoc'
|
||||
s.add_development_dependency 'rspec', '~> 2.14'
|
||||
s.add_development_dependency 'rspec', '>= 2.14'
|
||||
s.add_development_dependency 'rr'
|
||||
# s.add_development_dependency 'sqlite3'
|
||||
s.add_development_dependency 'minitest'
|
||||
|
|
|
@ -5,24 +5,19 @@ module AASM
|
|||
@clazz = clazz
|
||||
@state_machine = AASM::StateMachine[@clazz]
|
||||
@state_machine.config.column = options[:column].to_sym if options[:column]
|
||||
@options = options
|
||||
|
||||
if options.key?(:whiny_transitions)
|
||||
@state_machine.config.whiny_transitions = options[:whiny_transitions]
|
||||
elsif @state_machine.config.whiny_transitions.nil?
|
||||
@state_machine.config.whiny_transitions = true # this is the default, so let's cry
|
||||
end
|
||||
# let's cry if the transition is invalid
|
||||
configure :whiny_transitions, true
|
||||
|
||||
if options.key?(:create_scopes)
|
||||
@state_machine.config.create_scopes = options[:create_scopes]
|
||||
elsif @state_machine.config.create_scopes.nil?
|
||||
@state_machine.config.create_scopes = true # this is the default, so let's create scopes
|
||||
end
|
||||
# create named scopes for each state
|
||||
configure :create_scopes, true
|
||||
|
||||
if options.key?(:skip_validation_on_save)
|
||||
@state_machine.config.skip_validation_on_save = options[:skip_validation_on_save]
|
||||
elsif @state_machine.config.skip_validation_on_save.nil?
|
||||
@state_machine.config.skip_validation_on_save = false # this is the default, so don't store any new state if the model is invalid
|
||||
end
|
||||
# don't store any new state if the model is invalid
|
||||
configure :skip_validation_on_save, false
|
||||
|
||||
# use requires_new for nested transactions
|
||||
configure :requires_new_transaction, true
|
||||
end
|
||||
|
||||
def initial_state(new_initial_state=nil)
|
||||
|
@ -87,5 +82,16 @@ module AASM
|
|||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def configure(key, default_value)
|
||||
@state_machine.config.send(:new_ostruct_member, key)
|
||||
if @options.key?(key)
|
||||
@state_machine.config.send("#{key}=", @options[key])
|
||||
elsif @state_machine.config.send(key).nil?
|
||||
@state_machine.config.send("#{key}=", default_value)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@ module AASM
|
|||
def initialize(name, options = {}, &block)
|
||||
@name = name
|
||||
@transitions = []
|
||||
@guards = Array(options[:guard] || options[:guards])
|
||||
update(options, &block)
|
||||
end
|
||||
|
||||
|
@ -59,18 +60,28 @@ module AASM
|
|||
## DSL interface
|
||||
def transitions(definitions=nil)
|
||||
if definitions # define new transitions
|
||||
# Create a separate transition for each from state to the given state
|
||||
# Create a separate transition for each from-state to the given state
|
||||
Array(definitions[:from]).each do |s|
|
||||
@transitions << AASM::Transition.new(definitions.merge({:from => s.to_sym}))
|
||||
@transitions << AASM::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)))
|
||||
end
|
||||
# Create a transition if :to is specified without :from (transitions from ANY state)
|
||||
if @transitions.empty? && definitions[:to]
|
||||
@transitions << AASM::Transition.new(attach_event_guards(definitions))
|
||||
end
|
||||
# Create a transition if to is specified without from (transitions from ANY state)
|
||||
@transitions << AASM::Transition.new(definitions) if @transitions.empty? && definitions[:to]
|
||||
end
|
||||
@transitions
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attach_event_guards(definitions)
|
||||
unless @guards.empty?
|
||||
given_guards = Array(definitions.delete(:guard) || definitions.delete(:guards))
|
||||
definitions[:guards] = given_guards + @guards
|
||||
end
|
||||
definitions
|
||||
end
|
||||
|
||||
def update(options = {}, &block)
|
||||
@options = options
|
||||
if block then
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module AASM
|
||||
class InstanceBase
|
||||
|
||||
attr_accessor :from_state, :to_state
|
||||
|
||||
def initialize(instance)
|
||||
@instance = instance
|
||||
end
|
||||
|
|
|
@ -138,7 +138,7 @@ module AASM
|
|||
end
|
||||
|
||||
def aasm_fire_event(name, options, *args, &block)
|
||||
success = self.class.transaction(:requires_new => true) do
|
||||
success = self.class.transaction(:requires_new => requires_new?) do
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -150,6 +150,10 @@ module AASM
|
|||
success
|
||||
end
|
||||
|
||||
def requires_new?
|
||||
AASM::StateMachine[self.class].config.requires_new_transaction
|
||||
end
|
||||
|
||||
def aasm_validate_states
|
||||
unless AASM::StateMachine[self.class].config.skip_validation_on_save
|
||||
if aasm.current_state && !aasm.states.include?(aasm.current_state)
|
||||
|
|
|
@ -4,20 +4,24 @@ module AASM
|
|||
alias_method :options, :opts
|
||||
|
||||
def initialize(opts)
|
||||
@from, @to, @guard, @on_transition = opts[:from], opts[:to], opts[:guard], opts[:on_transition]
|
||||
@from = opts[:from]
|
||||
@to = opts[:to]
|
||||
@guards = Array(opts[:guard] || opts[:guards])
|
||||
@on_transition = opts[:on_transition]
|
||||
@opts = opts
|
||||
end
|
||||
|
||||
# TODO: should be named allowed? or similar
|
||||
def perform(obj, *args)
|
||||
case @guard
|
||||
@guards.each do |guard|
|
||||
case guard
|
||||
when Symbol, String
|
||||
obj.send(@guard, *args)
|
||||
return false unless obj.send(guard, *args)
|
||||
when Proc
|
||||
@guard.call(obj, *args)
|
||||
else
|
||||
true
|
||||
return false unless guard.call(obj, *args)
|
||||
end
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def execute(obj, *args)
|
||||
|
@ -37,6 +41,9 @@ module AASM
|
|||
private
|
||||
|
||||
def _execute(obj, on_transition, *args)
|
||||
obj.aasm.from_state = @from if obj.aasm.respond_to?(:from_state=)
|
||||
obj.aasm.to_state = @to if obj.aasm.respond_to?(:to_state=)
|
||||
|
||||
case on_transition
|
||||
when Proc
|
||||
on_transition.arity == 0 ? on_transition.call : on_transition.call(obj, *args)
|
||||
|
|
48
spec/models/guardian.rb
Normal file
48
spec/models/guardian.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
class Guardian
|
||||
include AASM
|
||||
|
||||
aasm 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
|
|
@ -3,19 +3,19 @@ require 'models/active_record/api.rb'
|
|||
|
||||
describe "reading the current state" do
|
||||
it "uses the AASM default" do
|
||||
DefaultState.new.aasm.current_state.should eql :alpha
|
||||
expect(DefaultState.new.aasm.current_state).to eql :alpha
|
||||
end
|
||||
|
||||
it "uses the provided method" do
|
||||
ProvidedState.new.aasm.current_state.should eql :beta
|
||||
expect(ProvidedState.new.aasm.current_state).to eql :beta
|
||||
end
|
||||
|
||||
it "uses the persistence storage" do
|
||||
PersistedState.new.aasm.current_state.should eql :alpha
|
||||
expect(PersistedState.new.aasm.current_state).to eql :alpha
|
||||
end
|
||||
|
||||
it "uses the provided method even if persisted" do
|
||||
ProvidedAndPersistedState.new.aasm.current_state.should eql :gamma
|
||||
expect(ProvidedAndPersistedState.new.aasm.current_state).to eql :gamma
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -23,25 +23,25 @@ describe "writing and persisting the current state" do
|
|||
it "uses the AASM default" do
|
||||
o = DefaultState.new
|
||||
o.release!
|
||||
o.persisted_store.should be_nil
|
||||
expect(o.persisted_store).to be_nil
|
||||
end
|
||||
|
||||
it "uses the provided method" do
|
||||
o = ProvidedState.new
|
||||
o.release!
|
||||
o.persisted_store.should eql :beta
|
||||
expect(o.persisted_store).to eql :beta
|
||||
end
|
||||
|
||||
it "uses the persistence storage" do
|
||||
o = PersistedState.new
|
||||
o.release!
|
||||
o.persisted_store.should be_nil
|
||||
expect(o.persisted_store).to be_nil
|
||||
end
|
||||
|
||||
it "uses the provided method even if persisted" do
|
||||
o = ProvidedAndPersistedState.new
|
||||
o.release!
|
||||
o.persisted_store.should eql :beta
|
||||
expect(o.persisted_store).to eql :beta
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,24 +49,24 @@ describe "writing the current state without persisting it" do
|
|||
it "uses the AASM default" do
|
||||
o = DefaultState.new
|
||||
o.release
|
||||
o.transient_store.should be_nil
|
||||
expect(o.transient_store).to be_nil
|
||||
end
|
||||
|
||||
it "uses the provided method" do
|
||||
o = ProvidedState.new
|
||||
o.release
|
||||
o.transient_store.should eql :beta
|
||||
expect(o.transient_store).to eql :beta
|
||||
end
|
||||
|
||||
it "uses the persistence storage" do
|
||||
o = PersistedState.new
|
||||
o.release
|
||||
o.transient_store.should be_nil
|
||||
expect(o.transient_store).to be_nil
|
||||
end
|
||||
|
||||
it "uses the provided method even if persisted" do
|
||||
o = ProvidedAndPersistedState.new
|
||||
o.release
|
||||
o.transient_store.should eql :beta
|
||||
expect(o.transient_store).to eql :beta
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,15 +4,15 @@ describe 'callbacks for the new DSL' do
|
|||
let(:callback) {CallbackNewDsl.new}
|
||||
|
||||
it "be called in order" do
|
||||
callback.should_receive(:exit_open).once.ordered
|
||||
callback.should_receive(:before).once.ordered
|
||||
callback.should_receive(:before_exit_open).once.ordered # these should be before the state changes
|
||||
callback.should_receive(:before_enter_closed).once.ordered
|
||||
callback.should_receive(:enter_closed).once.ordered
|
||||
callback.should_receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
|
||||
callback.should_receive(:after_exit_open).once.ordered # these should be after the state changes
|
||||
callback.should_receive(:after_enter_closed).once.ordered
|
||||
callback.should_receive(:after).once.ordered
|
||||
expect(callback).to receive(:exit_open).once.ordered
|
||||
expect(callback).to receive(:before).once.ordered
|
||||
expect(callback).to receive(:before_exit_open).once.ordered # these should be before the state changes
|
||||
expect(callback).to receive(:before_enter_closed).once.ordered
|
||||
expect(callback).to receive(:enter_closed).once.ordered
|
||||
expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
|
||||
expect(callback).to receive(:after_exit_open).once.ordered # these should be after the state changes
|
||||
expect(callback).to receive(:after_enter_closed).once.ordered
|
||||
expect(callback).to receive(:after).once.ordered
|
||||
|
||||
callback.close!
|
||||
end
|
||||
|
@ -67,20 +67,20 @@ describe 'event callbacks' do
|
|||
it "should run error_callback if an exception is raised and error_callback defined" do
|
||||
def @foo.error_callback(e); end
|
||||
|
||||
@foo.stub(:enter).and_raise(e=StandardError.new)
|
||||
@foo.should_receive(:error_callback).with(e)
|
||||
allow(@foo).to receive(:enter).and_raise(e=StandardError.new)
|
||||
expect(@foo).to receive(:error_callback).with(e)
|
||||
|
||||
@foo.safe_close!
|
||||
end
|
||||
|
||||
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)
|
||||
allow(@foo).to receive(:enter).and_raise(StandardError)
|
||||
expect{@foo.safe_close!}.to raise_error(NoMethodError)
|
||||
end
|
||||
|
||||
it "should propagate an error if no error callback is declared" do
|
||||
@foo.stub(:enter).and_raise("Cannot enter safe")
|
||||
lambda{@foo.close!}.should raise_error(StandardError, "Cannot enter safe")
|
||||
allow(@foo).to receive(:enter).and_raise("Cannot enter safe")
|
||||
expect{@foo.close!}.to raise_error(StandardError, "Cannot enter safe")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -91,18 +91,18 @@ describe 'event callbacks' do
|
|||
end
|
||||
|
||||
it 'should call it for successful bang fire' do
|
||||
@foo.should_receive(:aasm_event_fired).with(:close, :open, :closed)
|
||||
expect(@foo).to receive(:aasm_event_fired).with(:close, :open, :closed)
|
||||
@foo.close!
|
||||
end
|
||||
|
||||
it 'should call it for successful non-bang fire' do
|
||||
@foo.should_receive(:aasm_event_fired)
|
||||
expect(@foo).to receive(:aasm_event_fired)
|
||||
@foo.close
|
||||
end
|
||||
|
||||
it 'should not call it for failing bang fire' do
|
||||
@foo.aasm.stub(:set_current_state_with_persistence).and_return(false)
|
||||
@foo.should_not_receive(:aasm_event_fired)
|
||||
allow(@foo.aasm).to receive(:set_current_state_with_persistence).and_return(false)
|
||||
expect(@foo).not_to receive(:aasm_event_fired)
|
||||
@foo.close!
|
||||
end
|
||||
end
|
||||
|
@ -114,18 +114,18 @@ describe 'event callbacks' do
|
|||
end
|
||||
|
||||
it 'should call it when transition failed for bang fire' do
|
||||
@foo.should_receive(:aasm_event_failed).with(:null, :open)
|
||||
lambda {@foo.null!}.should raise_error(AASM::InvalidTransition)
|
||||
expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
|
||||
expect {@foo.null!}.to raise_error(AASM::InvalidTransition)
|
||||
end
|
||||
|
||||
it 'should call it when transition failed for non-bang fire' do
|
||||
@foo.should_receive(:aasm_event_failed).with(:null, :open)
|
||||
lambda {@foo.null}.should raise_error(AASM::InvalidTransition)
|
||||
expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
|
||||
expect {@foo.null}.to raise_error(AASM::InvalidTransition)
|
||||
end
|
||||
|
||||
it 'should not call it if persist fails for bang fire' do
|
||||
@foo.aasm.stub(:set_current_state_with_persistence).and_return(false)
|
||||
@foo.should_receive(:aasm_event_failed)
|
||||
allow(@foo.aasm).to receive(:set_current_state_with_persistence).and_return(false)
|
||||
expect(@foo).to receive(:aasm_event_failed)
|
||||
@foo.close!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,12 +4,12 @@ describe 'on initialization' do
|
|||
let(:auth) {AuthMachine.new}
|
||||
|
||||
it 'should be in the pending state' do
|
||||
auth.aasm.current_state.should == :pending
|
||||
expect(auth.aasm.current_state).to eq(:pending)
|
||||
end
|
||||
|
||||
it 'should have an activation code' do
|
||||
auth.has_activation_code?.should be_true
|
||||
auth.activation_code.should_not be_nil
|
||||
expect(auth.has_activation_code?).to be_true
|
||||
expect(auth.activation_code).not_to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -19,26 +19,26 @@ describe 'when being unsuspended' do
|
|||
it 'should be able to be unsuspended' do
|
||||
auth.activate!
|
||||
auth.suspend!
|
||||
auth.may_unsuspend?.should be_true
|
||||
expect(auth.may_unsuspend?).to be_true
|
||||
end
|
||||
|
||||
it 'should not be able to be unsuspended into active' do
|
||||
auth.suspend!
|
||||
auth.may_unsuspend?(:active).should_not be_true
|
||||
expect(auth.may_unsuspend?(:active)).not_to be_true
|
||||
end
|
||||
|
||||
it 'should be able to be unsuspended into active if polite' do
|
||||
auth.suspend!
|
||||
auth.may_wait?(:waiting, :please).should be_true
|
||||
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!
|
||||
auth.may_wait?(:waiting).should_not be_true
|
||||
auth.may_wait?(:waiting, :rude).should_not be_true
|
||||
lambda {auth.wait!(nil, :rude)}.should raise_error(AASM::InvalidTransition)
|
||||
lambda {auth.wait!}.should raise_error(AASM::InvalidTransition)
|
||||
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
|
||||
|
@ -46,8 +46,8 @@ describe 'when being unsuspended' do
|
|||
auth.suspend!
|
||||
auth.unsuspend!
|
||||
|
||||
auth.may_unpassify?.should_not be_true
|
||||
lambda {auth.unpassify!}.should raise_error(AASM::InvalidTransition)
|
||||
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
|
||||
|
@ -55,14 +55,14 @@ describe 'when being unsuspended' do
|
|||
auth.suspend!
|
||||
auth.unsuspend!
|
||||
|
||||
auth.aasm.current_state.should == :active
|
||||
expect(auth.aasm.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!
|
||||
|
||||
auth.aasm.current_state.should == :pending
|
||||
expect(auth.aasm.current_state).to eq(:pending)
|
||||
end
|
||||
|
||||
it 'should be passive if not previously activated and there is no activation code' do
|
||||
|
@ -70,6 +70,6 @@ describe 'when being unsuspended' do
|
|||
auth.suspend!
|
||||
auth.unsuspend!
|
||||
|
||||
auth.aasm.current_state.should == :passive
|
||||
expect(auth.aasm.current_state).to eq(:passive)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,27 +10,27 @@ describe 'adding an event' do
|
|||
end
|
||||
|
||||
it 'should set the name' do
|
||||
event.name.should == :close_order
|
||||
expect(event.name).to eq(:close_order)
|
||||
end
|
||||
|
||||
it 'should set the success callback' do
|
||||
event.options[:success].should == :success_callback
|
||||
expect(event.options[:success]).to eq(:success_callback)
|
||||
end
|
||||
|
||||
it 'should set the after callback' do
|
||||
event.options[:after].should == [:after_callback]
|
||||
expect(event.options[:after]).to eq([:after_callback])
|
||||
end
|
||||
|
||||
it 'should set the before callback' do
|
||||
event.options[:before].should == [:before_callback]
|
||||
expect(event.options[:before]).to eq([:before_callback])
|
||||
end
|
||||
|
||||
it 'should create transitions' do
|
||||
transitions = event.transitions
|
||||
transitions[0].from.should == :open
|
||||
transitions[0].to.should == :closed
|
||||
transitions[1].from.should == :received
|
||||
transitions[1].to.should == :closed
|
||||
expect(transitions[0].from).to eq(:open)
|
||||
expect(transitions[0].to).to eq(:closed)
|
||||
expect(transitions[1].from).to eq(:received)
|
||||
expect(transitions[1].to).to eq(:closed)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -42,19 +42,19 @@ describe 'transition inspection' do
|
|||
end
|
||||
|
||||
it 'should support inspecting transitions from other states' do
|
||||
event.transitions_from_state(:sleeping).map(&:to).should == [:running]
|
||||
event.transitions_from_state?(:sleeping).should be_true
|
||||
expect(event.transitions_from_state(:sleeping).map(&:to)).to eq([:running])
|
||||
expect(event.transitions_from_state?(:sleeping)).to be_true
|
||||
|
||||
event.transitions_from_state(:cleaning).map(&:to).should == []
|
||||
event.transitions_from_state?(:cleaning).should be_false
|
||||
expect(event.transitions_from_state(:cleaning).map(&:to)).to eq([])
|
||||
expect(event.transitions_from_state?(:cleaning)).to be_false
|
||||
end
|
||||
|
||||
it 'should support inspecting transitions to other states' do
|
||||
event.transitions_to_state(:running).map(&:from).should == [:sleeping]
|
||||
event.transitions_to_state?(:running).should be_true
|
||||
expect(event.transitions_to_state(:running).map(&:from)).to eq([:sleeping])
|
||||
expect(event.transitions_to_state?(:running)).to be_true
|
||||
|
||||
event.transitions_to_state(:cleaning).map(&:to).should == []
|
||||
event.transitions_to_state?(:cleaning).should be_false
|
||||
expect(event.transitions_to_state(:cleaning).map(&:to)).to eq([])
|
||||
expect(event.transitions_to_state?(:cleaning)).to be_false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,7 +63,7 @@ describe 'firing an event' do
|
|||
obj = double('object', :aasm => double('aasm', :current_state => 'open'))
|
||||
|
||||
event = AASM::Event.new(:event)
|
||||
event.fire(obj).should be_nil
|
||||
expect(event.fire(obj)).to be_nil
|
||||
end
|
||||
|
||||
it 'should return the state of the first matching transition it finds' do
|
||||
|
@ -73,7 +73,7 @@ describe 'firing an event' do
|
|||
|
||||
obj = double('object', :aasm => double('aasm', :current_state => :open))
|
||||
|
||||
event.fire(obj).should == :closed
|
||||
expect(event.fire(obj)).to eq(:closed)
|
||||
end
|
||||
|
||||
it 'should call the guard with the params passed in' do
|
||||
|
@ -82,9 +82,9 @@ describe 'firing an event' do
|
|||
end
|
||||
|
||||
obj = double('object', :aasm => double('aasm', :current_state => :open))
|
||||
obj.should_receive(:guard_fn).with('arg1', 'arg2').and_return(true)
|
||||
expect(obj).to receive(:guard_fn).with('arg1', 'arg2').and_return(true)
|
||||
|
||||
event.fire(obj, nil, 'arg1', 'arg2').should == :closed
|
||||
expect(event.fire(obj, nil, 'arg1', 'arg2')).to eq(:closed)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -101,7 +101,7 @@ describe 'should fire callbacks' do
|
|||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:symbol_success_callback)
|
||||
expect(model).to receive(:symbol_success_callback)
|
||||
model.with_symbol!
|
||||
end
|
||||
|
||||
|
@ -115,7 +115,7 @@ describe 'should fire callbacks' do
|
|||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:string_success_callback)
|
||||
expect(model).to receive(:string_success_callback)
|
||||
model.with_string!
|
||||
end
|
||||
|
||||
|
@ -129,8 +129,8 @@ describe 'should fire callbacks' do
|
|||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:success_callback1)
|
||||
model.should_receive(:success_callback2)
|
||||
expect(model).to receive(:success_callback1)
|
||||
expect(model).to receive(:success_callback2)
|
||||
model.with_array!
|
||||
end
|
||||
|
||||
|
@ -144,9 +144,9 @@ describe 'should fire callbacks' do
|
|||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:success_callback1)
|
||||
model.should_receive(:success_callback2)
|
||||
model.should_receive(:proc_success_callback)
|
||||
expect(model).to receive(:success_callback1)
|
||||
expect(model).to receive(:success_callback2)
|
||||
expect(model).to receive(:proc_success_callback)
|
||||
model.with_array_including_procs!
|
||||
end
|
||||
|
||||
|
@ -160,7 +160,7 @@ describe 'should fire callbacks' do
|
|||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:proc_success_callback)
|
||||
expect(model).to receive(:proc_success_callback)
|
||||
model.with_proc!
|
||||
end
|
||||
end
|
||||
|
@ -182,9 +182,9 @@ describe 'should fire callbacks' do
|
|||
end
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:do_one_thing_after).once.ordered
|
||||
model.should_receive(:do_another_thing_after_too).once.ordered
|
||||
model.should_receive(:do_third_thing_at_last).once.ordered
|
||||
expect(model).to receive(:do_one_thing_after).once.ordered
|
||||
expect(model).to receive(:do_another_thing_after_too).once.ordered
|
||||
expect(model).to receive(:do_third_thing_at_last).once.ordered
|
||||
model.with_afters!
|
||||
end
|
||||
end
|
||||
|
@ -203,7 +203,7 @@ describe 'should fire callbacks' do
|
|||
end
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:do_something_before).once
|
||||
expect(model).to receive(:do_something_before).once
|
||||
model.before_as_proc!
|
||||
end
|
||||
end
|
||||
|
@ -221,8 +221,8 @@ describe 'should fire callbacks' do
|
|||
end
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:do_something_before).once.ordered
|
||||
model.should_receive(:do_something_after).once.ordered
|
||||
expect(model).to receive(:do_something_before).once.ordered
|
||||
expect(model).to receive(:do_something_after).once.ordered
|
||||
model.in_right_order!
|
||||
end
|
||||
end
|
||||
|
@ -232,40 +232,40 @@ describe 'parametrised events' do
|
|||
|
||||
it 'should transition to specified next state (sleeping to showering)' do
|
||||
pe.wakeup!(:showering)
|
||||
pe.aasm.current_state.should == :showering
|
||||
expect(pe.aasm.current_state).to eq(:showering)
|
||||
end
|
||||
|
||||
it 'should transition to specified next state (sleeping to working)' do
|
||||
pe.wakeup!(:working)
|
||||
pe.aasm.current_state.should == :working
|
||||
expect(pe.aasm.current_state).to eq(:working)
|
||||
end
|
||||
|
||||
it 'should transition to default (first or showering) state' do
|
||||
pe.wakeup!
|
||||
pe.aasm.current_state.should == :showering
|
||||
expect(pe.aasm.current_state).to eq(:showering)
|
||||
end
|
||||
|
||||
it 'should transition to default state when on_transition invoked' do
|
||||
pe.dress!(nil, 'purple', 'dressy')
|
||||
pe.aasm.current_state.should == :working
|
||||
expect(pe.aasm.current_state).to eq(:working)
|
||||
end
|
||||
|
||||
it 'should call on_transition method with args' do
|
||||
pe.wakeup!(:showering)
|
||||
pe.should_receive(:wear_clothes).with('blue', 'jeans')
|
||||
expect(pe).to receive(:wear_clothes).with('blue', 'jeans')
|
||||
pe.dress!(:working, 'blue', 'jeans')
|
||||
end
|
||||
|
||||
it 'should call on_transition proc' do
|
||||
pe.wakeup!(:showering)
|
||||
pe.should_receive(:wear_clothes).with('purple', 'slacks')
|
||||
expect(pe).to receive(:wear_clothes).with('purple', 'slacks')
|
||||
pe.dress!(:dating, 'purple', 'slacks')
|
||||
end
|
||||
|
||||
it 'should call on_transition with an array of methods' do
|
||||
pe.wakeup!(:showering)
|
||||
pe.should_receive(:condition_hair)
|
||||
pe.should_receive(:fix_hair)
|
||||
expect(pe).to receive(:condition_hair)
|
||||
expect(pe).to receive(:fix_hair)
|
||||
pe.dress!(:prettying_up)
|
||||
end
|
||||
end
|
||||
|
@ -274,9 +274,9 @@ 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
|
||||
foo.should be_open
|
||||
expect(foo).to be_open
|
||||
|
||||
foo.should_receive(:aasm_write_state_without_persistence)
|
||||
expect(foo).to receive(:aasm_write_state_without_persistence)
|
||||
foo.close
|
||||
end
|
||||
end
|
||||
|
|
60
spec/unit/guard_spec.rb
Normal file
60
spec/unit/guard_spec.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "per-transition guards" do
|
||||
let(:guardian) { Guardian.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) { Guardian.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
|
|
@ -17,11 +17,11 @@ describe 'initial states' do
|
|||
let(:bar) {Bar.new}
|
||||
|
||||
it 'should use the first state defined if no initial state is given' do
|
||||
bar.aasm.current_state.should == :read
|
||||
expect(bar.aasm.current_state).to eq(:read)
|
||||
end
|
||||
|
||||
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
|
||||
expect(Banker.new(Banker::RICH - 1).aasm.current_state).to eq(:selling_bad_mortgages)
|
||||
expect(Banker.new(Banker::RICH + 1).aasm.current_state).to eq(:retired)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,16 +2,16 @@ require 'spec_helper'
|
|||
|
||||
describe 'inspection for common cases' do
|
||||
it 'should support the new DSL' do
|
||||
Foo.aasm.should respond_to(:states)
|
||||
Foo.aasm.states.should include(:open)
|
||||
Foo.aasm.states.should include(:closed)
|
||||
expect(Foo.aasm).to respond_to(:states)
|
||||
expect(Foo.aasm.states).to include(:open)
|
||||
expect(Foo.aasm.states).to include(:closed)
|
||||
|
||||
Foo.aasm.should respond_to(:initial_state)
|
||||
Foo.aasm.initial_state.should == :open
|
||||
expect(Foo.aasm).to respond_to(:initial_state)
|
||||
expect(Foo.aasm.initial_state).to eq(:open)
|
||||
|
||||
Foo.aasm.should respond_to(:events)
|
||||
Foo.aasm.events.should include(:close)
|
||||
Foo.aasm.events.should include(:null)
|
||||
expect(Foo.aasm).to respond_to(:events)
|
||||
expect(Foo.aasm.events).to include(:close)
|
||||
expect(Foo.aasm.events).to include(:null)
|
||||
end
|
||||
|
||||
context "instance level inspection" do
|
||||
|
@ -20,77 +20,77 @@ describe 'inspection for common cases' do
|
|||
|
||||
it "delivers all states" do
|
||||
states = foo.aasm.states
|
||||
states.should include(:open)
|
||||
states.should include(:closed)
|
||||
expect(states).to include(:open)
|
||||
expect(states).to include(:closed)
|
||||
|
||||
states = foo.aasm.states(:permissible => true)
|
||||
states.should include(:closed)
|
||||
states.should_not include(:open)
|
||||
expect(states).to include(:closed)
|
||||
expect(states).not_to include(:open)
|
||||
|
||||
foo.close
|
||||
foo.aasm.states(:permissible => true).should be_empty
|
||||
expect(foo.aasm.states(:permissible => true)).to be_empty
|
||||
end
|
||||
|
||||
it "delivers all states for subclasses" do
|
||||
states = two.aasm.states
|
||||
states.should include(:open)
|
||||
states.should include(:closed)
|
||||
states.should include(:foo)
|
||||
expect(states).to include(:open)
|
||||
expect(states).to include(:closed)
|
||||
expect(states).to include(:foo)
|
||||
|
||||
states = two.aasm.states(:permissible => true)
|
||||
states.should include(:closed)
|
||||
states.should_not include(:open)
|
||||
expect(states).to include(:closed)
|
||||
expect(states).not_to include(:open)
|
||||
|
||||
two.close
|
||||
two.aasm.states(:permissible => true).should be_empty
|
||||
expect(two.aasm.states(:permissible => true)).to be_empty
|
||||
end
|
||||
|
||||
it "delivers all events" do
|
||||
events = foo.aasm.events
|
||||
events.should include(:close)
|
||||
events.should include(:null)
|
||||
expect(events).to include(:close)
|
||||
expect(events).to include(:null)
|
||||
foo.close
|
||||
foo.aasm.events.should be_empty
|
||||
expect(foo.aasm.events).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
it 'should list states in the order they have been defined' do
|
||||
Conversation.aasm.states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk]
|
||||
expect(Conversation.aasm.states).to eq([:needs_attention, :read, :closed, :awaiting_response, :junk])
|
||||
end
|
||||
end
|
||||
|
||||
describe "special cases" do
|
||||
it "should support valid a state name" do
|
||||
Argument.aasm.states.should include(:invalid)
|
||||
Argument.aasm.states.should include(:valid)
|
||||
expect(Argument.aasm.states).to include(:invalid)
|
||||
expect(Argument.aasm.states).to include(:valid)
|
||||
|
||||
argument = Argument.new
|
||||
argument.invalid?.should be_true
|
||||
argument.aasm.current_state.should == :invalid
|
||||
expect(argument.invalid?).to be_true
|
||||
expect(argument.aasm.current_state).to eq(:invalid)
|
||||
|
||||
argument.valid!
|
||||
argument.valid?.should be_true
|
||||
argument.aasm.current_state.should == :valid
|
||||
expect(argument.valid?).to be_true
|
||||
expect(argument.aasm.current_state).to eq(:valid)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'aasm.states_for_select' do
|
||||
it "should return a select friendly array of states" do
|
||||
Foo.aasm.should respond_to(:states_for_select)
|
||||
Foo.aasm.states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
|
||||
expect(Foo.aasm).to respond_to(:states_for_select)
|
||||
expect(Foo.aasm.states_for_select).to eq([['Open', 'open'], ['Closed', 'closed']])
|
||||
end
|
||||
end
|
||||
|
||||
describe 'aasm.from_states_for_state' do
|
||||
it "should return all from states for a state" do
|
||||
AuthMachine.aasm.should respond_to(:from_states_for_state)
|
||||
expect(AuthMachine.aasm).to respond_to(:from_states_for_state)
|
||||
froms = AuthMachine.aasm.from_states_for_state(:active)
|
||||
[:pending, :passive, :suspended].each {|from| froms.should include(from)}
|
||||
[: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 = AuthMachine.aasm.from_states_for_state(:active, :transition => :unsuspend)
|
||||
[:suspended].each {|from| froms.should include(from)}
|
||||
[:suspended].each {|from| expect(froms).to include(from)}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,7 +98,7 @@ describe 'permissible events' do
|
|||
let(:foo) {Foo.new}
|
||||
|
||||
it 'work' do
|
||||
foo.aasm.permissible_events.should include(:close)
|
||||
foo.aasm.permissible_events.should_not include(:null)
|
||||
expect(foo.aasm.permissible_events).to include(:close)
|
||||
expect(foo.aasm.permissible_events).not_to include(:null)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,14 +31,14 @@ describe 'localized state names' do
|
|||
|
||||
it 'should localize' do
|
||||
state = LocalizerTestModel.aasm.states.detect {|s| s == :opened}
|
||||
state.localized_name.should == "It's open now!"
|
||||
state.human_name.should == "It's open now!"
|
||||
expect(state.localized_name).to eq("It's open now!")
|
||||
expect(state.human_name).to eq("It's open now!")
|
||||
end
|
||||
|
||||
it 'should use fallback' do
|
||||
state = LocalizerTestModel.aasm.states.detect {|s| s == :closed}
|
||||
state.localized_name.should == 'Closed'
|
||||
state.human_name.should == 'Closed'
|
||||
expect(state.localized_name).to eq('Closed')
|
||||
expect(state.human_name).to eq('Closed')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -58,21 +58,21 @@ describe AASM::Localizer, "new style" do
|
|||
|
||||
context 'aasm.human_state' do
|
||||
it 'should return translated state value' do
|
||||
foo_opened.aasm.human_state.should == "It's open now!"
|
||||
expect(foo_opened.aasm.human_state).to eq("It's open now!")
|
||||
end
|
||||
|
||||
it 'should return humanized value if not localized' do
|
||||
foo_closed.aasm.human_state.should == "Closed"
|
||||
expect(foo_closed.aasm.human_state).to eq("Closed")
|
||||
end
|
||||
end
|
||||
|
||||
context 'aasm_human_event_name' do
|
||||
it 'should return translated event name' do
|
||||
LocalizerTestModel.aasm_human_event_name(:close).should == "Let's close it!"
|
||||
expect(LocalizerTestModel.aasm_human_event_name(:close)).to eq("Let's close it!")
|
||||
end
|
||||
|
||||
it 'should return humanized event name' do
|
||||
LocalizerTestModel.aasm_human_event_name(:open).should == "Open"
|
||||
expect(LocalizerTestModel.aasm_human_event_name(:open)).to eq("Open")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -93,21 +93,21 @@ describe AASM::Localizer, "deprecated style" do
|
|||
|
||||
context 'aasm.human_state' do
|
||||
it 'should return translated state value' do
|
||||
foo_opened.aasm.human_state.should == "It's open now!"
|
||||
expect(foo_opened.aasm.human_state).to eq("It's open now!")
|
||||
end
|
||||
|
||||
it 'should return humanized value if not localized' do
|
||||
foo_closed.aasm.human_state.should == "Closed"
|
||||
expect(foo_closed.aasm.human_state).to eq("Closed")
|
||||
end
|
||||
end
|
||||
|
||||
context 'aasm_human_event_name' do
|
||||
it 'should return translated event name' do
|
||||
LocalizerTestModel.aasm_human_event_name(:close).should == "Let's close it!"
|
||||
expect(LocalizerTestModel.aasm_human_event_name(:close)).to eq("Let's close it!")
|
||||
end
|
||||
|
||||
it 'should return humanized event name' do
|
||||
LocalizerTestModel.aasm_human_event_name(:open).should == "Open"
|
||||
expect(LocalizerTestModel.aasm_human_event_name(:open)).to eq("Open")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,8 +5,8 @@ describe "the new dsl" do
|
|||
let(:process) {ProcessWithNewDsl.new}
|
||||
|
||||
it 'should not conflict with other event or state methods' do
|
||||
lambda {ProcessWithNewDsl.state}.should raise_error(RuntimeError, "wrong state method")
|
||||
lambda {ProcessWithNewDsl.event}.should raise_error(RuntimeError, "wrong event method")
|
||||
expect {ProcessWithNewDsl.state}.to raise_error(RuntimeError, "wrong state method")
|
||||
expect {ProcessWithNewDsl.event}.to raise_error(RuntimeError, "wrong event method")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -9,8 +9,8 @@ load_schema
|
|||
|
||||
shared_examples_for "aasm model" do
|
||||
it "should include persistence mixins" do
|
||||
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence)
|
||||
klass.included_modules.should be_include(AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
||||
expect(klass.included_modules).to be_include(AASM::Persistence::ActiveRecordPersistence)
|
||||
expect(klass.included_modules).to be_include(AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -18,45 +18,45 @@ describe "instance methods" do
|
|||
let(:gate) {Gate.new}
|
||||
|
||||
it "should respond to aasm persistence methods" do
|
||||
gate.should respond_to(:aasm_read_state)
|
||||
gate.should respond_to(:aasm_write_state)
|
||||
gate.should respond_to(:aasm_write_state_without_persistence)
|
||||
expect(gate).to respond_to(:aasm_read_state)
|
||||
expect(gate).to respond_to(:aasm_write_state)
|
||||
expect(gate).to respond_to(:aasm_write_state_without_persistence)
|
||||
end
|
||||
|
||||
it "should return the initial state when new and the aasm field is nil" do
|
||||
gate.aasm.current_state.should == :opened
|
||||
expect(gate.aasm.current_state).to eq(:opened)
|
||||
end
|
||||
|
||||
it "should return the aasm column when new and the aasm field is not nil" do
|
||||
gate.aasm_state = "closed"
|
||||
gate.aasm.current_state.should == :closed
|
||||
expect(gate.aasm.current_state).to eq(:closed)
|
||||
end
|
||||
|
||||
it "should return the aasm column when not new and the aasm_column is not nil" do
|
||||
gate.stub(:new_record?).and_return(false)
|
||||
allow(gate).to receive(:new_record?).and_return(false)
|
||||
gate.aasm_state = "state"
|
||||
gate.aasm.current_state.should == :state
|
||||
expect(gate.aasm.current_state).to eq(:state)
|
||||
end
|
||||
|
||||
it "should allow a nil state" do
|
||||
gate.stub(:new_record?).and_return(false)
|
||||
allow(gate).to receive(:new_record?).and_return(false)
|
||||
gate.aasm_state = nil
|
||||
gate.aasm.current_state.should be_nil
|
||||
expect(gate.aasm.current_state).to be_nil
|
||||
end
|
||||
|
||||
it "should call aasm_ensure_initial_state on validation before create" do
|
||||
gate.should_receive(:aasm_ensure_initial_state).and_return(true)
|
||||
expect(gate).to receive(:aasm_ensure_initial_state).and_return(true)
|
||||
gate.valid?
|
||||
end
|
||||
|
||||
it "should call aasm_ensure_initial_state before create, even if skipping validations" do
|
||||
gate.should_receive(:aasm_ensure_initial_state).and_return(true)
|
||||
expect(gate).to receive(:aasm_ensure_initial_state).and_return(true)
|
||||
gate.save(:validate => false)
|
||||
end
|
||||
|
||||
it "should not call aasm_ensure_initial_state on validation before update" do
|
||||
gate.stub(:new_record?).and_return(false)
|
||||
gate.should_not_receive(:aasm_ensure_initial_state)
|
||||
allow(gate).to receive(:new_record?).and_return(false)
|
||||
expect(gate).not_to receive(:aasm_ensure_initial_state)
|
||||
gate.valid?
|
||||
end
|
||||
|
||||
|
@ -64,36 +64,36 @@ end
|
|||
|
||||
describe 'subclasses' do
|
||||
it "should have the same states as its parent class" do
|
||||
DerivateNewDsl.aasm.states.should == SimpleNewDsl.aasm.states
|
||||
expect(DerivateNewDsl.aasm.states).to eq(SimpleNewDsl.aasm.states)
|
||||
end
|
||||
|
||||
it "should have the same events as its parent class" do
|
||||
DerivateNewDsl.aasm.events.should == SimpleNewDsl.aasm.events
|
||||
expect(DerivateNewDsl.aasm.events).to eq(SimpleNewDsl.aasm.events)
|
||||
end
|
||||
|
||||
it "should have the same column as its parent even for the new dsl" do
|
||||
SimpleNewDsl.aasm_column.should == :status
|
||||
DerivateNewDsl.aasm_column.should == :status
|
||||
expect(SimpleNewDsl.aasm_column).to eq(:status)
|
||||
expect(DerivateNewDsl.aasm_column).to eq(:status)
|
||||
end
|
||||
end
|
||||
|
||||
describe "named scopes with the new DSL" do
|
||||
context "Does not already respond_to? the scope name" do
|
||||
it "should add a scope" do
|
||||
SimpleNewDsl.should respond_to(:unknown_scope)
|
||||
SimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation).should be_true
|
||||
expect(SimpleNewDsl).to respond_to(:unknown_scope)
|
||||
expect(SimpleNewDsl.unknown_scope.is_a?(ActiveRecord::Relation)).to be_true
|
||||
end
|
||||
end
|
||||
|
||||
context "Already respond_to? the scope name" do
|
||||
it "should not add a scope" do
|
||||
SimpleNewDsl.should respond_to(:new)
|
||||
SimpleNewDsl.new.class.should == SimpleNewDsl
|
||||
expect(SimpleNewDsl).to respond_to(:new)
|
||||
expect(SimpleNewDsl.new.class).to eq(SimpleNewDsl)
|
||||
end
|
||||
end
|
||||
|
||||
it "does not create scopes if requested" do
|
||||
NoScope.should_not respond_to(:ignored_scope)
|
||||
expect(NoScope).not_to respond_to(:ignored_scope)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -101,8 +101,8 @@ end
|
|||
describe 'initial states' do
|
||||
|
||||
it 'should support conditions' do
|
||||
Thief.new(:skilled => true).aasm.current_state.should == :rich
|
||||
Thief.new(:skilled => false).aasm.current_state.should == :jailed
|
||||
expect(Thief.new(:skilled => true).aasm.current_state).to eq(:rich)
|
||||
expect(Thief.new(:skilled => false).aasm.current_state).to eq(:jailed)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -110,54 +110,54 @@ describe 'transitions with persistence' do
|
|||
|
||||
it "should work for valid models" do
|
||||
valid_object = Validator.create(:name => 'name')
|
||||
valid_object.should be_sleeping
|
||||
expect(valid_object).to be_sleeping
|
||||
valid_object.status = :running
|
||||
valid_object.should be_running
|
||||
expect(valid_object).to be_running
|
||||
end
|
||||
|
||||
it 'should not store states for invalid models' do
|
||||
validator = Validator.create(:name => 'name')
|
||||
validator.should be_valid
|
||||
validator.should be_sleeping
|
||||
expect(validator).to be_valid
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = nil
|
||||
validator.should_not be_valid
|
||||
validator.run!.should be_false
|
||||
validator.should be_sleeping
|
||||
expect(validator).not_to be_valid
|
||||
expect(validator.run!).to be_false
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.reload
|
||||
validator.should_not be_running
|
||||
validator.should be_sleeping
|
||||
expect(validator).not_to be_running
|
||||
expect(validator).to be_sleeping
|
||||
|
||||
validator.name = 'another name'
|
||||
validator.should be_valid
|
||||
validator.run!.should be_true
|
||||
validator.should be_running
|
||||
expect(validator).to be_valid
|
||||
expect(validator.run!).to be_true
|
||||
expect(validator).to be_running
|
||||
|
||||
validator.reload
|
||||
validator.should be_running
|
||||
validator.should_not be_sleeping
|
||||
expect(validator).to be_running
|
||||
expect(validator).not_to be_sleeping
|
||||
end
|
||||
|
||||
it 'should store states for invalid models if configured' do
|
||||
persistor = InvalidPersistor.create(:name => 'name')
|
||||
persistor.should be_valid
|
||||
persistor.should be_sleeping
|
||||
expect(persistor).to be_valid
|
||||
expect(persistor).to be_sleeping
|
||||
|
||||
persistor.name = nil
|
||||
persistor.should_not be_valid
|
||||
persistor.run!.should be_true
|
||||
persistor.should be_running
|
||||
expect(persistor).not_to be_valid
|
||||
expect(persistor.run!).to be_true
|
||||
expect(persistor).to be_running
|
||||
|
||||
persistor = InvalidPersistor.find(persistor.id)
|
||||
persistor.valid?
|
||||
persistor.should be_valid
|
||||
persistor.should be_running
|
||||
persistor.should_not be_sleeping
|
||||
expect(persistor).to be_valid
|
||||
expect(persistor).to be_running
|
||||
expect(persistor).not_to be_sleeping
|
||||
|
||||
persistor.reload
|
||||
persistor.should be_running
|
||||
persistor.should_not be_sleeping
|
||||
expect(persistor).to be_running
|
||||
expect(persistor).not_to be_sleeping
|
||||
end
|
||||
|
||||
describe 'transactions' do
|
||||
|
@ -165,39 +165,56 @@ describe 'transitions with persistence' do
|
|||
let(:transactor) { Transactor.create!(:name => 'transactor', :worker => worker) }
|
||||
|
||||
it 'should rollback all changes' do
|
||||
transactor.should be_sleeping
|
||||
worker.status.should == 'sleeping'
|
||||
expect(transactor).to be_sleeping
|
||||
expect(worker.status).to eq('sleeping')
|
||||
|
||||
lambda {transactor.run!}.should raise_error(StandardError, 'failed on purpose')
|
||||
transactor.should be_running
|
||||
worker.reload.status.should == 'sleeping'
|
||||
expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
|
||||
expect(transactor).to be_running
|
||||
expect(worker.reload.status).to eq('sleeping')
|
||||
end
|
||||
|
||||
it "should rollback all changes in nested transaction" do
|
||||
transactor.should be_sleeping
|
||||
worker.status.should == 'sleeping'
|
||||
context "nested transactions" do
|
||||
it "should rollback all changes in nested transaction" do
|
||||
expect(transactor).to be_sleeping
|
||||
expect(worker.status).to eq('sleeping')
|
||||
|
||||
Worker.transaction do
|
||||
lambda { transactor.run! }.should raise_error(StandardError, 'failed on purpose')
|
||||
Worker.transaction do
|
||||
expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
|
||||
end
|
||||
|
||||
expect(transactor).to be_running
|
||||
expect(worker.reload.status).to eq('sleeping')
|
||||
end
|
||||
|
||||
transactor.should be_running
|
||||
worker.reload.status.should == 'sleeping'
|
||||
it "should only rollback changes in the main transaction not the nested one" do
|
||||
# change configuration to not require new transaction
|
||||
AASM::StateMachine[Transactor].config.requires_new_transaction = false
|
||||
|
||||
expect(transactor).to be_sleeping
|
||||
expect(worker.status).to eq('sleeping')
|
||||
|
||||
Worker.transaction do
|
||||
expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
|
||||
end
|
||||
|
||||
expect(transactor).to be_running
|
||||
expect(worker.reload.status).to eq('running')
|
||||
end
|
||||
end
|
||||
|
||||
describe "after_commit callback" do
|
||||
it "should fire :after_commit if transaction was successful" do
|
||||
validator = Validator.create(:name => 'name')
|
||||
validator.should be_sleeping
|
||||
expect(validator).to be_sleeping
|
||||
validator.run!
|
||||
validator.should be_running
|
||||
validator.name.should_not == "name"
|
||||
expect(validator).to be_running
|
||||
expect(validator.name).not_to eq("name")
|
||||
end
|
||||
|
||||
it "should not fire :after_commit if transaction failed" do
|
||||
validator = Validator.create(:name => 'name')
|
||||
lambda { validator.fail! }.should raise_error(StandardError, 'failed on purpose')
|
||||
validator.name.should == "name"
|
||||
expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
|
||||
expect(validator.name).to eq("name")
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -209,20 +226,20 @@ describe "invalid states with persistence" do
|
|||
it "should not store states" do
|
||||
validator = Validator.create(:name => 'name')
|
||||
validator.status = 'invalid_state'
|
||||
validator.save.should be_false
|
||||
lambda {validator.save!}.should raise_error(ActiveRecord::RecordInvalid)
|
||||
expect(validator.save).to be_false
|
||||
expect {validator.save!}.to raise_error(ActiveRecord::RecordInvalid)
|
||||
|
||||
validator.reload
|
||||
validator.should be_sleeping
|
||||
expect(validator).to be_sleeping
|
||||
end
|
||||
|
||||
it "should store invalid states if configured" do
|
||||
persistor = InvalidPersistor.create(:name => 'name')
|
||||
persistor.status = 'invalid_state'
|
||||
persistor.save.should be_true
|
||||
expect(persistor.save).to be_true
|
||||
|
||||
persistor.reload
|
||||
persistor.status.should == 'invalid_state'
|
||||
expect(persistor.status).to eq('invalid_state')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -27,15 +27,15 @@ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version
|
|||
|
||||
context "Does not already respond_to? the scope name" do
|
||||
it "should add a scope" do
|
||||
SimpleMongoid.should respond_to(:unknown_scope)
|
||||
SimpleMongoid.unknown_scope.class.should == Mongoid::Criteria
|
||||
expect(SimpleMongoid).to respond_to(:unknown_scope)
|
||||
expect(SimpleMongoid.unknown_scope.class).to eq(Mongoid::Criteria)
|
||||
end
|
||||
end
|
||||
|
||||
context "Already respond_to? the scope name" do
|
||||
it "should not add a scope" do
|
||||
SimpleMongoid.should respond_to(:new)
|
||||
SimpleMongoid.new.class.should == SimpleMongoid
|
||||
expect(SimpleMongoid).to respond_to(:new)
|
||||
expect(SimpleMongoid.new.class).to eq(SimpleMongoid)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -45,20 +45,20 @@ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version
|
|||
|
||||
context "Does not already respond_to? the scope name" do
|
||||
it "should add a scope" do
|
||||
SimpleNewDslMongoid.should respond_to(:unknown_scope)
|
||||
SimpleNewDslMongoid.unknown_scope.class.should == Mongoid::Criteria
|
||||
expect(SimpleNewDslMongoid).to respond_to(:unknown_scope)
|
||||
expect(SimpleNewDslMongoid.unknown_scope.class).to eq(Mongoid::Criteria)
|
||||
end
|
||||
end
|
||||
|
||||
context "Already respond_to? the scope name" do
|
||||
it "should not add a scope" do
|
||||
SimpleNewDslMongoid.should respond_to(:new)
|
||||
SimpleNewDslMongoid.new.class.should == SimpleNewDslMongoid
|
||||
expect(SimpleNewDslMongoid).to respond_to(:new)
|
||||
expect(SimpleNewDslMongoid.new.class).to eq(SimpleNewDslMongoid)
|
||||
end
|
||||
end
|
||||
|
||||
it "does not create scopes if requested" do
|
||||
NoScopeMongoid.should_not respond_to(:ignored_scope)
|
||||
expect(NoScopeMongoid).not_to respond_to(:ignored_scope)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -69,12 +69,12 @@ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version
|
|||
let!(:model_id) { model._id }
|
||||
|
||||
it "should respond to method" do
|
||||
SimpleNewDslMongoid.should respond_to(:find_in_state)
|
||||
expect(SimpleNewDslMongoid).to respond_to(:find_in_state)
|
||||
end
|
||||
|
||||
it "should find the model when given the correct scope and model id" do
|
||||
SimpleNewDslMongoid.find_in_state(model_id, 'unknown_scope').class.should == SimpleNewDslMongoid
|
||||
SimpleNewDslMongoid.find_in_state(model_id, 'unknown_scope').should == model
|
||||
expect(SimpleNewDslMongoid.find_in_state(model_id, 'unknown_scope').class).to eq(SimpleNewDslMongoid)
|
||||
expect(SimpleNewDslMongoid.find_in_state(model_id, 'unknown_scope')).to eq(model)
|
||||
end
|
||||
|
||||
it "should raise DocumentNotFound error when given incorrect scope" do
|
||||
|
@ -94,17 +94,17 @@ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version
|
|||
end
|
||||
|
||||
it "should respond to method" do
|
||||
SimpleNewDslMongoid.should respond_to(:count_in_state)
|
||||
expect(SimpleNewDslMongoid).to respond_to(:count_in_state)
|
||||
end
|
||||
|
||||
it "should return n for a scope with n records persisted" do
|
||||
SimpleNewDslMongoid.count_in_state('unknown_scope').class.should == Fixnum
|
||||
SimpleNewDslMongoid.count_in_state('unknown_scope').should == 3
|
||||
expect(SimpleNewDslMongoid.count_in_state('unknown_scope').class).to eq(Fixnum)
|
||||
expect(SimpleNewDslMongoid.count_in_state('unknown_scope')).to eq(3)
|
||||
end
|
||||
|
||||
it "should return zero for a scope without records persisted" do
|
||||
SimpleNewDslMongoid.count_in_state('new').class.should == Fixnum
|
||||
SimpleNewDslMongoid.count_in_state('new').should == 0
|
||||
expect(SimpleNewDslMongoid.count_in_state('new').class).to eq(Fixnum)
|
||||
expect(SimpleNewDslMongoid.count_in_state('new')).to eq(0)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -117,16 +117,16 @@ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version
|
|||
end
|
||||
|
||||
it "should respond to method" do
|
||||
SimpleNewDslMongoid.should respond_to(:with_state_scope)
|
||||
expect(SimpleNewDslMongoid).to respond_to(:with_state_scope)
|
||||
end
|
||||
|
||||
it "should correctly process block" do
|
||||
SimpleNewDslMongoid.with_state_scope('unknown_scope') do
|
||||
expect(SimpleNewDslMongoid.with_state_scope('unknown_scope') do
|
||||
SimpleNewDslMongoid.count
|
||||
end.should == 3
|
||||
SimpleNewDslMongoid.with_state_scope('new') do
|
||||
end).to eq(3)
|
||||
expect(SimpleNewDslMongoid.with_state_scope('new') do
|
||||
SimpleNewDslMongoid.count
|
||||
end.should == 2
|
||||
end).to eq(2)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -136,12 +136,12 @@ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version
|
|||
let(:simple) {SimpleNewDslMongoid.new}
|
||||
|
||||
it "should call aasm_ensure_initial_state on validation before create" do
|
||||
simple.should_receive(:aasm_ensure_initial_state).and_return(true)
|
||||
expect(simple).to receive(:aasm_ensure_initial_state).and_return(true)
|
||||
simple.valid?
|
||||
end
|
||||
|
||||
it "should call aasm_ensure_initial_state before create, even if skipping validations" do
|
||||
simple.should_receive(:aasm_ensure_initial_state).and_return(true)
|
||||
expect(simple).to receive(:aasm_ensure_initial_state).and_return(true)
|
||||
simple.save(:validate => false)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,39 +20,39 @@ describe 'state machine' do
|
|||
let(:payment) {Payment.new}
|
||||
|
||||
it 'starts with an initial state' do
|
||||
payment.aasm.current_state.should == :initialised
|
||||
payment.should respond_to(:initialised?)
|
||||
payment.should be_initialised
|
||||
expect(payment.aasm.current_state).to eq(:initialised)
|
||||
expect(payment).to respond_to(:initialised?)
|
||||
expect(payment).to be_initialised
|
||||
end
|
||||
|
||||
it 'allows transitions to other states' do
|
||||
payment.should respond_to(:fill_out)
|
||||
payment.should respond_to(:fill_out!)
|
||||
expect(payment).to respond_to(:fill_out)
|
||||
expect(payment).to respond_to(:fill_out!)
|
||||
payment.fill_out!
|
||||
payment.should respond_to(:filled_out?)
|
||||
payment.should be_filled_out
|
||||
expect(payment).to respond_to(:filled_out?)
|
||||
expect(payment).to be_filled_out
|
||||
|
||||
payment.should respond_to(:authorise)
|
||||
payment.should respond_to(:authorise!)
|
||||
expect(payment).to respond_to(:authorise)
|
||||
expect(payment).to respond_to(:authorise!)
|
||||
payment.authorise
|
||||
payment.should respond_to(:authorised?)
|
||||
payment.should be_authorised
|
||||
expect(payment).to respond_to(:authorised?)
|
||||
expect(payment).to be_authorised
|
||||
end
|
||||
|
||||
it 'denies transitions to other states' do
|
||||
lambda {payment.authorise}.should raise_error(AASM::InvalidTransition)
|
||||
lambda {payment.authorise!}.should raise_error(AASM::InvalidTransition)
|
||||
expect {payment.authorise}.to raise_error(AASM::InvalidTransition)
|
||||
expect {payment.authorise!}.to raise_error(AASM::InvalidTransition)
|
||||
payment.fill_out
|
||||
lambda {payment.fill_out}.should raise_error(AASM::InvalidTransition)
|
||||
lambda {payment.fill_out!}.should raise_error(AASM::InvalidTransition)
|
||||
expect {payment.fill_out}.to raise_error(AASM::InvalidTransition)
|
||||
expect {payment.fill_out!}.to raise_error(AASM::InvalidTransition)
|
||||
payment.authorise
|
||||
lambda {payment.fill_out}.should raise_error(AASM::InvalidTransition)
|
||||
lambda {payment.fill_out!}.should raise_error(AASM::InvalidTransition)
|
||||
expect {payment.fill_out}.to raise_error(AASM::InvalidTransition)
|
||||
expect {payment.fill_out!}.to raise_error(AASM::InvalidTransition)
|
||||
end
|
||||
|
||||
it 'defines constants for each state name' do
|
||||
Payment::STATE_INITIALISED.should eq(:initialised)
|
||||
Payment::STATE_FILLED_OUT.should eq(:filled_out)
|
||||
Payment::STATE_AUTHORISED.should eq(:authorised)
|
||||
expect(Payment::STATE_INITIALISED).to eq(:initialised)
|
||||
expect(Payment::STATE_FILLED_OUT).to eq(:filled_out)
|
||||
expect(Payment::STATE_AUTHORISED).to eq(:authorised)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,34 +12,34 @@ describe AASM::State do
|
|||
|
||||
it 'should set the name' do
|
||||
state = new_state
|
||||
state.name.should == :astate
|
||||
expect(state.name).to eq(:astate)
|
||||
end
|
||||
|
||||
it 'should set the display_name from name' do
|
||||
new_state.display_name.should == 'Astate'
|
||||
expect(new_state.display_name).to eq('Astate')
|
||||
end
|
||||
|
||||
it 'should set the display_name from options' do
|
||||
new_state(:display => "A State").display_name.should == 'A State'
|
||||
expect(new_state(:display => "A State").display_name).to eq('A State')
|
||||
end
|
||||
|
||||
it 'should set the options and expose them as options' do
|
||||
new_state.options.should == @options
|
||||
expect(new_state.options).to eq(@options)
|
||||
end
|
||||
|
||||
it 'should be equal to a symbol of the same name' do
|
||||
new_state.should == :astate
|
||||
expect(new_state).to eq(:astate)
|
||||
end
|
||||
|
||||
it 'should be equal to a State of the same name' do
|
||||
new_state.should == new_state
|
||||
expect(new_state).to eq(new_state)
|
||||
end
|
||||
|
||||
it 'should send a message to the record for an action if the action is present as a symbol' do
|
||||
state = new_state(:entering => :foo)
|
||||
|
||||
record = double('record')
|
||||
record.should_receive(:foo)
|
||||
expect(record).to receive(:foo)
|
||||
|
||||
state.fire_callbacks(:entering, record)
|
||||
end
|
||||
|
@ -48,7 +48,7 @@ describe AASM::State do
|
|||
state = new_state(:entering => 'foo')
|
||||
|
||||
record = double('record')
|
||||
record.should_receive(:foo)
|
||||
expect(record).to receive(:foo)
|
||||
|
||||
state.fire_callbacks(:entering, record)
|
||||
end
|
||||
|
@ -57,10 +57,10 @@ describe AASM::State do
|
|||
state = new_state(:entering => [:a, :b, "c", lambda {|r| r.foobar }])
|
||||
|
||||
record = double('record')
|
||||
record.should_receive(:a)
|
||||
record.should_receive(:b)
|
||||
record.should_receive(:c)
|
||||
record.should_receive(:foobar)
|
||||
expect(record).to receive(:a)
|
||||
expect(record).to receive(:b)
|
||||
expect(record).to receive(:c)
|
||||
expect(record).to receive(:foobar)
|
||||
|
||||
state.fire_callbacks(:entering, record)
|
||||
end
|
||||
|
@ -69,9 +69,9 @@ describe AASM::State do
|
|||
state = new_state(:entering => [:a, :b, :c])
|
||||
|
||||
record = double('record')
|
||||
record.should_receive(:a)
|
||||
record.should_receive(:b).and_throw(:halt_aasm_chain)
|
||||
record.should_not_receive(:c)
|
||||
expect(record).to receive(:a)
|
||||
expect(record).to receive(:b).and_throw(:halt_aasm_chain)
|
||||
expect(record).not_to receive(:c)
|
||||
|
||||
state.fire_callbacks(:entering, record)
|
||||
end
|
||||
|
@ -80,7 +80,7 @@ describe AASM::State do
|
|||
state = new_state(:entering => Proc.new {|r| r.foobar})
|
||||
|
||||
record = double('record')
|
||||
record.should_receive(:foobar)
|
||||
expect(record).to receive(:foobar)
|
||||
|
||||
state.fire_callbacks(:entering, record)
|
||||
end
|
||||
|
|
|
@ -5,26 +5,26 @@ describe 'subclassing' do
|
|||
|
||||
it 'should have the parent states' do
|
||||
Foo.aasm.states.each do |state|
|
||||
FooTwo.aasm.states.should include(state)
|
||||
expect(FooTwo.aasm.states).to include(state)
|
||||
end
|
||||
Baz.aasm.states.should == Bar.aasm.states
|
||||
expect(Baz.aasm.states).to eq(Bar.aasm.states)
|
||||
end
|
||||
|
||||
it 'should not add the child states to the parent machine' do
|
||||
Foo.aasm.states.should_not include(:foo)
|
||||
expect(Foo.aasm.states).not_to include(:foo)
|
||||
end
|
||||
|
||||
it "should have the same events as its parent" do
|
||||
Baz.aasm.events.should == Bar.aasm.events
|
||||
expect(Baz.aasm.events).to eq(Bar.aasm.events)
|
||||
end
|
||||
|
||||
it 'should know how to respond to `may_add_details?`' do
|
||||
son.may_add_details?.should be_true
|
||||
expect(son.may_add_details?).to be_true
|
||||
end
|
||||
|
||||
it 'should not break if I call Son#update_state' do
|
||||
son.update_state
|
||||
son.aasm.current_state.should == :pending_details_confirmation
|
||||
expect(son.aasm.current_state).to eq(:pending_details_confirmation)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -4,46 +4,46 @@ describe 'transitions' do
|
|||
|
||||
it 'should raise an exception when whiny' do
|
||||
process = ProcessWithNewDsl.new
|
||||
lambda { process.stop! }.should raise_error(AASM::InvalidTransition)
|
||||
process.should be_sleeping
|
||||
expect { process.stop! }.to raise_error(AASM::InvalidTransition)
|
||||
expect(process).to be_sleeping
|
||||
end
|
||||
|
||||
it 'should not raise an exception when not whiny' do
|
||||
silencer = Silencer.new
|
||||
silencer.smile!.should be_false
|
||||
silencer.should be_silent
|
||||
expect(silencer.smile!).to be_false
|
||||
expect(silencer).to be_silent
|
||||
end
|
||||
|
||||
it 'should not raise an exception when superclass not whiny' do
|
||||
sub = SubClassing.new
|
||||
sub.smile!.should be_false
|
||||
sub.should be_silent
|
||||
expect(sub.smile!).to be_false
|
||||
expect(sub).to be_silent
|
||||
end
|
||||
|
||||
it 'should not raise an exception when from is nil even if whiny' do
|
||||
silencer = Silencer.new
|
||||
silencer.smile_any!.should be_true
|
||||
silencer.should be_smiling
|
||||
expect(silencer.smile_any!).to be_true
|
||||
expect(silencer).to be_smiling
|
||||
end
|
||||
|
||||
it 'should call the block when success' do
|
||||
silencer = Silencer.new
|
||||
success = false
|
||||
lambda {
|
||||
expect {
|
||||
silencer.smile_any! do
|
||||
success = true
|
||||
end
|
||||
}.should change { success }.to(true)
|
||||
}.to change { success }.to(true)
|
||||
end
|
||||
|
||||
it 'should not call the block when failure' do
|
||||
silencer = Silencer.new
|
||||
success = false
|
||||
lambda {
|
||||
expect {
|
||||
silencer.smile! do
|
||||
success = true
|
||||
end
|
||||
}.should_not change { success }.to(true)
|
||||
}.not_to change { success }.to(true)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -56,9 +56,9 @@ describe AASM::Transition do
|
|||
opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
|
||||
st = AASM::Transition.new(opts)
|
||||
|
||||
st.from.should == opts[:from]
|
||||
st.to.should == opts[:to]
|
||||
st.opts.should == opts
|
||||
expect(st.from).to eq(opts[:from])
|
||||
expect(st.to).to eq(opts[:to])
|
||||
expect(st.opts).to eq(opts)
|
||||
end
|
||||
|
||||
it 'should pass equality check if from and to are the same' do
|
||||
|
@ -66,10 +66,10 @@ describe AASM::Transition do
|
|||
st = AASM::Transition.new(opts)
|
||||
|
||||
obj = double('object')
|
||||
obj.stub(:from).and_return(opts[:from])
|
||||
obj.stub(:to).and_return(opts[:to])
|
||||
allow(obj).to receive(:from).and_return(opts[:from])
|
||||
allow(obj).to receive(:to).and_return(opts[:to])
|
||||
|
||||
st.should == obj
|
||||
expect(st).to eq(obj)
|
||||
end
|
||||
|
||||
it 'should fail equality check if from are not the same' do
|
||||
|
@ -77,10 +77,10 @@ describe AASM::Transition do
|
|||
st = AASM::Transition.new(opts)
|
||||
|
||||
obj = double('object')
|
||||
obj.stub(:from).and_return('blah')
|
||||
obj.stub(:to).and_return(opts[:to])
|
||||
allow(obj).to receive(:from).and_return('blah')
|
||||
allow(obj).to receive(:to).and_return(opts[:to])
|
||||
|
||||
st.should_not == obj
|
||||
expect(st).not_to eq(obj)
|
||||
end
|
||||
|
||||
it 'should fail equality check if to are not the same' do
|
||||
|
@ -88,10 +88,10 @@ describe AASM::Transition do
|
|||
st = AASM::Transition.new(opts)
|
||||
|
||||
obj = double('object')
|
||||
obj.stub(:from).and_return(opts[:from])
|
||||
obj.stub(:to).and_return('blah')
|
||||
allow(obj).to receive(:from).and_return(opts[:from])
|
||||
allow(obj).to receive(:to).and_return('blah')
|
||||
|
||||
st.should_not == obj
|
||||
expect(st).not_to eq(obj)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -100,7 +100,7 @@ describe AASM::Transition, '- when performing guard checks' do
|
|||
opts = {:from => 'foo', :to => 'bar'}
|
||||
st = AASM::Transition.new(opts)
|
||||
|
||||
st.perform(nil).should be_true
|
||||
expect(st.perform(nil)).to be_true
|
||||
end
|
||||
|
||||
it 'should call the method on the object if guard is a symbol' do
|
||||
|
@ -108,7 +108,7 @@ describe AASM::Transition, '- when performing guard checks' do
|
|||
st = AASM::Transition.new(opts)
|
||||
|
||||
obj = double('object')
|
||||
obj.should_receive(:test)
|
||||
expect(obj).to receive(:test)
|
||||
|
||||
st.perform(obj)
|
||||
end
|
||||
|
@ -118,7 +118,7 @@ describe AASM::Transition, '- when performing guard checks' do
|
|||
st = AASM::Transition.new(opts)
|
||||
|
||||
obj = double('object')
|
||||
obj.should_receive(:test)
|
||||
expect(obj).to receive(:test)
|
||||
|
||||
st.perform(obj)
|
||||
end
|
||||
|
@ -128,7 +128,7 @@ describe AASM::Transition, '- when performing guard checks' do
|
|||
st = AASM::Transition.new(opts)
|
||||
|
||||
obj = double('object')
|
||||
obj.should_receive(:test)
|
||||
expect(obj).to receive(:test)
|
||||
|
||||
st.perform(obj)
|
||||
end
|
||||
|
@ -139,9 +139,9 @@ describe AASM::Transition, '- when executing the transition with a Proc' do
|
|||
opts = {:from => 'foo', :to => 'bar', :on_transition => Proc.new {|o| o.test}}
|
||||
st = AASM::Transition.new(opts)
|
||||
args = {:arg1 => '1', :arg2 => '2'}
|
||||
obj = double('object')
|
||||
obj = double('object', :aasm => 'aasm')
|
||||
|
||||
opts[:on_transition].should_receive(:call).with(any_args)
|
||||
expect(opts[:on_transition]).to receive(:call).with(any_args)
|
||||
|
||||
st.execute(obj, args)
|
||||
end
|
||||
|
@ -150,9 +150,9 @@ describe AASM::Transition, '- when executing the transition with a Proc' do
|
|||
opts = {:from => 'foo', :to => 'bar', :on_transition => Proc.new {||}}
|
||||
st = AASM::Transition.new(opts)
|
||||
args = {:arg1 => '1', :arg2 => '2'}
|
||||
obj = double('object')
|
||||
obj = double('object', :aasm => 'aasm')
|
||||
|
||||
opts[:on_transition].should_receive(:call).with(no_args)
|
||||
expect(opts[:on_transition]).to receive(:call).with(no_args)
|
||||
|
||||
st.execute(obj, args)
|
||||
end
|
||||
|
@ -163,9 +163,9 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
|
|||
opts = {:from => 'foo', :to => 'bar', :on_transition => 'test'}
|
||||
st = AASM::Transition.new(opts)
|
||||
args = {:arg1 => '1', :arg2 => '2'}
|
||||
obj = double('object')
|
||||
obj = double('object', :aasm => 'aasm')
|
||||
|
||||
obj.should_receive(:test)
|
||||
expect(obj).to receive(:test)
|
||||
|
||||
st.execute(obj, args)
|
||||
end
|
||||
|
@ -174,9 +174,9 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
|
|||
opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
|
||||
st = AASM::Transition.new(opts)
|
||||
args = {:arg1 => '1', :arg2 => '2'}
|
||||
obj = double('object')
|
||||
obj = double('object', :aasm => 'aasm')
|
||||
|
||||
obj.should_receive(:test)
|
||||
expect(obj).to receive(:test)
|
||||
|
||||
st.execute(obj, args)
|
||||
end
|
||||
|
@ -185,7 +185,7 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
|
|||
opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
|
||||
st = AASM::Transition.new(opts)
|
||||
args = {:arg1 => '1', :arg2 => '2'}
|
||||
obj = double('object')
|
||||
obj = double('object', :aasm => 'aasm')
|
||||
|
||||
def obj.test(args)
|
||||
"arg1: #{args[:arg1]} arg2: #{args[:arg2]}"
|
||||
|
@ -193,14 +193,14 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
|
|||
|
||||
return_value = st.execute(obj, args)
|
||||
|
||||
return_value.should == 'arg1: 1 arg2: 2'
|
||||
expect(return_value).to eq('arg1: 1 arg2: 2')
|
||||
end
|
||||
|
||||
it 'should NOT pass args if the target method does NOT accept them' do
|
||||
opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
|
||||
st = AASM::Transition.new(opts)
|
||||
args = {:arg1 => '1', :arg2 => '2'}
|
||||
obj = double('object')
|
||||
obj = double('object', :aasm => 'aasm')
|
||||
|
||||
def obj.test
|
||||
'success'
|
||||
|
@ -208,7 +208,22 @@ describe AASM::Transition, '- when executing the transition with an :on_transtio
|
|||
|
||||
return_value = st.execute(obj, args)
|
||||
|
||||
return_value.should == 'success'
|
||||
expect(return_value).to eq('success')
|
||||
end
|
||||
|
||||
it 'should allow accessing the from_state and the to_state' do
|
||||
opts = {:from => 'foo', :to => 'bar', :on_transition => :test}
|
||||
st = AASM::Transition.new(opts)
|
||||
args = {:arg1 => '1', :arg2 => '2'}
|
||||
obj = double('object', :aasm => AASM::InstanceBase.new('object'))
|
||||
|
||||
def obj.test(args)
|
||||
"from: #{aasm.from_state} to: #{aasm.to_state}"
|
||||
end
|
||||
|
||||
return_value = st.execute(obj, args)
|
||||
|
||||
expect(return_value).to eq('from: foo to: bar')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue