shoulda-activemodel 0.0.2

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.
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