remarkable_activerecord 3.1.8 → 3.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/CHANGELOG +140 -138
  2. data/LICENSE +20 -20
  3. data/README +80 -80
  4. data/lib/remarkable_activerecord.rb +29 -29
  5. data/lib/remarkable_activerecord/base.rb +248 -237
  6. data/lib/remarkable_activerecord/describe.rb +27 -27
  7. data/lib/remarkable_activerecord/human_names.rb +36 -36
  8. data/lib/remarkable_activerecord/matchers/accept_nested_attributes_for_matcher.rb +30 -30
  9. data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +59 -59
  10. data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +85 -94
  11. data/lib/remarkable_activerecord/matchers/association_matcher.rb +283 -283
  12. data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +68 -68
  13. data/lib/remarkable_activerecord/matchers/have_default_scope_matcher.rb +38 -38
  14. data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +73 -73
  15. data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +30 -30
  16. data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +85 -85
  17. data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +50 -50
  18. data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +97 -97
  19. data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +44 -44
  20. data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +53 -53
  21. data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +52 -52
  22. data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +150 -150
  23. data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +181 -181
  24. data/lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb +29 -29
  25. data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +233 -233
  26. data/locale/en.yml +261 -261
  27. data/spec/accept_nested_attributes_for_matcher_spec.rb +1 -1
  28. data/spec/allow_mass_assignment_of_matcher_spec.rb +90 -82
  29. data/spec/allow_values_for_matcher_spec.rb +72 -63
  30. data/spec/association_matcher_spec.rb +612 -612
  31. data/spec/describe_spec.rb +3 -3
  32. data/spec/have_column_matcher_spec.rb +73 -73
  33. data/spec/have_default_scope_matcher_spec.rb +1 -1
  34. data/spec/have_index_matcher_spec.rb +87 -87
  35. data/spec/have_readonly_attributes_matcher_spec.rb +47 -47
  36. data/spec/have_scope_matcher_spec.rb +77 -77
  37. data/spec/model_builder.rb +101 -101
  38. data/spec/rcov.opts +1 -1
  39. data/spec/spec.opts +4 -4
  40. data/spec/spec_helper.rb +27 -27
  41. data/spec/validate_acceptance_of_matcher_spec.rb +68 -68
  42. data/spec/validate_associated_matcher_spec.rb +121 -121
  43. data/spec/validate_confirmation_of_matcher_spec.rb +58 -58
  44. data/spec/validate_length_of_matcher_spec.rb +218 -218
  45. data/spec/validate_numericality_of_matcher_spec.rb +179 -179
  46. data/spec/validate_presence_of_matcher_spec.rb +56 -56
  47. data/spec/validate_uniqueness_of_matcher_spec.rb +164 -164
  48. 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