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