shoulda-activemodel 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. data/lib/shoulda/active_model.rb +16 -0
  2. data/lib/shoulda/active_model/assertions.rb +61 -0
  3. data/lib/shoulda/active_model/helpers.rb +31 -0
  4. data/lib/shoulda/active_model/macros.rb +268 -0
  5. data/lib/shoulda/active_model/matchers.rb +30 -0
  6. data/lib/shoulda/active_model/matchers/allow_value_matcher.rb +102 -0
  7. data/lib/shoulda/active_model/matchers/ensure_inclusion_of_matcher.rb +87 -0
  8. data/lib/shoulda/active_model/matchers/ensure_length_of_matcher.rb +141 -0
  9. data/lib/shoulda/active_model/matchers/validate_acceptance_of_matcher.rb +41 -0
  10. data/lib/shoulda/active_model/matchers/validate_format_of_matcher.rb +67 -0
  11. data/lib/shoulda/active_model/matchers/validate_numericality_of_matcher.rb +39 -0
  12. data/lib/shoulda/active_model/matchers/validate_presence_of_matcher.rb +60 -0
  13. data/lib/shoulda/active_model/matchers/validate_uniqueness_of_matcher.rb +148 -0
  14. data/lib/shoulda/active_model/matchers/validation_matcher.rb +57 -0
  15. data/test/fail_macros.rb +39 -0
  16. data/test/matchers/active_model/ensure_inclusion_of_matcher_test.rb +80 -0
  17. data/test/matchers/active_model/ensure_length_of_matcher_test.rb +158 -0
  18. data/test/matchers/active_model/validate_acceptance_of_matcher_test.rb +44 -0
  19. data/test/matchers/active_model/validate_format_of_matcher_test.rb +39 -0
  20. data/test/matchers/active_model/validate_numericality_of_matcher_test.rb +52 -0
  21. data/test/matchers/active_model/validate_presence_of_matcher_test.rb +86 -0
  22. data/test/matchers/active_model/validate_uniqueness_of_matcher_test.rb +147 -0
  23. data/test/model_builder.rb +106 -0
  24. data/test/rspec_test.rb +207 -0
  25. data/test/test_helper.rb +20 -0
  26. metadata +106 -0
@@ -0,0 +1,57 @@
1
+ module Shoulda # :nodoc:
2
+ module ActiveModel # :nodoc:
3
+ module Matchers
4
+
5
+ class ValidationMatcher # :nodoc:
6
+
7
+ attr_reader :failure_message
8
+
9
+ def initialize(attribute)
10
+ @attribute = attribute
11
+ end
12
+
13
+ def negative_failure_message
14
+ @negative_failure_message || @failure_message
15
+ end
16
+
17
+ def matches?(subject)
18
+ @subject = subject
19
+ false
20
+ end
21
+
22
+
23
+ private
24
+
25
+ def allows_value_of(value, message = nil)
26
+ allow = AllowValueMatcher.
27
+ new(value).
28
+ for(@attribute).
29
+ with_message(message)
30
+ if allow.matches?(@subject)
31
+ @negative_failure_message = allow.failure_message
32
+ true
33
+ else
34
+ @failure_message = allow.negative_failure_message
35
+ false
36
+ end
37
+ end
38
+
39
+ def disallows_value_of(value, message = nil)
40
+ disallow = AllowValueMatcher.
41
+ new(value).
42
+ for(@attribute).
43
+ with_message(message)
44
+ if disallow.matches?(@subject)
45
+ @failure_message = disallow.negative_failure_message
46
+ false
47
+ else
48
+ @negative_failure_message = disallow.failure_message
49
+ true
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,39 @@
1
+ module Shoulda
2
+ class << self
3
+ attr_accessor :expected_exceptions
4
+ end
5
+
6
+ module ClassMethods
7
+ # Enables the core shoulda test suite to test for failure scenarios. For
8
+ # example, to ensure that a set of test macros should fail, do this:
9
+ #
10
+ # should_fail do
11
+ # should_validate_presence_of :comments
12
+ # should_not_allow_mass_assignment_of :name
13
+ # end
14
+ def should_fail(&block)
15
+ context "should fail when trying to run:" do
16
+ if defined?(Test::Unit::AssertionFailedError)
17
+ failures = [Test::Unit::AssertionFailedError]
18
+ elsif defined?(MiniTest::Assertion)
19
+ failures = [MiniTest::Assertion]
20
+ end
21
+ Shoulda.expected_exceptions = failures
22
+ yield block
23
+ Shoulda.expected_exceptions = nil
24
+ end
25
+ end
26
+ end
27
+
28
+ class Context
29
+ # alias_method_chain hack to allow the should_fail macro to work
30
+ def should_with_failure_scenario(name, options = {}, &block)
31
+ if Shoulda.expected_exceptions
32
+ expected_exceptions = Shoulda.expected_exceptions
33
+ failure_block = lambda { assert_raise(*expected_exceptions, &block.bind(self)) }
34
+ end
35
+ should_without_failure_scenario(name, options, &(failure_block || block))
36
+ end
37
+ alias_method_chain :should, :failure_scenario
38
+ end
39
+ end
@@ -0,0 +1,80 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class EnsureInclusionOfMatcherTest < ActiveSupport::TestCase # :nodoc:
4
+
5
+ context "an attribute which must be included in a range" do
6
+ setup do
7
+ @model = define_model(:example, :attr => :integer) do
8
+ validates_inclusion_of :attr, :in => 2..5
9
+ end.new
10
+ end
11
+
12
+ should "accept ensuring the correct range" do
13
+ assert_accepts ensure_inclusion_of(:attr).in_range(2..5), @model
14
+ end
15
+
16
+ should "reject ensuring a lower minimum value" do
17
+ assert_rejects ensure_inclusion_of(:attr).in_range(1..5), @model
18
+ end
19
+
20
+ should "reject ensuring a higher minimum value" do
21
+ assert_rejects ensure_inclusion_of(:attr).in_range(3..5), @model
22
+ end
23
+
24
+ should "reject ensuring a lower maximum value" do
25
+ assert_rejects ensure_inclusion_of(:attr).in_range(2..4), @model
26
+ end
27
+
28
+ should "reject ensuring a higher maximum value" do
29
+ assert_rejects ensure_inclusion_of(:attr).in_range(2..6), @model
30
+ end
31
+
32
+ should "not override the default message with a blank" do
33
+ assert_accepts ensure_inclusion_of(:attr).
34
+ in_range(2..5).
35
+ with_message(nil),
36
+ @model
37
+ end
38
+ end
39
+
40
+ context "an attribute with a custom ranged value validation" do
41
+ setup do
42
+ @model = define_model(:example, :attr => :string) do
43
+ validates_inclusion_of :attr, :in => 2..4, :message => 'not good'
44
+
45
+ end.new
46
+ end
47
+
48
+ should "accept ensuring the correct range" do
49
+ assert_accepts ensure_inclusion_of(:attr).
50
+ in_range(2..4).
51
+ with_message(/not good/),
52
+ @model
53
+ end
54
+ end
55
+
56
+ context "an attribute with custom range validations" do
57
+ setup do
58
+ define_model :example, :attr => :integer do
59
+ def validate
60
+ if attr < 2
61
+ errors.add(:attr, 'too low')
62
+ elsif attr > 5
63
+ errors.add(:attr, 'too high')
64
+ end
65
+ end
66
+ end
67
+ @model = Example.new
68
+ end
69
+
70
+ should "accept ensuring the correct range and messages" do
71
+ assert_accepts ensure_inclusion_of(:attr).
72
+ in_range(2..5).
73
+ with_low_message(/low/).
74
+ with_high_message(/high/),
75
+ @model
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,158 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class EnsureLengthOfMatcher < ActiveSupport::TestCase # :nodoc:
4
+
5
+ context "an attribute with a non-zero minimum length validation" do
6
+ setup do
7
+ @model = define_model(:example, :attr => :string) do
8
+ validates_length_of :attr, :minimum => 4
9
+ end.new
10
+ end
11
+
12
+ should "accept ensuring the correct minimum length" do
13
+ assert_accepts ensure_length_of(:attr).is_at_least(4), @model
14
+ end
15
+
16
+ should "reject ensuring a lower minimum length with any message" do
17
+ assert_rejects ensure_length_of(:attr).
18
+ is_at_least(3).
19
+ with_short_message(/.*/),
20
+ @model
21
+ end
22
+
23
+ should "reject ensuring a higher minimum length with any message" do
24
+ assert_rejects ensure_length_of(:attr).
25
+ is_at_least(5).
26
+ with_short_message(/.*/),
27
+ @model
28
+ end
29
+
30
+ should "not override the default message with a blank" do
31
+ assert_accepts ensure_length_of(:attr).
32
+ is_at_least(4).
33
+ with_short_message(nil),
34
+ @model
35
+ end
36
+ end
37
+
38
+ context "an attribute with a minimum length validation of 0" do
39
+ setup do
40
+ @model = define_model(:example, :attr => :string) do
41
+ validates_length_of :attr, :minimum => 0
42
+ end.new
43
+ end
44
+
45
+ should "accept ensuring the correct minimum length" do
46
+ assert_accepts ensure_length_of(:attr).is_at_least(0), @model
47
+ end
48
+ end
49
+
50
+ context "an attribute with a maximum length" do
51
+ setup do
52
+ @model = define_model(:example, :attr => :string) do
53
+ validates_length_of :attr, :maximum => 4
54
+ end.new
55
+ end
56
+
57
+ should "accept ensuring the correct maximum length" do
58
+ assert_accepts ensure_length_of(:attr).is_at_most(4), @model
59
+ end
60
+
61
+ should "reject ensuring a lower maximum length with any message" do
62
+ assert_rejects ensure_length_of(:attr).
63
+ is_at_most(3).
64
+ with_long_message(/.*/),
65
+ @model
66
+ end
67
+
68
+ should "reject ensuring a higher maximum length with any message" do
69
+ assert_rejects ensure_length_of(:attr).
70
+ is_at_most(5).
71
+ with_long_message(/.*/),
72
+ @model
73
+ end
74
+
75
+ should "not override the default message with a blank" do
76
+ assert_accepts ensure_length_of(:attr).
77
+ is_at_most(4).
78
+ with_long_message(nil),
79
+ @model
80
+ end
81
+ end
82
+
83
+ context "an attribute with a required exact length" do
84
+ setup do
85
+ @model = define_model(:example, :attr => :string) do
86
+ validates_length_of :attr, :is => 4
87
+ end.new
88
+ end
89
+
90
+ should "accept ensuring the correct length" do
91
+ assert_accepts ensure_length_of(:attr).is_equal_to(4), @model
92
+ end
93
+
94
+ should "reject ensuring a lower maximum length with any message" do
95
+ assert_rejects ensure_length_of(:attr).
96
+ is_equal_to(3).
97
+ with_message(/.*/),
98
+ @model
99
+ end
100
+
101
+ should "reject ensuring a higher maximum length with any message" do
102
+ assert_rejects ensure_length_of(:attr).
103
+ is_equal_to(5).
104
+ with_message(/.*/),
105
+ @model
106
+ end
107
+
108
+ should "not override the default message with a blank" do
109
+ assert_accepts ensure_length_of(:attr).
110
+ is_equal_to(4).
111
+ with_message(nil),
112
+ @model
113
+ end
114
+ end
115
+
116
+ context "an attribute with a custom minimum length validation" do
117
+ setup do
118
+ @model = define_model(:example, :attr => :string) do
119
+ validates_length_of :attr, :minimum => 4, :too_short => 'short'
120
+ end.new
121
+ end
122
+
123
+ should "accept ensuring the correct minimum length" do
124
+ assert_accepts ensure_length_of(:attr).
125
+ is_at_least(4).
126
+ with_short_message(/short/),
127
+ @model
128
+ end
129
+
130
+ end
131
+
132
+ context "an attribute with a custom maximum length validation" do
133
+ setup do
134
+ @model = define_model(:example, :attr => :string) do
135
+ validates_length_of :attr, :maximum => 4, :too_long => 'long'
136
+ end.new
137
+ end
138
+
139
+ should "accept ensuring the correct minimum length" do
140
+ assert_accepts ensure_length_of(:attr).
141
+ is_at_most(4).
142
+ with_long_message(/long/),
143
+ @model
144
+ end
145
+
146
+ end
147
+
148
+ context "an attribute without a length validation" do
149
+ setup do
150
+ @model = define_model(:example, :attr => :string).new
151
+ end
152
+
153
+ should "reject ensuring a minimum length" do
154
+ assert_rejects ensure_length_of(:attr).is_at_least(1), @model
155
+ end
156
+ end
157
+
158
+ end
@@ -0,0 +1,44 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class ValidateAcceptanceOfMatcherTest < ActiveSupport::TestCase # :nodoc:
4
+
5
+ context "an attribute which must be accepted" do
6
+ setup do
7
+ @model = define_model(:example) do
8
+ validates_acceptance_of :attr
9
+ end.new
10
+ end
11
+
12
+ should "require that attribute to be accepted" do
13
+ assert_accepts validate_acceptance_of(:attr), @model
14
+ end
15
+
16
+ should "not overwrite the default message with nil" do
17
+ assert_accepts validate_acceptance_of(:attr).with_message(nil), @model
18
+ end
19
+ end
20
+
21
+ context "an attribute that does not need to be accepted" do
22
+ setup do
23
+ @model = define_model(:example, :attr => :string).new
24
+ end
25
+
26
+ should "not require that attribute to be accepted" do
27
+ assert_rejects validate_acceptance_of(:attr), @model
28
+ end
29
+ end
30
+
31
+ context "an attribute which must be accepted with a custom message" do
32
+ setup do
33
+ @model = define_model(:example) do
34
+ validates_acceptance_of :attr, :message => 'custom'
35
+ end.new
36
+ end
37
+
38
+ should "require that attribute to be accepted with that message" do
39
+ assert_accepts validate_acceptance_of(:attr).with_message(/custom/),
40
+ @model
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,39 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class ValidateFormatOfMatcherTest < ActiveSupport::TestCase # :nodoc:
4
+
5
+
6
+ context "a postal code" do
7
+ setup do
8
+ define_model :example, :attr => :string do
9
+ validates_format_of :attr, :with => /^\d{5}$/
10
+ end
11
+ @model = Example.new
12
+ end
13
+
14
+ should "be valid" do
15
+ assert_accepts validate_format_of(:attr).with('12345'), @model
16
+ end
17
+
18
+ should "not be valid with alpha in zip" do
19
+ assert_rejects validate_format_of(:attr).not_with('1234a'), @model, :message=>"is invalid"
20
+ end
21
+
22
+ should "not be valid with to few digits" do
23
+ assert_rejects validate_format_of(:attr).not_with('1234'), @model, :message=>"is invalid"
24
+ end
25
+
26
+ should "not be valid with to many digits" do
27
+ assert_rejects validate_format_of(:attr).not_with('123456'), @model, :message=>"is invalid"
28
+ end
29
+
30
+ should "raise error if you try to call both with and not_with" do
31
+ assert_raise RuntimeError do
32
+ validate_format_of(:attr).not_with('123456').with('12345')
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+
39
+ end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class ValidateNumericalityOfMatcherTest < ActiveSupport::TestCase # :nodoc:
4
+
5
+ context "a numeric attribute" do
6
+ setup do
7
+ define_model :example, :attr => :string do
8
+ validates_numericality_of :attr
9
+ end
10
+ @model = Example.new
11
+ end
12
+
13
+ should "only allow numeric values for that attribute" do
14
+ assert_accepts validate_numericality_of(:attr), @model
15
+ end
16
+
17
+ should "not override the default message with a blank" do
18
+ assert_accepts validate_numericality_of(:attr).with_message(nil),
19
+ @model
20
+ end
21
+ end
22
+
23
+ context "a numeric attribute with a custom validation message" do
24
+ setup do
25
+ define_model :example, :attr => :string do
26
+ validates_numericality_of :attr, :message => 'custom'
27
+ end
28
+ @model = Example.new
29
+ end
30
+
31
+ should "only allow numeric values for that attribute with that message" do
32
+ assert_accepts validate_numericality_of(:attr).
33
+ with_message(/custom/),
34
+ @model
35
+ end
36
+
37
+ should "not allow numeric values for that attribute with another message" do
38
+ assert_rejects validate_numericality_of(:attr), @model
39
+ end
40
+ end
41
+
42
+ context "a non-numeric attribute" do
43
+ setup do
44
+ @model = define_model(:example, :attr => :string).new
45
+ end
46
+
47
+ should "not only allow numeric values for that attribute" do
48
+ assert_rejects validate_numericality_of(:attr), @model
49
+ end
50
+ end
51
+
52
+ end