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