remarkable_activerecord 3.1.8 → 3.1.9
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 +140 -138
- data/LICENSE +20 -20
- data/README +80 -80
- data/lib/remarkable_activerecord.rb +29 -29
- data/lib/remarkable_activerecord/base.rb +248 -237
- data/lib/remarkable_activerecord/describe.rb +27 -27
- data/lib/remarkable_activerecord/human_names.rb +36 -36
- data/lib/remarkable_activerecord/matchers/accept_nested_attributes_for_matcher.rb +30 -30
- data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +59 -59
- data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +85 -94
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +283 -283
- data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +68 -68
- data/lib/remarkable_activerecord/matchers/have_default_scope_matcher.rb +38 -38
- data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +73 -73
- data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +30 -30
- data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +85 -85
- data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +50 -50
- data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +97 -97
- data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +44 -44
- data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +53 -53
- data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +52 -52
- data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +150 -150
- data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +181 -181
- data/lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb +29 -29
- data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +233 -233
- data/locale/en.yml +261 -261
- data/spec/accept_nested_attributes_for_matcher_spec.rb +1 -1
- data/spec/allow_mass_assignment_of_matcher_spec.rb +90 -82
- data/spec/allow_values_for_matcher_spec.rb +72 -63
- data/spec/association_matcher_spec.rb +612 -612
- data/spec/describe_spec.rb +3 -3
- data/spec/have_column_matcher_spec.rb +73 -73
- data/spec/have_default_scope_matcher_spec.rb +1 -1
- data/spec/have_index_matcher_spec.rb +87 -87
- data/spec/have_readonly_attributes_matcher_spec.rb +47 -47
- data/spec/have_scope_matcher_spec.rb +77 -77
- data/spec/model_builder.rb +101 -101
- data/spec/rcov.opts +1 -1
- data/spec/spec.opts +4 -4
- data/spec/spec_helper.rb +27 -27
- data/spec/validate_acceptance_of_matcher_spec.rb +68 -68
- data/spec/validate_associated_matcher_spec.rb +121 -121
- data/spec/validate_confirmation_of_matcher_spec.rb +58 -58
- data/spec/validate_length_of_matcher_spec.rb +218 -218
- data/spec/validate_numericality_of_matcher_spec.rb +179 -179
- data/spec/validate_presence_of_matcher_spec.rb +56 -56
- data/spec/validate_uniqueness_of_matcher_spec.rb +164 -164
- metadata +5 -5
@@ -1,126 +1,126 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe 'validate_associated' do
|
4
|
-
include ModelBuilder
|
5
|
-
|
6
|
-
# Defines a model, create a validation and returns a raw matcher
|
7
|
-
def define_and_validate(macro, association, options={})
|
8
|
-
define_model association, :name => :string do
|
9
|
-
if options[:with_builder]
|
10
|
-
validates_acceptance_of :name
|
11
|
-
else
|
12
|
-
validates_presence_of :name
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
options[:message] ||= :invalid
|
17
|
-
|
18
|
-
@model = define_model :project do
|
19
|
-
send(macro, association, :validate => false) unless options[:skip_association]
|
20
|
-
validates_associated association, options.slice(:message) unless options[:skip_validation]
|
21
|
-
end
|
22
|
-
|
23
|
-
validate_associated association
|
24
|
-
end
|
25
|
-
|
26
|
-
describe 'messages' do
|
27
|
-
it 'should contain a description' do
|
28
|
-
define_and_validate(:belongs_to, :company).description.should == 'require associated company to be valid'
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'should set is_valid? message' do
|
32
|
-
matcher = define_and_validate(:belongs_to, :company, :skip_validation => true)
|
33
|
-
matcher.matches?(@model)
|
34
|
-
matcher.failure_message.should == 'Expected Project to be invalid when company is invalid'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe 'error' do
|
39
|
-
it 'should raise an error if the association does not exist' do
|
40
|
-
lambda {
|
41
|
-
should define_and_validate(:belongs_to, :company, :skip_association => true)
|
42
|
-
}.should raise_error(ScriptError, 'Could not find association company on Project.')
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should raise an error if a singular association cannot be built' do
|
46
|
-
lambda {
|
47
|
-
matcher = define_and_validate(:belongs_to, :company)
|
48
|
-
@model.should_receive(:build_company).and_raise(NoMethodError)
|
49
|
-
should matcher
|
50
|
-
}.should raise_error(ScriptError, 'The association object company could not be built. ' <<
|
51
|
-
'You can give me :builder as option or a block which ' <<
|
52
|
-
'returns an association.')
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should raise an error if a plural association cannot be built' do
|
56
|
-
lambda {
|
57
|
-
matcher = define_and_validate(:has_many, :tasks)
|
58
|
-
@model.should_receive(:tasks).and_return(mock=mock('proxy'))
|
59
|
-
mock.should_receive(:build).and_raise(NoMethodError)
|
60
|
-
should matcher
|
61
|
-
}.should raise_error(ScriptError, 'The association object tasks could not be built. ' <<
|
62
|
-
'You can give me :builder as option or a block which ' <<
|
63
|
-
'returns an association.')
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'should raise an error if the associated object cannot be saved as invalid' do
|
67
|
-
lambda {
|
68
|
-
should define_and_validate(:belongs_to, :company, :with_builder => true)
|
69
|
-
}.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
|
70
|
-
'You can give me :builder as option or a block which ' <<
|
71
|
-
'returns an invalid association.')
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'should raise an error if the associated object cannot be saved even when a build is supplied' do
|
75
|
-
lambda {
|
76
|
-
should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{ |p| p.build_company })
|
77
|
-
}.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
|
78
|
-
'You can give me :builder as option or a block which ' <<
|
79
|
-
'returns an invalid association.')
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
describe 'matchers' do
|
84
|
-
it { should define_and_validate(:belongs_to, :company) }
|
85
|
-
it { should define_and_validate(:has_one, :manager) }
|
86
|
-
it { should define_and_validate(:has_many, :tasks) }
|
87
|
-
it { should define_and_validate(:has_and_belongs_to_many, :tags) }
|
88
|
-
|
89
|
-
it { should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{|p| p.build_company(:name => true)}) }
|
90
|
-
it { should define_and_validate(:has_one, :manager, :with_builder => true).builder(proc{|p| p.build_manager(:name => true)}) }
|
91
|
-
it { should define_and_validate(:has_many, :tasks, :with_builder => true).builder(proc{|p| p.tasks.build(:name => true)}) }
|
92
|
-
it { should define_and_validate(:has_and_belongs_to_many, :tags, :with_builder => true).builder(proc{|p| p.tags.build(:name => true)}) }
|
93
|
-
|
94
|
-
it { should_not define_and_validate(:belongs_to, :company, :skip_validation => true) }
|
95
|
-
it { should_not define_and_validate(:has_one, :manager, :skip_validation => true) }
|
96
|
-
it { should_not define_and_validate(:has_many, :tasks, :skip_validation => true) }
|
97
|
-
it { should_not define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
|
98
|
-
|
99
|
-
describe "with message option" do
|
100
|
-
it { should define_and_validate(:belongs_to, :company, :message => 'valid_message').message('valid_message') }
|
101
|
-
it { should_not define_and_validate(:belongs_to, :company, :message => 'not_valid').message('valid_message') }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
describe 'macros' do
|
106
|
-
describe 'belongs to' do
|
107
|
-
before(:each){ define_and_validate(:belongs_to, :company) }
|
108
|
-
should_validate_associated(:company)
|
109
|
-
end
|
110
|
-
|
111
|
-
describe 'has_many with builder' do
|
112
|
-
before(:each){ define_and_validate(:has_many, :tasks, :with_builder => true) }
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'validate_associated' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
# Defines a model, create a validation and returns a raw matcher
|
7
|
+
def define_and_validate(macro, association, options={})
|
8
|
+
define_model association, :name => :string do
|
9
|
+
if options[:with_builder]
|
10
|
+
validates_acceptance_of :name
|
11
|
+
else
|
12
|
+
validates_presence_of :name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
options[:message] ||= :invalid
|
17
|
+
|
18
|
+
@model = define_model :project do
|
19
|
+
send(macro, association, :validate => false) unless options[:skip_association]
|
20
|
+
validates_associated association, options.slice(:message) unless options[:skip_validation]
|
21
|
+
end
|
22
|
+
|
23
|
+
validate_associated association
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'messages' do
|
27
|
+
it 'should contain a description' do
|
28
|
+
define_and_validate(:belongs_to, :company).description.should == 'require associated company to be valid'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should set is_valid? message' do
|
32
|
+
matcher = define_and_validate(:belongs_to, :company, :skip_validation => true)
|
33
|
+
matcher.matches?(@model)
|
34
|
+
matcher.failure_message.should == 'Expected Project to be invalid when company is invalid'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'error' do
|
39
|
+
it 'should raise an error if the association does not exist' do
|
40
|
+
lambda {
|
41
|
+
should define_and_validate(:belongs_to, :company, :skip_association => true)
|
42
|
+
}.should raise_error(ScriptError, 'Could not find association company on Project.')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should raise an error if a singular association cannot be built' do
|
46
|
+
lambda {
|
47
|
+
matcher = define_and_validate(:belongs_to, :company)
|
48
|
+
@model.should_receive(:build_company).and_raise(NoMethodError)
|
49
|
+
should matcher
|
50
|
+
}.should raise_error(ScriptError, 'The association object company could not be built. ' <<
|
51
|
+
'You can give me :builder as option or a block which ' <<
|
52
|
+
'returns an association.')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should raise an error if a plural association cannot be built' do
|
56
|
+
lambda {
|
57
|
+
matcher = define_and_validate(:has_many, :tasks)
|
58
|
+
@model.should_receive(:tasks).and_return(mock=mock('proxy'))
|
59
|
+
mock.should_receive(:build).and_raise(NoMethodError)
|
60
|
+
should matcher
|
61
|
+
}.should raise_error(ScriptError, 'The association object tasks could not be built. ' <<
|
62
|
+
'You can give me :builder as option or a block which ' <<
|
63
|
+
'returns an association.')
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should raise an error if the associated object cannot be saved as invalid' do
|
67
|
+
lambda {
|
68
|
+
should define_and_validate(:belongs_to, :company, :with_builder => true)
|
69
|
+
}.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
|
70
|
+
'You can give me :builder as option or a block which ' <<
|
71
|
+
'returns an invalid association.')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should raise an error if the associated object cannot be saved even when a build is supplied' do
|
75
|
+
lambda {
|
76
|
+
should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{ |p| p.build_company })
|
77
|
+
}.should raise_error(ScriptError, 'The associated object company is not invalid. ' <<
|
78
|
+
'You can give me :builder as option or a block which ' <<
|
79
|
+
'returns an invalid association.')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'matchers' do
|
84
|
+
it { should define_and_validate(:belongs_to, :company) }
|
85
|
+
it { should define_and_validate(:has_one, :manager) }
|
86
|
+
it { should define_and_validate(:has_many, :tasks) }
|
87
|
+
it { should define_and_validate(:has_and_belongs_to_many, :tags) }
|
88
|
+
|
89
|
+
it { should define_and_validate(:belongs_to, :company, :with_builder => true).builder(proc{|p| p.build_company(:name => true)}) }
|
90
|
+
it { should define_and_validate(:has_one, :manager, :with_builder => true).builder(proc{|p| p.build_manager(:name => true)}) }
|
91
|
+
it { should define_and_validate(:has_many, :tasks, :with_builder => true).builder(proc{|p| p.tasks.build(:name => true)}) }
|
92
|
+
it { should define_and_validate(:has_and_belongs_to_many, :tags, :with_builder => true).builder(proc{|p| p.tags.build(:name => true)}) }
|
93
|
+
|
94
|
+
it { should_not define_and_validate(:belongs_to, :company, :skip_validation => true) }
|
95
|
+
it { should_not define_and_validate(:has_one, :manager, :skip_validation => true) }
|
96
|
+
it { should_not define_and_validate(:has_many, :tasks, :skip_validation => true) }
|
97
|
+
it { should_not define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
|
98
|
+
|
99
|
+
describe "with message option" do
|
100
|
+
it { should define_and_validate(:belongs_to, :company, :message => 'valid_message').message('valid_message') }
|
101
|
+
it { should_not define_and_validate(:belongs_to, :company, :message => 'not_valid').message('valid_message') }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'macros' do
|
106
|
+
describe 'belongs to' do
|
107
|
+
before(:each){ define_and_validate(:belongs_to, :company) }
|
108
|
+
should_validate_associated(:company)
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'has_many with builder' do
|
112
|
+
before(:each){ define_and_validate(:has_many, :tasks, :with_builder => true) }
|
113
113
|
should_validate_associated :tasks, :builder => proc{ |p| p.tasks.build(:name => true) }
|
114
114
|
|
115
115
|
should_validate_associated :tasks do |m|
|
116
116
|
m.builder { |p| p.tasks.build(:name => true) }
|
117
117
|
end
|
118
|
-
end
|
119
|
-
|
120
|
-
describe 'has_and_belongs_to_many with skip validation' do
|
121
|
-
before(:each){ define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
|
122
|
-
should_not_validate_associated(:tags)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'has_and_belongs_to_many with skip validation' do
|
121
|
+
before(:each){ define_and_validate(:has_and_belongs_to_many, :tags, :skip_validation => true) }
|
122
|
+
should_not_validate_associated(:tags)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
@@ -1,58 +1,58 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe 'validate_confirmation_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, :name => :string, :email => :string, :age => :string do
|
9
|
-
validates_confirmation_of :name, :email, options
|
10
|
-
end
|
11
|
-
|
12
|
-
validate_confirmation_of(:name, :email)
|
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 name and email to be confirmed'
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should set responds_to_confirmation? message' do
|
23
|
-
@matcher = validate_confirmation_of(:age)
|
24
|
-
@matcher.matches?(@model)
|
25
|
-
@matcher.failure_message.should == 'Expected User instance responds to age_confirmation'
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should set confirms? message' do
|
29
|
-
@model.instance_eval{ def age_confirmation=(*args); end }
|
30
|
-
@matcher = validate_confirmation_of(:age)
|
31
|
-
@matcher.matches?(@model)
|
32
|
-
@matcher.failure_message.should == 'Expected User to be valid only when age is confirmed'
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
describe 'matchers' do
|
38
|
-
|
39
|
-
describe 'without options' do
|
40
|
-
before(:each){ define_and_validate }
|
41
|
-
|
42
|
-
it { should validate_confirmation_of(:name) }
|
43
|
-
it { should validate_confirmation_of(:name, :email) }
|
44
|
-
it { should_not validate_confirmation_of(:name, :age) }
|
45
|
-
end
|
46
|
-
|
47
|
-
create_message_specs(self)
|
48
|
-
end
|
49
|
-
|
50
|
-
describe 'macros' do
|
51
|
-
before(:each){ define_and_validate }
|
52
|
-
|
53
|
-
should_validate_confirmation_of :name
|
54
|
-
should_validate_confirmation_of :name, :email
|
55
|
-
should_not_validate_confirmation_of :name, :age
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'validate_confirmation_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, :name => :string, :email => :string, :age => :string do
|
9
|
+
validates_confirmation_of :name, :email, options
|
10
|
+
end
|
11
|
+
|
12
|
+
validate_confirmation_of(:name, :email)
|
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 name and email to be confirmed'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should set responds_to_confirmation? message' do
|
23
|
+
@matcher = validate_confirmation_of(:age)
|
24
|
+
@matcher.matches?(@model)
|
25
|
+
@matcher.failure_message.should == 'Expected User instance responds to age_confirmation'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should set confirms? message' do
|
29
|
+
@model.instance_eval{ def age_confirmation=(*args); end }
|
30
|
+
@matcher = validate_confirmation_of(:age)
|
31
|
+
@matcher.matches?(@model)
|
32
|
+
@matcher.failure_message.should == 'Expected User to be valid only when age is confirmed'
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'matchers' do
|
38
|
+
|
39
|
+
describe 'without options' do
|
40
|
+
before(:each){ define_and_validate }
|
41
|
+
|
42
|
+
it { should validate_confirmation_of(:name) }
|
43
|
+
it { should validate_confirmation_of(:name, :email) }
|
44
|
+
it { should_not validate_confirmation_of(:name, :age) }
|
45
|
+
end
|
46
|
+
|
47
|
+
create_message_specs(self)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'macros' do
|
51
|
+
before(:each){ define_and_validate }
|
52
|
+
|
53
|
+
should_validate_confirmation_of :name
|
54
|
+
should_validate_confirmation_of :name, :email
|
55
|
+
should_not_validate_confirmation_of :name, :age
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -1,218 +1,218 @@
|
|
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
|
-
describe "with token and separator options" do
|
149
|
-
describe "and words as tokens" do
|
150
|
-
before(:each) do
|
151
|
-
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\w+/) })
|
152
|
-
end
|
153
|
-
|
154
|
-
it { should @matcher.within(3..5).token("word").separator(" ") }
|
155
|
-
it { should_not @matcher.within(2..5).token("word").separator(" ") }
|
156
|
-
it { should_not @matcher.within(4..5).token("word").separator(" ") }
|
157
|
-
it { should_not @matcher.within(3..4).token("word").separator(" ") }
|
158
|
-
it { should_not @matcher.within(3..6).token("word").separator(" ") }
|
159
|
-
it { should_not @matcher.within(3..5).token("word").separator("") }
|
160
|
-
it { should_not @matcher.within(3..5).token("word").separator(" a ") }
|
161
|
-
end
|
162
|
-
|
163
|
-
describe "and digits as tokens" do
|
164
|
-
before(:each) do
|
165
|
-
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\d+/) })
|
166
|
-
end
|
167
|
-
|
168
|
-
it { should @matcher.within(3..5).token("1").separator(" ") }
|
169
|
-
it { should_not @matcher.within(3..5).token("a").separator("") }
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe "with with kind of" do
|
174
|
-
def define_and_validate(options)
|
175
|
-
define_model :variant, :product_id => :integer
|
176
|
-
|
177
|
-
@model = define_model :product do
|
178
|
-
has_many :variants
|
179
|
-
validates_length_of :variants, options
|
180
|
-
end
|
181
|
-
|
182
|
-
validate_length_of(:variants)
|
183
|
-
end
|
184
|
-
|
185
|
-
it { should define_and_validate(:within => 3..6).within(3..6).with_kind_of(Variant) }
|
186
|
-
it { should_not define_and_validate(:within => 2..6).within(3..6).with_kind_of(Variant) }
|
187
|
-
it { should_not define_and_validate(:within => 3..7).within(3..6).with_kind_of(Variant) }
|
188
|
-
|
189
|
-
it "should raise association type mismatch if with_kind_of does not match" do
|
190
|
-
lambda {
|
191
|
-
should_not define_and_validate(:within => 3..6).within(3..6).with_kind_of(Product)
|
192
|
-
}.should raise_error(ActiveRecord::AssociationTypeMismatch)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
# Those are macros to test optionals which accept only boolean values
|
197
|
-
create_optional_boolean_specs(:allow_nil, self)
|
198
|
-
create_optional_boolean_specs(:allow_blank, self)
|
199
|
-
end
|
200
|
-
|
201
|
-
# In macros we include just a few tests to assure that everything works properly
|
202
|
-
describe 'macros' do
|
203
|
-
before(:each) { define_and_validate }
|
204
|
-
|
205
|
-
should_validate_length_of :size, :in => 3..5
|
206
|
-
should_validate_length_of :size, :within => 3..5
|
207
|
-
|
208
|
-
should_not_validate_length_of :size, :within => 2..5
|
209
|
-
should_not_validate_length_of :size, :within => 4..5
|
210
|
-
should_not_validate_length_of :size, :within => 3..4
|
211
|
-
should_not_validate_length_of :size, :within => 3..6
|
212
|
-
should_not_validate_length_of :category, :in => 3..5
|
213
|
-
|
214
|
-
should_validate_length_of :size do |m|
|
215
|
-
m.in = 3..5
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
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
|
+
describe "with token and separator options" do
|
149
|
+
describe "and words as tokens" do
|
150
|
+
before(:each) do
|
151
|
+
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\w+/) })
|
152
|
+
end
|
153
|
+
|
154
|
+
it { should @matcher.within(3..5).token("word").separator(" ") }
|
155
|
+
it { should_not @matcher.within(2..5).token("word").separator(" ") }
|
156
|
+
it { should_not @matcher.within(4..5).token("word").separator(" ") }
|
157
|
+
it { should_not @matcher.within(3..4).token("word").separator(" ") }
|
158
|
+
it { should_not @matcher.within(3..6).token("word").separator(" ") }
|
159
|
+
it { should_not @matcher.within(3..5).token("word").separator("") }
|
160
|
+
it { should_not @matcher.within(3..5).token("word").separator(" a ") }
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "and digits as tokens" do
|
164
|
+
before(:each) do
|
165
|
+
@matcher = define_and_validate(:within => 3..5, :tokenizer => lambda { |str| str.scan(/\d+/) })
|
166
|
+
end
|
167
|
+
|
168
|
+
it { should @matcher.within(3..5).token("1").separator(" ") }
|
169
|
+
it { should_not @matcher.within(3..5).token("a").separator("") }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "with with kind of" do
|
174
|
+
def define_and_validate(options)
|
175
|
+
define_model :variant, :product_id => :integer
|
176
|
+
|
177
|
+
@model = define_model :product do
|
178
|
+
has_many :variants
|
179
|
+
validates_length_of :variants, options
|
180
|
+
end
|
181
|
+
|
182
|
+
validate_length_of(:variants)
|
183
|
+
end
|
184
|
+
|
185
|
+
it { should define_and_validate(:within => 3..6).within(3..6).with_kind_of(Variant) }
|
186
|
+
it { should_not define_and_validate(:within => 2..6).within(3..6).with_kind_of(Variant) }
|
187
|
+
it { should_not define_and_validate(:within => 3..7).within(3..6).with_kind_of(Variant) }
|
188
|
+
|
189
|
+
it "should raise association type mismatch if with_kind_of does not match" do
|
190
|
+
lambda {
|
191
|
+
should_not define_and_validate(:within => 3..6).within(3..6).with_kind_of(Product)
|
192
|
+
}.should raise_error(ActiveRecord::AssociationTypeMismatch)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Those are macros to test optionals which accept only boolean values
|
197
|
+
create_optional_boolean_specs(:allow_nil, self)
|
198
|
+
create_optional_boolean_specs(:allow_blank, self)
|
199
|
+
end
|
200
|
+
|
201
|
+
# In macros we include just a few tests to assure that everything works properly
|
202
|
+
describe 'macros' do
|
203
|
+
before(:each) { define_and_validate }
|
204
|
+
|
205
|
+
should_validate_length_of :size, :in => 3..5
|
206
|
+
should_validate_length_of :size, :within => 3..5
|
207
|
+
|
208
|
+
should_not_validate_length_of :size, :within => 2..5
|
209
|
+
should_not_validate_length_of :size, :within => 4..5
|
210
|
+
should_not_validate_length_of :size, :within => 3..4
|
211
|
+
should_not_validate_length_of :size, :within => 3..6
|
212
|
+
should_not_validate_length_of :category, :in => 3..5
|
213
|
+
|
214
|
+
should_validate_length_of :size do |m|
|
215
|
+
m.in = 3..5
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|