state_machine 0.5.2 → 0.6.0

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