aasm 4.2.0 → 4.3.0

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -1
  3. data/Gemfile +2 -2
  4. data/PLANNED_CHANGES.md +24 -4
  5. data/README.md +75 -5
  6. data/lib/aasm/aasm.rb +50 -36
  7. data/lib/aasm/base.rb +36 -18
  8. data/lib/aasm/core/event.rb +6 -5
  9. data/lib/aasm/core/state.rb +3 -2
  10. data/lib/aasm/core/transition.rb +5 -4
  11. data/lib/aasm/errors.rb +7 -4
  12. data/lib/aasm/instance_base.rb +14 -13
  13. data/lib/aasm/localizer.rb +1 -1
  14. data/lib/aasm/persistence/active_record_persistence.rb +41 -66
  15. data/lib/aasm/persistence/base.rb +7 -7
  16. data/lib/aasm/persistence/mongo_mapper_persistence.rb +34 -51
  17. data/lib/aasm/persistence/mongoid_persistence.rb +15 -36
  18. data/lib/aasm/persistence/plain_persistence.rb +8 -7
  19. data/lib/aasm/persistence/sequel_persistence.rb +12 -10
  20. data/lib/aasm/state_machine.rb +11 -6
  21. data/lib/aasm/version.rb +1 -1
  22. data/spec/database.rb +27 -1
  23. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  24. data/spec/models/active_record/complex_active_record_example.rb +33 -0
  25. data/spec/models/active_record/derivate_new_dsl.rb +4 -0
  26. data/spec/models/active_record/false_state.rb +18 -0
  27. data/spec/models/active_record/gate.rb +20 -0
  28. data/spec/models/active_record/no_direct_assignment.rb +11 -0
  29. data/spec/models/active_record/no_scope.rb +11 -0
  30. data/spec/models/active_record/provided_and_persisted_state.rb +3 -3
  31. data/spec/models/active_record/simple_new_dsl.rb +9 -0
  32. data/spec/models/active_record/thief.rb +15 -0
  33. data/spec/models/active_record/with_enum.rb +20 -0
  34. data/spec/models/active_record/with_false_enum.rb +16 -0
  35. data/spec/models/active_record/with_true_enum.rb +20 -0
  36. data/spec/models/basic_two_state_machines_example.rb +25 -0
  37. data/spec/models/callbacks/basic_multiple.rb +75 -0
  38. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  39. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  40. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  41. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  42. data/spec/models/callbacks/{with_state_args.rb → with_state_arg.rb} +0 -0
  43. data/spec/models/callbacks/with_state_arg_multiple.rb +26 -0
  44. data/spec/models/complex_example.rb +134 -0
  45. data/spec/models/conversation.rb +47 -1
  46. data/spec/models/foo.rb +57 -0
  47. data/spec/models/foo_callback_multiple.rb +45 -0
  48. data/spec/models/guardian_multiple.rb +48 -0
  49. data/spec/models/initial_state_proc.rb +16 -0
  50. data/spec/models/invalid_persistor.rb +15 -0
  51. data/spec/models/mongo_mapper/complex_mongo_mapper_example.rb +37 -0
  52. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +11 -0
  53. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +12 -0
  54. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +13 -0
  55. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  56. data/spec/models/mongoid/no_scope_mongoid.rb +11 -0
  57. data/spec/models/mongoid/simple_mongoid.rb +12 -0
  58. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +13 -0
  59. data/spec/models/no_initial_state.rb +13 -0
  60. data/spec/models/parametrised_event.rb +1 -1
  61. data/spec/models/parametrised_event_multiple.rb +29 -0
  62. data/spec/models/provided_state.rb +3 -3
  63. data/spec/models/sequel/complex_sequel_example.rb +45 -0
  64. data/spec/models/sequel/sequel_multiple.rb +25 -0
  65. data/spec/models/sequel/sequel_simple.rb +25 -0
  66. data/spec/models/simple_multiple_example.rb +30 -0
  67. data/spec/models/sub_class.rb +4 -0
  68. data/spec/models/sub_class_with_more_states.rb +11 -0
  69. data/spec/models/super_class.rb +28 -0
  70. data/spec/models/transactor.rb +27 -0
  71. data/spec/models/valid_state_name.rb +12 -0
  72. data/spec/models/validator.rb +39 -0
  73. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  74. data/spec/unit/callback_multiple_spec.rb +295 -0
  75. data/spec/unit/callbacks_spec.rb +1 -1
  76. data/spec/unit/complex_multiple_example_spec.rb +99 -0
  77. data/spec/unit/edge_cases_spec.rb +16 -0
  78. data/spec/unit/event_multiple_spec.rb +73 -0
  79. data/spec/unit/event_spec.rb +11 -6
  80. data/spec/unit/guard_multiple_spec.rb +60 -0
  81. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  82. data/spec/unit/inspection_multiple_spec.rb +201 -0
  83. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +560 -0
  84. data/spec/unit/persistence/active_record_persistence_spec.rb +17 -12
  85. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +146 -0
  86. data/spec/unit/persistence/{mongo_mapper_persistance_spec.rb → mongo_mapper_persistence_spec.rb} +7 -49
  87. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +127 -0
  88. data/spec/unit/persistence/mongoid_persistence_spec.rb +79 -0
  89. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +153 -0
  90. data/spec/unit/persistence/sequel_persistence_spec.rb +7 -24
  91. data/spec/unit/reloading_spec.rb +1 -1
  92. data/spec/unit/simple_multiple_example_spec.rb +63 -0
  93. data/spec/unit/state_spec.rb +3 -1
  94. data/spec/unit/subclassing_multiple_spec.rb +39 -0
  95. data/spec/unit/transition_spec.rb +31 -22
  96. metadata +73 -9
  97. data/spec/unit/persistence/mongoid_persistance_spec.rb +0 -146
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'on initialization' do
4
+ let(:example) { BasicTwoStateMachinesExample.new }
5
+
6
+ it 'should be in the initial state' do
7
+ expect(example.aasm(:search).current_state).to eql :initialised
8
+ expect(example.aasm(:sync).current_state).to eql :unsynced
9
+ end
10
+ end
@@ -0,0 +1,295 @@
1
+ require 'spec_helper'
2
+ Dir[File.dirname(__FILE__) + "/../models/callbacks/*.rb"].sort.each { |f| require File.expand_path(f) }
3
+
4
+ describe 'callbacks for the new DSL' do
5
+
6
+ it "be called in order" do
7
+ show_debug_log = false
8
+
9
+ callback = Callbacks::BasicMultiple.new(:log => show_debug_log)
10
+ callback.aasm(:left).current_state
11
+
12
+ unless show_debug_log
13
+ expect(callback).to receive(:before_event).once.ordered
14
+ expect(callback).to receive(:event_guard).once.ordered.and_return(true)
15
+ expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
16
+ expect(callback).to receive(:before_exit_open).once.ordered # these should be before the state changes
17
+ expect(callback).to receive(:exit_open).once.ordered
18
+ # expect(callback).to receive(:event_guard).once.ordered.and_return(true)
19
+ # expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
20
+ expect(callback).to receive(:after_transition).once.ordered
21
+ expect(callback).to receive(:before_enter_closed).once.ordered
22
+ expect(callback).to receive(:enter_closed).once.ordered
23
+ expect(callback).to receive(:aasm_write_state).with(:closed, :left).once.ordered.and_return(true) # this is when the state changes
24
+ expect(callback).to receive(:after_exit_open).once.ordered # these should be after the state changes
25
+ expect(callback).to receive(:after_enter_closed).once.ordered
26
+ expect(callback).to receive(:after_event).once.ordered
27
+ end
28
+
29
+ # puts "------- close!"
30
+ callback.left_close!
31
+ end
32
+
33
+ it "does not run any state callback if the event guard fails" do
34
+ callback = Callbacks::BasicMultiple.new(:log => false)
35
+ callback.aasm(:left).current_state
36
+
37
+ expect(callback).to receive(:before_event).once.ordered
38
+ expect(callback).to receive(:event_guard).once.ordered.and_return(false)
39
+ expect(callback).to_not receive(:transition_guard)
40
+ expect(callback).to_not receive(:before_exit_open)
41
+ expect(callback).to_not receive(:exit_open)
42
+ expect(callback).to_not receive(:after_transition)
43
+ expect(callback).to_not receive(:before_enter_closed)
44
+ expect(callback).to_not receive(:enter_closed)
45
+ expect(callback).to_not receive(:aasm_write_state)
46
+ expect(callback).to_not receive(:after_exit_open)
47
+ expect(callback).to_not receive(:after_enter_closed)
48
+ expect(callback).to_not receive(:after_event)
49
+
50
+ expect {
51
+ callback.left_close!
52
+ }.to raise_error(AASM::InvalidTransition)
53
+ end
54
+
55
+ it "handles private callback methods as well" do
56
+ show_debug_log = false
57
+
58
+ callback = Callbacks::PrivateMethodMultiple.new(:log => show_debug_log)
59
+ callback.aasm(:left).current_state
60
+
61
+ # puts "------- close!"
62
+ expect {
63
+ callback.close!
64
+ }.to_not raise_error
65
+ end
66
+
67
+ context "if the transition guard fails" do
68
+ it "does not run any state callback if guard is defined inline" do
69
+ show_debug_log = false
70
+ callback = Callbacks::BasicMultiple.new(:log => show_debug_log, :fail_transition_guard => true)
71
+ callback.aasm(:left).current_state
72
+
73
+ unless show_debug_log
74
+ expect(callback).to receive(:before_event).once.ordered
75
+ expect(callback).to receive(:event_guard).once.ordered.and_return(true)
76
+ expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
77
+ expect(callback).to_not receive(:before_exit_open)
78
+ expect(callback).to_not receive(:exit_open)
79
+ expect(callback).to_not receive(:after_transition)
80
+ expect(callback).to_not receive(:before_enter_closed)
81
+ expect(callback).to_not receive(:enter_closed)
82
+ expect(callback).to_not receive(:aasm_write_state)
83
+ expect(callback).to_not receive(:after_exit_open)
84
+ expect(callback).to_not receive(:after_enter_closed)
85
+ expect(callback).to_not receive(:after_event)
86
+ end
87
+
88
+ expect {
89
+ callback.left_close!
90
+ }.to raise_error(AASM::InvalidTransition)
91
+ end
92
+
93
+ it "does not run transition_guard twice for multiple permitted transitions" do
94
+ show_debug_log = false
95
+ callback = Callbacks::MultipleTransitionsTransitionGuardMultiple.new(:log => show_debug_log, :fail_transition_guard => true)
96
+ callback.aasm(:left).current_state
97
+
98
+ unless show_debug_log
99
+ expect(callback).to receive(:before).once.ordered
100
+ expect(callback).to receive(:event_guard).once.ordered.and_return(true)
101
+ expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
102
+ expect(callback).to receive(:event_guard).once.ordered.and_return(true)
103
+ expect(callback).to receive(:before_exit_open).once.ordered
104
+ expect(callback).to receive(:exit_open).once.ordered
105
+ expect(callback).to receive(:aasm_write_state).once.ordered.and_return(true) # this is when the state changes
106
+ expect(callback).to receive(:after_exit_open).once.ordered
107
+ expect(callback).to receive(:after).once.ordered
108
+
109
+ expect(callback).to_not receive(:transitioning)
110
+ expect(callback).to_not receive(:before_enter_closed)
111
+ expect(callback).to_not receive(:enter_closed)
112
+ expect(callback).to_not receive(:after_enter_closed)
113
+ end
114
+
115
+ callback.close!
116
+ expect(callback.aasm(:left).current_state).to eql :failed
117
+ end
118
+
119
+ it "does not run any state callback if guard is defined with block" do
120
+ callback = Callbacks::GuardWithinBlockMultiple.new #(:log => true, :fail_transition_guard => true)
121
+ callback.aasm(:left).current_state
122
+
123
+ expect(callback).to receive(:before).once.ordered
124
+ expect(callback).to receive(:event_guard).once.ordered.and_return(true)
125
+ expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
126
+ expect(callback).to_not receive(:before_exit_open)
127
+ expect(callback).to_not receive(:exit_open)
128
+ expect(callback).to_not receive(:transitioning)
129
+ expect(callback).to_not receive(:before_enter_closed)
130
+ expect(callback).to_not receive(:enter_closed)
131
+ expect(callback).to_not receive(:aasm_write_state)
132
+ expect(callback).to_not receive(:after_exit_open)
133
+ expect(callback).to_not receive(:after_enter_closed)
134
+ expect(callback).to_not receive(:after)
135
+
136
+ expect {
137
+ callback.close!
138
+ }.to raise_error(AASM::InvalidTransition)
139
+ end
140
+ end
141
+
142
+ it "should properly pass arguments" do
143
+ cb = Callbacks::WithArgsMultiple.new(:log => false)
144
+ cb.aasm(:left).current_state
145
+
146
+ cb.reset_data
147
+ cb.close!(:arg1, :arg2)
148
+ expect(cb.data).to eql 'before(:arg1,:arg2) before_exit_open(:arg1,:arg2) transition_proc(:arg1,:arg2) before_enter_closed(:arg1,:arg2) aasm_write_state after_exit_open(:arg1,:arg2) after_enter_closed(:arg1,:arg2) after(:arg1,:arg2)'
149
+ end
150
+
151
+ it "should call the callbacks given the to-state as argument" do
152
+ cb = Callbacks::WithStateArgMultiple.new
153
+ expect(cb).to receive(:before_method).with(:arg1).once.ordered
154
+ expect(cb).to receive(:transition_method).never
155
+ expect(cb).to receive(:transition_method2).with(:arg1).once.ordered
156
+ expect(cb).to receive(:after_method).with(:arg1).once.ordered
157
+ cb.close!(:out_to_lunch, :arg1)
158
+
159
+ cb = Callbacks::WithStateArgMultiple.new
160
+ some_object = double('some object')
161
+ expect(cb).to receive(:before_method).with(some_object).once.ordered
162
+ expect(cb).to receive(:transition_method2).with(some_object).once.ordered
163
+ expect(cb).to receive(:after_method).with(some_object).once.ordered
164
+ cb.close!(:out_to_lunch, some_object)
165
+ end
166
+
167
+ it "should call the proper methods just with arguments" do
168
+ cb = Callbacks::WithStateArgMultiple.new
169
+ expect(cb).to receive(:before_method).with(:arg1).once.ordered
170
+ expect(cb).to receive(:transition_method).with(:arg1).once.ordered
171
+ expect(cb).to receive(:transition_method).never
172
+ expect(cb).to receive(:after_method).with(:arg1).once.ordered
173
+ cb.close!(:arg1)
174
+
175
+ cb = Callbacks::WithStateArgMultiple.new
176
+ some_object = double('some object')
177
+ expect(cb).to receive(:before_method).with(some_object).once.ordered
178
+ expect(cb).to receive(:transition_method).with(some_object).once.ordered
179
+ expect(cb).to receive(:transition_method).never
180
+ expect(cb).to receive(:after_method).with(some_object).once.ordered
181
+ cb.close!(some_object)
182
+ end
183
+ end # callbacks for the new DSL
184
+
185
+ describe 'event callbacks' do
186
+ describe "with an error callback defined" do
187
+ before do
188
+ class FooCallbackMultiple
189
+ # this hack is needed to allow testing of parameters, since RSpec
190
+ # destroys a method's arity when mocked
191
+ attr_accessor :data
192
+
193
+ aasm(:left) do
194
+ event :safe_close, :success => :success_callback, :error => :error_callback do
195
+ transitions :to => :closed, :from => [:open]
196
+ end
197
+ end
198
+ end
199
+
200
+ @foo = FooCallbackMultiple.new
201
+ end
202
+
203
+ context "error_callback defined" do
204
+ it "should run error_callback if an exception is raised" do
205
+ def @foo.error_callback(e)
206
+ @data = [e]
207
+ end
208
+
209
+ allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
210
+
211
+ @foo.safe_close!
212
+ expect(@foo.data).to eql [e]
213
+ end
214
+
215
+ it "should run error_callback without parameters if callback does not support any" do
216
+ def @foo.error_callback(e)
217
+ @data = []
218
+ end
219
+
220
+ allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
221
+
222
+ @foo.safe_close!('arg1', 'arg2')
223
+ expect(@foo.data).to eql []
224
+ end
225
+
226
+ it "should run error_callback with parameters if callback supports them" do
227
+ def @foo.error_callback(e, arg1, arg2)
228
+ @data = [arg1, arg2]
229
+ end
230
+
231
+ allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
232
+
233
+ @foo.safe_close!('arg1', 'arg2')
234
+ expect(@foo.data).to eql ['arg1', 'arg2']
235
+ end
236
+ end
237
+
238
+ it "should raise NoMethodError if exception is raised and error_callback is declared but not defined" do
239
+ allow(@foo).to receive(:before_enter).and_raise(StandardError)
240
+ expect{@foo.safe_close!}.to raise_error(NoMethodError)
241
+ end
242
+
243
+ it "should propagate an error if no error callback is declared" do
244
+ allow(@foo).to receive(:before_enter).and_raise("Cannot enter safe")
245
+ expect{@foo.close!}.to raise_error(StandardError, "Cannot enter safe")
246
+ end
247
+ end
248
+
249
+ describe "with aasm_event_fired defined" do
250
+ before do
251
+ @foo = FooMultiple.new
252
+ def @foo.aasm_event_fired(event, from, to); end
253
+ end
254
+
255
+ it 'should call it for successful bang fire' do
256
+ expect(@foo).to receive(:aasm_event_fired).with(:close, :open, :closed)
257
+ @foo.close!
258
+ end
259
+
260
+ it 'should call it for successful non-bang fire' do
261
+ expect(@foo).to receive(:aasm_event_fired)
262
+ @foo.close
263
+ end
264
+
265
+ it 'should not call it for failing bang fire' do
266
+ allow(@foo.aasm(:left)).to receive(:set_current_state_with_persistence).and_return(false)
267
+ expect(@foo).not_to receive(:aasm_event_fired)
268
+ @foo.close!
269
+ end
270
+ end
271
+
272
+ describe "with aasm_event_failed defined" do
273
+ before do
274
+ @foo = FooMultiple.new
275
+ def @foo.aasm_event_failed(event, from); end
276
+ end
277
+
278
+ it 'should call it when transition failed for bang fire' do
279
+ expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
280
+ expect {@foo.null!}.to raise_error(AASM::InvalidTransition)
281
+ end
282
+
283
+ it 'should call it when transition failed for non-bang fire' do
284
+ expect(@foo).to receive(:aasm_event_failed).with(:null, :open)
285
+ expect {@foo.null}.to raise_error(AASM::InvalidTransition)
286
+ end
287
+
288
+ it 'should not call it if persist fails for bang fire' do
289
+ allow(@foo.aasm(:left)).to receive(:set_current_state_with_persistence).and_return(false)
290
+ expect(@foo).to receive(:aasm_event_failed)
291
+ @foo.close!
292
+ end
293
+ end
294
+
295
+ end # event callbacks
@@ -52,7 +52,7 @@ describe 'callbacks for the new DSL' do
52
52
  }.to raise_error(AASM::InvalidTransition)
53
53
  end
54
54
 
55
- it "it handles private callback methods as well" do
55
+ it "handles private callback methods as well" do
56
56
  show_debug_log = false
57
57
 
58
58
  callback = Callbacks::PrivateMethod.new(:log => show_debug_log)
@@ -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