aasm 2.1.1 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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