aasm 2.1.1 → 2.1.3

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.
@@ -0,0 +1,74 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ # TODO These are specs ported from original aasm
4
+ describe AASM::SupportingClasses::State do
5
+ before(:each) do
6
+ @name = :astate
7
+ @options = { :crazy_custom_key => 'key' }
8
+ end
9
+
10
+ def new_state(options={})
11
+ AASM::SupportingClasses::State.new(@name, @options.merge(options))
12
+ end
13
+
14
+ it 'should set the name' do
15
+ state = new_state
16
+
17
+ state.name.should == :astate
18
+ end
19
+
20
+ it 'should set the options and expose them as options' do
21
+ state = new_state
22
+
23
+ state.options.should == @options
24
+ end
25
+
26
+ it 'should be equal to a symbol of the same name' do
27
+ state = new_state
28
+
29
+ state.should == :astate
30
+ end
31
+
32
+ it 'should be equal to a State of the same name' do
33
+ new_state.should == new_state
34
+ end
35
+
36
+ it 'should send a message to the record for an action if the action is present as a symbol' do
37
+ state = new_state(:entering => :foo)
38
+
39
+ record = mock('record')
40
+ record.should_receive(:foo)
41
+
42
+ state.call_action(:entering, record)
43
+ end
44
+
45
+ it 'should send a message to the record for an action if the action is present as a string' do
46
+ state = new_state(:entering => 'foo')
47
+
48
+ record = mock('record')
49
+ record.should_receive(:foo)
50
+
51
+ state.call_action(:entering, record)
52
+ end
53
+
54
+ it 'should send a message to the record for each action' do
55
+ state = new_state(:entering => [:a, :b, "c", lambda {|r| r.foobar }])
56
+
57
+ record = mock('record')
58
+ record.should_receive(:a)
59
+ record.should_receive(:b)
60
+ record.should_receive(:c)
61
+ record.should_receive(:foobar)
62
+
63
+ state.call_action(:entering, record)
64
+ end
65
+
66
+ it 'should call a proc, passing in the record for an action if the action is present' do
67
+ state = new_state(:entering => Proc.new {|r| r.foobar})
68
+
69
+ record = mock('record')
70
+ record.should_receive(:foobar)
71
+
72
+ state.call_action(:entering, record)
73
+ end
74
+ end
@@ -0,0 +1,84 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe AASM::SupportingClasses::StateTransition do
4
+ it 'should set from, to, and opts attr readers' do
5
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
6
+ st = AASM::SupportingClasses::StateTransition.new(opts)
7
+
8
+ st.from.should == opts[:from]
9
+ st.to.should == opts[:to]
10
+ st.opts.should == opts
11
+ end
12
+
13
+ it 'should pass equality check if from and to are the same' do
14
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
15
+ st = AASM::SupportingClasses::StateTransition.new(opts)
16
+
17
+ obj = mock('object')
18
+ obj.stub!(:from).and_return(opts[:from])
19
+ obj.stub!(:to).and_return(opts[:to])
20
+
21
+ st.should == obj
22
+ end
23
+
24
+ it 'should fail equality check if from are not the same' do
25
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
26
+ st = AASM::SupportingClasses::StateTransition.new(opts)
27
+
28
+ obj = mock('object')
29
+ obj.stub!(:from).and_return('blah')
30
+ obj.stub!(:to).and_return(opts[:to])
31
+
32
+ st.should_not == obj
33
+ end
34
+
35
+ it 'should fail equality check if to are not the same' do
36
+ opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
37
+ st = AASM::SupportingClasses::StateTransition.new(opts)
38
+
39
+ obj = mock('object')
40
+ obj.stub!(:from).and_return(opts[:from])
41
+ obj.stub!(:to).and_return('blah')
42
+
43
+ st.should_not == obj
44
+ end
45
+ end
46
+
47
+ describe AASM::SupportingClasses::StateTransition, '- when performing guard checks' do
48
+ it 'should return true of there is no guard' do
49
+ opts = {:from => 'foo', :to => 'bar'}
50
+ st = AASM::SupportingClasses::StateTransition.new(opts)
51
+
52
+ st.perform(nil).should be_true
53
+ end
54
+
55
+ it 'should call the method on the object if guard is a symbol' do
56
+ opts = {:from => 'foo', :to => 'bar', :guard => :test}
57
+ st = AASM::SupportingClasses::StateTransition.new(opts)
58
+
59
+ obj = mock('object')
60
+ obj.should_receive(:test)
61
+
62
+ st.perform(obj)
63
+ end
64
+
65
+ it 'should call the method on the object if guard is a string' do
66
+ opts = {:from => 'foo', :to => 'bar', :guard => 'test'}
67
+ st = AASM::SupportingClasses::StateTransition.new(opts)
68
+
69
+ obj = mock('object')
70
+ obj.should_receive(:test)
71
+
72
+ st.perform(obj)
73
+ end
74
+
75
+ it 'should call the proc passing the object if the guard is a proc' do
76
+ opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test}}
77
+ st = AASM::SupportingClasses::StateTransition.new(opts)
78
+
79
+ obj = mock('object')
80
+ obj.should_receive(:test)
81
+
82
+ st.perform(obj)
83
+ end
84
+ end
@@ -0,0 +1,120 @@
1
+ require 'test_helper'
2
+
3
+ class AuthMachine
4
+ include AASM
5
+
6
+ attr_accessor :activation_code, :activated_at, :deleted_at
7
+
8
+ aasm_initial_state :pending
9
+
10
+ aasm_state :passive
11
+ aasm_state :pending, :enter => :make_activation_code
12
+ aasm_state :active, :enter => :do_activate
13
+ aasm_state :suspended
14
+ aasm_state :deleted, :enter => :do_delete, :exit => :do_undelete
15
+
16
+ aasm_event :register do
17
+ transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| u.can_register? }
18
+ end
19
+
20
+ aasm_event :activate do
21
+ transitions :from => :pending, :to => :active
22
+ end
23
+
24
+ aasm_event :suspend do
25
+ transitions :from => [:passive, :pending, :active], :to => :suspended
26
+ end
27
+
28
+ aasm_event :delete do
29
+ transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
30
+ end
31
+
32
+ aasm_event :unsuspend do
33
+ transitions :from => :suspended, :to => :active, :guard => Proc.new {|u| u.has_activated? }
34
+ transitions :from => :suspended, :to => :pending, :guard => Proc.new {|u| u.has_activation_code? }
35
+ transitions :from => :suspended, :to => :passive
36
+ end
37
+
38
+ def initialize
39
+ # the AR backend uses a before_validate_on_create :aasm_ensure_initial_state
40
+ # lets do something similar here for testing purposes.
41
+ aasm_enter_initial_state
42
+ end
43
+
44
+ def make_activation_code
45
+ @activation_code = 'moo'
46
+ end
47
+
48
+ def do_activate
49
+ @activated_at = Time.now
50
+ @activation_code = nil
51
+ end
52
+
53
+ def do_delete
54
+ @deleted_at = Time.now
55
+ end
56
+
57
+ def do_undelete
58
+ @deleted_at = false
59
+ end
60
+
61
+ def can_register?
62
+ true
63
+ end
64
+
65
+ def has_activated?
66
+ !!@activated_at
67
+ end
68
+
69
+ def has_activation_code?
70
+ !!@activation_code
71
+ end
72
+ end
73
+
74
+ class AuthMachineTest < Test::Unit::TestCase
75
+ context 'authentication state machine' do
76
+ context 'on initialization' do
77
+ setup do
78
+ @auth = AuthMachine.new
79
+ end
80
+
81
+ should 'be in the pending state' do
82
+ assert_equal :pending, @auth.aasm_current_state
83
+ end
84
+
85
+ should 'have an activation code' do
86
+ assert @auth.has_activation_code?
87
+ assert_not_nil @auth.activation_code
88
+ end
89
+ end
90
+
91
+ context 'when being unsuspended' do
92
+ should 'be active if previously activated' do
93
+ @auth = AuthMachine.new
94
+ @auth.activate!
95
+ @auth.suspend!
96
+ @auth.unsuspend!
97
+
98
+ assert_equal :active, @auth.aasm_current_state
99
+ end
100
+
101
+ should 'be pending if not previously activated, but an activation code is present' do
102
+ @auth = AuthMachine.new
103
+ @auth.suspend!
104
+ @auth.unsuspend!
105
+
106
+ assert_equal :pending, @auth.aasm_current_state
107
+ end
108
+
109
+ should 'be passive if not previously activated and there is no activation code' do
110
+ @auth = AuthMachine.new
111
+ @auth.activation_code = nil
112
+ @auth.suspend!
113
+ @auth.unsuspend!
114
+
115
+ assert_equal :passive, @auth.aasm_current_state
116
+ end
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,33 @@
1
+ require 'ostruct'
2
+ require 'rubygems'
3
+
4
+ begin
5
+ gem 'minitest'
6
+ rescue Gem::LoadError
7
+ puts 'minitest gem not found'
8
+ end
9
+
10
+ begin
11
+ require 'minitest/autorun'
12
+ puts 'using minitest'
13
+ rescue LoadError
14
+ require 'test/unit'
15
+ puts 'using test/unit'
16
+ end
17
+
18
+ require 'rr'
19
+ require 'shoulda'
20
+
21
+ class Test::Unit::TestCase
22
+ include RR::Adapters::TestUnit
23
+ end
24
+
25
+ begin
26
+ require 'ruby-debug'
27
+ Debugger.start
28
+ rescue LoadError
29
+ end
30
+
31
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
32
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
33
+ require 'aasm'
File without changes
@@ -0,0 +1,54 @@
1
+ require 'test_helper'
2
+
3
+ class EventTest < Test::Unit::TestCase
4
+ def new_event
5
+ @event = AASM::SupportingClasses::Event.new(@name, {:success => @success}) do
6
+ transitions :to => :closed, :from => [:open, :received]
7
+ end
8
+ end
9
+
10
+ context 'event' do
11
+ setup do
12
+ @name = :close_order
13
+ @success = :success_callback
14
+ end
15
+
16
+ should 'set the name' do
17
+ assert_equal @name, new_event.name
18
+ end
19
+
20
+ should 'set the success option' do
21
+ assert_equal @success, new_event.success
22
+ end
23
+
24
+ should 'create StateTransitions' do
25
+ mock(AASM::SupportingClasses::StateTransition).new({:to => :closed, :from => :open})
26
+ mock(AASM::SupportingClasses::StateTransition).new({:to => :closed, :from => :received})
27
+ new_event
28
+ end
29
+
30
+ context 'when firing' do
31
+ should 'raise an AASM::InvalidTransition error if the transitions are empty' do
32
+ event = AASM::SupportingClasses::Event.new(:event)
33
+
34
+ obj = OpenStruct.new
35
+ obj.aasm_current_state = :open
36
+
37
+ assert_raise AASM::InvalidTransition do
38
+ event.fire(obj)
39
+ end
40
+ end
41
+
42
+ should 'return the state of the first matching transition it finds' do
43
+ event = AASM::SupportingClasses::Event.new(:event) do
44
+ transitions :to => :closed, :from => [:open, :received]
45
+ end
46
+
47
+ obj = OpenStruct.new
48
+ obj.aasm_current_state = :open
49
+
50
+ assert_equal :closed, event.fire(obj)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+
3
+ class StateTest < Test::Unit::TestCase
4
+ def new_state(options={})
5
+ AASM::SupportingClasses::State.new(@name, @options.merge(options))
6
+ end
7
+
8
+ context 'state' do
9
+ setup do
10
+ @name = :astate
11
+ @options = { :crazy_custom_key => 'key' }
12
+ end
13
+
14
+ should 'set the name' do
15
+ assert_equal :astate, new_state.name
16
+ end
17
+
18
+ should 'set the display_name from name' do
19
+ assert_equal "Astate", new_state.display_name
20
+ end
21
+
22
+ should 'set the display_name from options' do
23
+ assert_equal "A State", new_state(:display => "A State").display_name
24
+ end
25
+
26
+ should 'set the options and expose them as options' do
27
+ assert_equal @options, new_state.options
28
+ end
29
+
30
+ should 'equal a symbol of the same name' do
31
+ assert_equal new_state, :astate
32
+ end
33
+
34
+ should 'equal a state of the same name' do
35
+ assert_equal new_state, new_state
36
+ end
37
+
38
+ should 'send a message to the record for an action if the action is present as a symbol' do
39
+ state = new_state(:entering => :foo)
40
+ mock(record = Object.new).foo
41
+ state.call_action(:entering, record)
42
+ end
43
+
44
+ should 'send a message to the record for an action if the action is present as a string' do
45
+ state = new_state(:entering => 'foo')
46
+ mock(record = Object.new).foo
47
+ state.call_action(:entering, record)
48
+ end
49
+
50
+ should 'call a proc with the record as its argument for an action if the action is present as a proc' do
51
+ state = new_state(:entering => Proc.new {|r| r.foobar})
52
+ mock(record = Object.new).foobar
53
+ state.call_action(:entering, record)
54
+ end
55
+
56
+ should 'send a message to the record for each action if the action is present as an array' do
57
+ state = new_state(:entering => [:a, :b, 'c', lambda {|r| r.foobar}])
58
+
59
+ record = Object.new
60
+ mock(record).a
61
+ mock(record).b
62
+ mock(record).c
63
+ mock(record).foobar
64
+
65
+ state.call_action(:entering, record)
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,75 @@
1
+ require 'test_helper'
2
+
3
+ class StateTransitionTest < Test::Unit::TestCase
4
+ context 'state transition' do
5
+ setup do
6
+ @opts = {:from => 'foo', :to => 'bar', :guard => 'g'}
7
+ @st = AASM::SupportingClasses::StateTransition.new(@opts)
8
+ end
9
+
10
+ should 'set from, to, and opts attr readers' do
11
+ assert_equal @opts[:from], @st.from
12
+ assert_equal @opts[:to], @st.to
13
+ assert_equal @opts, @st.options
14
+ end
15
+
16
+ should 'pass equality check if from and to are the same' do
17
+ obj = OpenStruct.new
18
+ obj.from = @opts[:from]
19
+ obj.to = @opts[:to]
20
+
21
+ assert_equal @st, obj
22
+ end
23
+
24
+ should 'fail equality check if from is not the same' do
25
+ obj = OpenStruct.new
26
+ obj.from = 'blah'
27
+ obj.to = @opts[:to]
28
+
29
+ assert_not_equal @st, obj
30
+ end
31
+
32
+ should 'fail equality check if to is not the same' do
33
+ obj = OpenStruct.new
34
+ obj.from = @opts[:from]
35
+ obj.to = 'blah'
36
+
37
+ assert_not_equal @st, obj
38
+ end
39
+
40
+ context 'when performing guard checks' do
41
+ should 'return true if there is no guard' do
42
+ opts = {:from => 'foo', :to => 'bar'}
43
+ st = AASM::SupportingClasses::StateTransition.new(opts)
44
+ assert st.perform(nil)
45
+ end
46
+
47
+ should 'call the method on the object if guard is a symbol' do
48
+ opts = {:from => 'foo', :to => 'bar', :guard => :test_guard}
49
+ st = AASM::SupportingClasses::StateTransition.new(opts)
50
+
51
+ mock(obj = Object.new).test_guard
52
+
53
+ st.perform(obj)
54
+ end
55
+
56
+ should 'call the method on the object if guard is a string' do
57
+ opts = {:from => 'foo', :to => 'bar', :guard => 'test_guard'}
58
+ st = AASM::SupportingClasses::StateTransition.new(opts)
59
+
60
+ mock(obj = Object.new).test_guard
61
+
62
+ st.perform(obj)
63
+ end
64
+
65
+ should 'call the proc passing the object if guard is a proc' do
66
+ opts = {:from => 'foo', :to => 'bar', :guard => Proc.new {|o| o.test_guard}}
67
+ st = AASM::SupportingClasses::StateTransition.new(opts)
68
+
69
+ mock(obj = Object.new).test_guard
70
+
71
+ st.perform(obj)
72
+ end
73
+ end
74
+ end
75
+ end