state_machine 0.5.2 → 0.6.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.
@@ -2,12 +2,11 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
3
  class GuardTest < Test::Unit::TestCase
4
4
  def setup
5
- @guard = StateMachine::Guard.new(:to => :idling, :from => :parked)
5
+ @guard = StateMachine::Guard.new(:from => :parked, :to => :idling)
6
6
  end
7
7
 
8
- def test_should_raise_exception_if_invalid_option_specified
9
- exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:invalid => true) }
10
- assert_equal 'Invalid key(s): invalid', exception.message
8
+ def test_should_not_raise_exception_if_implicit_option_specified
9
+ assert_nothing_raised { StateMachine::Guard.new(:invalid => true) }
11
10
  end
12
11
 
13
12
  def test_should_not_have_an_if_condition
@@ -17,6 +16,10 @@ class GuardTest < Test::Unit::TestCase
17
16
  def test_should_not_have_an_unless_condition
18
17
  assert_nil @guard.unless_condition
19
18
  end
19
+
20
+ def test_should_have_a_state_requirement
21
+ assert_equal 1, @guard.state_requirements.length
22
+ end
20
23
  end
21
24
 
22
25
  class GuardWithNoRequirementsTest < Test::Unit::TestCase
@@ -30,11 +33,11 @@ class GuardWithNoRequirementsTest < Test::Unit::TestCase
30
33
  end
31
34
 
32
35
  def test_should_use_all_matcher_for_from_state_requirement
33
- assert_equal StateMachine::AllMatcher.instance, @guard.state_requirement[:from]
36
+ assert_equal StateMachine::AllMatcher.instance, @guard.state_requirements.first[:from]
34
37
  end
35
38
 
36
39
  def test_should_use_all_matcher_for_to_state_requirement
37
- assert_equal StateMachine::AllMatcher.instance, @guard.state_requirement[:to]
40
+ assert_equal StateMachine::AllMatcher.instance, @guard.state_requirements.first[:to]
38
41
  end
39
42
 
40
43
  def test_should_match_nil_query
@@ -48,6 +51,14 @@ class GuardWithNoRequirementsTest < Test::Unit::TestCase
48
51
  def test_should_match_non_empty_query
49
52
  assert @guard.matches?(@object, :to => :idling, :from => :parked, :on => :ignite)
50
53
  end
54
+
55
+ def test_should_include_all_requirements_in_match
56
+ match = @guard.match(@object, nil)
57
+
58
+ assert_equal @guard.state_requirements.first[:from], match[:from]
59
+ assert_equal @guard.state_requirements.first[:to], match[:to]
60
+ assert_equal @guard.event_requirement, match[:on]
61
+ end
51
62
  end
52
63
 
53
64
  class GuardWithFromRequirementTest < Test::Unit::TestCase
@@ -57,7 +68,7 @@ class GuardWithFromRequirementTest < Test::Unit::TestCase
57
68
  end
58
69
 
59
70
  def test_should_use_a_whitelist_matcher
60
- assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirement[:from]
71
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
61
72
  end
62
73
 
63
74
  def test_should_match_if_not_specified
@@ -87,6 +98,11 @@ class GuardWithFromRequirementTest < Test::Unit::TestCase
87
98
  def test_should_be_included_in_known_states
88
99
  assert_equal [:parked], @guard.known_states
89
100
  end
101
+
102
+ def test_should_include_requirement_in_match
103
+ match = @guard.match(@object, :from => :parked)
104
+ assert_equal @guard.state_requirements.first[:from], match[:from]
105
+ end
90
106
  end
91
107
 
92
108
  class GuardWithMultipleFromRequirementsTest < Test::Unit::TestCase
@@ -115,7 +131,7 @@ class GuardWithToRequirementTest < Test::Unit::TestCase
115
131
  end
116
132
 
117
133
  def test_should_use_a_whitelist_matcher
118
- assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirement[:to]
134
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
119
135
  end
120
136
 
121
137
  def test_should_match_if_not_specified
@@ -145,6 +161,11 @@ class GuardWithToRequirementTest < Test::Unit::TestCase
145
161
  def test_should_be_included_in_known_states
146
162
  assert_equal [:idling], @guard.known_states
147
163
  end
164
+
165
+ def test_should_include_requirement_in_match
166
+ match = @guard.match(@object, :to => :idling)
167
+ assert_equal @guard.state_requirements.first[:to], match[:to]
168
+ end
148
169
  end
149
170
 
150
171
  class GuardWithMultipleToRequirementsTest < Test::Unit::TestCase
@@ -203,6 +224,11 @@ class GuardWithOnRequirementTest < Test::Unit::TestCase
203
224
  def test_should_not_be_included_in_known_states
204
225
  assert_equal [], @guard.known_states
205
226
  end
227
+
228
+ def test_should_include_requirement_in_match
229
+ match = @guard.match(@object, :on => :ignite)
230
+ assert_equal @guard.event_requirement, match[:on]
231
+ end
206
232
  end
207
233
 
208
234
  class GuardWithMultipleOnRequirementsTest < Test::Unit::TestCase
@@ -227,7 +253,7 @@ class GuardWithExceptFromRequirementTest < Test::Unit::TestCase
227
253
  end
228
254
 
229
255
  def test_should_use_a_blacklist_matcher
230
- assert_instance_of StateMachine::BlacklistMatcher, @guard.state_requirement[:from]
256
+ assert_instance_of StateMachine::BlacklistMatcher, @guard.state_requirements.first[:from]
231
257
  end
232
258
 
233
259
  def test_should_match_if_not_included
@@ -281,7 +307,7 @@ class GuardWithExceptToRequirementTest < Test::Unit::TestCase
281
307
  end
282
308
 
283
309
  def test_should_use_a_blacklist_matcher
284
- assert_instance_of StateMachine::BlacklistMatcher, @guard.state_requirement[:to]
310
+ assert_instance_of StateMachine::BlacklistMatcher, @guard.state_requirements.first[:to]
285
311
  end
286
312
 
287
313
  def test_should_match_if_not_included
@@ -425,6 +451,10 @@ class GuardWithDifferentRequirementsTest < Test::Unit::TestCase
425
451
  assert !@guard.matches?(@object, :on => :park)
426
452
  end
427
453
 
454
+ def test_should_be_nil_if_unmatched
455
+ assert_nil @guard.match(@object, :from => :parked, :to => :idling, :on => :park)
456
+ end
457
+
428
458
  def test_should_include_all_known_states
429
459
  assert_equal [:parked, :idling], @guard.known_states
430
460
  end
@@ -462,6 +492,129 @@ class GuardWithNilRequirementsTest < Test::Unit::TestCase
462
492
  end
463
493
  end
464
494
 
495
+ class GuardWithImplicitRequirementTest < Test::Unit::TestCase
496
+ def setup
497
+ @guard = StateMachine::Guard.new(:parked => :idling, :on => :ignite)
498
+ end
499
+
500
+ def test_should_create_an_event_requirement
501
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.event_requirement
502
+ assert_equal [:ignite], @guard.event_requirement.values
503
+ end
504
+
505
+ def test_should_use_a_whitelist_from_matcher
506
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
507
+ end
508
+
509
+ def test_should_use_a_whitelist_to_matcher
510
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
511
+ end
512
+ end
513
+
514
+ class GuardWithMultipleImplicitRequirementsTest < Test::Unit::TestCase
515
+ def setup
516
+ @object = Object.new
517
+ @guard = StateMachine::Guard.new(:parked => :idling, :idling => :first_gear, :on => :ignite)
518
+ end
519
+
520
+ def test_should_create_multiple_state_requirements
521
+ assert_equal 2, @guard.state_requirements.length
522
+ end
523
+
524
+ def test_should_not_match_event_as_state_requirement
525
+ assert !@guard.matches?(@object, :from => :on, :to => :ignite)
526
+ end
527
+
528
+ def test_should_match_if_from_included_in_any
529
+ assert @guard.matches?(@object, :from => :parked)
530
+ assert @guard.matches?(@object, :from => :idling)
531
+ end
532
+
533
+ def test_should_not_match_if_from_not_included_in_any
534
+ assert !@guard.matches?(@object, :from => :first_gear)
535
+ end
536
+
537
+ def test_should_match_if_to_included_in_any
538
+ assert @guard.matches?(@object, :to => :idling)
539
+ assert @guard.matches?(@object, :to => :first_gear)
540
+ end
541
+
542
+ def test_should_not_match_if_to_not_included_in_any
543
+ assert !@guard.matches?(@object, :to => :parked)
544
+ end
545
+
546
+ def test_should_match_if_all_options_match
547
+ assert @guard.matches?(@object, :from => :parked, :to => :idling, :on => :ignite)
548
+ assert @guard.matches?(@object, :from => :idling, :to => :first_gear, :on => :ignite)
549
+ end
550
+
551
+ def test_should_not_match_if_any_options_do_not_match
552
+ assert !@guard.matches?(@object, :from => :parked, :to => :idling, :on => :park)
553
+ assert !@guard.matches?(@object, :from => :parked, :to => :first_gear, :on => :park)
554
+ end
555
+
556
+ def test_should_include_all_known_states
557
+ assert_equal [:first_gear, :idling, :parked], @guard.known_states.sort_by {|state| state.to_s}
558
+ end
559
+
560
+ def test_should_not_duplicate_known_statse
561
+ guard = StateMachine::Guard.new(:parked => :idling, :first_gear => :idling)
562
+ assert_equal [:first_gear, :idling, :parked], guard.known_states.sort_by {|state| state.to_s}
563
+ end
564
+ end
565
+
566
+ class GuardWithImplicitFromRequirementMatcherTest < Test::Unit::TestCase
567
+ def setup
568
+ @matcher = StateMachine::BlacklistMatcher.new(:parked)
569
+ @guard = StateMachine::Guard.new(@matcher => :idling)
570
+ end
571
+
572
+ def test_should_not_convert_from_to_whitelist_matcher
573
+ assert_equal @matcher, @guard.state_requirements.first[:from]
574
+ end
575
+
576
+ def test_should_convert_to_to_whitelist_matcher
577
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
578
+ end
579
+ end
580
+
581
+ class GuardWithImplicitToRequirementMatcherTest < Test::Unit::TestCase
582
+ def setup
583
+ @matcher = StateMachine::BlacklistMatcher.new(:idling)
584
+ @guard = StateMachine::Guard.new(:parked => @matcher)
585
+ end
586
+
587
+ def test_should_convert_from_to_whitelist_matcher
588
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
589
+ end
590
+
591
+ def test_should_not_convert_to_to_whitelist_matcher
592
+ assert_equal @matcher, @guard.state_requirements.first[:to]
593
+ end
594
+ end
595
+
596
+ class GuardWithImplicitAndExplicitRequirementsTest < Test::Unit::TestCase
597
+ def setup
598
+ @guard = StateMachine::Guard.new(:parked => :idling, :from => :parked)
599
+ end
600
+
601
+ def test_should_create_multiple_requirements
602
+ assert_equal 2, @guard.state_requirements.length
603
+ end
604
+
605
+ def test_should_create_implicit_requirements_for_implicit_options
606
+ assert(@guard.state_requirements.any? do |state_requirement|
607
+ state_requirement[:from].values == [:parked] && state_requirement[:to].values == [:idling]
608
+ end)
609
+ end
610
+
611
+ def test_should_create_implicit_requirements_for_explicit_options
612
+ assert(@guard.state_requirements.any? do |state_requirement|
613
+ state_requirement[:from].values == [:from] && state_requirement[:to].values == [:parked]
614
+ end)
615
+ end
616
+ end
617
+
465
618
  class GuardWithIfConditionalTest < Test::Unit::TestCase
466
619
  def setup
467
620
  @object = Object.new
@@ -481,6 +634,30 @@ class GuardWithIfConditionalTest < Test::Unit::TestCase
481
634
  guard = StateMachine::Guard.new(:if => lambda {false})
482
635
  assert !guard.matches?(@object)
483
636
  end
637
+
638
+ def test_should_be_nil_if_unmatched
639
+ guard = StateMachine::Guard.new(:if => lambda {false})
640
+ assert_nil guard.match(@object)
641
+ end
642
+ end
643
+
644
+ class GuardWithMultipleIfConditionalsTest < Test::Unit::TestCase
645
+ def setup
646
+ @object = Object.new
647
+ end
648
+
649
+ def test_should_match_if_all_are_true
650
+ guard = StateMachine::Guard.new(:if => [lambda {true}, lambda {true}])
651
+ assert guard.match(@object)
652
+ end
653
+
654
+ def test_should_not_match_if_any_are_false
655
+ guard = StateMachine::Guard.new(:if => [lambda {true}, lambda {false}])
656
+ assert !guard.match(@object)
657
+
658
+ guard = StateMachine::Guard.new(:if => [lambda {false}, lambda {true}])
659
+ assert !guard.match(@object)
660
+ end
484
661
  end
485
662
 
486
663
  class GuardWithUnlessConditionalTest < Test::Unit::TestCase
@@ -502,12 +679,51 @@ class GuardWithUnlessConditionalTest < Test::Unit::TestCase
502
679
  guard = StateMachine::Guard.new(:unless => lambda {true})
503
680
  assert !guard.matches?(@object)
504
681
  end
682
+
683
+ def test_should_be_nil_if_unmatched
684
+ guard = StateMachine::Guard.new(:unless => lambda {true})
685
+ assert_nil guard.match(@object)
686
+ end
687
+ end
688
+
689
+ class GuardWithMultipleUnlessConditionalsTest < Test::Unit::TestCase
690
+ def setup
691
+ @object = Object.new
692
+ end
693
+
694
+ def test_should_match_if_all_are_false
695
+ guard = StateMachine::Guard.new(:unless => [lambda {false}, lambda {false}])
696
+ assert guard.match(@object)
697
+ end
698
+
699
+ def test_should_not_match_if_any_are_true
700
+ guard = StateMachine::Guard.new(:unless => [lambda {true}, lambda {false}])
701
+ assert !guard.match(@object)
702
+
703
+ guard = StateMachine::Guard.new(:unless => [lambda {false}, lambda {true}])
704
+ assert !guard.match(@object)
705
+ end
505
706
  end
506
707
 
507
708
  class GuardWithConflictingConditionalsTest < Test::Unit::TestCase
508
- def test_should_raise_an_exception
509
- exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:if => lambda {true}, :unless => lambda {true}) }
510
- assert_equal 'Conflicting keys: if, unless', exception.message
709
+ def test_should_match_if_if_is_true_and_unless_is_false
710
+ guard = StateMachine::Guard.new(:if => lambda {true}, :unless => lambda {false})
711
+ assert guard.match(@object)
712
+ end
713
+
714
+ def test_should_not_match_if_if_is_false_and_unless_is_true
715
+ guard = StateMachine::Guard.new(:if => lambda {false}, :unless => lambda {true})
716
+ assert !guard.match(@object)
717
+ end
718
+
719
+ def test_should_not_match_if_if_is_false_and_unless_is_false
720
+ guard = StateMachine::Guard.new(:if => lambda {false}, :unless => lambda {false})
721
+ assert !guard.match(@object)
722
+ end
723
+
724
+ def test_should_not_match_if_if_is_true_and_unless_is_true
725
+ guard = StateMachine::Guard.new(:if => lambda {true}, :unless => lambda {true})
726
+ assert !guard.match(@object)
511
727
  end
512
728
  end
513
729
 
@@ -624,6 +840,23 @@ begin
624
840
  assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
625
841
  end
626
842
  end
843
+
844
+ class GuardDrawingWithNilStateTest < Test::Unit::TestCase
845
+ def setup
846
+ @machine = StateMachine::Machine.new(Class.new)
847
+
848
+ graph = GraphViz.new('G')
849
+ graph.add_node('parked')
850
+
851
+ @guard = StateMachine::Guard.new(:from => :idling, :to => nil)
852
+ @edges = @guard.draw(graph, :park, [nil, :idling])
853
+ end
854
+
855
+ def test_should_generate_edges_for_each_valid_from_state
856
+ assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
857
+ assert_equal 'nil', @edges.first.instance_variable_get('@xNodeTwo')
858
+ end
859
+ end
627
860
  rescue LoadError
628
861
  $stderr.puts 'Skipping GraphViz StateMachine::Guard tests. `gem install ruby-graphviz` and try again.'
629
862
  end
@@ -486,6 +486,35 @@ begin
486
486
  end
487
487
  end
488
488
 
489
+ class MachineWithStateDrivenValidationsTest < ActiveRecord::TestCase
490
+ def setup
491
+ @model = new_model do
492
+ attr_accessor :seatbelt
493
+ end
494
+
495
+ @machine = StateMachine::Machine.new(@model)
496
+ @machine.state :first_gear, :second_gear do
497
+ validates_presence_of :seatbelt
498
+ end
499
+ @machine.other_states :parked
500
+ end
501
+
502
+ def test_should_be_valid_if_validation_fails_outside_state_scope
503
+ record = @model.new(:state => 'parked', :seatbelt => nil)
504
+ assert record.valid?
505
+ end
506
+
507
+ def test_should_be_invalid_if_validation_fails_within_state_scope
508
+ record = @model.new(:state => 'first_gear', :seatbelt => nil)
509
+ assert !record.valid?
510
+ end
511
+
512
+ def test_should_be_valid_if_validation_succeeds_within_state_scope
513
+ record = @model.new(:state => 'second_gear', :seatbelt => true)
514
+ assert record.valid?
515
+ end
516
+ end
517
+
489
518
  class MachineWithFailedAfterCallbacksTest < ActiveRecord::TestCase
490
519
  def setup
491
520
  @after_count = 0
@@ -334,6 +334,16 @@ begin
334
334
  @transition = StateMachine::Transition.new(@record, @machine, :ignite, :parked, :idling)
335
335
  end
336
336
 
337
+ def test_should_provide_matcher_helpers
338
+ matchers = []
339
+
340
+ new_observer(@resource) do
341
+ matchers = [all, any, same]
342
+ end
343
+
344
+ assert_equal [StateMachine::AllMatcher.instance, StateMachine::AllMatcher.instance, StateMachine::LoopbackMatcher.instance], matchers
345
+ end
346
+
337
347
  def test_should_call_before_transition_callback_if_requirements_match
338
348
  called = false
339
349
 
@@ -476,6 +486,41 @@ begin
476
486
  rescue LoadError
477
487
  $stderr.puts 'Skipping DataMapper Observer tests. `gem install dm-observer` and try again.'
478
488
  end
489
+
490
+ begin
491
+ require 'dm-validations'
492
+
493
+ class MachineWithStateDrivenValidationsTest < BaseTestCase
494
+ def setup
495
+ @resource = new_resource do
496
+ attr_accessor :seatbelt
497
+ end
498
+
499
+ @machine = StateMachine::Machine.new(@resource)
500
+ @machine.state :first_gear, :second_gear do
501
+ validates_present :seatbelt
502
+ end
503
+ @machine.other_states :parked
504
+ end
505
+
506
+ def test_should_be_valid_if_validation_fails_outside_state_scope
507
+ record = @resource.new(:state => 'parked', :seatbelt => nil)
508
+ assert record.valid?
509
+ end
510
+
511
+ def test_should_be_invalid_if_validation_fails_within_state_scope
512
+ record = @resource.new(:state => 'first_gear', :seatbelt => nil)
513
+ assert !record.valid?
514
+ end
515
+
516
+ def test_should_be_valid_if_validation_succeeds_within_state_scope
517
+ record = @resource.new(:state => 'second_gear', :seatbelt => true)
518
+ assert record.valid?
519
+ end
520
+ end
521
+ rescue LoadError
522
+ $stderr.puts 'Skipping DataMapper Validation tests. `gem install dm-validations` and try again.'
523
+ end
479
524
  end
480
525
  rescue LoadError
481
526
  $stderr.puts 'Skipping DataMapper tests. `gem install dm-core cucumber rspec hoe launchy do_sqlite3` and try again.'