aasm 4.11.1 → 4.12.1

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +19 -16
  3. data/Appraisals +46 -0
  4. data/CHANGELOG.md +19 -0
  5. data/CONTRIBUTING.md +24 -0
  6. data/Gemfile +4 -21
  7. data/README.md +154 -39
  8. data/Rakefile +6 -1
  9. data/TESTING.md +25 -0
  10. data/aasm.gemspec +3 -0
  11. data/gemfiles/rails_3.2.gemfile +13 -0
  12. data/gemfiles/rails_4.0.gemfile +8 -9
  13. data/gemfiles/rails_4.2.gemfile +10 -9
  14. data/gemfiles/rails_4.2_mongoid_5.gemfile +5 -9
  15. data/gemfiles/rails_5.0.gemfile +8 -16
  16. data/lib/aasm/aasm.rb +9 -3
  17. data/lib/aasm/base.rb +11 -1
  18. data/lib/aasm/configuration.rb +4 -0
  19. data/lib/aasm/core/event.rb +18 -4
  20. data/lib/aasm/core/state.rb +7 -0
  21. data/lib/aasm/core/transition.rb +10 -1
  22. data/lib/aasm/instance_base.rb +0 -2
  23. data/lib/aasm/minitest/allow_event.rb +13 -0
  24. data/lib/aasm/minitest/allow_transition_to.rb +13 -0
  25. data/lib/aasm/minitest/have_state.rb +13 -0
  26. data/lib/aasm/minitest/transition_from.rb +21 -0
  27. data/lib/aasm/minitest.rb +5 -0
  28. data/lib/aasm/minitest_spec.rb +15 -0
  29. data/lib/aasm/persistence/active_record_persistence.rb +25 -101
  30. data/lib/aasm/persistence/base.rb +7 -3
  31. data/lib/aasm/persistence/mongoid_persistence.rb +25 -31
  32. data/lib/aasm/persistence/orm.rb +142 -0
  33. data/lib/aasm/persistence/redis_persistence.rb +16 -11
  34. data/lib/aasm/persistence/sequel_persistence.rb +36 -63
  35. data/lib/aasm/persistence.rb +0 -3
  36. data/lib/aasm/state_machine.rb +4 -2
  37. data/lib/aasm/state_machine_store.rb +5 -2
  38. data/lib/aasm/version.rb +1 -1
  39. data/lib/generators/active_record/templates/migration.rb +1 -1
  40. data/lib/generators/active_record/templates/migration_existing.rb +1 -1
  41. data/lib/motion-aasm.rb +2 -1
  42. data/spec/generators/active_record_generator_spec.rb +42 -39
  43. data/spec/generators/mongoid_generator_spec.rb +4 -6
  44. data/spec/models/active_record/complex_active_record_example.rb +5 -1
  45. data/spec/models/{invalid_persistor.rb → active_record/invalid_persistor.rb} +0 -2
  46. data/spec/models/{silent_persistor.rb → active_record/silent_persistor.rb} +0 -2
  47. data/spec/models/{transactor.rb → active_record/transactor.rb} +0 -2
  48. data/spec/models/{validator.rb → active_record/validator.rb} +0 -2
  49. data/spec/models/callbacks/basic.rb +5 -2
  50. data/spec/models/guard_with_params.rb +1 -1
  51. data/spec/models/guardian_without_from_specified.rb +18 -0
  52. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  53. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  54. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  55. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  56. data/spec/models/namespaced_multiple_example.rb +14 -0
  57. data/spec/models/parametrised_event.rb +7 -0
  58. data/spec/models/{mongo_mapper/complex_mongo_mapper_example.rb → redis/complex_redis_example.rb} +8 -5
  59. data/spec/models/redis/redis_multiple.rb +20 -0
  60. data/spec/models/redis/redis_simple.rb +20 -0
  61. data/spec/models/sequel/complex_sequel_example.rb +4 -3
  62. data/spec/models/sequel/invalid_persistor.rb +52 -0
  63. data/spec/models/sequel/sequel_multiple.rb +13 -13
  64. data/spec/models/sequel/sequel_simple.rb +13 -12
  65. data/spec/models/sequel/silent_persistor.rb +50 -0
  66. data/spec/models/sequel/transactor.rb +112 -0
  67. data/spec/models/sequel/validator.rb +93 -0
  68. data/spec/models/sequel/worker.rb +12 -0
  69. data/spec/models/simple_multiple_example.rb +12 -0
  70. data/spec/models/sub_class.rb +34 -0
  71. data/spec/spec_helper.rb +0 -33
  72. data/spec/spec_helpers/active_record.rb +7 -0
  73. data/spec/spec_helpers/dynamoid.rb +33 -0
  74. data/spec/spec_helpers/mongoid.rb +7 -0
  75. data/spec/spec_helpers/redis.rb +15 -0
  76. data/spec/spec_helpers/remove_warnings.rb +1 -0
  77. data/spec/spec_helpers/sequel.rb +7 -0
  78. data/spec/unit/api_spec.rb +76 -73
  79. data/spec/unit/callbacks_spec.rb +5 -0
  80. data/spec/unit/event_spec.rb +12 -0
  81. data/spec/unit/guard_spec.rb +17 -0
  82. data/spec/unit/guard_with_params_spec.rb +4 -0
  83. data/spec/unit/guard_without_from_specified_spec.rb +10 -0
  84. data/spec/unit/localizer_spec.rb +55 -53
  85. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  86. data/spec/unit/namespaced_multiple_example_spec.rb +22 -0
  87. data/spec/unit/override_warning_spec.rb +8 -0
  88. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +453 -449
  89. data/spec/unit/persistence/active_record_persistence_spec.rb +524 -502
  90. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +4 -9
  91. data/spec/unit/persistence/dynamoid_persistence_spec.rb +4 -9
  92. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +83 -9
  93. data/spec/unit/persistence/mongoid_persistence_spec.rb +85 -9
  94. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
  95. data/spec/unit/persistence/redis_persistence_spec.rb +8 -32
  96. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +6 -11
  97. data/spec/unit/persistence/sequel_persistence_spec.rb +278 -10
  98. data/spec/unit/simple_multiple_example_spec.rb +28 -0
  99. data/spec/unit/subclassing_multiple_spec.rb +37 -2
  100. data/spec/unit/subclassing_spec.rb +17 -2
  101. data/test/minitest_helper.rb +57 -0
  102. data/test/unit/minitest_matcher_test.rb +80 -0
  103. metadata +99 -28
  104. data/gemfiles/rails_3.2_stable.gemfile +0 -15
  105. data/gemfiles/rails_4.0_mongo_mapper.gemfile +0 -16
  106. data/gemfiles/rails_4.2_mongo_mapper.gemfile +0 -17
  107. data/lib/aasm/persistence/mongo_mapper_persistence.rb +0 -163
  108. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +0 -21
  109. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +0 -23
  110. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +0 -25
  111. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +0 -149
  112. data/spec/unit/persistence/mongo_mapper_persistence_spec.rb +0 -96
  113. /data/spec/models/{worker.rb → active_record/worker.rb} +0 -0
@@ -1,15 +1,13 @@
1
- describe 'sequel' do
2
- begin
3
- require 'sequel'
4
- require 'logger'
5
- require 'spec_helper'
1
+ require 'spec_helper'
2
+ if defined?(Sequel)
3
+ describe 'sequel' do
6
4
 
7
5
  Dir[File.dirname(__FILE__) + "/../../models/sequel/*.rb"].sort.each do |f|
8
6
  require File.expand_path(f)
9
7
  end
10
8
 
11
9
  before(:all) do
12
- @model = SequelSimple
10
+ @model = Sequel::Simple
13
11
  end
14
12
 
15
13
  describe "instance methods" do
@@ -92,9 +90,279 @@ describe 'sequel' do
92
90
  end
93
91
  end
94
92
 
95
- rescue LoadError
96
- puts "------------------------------------------------------------------------"
97
- puts "Not running Sequel specs because sequel gem is not installed!!!"
98
- puts "------------------------------------------------------------------------"
93
+ describe 'transitions with persistence' do
94
+
95
+ it "should work for valid models" do
96
+ valid_object = Sequel::Validator.create(:name => 'name')
97
+ expect(valid_object).to be_sleeping
98
+ valid_object.status = :running
99
+ expect(valid_object).to be_running
100
+ end
101
+
102
+ it 'should not store states for invalid models' do
103
+ validator = Sequel::Validator.create(:name => 'name')
104
+ expect(validator).to be_valid
105
+ expect(validator).to be_sleeping
106
+
107
+ validator.name = nil
108
+ expect(validator).not_to be_valid
109
+ expect { validator.run! }.to raise_error(Sequel::ValidationFailed)
110
+ expect(validator).to be_sleeping
111
+
112
+ validator.reload
113
+ expect(validator).not_to be_running
114
+ expect(validator).to be_sleeping
115
+
116
+ validator.name = 'another name'
117
+ expect(validator).to be_valid
118
+ expect(validator.run!).to be_truthy
119
+ expect(validator).to be_running
120
+
121
+ validator.reload
122
+ expect(validator).to be_running
123
+ expect(validator).not_to be_sleeping
124
+ end
125
+
126
+ it 'should not store states for invalid models silently if configured' do
127
+ validator = Sequel::SilentPersistor.create(:name => 'name')
128
+ expect(validator).to be_valid
129
+ expect(validator).to be_sleeping
130
+
131
+ validator.name = nil
132
+ expect(validator).not_to be_valid
133
+ expect(validator.run!).to be_falsey
134
+ expect(validator).to be_sleeping
135
+
136
+ validator.reload
137
+ expect(validator).not_to be_running
138
+ expect(validator).to be_sleeping
139
+
140
+ validator.name = 'another name'
141
+ expect(validator).to be_valid
142
+ expect(validator.run!).to be_truthy
143
+ expect(validator).to be_running
144
+
145
+ validator.reload
146
+ expect(validator).to be_running
147
+ expect(validator).not_to be_sleeping
148
+ end
149
+
150
+ it 'should store states for invalid models if configured' do
151
+ persistor = Sequel::InvalidPersistor.create(:name => 'name')
152
+ expect(persistor).to be_valid
153
+ expect(persistor).to be_sleeping
154
+
155
+ persistor.name = nil
156
+ expect(persistor).not_to be_valid
157
+ expect(persistor.run!).to be_truthy
158
+ expect(persistor).to be_running
159
+
160
+ persistor = Sequel::InvalidPersistor[persistor.id]
161
+ persistor.valid?
162
+ expect(persistor).to be_valid
163
+ expect(persistor).to be_running
164
+ expect(persistor).not_to be_sleeping
165
+
166
+ persistor.reload
167
+ expect(persistor).to be_running
168
+ expect(persistor).not_to be_sleeping
169
+ end
170
+
171
+ describe 'pessimistic locking' do
172
+ let(:worker) { Sequel::Worker.create(:name => 'worker', :status => 'sleeping') }
173
+
174
+ subject { transactor.run! }
175
+
176
+ context 'no lock' do
177
+ let(:transactor) { Sequel::NoLockTransactor.create(:name => 'no_lock_transactor', :worker => worker) }
178
+
179
+ it 'should not invoke lock!' do
180
+ expect(transactor).to_not receive(:lock!)
181
+ subject
182
+ end
183
+ end
184
+
185
+ context 'a default lock' do
186
+ let(:transactor) { Sequel::LockTransactor.create(:name => 'lock_transactor', :worker => worker) }
187
+
188
+ it 'should invoke lock!' do
189
+ expect(transactor).to receive(:lock!).and_call_original
190
+ subject
191
+ end
192
+ end
193
+
194
+ context 'a FOR UPDATE NOWAIT lock' do
195
+ let(:transactor) { Sequel::LockNoWaitTransactor.create(:name => 'lock_no_wait_transactor', :worker => worker) }
196
+
197
+ it 'should invoke lock! with FOR UPDATE NOWAIT' do
198
+ # TODO: With and_call_original, get an error with syntax, should look into it.
199
+ expect(transactor).to receive(:lock!).with('FOR UPDATE NOWAIT')# .and_call_original
200
+ subject
201
+ end
202
+ end
203
+ end
204
+
205
+ describe 'transactions' do
206
+ let(:worker) { Sequel::Worker.create(:name => 'worker', :status => 'sleeping') }
207
+ let(:transactor) { Sequel::Transactor.create(:name => 'transactor', :worker => worker) }
208
+
209
+ it 'should rollback all changes' do
210
+ expect(transactor).to be_sleeping
211
+ expect(worker.status).to eq('sleeping')
212
+
213
+ expect {transactor.run!}.to raise_error(StandardError, 'failed on purpose')
214
+ expect(transactor).to be_running
215
+ expect(worker.reload.status).to eq('sleeping')
216
+ end
217
+
218
+ context "nested transactions" do
219
+ it "should rollback all changes in nested transaction" do
220
+ expect(transactor).to be_sleeping
221
+ expect(worker.status).to eq('sleeping')
222
+
223
+ Sequel::Worker.db.transaction do
224
+ expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
225
+ end
226
+
227
+ expect(transactor).to be_running
228
+ expect(worker.reload.status).to eq('sleeping')
229
+ end
230
+
231
+ it "should only rollback changes in the main transaction not the nested one" do
232
+ # change configuration to not require new transaction
233
+ AASM::StateMachineStore[Sequel::Transactor][:default].config.requires_new_transaction = false
234
+
235
+ expect(transactor).to be_sleeping
236
+ expect(worker.status).to eq('sleeping')
237
+ Sequel::Worker.db.transaction do
238
+ expect { transactor.run! }.to raise_error(StandardError, 'failed on purpose')
239
+ end
240
+ expect(transactor).to be_running
241
+ expect(worker.reload.status).to eq('running')
242
+ end
243
+ end
244
+
245
+ describe "after_commit callback" do
246
+ it "should fire :after_commit if transaction was successful" do
247
+ validator = Sequel::Validator.create(:name => 'name')
248
+ expect(validator).to be_sleeping
249
+
250
+ validator.run!
251
+ expect(validator).to be_running
252
+ expect(validator.name).to eq("name changed")
253
+
254
+ validator.sleep!("sleeper")
255
+ expect(validator).to be_sleeping
256
+ expect(validator.name).to eq("sleeper")
257
+ end
258
+
259
+ it "should not fire :after_commit if transaction failed" do
260
+ validator = Sequel::Validator.create(:name => 'name')
261
+ expect { validator.fail! }.to raise_error(StandardError, 'failed on purpose')
262
+ expect(validator.name).to eq("name")
263
+ end
264
+
265
+ it "should not fire :after_commit if validation failed when saving object" do
266
+ validator = Sequel::Validator.create(:name => 'name')
267
+ validator.invalid = true
268
+ expect { validator.run! }.to raise_error(Sequel::ValidationFailed, 'validator invalid')
269
+ expect(validator).to be_sleeping
270
+ expect(validator.name).to eq("name")
271
+ end
272
+
273
+ it "should not fire if not saving" do
274
+ validator = Sequel::Validator.create(:name => 'name')
275
+ expect(validator).to be_sleeping
276
+ validator.run
277
+ expect(validator).to be_running
278
+ expect(validator.name).to eq("name")
279
+ end
280
+ end
281
+
282
+ describe 'before and after transaction callbacks' do
283
+ [:after, :before].each do |event_type|
284
+ describe "#{event_type}_transaction callback" do
285
+ it "should fire :#{event_type}_transaction if transaction was successful" do
286
+ validator = Sequel::Validator.create(:name => 'name')
287
+ expect(validator).to be_sleeping
288
+
289
+ expect { validator.run! }.to change { validator.send("#{event_type}_transaction_performed_on_run") }.from(nil).to(true)
290
+ expect(validator).to be_running
291
+ end
292
+
293
+ it "should fire :#{event_type}_transaction if transaction failed" do
294
+ validator = Sequel::Validator.create(:name => 'name')
295
+ expect do
296
+ begin
297
+ validator.fail!
298
+ rescue => ignored
299
+ end
300
+ end.to change { validator.send("#{event_type}_transaction_performed_on_fail") }.from(nil).to(true)
301
+ expect(validator).to_not be_running
302
+ end
303
+
304
+ it "should not fire :#{event_type}_transaction if not saving" do
305
+ validator = Sequel::Validator.create(:name => 'name')
306
+ expect(validator).to be_sleeping
307
+ expect { validator.run }.to_not change { validator.send("#{event_type}_transaction_performed_on_run") }
308
+ expect(validator).to be_running
309
+ expect(validator.name).to eq("name")
310
+ end
311
+ end
312
+ end
313
+ end
314
+
315
+ describe 'before and after all transactions callbacks' do
316
+ [:after, :before].each do |event_type|
317
+ describe "#{event_type}_all_transactions callback" do
318
+ it "should fire :#{event_type}_all_transactions if transaction was successful" do
319
+ validator = Sequel::Validator.create(:name => 'name')
320
+ expect(validator).to be_sleeping
321
+
322
+ expect { validator.run! }.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
323
+ expect(validator).to be_running
324
+ end
325
+
326
+ it "should fire :#{event_type}_all_transactions if transaction failed" do
327
+ validator = Sequel::Validator.create(:name => 'name')
328
+ expect do
329
+ begin
330
+ validator.fail!
331
+ rescue => ignored
332
+ end
333
+ end.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
334
+ expect(validator).to_not be_running
335
+ end
336
+
337
+ it "should not fire :#{event_type}_all_transactions if not saving" do
338
+ validator = Sequel::Validator.create(:name => 'name')
339
+ expect(validator).to be_sleeping
340
+ expect { validator.run }.to_not change { validator.send("#{event_type}_all_transactions_performed") }
341
+ expect(validator).to be_running
342
+ expect(validator.name).to eq("name")
343
+ end
344
+ end
345
+ end
346
+ end
347
+
348
+ context "when not persisting" do
349
+ it 'should not rollback all changes' do
350
+ expect(transactor).to be_sleeping
351
+ expect(worker.status).to eq('sleeping')
352
+
353
+ # Notice here we're calling "run" and not "run!" with a bang.
354
+ expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
355
+ expect(transactor).to be_running
356
+ expect(worker.reload.status).to eq('running')
357
+ end
358
+
359
+ it 'should not create a database transaction' do
360
+ expect(transactor.class).not_to receive(:transaction)
361
+ expect {transactor.run}.to raise_error(StandardError, 'failed on purpose')
362
+ end
363
+ end
364
+ end
365
+ end
366
+
99
367
  end
100
368
  end
@@ -60,4 +60,32 @@ describe 'state machine' do
60
60
  expect(SimpleMultipleExample::STATE_PROCESSING).to eq(:processing)
61
61
  expect(SimpleMultipleExample::STATE_RUNNING).to eq(:running)
62
62
  end
63
+
64
+ context 'triggers binding_events in bindind_state_machine' do
65
+ it 'does persist' do
66
+ expect(simple).to be_sleeping
67
+ expect(simple).to be_answered
68
+ expect(simple).to receive(:start!).and_call_original
69
+ simple.ask!
70
+ expect(simple).to be_asked
71
+ expect(simple).to be_processing
72
+ expect(simple).to receive(:stop!).and_call_original
73
+ simple.answer!
74
+ expect(simple).to be_sleeping
75
+ expect(simple).to be_answered
76
+ end
77
+
78
+ it 'does not persist' do
79
+ expect(simple).to be_sleeping
80
+ expect(simple).to be_answered
81
+ expect(simple).to receive(:start).and_call_original
82
+ simple.ask
83
+ expect(simple).to be_asked
84
+ expect(simple).to be_processing
85
+ expect(simple).to receive(:stop).and_call_original
86
+ simple.answer
87
+ expect(simple).to be_sleeping
88
+ expect(simple).to be_answered
89
+ end
90
+ end
63
91
  end
@@ -19,7 +19,7 @@ describe 'subclassing with multiple state machines' do
19
19
  expect(SuperClassMultiple.aasm(:right).states).not_to include(:archived)
20
20
  end
21
21
 
22
- it "should have the same events as its parent" do
22
+ it 'should have the same events as its parent' do
23
23
  expect(SubClassMultiple.aasm(:left).events).to eq(SuperClassMultiple.aasm(:left).events)
24
24
  expect(SubClassMultiple.aasm(:right).events).to eq(SuperClassMultiple.aasm(:right).events)
25
25
  end
@@ -35,5 +35,40 @@ describe 'subclassing with multiple state machines' do
35
35
  expect(son.aasm(:left).current_state).to eq(:ended)
36
36
  end
37
37
 
38
- end
38
+ it 'should allow the child to modify its left state machine' do
39
+ son = SubClassMultiple.new
40
+ expect(son.left_called_after).to eq(nil)
41
+ expect(son.right_called_after).to eq(nil)
42
+ son.foo
43
+ expect(son.left_called_after).to eq(true)
44
+ expect(son.right_called_after).to eq(nil)
45
+ global_callbacks = SubClassMultiple.aasm(:left).state_machine.global_callbacks
46
+ expect(global_callbacks).to_not be_empty
47
+ expect(global_callbacks[:after_all_transitions]).to eq :left_after_all_event
48
+ end
49
+
50
+ it 'should allow the child to modify its right state machine' do
51
+ son = SubClassMultiple.new
52
+ expect(son.right_called_after).to eq(nil)
53
+ expect(son.left_called_after).to eq(nil)
54
+ son.close
55
+ expect(son.right_called_after).to eq(true)
56
+ expect(son.left_called_after).to eq(nil)
57
+ global_callbacks = SubClassMultiple.aasm(:right).state_machine.global_callbacks
58
+ expect(global_callbacks).to_not be_empty
59
+ expect(global_callbacks[:after_all_transitions]).to eq :right_after_all_event
60
+ end
39
61
 
62
+ it 'should not modify the parent left state machine' do
63
+ super_class_event = SuperClassMultiple.aasm(:left).events.select { |event| event.name == :foo }.first
64
+ expect(super_class_event.options).to be_empty
65
+ expect(SuperClassMultiple.aasm(:left).state_machine.global_callbacks).to be_empty
66
+ end
67
+
68
+ it 'should not modify the parent right state machine' do
69
+ super_class_event = SuperClassMultiple.aasm(:right).events.select { |event| event.name == :close }.first
70
+ expect(super_class_event.options).to be_empty
71
+ expect(SuperClassMultiple.aasm(:right).state_machine.global_callbacks).to be_empty
72
+ end
73
+
74
+ end
@@ -13,7 +13,7 @@ describe 'subclassing' do
13
13
  expect(SuperClass.aasm.states).not_to include(:foo)
14
14
  end
15
15
 
16
- it "should have the same events as its parent" do
16
+ it 'should have the same events as its parent' do
17
17
  expect(SubClass.aasm.events).to eq(SuperClass.aasm.events)
18
18
  end
19
19
 
@@ -27,5 +27,20 @@ describe 'subclassing' do
27
27
  expect(son.aasm.current_state).to eq(:ended)
28
28
  end
29
29
 
30
- end
30
+ it 'should allow the child to modify its state machine' do
31
+ son = SubClass.new
32
+ expect(son.called_after).to eq(nil)
33
+ son.foo
34
+ expect(son.called_after).to eq(true)
35
+ global_callbacks = SubClass.aasm.state_machine.global_callbacks
36
+ expect(global_callbacks).to_not be_empty
37
+ expect(global_callbacks[:after_all_transitions]).to eq :after_all_event
38
+ end
31
39
 
40
+ it 'should not modify the parent state machine' do
41
+ super_class_event = SuperClass.aasm.events.select { |event| event.name == :foo }.first
42
+ expect(super_class_event.options).to be_empty
43
+ expect(SuperClass.aasm.state_machine.global_callbacks).to be_empty
44
+ end
45
+
46
+ end
@@ -0,0 +1,57 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
2
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec', 'models')))
3
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
4
+ require 'aasm'
5
+ require 'minitest/autorun'
6
+ require 'aasm/minitest_spec'
7
+ require 'pry'
8
+
9
+ # require 'ruby-debug'; Debugger.settings[:autoeval] = true; debugger; rubys_debugger = 'annoying'
10
+ # require 'ruby-debug/completion'
11
+ # require 'pry'
12
+
13
+ SEQUEL_DB = defined?(JRUBY_VERSION) ? 'jdbc:sqlite::memory:' : 'sqlite:/'
14
+
15
+ def load_schema
16
+ require 'logger'
17
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
18
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
19
+ ActiveRecord::Base.establish_connection(config['sqlite3'])
20
+ require File.dirname(__FILE__) + "/database.rb"
21
+ end
22
+
23
+ # Dynamoid initialization
24
+ begin
25
+ require 'dynamoid'
26
+ require 'aws-sdk-resources'
27
+
28
+ ENV['ACCESS_KEY'] ||= 'abcd'
29
+ ENV['SECRET_KEY'] ||= '1234'
30
+
31
+ Aws.config.update({
32
+ region: 'us-west-2',
33
+ credentials: Aws::Credentials.new(ENV['ACCESS_KEY'], ENV['SECRET_KEY'])
34
+ })
35
+
36
+ Dynamoid.configure do |config|
37
+ config.namespace = "dynamoid_tests"
38
+ config.endpoint = 'http://127.0.0.1:30180'
39
+ config.warn_on_scan = false
40
+ end
41
+
42
+ Dynamoid.logger.level = Logger::FATAL
43
+
44
+ class Minitest::Spec
45
+ before do
46
+ Dynamoid.adapter.list_tables.each do |table|
47
+ Dynamoid.adapter.delete_table(table) if table =~ /^#{Dynamoid::Config.namespace}/
48
+ end
49
+ Dynamoid.adapter.tables.clear
50
+ end
51
+ end
52
+ rescue LoadError
53
+ # Without Dynamoid settings
54
+ end
55
+
56
+ # example model classes
57
+ Dir[File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec', 'models')) + '/*.rb'].sort.each { |f| require File.expand_path(f) }
@@ -0,0 +1,80 @@
1
+ require 'minitest_helper'
2
+
3
+ class StateMachineTest < Minitest::Spec
4
+
5
+ let(:simple) { SimpleExample.new }
6
+ let(:multiple) { SimpleMultipleExample.new }
7
+
8
+ describe 'transition_from' do
9
+ it "works for simple state machines" do
10
+ simple.must_transition_from :initialised, to: :filled_out, on_event: :fill_out
11
+ simple.wont_transition_from :initialised, to: :authorised, on_event: :fill_out
12
+ end
13
+
14
+ it "works for multiple state machines" do
15
+ multiple.must_transition_from :standing, to: :walking, on_event: :walk, on: :move
16
+ multiple.wont_transition_from :standing, to: :running, on_event: :walk, on: :move
17
+
18
+ multiple.must_transition_from :sleeping, to: :processing, on_event: :start, on: :work
19
+ multiple.wont_transition_from :sleeping, to: :sleeping, on_event: :start, on: :work
20
+ end
21
+ end
22
+
23
+ describe 'allow_transition_to' do
24
+ it "works for simple state machines" do
25
+ simple.must_allow_transition_to :filled_out
26
+ simple.wont_allow_transition_to :authorised
27
+ end
28
+
29
+ it "works for multiple state machines" do
30
+ multiple.must_allow_transition_to :walking, on: :move
31
+ multiple.wont_allow_transition_to :standing, on: :move
32
+
33
+ multiple.must_allow_transition_to :processing, on: :work
34
+ multiple.wont_allow_transition_to :sleeping, on: :work
35
+ end
36
+ end
37
+
38
+ describe "have_state" do
39
+ it "works for simple state machines" do
40
+ simple.must_have_state :initialised
41
+ simple.wont_have_state :filled_out
42
+ simple.fill_out
43
+ simple.must_have_state :filled_out
44
+ end
45
+
46
+ it "works for multiple state machines" do
47
+ multiple.must_have_state :standing, on: :move
48
+ multiple.wont_have_state :walking, on: :move
49
+ multiple.walk
50
+ multiple.must_have_state :walking, on: :move
51
+
52
+ multiple.must_have_state :sleeping, on: :work
53
+ multiple.wont_have_state :processing, on: :work
54
+ multiple.start
55
+ multiple.must_have_state :processing, on: :work
56
+ end
57
+ end
58
+
59
+ describe "allow_event" do
60
+ it "works for simple state machines" do
61
+ simple.must_allow_event :fill_out
62
+ simple.wont_allow_event :authorise
63
+ simple.fill_out
64
+ simple.must_allow_event :authorise
65
+ end
66
+
67
+ it "works for multiple state machines" do
68
+ multiple.must_allow_event :walk, on: :move
69
+ multiple.wont_allow_event :hold, on: :move
70
+ multiple.walk
71
+ multiple.must_allow_event :hold, on: :move
72
+
73
+ multiple.must_allow_event :start, on: :work
74
+ multiple.wont_allow_event :stop, on: :work
75
+ multiple.start
76
+ multiple.must_allow_event :stop, on: :work
77
+ end
78
+ end
79
+
80
+ end