aasm 3.0.14 → 3.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'AuthMachine on initialization' do
3
+ describe 'on initialization' do
4
4
  let(:auth) {AuthMachine.new}
5
5
 
6
6
  it 'should be in the pending state' do
@@ -13,7 +13,7 @@ describe 'AuthMachine on initialization' do
13
13
  end
14
14
  end
15
15
 
16
- describe 'AuthMachine when being unsuspended' do
16
+ describe 'when being unsuspended' do
17
17
  let(:auth) {AuthMachine.new}
18
18
 
19
19
  it 'should be able to be unsuspended' do
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ class Banker
4
+ include AASM
5
+ aasm do
6
+ state :retired
7
+ state :selling_bad_mortgages
8
+ end
9
+ aasm_initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
10
+ RICH = 1_000_000
11
+ attr_accessor :balance
12
+ def initialize(balance = 0); self.balance = balance; end
13
+ def rich?; self.balance >= RICH; end
14
+ end
15
+
16
+ describe 'initial states' do
17
+ let(:bar) {Bar.new}
18
+
19
+ it 'should use the first state defined if no initial state is given' do
20
+ bar.aasm_current_state.should == :read
21
+ # bar.aasm.current_state.should == :read # not yet supported
22
+ end
23
+
24
+ it 'should determine initial state from the Proc results' do
25
+ Banker.new(Banker::RICH - 1).aasm_current_state.should == :selling_bad_mortgages
26
+ Banker.new(Banker::RICH + 1).aasm_current_state.should == :retired
27
+ end
28
+ end
@@ -1,7 +1,79 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'inspecting AASM' do
4
- it 'should support listing all states in the order they have been defined' do
5
- Conversation.aasm_states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk]
3
+ describe 'inspection for common cases' do
4
+ it 'should support the old DSL' do
5
+ Foo.should respond_to(:aasm_states)
6
+ Foo.aasm_states.should include(:open)
7
+ Foo.aasm_states.should include(:closed)
8
+
9
+ Foo.should respond_to(:aasm_initial_state)
10
+ Foo.aasm_initial_state.should == :open
11
+
12
+ Foo.should respond_to(:aasm_events)
13
+ Foo.aasm_events.should include(:close)
14
+ Foo.aasm_events.should include(:null)
15
+ end
16
+
17
+ it 'should support the new DSL' do
18
+ Foo.aasm.should respond_to(:states)
19
+ Foo.aasm.states.should include(:open)
20
+ Foo.aasm.states.should include(:closed)
21
+
22
+ Foo.aasm.should respond_to(:initial_state)
23
+ Foo.aasm.initial_state.should == :open
24
+
25
+ Foo.aasm.should respond_to(:events)
26
+ Foo.aasm.events.should include(:close)
27
+ Foo.aasm.events.should include(:null)
28
+ end
29
+
30
+ it 'should list states in the order they have been defined' do
31
+ Conversation.aasm.states.should == [:needs_attention, :read, :closed, :awaiting_response, :junk]
32
+ end
33
+ end
34
+
35
+ describe "special cases" do
36
+ it "should support valid a state name" do
37
+ Argument.aasm_states.should include(:invalid)
38
+ Argument.aasm_states.should include(:valid)
39
+
40
+ argument = Argument.new
41
+ argument.invalid?.should be_true
42
+ argument.aasm_current_state.should == :invalid
43
+
44
+ argument.valid!
45
+ argument.valid?.should be_true
46
+ argument.aasm_current_state.should == :valid
47
+ end
48
+ end
49
+
50
+ describe :aasm_states_for_select do
51
+ it "should return a select friendly array of states" do
52
+ Foo.should respond_to(:aasm_states_for_select)
53
+ Foo.aasm_states_for_select.should == [['Open', 'open'], ['Closed', 'closed']]
54
+ end
55
+ end
56
+
57
+ describe :aasm_from_states_for_state do
58
+ it "should return all from states for a state" do
59
+ AuthMachine.should respond_to(:aasm_from_states_for_state)
60
+ froms = AuthMachine.aasm_from_states_for_state(:active)
61
+ [:pending, :passive, :suspended].each {|from| froms.should include(from)}
62
+ end
63
+
64
+ it "should return from states for a state for a particular transition only" do
65
+ froms = AuthMachine.aasm_from_states_for_state(:active, :transition => :unsuspend)
66
+ [:suspended].each {|from| froms.should include(from)}
67
+ end
68
+ end
69
+
70
+ describe :aasm_events_for_current_state do
71
+ let(:foo) {Foo.new}
72
+
73
+ it 'work' do
74
+ foo.aasm_events_for_current_state.should include(:close)
75
+ foo.aasm_events_for_current_state.should include(:null)
76
+ foo.close
77
+ foo.aasm_events_for_current_state.should be_empty
6
78
  end
7
79
  end
@@ -1,34 +1,38 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ # require 'spec_helper'
2
2
 
3
- describe "state machines" do
3
+ # describe "state machines" do
4
4
 
5
- def number_of_objects(clazz)
6
- ObjectSpace.each_object(clazz) {}
7
- end
8
-
9
- def machines
10
- AASM::StateMachine.instance_variable_get("@machines")
11
- end
5
+ # def number_of_objects(clazz)
6
+ # ObjectSpace.each_object(clazz) {}
7
+ # end
12
8
 
13
- it "should be created without memory leak" do
14
- machines_count = machines.size
15
- state_count = number_of_objects(AASM::SupportingClasses::State)
16
- event_count = number_of_objects(AASM::SupportingClasses::Event)
17
- transition_count = number_of_objects(AASM::SupportingClasses::StateTransition)
9
+ # def machines
10
+ # AASM::StateMachine.instance_variable_get("@machines")
11
+ # end
18
12
 
19
- load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
20
- machines.size.should == machines_count + 1 # + Process
21
- number_of_objects(Models::Process).should == 0
22
- number_of_objects(AASM::SupportingClasses::State).should == state_count + 3 # + Process
23
- number_of_objects(AASM::SupportingClasses::Event).should == event_count + 2 # + Process
24
- number_of_objects(AASM::SupportingClasses::StateTransition).should == transition_count + 2 # + Process
13
+ # it "should be created without memory leak" do
14
+ # machines_count = machines.size
15
+ # state_count = number_of_objects(AASM::SupportingClasses::State)
16
+ # event_count = number_of_objects(AASM::SupportingClasses::Event)
17
+ # puts "event_count = #{event_count}"
18
+ # transition_count = number_of_objects(AASM::SupportingClasses::StateTransition)
25
19
 
26
- Models.send(:remove_const, "Process") if Models.const_defined?("Process")
27
- load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
28
- machines.size.should == machines_count + 1 # + Process
29
- number_of_objects(AASM::SupportingClasses::State).should == state_count + 3 # + Process
30
- number_of_objects(AASM::SupportingClasses::Event).should == event_count + 2 # + Process
31
- number_of_objects(AASM::SupportingClasses::StateTransition).should == transition_count + 2 # + Process
32
- end
20
+ # load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
21
+ # machines.size.should == machines_count + 1 # + Process
22
+ # number_of_objects(Models::Process).should == 0
23
+ # number_of_objects(AASM::SupportingClasses::State).should == state_count + 3 # + Process
24
+ # puts "event_count = #{number_of_objects(AASM::SupportingClasses::Event)}"
25
+ # number_of_objects(AASM::SupportingClasses::Event).should == event_count + 2 # + Process
26
+ # number_of_objects(AASM::SupportingClasses::StateTransition).should == transition_count + 2 # + Process
33
27
 
34
- end
28
+ # Models.send(:remove_const, "Process") if Models.const_defined?("Process")
29
+ # load File.expand_path(File.dirname(__FILE__) + '/../models/not_auto_loaded/process.rb')
30
+ # machines.size.should == machines_count + 1 # + Process
31
+ # number_of_objects(AASM::SupportingClasses::State).should == state_count + 3 # + Process
32
+ # # ObjectSpace.each_object(AASM::SupportingClasses::Event) {|o| puts o.inspect}
33
+ # puts "event_count = #{number_of_objects(AASM::SupportingClasses::Event)}"
34
+ # number_of_objects(AASM::SupportingClasses::Event).should == event_count + 2 # + Process
35
+ # number_of_objects(AASM::SupportingClasses::StateTransition).should == transition_count + 2 # + Process
36
+ # end
37
+
38
+ # end
@@ -1,24 +1,8 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  describe "the new dsl" do
4
4
 
5
- before(:each) do
6
- @process = ProcessWithNewDsl.new
7
- end
8
-
9
- it 'should use an initial event' do
10
- @process.aasm_current_state.should == :sleeping
11
- @process.should be_sleeping
12
- end
13
-
14
- it 'should have states and transitions' do
15
- @process.flagged.should be_nil
16
- @process.start!
17
- @process.should be_running
18
- @process.flagged.should be_true
19
- @process.stop!
20
- @process.should be_suspended
21
- end
5
+ let(:process) {ProcessWithNewDsl.new}
22
6
 
23
7
  it 'should not conflict with other event or state methods' do
24
8
  lambda {ProcessWithNewDsl.state}.should raise_error(RuntimeError, "wrong state method")
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'active_record'
3
2
  require 'logger'
4
3
  require 'spec_helper'
@@ -58,7 +57,7 @@ end
58
57
  describe "instance methods" do
59
58
  let(:gate) {Gate.new}
60
59
 
61
- it "should respond to aasm states" do
60
+ it "should respond to aasm persistence methods" do
62
61
  gate.should respond_to(:aasm_read_state)
63
62
  gate.should respond_to(:aasm_write_state)
64
63
  gate.should respond_to(:aasm_write_state_without_persistence)
@@ -85,16 +84,12 @@ describe "instance methods" do
85
84
  gate.aasm_current_state.should be_nil
86
85
  end
87
86
 
88
- it "should have aasm_ensure_initial_state" do
89
- gate.send :aasm_ensure_initial_state
90
- end
91
-
92
87
  it "should call aasm_ensure_initial_state on validation before create" do
93
88
  gate.should_receive(:aasm_ensure_initial_state).and_return(true)
94
89
  gate.valid?
95
90
  end
96
91
 
97
- it "should call aasm_ensure_initial_state on validation before create" do
92
+ it "should not call aasm_ensure_initial_state on validation before update" do
98
93
  gate.stub!(:new_record?).and_return(false)
99
94
  gate.should_not_receive(:aasm_ensure_initial_state)
100
95
  gate.valid?
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ class Payment
4
+ include AASM
5
+ aasm do
6
+ state :initialised, :initial => true
7
+ state :filled_out
8
+ state :authorised
9
+
10
+ event :fill_out do
11
+ transitions :from => :initialised, :to => :filled_out
12
+ end
13
+ event :authorise do
14
+ transitions :from => :filled_out, :to => :authorised
15
+ end
16
+ end
17
+ end
18
+
19
+ describe 'state machine' do
20
+ let(:payment) {Payment.new}
21
+
22
+ it 'starts with an initial state' do
23
+ payment.aasm_current_state.should == :initialised
24
+ # payment.aasm.current_state.should == :initialised # not yet supported
25
+ payment.should respond_to(:initialised?)
26
+ payment.should be_initialised
27
+ end
28
+
29
+ it 'allows transitions to other states' do
30
+ payment.should respond_to(:fill_out)
31
+ payment.should respond_to(:fill_out!)
32
+ payment.fill_out!
33
+ payment.should respond_to(:filled_out?)
34
+ payment.should be_filled_out
35
+
36
+ payment.should respond_to(:authorise)
37
+ payment.should respond_to(:authorise!)
38
+ payment.authorise
39
+ payment.should respond_to(:authorised?)
40
+ payment.should be_authorised
41
+ end
42
+
43
+ it 'denies transitions to other states' do
44
+ lambda {payment.authorise}.should raise_error(AASM::InvalidTransition)
45
+ lambda {payment.authorise!}.should raise_error(AASM::InvalidTransition)
46
+ payment.fill_out
47
+ lambda {payment.fill_out}.should raise_error(AASM::InvalidTransition)
48
+ lambda {payment.fill_out!}.should raise_error(AASM::InvalidTransition)
49
+ payment.authorise
50
+ lambda {payment.fill_out}.should raise_error(AASM::InvalidTransition)
51
+ lambda {payment.fill_out!}.should raise_error(AASM::InvalidTransition)
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'subclassing' do
4
+ it 'should have the parent states' do
5
+ Foo.aasm_states.each do |state|
6
+ FooTwo.aasm_states.should include(state)
7
+ end
8
+ Baz.aasm_states.should == Bar.aasm_states
9
+ end
10
+
11
+ it 'should not add the child states to the parent machine' do
12
+ Foo.aasm_states.should_not include(:foo)
13
+ end
14
+
15
+ it "should have the same events as its parent" do
16
+ Baz.aasm_events.should == Bar.aasm_events
17
+ end
18
+ end
19
+
@@ -1,51 +1,50 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'adding an event' do
4
-
5
- def new_event
6
- @event = AASM::SupportingClasses::Event.new(:close_order, {:success => :success_callback}) do
4
+ let(:event) do
5
+ AASM::SupportingClasses::Event.new(:close_order, {:success => :success_callback}) do
7
6
  transitions :to => :closed, :from => [:open, :received]
8
7
  end
9
8
  end
10
9
 
11
10
  it 'should set the name' do
12
- new_event
13
- @event.name.should == :close_order
11
+ event.name.should == :close_order
14
12
  end
15
13
 
16
- it 'should set the success option' do
17
- new_event
18
- @event.success.should == :success_callback
14
+ it 'should set the success callback' do
15
+ event.success.should == :success_callback
19
16
  end
20
17
 
21
- it 'should create StateTransitions' do
22
- AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :open})
23
- AASM::SupportingClasses::StateTransition.should_receive(:new).with({:to => :closed, :from => :received})
24
- new_event
18
+ it 'should create transitions' do
19
+ transitions = event.all_transitions
20
+ transitions[0].from.should == :open
21
+ transitions[0].to.should == :closed
22
+ transitions[1].from.should == :received
23
+ transitions[1].to.should == :closed
25
24
  end
26
25
  end
27
26
 
28
27
  describe 'transition inspection' do
29
- before do
30
- @event = AASM::SupportingClasses::Event.new(:run) do
28
+ let(:event) do
29
+ AASM::SupportingClasses::Event.new(:run) do
31
30
  transitions :to => :running, :from => :sleeping
32
31
  end
33
32
  end
34
33
 
35
- it 'should support inspecting transitions from states' do
36
- @event.transitions_from_state(:sleeping).map(&:to).should == [:running]
37
- @event.transitions_from_state?(:sleeping).should be_true
34
+ it 'should support inspecting transitions from other states' do
35
+ event.transitions_from_state(:sleeping).map(&:to).should == [:running]
36
+ event.transitions_from_state?(:sleeping).should be_true
38
37
 
39
- @event.transitions_from_state(:cleaning).map(&:to).should == []
40
- @event.transitions_from_state?(:cleaning).should be_false
38
+ event.transitions_from_state(:cleaning).map(&:to).should == []
39
+ event.transitions_from_state?(:cleaning).should be_false
41
40
  end
42
41
 
43
- it 'should support inspecting transitions to states' do
44
- @event.transitions_to_state(:running).map(&:from).should == [:sleeping]
45
- @event.transitions_to_state?(:running).should be_true
42
+ it 'should support inspecting transitions to other states' do
43
+ event.transitions_to_state(:running).map(&:from).should == [:sleeping]
44
+ event.transitions_to_state?(:running).should be_true
46
45
 
47
- @event.transitions_to_state(:cleaning).map(&:to).should == []
48
- @event.transitions_to_state?(:cleaning).should be_false
46
+ event.transitions_to_state(:cleaning).map(&:to).should == []
47
+ event.transitions_to_state?(:cleaning).should be_false
49
48
  end
50
49
  end
51
50
 
@@ -148,3 +147,57 @@ describe 'executing the success callback' do
148
147
  model.with_proc!
149
148
  end
150
149
  end
150
+
151
+ describe 'parametrised events' do
152
+ let(:pe) {ParametrisedEvent.new}
153
+
154
+ it 'should transition to specified next state (sleeping to showering)' do
155
+ pe.wakeup!(:showering)
156
+ pe.aasm_current_state.should == :showering
157
+ end
158
+
159
+ it 'should transition to specified next state (sleeping to working)' do
160
+ pe.wakeup!(:working)
161
+ pe.aasm_current_state.should == :working
162
+ end
163
+
164
+ it 'should transition to default (first or showering) state' do
165
+ pe.wakeup!
166
+ pe.aasm_current_state.should == :showering
167
+ end
168
+
169
+ it 'should transition to default state when on_transition invoked' do
170
+ pe.dress!(nil, 'purple', 'dressy')
171
+ pe.aasm_current_state.should == :working
172
+ end
173
+
174
+ it 'should call on_transition method with args' do
175
+ pe.wakeup!(:showering)
176
+ pe.should_receive(:wear_clothes).with('blue', 'jeans')
177
+ pe.dress!(:working, 'blue', 'jeans')
178
+ end
179
+
180
+ it 'should call on_transition proc' do
181
+ pe.wakeup!(:showering)
182
+ pe.should_receive(:wear_clothes).with('purple', 'slacks')
183
+ pe.dress!(:dating, 'purple', 'slacks')
184
+ end
185
+
186
+ it 'should call on_transition with an array of methods' do
187
+ pe.wakeup!(:showering)
188
+ pe.should_receive(:condition_hair)
189
+ pe.should_receive(:fix_hair)
190
+ pe.dress!(:prettying_up)
191
+ end
192
+ end
193
+
194
+ describe 'event firing without persistence' do
195
+ it 'should attempt to persist if aasm_write_state is defined' do
196
+ foo = Foo.new
197
+ def foo.aasm_write_state; end
198
+ foo.should be_open
199
+
200
+ foo.should_receive(:aasm_write_state_without_persistence)
201
+ foo.close
202
+ end
203
+ end