Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
first tests for state machines with multiple state attributes
- Loading branch information
Showing
2 changed files
with
216 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
class ComplexMultipleExample | ||
include AASM | ||
|
||
attr_accessor :activation_code, :activated_at, :deleted_at | ||
|
||
aasm(:left) do | ||
state :passive | ||
state :pending, :initial => true, :before_enter => :make_activation_code | ||
state :active, :before_enter => :do_activate | ||
state :suspended | ||
state :deleted, :before_enter => :do_delete#, :exit => :do_undelete | ||
state :waiting | ||
|
||
event :register do | ||
transitions :from => :passive, :to => :pending do | ||
guard do | ||
can_register? | ||
end | ||
end | ||
end | ||
|
||
event :activate do | ||
transitions :from => :pending, :to => :active | ||
end | ||
|
||
event :suspend do | ||
transitions :from => [:passive, :pending, :active], :to => :suspended | ||
end | ||
|
||
event :delete do | ||
transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted | ||
end | ||
|
||
# a dummy event that can never happen | ||
event :unpassify do | ||
transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false } | ||
end | ||
|
||
event :unsuspend do | ||
transitions :from => :suspended, :to => :active, :guard => Proc.new { has_activated? } | ||
transitions :from => :suspended, :to => :pending, :guard => :has_activation_code? | ||
transitions :from => :suspended, :to => :passive | ||
end | ||
|
||
event :wait do | ||
transitions :from => :suspended, :to => :waiting, :guard => :if_polite? | ||
end | ||
end | ||
|
||
# aasm(:right) do | ||
# state :passive | ||
# state :pending, :initial => true, :before_enter => :make_activation_code | ||
# state :active, :before_enter => :do_activate | ||
# state :suspended | ||
# state :deleted, :before_enter => :do_delete#, :exit => :do_undelete | ||
# state :waiting | ||
|
||
# event :register do | ||
# transitions :from => :passive, :to => :pending do | ||
# guard do | ||
# can_register? | ||
# end | ||
# end | ||
# end | ||
|
||
# event :activate do | ||
# transitions :from => :pending, :to => :active | ||
# end | ||
|
||
# event :suspend do | ||
# transitions :from => [:passive, :pending, :active], :to => :suspended | ||
# end | ||
|
||
# event :delete do | ||
# transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted | ||
# end | ||
|
||
# # a dummy event that can never happen | ||
# event :unpassify do | ||
# transitions :from => :passive, :to => :active, :guard => Proc.new {|u| false } | ||
# end | ||
|
||
# event :unsuspend do | ||
# transitions :from => :suspended, :to => :active, :guard => Proc.new { has_activated? } | ||
# transitions :from => :suspended, :to => :pending, :guard => :has_activation_code? | ||
# transitions :from => :suspended, :to => :passive | ||
# end | ||
|
||
# event :wait do | ||
# transitions :from => :suspended, :to => :waiting, :guard => :if_polite? | ||
# end | ||
# end # right | ||
|
||
def initialize | ||
# the AR backend uses a before_validate_on_create :aasm_ensure_initial_state | ||
# lets do something similar here for testing purposes. | ||
aasm(:left).enter_initial_state | ||
end | ||
|
||
def make_activation_code | ||
@activation_code = 'moo' | ||
end | ||
|
||
def do_activate | ||
@activated_at = Time.now | ||
@activation_code = nil | ||
end | ||
|
||
def do_delete | ||
@deleted_at = Time.now | ||
end | ||
|
||
def do_undelete | ||
@deleted_at = false | ||
end | ||
|
||
def can_register? | ||
true | ||
end | ||
|
||
def has_activated? | ||
!!@activated_at | ||
end | ||
|
||
def has_activation_code? | ||
!!@activation_code | ||
end | ||
|
||
def if_polite?(phrase = nil) | ||
phrase == :please | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
require 'spec_helper' | ||
|
||
describe 'on initialization' do | ||
let(:auth) {ComplexMultipleExample.new} | ||
|
||
it 'should be in the pending state' do | ||
expect(auth.aasm(:left).current_state).to eq(:pending) | ||
end | ||
|
||
it 'should have an activation code' do | ||
expect(auth.has_activation_code?).to be_truthy | ||
expect(auth.activation_code).not_to be_nil | ||
end | ||
end | ||
|
||
describe 'when being unsuspended' do | ||
let(:auth) {ComplexMultipleExample.new} | ||
|
||
it 'should be able to be unsuspended' do | ||
auth.activate! | ||
auth.suspend! | ||
expect(auth.may_unsuspend?).to be true | ||
end | ||
|
||
it 'should not be able to be unsuspended into active' do | ||
auth.suspend! | ||
expect(auth.may_unsuspend?(:active)).not_to be true | ||
end | ||
|
||
it 'should be able to be unsuspended into active if polite' do | ||
auth.suspend! | ||
expect(auth.may_wait?(:waiting, :please)).to be true | ||
auth.wait!(nil, :please) | ||
end | ||
|
||
it 'should not be able to be unsuspended into active if not polite' do | ||
auth.suspend! | ||
expect(auth.may_wait?(:waiting)).not_to be true | ||
expect(auth.may_wait?(:waiting, :rude)).not_to be true | ||
expect {auth.wait!(nil, :rude)}.to raise_error(AASM::InvalidTransition) | ||
expect {auth.wait!}.to raise_error(AASM::InvalidTransition) | ||
end | ||
|
||
it 'should not be able to be unpassified' do | ||
auth.activate! | ||
auth.suspend! | ||
auth.unsuspend! | ||
|
||
expect(auth.may_unpassify?).not_to be true | ||
expect {auth.unpassify!}.to raise_error(AASM::InvalidTransition) | ||
end | ||
|
||
it 'should be active if previously activated' do | ||
auth.activate! | ||
auth.suspend! | ||
auth.unsuspend! | ||
|
||
expect(auth.aasm(:left).current_state).to eq(:active) | ||
end | ||
|
||
it 'should be pending if not previously activated, but an activation code is present' do | ||
auth.suspend! | ||
auth.unsuspend! | ||
|
||
expect(auth.aasm(:left).current_state).to eq(:pending) | ||
end | ||
|
||
it 'should be passive if not previously activated and there is no activation code' do | ||
auth.activation_code = nil | ||
auth.suspend! | ||
auth.unsuspend! | ||
|
||
expect(auth.aasm(:left).current_state).to eq(:passive) | ||
end | ||
|
||
it "should be able to fire known events" do | ||
expect(auth.aasm(:left).may_fire_event?(:activate)).to be true | ||
end | ||
|
||
it "should not be able to fire unknown events" do | ||
expect(auth.aasm(:left).may_fire_event?(:unknown)).to be false | ||
end | ||
|
||
end |