remarkable_activerecord 3.0.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.
- data/CHANGELOG +47 -0
- data/LICENSE +20 -0
- data/README +2 -0
- data/lib/remarkable_activerecord/base.rb +238 -0
- data/lib/remarkable_activerecord/human_names.rb +37 -0
- data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +34 -0
- data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +94 -0
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +235 -0
- data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +68 -0
- data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +57 -0
- data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +30 -0
- data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +80 -0
- data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +51 -0
- data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +99 -0
- data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +45 -0
- data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +47 -0
- data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +47 -0
- data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +123 -0
- data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +184 -0
- data/lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb +29 -0
- data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +151 -0
- data/lib/remarkable_activerecord.rb +29 -0
- data/locale/en.yml +253 -0
- data/spec/allow_mass_assignment_of_matcher_spec.rb +57 -0
- data/spec/allow_values_for_matcher_spec.rb +56 -0
- data/spec/association_matcher_spec.rb +616 -0
- data/spec/have_column_matcher_spec.rb +73 -0
- data/spec/have_index_matcher_spec.rb +68 -0
- data/spec/have_readonly_attributes_matcher_spec.rb +47 -0
- data/spec/have_scope_matcher_spec.rb +69 -0
- data/spec/model_builder.rb +101 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/validate_acceptance_of_matcher_spec.rb +68 -0
- data/spec/validate_associated_matcher_spec.rb +122 -0
- data/spec/validate_confirmation_of_matcher_spec.rb +58 -0
- data/spec/validate_exclusion_of_matcher_spec.rb +88 -0
- data/spec/validate_inclusion_of_matcher_spec.rb +84 -0
- data/spec/validate_length_of_matcher_spec.rb +165 -0
- data/spec/validate_numericality_of_matcher_spec.rb +180 -0
- data/spec/validate_presence_of_matcher_spec.rb +52 -0
- data/spec/validate_uniqueness_of_matcher_spec.rb +150 -0
- metadata +112 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'validate_inclusion_of' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(options={})
|
8
|
+
@model = define_model :product, :title => :string, :size => :string do
|
9
|
+
validates_inclusion_of :title, :size, options
|
10
|
+
end
|
11
|
+
|
12
|
+
validate_inclusion_of(:title, :size)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'messages' do
|
16
|
+
before(:each){ @matcher = define_and_validate(:in => 2..10) }
|
17
|
+
|
18
|
+
it 'should contain a description' do
|
19
|
+
@matcher.in(2..10)
|
20
|
+
@matcher.description.should == 'ensure inclusion of title and size in 2..10'
|
21
|
+
|
22
|
+
@matcher = validate_inclusion_of(:title, :size).in('X', 'Y', 'Z')
|
23
|
+
@matcher.description.should == 'ensure inclusion of title and size in "X", "Y", and "Z"'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should set is_valid? message' do
|
27
|
+
@matcher.in(1..10).matches?(@model)
|
28
|
+
@matcher.failure_message.should == 'Expected Product to be valid when title is set to 1'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should set is_invalid? message' do
|
32
|
+
@matcher.in(3..10).matches?(@model)
|
33
|
+
@matcher.failure_message.should == 'Expected Product to be invalid when title is set to 2'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should set allow_nil? message' do
|
37
|
+
@matcher.allow_nil.matches?(@model)
|
38
|
+
@matcher.failure_message.should == 'Expected Product to allow nil values for title'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should set allow_blank? message' do
|
42
|
+
@matcher.allow_blank.matches?(@model)
|
43
|
+
@matcher.failure_message.should == 'Expected Product to allow blank values for title'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'matchers' do
|
48
|
+
it { should define_and_validate(:in => ['X', 'Y', 'Z']).in('X', 'Y', 'Z') }
|
49
|
+
it { should_not define_and_validate(:in => ['X', 'Y', 'Z']).in('A') }
|
50
|
+
|
51
|
+
it { should define_and_validate(:in => 2..3).in(2..3) }
|
52
|
+
it { should define_and_validate(:in => 2..20).in(2..20) }
|
53
|
+
it { should_not define_and_validate(:in => 2..20).in(1..20) }
|
54
|
+
it { should_not define_and_validate(:in => 2..20).in(3..20) }
|
55
|
+
it { should_not define_and_validate(:in => 2..20).in(2..19) }
|
56
|
+
it { should_not define_and_validate(:in => 2..20).in(2..21) }
|
57
|
+
|
58
|
+
it { should define_and_validate(:in => ['X', 'Y', 'Z'], :message => 'valid').in('X', 'Y', 'Z').message('valid') }
|
59
|
+
|
60
|
+
create_optional_boolean_specs(:allow_nil, self, :in => ['X'])
|
61
|
+
create_optional_boolean_specs(:allow_blank, self, :in => ['X'])
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'macros' do
|
65
|
+
describe 'with array' do
|
66
|
+
before(:each){ define_and_validate(:in => ['X', 'Y', 'Z']) }
|
67
|
+
|
68
|
+
should_validate_inclusion_of :title, :in => ['X']
|
69
|
+
should_validate_inclusion_of :title, :size, :in => ['X']
|
70
|
+
should_not_validate_inclusion_of :title, :size, :in => ['A']
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'with range' do
|
74
|
+
before(:each){ define_and_validate(:in => 2..20) }
|
75
|
+
|
76
|
+
should_validate_inclusion_of :title, :in => 2..20
|
77
|
+
should_not_validate_inclusion_of :title, :in => 1..20
|
78
|
+
should_not_validate_inclusion_of :title, :in => 3..20
|
79
|
+
should_not_validate_inclusion_of :title, :in => 2..19
|
80
|
+
should_not_validate_inclusion_of :title, :in => 2..21
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'validate_length_of' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(options={})
|
8
|
+
options = options.merge(:within => 3..5) if options.slice(:in, :within, :maximum, :minimum, :is).empty?
|
9
|
+
|
10
|
+
@model = define_model :product, :size => :string, :category => :string do
|
11
|
+
validates_length_of :size, options
|
12
|
+
end
|
13
|
+
|
14
|
+
validate_length_of(:size)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'messages' do
|
18
|
+
before(:each){ @matcher = define_and_validate }
|
19
|
+
|
20
|
+
it 'should contain a description' do
|
21
|
+
@matcher.within(3..5)
|
22
|
+
@matcher.description.should == 'ensure length of size is within 3..5 characters'
|
23
|
+
|
24
|
+
@matcher.within(nil).in(3..5)
|
25
|
+
@matcher.description.should == 'ensure length of size is within 3..5 characters'
|
26
|
+
|
27
|
+
@matcher.in(nil).is(3)
|
28
|
+
@matcher.description.should == 'ensure length of size is equal to 3 characters'
|
29
|
+
|
30
|
+
@matcher.is(nil).maximum(5)
|
31
|
+
@matcher.description.should == 'ensure length of size is maximum 5 characters'
|
32
|
+
|
33
|
+
@matcher.maximum(nil).minimum(3)
|
34
|
+
@matcher.description.should == 'ensure length of size is minimum 3 characters'
|
35
|
+
|
36
|
+
@matcher.allow_nil(false)
|
37
|
+
@matcher.description.should == 'ensure length of size is minimum 3 characters and not allowing nil values'
|
38
|
+
|
39
|
+
@matcher.allow_blank
|
40
|
+
@matcher.description.should == 'ensure length of size is minimum 3 characters, not allowing nil values, and allowing blank values'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should set less_than_min_length? message' do
|
44
|
+
@matcher.within(4..5).matches?(@model)
|
45
|
+
@matcher.failure_message.should == 'Expected Product to be invalid when size length is less than 4 characters'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should set exactly_min_length? message' do
|
49
|
+
@matcher.should_receive(:less_than_min_length?).and_return(true)
|
50
|
+
@matcher.within(2..5).matches?(@model)
|
51
|
+
@matcher.failure_message.should == 'Expected Product to be valid when size length is 2 characters'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should set more_than_max_length? message' do
|
55
|
+
@matcher.within(3..4).matches?(@model)
|
56
|
+
@matcher.failure_message.should == 'Expected Product to be invalid when size length is more than 4 characters'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should set exactly_max_length? message' do
|
60
|
+
@matcher.should_receive(:more_than_max_length?).and_return(true)
|
61
|
+
@matcher.within(3..6).matches?(@model)
|
62
|
+
@matcher.failure_message.should == 'Expected Product to be valid when size length is 6 characters'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should set allow_blank? message' do
|
66
|
+
@matcher.within(3..5).allow_blank.matches?(@model)
|
67
|
+
@matcher.failure_message.should == 'Expected Product to allow blank values for size'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should set allow_nil? message' do
|
71
|
+
@matcher.within(3..5).allow_nil.matches?(@model)
|
72
|
+
@matcher.failure_message.should == 'Expected Product to allow nil values for size'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'matcher' do
|
77
|
+
# Wrap specs without options. Usually a couple specs.
|
78
|
+
describe 'without options' do
|
79
|
+
before(:each){ define_and_validate }
|
80
|
+
|
81
|
+
it { should validate_length_of(:size, :within => 3..5) }
|
82
|
+
it { should_not validate_length_of(:category, :within => 3..5) }
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "with message option" do
|
86
|
+
|
87
|
+
if RAILS_VERSION =~ /^2.3/
|
88
|
+
it { should define_and_validate(:message => 'not valid').within(3..5).message('not valid') }
|
89
|
+
it { should_not define_and_validate(:message => 'not valid').within(3..5).message('valid') }
|
90
|
+
else
|
91
|
+
it { should define_and_validate(:too_short => 'not valid', :too_long => 'not valid').within(3..5).message('not valid') }
|
92
|
+
it { should_not define_and_validate(:too_short => 'not valid', :too_long => 'not valid').within(3..5).message('valid') }
|
93
|
+
end
|
94
|
+
|
95
|
+
it { should define_and_validate(:is => 4, :message => 'not valid').is(4).message('not valid') }
|
96
|
+
it { should_not define_and_validate(:is => 4, :message => 'not valid').is(4).message('valid') }
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "with too_short option" do
|
100
|
+
it { should define_and_validate(:too_short => 'not valid').within(3..5).too_short('not valid') }
|
101
|
+
it { should_not define_and_validate(:too_short => 'not valid').within(3..5).too_short('valid') }
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "with too_long option" do
|
105
|
+
it { should define_and_validate(:too_long => 'not valid').within(3..5).too_long('not valid') }
|
106
|
+
it { should_not define_and_validate(:too_long => 'not valid').within(3..5).too_long('valid') }
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "with wrong_length option" do
|
110
|
+
it { should define_and_validate(:is => 4, :wrong_length => 'not valid').is(4).wrong_length('not valid') }
|
111
|
+
it { should_not define_and_validate(:is => 4, :wrong_length => 'not valid').is(4).wrong_length('valid') }
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "with within option" do
|
115
|
+
it { should define_and_validate(:within => 3..5).within(3..5) }
|
116
|
+
it { should_not define_and_validate(:within => 3..5).within(2..5) }
|
117
|
+
it { should_not define_and_validate(:within => 3..5).within(4..5) }
|
118
|
+
it { should_not define_and_validate(:within => 3..5).within(3..4) }
|
119
|
+
it { should_not define_and_validate(:within => 3..5).within(3..6) }
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "with in option" do
|
123
|
+
it { should define_and_validate(:in => 3..5).within(3..5) }
|
124
|
+
it { should_not define_and_validate(:in => 3..5).within(2..5) }
|
125
|
+
it { should_not define_and_validate(:in => 3..5).within(4..5) }
|
126
|
+
it { should_not define_and_validate(:in => 3..5).within(3..4) }
|
127
|
+
it { should_not define_and_validate(:in => 3..5).within(3..6) }
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "with minimum option" do
|
131
|
+
it { should define_and_validate(:minimum => 3).minimum(3) }
|
132
|
+
it { should_not define_and_validate(:minimum => 3).minimum(2) }
|
133
|
+
it { should_not define_and_validate(:minimum => 3).minimum(4) }
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "with maximum option" do
|
137
|
+
it { should define_and_validate(:maximum => 3).maximum(3) }
|
138
|
+
it { should_not define_and_validate(:maximum => 3).maximum(2) }
|
139
|
+
it { should_not define_and_validate(:maximum => 3).maximum(4) }
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "with is option" do
|
143
|
+
it { should define_and_validate(:is => 3).is(3) }
|
144
|
+
it { should_not define_and_validate(:is => 3).is(2) }
|
145
|
+
it { should_not define_and_validate(:is => 3).is(4) }
|
146
|
+
end
|
147
|
+
|
148
|
+
# Those are macros to test optionals which accept only boolean values
|
149
|
+
create_optional_boolean_specs(:allow_nil, self)
|
150
|
+
create_optional_boolean_specs(:allow_blank, self)
|
151
|
+
end
|
152
|
+
|
153
|
+
# In macros we include just a few tests to assure that everything works properly
|
154
|
+
describe 'macros' do
|
155
|
+
before(:each) { define_and_validate }
|
156
|
+
|
157
|
+
should_validate_length_of :size, :in => 3..5
|
158
|
+
should_validate_length_of :size, :within => 3..5
|
159
|
+
should_not_validate_length_of :size, :within => 2..5
|
160
|
+
should_not_validate_length_of :size, :within => 4..5
|
161
|
+
should_not_validate_length_of :size, :within => 3..4
|
162
|
+
should_not_validate_length_of :size, :within => 3..6
|
163
|
+
should_not_validate_length_of :category, :in => 3..5
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'validate_numericality_of' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(options={})
|
8
|
+
@model = define_model :product, :price => :integer, :size => :integer do
|
9
|
+
validates_numericality_of :price, options
|
10
|
+
end
|
11
|
+
|
12
|
+
validate_numericality_of(:price)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'messages' do
|
16
|
+
before(:each){ @matcher = define_and_validate }
|
17
|
+
|
18
|
+
# To tests descriptions, we don't need to use mocks neither stubs.
|
19
|
+
# We just need to define a matcher.
|
20
|
+
#
|
21
|
+
it 'should contain a description' do
|
22
|
+
matcher = validate_numericality_of(:age)
|
23
|
+
matcher.description.should == 'ensure numericality of age'
|
24
|
+
|
25
|
+
matcher.allow_nil(false)
|
26
|
+
matcher.description.should == 'ensure numericality of age not allowing nil values'
|
27
|
+
|
28
|
+
matcher.allow_blank
|
29
|
+
matcher.description.should == 'ensure numericality of age not allowing nil values and allowing blank values'
|
30
|
+
|
31
|
+
matcher = validate_numericality_of(:age, :only_integer => true)
|
32
|
+
matcher.description.should == 'ensure numericality of age allowing only integer values'
|
33
|
+
|
34
|
+
matcher = validate_numericality_of(:age, :even => true)
|
35
|
+
matcher.description.should == 'ensure numericality of age allowing only even values'
|
36
|
+
|
37
|
+
matcher = validate_numericality_of(:age, :odd => true)
|
38
|
+
matcher.description.should == 'ensure numericality of age allowing only odd values'
|
39
|
+
|
40
|
+
matcher = validate_numericality_of(:age, :equal_to => 10)
|
41
|
+
matcher.description.should == 'ensure numericality of age is equal to 10'
|
42
|
+
|
43
|
+
matcher = validate_numericality_of(:age, :less_than_or_equal_to => 10)
|
44
|
+
matcher.description.should == 'ensure numericality of age is less than or equal to 10'
|
45
|
+
|
46
|
+
matcher = validate_numericality_of(:age, :greater_than_or_equal_to => 10)
|
47
|
+
matcher.description.should == 'ensure numericality of age is greater than or equal to 10'
|
48
|
+
|
49
|
+
matcher = validate_numericality_of(:age, :less_than => 10)
|
50
|
+
matcher.description.should == 'ensure numericality of age is less than 10'
|
51
|
+
|
52
|
+
matcher = validate_numericality_of(:age, :greater_than => 10)
|
53
|
+
matcher.description.should == 'ensure numericality of age is greater than 10'
|
54
|
+
|
55
|
+
matcher = validate_numericality_of(:age, :greater_than => 10, :less_than => 20)
|
56
|
+
matcher.description.should == 'ensure numericality of age is greater than 10 and is less than 20'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should set only_numeric_values? message' do
|
60
|
+
@matcher.should_receive(:only_numeric_values?).and_return(false)
|
61
|
+
@matcher.matches?(@model)
|
62
|
+
@matcher.failure_message.should == 'Expected Product to allow only numeric values for price'
|
63
|
+
@matcher.negative_failure_message.should == 'Did not expect Product to allow only numeric values for price'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should set only_integer_values? message' do
|
67
|
+
@matcher.should_receive(:only_integer?).and_return([false, { :not => '' }])
|
68
|
+
@matcher.matches?(@model)
|
69
|
+
@matcher.failure_message.should == 'Expected Product to allow only integer values for price'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should set only_odd_values? message' do
|
73
|
+
@matcher.should_receive(:only_odd?).and_return(false)
|
74
|
+
@matcher.matches?(@model)
|
75
|
+
@matcher.failure_message.should == 'Expected Product to allow only odd values for price'
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should set only_even_values? message' do
|
79
|
+
@matcher.should_receive(:only_even?).and_return(false)
|
80
|
+
@matcher.matches?(@model)
|
81
|
+
@matcher.failure_message.should == 'Expected Product to allow only even values for price'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should set equals_to? message' do
|
85
|
+
@matcher.should_receive(:equals_to?).and_return([false, { :count => 10 }])
|
86
|
+
@matcher.matches?(@model)
|
87
|
+
@matcher.failure_message.should == 'Expected Product to be valid only when price is equal to 10'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should set less_than_minimum? message' do
|
91
|
+
@matcher.should_receive(:less_than_minimum?).and_return([false, { :count => 10 }])
|
92
|
+
@matcher.matches?(@model)
|
93
|
+
@matcher.failure_message.should == 'Expected Product to be invalid when price is less than 10'
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should set more_than_maximum? message' do
|
97
|
+
@matcher.should_receive(:more_than_maximum?).and_return([false, { :count => 10 }])
|
98
|
+
@matcher.matches?(@model)
|
99
|
+
@matcher.failure_message.should == 'Expected Product to be invalid when price is greater than 10'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'matcher' do
|
104
|
+
# Wrap specs without options. Usually a couple specs.
|
105
|
+
describe 'without options' do
|
106
|
+
before(:each){ define_and_validate }
|
107
|
+
|
108
|
+
it { should validate_numericality_of(:price) }
|
109
|
+
it { should_not validate_numericality_of(:size) }
|
110
|
+
end
|
111
|
+
|
112
|
+
# Wrap each option inside a describe group.
|
113
|
+
describe 'with equal_to option' do
|
114
|
+
it { should define_and_validate(:equal_to => 100).equal_to(100) }
|
115
|
+
it { should_not define_and_validate(:equal_to => 100).equal_to(99) }
|
116
|
+
it { should_not define_and_validate(:equal_to => 100).equal_to(101) }
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'with less_than option' do
|
120
|
+
it { should define_and_validate(:less_than => 100).less_than(100) }
|
121
|
+
it { should_not define_and_validate(:less_than => 100).less_than(99) }
|
122
|
+
it { should_not define_and_validate(:less_than => 100).less_than(101) }
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'with greater_than option' do
|
126
|
+
it { should define_and_validate(:greater_than => 100).greater_than(100) }
|
127
|
+
it { should_not define_and_validate(:greater_than => 100).greater_than(99) }
|
128
|
+
it { should_not define_and_validate(:greater_than => 100).greater_than(101) }
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'with less_than_or_equal_to option' do
|
132
|
+
it { should define_and_validate(:less_than_or_equal_to => 100).less_than_or_equal_to(100) }
|
133
|
+
it { should_not define_and_validate(:less_than_or_equal_to => 100).less_than_or_equal_to(99) }
|
134
|
+
it { should_not define_and_validate(:less_than_or_equal_to => 100).less_than_or_equal_to(101) }
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'with greater_than_or_equal_to option' do
|
138
|
+
it { should define_and_validate(:greater_than_or_equal_to => 100).greater_than_or_equal_to(100) }
|
139
|
+
it { should_not define_and_validate(:greater_than_or_equal_to => 100).greater_than_or_equal_to(99) }
|
140
|
+
it { should_not define_and_validate(:greater_than_or_equal_to => 100).greater_than_or_equal_to(101) }
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "with even option" do
|
144
|
+
it { should define_and_validate(:even => true).even }
|
145
|
+
it { should_not define_and_validate.even(true) }
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "with odd option" do
|
149
|
+
it { should define_and_validate(:odd => true).odd }
|
150
|
+
it { should_not define_and_validate.odd(true) }
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "with several options" do
|
154
|
+
it { should define_and_validate(:less_than => 100, :greater_than => 10).less_than(100).greater_than(10) }
|
155
|
+
it { should define_and_validate(:less_than => 100, :message => 'not valid').less_than(100).message('not valid') }
|
156
|
+
it { should define_and_validate(:less_than_or_equal_to => 100, :greater_than => 1).less_than_or_equal_to(100).greater_than(1) }
|
157
|
+
end
|
158
|
+
|
159
|
+
# A macro to spec messages
|
160
|
+
create_message_specs(self)
|
161
|
+
|
162
|
+
# Those are macros to test optionals which accept only boolean values
|
163
|
+
create_optional_boolean_specs(:allow_nil, self)
|
164
|
+
create_optional_boolean_specs(:allow_blank, self)
|
165
|
+
create_optional_boolean_specs(:only_integer, self)
|
166
|
+
end
|
167
|
+
|
168
|
+
# In macros we include just a few tests to assure that everything works properly
|
169
|
+
describe 'macros' do
|
170
|
+
before(:each) { define_and_validate(:less_than => 100000, :greater_than => 9999) }
|
171
|
+
|
172
|
+
should_validate_numericality_of :price
|
173
|
+
should_validate_numericality_of :price, :less_than => 100000
|
174
|
+
should_validate_numericality_of :price, :greater_than => 9999
|
175
|
+
should_validate_numericality_of :price, :less_than => 100000, :greater_than => 999
|
176
|
+
should_not_validate_numericality_of :size
|
177
|
+
should_not_validate_numericality_of :price, :less_than => 55555
|
178
|
+
should_not_validate_numericality_of :price, :greater_than => 55555
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'validate_presence_of' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(options={})
|
8
|
+
@model = define_model :product, :title => :string, :size => :string, :category => :string do
|
9
|
+
validates_presence_of :title, :size, options
|
10
|
+
end
|
11
|
+
|
12
|
+
validate_presence_of(:title, :size)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'messages' do
|
16
|
+
before(:each){ @matcher = define_and_validate }
|
17
|
+
|
18
|
+
it 'should contain a description' do
|
19
|
+
@matcher.description.should == 'require title and size to be set'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should set allow_nil? message' do
|
23
|
+
@matcher = validate_presence_of(:category)
|
24
|
+
@matcher.matches?(@model)
|
25
|
+
@matcher.failure_message.should == 'Expected Product to require category to be set'
|
26
|
+
@matcher.negative_failure_message.should == 'Did not expect Product to require category to be set'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'matchers' do
|
31
|
+
describe 'without options' do
|
32
|
+
before(:each){ define_and_validate }
|
33
|
+
|
34
|
+
it { should validate_presence_of(:size) }
|
35
|
+
it { should validate_presence_of(:title) }
|
36
|
+
it { should validate_presence_of(:title, :size) }
|
37
|
+
it { should_not validate_presence_of(:category) }
|
38
|
+
end
|
39
|
+
|
40
|
+
create_message_specs(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'macros' do
|
44
|
+
before(:each){ define_and_validate }
|
45
|
+
|
46
|
+
should_validate_presence_of(:size)
|
47
|
+
should_validate_presence_of(:title)
|
48
|
+
should_validate_presence_of(:size, :title)
|
49
|
+
should_not_validate_presence_of(:category)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'validate_uniqueness_of' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(options={})
|
8
|
+
@model = define_model :user, :username => :string, :email => :integer, :access_code => :string do
|
9
|
+
validates_uniqueness_of :username, options
|
10
|
+
end
|
11
|
+
|
12
|
+
# Create a model
|
13
|
+
User.create(:username => 'jose')
|
14
|
+
|
15
|
+
validate_uniqueness_of(:username)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'messages' do
|
19
|
+
before(:each){ @matcher = define_and_validate }
|
20
|
+
|
21
|
+
it 'should contain a description' do
|
22
|
+
@matcher.description.should == 'require unique values for username'
|
23
|
+
|
24
|
+
@matcher.scope(:email)
|
25
|
+
@matcher.description.should == 'require unique values for username scoped to [:email]'
|
26
|
+
|
27
|
+
@matcher.scope(:email, :access_code)
|
28
|
+
@matcher.description.should == 'require unique values for username scoped to [:email, :access_code]'
|
29
|
+
|
30
|
+
@matcher.case_sensitive
|
31
|
+
@matcher.description.should == 'require unique values for username scoped to [:email, :access_code] and case sensitive'
|
32
|
+
|
33
|
+
@matcher.case_sensitive(false)
|
34
|
+
@matcher.description.should == 'require unique values for username scoped to [:email, :access_code] and case insensitive'
|
35
|
+
|
36
|
+
@matcher.allow_nil
|
37
|
+
@matcher.description.should == 'require unique values for username scoped to [:email, :access_code], case insensitive, and allowing nil values'
|
38
|
+
|
39
|
+
@matcher.allow_blank(false)
|
40
|
+
@matcher.description.should == 'require unique values for username scoped to [:email, :access_code], case insensitive, allowing nil values, and not allowing blank values'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should set responds_to_scope? message' do
|
44
|
+
@matcher.scope(:title).matches?(@model)
|
45
|
+
@matcher.failure_message.should == 'Expected User instance responds to title='
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should set is_unique? message' do
|
49
|
+
@matcher = validate_uniqueness_of(:email)
|
50
|
+
@matcher.matches?(@model)
|
51
|
+
@matcher.failure_message.should == 'Expected User to require unique values for email'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should set case_sensitive? message' do
|
55
|
+
@matcher.case_sensitive(false).matches?(@model)
|
56
|
+
@matcher.failure_message.should == 'Expected User to not be case sensitive on username validation'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should valid with new scope' do
|
60
|
+
@matcher.scope(:email).matches?(@model)
|
61
|
+
@matcher.failure_message.should == 'Expected User to be valid when username scope (email) change'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'matcher' do
|
66
|
+
|
67
|
+
describe 'without options' do
|
68
|
+
before(:each){ define_and_validate }
|
69
|
+
|
70
|
+
it { should validate_uniqueness_of(:username) }
|
71
|
+
it { should_not validate_uniqueness_of(:email) }
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'scoped to' do
|
75
|
+
it { should define_and_validate(:scope => :email).scope(:email) }
|
76
|
+
it { should define_and_validate(:scope => [:email, :access_code]).scope(:email, :access_code) }
|
77
|
+
it { should_not define_and_validate(:scope => :email).scope(:title) }
|
78
|
+
it { should_not define_and_validate(:scope => :email).scope(:access_code) }
|
79
|
+
end
|
80
|
+
|
81
|
+
create_message_specs(self)
|
82
|
+
|
83
|
+
# Those are macros to test optionals which accept only boolean values
|
84
|
+
create_optional_boolean_specs(:allow_nil, self)
|
85
|
+
create_optional_boolean_specs(:allow_blank, self)
|
86
|
+
create_optional_boolean_specs(:case_sensitive, self)
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'errors' do
|
90
|
+
it 'should raise an error if no object is found' do
|
91
|
+
@matcher = define_and_validate
|
92
|
+
User.destroy_all
|
93
|
+
|
94
|
+
proc { @matcher.matches?(@model) }.should raise_error(ScriptError)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should raise an error if no object with not nil attribute is found' do
|
98
|
+
@matcher = define_and_validate.allow_nil
|
99
|
+
User.destroy_all
|
100
|
+
|
101
|
+
User.create(:username => nil)
|
102
|
+
proc { @matcher.matches?(@model) }.should raise_error(ScriptError)
|
103
|
+
|
104
|
+
User.create(:username => 'jose')
|
105
|
+
proc { @matcher.matches?(@model) }.should_not raise_error(ScriptError)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should raise an error if no object with not nil attribute is found' do
|
109
|
+
@matcher = define_and_validate.allow_blank
|
110
|
+
User.destroy_all
|
111
|
+
|
112
|
+
User.create(:username => '')
|
113
|
+
proc { @matcher.matches?(@model) }.should raise_error(ScriptError)
|
114
|
+
|
115
|
+
User.create(:username => 'jose')
|
116
|
+
proc { @matcher.matches?(@model) }.should_not raise_error(ScriptError)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should raise an error if cannot find a new scope value' do
|
120
|
+
@matcher = define_and_validate(:scope => :email).scope(:email)
|
121
|
+
|
122
|
+
User.stub!(:find).and_return do |many, conditions|
|
123
|
+
if many == :all
|
124
|
+
1000.upto(1100).map{|i| User.new(:email => i) }
|
125
|
+
else
|
126
|
+
User.new(:username => 'jose')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
proc { @matcher.matches?(@model) }.should raise_error(ScriptError)
|
130
|
+
|
131
|
+
User.stub!(:find).and_return do |many, conditions|
|
132
|
+
if many == :all
|
133
|
+
1000.upto(1099).map{|i| User.new(:email => i) }
|
134
|
+
else
|
135
|
+
User.new(:username => 'jose')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
proc { @matcher.matches?(@model) }.should_not raise_error(ScriptError)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'macros' do
|
143
|
+
before(:each){ define_and_validate(:scope => :email) }
|
144
|
+
|
145
|
+
should_validate_uniqueness_of :username
|
146
|
+
should_validate_uniqueness_of :username, :scope => :email
|
147
|
+
should_not_validate_uniqueness_of :email
|
148
|
+
should_not_validate_uniqueness_of :username, :scope => :access_code
|
149
|
+
end
|
150
|
+
end
|