aasm 4.0.8 → 4.5.2

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.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -2
  3. data/CHANGELOG.md +43 -2
  4. data/CODE_OF_CONDUCT.md +13 -0
  5. data/Gemfile +6 -3
  6. data/LICENSE +1 -1
  7. data/PLANNED_CHANGES.md +8 -4
  8. data/README.md +171 -14
  9. data/aasm.gemspec +1 -5
  10. data/gemfiles/rails_3.2.gemfile +3 -2
  11. data/gemfiles/rails_4.0.gemfile +2 -6
  12. data/gemfiles/rails_4.0_mongo_mapper.gemfile +14 -0
  13. data/gemfiles/rails_4.1.gemfile +2 -6
  14. data/gemfiles/rails_4.1_mongo_mapper.gemfile +14 -0
  15. data/gemfiles/rails_4.2.gemfile +1 -5
  16. data/gemfiles/rails_4.2_mongo_mapper.gemfile +14 -0
  17. data/gemfiles/rails_4.2_mongoid_5.gemfile +12 -0
  18. data/lib/aasm/aasm.rb +69 -36
  19. data/lib/aasm/base.rb +51 -21
  20. data/lib/aasm/core/event.rb +7 -6
  21. data/lib/aasm/core/state.rb +11 -8
  22. data/lib/aasm/core/transition.rb +7 -5
  23. data/lib/aasm/errors.rb +15 -1
  24. data/lib/aasm/instance_base.rb +17 -13
  25. data/lib/aasm/localizer.rb +1 -1
  26. data/lib/aasm/persistence/active_record_persistence.rb +63 -73
  27. data/lib/aasm/persistence/base.rb +55 -20
  28. data/lib/aasm/persistence/mongo_mapper_persistence.rb +157 -0
  29. data/lib/aasm/persistence/mongoid_persistence.rb +16 -41
  30. data/lib/aasm/persistence/plain_persistence.rb +8 -7
  31. data/lib/aasm/persistence/sequel_persistence.rb +12 -9
  32. data/lib/aasm/persistence.rb +2 -0
  33. data/lib/aasm/rspec/allow_event.rb +22 -0
  34. data/lib/aasm/rspec/allow_transition_to.rb +22 -0
  35. data/lib/aasm/rspec/have_state.rb +22 -0
  36. data/lib/aasm/rspec/transition_from.rb +32 -0
  37. data/lib/aasm/rspec.rb +5 -0
  38. data/lib/aasm/state_machine.rb +20 -6
  39. data/lib/aasm/version.rb +1 -1
  40. data/spec/database.rb +27 -1
  41. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  42. data/spec/models/active_record/complex_active_record_example.rb +33 -0
  43. data/spec/models/active_record/derivate_new_dsl.rb +7 -0
  44. data/spec/models/active_record/false_state.rb +35 -0
  45. data/spec/models/active_record/gate.rb +39 -0
  46. data/spec/models/active_record/localizer_test_model.rb +34 -0
  47. data/spec/models/active_record/no_direct_assignment.rb +21 -0
  48. data/spec/models/active_record/no_scope.rb +21 -0
  49. data/spec/models/active_record/persisted_state.rb +12 -0
  50. data/spec/models/active_record/provided_and_persisted_state.rb +24 -0
  51. data/spec/models/active_record/reader.rb +7 -0
  52. data/spec/models/active_record/readme_job.rb +21 -0
  53. data/spec/models/active_record/simple_new_dsl.rb +17 -0
  54. data/spec/models/active_record/thief.rb +29 -0
  55. data/spec/models/active_record/transient.rb +6 -0
  56. data/spec/models/active_record/with_enum.rb +39 -0
  57. data/spec/models/active_record/with_false_enum.rb +31 -0
  58. data/spec/models/active_record/with_true_enum.rb +39 -0
  59. data/spec/models/active_record/writer.rb +6 -0
  60. data/spec/models/basic_two_state_machines_example.rb +25 -0
  61. data/spec/models/callbacks/basic.rb +3 -0
  62. data/spec/models/callbacks/basic_multiple.rb +75 -0
  63. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  64. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  65. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  66. data/spec/models/callbacks/with_args.rb +9 -9
  67. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  68. data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +1 -1
  69. data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
  70. data/spec/models/complex_example.rb +222 -0
  71. data/spec/models/conversation.rb +47 -1
  72. data/spec/models/default_state.rb +12 -0
  73. data/spec/models/foo.rb +57 -0
  74. data/spec/models/foo_callback_multiple.rb +45 -0
  75. data/spec/models/guardian.rb +10 -0
  76. data/spec/models/guardian_multiple.rb +48 -0
  77. data/spec/models/initial_state_proc.rb +31 -0
  78. data/spec/models/invalid_persistor.rb +15 -0
  79. data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +37 -0
  80. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +21 -0
  81. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +23 -0
  82. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +25 -0
  83. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  84. data/spec/models/mongoid/no_scope_mongoid.rb +11 -0
  85. data/spec/models/mongoid/simple_mongoid.rb +12 -0
  86. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +14 -1
  87. data/spec/models/no_initial_state.rb +25 -0
  88. data/spec/models/parametrised_event.rb +1 -1
  89. data/spec/models/parametrised_event_multiple.rb +29 -0
  90. data/spec/models/provided_state.rb +24 -0
  91. data/spec/models/sequel/complex_sequel_example.rb +45 -0
  92. data/spec/models/sequel/sequel_multiple.rb +25 -0
  93. data/spec/models/sequel/sequel_simple.rb +25 -0
  94. data/spec/models/silencer.rb +5 -0
  95. data/spec/models/simple_example.rb +15 -0
  96. data/spec/models/simple_multiple_example.rb +30 -0
  97. data/spec/models/state_machine_with_failed_event.rb +12 -0
  98. data/spec/models/sub_class.rb +7 -0
  99. data/spec/models/sub_class_with_more_states.rb +18 -0
  100. data/spec/models/super_class.rb +46 -0
  101. data/spec/models/transactor.rb +27 -0
  102. data/spec/models/valid_state_name.rb +23 -0
  103. data/spec/models/validator.rb +47 -0
  104. data/spec/spec_helper.rb +4 -4
  105. data/spec/unit/api_spec.rb +6 -1
  106. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  107. data/spec/unit/callback_multiple_spec.rb +295 -0
  108. data/spec/unit/callbacks_spec.rb +3 -2
  109. data/spec/unit/complex_example_spec.rb +2 -2
  110. data/spec/unit/complex_multiple_example_spec.rb +99 -0
  111. data/spec/unit/edge_cases_spec.rb +16 -0
  112. data/spec/unit/event_multiple_spec.rb +73 -0
  113. data/spec/unit/event_naming_spec.rb +2 -15
  114. data/spec/unit/event_spec.rb +11 -6
  115. data/spec/unit/guard_multiple_spec.rb +60 -0
  116. data/spec/unit/guard_spec.rb +12 -0
  117. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  118. data/spec/unit/initial_state_spec.rb +3 -18
  119. data/spec/unit/inspection_multiple_spec.rb +201 -0
  120. data/spec/unit/inspection_spec.rb +12 -7
  121. data/spec/unit/localizer_spec.rb +0 -38
  122. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +573 -0
  123. data/spec/unit/persistence/active_record_persistence_spec.rb +70 -13
  124. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
  125. data/spec/unit/persistence/mongo_mapper_persistence_spec.rb +93 -0
  126. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +127 -0
  127. data/spec/unit/persistence/mongoid_persistence_spec.rb +79 -0
  128. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +153 -0
  129. data/spec/unit/persistence/sequel_persistence_spec.rb +20 -23
  130. data/spec/unit/readme_spec.rb +42 -0
  131. data/spec/unit/reloading_spec.rb +1 -1
  132. data/spec/unit/rspec_matcher_spec.rb +79 -0
  133. data/spec/unit/simple_example_spec.rb +26 -42
  134. data/spec/unit/simple_multiple_example_spec.rb +63 -0
  135. data/spec/unit/state_spec.rb +3 -1
  136. data/spec/unit/subclassing_multiple_spec.rb +39 -0
  137. data/spec/unit/subclassing_spec.rb +10 -10
  138. data/spec/unit/transition_spec.rb +39 -25
  139. metadata +152 -23
  140. data/spec/models/active_record/api.rb +0 -75
  141. data/spec/models/argument.rb +0 -11
  142. data/spec/models/auth_machine.rb +0 -88
  143. data/spec/models/bar.rb +0 -15
  144. data/spec/models/father.rb +0 -21
  145. data/spec/models/persistence.rb +0 -164
  146. data/spec/models/son.rb +0 -3
  147. data/spec/unit/persistence/mongoid_persistance_spec.rb +0 -152
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'on initialization' do
4
+ let(:auth) {ComplexExampleMultiple.new}
5
+
6
+ it 'should be in the initial state' do
7
+ expect(auth.aasm(:left).current_state).to eq(:pending)
8
+ expect(auth.aasm(:right).current_state).to eq(:pending)
9
+ end
10
+
11
+ it 'should have an activation code' do
12
+ expect(auth.has_activation_code?).to be_truthy
13
+ expect(auth.activation_code).to eq '12'
14
+ end
15
+ end
16
+
17
+ describe 'when being unsuspended' do
18
+ let(:auth) {ComplexExampleMultiple.new}
19
+
20
+ it 'should be able to unsuspend' do
21
+ auth.left_activate!
22
+ auth.left_suspend!
23
+ expect(auth.may_left_unsuspend?).to be true
24
+
25
+ auth.right_activate!
26
+ auth.right_suspend!
27
+ expect(auth.may_right_unsuspend?).to be true
28
+ end
29
+
30
+ it 'should not be able to unsuspend into active' do
31
+ auth.left_suspend!
32
+ expect(auth.may_left_unsuspend?(:active)).not_to be true
33
+
34
+ auth.right_activate!
35
+ auth.right_suspend!
36
+ expect(auth.may_right_unsuspend?(:active)).to be true
37
+ end
38
+
39
+ it 'should be able to wait into waiting if polite' do
40
+ auth.left_suspend!
41
+ expect(auth.may_left_wait?(:waiting, :please)).to be true
42
+ auth.left_wait!(nil, :please)
43
+
44
+ auth.right_suspend!
45
+ expect(auth.may_right_wait?(:waiting)).to be false
46
+ auth.right_wait!(nil, :please)
47
+ end
48
+
49
+ it 'should not be able to be unsuspended into active if not polite' do
50
+ auth.left_suspend!
51
+ expect(auth.may_left_wait?(:waiting)).not_to be true
52
+ expect(auth.may_left_wait?(:waiting, :rude)).not_to be true
53
+ expect {auth.left_wait!(nil, :rude)}.to raise_error(AASM::InvalidTransition)
54
+ expect {auth.left_wait!}.to raise_error(AASM::InvalidTransition)
55
+ end
56
+
57
+ it 'should not be able to be unpassified' do
58
+ auth.left_activate!
59
+ auth.left_suspend!
60
+ auth.left_unsuspend!
61
+
62
+ expect(auth.may_left_unpassify?).not_to be true
63
+ expect {auth.left_unpassify!}.to raise_error(AASM::InvalidTransition)
64
+ end
65
+
66
+ it 'should be active if previously activated' do
67
+ auth.left_activate!
68
+ auth.left_suspend!
69
+ auth.left_unsuspend!
70
+
71
+ expect(auth.aasm(:left).current_state).to eq(:active)
72
+ end
73
+
74
+ it 'should be pending if not previously activated, but an activation code is present' do
75
+ auth.left_suspend!
76
+ auth.left_unsuspend!
77
+
78
+ expect(auth.aasm(:left).current_state).to eq(:pending)
79
+ end
80
+
81
+ it 'should be passive if not previously activated and there is no activation code' do
82
+ auth.activation_code = nil
83
+ auth.left_suspend!
84
+ auth.left_unsuspend!
85
+
86
+ expect(auth.aasm(:left).current_state).to eq(:passive)
87
+ end
88
+
89
+ it "should be able to fire known events" do
90
+ expect(auth.aasm(:left).may_fire_event?(:left_activate)).to be true
91
+ expect(auth.aasm(:right).may_fire_event?(:right_activate)).to be true
92
+ end
93
+
94
+ it "should not be able to fire unknown events" do
95
+ expect(auth.aasm(:left).may_fire_event?(:unknown)).to be false
96
+ expect(auth.aasm(:right).may_fire_event?(:unknown)).to be false
97
+ end
98
+
99
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe "edge cases" do
4
+ describe "for classes with multiple state machines" do
5
+ it "allows accessing a multiple state machine class without state machine name" do
6
+ # it's like starting to define a new state machine within the
7
+ # requested class
8
+ expect(SimpleMultipleExample.aasm.states.map(&:name)).to be_empty
9
+ end
10
+
11
+ it "do not know yet" do
12
+ example = ComplexExampleMultiple.new
13
+ expect { example.aasm.states.inspect }.to raise_error(AASM::UnknownStateMachineError)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'current event' do
4
+ let(:pe) {ParametrisedEventMultiple.new}
5
+
6
+ it 'if no event has been triggered' do
7
+ expect(pe.aasm(:left).current_event).to be_nil
8
+ end
9
+
10
+ it 'if a event has been triggered' do
11
+ pe.wakeup
12
+ expect(pe.aasm(:left).current_event).to eql :wakeup
13
+ end
14
+
15
+ it 'if no event has been triggered' do
16
+ pe.wakeup!
17
+ expect(pe.aasm(:left).current_event).to eql :wakeup!
18
+ end
19
+ end
20
+
21
+ describe 'parametrised events' do
22
+ let(:pe) {ParametrisedEventMultiple.new}
23
+
24
+ it 'should transition to specified next state (sleeping to showering)' do
25
+ pe.wakeup!(:showering)
26
+ expect(pe.aasm(:left).current_state).to eq(:showering)
27
+ end
28
+
29
+ it 'should transition to specified next state (sleeping to working)' do
30
+ pe.wakeup!(:working)
31
+ expect(pe.aasm(:left).current_state).to eq(:working)
32
+ end
33
+
34
+ it 'should transition to default (first or showering) state' do
35
+ pe.wakeup!
36
+ expect(pe.aasm(:left).current_state).to eq(:showering)
37
+ end
38
+
39
+ it 'should transition to default state when :after transition invoked' do
40
+ pe.dress!(nil, 'purple', 'dressy')
41
+ expect(pe.aasm(:left).current_state).to eq(:working)
42
+ end
43
+
44
+ it 'should call :after transition method with args' do
45
+ pe.wakeup!(:showering)
46
+ expect(pe).to receive(:wear_clothes).with('blue', 'jeans')
47
+ pe.dress!(:working, 'blue', 'jeans')
48
+ end
49
+
50
+ it 'should call :after transition proc' do
51
+ pe.wakeup!(:showering)
52
+ expect(pe).to receive(:wear_clothes).with('purple', 'slacks')
53
+ pe.dress!(:dating, 'purple', 'slacks')
54
+ end
55
+
56
+ it 'should call :after transition with an array of methods' do
57
+ pe.wakeup!(:showering)
58
+ expect(pe).to receive(:condition_hair)
59
+ expect(pe).to receive(:fix_hair)
60
+ pe.dress!(:prettying_up)
61
+ end
62
+ end
63
+
64
+ describe 'event firing without persistence' do
65
+ it 'should attempt to persist if aasm_write_state is defined' do
66
+ foo = Foo.new
67
+ def foo.aasm_write_state; end
68
+ expect(foo).to be_open
69
+
70
+ expect(foo).to receive(:aasm_write_state_without_persistence)
71
+ foo.close
72
+ end
73
+ end
@@ -1,22 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- class SimpleStateMachine
4
- include AASM
5
-
6
- aasm do
7
- state :init, :initial => true
8
- state :failed
9
-
10
- event :failed do
11
- transitions :from => :init, :to => :failed
12
- end
13
- end
14
- end
15
-
16
3
  describe "event naming" do
17
- let(:state_machine) { SimpleStateMachine.new }
4
+ let(:state_machine) { StateMachineWithFailedEvent.new }
18
5
 
19
- it "allows an event of failed without blowing the stack" do
6
+ it "allows an event of failed without blowing the stack aka stack level too deep" do
20
7
  state_machine.failed
21
8
 
22
9
  expect { state_machine.failed }.to raise_error(AASM::InvalidTransition)
@@ -1,8 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'adding an event' do
4
+ let(:state_machine) { AASM::StateMachine.new(:name) }
4
5
  let(:event) do
5
- AASM::Core::Event.new(:close_order, {:success => :success_callback}) do
6
+ AASM::Core::Event.new(:close_order, state_machine, {:success => :success_callback}) do
6
7
  before :before_callback
7
8
  after :after_callback
8
9
  transitions :to => :closed, :from => [:open, :received]
@@ -35,8 +36,9 @@ describe 'adding an event' do
35
36
  end
36
37
 
37
38
  describe 'transition inspection' do
39
+ let(:state_machine) { AASM::StateMachine.new(:name) }
38
40
  let(:event) do
39
- AASM::Core::Event.new(:run) do
41
+ AASM::Core::Event.new(:run, state_machine) do
40
42
  transitions :to => :running, :from => :sleeping
41
43
  end
42
44
  end
@@ -59,8 +61,9 @@ describe 'transition inspection' do
59
61
  end
60
62
 
61
63
  describe 'transition inspection without from' do
64
+ let(:state_machine) { AASM::StateMachine.new(:name) }
62
65
  let(:event) do
63
- AASM::Core::Event.new(:run) do
66
+ AASM::Core::Event.new(:run, state_machine) do
64
67
  transitions :to => :running
65
68
  end
66
69
  end
@@ -76,15 +79,17 @@ describe 'transition inspection without from' do
76
79
  end
77
80
 
78
81
  describe 'firing an event' do
82
+ let(:state_machine) { AASM::StateMachine.new(:name) }
83
+
79
84
  it 'should return nil if the transitions are empty' do
80
85
  obj = double('object', :aasm => double('aasm', :current_state => 'open'))
81
86
 
82
- event = AASM::Core::Event.new(:event)
87
+ event = AASM::Core::Event.new(:event, state_machine)
83
88
  expect(event.fire(obj)).to be_nil
84
89
  end
85
90
 
86
91
  it 'should return the state of the first matching transition it finds' do
87
- event = AASM::Core::Event.new(:event) do
92
+ event = AASM::Core::Event.new(:event, state_machine) do
88
93
  transitions :to => :closed, :from => [:open, :received]
89
94
  end
90
95
 
@@ -94,7 +99,7 @@ describe 'firing an event' do
94
99
  end
95
100
 
96
101
  it 'should call the guard with the params passed in' do
97
- event = AASM::Core::Event.new(:event) do
102
+ event = AASM::Core::Event.new(:event, state_machine) do
98
103
  transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
99
104
  end
100
105
 
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe "per-transition guards" do
4
+ let(:guardian) { GuardianMultiple.new }
5
+
6
+ it "allows the transition if the guard succeeds" do
7
+ expect { guardian.use_one_guard_that_succeeds! }.to_not raise_error
8
+ expect(guardian).to be_beta
9
+ end
10
+
11
+ it "stops the transition if the guard fails" do
12
+ expect { guardian.use_one_guard_that_fails! }.to raise_error(AASM::InvalidTransition)
13
+ expect(guardian).to be_alpha
14
+ end
15
+
16
+ it "allows the transition if all guards succeeds" do
17
+ expect { guardian.use_guards_that_succeed! }.to_not raise_error
18
+ expect(guardian).to be_beta
19
+ end
20
+
21
+ it "stops the transition if the first guard fails" do
22
+ expect { guardian.use_guards_where_the_first_fails! }.to raise_error(AASM::InvalidTransition)
23
+ expect(guardian).to be_alpha
24
+ end
25
+
26
+ it "stops the transition if the second guard fails" do
27
+ expect { guardian.use_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
28
+ expect(guardian).to be_alpha
29
+ end
30
+ end
31
+
32
+ describe "event guards" do
33
+ let(:guardian) { GuardianMultiple.new }
34
+
35
+ it "allows the transition if the event guards succeed" do
36
+ expect { guardian.use_event_guards_that_succeed! }.to_not raise_error
37
+ expect(guardian).to be_beta
38
+ end
39
+
40
+ it "allows the transition if the event and transition guards succeed" do
41
+ expect { guardian.use_event_and_transition_guards_that_succeed! }.to_not raise_error
42
+ expect(guardian).to be_beta
43
+ end
44
+
45
+ it "stops the transition if the first event guard fails" do
46
+ expect { guardian.use_event_guards_where_the_first_fails! }.to raise_error(AASM::InvalidTransition)
47
+ expect(guardian).to be_alpha
48
+ end
49
+
50
+ it "stops the transition if the second event guard fails" do
51
+ expect { guardian.use_event_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
52
+ expect(guardian).to be_alpha
53
+ end
54
+
55
+ it "stops the transition if the transition guard fails" do
56
+ expect { guardian.use_event_and_transition_guards_where_third_fails! }.to raise_error(AASM::InvalidTransition)
57
+ expect(guardian).to be_alpha
58
+ end
59
+
60
+ end
@@ -27,6 +27,18 @@ describe "per-transition guards" do
27
27
  expect { guardian.use_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
28
28
  expect(guardian).to be_alpha
29
29
  end
30
+
31
+ describe "with params" do
32
+ it "using a Proc" do
33
+ expect(guardian).to receive(:inner_guard).with({:flag => true}).and_return(true)
34
+ guardian.use_proc_guard_with_params(:flag => true)
35
+ end
36
+
37
+ it "using a lambda" do
38
+ expect(guardian).to receive(:inner_guard).with({:flag => true}).and_return(true)
39
+ guardian.use_lambda_guard_with_params(:flag => true)
40
+ end
41
+ end
30
42
  end
31
43
 
32
44
  describe "event guards" do
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'initial states' do
4
+ it 'should use the first state defined if no initial state is given' do
5
+ expect(NoInitialStateMultiple.new.aasm(:left).current_state).to eq(:read)
6
+ end
7
+
8
+ it 'should determine initial state from the Proc results' do
9
+ balance = InitialStateProcMultiple::RICH - 1
10
+ expect(InitialStateProcMultiple.new(balance).aasm(:left).current_state).to eq(:selling_bad_mortgages)
11
+
12
+ balance = InitialStateProcMultiple::RICH + 1
13
+ expect(InitialStateProcMultiple.new(balance).aasm(:left).current_state).to eq(:retired)
14
+ end
15
+ end
@@ -1,27 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
- class Banker
4
- include AASM
5
- aasm do
6
- state :retired
7
- state :selling_bad_mortgages
8
- initial_state Proc.new { |banker| banker.rich? ? :retired : :selling_bad_mortgages }
9
- end
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
3
  describe 'initial states' do
17
- let(:bar) {Bar.new}
18
-
19
4
  it 'should use the first state defined if no initial state is given' do
20
- expect(bar.aasm.current_state).to eq(:read)
5
+ expect(NoInitialState.new.aasm.current_state).to eq(:read)
21
6
  end
22
7
 
23
8
  it 'should determine initial state from the Proc results' do
24
- expect(Banker.new(Banker::RICH - 1).aasm.current_state).to eq(:selling_bad_mortgages)
25
- expect(Banker.new(Banker::RICH + 1).aasm.current_state).to eq(:retired)
9
+ expect(InitialStateProc.new(InitialStateProc::RICH - 1).aasm.current_state).to eq(:selling_bad_mortgages)
10
+ expect(InitialStateProc.new(InitialStateProc::RICH + 1).aasm.current_state).to eq(:retired)
26
11
  end
27
12
  end
@@ -0,0 +1,201 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'inspection for common cases' do
4
+ it 'should support the new DSL' do
5
+ # 1st state machine
6
+ expect(FooMultiple.aasm(:left)).to respond_to(:states)
7
+ expect(FooMultiple.aasm(:left).states.size).to eql 3
8
+ expect(FooMultiple.aasm(:left).states).to include(:open)
9
+ expect(FooMultiple.aasm(:left).states).to include(:closed)
10
+ expect(FooMultiple.aasm(:left).states).to include(:final)
11
+
12
+ expect(FooMultiple.aasm(:left)).to respond_to(:initial_state)
13
+ expect(FooMultiple.aasm(:left).initial_state).to eq(:open)
14
+
15
+ expect(FooMultiple.aasm(:left)).to respond_to(:events)
16
+ expect(FooMultiple.aasm(:left).events.size).to eql 2
17
+ expect(FooMultiple.aasm(:left).events).to include(:close)
18
+ expect(FooMultiple.aasm(:left).events).to include(:null)
19
+
20
+ # 2nd state machine
21
+ expect(FooMultiple.aasm(:right)).to respond_to(:states)
22
+ expect(FooMultiple.aasm(:right).states.size).to eql 3
23
+ expect(FooMultiple.aasm(:right).states).to include(:green)
24
+ expect(FooMultiple.aasm(:right).states).to include(:yellow)
25
+ expect(FooMultiple.aasm(:right).states).to include(:red)
26
+
27
+ expect(FooMultiple.aasm(:right)).to respond_to(:initial_state)
28
+ expect(FooMultiple.aasm(:right).initial_state).to eq(:green)
29
+
30
+ expect(FooMultiple.aasm(:right)).to respond_to(:events)
31
+ expect(FooMultiple.aasm(:right).events.size).to eql 3
32
+ expect(FooMultiple.aasm(:right).events).to include(:green)
33
+ expect(FooMultiple.aasm(:right).events).to include(:yellow)
34
+ expect(FooMultiple.aasm(:right).events).to include(:red)
35
+ end
36
+
37
+ context "instance level inspection" do
38
+ let(:foo) { FooMultiple.new }
39
+ let(:two) { FooTwoMultiple.new }
40
+
41
+ it "delivers all states" do
42
+ # 1st state machine
43
+ states = foo.aasm(:left).states
44
+ expect(states.size).to eql 3
45
+ expect(states).to include(:open)
46
+ expect(states).to include(:closed)
47
+ expect(states).to include(:final)
48
+
49
+ states = foo.aasm(:left).states(:permitted => true)
50
+ expect(states.size).to eql 1
51
+ expect(states).to include(:closed)
52
+ expect(states).not_to include(:open)
53
+ expect(states).not_to include(:final)
54
+
55
+ foo.close
56
+ expect(foo.aasm(:left).states(:permitted => true)).to be_empty
57
+
58
+ # 2nd state machine
59
+ states = foo.aasm(:right).states
60
+ expect(states.size).to eql 3
61
+ expect(states).to include(:green)
62
+ expect(states).to include(:yellow)
63
+ expect(states).to include(:red)
64
+
65
+ states = foo.aasm(:right).states(:permitted => true)
66
+ expect(states.size).to eql 1
67
+ expect(states).to include(:yellow)
68
+ expect(states).not_to include(:green)
69
+ expect(states).not_to include(:red)
70
+
71
+ foo.yellow
72
+ states = foo.aasm(:right).states(:permitted => true)
73
+ expect(states.size).to eql 2
74
+ expect(states).to include(:red)
75
+ expect(states).to include(:green)
76
+ expect(states).not_to include(:yellow)
77
+ end
78
+
79
+ it "delivers all states for subclasses" do
80
+ # 1st state machine
81
+ states = two.aasm(:left).states
82
+ expect(states.size).to eql 4
83
+ expect(states).to include(:open)
84
+ expect(states).to include(:closed)
85
+ expect(states).to include(:final)
86
+ expect(states).to include(:foo)
87
+
88
+ states = two.aasm(:left).states(:permitted => true)
89
+ expect(states.size).to eql 1
90
+ expect(states).to include(:closed)
91
+ expect(states).not_to include(:open)
92
+
93
+ two.close
94
+ expect(two.aasm(:left).states(:permitted => true)).to be_empty
95
+
96
+ # 2nd state machine
97
+ states = two.aasm(:right).states
98
+ expect(states.size).to eql 4
99
+ expect(states).to include(:green)
100
+ expect(states).to include(:yellow)
101
+ expect(states).to include(:red)
102
+ expect(states).to include(:bar)
103
+
104
+ states = two.aasm(:right).states(:permitted => true)
105
+ expect(states.size).to eql 1
106
+ expect(states).to include(:yellow)
107
+ expect(states).not_to include(:red)
108
+ expect(states).not_to include(:green)
109
+ expect(states).not_to include(:bar)
110
+
111
+ two.yellow
112
+ states = two.aasm(:right).states(:permitted => true)
113
+ expect(states.size).to eql 2
114
+ expect(states).to include(:green)
115
+ expect(states).to include(:red)
116
+ expect(states).not_to include(:yellow)
117
+ expect(states).not_to include(:bar)
118
+ end
119
+
120
+ it "delivers all events" do
121
+ # 1st state machine
122
+ events = foo.aasm(:left).events
123
+ expect(events.size).to eql 2
124
+ expect(events).to include(:close)
125
+ expect(events).to include(:null)
126
+
127
+ foo.close
128
+ expect(foo.aasm(:left).events).to be_empty
129
+
130
+ # 2nd state machine
131
+ events = foo.aasm(:right).events
132
+ expect(events.size).to eql 1
133
+ expect(events).to include(:yellow)
134
+ expect(events).not_to include(:green)
135
+ expect(events).not_to include(:red)
136
+
137
+ foo.yellow
138
+ events = foo.aasm(:right).events
139
+ expect(events.size).to eql 2
140
+ expect(events).to include(:green)
141
+ expect(events).to include(:red)
142
+ expect(events).not_to include(:yellow)
143
+ end
144
+ end
145
+
146
+ it 'should list states in the order they have been defined' do
147
+ expect(ConversationMultiple.aasm(:left).states).to eq([
148
+ :needs_attention, :read, :closed, :awaiting_response, :junk
149
+ ])
150
+ end
151
+ end
152
+
153
+ describe "special cases" do
154
+ it "should support valid as state name" do
155
+ expect(ValidStateNameMultiple.aasm(:left).states).to include(:invalid)
156
+ expect(ValidStateNameMultiple.aasm(:left).states).to include(:valid)
157
+
158
+ argument = ValidStateNameMultiple.new
159
+ expect(argument.invalid?).to be_truthy
160
+ expect(argument.aasm(:left).current_state).to eq(:invalid)
161
+
162
+ argument.valid!
163
+ expect(argument.valid?).to be_truthy
164
+ expect(argument.aasm(:left).current_state).to eq(:valid)
165
+ end
166
+ end
167
+
168
+ describe 'aasm.states_for_select' do
169
+ it "should return a select friendly array of states" do
170
+ expect(FooMultiple.aasm(:left)).to respond_to(:states_for_select)
171
+ expect(FooMultiple.aasm(:left).states_for_select).to eq(
172
+ [['Open', 'open'], ['Closed', 'closed'], ['Final', 'final']]
173
+ )
174
+ end
175
+ end
176
+
177
+ describe 'aasm.from_states_for_state' do
178
+ it "should return all from states for a state" do
179
+ expect(ComplexExampleMultiple.aasm(:left)).to respond_to(:from_states_for_state)
180
+ froms = ComplexExampleMultiple.aasm(:left).from_states_for_state(:active)
181
+ [:pending, :passive, :suspended].each {|from| expect(froms).to include(from)}
182
+ end
183
+
184
+ it "should return from states for a state for a particular transition only" do
185
+ froms = ComplexExampleMultiple.aasm(:left).from_states_for_state(:active, :transition => :left_unsuspend)
186
+ [:suspended].each {|from| expect(froms).to include(from)}
187
+ end
188
+ end
189
+
190
+ describe 'permitted events' do
191
+ let(:foo) {FooMultiple.new}
192
+
193
+ it 'work' do
194
+ expect(foo.aasm(:left).events(:permitted => true)).to include(:close)
195
+ expect(foo.aasm(:left).events(:permitted => true)).not_to include(:null)
196
+
197
+ expect(foo.aasm(:right).events(:permitted => true)).to include(:yellow)
198
+ expect(foo.aasm(:right).events(:permitted => true)).not_to include(:green)
199
+ expect(foo.aasm(:right).events(:permitted => true)).not_to include(:red)
200
+ end
201
+ end
@@ -62,11 +62,11 @@ describe 'inspection for common cases' do
62
62
  end
63
63
 
64
64
  describe "special cases" do
65
- it "should support valid a state name" do
66
- expect(Argument.aasm.states).to include(:invalid)
67
- expect(Argument.aasm.states).to include(:valid)
65
+ it "should support valid as state name" do
66
+ expect(ValidStateName.aasm.states).to include(:invalid)
67
+ expect(ValidStateName.aasm.states).to include(:valid)
68
68
 
69
- argument = Argument.new
69
+ argument = ValidStateName.new
70
70
  expect(argument.invalid?).to be_truthy
71
71
  expect(argument.aasm.current_state).to eq(:invalid)
72
72
 
@@ -85,13 +85,13 @@ end
85
85
 
86
86
  describe 'aasm.from_states_for_state' do
87
87
  it "should return all from states for a state" do
88
- expect(AuthMachine.aasm).to respond_to(:from_states_for_state)
89
- froms = AuthMachine.aasm.from_states_for_state(:active)
88
+ expect(ComplexExample.aasm).to respond_to(:from_states_for_state)
89
+ froms = ComplexExample.aasm.from_states_for_state(:active)
90
90
  [:pending, :passive, :suspended].each {|from| expect(froms).to include(from)}
91
91
  end
92
92
 
93
93
  it "should return from states for a state for a particular transition only" do
94
- froms = AuthMachine.aasm.from_states_for_state(:active, :transition => :unsuspend)
94
+ froms = ComplexExample.aasm.from_states_for_state(:active, :transition => :unsuspend)
95
95
  [:suspended].each {|from| expect(froms).to include(from)}
96
96
  end
97
97
  end
@@ -103,4 +103,9 @@ describe 'permitted events' do
103
103
  expect(foo.aasm.events(:permitted => true)).to include(:close)
104
104
  expect(foo.aasm.events(:permitted => true)).not_to include(:null)
105
105
  end
106
+
107
+ it 'should not include events in the reject option' do
108
+ expect(foo.aasm.events(:permitted => true, reject: :close)).not_to include(:close)
109
+ expect(foo.aasm.events(:permitted => true, reject: [:close])).not_to include(:close)
110
+ end
106
111
  end