state_machine 0.7.6 → 0.8.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.
- data/CHANGELOG.rdoc +17 -0
- data/Rakefile +1 -1
- data/lib/state_machine.rb +11 -8
- data/lib/state_machine/callback.rb +1 -1
- data/lib/state_machine/event.rb +9 -8
- data/lib/state_machine/event_collection.rb +21 -10
- data/lib/state_machine/extensions.rb +2 -11
- data/lib/state_machine/guard.rb +12 -1
- data/lib/state_machine/integrations/active_record.rb +37 -1
- data/lib/state_machine/integrations/data_mapper.rb +17 -2
- data/lib/state_machine/integrations/sequel.rb +32 -1
- data/lib/state_machine/machine.rb +56 -16
- data/lib/state_machine/machine_collection.rb +7 -5
- data/lib/state_machine/state.rb +1 -1
- data/lib/state_machine/transition.rb +41 -14
- data/test/unit/assertions_test.rb +3 -3
- data/test/unit/eval_helpers_test.rb +13 -22
- data/test/unit/event_collection_test.rb +24 -0
- data/test/unit/event_test.rb +94 -0
- data/test/unit/guard_test.rb +46 -0
- data/test/unit/integrations/active_record_test.rb +247 -18
- data/test/unit/integrations/data_mapper_test.rb +143 -1
- data/test/unit/integrations/sequel_test.rb +279 -10
- data/test/unit/machine_collection_test.rb +42 -19
- data/test/unit/machine_test.rb +55 -0
- data/test/unit/state_test.rb +1 -1
- data/test/unit/transition_test.rb +106 -7
- metadata +2 -2
data/test/unit/guard_test.rb
CHANGED
@@ -404,6 +404,52 @@ class GuardWithMultipleExceptOnRequirementsTest < Test::Unit::TestCase
|
|
404
404
|
end
|
405
405
|
end
|
406
406
|
|
407
|
+
class GuardWithFailuresExcludedTest < Test::Unit::TestCase
|
408
|
+
def setup
|
409
|
+
@object = Object.new
|
410
|
+
@guard = StateMachine::Guard.new(:include_failures => false)
|
411
|
+
end
|
412
|
+
|
413
|
+
def test_should_use_a_blacklist_matcher
|
414
|
+
assert_instance_of StateMachine::WhitelistMatcher, @guard.success_requirement
|
415
|
+
end
|
416
|
+
|
417
|
+
def test_should_match_if_not_specified
|
418
|
+
assert @guard.matches?(@object)
|
419
|
+
end
|
420
|
+
|
421
|
+
def test_should_match_if_true
|
422
|
+
assert @guard.matches?(@object, :success => true)
|
423
|
+
end
|
424
|
+
|
425
|
+
def test_should_not_match_if_false
|
426
|
+
assert !@guard.matches?(@object, :success => false)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
class GuardWithFailuresIncludedTest < Test::Unit::TestCase
|
431
|
+
def setup
|
432
|
+
@object = Object.new
|
433
|
+
@guard = StateMachine::Guard.new(:include_failures => true)
|
434
|
+
end
|
435
|
+
|
436
|
+
def test_should_use_all_matcher
|
437
|
+
assert_equal StateMachine::AllMatcher.instance, @guard.success_requirement
|
438
|
+
end
|
439
|
+
|
440
|
+
def test_should_match_if_not_specified
|
441
|
+
assert @guard.matches?(@object)
|
442
|
+
end
|
443
|
+
|
444
|
+
def test_should_match_if_true
|
445
|
+
assert @guard.matches?(@object, :success => true)
|
446
|
+
end
|
447
|
+
|
448
|
+
def test_should_match_if_false
|
449
|
+
assert @guard.matches?(@object, :success => false)
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
407
453
|
class GuardWithConflictingFromRequirementsTest < Test::Unit::TestCase
|
408
454
|
def test_should_raise_an_exception
|
409
455
|
exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:from => :parked, :except_from => :parked) }
|
@@ -168,15 +168,14 @@ begin
|
|
168
168
|
|
169
169
|
@machine.invalidate(record, :state, :invalid_transition, [[:event, :park]])
|
170
170
|
|
171
|
-
|
172
|
-
assert_equal 'cannot transition via "park"', record.errors.on(:state)
|
171
|
+
assert_equal ['State cannot transition via "park"'], record.errors.full_messages
|
173
172
|
end
|
174
173
|
|
175
174
|
def test_should_auto_prefix_custom_attributes_on_invalidation
|
176
175
|
record = @model.new
|
177
176
|
@machine.invalidate(record, :event, :invalid)
|
178
177
|
|
179
|
-
assert_equal 'is invalid', record.errors.
|
178
|
+
assert_equal ['State event is invalid'], record.errors.full_messages
|
180
179
|
end
|
181
180
|
|
182
181
|
def test_should_clear_errors_on_reset
|
@@ -185,7 +184,7 @@ begin
|
|
185
184
|
record.errors.add(:state, 'is invalid')
|
186
185
|
|
187
186
|
@machine.reset(record)
|
188
|
-
|
187
|
+
assert_equal [], record.errors.full_messages
|
189
188
|
end
|
190
189
|
|
191
190
|
def test_should_not_override_the_column_reader
|
@@ -229,15 +228,126 @@ begin
|
|
229
228
|
end
|
230
229
|
end
|
231
230
|
|
232
|
-
class
|
231
|
+
class MachineWithStaticInitialStateTest < ActiveRecord::TestCase
|
233
232
|
def setup
|
234
|
-
@model = new_model
|
233
|
+
@model = new_model do
|
234
|
+
attr_accessor :value
|
235
|
+
end
|
235
236
|
@machine = StateMachine::Machine.new(@model, :initial => :parked)
|
236
|
-
@record = @model.new
|
237
237
|
end
|
238
238
|
|
239
239
|
def test_should_set_initial_state_on_created_object
|
240
|
-
|
240
|
+
record = @model.new
|
241
|
+
assert_equal 'parked', record.state
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_should_still_set_attributes
|
245
|
+
record = @model.new(:value => 1)
|
246
|
+
assert_equal 1, record.value
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_should_still_allow_initialize_blocks
|
250
|
+
block_args = nil
|
251
|
+
record = @model.new do |*args|
|
252
|
+
block_args = args
|
253
|
+
end
|
254
|
+
|
255
|
+
assert_equal [record], block_args
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_should_set_attributes_prior_to_after_initialize_hook
|
259
|
+
state = nil
|
260
|
+
@model.class_eval do
|
261
|
+
define_method(:after_initialize) do
|
262
|
+
state = self.state
|
263
|
+
end
|
264
|
+
end
|
265
|
+
@model.new
|
266
|
+
assert_equal 'parked', state
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_should_set_initial_state_before_setting_attributes
|
270
|
+
@model.class_eval do
|
271
|
+
attr_accessor :state_during_setter
|
272
|
+
|
273
|
+
define_method(:value=) do |value|
|
274
|
+
self.state_during_setter = state
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
record = @model.new(:value => 1)
|
279
|
+
assert_equal 'parked', record.state_during_setter
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_should_not_set_initial_state_after_already_initialized
|
283
|
+
record = @model.new(:value => 1)
|
284
|
+
assert_equal 'parked', record.state
|
285
|
+
|
286
|
+
record.state = 'idling'
|
287
|
+
record.attributes = {}
|
288
|
+
assert_equal 'idling', record.state
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
class MachineWithDynamicInitialStateTest < ActiveRecord::TestCase
|
293
|
+
def setup
|
294
|
+
@model = new_model do
|
295
|
+
attr_accessor :value
|
296
|
+
end
|
297
|
+
@machine = StateMachine::Machine.new(@model, :initial => lambda {|object| :parked})
|
298
|
+
@machine.state :parked
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_should_set_initial_state_on_created_object
|
302
|
+
record = @model.new
|
303
|
+
assert_equal 'parked', record.state
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_should_still_set_attributes
|
307
|
+
record = @model.new(:value => 1)
|
308
|
+
assert_equal 1, record.value
|
309
|
+
end
|
310
|
+
|
311
|
+
def test_should_still_allow_initialize_blocks
|
312
|
+
block_args = nil
|
313
|
+
record = @model.new do |*args|
|
314
|
+
block_args = args
|
315
|
+
end
|
316
|
+
|
317
|
+
assert_equal [record], block_args
|
318
|
+
end
|
319
|
+
|
320
|
+
def test_should_set_attributes_prior_to_after_initialize_hook
|
321
|
+
state = nil
|
322
|
+
@model.class_eval do
|
323
|
+
define_method(:after_initialize) do
|
324
|
+
state = self.state
|
325
|
+
end
|
326
|
+
end
|
327
|
+
@model.new
|
328
|
+
assert_equal 'parked', state
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_should_set_initial_state_after_setting_attributes
|
332
|
+
@model.class_eval do
|
333
|
+
attr_accessor :state_during_setter
|
334
|
+
|
335
|
+
define_method(:value=) do |value|
|
336
|
+
self.state_during_setter = state || 'nil'
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
record = @model.new(:value => 1)
|
341
|
+
assert_equal 'nil', record.state_during_setter
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_should_not_set_initial_state_after_already_initialized
|
345
|
+
record = @model.new(:value => 1)
|
346
|
+
assert_equal 'parked', record.state
|
347
|
+
|
348
|
+
record.state = 'idling'
|
349
|
+
record.attributes = {}
|
350
|
+
assert_equal 'idling', record.state
|
241
351
|
end
|
242
352
|
end
|
243
353
|
|
@@ -395,28 +505,31 @@ begin
|
|
395
505
|
|
396
506
|
class MachineWithCustomAttributeTest < ActiveRecord::TestCase
|
397
507
|
def setup
|
398
|
-
@model = new_model
|
399
|
-
|
508
|
+
@model = new_model do
|
509
|
+
alias_attribute :vehicle_status, :state
|
510
|
+
end
|
511
|
+
|
512
|
+
@machine = StateMachine::Machine.new(@model, :status, :attribute => :vehicle_status)
|
400
513
|
@machine.state :parked
|
401
514
|
|
402
515
|
@record = @model.new
|
403
516
|
end
|
404
517
|
|
405
518
|
def test_should_add_validation_errors_to_custom_attribute
|
406
|
-
@record.
|
519
|
+
@record.vehicle_status = 'invalid'
|
407
520
|
|
408
521
|
assert !@record.valid?
|
409
|
-
assert_equal ['
|
522
|
+
assert_equal ['Vehicle status is invalid'], @record.errors.full_messages
|
410
523
|
|
411
|
-
@record.
|
524
|
+
@record.vehicle_status = 'parked'
|
412
525
|
assert @record.valid?
|
413
526
|
end
|
414
527
|
|
415
528
|
def test_should_check_custom_attribute_for_predicate
|
416
|
-
@record.
|
529
|
+
@record.vehicle_status = nil
|
417
530
|
assert !@record.status?(:parked)
|
418
531
|
|
419
|
-
@record.
|
532
|
+
@record.vehicle_status = 'parked'
|
420
533
|
assert @record.status?(:parked)
|
421
534
|
end
|
422
535
|
end
|
@@ -528,9 +641,46 @@ begin
|
|
528
641
|
end
|
529
642
|
end
|
530
643
|
|
644
|
+
class MachineWithLoopbackTest < ActiveRecord::TestCase
|
645
|
+
def setup
|
646
|
+
changed_attrs = nil
|
647
|
+
|
648
|
+
@model = new_model do
|
649
|
+
connection.change_table(:foo) {|t| t.datetime(:updated_at)}
|
650
|
+
|
651
|
+
define_method(:before_update) do
|
652
|
+
changed_attrs = changed_attributes.dup
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
@machine = StateMachine::Machine.new(@model, :initial => :parked)
|
657
|
+
@machine.event :park
|
658
|
+
|
659
|
+
@record = @model.create(:updated_at => Time.now - 1)
|
660
|
+
@timestamp = @record.updated_at
|
661
|
+
|
662
|
+
@transition = StateMachine::Transition.new(@record, @machine, :park, :parked, :parked)
|
663
|
+
@transition.perform
|
664
|
+
|
665
|
+
@changed_attrs = changed_attrs
|
666
|
+
end
|
667
|
+
|
668
|
+
def test_should_include_state_in_changed_attributes
|
669
|
+
@changed_attrs.delete('updated_at')
|
670
|
+
|
671
|
+
expected = {'state' => 'parked'}
|
672
|
+
assert_equal expected, @changed_attrs
|
673
|
+
end
|
674
|
+
|
675
|
+
def test_should_update_record
|
676
|
+
assert_not_equal @timestamp, @record.updated_at
|
677
|
+
end
|
678
|
+
end
|
679
|
+
|
531
680
|
class MachineWithFailedBeforeCallbacksTest < ActiveRecord::TestCase
|
532
681
|
def setup
|
533
682
|
@before_count = 0
|
683
|
+
@after_count = 0
|
534
684
|
|
535
685
|
@model = new_model
|
536
686
|
@machine = StateMachine::Machine.new(@model)
|
@@ -538,6 +688,7 @@ begin
|
|
538
688
|
@machine.event :ignite
|
539
689
|
@machine.before_transition(lambda {@before_count += 1; false})
|
540
690
|
@machine.before_transition(lambda {@before_count += 1})
|
691
|
+
@machine.after_transition(lambda {@after_count += 1})
|
541
692
|
|
542
693
|
@record = @model.new(:state => 'parked')
|
543
694
|
@transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
|
@@ -559,6 +710,10 @@ begin
|
|
559
710
|
def test_should_not_run_further_before_callbacks
|
560
711
|
assert_equal 1, @before_count
|
561
712
|
end
|
713
|
+
|
714
|
+
def test_should_not_run_after_callbacks
|
715
|
+
assert_equal 0, @after_count
|
716
|
+
end
|
562
717
|
end
|
563
718
|
|
564
719
|
class MachineWithFailedActionTest < ActiveRecord::TestCase
|
@@ -570,6 +725,14 @@ begin
|
|
570
725
|
@machine = StateMachine::Machine.new(@model)
|
571
726
|
@machine.state :parked, :idling
|
572
727
|
@machine.event :ignite
|
728
|
+
|
729
|
+
@before_transition_called = false
|
730
|
+
@after_transition_called = false
|
731
|
+
@after_transition_with_failures_called = false
|
732
|
+
@machine.before_transition(lambda {@before_transition_called = true})
|
733
|
+
@machine.after_transition(lambda {@after_transition_called = true})
|
734
|
+
@machine.after_transition(lambda {@after_transition_with_failures_called = true}, :include_failures => true)
|
735
|
+
|
573
736
|
@record = @model.new(:state => 'parked')
|
574
737
|
@transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
|
575
738
|
@result = @transition.perform
|
@@ -586,6 +749,18 @@ begin
|
|
586
749
|
def test_should_not_save_record
|
587
750
|
assert @record.new_record?
|
588
751
|
end
|
752
|
+
|
753
|
+
def test_should_run_before_callback
|
754
|
+
assert @before_transition_called
|
755
|
+
end
|
756
|
+
|
757
|
+
def test_should_not_run_after_callback_if_not_including_failures
|
758
|
+
assert !@after_transition_called
|
759
|
+
end
|
760
|
+
|
761
|
+
def test_should_run_after_callback_if_including_failures
|
762
|
+
assert @after_transition_with_failures_called
|
763
|
+
end
|
589
764
|
end
|
590
765
|
|
591
766
|
class MachineWithValidationsTest < ActiveRecord::TestCase
|
@@ -722,6 +897,32 @@ begin
|
|
722
897
|
@record.valid?
|
723
898
|
assert !ran_callback
|
724
899
|
end
|
900
|
+
|
901
|
+
def test_should_not_run_after_callbacks_with_failures_disabled_if_validation_fails
|
902
|
+
@model.class_eval do
|
903
|
+
attr_accessor :seatbelt
|
904
|
+
validates_presence_of :seatbelt
|
905
|
+
end
|
906
|
+
|
907
|
+
ran_callback = false
|
908
|
+
@machine.after_transition { ran_callback = true }
|
909
|
+
|
910
|
+
@record.valid?
|
911
|
+
assert !ran_callback
|
912
|
+
end
|
913
|
+
|
914
|
+
def test_should_run_after_callbacks_with_failures_enabled_if_validation_fails
|
915
|
+
@model.class_eval do
|
916
|
+
attr_accessor :seatbelt
|
917
|
+
validates_presence_of :seatbelt
|
918
|
+
end
|
919
|
+
|
920
|
+
ran_callback = false
|
921
|
+
@machine.after_transition(:include_failures => true) { ran_callback = true }
|
922
|
+
|
923
|
+
@record.valid?
|
924
|
+
assert ran_callback
|
925
|
+
end
|
725
926
|
end
|
726
927
|
|
727
928
|
class MachineWithEventAttributesOnSaveBangTest < ActiveRecord::TestCase
|
@@ -759,6 +960,14 @@ begin
|
|
759
960
|
assert ran_callback
|
760
961
|
end
|
761
962
|
|
963
|
+
def test_should_run_before_callbacks_once
|
964
|
+
before_count = 0
|
965
|
+
@machine.before_transition { before_count += 1 }
|
966
|
+
|
967
|
+
@record.save!
|
968
|
+
assert_equal 1, before_count
|
969
|
+
end
|
970
|
+
|
762
971
|
def test_should_persist_new_state
|
763
972
|
@record.save!
|
764
973
|
assert_equal 'idling', @record.state
|
@@ -771,6 +980,26 @@ begin
|
|
771
980
|
@record.save!
|
772
981
|
assert ran_callback
|
773
982
|
end
|
983
|
+
|
984
|
+
def test_should_not_run_after_callbacks_with_failures_disabled_if_fails
|
985
|
+
@model.before_create {|record| false}
|
986
|
+
|
987
|
+
ran_callback = false
|
988
|
+
@machine.after_transition { ran_callback = true }
|
989
|
+
|
990
|
+
begin; @record.save!; rescue; end
|
991
|
+
assert !ran_callback
|
992
|
+
end
|
993
|
+
|
994
|
+
def test_should_run_after_callbacks_with_failures_enabled_if_fails
|
995
|
+
@model.before_create {|record| false}
|
996
|
+
|
997
|
+
ran_callback = false
|
998
|
+
@machine.after_transition(:include_failures => true) { ran_callback = true }
|
999
|
+
|
1000
|
+
begin; @record.save!; rescue; end
|
1001
|
+
assert ran_callback
|
1002
|
+
end
|
774
1003
|
end
|
775
1004
|
|
776
1005
|
class MachineWithEventAttributesOnCustomActionTest < ActiveRecord::TestCase
|
@@ -1004,7 +1233,7 @@ begin
|
|
1004
1233
|
record = @model.new(:state => 'idling')
|
1005
1234
|
|
1006
1235
|
machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
|
1007
|
-
assert_equal 'cannot ignite', record.errors.
|
1236
|
+
assert_equal ['State cannot ignite'], record.errors.full_messages
|
1008
1237
|
end
|
1009
1238
|
|
1010
1239
|
def test_should_invalidate_using_customized_i18n_key_if_specified
|
@@ -1024,7 +1253,7 @@ begin
|
|
1024
1253
|
record = @model.new(:state => 'idling')
|
1025
1254
|
|
1026
1255
|
machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
|
1027
|
-
assert_equal 'cannot ignite', record.errors.
|
1256
|
+
assert_equal ['State cannot ignite'], record.errors.full_messages
|
1028
1257
|
end
|
1029
1258
|
|
1030
1259
|
def test_should_invalidate_using_customized_i18n_string_if_specified
|
@@ -1034,7 +1263,7 @@ begin
|
|
1034
1263
|
record = @model.new(:state => 'idling')
|
1035
1264
|
|
1036
1265
|
machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
|
1037
|
-
assert_equal 'cannot ignite', record.errors.
|
1266
|
+
assert_equal ['State cannot ignite'], record.errors.full_messages
|
1038
1267
|
end
|
1039
1268
|
|
1040
1269
|
def test_should_only_add_locale_once_in_load_path
|
@@ -25,7 +25,7 @@ begin
|
|
25
25
|
storage_names[:default] = 'foo'
|
26
26
|
def self.name; 'DataMapperTest::Foo'; end
|
27
27
|
|
28
|
-
property :id,
|
28
|
+
property :id, DataMapper::Types::Serial
|
29
29
|
property :state, String
|
30
30
|
|
31
31
|
auto_migrate! if auto_migrate
|
@@ -375,6 +375,45 @@ begin
|
|
375
375
|
end
|
376
376
|
end
|
377
377
|
|
378
|
+
class MachineWithLoopbackTest < BaseTestCase
|
379
|
+
def setup
|
380
|
+
dirty_attributes = nil
|
381
|
+
|
382
|
+
@resource = new_resource do
|
383
|
+
property :updated_at, DateTime
|
384
|
+
auto_migrate!
|
385
|
+
|
386
|
+
# Simulate dm-timestamps
|
387
|
+
before :update do
|
388
|
+
dirty_attributes = self.dirty_attributes.dup
|
389
|
+
|
390
|
+
return unless dirty?
|
391
|
+
self.updated_at = DateTime.now
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
@machine = StateMachine::Machine.new(@resource, :initial => :parked)
|
396
|
+
@machine.event :park
|
397
|
+
|
398
|
+
@record = @resource.create(:updated_at => Time.now - 1)
|
399
|
+
@timestamp = @record.updated_at
|
400
|
+
|
401
|
+
@transition = StateMachine::Transition.new(@record, @machine, :park, :parked, :parked)
|
402
|
+
@transition.perform
|
403
|
+
|
404
|
+
@dirty_attributes = dirty_attributes
|
405
|
+
end
|
406
|
+
|
407
|
+
def test_should_include_state_in_dirty_attributes
|
408
|
+
expected = {@resource.properties[:state] => 'parked'}
|
409
|
+
assert_equal expected, @dirty_attributes
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_should_update_record
|
413
|
+
assert_not_equal @timestamp, @record.updated_at
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
378
417
|
begin
|
379
418
|
gem 'dm-observer', ENV['DM_VERSION'] ? "=#{ENV['DM_VERSION']}" : '>=0.9.4'
|
380
419
|
require 'dm-observer'
|
@@ -721,6 +760,109 @@ begin
|
|
721
760
|
@record.valid?
|
722
761
|
assert !ran_callback
|
723
762
|
end
|
763
|
+
|
764
|
+
def test_should_not_run_after_callbacks_with_failures_disabled_if_validation_fails
|
765
|
+
@resource.class_eval do
|
766
|
+
attr_accessor :seatbelt
|
767
|
+
validates_present :seatbelt
|
768
|
+
end
|
769
|
+
|
770
|
+
ran_callback = false
|
771
|
+
@machine.after_transition { ran_callback = true }
|
772
|
+
|
773
|
+
@record.valid?
|
774
|
+
assert !ran_callback
|
775
|
+
end
|
776
|
+
|
777
|
+
def test_should_run_after_callbacks_with_failures_enabled_if_validation_fails
|
778
|
+
@resource.class_eval do
|
779
|
+
attr_accessor :seatbelt
|
780
|
+
validates_present :seatbelt
|
781
|
+
end
|
782
|
+
|
783
|
+
ran_callback = false
|
784
|
+
@machine.after_transition(:include_failures => true) { ran_callback = true }
|
785
|
+
|
786
|
+
@record.valid?
|
787
|
+
assert ran_callback
|
788
|
+
end
|
789
|
+
end
|
790
|
+
|
791
|
+
class MachineWithEventAttributesOnSaveTest < BaseTestCase
|
792
|
+
def setup
|
793
|
+
@resource = new_resource
|
794
|
+
@machine = StateMachine::Machine.new(@resource)
|
795
|
+
@machine.event :ignite do
|
796
|
+
transition :parked => :idling
|
797
|
+
end
|
798
|
+
|
799
|
+
@record = @resource.new
|
800
|
+
@record.state = 'parked'
|
801
|
+
@record.state_event = 'ignite'
|
802
|
+
end
|
803
|
+
|
804
|
+
def test_should_fail_if_event_is_invalid
|
805
|
+
@record.state_event = 'invalid'
|
806
|
+
assert !@record.save
|
807
|
+
end
|
808
|
+
|
809
|
+
def test_should_fail_if_event_has_no_transition
|
810
|
+
@record.state = 'idling'
|
811
|
+
assert !@record.save
|
812
|
+
end
|
813
|
+
|
814
|
+
def test_should_be_successful_if_event_has_transition
|
815
|
+
assert_equal true, @record.save
|
816
|
+
end
|
817
|
+
|
818
|
+
def test_should_run_before_callbacks
|
819
|
+
ran_callback = false
|
820
|
+
@machine.before_transition { ran_callback = true }
|
821
|
+
|
822
|
+
@record.save
|
823
|
+
assert ran_callback
|
824
|
+
end
|
825
|
+
|
826
|
+
def test_should_run_before_callbacks_once
|
827
|
+
before_count = 0
|
828
|
+
@machine.before_transition { before_count += 1 }
|
829
|
+
|
830
|
+
@record.save
|
831
|
+
assert_equal 1, before_count
|
832
|
+
end
|
833
|
+
|
834
|
+
def test_should_persist_new_state
|
835
|
+
@record.save
|
836
|
+
assert_equal 'idling', @record.state
|
837
|
+
end
|
838
|
+
|
839
|
+
def test_should_run_after_callbacks
|
840
|
+
ran_callback = false
|
841
|
+
@machine.after_transition { ran_callback = true }
|
842
|
+
|
843
|
+
@record.save
|
844
|
+
assert ran_callback
|
845
|
+
end
|
846
|
+
|
847
|
+
def test_should_not_run_after_callbacks_with_failures_disabled_if_fails
|
848
|
+
@resource.before(:create) { throw :halt }
|
849
|
+
|
850
|
+
ran_callback = false
|
851
|
+
@machine.after_transition { ran_callback = true }
|
852
|
+
|
853
|
+
@record.save
|
854
|
+
assert !ran_callback
|
855
|
+
end
|
856
|
+
|
857
|
+
def test_should_run_after_callbacks_with_failures_enabled_if_fails
|
858
|
+
@resource.before(:create) { throw :halt }
|
859
|
+
|
860
|
+
ran_callback = false
|
861
|
+
@machine.after_transition(:include_failures => true) { ran_callback = true }
|
862
|
+
|
863
|
+
@record.save
|
864
|
+
assert ran_callback
|
865
|
+
end
|
724
866
|
end
|
725
867
|
|
726
868
|
class MachineWithEventAttributesOnCustomActionTest < BaseTestCase
|