aasm 4.2.0 → 4.3.0

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