shoulda-matchers 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +11 -3
- data/Appraisals +3 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +69 -70
- data/MIT-LICENSE +1 -1
- data/NEWS.md +22 -4
- data/README.md +3 -1
- data/Rakefile +9 -5
- data/features/step_definitions/rails_steps.rb +7 -7
- data/features/support/env.rb +1 -1
- data/gemfiles/3.0.gemfile +1 -1
- data/gemfiles/3.0.gemfile.lock +25 -22
- data/gemfiles/3.1.gemfile +1 -1
- data/gemfiles/3.1.gemfile.lock +27 -24
- data/gemfiles/3.2.gemfile +1 -1
- data/gemfiles/3.2.gemfile.lock +56 -52
- data/lib/shoulda/matchers/action_controller.rb +3 -2
- data/lib/shoulda/matchers/action_controller/assign_to_matcher.rb +10 -8
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +2 -4
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +3 -4
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +3 -4
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +6 -6
- data/lib/shoulda/matchers/action_controller/respond_with_content_type_matcher.rb +5 -2
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +2 -2
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +12 -12
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +3 -4
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +10 -11
- data/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb +121 -0
- data/lib/shoulda/matchers/action_mailer/have_sent_email_matcher.rb +7 -4
- data/lib/shoulda/matchers/active_model.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +8 -8
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +5 -4
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +0 -1
- data/lib/shoulda/matchers/active_model/helpers.rb +16 -7
- data/lib/shoulda/matchers/active_model/only_integer_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +8 -6
- data/lib/shoulda/matchers/active_model/validate_format_of_matcher.rb +19 -10
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +4 -4
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +19 -21
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +7 -7
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +1 -1
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +5 -5
- data/lib/shoulda/matchers/active_record/association_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +11 -7
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +5 -5
- data/lib/shoulda/matchers/active_record/query_the_database_matcher.rb +5 -2
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +3 -3
- data/lib/shoulda/matchers/assertion_error.rb +4 -1
- data/lib/shoulda/matchers/independent/delegate_matcher.rb +17 -7
- data/lib/shoulda/matchers/integrations/rspec.rb +19 -33
- data/lib/shoulda/matchers/version.rb +1 -1
- data/shoulda-matchers.gemspec +6 -4
- data/spec/shoulda/matchers/action_controller/assign_to_matcher_spec.rb +66 -0
- data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +22 -0
- data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +42 -0
- data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +58 -0
- data/spec/shoulda/matchers/action_controller/respond_with_content_type_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +65 -0
- data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +51 -0
- data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +153 -0
- data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +142 -0
- data/spec/shoulda/matchers/action_mailer/have_sent_email_spec.rb +324 -0
- data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +124 -0
- data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +43 -0
- data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +74 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +171 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +113 -0
- data/spec/shoulda/{active_model → matchers/active_model}/exception_message_finder_spec.rb +2 -2
- data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
- data/spec/shoulda/matchers/active_model/only_integer_matcher_spec.rb +52 -0
- data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_model/validate_format_of_matcher_spec.rb +75 -0
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +73 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +127 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +175 -0
- data/spec/shoulda/{active_model → matchers/active_model}/validation_message_finder_spec.rb +0 -1
- data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +106 -0
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +534 -0
- data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +41 -0
- data/spec/shoulda/{active_record → matchers/active_record}/query_the_database_matcher_spec.rb +10 -10
- data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +86 -0
- data/spec/shoulda/{independent → matchers/independent}/delegate_matcher_spec.rb +55 -34
- data/spec/spec_helper.rb +1 -2
- data/spec/support/active_model_versions.rb +4 -0
- data/spec/support/activemodel_helpers.rb +19 -0
- data/spec/support/controller_builder.rb +38 -12
- data/spec/support/model_builder.rb +8 -2
- metadata +106 -98
- data/spec/fixtures/addresses.yml +0 -3
- data/spec/fixtures/friendships.yml +0 -0
- data/spec/fixtures/posts.yml +0 -5
- data/spec/fixtures/products.yml +0 -0
- data/spec/fixtures/taggings.yml +0 -0
- data/spec/fixtures/tags.yml +0 -9
- data/spec/fixtures/users.yml +0 -6
- data/spec/shoulda/action_controller/assign_to_matcher_spec.rb +0 -63
- data/spec/shoulda/action_controller/filter_param_matcher_spec.rb +0 -20
- data/spec/shoulda/action_controller/redirect_to_matcher_spec.rb +0 -40
- data/spec/shoulda/action_controller/render_template_matcher_spec.rb +0 -69
- data/spec/shoulda/action_controller/render_with_layout_matcher_spec.rb +0 -55
- data/spec/shoulda/action_controller/respond_with_content_type_matcher_spec.rb +0 -28
- data/spec/shoulda/action_controller/respond_with_matcher_spec.rb +0 -83
- data/spec/shoulda/action_controller/route_matcher_spec.rb +0 -65
- data/spec/shoulda/action_controller/set_session_matcher_spec.rb +0 -46
- data/spec/shoulda/action_controller/set_the_flash_matcher_spec.rb +0 -130
- data/spec/shoulda/action_mailer/have_sent_email_spec.rb +0 -333
- data/spec/shoulda/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -115
- data/spec/shoulda/active_model/allow_value_matcher_spec.rb +0 -131
- data/spec/shoulda/active_model/disallow_value_matcher_spec.rb +0 -65
- data/spec/shoulda/active_model/ensure_exclusion_of_matcher_spec.rb +0 -79
- data/spec/shoulda/active_model/ensure_inclusion_of_matcher_spec.rb +0 -181
- data/spec/shoulda/active_model/ensure_length_of_matcher_spec.rb +0 -138
- data/spec/shoulda/active_model/helpers_spec.rb +0 -129
- data/spec/shoulda/active_model/only_integer_matcher_spec.rb +0 -69
- data/spec/shoulda/active_model/validate_acceptance_of_matcher_spec.rb +0 -43
- data/spec/shoulda/active_model/validate_confirmation_of_matcher_spec.rb +0 -48
- data/spec/shoulda/active_model/validate_format_of_matcher_spec.rb +0 -79
- data/spec/shoulda/active_model/validate_numericality_of_matcher_spec.rb +0 -112
- data/spec/shoulda/active_model/validate_presence_of_matcher_spec.rb +0 -135
- data/spec/shoulda/active_model/validate_uniqueness_of_matcher_spec.rb +0 -154
- data/spec/shoulda/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -84
- data/spec/shoulda/active_record/association_matcher_spec.rb +0 -642
- data/spec/shoulda/active_record/have_db_column_matcher_spec.rb +0 -185
- data/spec/shoulda/active_record/have_db_index_matcher_spec.rb +0 -105
- data/spec/shoulda/active_record/have_readonly_attributes_matcher_spec.rb +0 -46
- data/spec/shoulda/active_record/serialize_matcher_spec.rb +0 -81
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::AllowMassAssignmentOfMatcher do
|
4
|
+
context '#description' do
|
5
|
+
context 'without a role' do
|
6
|
+
it 'includes the attribute name' do
|
7
|
+
described_class.new(:attr).description.should ==
|
8
|
+
'allow mass assignment of attr'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
if active_model_3_1?
|
13
|
+
context 'with a role' do
|
14
|
+
it 'includes the attribute name and the role' do
|
15
|
+
described_class.new(:attr).as(:admin).description.should ==
|
16
|
+
'allow mass assignment of attr as admin'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'an attribute that is blacklisted from mass-assignment' do
|
23
|
+
it 'rejects being mass-assignable' do
|
24
|
+
model = define_model(:example, :blacklisted => :string) do
|
25
|
+
attr_protected :blacklisted
|
26
|
+
end.new
|
27
|
+
|
28
|
+
model.should_not allow_mass_assignment_of(:blacklisted)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'an attribute that is not whitelisted for mass-assignment' do
|
33
|
+
it 'rejects being mass-assignable' do
|
34
|
+
model = define_model(:example, :not_whitelisted => :string,
|
35
|
+
:whitelisted => :string) do
|
36
|
+
attr_accessible :whitelisted
|
37
|
+
end.new
|
38
|
+
|
39
|
+
model.should_not allow_mass_assignment_of(:not_whitelisted)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'an attribute that is whitelisted for mass-assignment' do
|
44
|
+
it 'accepts being mass-assignable' do
|
45
|
+
define_model(:example, :whitelisted => :string) do
|
46
|
+
attr_accessible :whitelisted
|
47
|
+
end.new.should allow_mass_assignment_of(:whitelisted)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'an attribute not included in the mass-assignment blacklist' do
|
52
|
+
it 'accepts being mass-assignable' do
|
53
|
+
model = define_model(:example, :not_blacklisted => :string,
|
54
|
+
:blacklisted => :string) do
|
55
|
+
attr_protected :blacklisted
|
56
|
+
end.new
|
57
|
+
|
58
|
+
model.should allow_mass_assignment_of(:not_blacklisted)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
unless active_model_3_2?
|
63
|
+
context 'an attribute on a class with no protected attributes' do
|
64
|
+
it 'accepts being mass-assignable' do
|
65
|
+
no_protected_attributes.should allow_mass_assignment_of(:attr)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'assigns a negative failure message' do
|
69
|
+
matcher = allow_mass_assignment_of(:attr)
|
70
|
+
|
71
|
+
matcher.matches?(no_protected_attributes).should be_true
|
72
|
+
|
73
|
+
matcher.failure_message_for_should_not.should_not be_nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def no_protected_attributes
|
78
|
+
define_model(:example, :attr => :string).new
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'an attribute on a class with all protected attributes' do
|
83
|
+
it 'rejects being mass-assignable' do
|
84
|
+
all_protected_attributes.should_not allow_mass_assignment_of(:attr)
|
85
|
+
end
|
86
|
+
|
87
|
+
def all_protected_attributes
|
88
|
+
define_model(:example, :attr => :string) do
|
89
|
+
attr_accessible nil
|
90
|
+
end.new
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
if active_model_3_1?
|
95
|
+
context 'an attribute included in the mass-assignment whitelist for admin role only' do
|
96
|
+
it 'rejects being mass-assignable' do
|
97
|
+
mass_assignable_as_admin.should_not allow_mass_assignment_of(:attr)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'accepts being mass-assignable for admin' do
|
101
|
+
mass_assignable_as_admin.should allow_mass_assignment_of(:attr).as(:admin)
|
102
|
+
end
|
103
|
+
|
104
|
+
def mass_assignable_as_admin
|
105
|
+
define_model(:example, :attr => :string) do
|
106
|
+
attr_accessible :attr, :as => :admin
|
107
|
+
end.new
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
|
4
|
+
context "#description" do
|
5
|
+
it 'describes itself with multiple values' do
|
6
|
+
matcher = allow_value('foo', 'bar').for(:baz)
|
7
|
+
|
8
|
+
matcher.description.should == 'allow baz to be set to any of ["foo", "bar"]'
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'describes itself with a single value' do
|
12
|
+
matcher = allow_value('foo').for(:baz)
|
13
|
+
|
14
|
+
matcher.description.should == 'allow baz to be set to "foo"'
|
15
|
+
end
|
16
|
+
|
17
|
+
if active_model_3_2?
|
18
|
+
it 'describes itself with a strict validation' do
|
19
|
+
strict_matcher = allow_value('xyz').for(:attr).strict
|
20
|
+
|
21
|
+
strict_matcher.description.should ==
|
22
|
+
%q(doesn't raise when attr is set to "xyz")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'an attribute with a validation' do
|
28
|
+
it 'allows a good value' do
|
29
|
+
validating_format(:with => /abc/).should allow_value('abcde').for(:attr)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'rejects a bad value' do
|
33
|
+
validating_format(:with => /abc/).should_not allow_value('xyz').for(:attr)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'allows several good values' do
|
37
|
+
validating_format(:with => /abc/).
|
38
|
+
should allow_value('abcde', 'deabc').for(:attr)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'rejects several bad values' do
|
42
|
+
validating_format(:with => /abc/).
|
43
|
+
should_not allow_value('xyz', 'zyx', nil, []).for(:attr)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'an attribute with a validation and a custom message' do
|
48
|
+
it 'allows a good value' do
|
49
|
+
validating_format(:with => /abc/, :message => 'bad value').
|
50
|
+
should allow_value('abcde').for(:attr).with_message(/bad/)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'rejects a bad value' do
|
54
|
+
validating_format(:with => /abc/, :message => 'bad value').
|
55
|
+
should_not allow_value('xyz').for(:attr).with_message(/bad/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'an attribute with several validations' do
|
60
|
+
let(:model) do
|
61
|
+
define_model :example, :attr => :string do
|
62
|
+
validates_presence_of :attr
|
63
|
+
validates_length_of :attr, :within => 1..5
|
64
|
+
validates_numericality_of :attr, :greater_than_or_equal_to => 1,
|
65
|
+
:less_than_or_equal_to => 50000
|
66
|
+
end.new
|
67
|
+
end
|
68
|
+
bad_values = [nil, '', 'abc', '0', '50001', '123456', []]
|
69
|
+
|
70
|
+
it 'allows a good value' do
|
71
|
+
model.should allow_value('12345').for(:attr)
|
72
|
+
end
|
73
|
+
|
74
|
+
bad_values.each do |bad_value|
|
75
|
+
it "rejects a bad value (#{bad_value.inspect})" do
|
76
|
+
model.should_not allow_value(bad_value).for(:attr)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "rejects several bad values (#{bad_values.map(&:inspect).join(', ')})" do
|
81
|
+
model.should_not allow_value(*bad_values).for(:attr)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with a single value' do
|
86
|
+
it 'allows you to call description before calling matches?' do
|
87
|
+
model = define_model(:example, :attr => :string).new
|
88
|
+
matcher = described_class.new('foo').for(:attr)
|
89
|
+
matcher.description
|
90
|
+
|
91
|
+
expect { matcher.matches?(model) }.not_to raise_error(NoMethodError)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'with no values' do
|
96
|
+
it 'raises an error' do
|
97
|
+
expect { allow_value.for(:baz) }.
|
98
|
+
to raise_error(ArgumentError, /at least one argument/)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
if active_model_3_2?
|
103
|
+
context 'an attribute with a strict format validation' do
|
104
|
+
it 'strictly rejects a bad value' do
|
105
|
+
validating_format(:with => /abc/, :strict => true).
|
106
|
+
should_not allow_value('xyz').for(:attr).strict
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'strictly allows a bad value with a different message' do
|
110
|
+
validating_format(:with => /abc/, :strict => true).
|
111
|
+
should allow_value('xyz').for(:attr).with_message(/abc/).strict
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'provides a useful negative failure message' do
|
115
|
+
matcher = allow_value('xyz').for(:attr).strict.with_message(/abc/)
|
116
|
+
|
117
|
+
matcher.matches?(validating_format(:with => /abc/, :strict => true))
|
118
|
+
|
119
|
+
matcher.failure_message_for_should_not.should == 'Expected exception to include /abc/ ' +
|
120
|
+
'when attr is set to "xyz", got Attr is invalid'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher do
|
4
|
+
it 'does not allow any types' do
|
5
|
+
matcher('abcde').allowed_types.should == ''
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'an attribute with a format validation' do
|
9
|
+
it 'does not match if the value is allowed' do
|
10
|
+
validating_format(:with => /abc/).should_not matcher('abcde').for(:attr)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'matches if the value is not allowed' do
|
14
|
+
validating_format(:with => /abc/).should matcher('xyz').for(:attr)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'an attribute with a format validation and a custom message' do
|
19
|
+
it 'does not match if the value and message are both correct' do
|
20
|
+
validating_format(:with => /abc/, :message => 'good message').
|
21
|
+
should_not matcher('abcde').for(:attr).with_message('good message')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "delegates its failure message to its allow matcher's negative failure message" do
|
25
|
+
allow_matcher = stub_everything(:failure_message_for_should_not => 'allow matcher failure')
|
26
|
+
Shoulda::Matchers::ActiveModel::AllowValueMatcher.stubs(:new).returns(allow_matcher)
|
27
|
+
|
28
|
+
matcher = matcher('abcde').for(:attr).with_message('good message')
|
29
|
+
matcher.matches?(validating_format(:with => /abc/, :message => 'good message'))
|
30
|
+
|
31
|
+
matcher.failure_message_for_should.should == 'allow matcher failure'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'matches if the message is correct but the value is not' do
|
35
|
+
validating_format(:with => /abc/, :message => 'good message').
|
36
|
+
should matcher('xyz').for(:attr).with_message('good message')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def matcher(value)
|
41
|
+
described_class.new(value)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::EnsureExclusionOfMatcher do
|
4
|
+
context 'an attribute which must be excluded from a range' do
|
5
|
+
it 'accepts ensuring the correct range' do
|
6
|
+
validating_exclusion(:in => 2..5).
|
7
|
+
should ensure_exclusion_of(:attr).in_range(2..5)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'rejects ensuring excluded value' do
|
11
|
+
validating_exclusion(:in => 2..5).
|
12
|
+
should_not ensure_exclusion_of(:attr).in_range(2..6)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'does not override the default message with a blank' do
|
16
|
+
validating_exclusion(:in => 2..5).
|
17
|
+
should ensure_exclusion_of(:attr).in_range(2..5).with_message(nil)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'an attribute with a custom validation message' do
|
22
|
+
it 'accepts ensuring the correct range' do
|
23
|
+
validating_exclusion(:in => 2..4, :message => 'not good').
|
24
|
+
should ensure_exclusion_of(:attr).in_range(2..4).with_message(/not good/)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'an attribute with custom range validations' do
|
29
|
+
it 'accepts ensuring the correct range and messages' do
|
30
|
+
model = custom_validation do
|
31
|
+
if attr >= 2 && attr <= 5
|
32
|
+
errors.add(:attr, 'should be out of this range')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
model.should ensure_exclusion_of(:attr).in_range(2..5).
|
37
|
+
with_message(/should be out of this range/)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'an attribute which must be excluded from an array' do
|
42
|
+
it 'accepts with correct array' do
|
43
|
+
validating_exclusion(:in => %w(one two)).
|
44
|
+
should ensure_exclusion_of(:attr).in_array(%w(one two))
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'rejects when only part of array matches' do
|
48
|
+
validating_exclusion(:in => %w(one two)).
|
49
|
+
should_not ensure_exclusion_of(:attr).in_array(%w(one wrong_value))
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'rejects when array does not match at all' do
|
53
|
+
validating_exclusion(:in => %w(one two)).
|
54
|
+
should_not ensure_exclusion_of(:attr).in_array(%w(cat dog))
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'has correct description' do
|
58
|
+
ensure_exclusion_of(:attr).in_array([true, 'dog']).description.
|
59
|
+
should == 'ensure exclusion of attr in [true, "dog"]'
|
60
|
+
end
|
61
|
+
|
62
|
+
def validating_exclusion(options)
|
63
|
+
define_model(:example, :attr => :string) do
|
64
|
+
validates_exclusion_of :attr, options
|
65
|
+
end.new
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def validating_exclusion(options)
|
70
|
+
define_model(:example, :attr => :integer) do
|
71
|
+
validates_exclusion_of :attr, options
|
72
|
+
end.new
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::EnsureInclusionOfMatcher do
|
4
|
+
context 'with no validations' do
|
5
|
+
it 'rejects an array which does not have a validator defined' do
|
6
|
+
define_model(:example, :attr => :string).new.
|
7
|
+
should_not ensure_inclusion_of(:attr).in_array(%w(Yes No))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'with true/false values' do
|
12
|
+
it 'can verify outside values to ensure the negative case' do
|
13
|
+
define_model(:example, :attr => :string).new.
|
14
|
+
should_not ensure_inclusion_of(:attr).in_array([true, false])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'where we cannot determine a value outside the array' do
|
19
|
+
it 'raises a custom exception' do
|
20
|
+
model = define_model(:example, :attr => :string).new
|
21
|
+
|
22
|
+
arbitrary_string = described_class::ARBITRARY_OUTSIDE_STRING
|
23
|
+
expect { model.should ensure_inclusion_of(:attr).in_array([arbitrary_string]) }.to raise_error Shoulda::Matchers::ActiveModel::CouldNotDetermineValueOutsideOfArray
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'an attribute which must be included in a range' do
|
28
|
+
it 'accepts ensuring the correct range' do
|
29
|
+
validating_inclusion(:in => 2..5).
|
30
|
+
should ensure_inclusion_of(:attr).in_range(2..5)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'rejects ensuring a lower minimum value' do
|
34
|
+
validating_inclusion(:in => 2..5).
|
35
|
+
should_not ensure_inclusion_of(:attr).in_range(1..5)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'rejects ensuring a higher minimum value' do
|
39
|
+
validating_inclusion(:in => 2..5).
|
40
|
+
should_not ensure_inclusion_of(:attr).in_range(3..5)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'rejects ensuring a lower maximum value' do
|
44
|
+
validating_inclusion(:in => 2..5).
|
45
|
+
should_not ensure_inclusion_of(:attr).in_range(2..4)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'rejects ensuring a higher maximum value' do
|
49
|
+
validating_inclusion(:in => 2..5).
|
50
|
+
should_not ensure_inclusion_of(:attr).in_range(2..6)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'does not override the default message with a blank' do
|
54
|
+
validating_inclusion(:in => 2..5).
|
55
|
+
should ensure_inclusion_of(:attr).in_range(2..5).with_message(nil)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'an attribute with a custom ranged value validation' do
|
60
|
+
it 'accepts ensuring the correct range' do
|
61
|
+
validating_inclusion(:in => 2..4, :message => 'not good').
|
62
|
+
should ensure_inclusion_of(:attr).in_range(2..4).with_message(/not good/)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'an attribute with custom range validations' do
|
67
|
+
it 'accepts ensuring the correct range and messages' do
|
68
|
+
model = custom_validation do
|
69
|
+
if attr < 2
|
70
|
+
errors.add(:attr, 'too low')
|
71
|
+
elsif attr > 5
|
72
|
+
errors.add(:attr, 'too high')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
model.should ensure_inclusion_of(:attr).in_range(2..5).
|
77
|
+
with_low_message(/low/).with_high_message(/high/)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'an attribute which must be included in an array' do
|
82
|
+
it 'accepts with correct array' do
|
83
|
+
validating_inclusion(:in => %w(one two)).
|
84
|
+
should ensure_inclusion_of(:attr).in_array(%w(one two))
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'rejects when only part of array matches' do
|
88
|
+
validating_inclusion(:in => %w(one two)).
|
89
|
+
should_not ensure_inclusion_of(:attr).in_array(%w(one wrong_value))
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'rejects when array does not match at all' do
|
93
|
+
validating_inclusion(:in => %w(one two)).
|
94
|
+
should_not ensure_inclusion_of(:attr).in_array(%w(cat dog))
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'has correct description' do
|
98
|
+
ensure_inclusion_of(:attr).in_array([true, "dog"]).description.
|
99
|
+
should == 'ensure inclusion of attr in [true, "dog"]'
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'rejects allow_blank' do
|
103
|
+
validating_inclusion(:in => %w(one two)).
|
104
|
+
should_not ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(true)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'accepts allow_blank(false)' do
|
108
|
+
validating_inclusion(:in => %w(one two)).
|
109
|
+
should ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(false)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'rejects allow_nil' do
|
113
|
+
validating_inclusion(:in => %w(one two)).
|
114
|
+
should_not ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(true)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'accepts allow_nil(false)' do
|
118
|
+
validating_inclusion(:in => %w(one two)).
|
119
|
+
should ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(false)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'with allowed blank and allowed nil' do
|
124
|
+
it 'accepts allow_blank' do
|
125
|
+
validating_inclusion(:in => %w(one two), :allow_blank => true).
|
126
|
+
should ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'rejects allow_blank(false)' do
|
130
|
+
validating_inclusion(:in => %w(one two), :allow_blank => true).
|
131
|
+
should_not ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(false)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'accepts allow_nil' do
|
135
|
+
validating_inclusion(:in => %w(one two), :allow_nil => true).
|
136
|
+
should ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'rejects allow_nil' do
|
140
|
+
validating_inclusion(:in => %w(one two), :allow_nil => true).
|
141
|
+
should_not ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(false)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'an attribute allowing some blank values but not others' do
|
146
|
+
it 'rejects allow_blank' do
|
147
|
+
validating_inclusion(:in => ['one', 'two', '']).
|
148
|
+
should_not ensure_inclusion_of(:attr).in_array(['one', 'two', '']).allow_blank(true)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
if active_model_3_2?
|
153
|
+
context 'a strict attribute which must be included in a range' do
|
154
|
+
it 'accepts ensuring the correct range' do
|
155
|
+
validating_inclusion(:in => 2..5, :strict => true).
|
156
|
+
should ensure_inclusion_of(:attr).in_range(2..5).strict
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'rejects ensuring another range' do
|
160
|
+
validating_inclusion(:in => 2..5, :strict => true).
|
161
|
+
should_not ensure_inclusion_of(:attr).in_range(2..6).strict
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def validating_inclusion(options)
|
168
|
+
define_model(:example, :attr => :string) do
|
169
|
+
validates_inclusion_of :attr, options
|
170
|
+
end.new
|
171
|
+
end
|