mcmire-shoulda-matchers 2.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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +32 -0
- data/.yardopts +7 -0
- data/Appraisals +45 -0
- data/CONTRIBUTING.md +41 -0
- data/Gemfile +31 -0
- data/Gemfile.lock +166 -0
- data/MIT-LICENSE +22 -0
- data/NEWS.md +299 -0
- data/README.md +163 -0
- data/Rakefile +116 -0
- data/doc_config/gh-pages/index.html.erb +9 -0
- data/doc_config/yard/setup.rb +22 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +300 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
- data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
- data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
- data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
- data/doc_config/yard/templates/default/layout/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
- data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
- data/features/rails_integration.feature +113 -0
- data/features/step_definitions/rails_steps.rb +162 -0
- data/features/support/env.rb +5 -0
- data/gemfiles/3.0.gemfile +24 -0
- data/gemfiles/3.0.gemfile.lock +150 -0
- data/gemfiles/3.1.gemfile +27 -0
- data/gemfiles/3.1.gemfile.lock +173 -0
- data/gemfiles/3.2.gemfile +27 -0
- data/gemfiles/3.2.gemfile.lock +171 -0
- data/gemfiles/4.0.0.gemfile +28 -0
- data/gemfiles/4.0.0.gemfile.lock +172 -0
- data/gemfiles/4.0.1.gemfile +28 -0
- data/gemfiles/4.0.1.gemfile.lock +172 -0
- data/lib/shoulda-matchers.rb +1 -0
- data/lib/shoulda/matchers.rb +11 -0
- data/lib/shoulda/matchers/action_controller.rb +17 -0
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +64 -0
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +97 -0
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +81 -0
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +117 -0
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +114 -0
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +154 -0
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +116 -0
- data/lib/shoulda/matchers/action_controller/route_params.rb +48 -0
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +164 -0
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +296 -0
- data/lib/shoulda/matchers/active_model.rb +30 -0
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +167 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +314 -0
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +46 -0
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +160 -0
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +417 -0
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +337 -0
- data/lib/shoulda/matchers/active_model/errors.rb +10 -0
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +58 -0
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +92 -0
- data/lib/shoulda/matchers/active_model/helpers.rb +46 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +75 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +26 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +112 -0
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +77 -0
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +121 -0
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +380 -0
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +89 -0
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +372 -0
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +97 -0
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +69 -0
- data/lib/shoulda/matchers/active_record.rb +22 -0
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +204 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +901 -0
- data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +81 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +65 -0
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +94 -0
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +63 -0
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +261 -0
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +149 -0
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +72 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +181 -0
- data/lib/shoulda/matchers/assertion_error.rb +19 -0
- data/lib/shoulda/matchers/error.rb +6 -0
- data/lib/shoulda/matchers/integrations/rspec.rb +20 -0
- data/lib/shoulda/matchers/integrations/test_unit.rb +30 -0
- data/lib/shoulda/matchers/rails_shim.rb +50 -0
- data/lib/shoulda/matchers/version.rb +6 -0
- data/lib/shoulda/matchers/warn.rb +8 -0
- data/shoulda-matchers.gemspec +23 -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 +63 -0
- data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +70 -0
- data/spec/shoulda/matchers/action_controller/route_params_spec.rb +30 -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/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +170 -0
- data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +81 -0
- data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +95 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +320 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +166 -0
- data/spec/shoulda/matchers/active_model/exception_message_finder_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +20 -0
- data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +169 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +57 -0
- data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +139 -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 +47 -0
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +331 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +180 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +398 -0
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +127 -0
- data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +107 -0
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +860 -0
- data/spec/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +247 -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/matchers/active_record/serialize_matcher_spec.rb +86 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/active_model_versions.rb +13 -0
- data/spec/support/active_resource_builder.rb +29 -0
- data/spec/support/activemodel_helpers.rb +19 -0
- data/spec/support/capture_helpers.rb +19 -0
- data/spec/support/class_builder.rb +42 -0
- data/spec/support/controller_builder.rb +74 -0
- data/spec/support/fail_with_message_including_matcher.rb +33 -0
- data/spec/support/fail_with_message_matcher.rb +32 -0
- data/spec/support/i18n_faker.rb +10 -0
- data/spec/support/mailer_builder.rb +10 -0
- data/spec/support/model_builder.rb +81 -0
- data/spec/support/rails_versions.rb +18 -0
- data/spec/support/shared_examples/numerical_submatcher.rb +19 -0
- data/spec/support/shared_examples/numerical_type_submatcher.rb +17 -0
- data/spec/support/test_application.rb +120 -0
- data/yard.watchr +5 -0
- metadata +281 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::EvenNumberMatcher do
|
4
|
+
subject { described_class.new(:attr) }
|
5
|
+
|
6
|
+
it_behaves_like 'a numerical submatcher'
|
7
|
+
it_behaves_like 'a numerical type submatcher'
|
8
|
+
|
9
|
+
it 'allows even number' do
|
10
|
+
expect(subject.allowed_type).to eq 'even numbers'
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#diff_to_compare' do
|
14
|
+
it { expect(subject.diff_to_compare).to eq 2 }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when the model has an even validation' do
|
18
|
+
it 'matches' do
|
19
|
+
match = subject
|
20
|
+
expect(validating_even_number).to match
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when the model does not have an even validation' do
|
25
|
+
it 'does not match' do
|
26
|
+
match = subject
|
27
|
+
expect(not_validating_even_number).not_to match
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'fails with the ActiveRecord :even message' do
|
31
|
+
match = subject
|
32
|
+
expect {
|
33
|
+
expect(not_validating_even_number).to match
|
34
|
+
}.to fail_with_message_including('Expected errors to include "must be even"')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with custom validation message' do
|
39
|
+
it 'only accepts even number values for that attribute with that message' do
|
40
|
+
expect(validating_even_number(message: 'custom')).to subject.with_message(/custom/)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'fails even number values for that attribute with another message' do
|
44
|
+
expect(validating_even_number(message: 'custom')).not_to subject.with_message(/wrong/)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def validating_even_number(options = {})
|
50
|
+
define_model :example, attr: :string do
|
51
|
+
validates_numericality_of :attr, { even: true }.merge(options)
|
52
|
+
end.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def not_validating_even_number
|
56
|
+
define_model(:example, attr: :string).new
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::OddNumberMatcher do
|
4
|
+
subject { described_class.new(:attr) }
|
5
|
+
|
6
|
+
it_behaves_like 'a numerical submatcher'
|
7
|
+
it_behaves_like 'a numerical type submatcher'
|
8
|
+
|
9
|
+
it 'allows odd number' do
|
10
|
+
expect(subject.allowed_type).to eq 'odd numbers'
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#diff_to_compare' do
|
14
|
+
it { expect(subject.diff_to_compare).to eq 2 }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when the model has an odd validation' do
|
18
|
+
it 'matches' do
|
19
|
+
match = subject
|
20
|
+
expect(validating_odd_number).to match
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when the model does not have an odd validation' do
|
25
|
+
it 'does not match' do
|
26
|
+
match = subject
|
27
|
+
expect(not_validating_odd_number).not_to match
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'fails with the ActiveRecord :odd message' do
|
31
|
+
match = subject
|
32
|
+
expect {
|
33
|
+
expect(not_validating_odd_number).to match
|
34
|
+
}.to fail_with_message_including('Expected errors to include "must be odd"')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with custom validation message' do
|
39
|
+
it 'only accepts odd number values for that attribute with that message' do
|
40
|
+
expect(validating_odd_number(message: 'custom')).to subject.with_message(/custom/)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'fails odd number values for that attribute with another message' do
|
44
|
+
expect(validating_odd_number(message: 'custom')).not_to subject.with_message(/wrong/)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def validating_odd_number(options = {})
|
50
|
+
define_model :example, attr: :string do
|
51
|
+
validates_numericality_of :attr, { odd: true }.merge(options)
|
52
|
+
end.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def not_validating_odd_number
|
56
|
+
define_model(:example, attr: :string).new
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::OnlyIntegerMatcher do
|
4
|
+
subject { described_class.new(:attr) }
|
5
|
+
|
6
|
+
it_behaves_like 'a numerical submatcher'
|
7
|
+
it_behaves_like 'a numerical type submatcher'
|
8
|
+
|
9
|
+
it 'allows integer types' do
|
10
|
+
expect(subject.allowed_type).to eq 'integers'
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#diff_to_compare' do
|
14
|
+
it { expect(subject.diff_to_compare).to eq 1 }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'given an attribute that only allows integer values' do
|
18
|
+
it 'matches' do
|
19
|
+
match = subject
|
20
|
+
expect(validating_only_integer).to match
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'given an attribute that only allows integer values with a custom validation message' do
|
25
|
+
it 'only accepts integer values for that attribute with that message' do
|
26
|
+
expect(validating_only_integer(message: 'custom')).to subject.with_message(/custom/)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'rejects integer values for that attribute with another message' do
|
30
|
+
expect(validating_only_integer(message: 'custom')).not_to subject.with_message(/wrong/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when the model does not have an only_integer validation' do
|
35
|
+
it 'does not match' do
|
36
|
+
match = subject
|
37
|
+
expect(not_validating_only_integer).not_to match
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'fails with the ActiveRecord :not_an_integer message' do
|
41
|
+
match = subject
|
42
|
+
expect {
|
43
|
+
expect(not_validating_only_integer).to match
|
44
|
+
}.to fail_with_message_including('Expected errors to include "must be an integer"')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def validating_only_integer(options = {})
|
49
|
+
define_model :example, attr: :string do
|
50
|
+
validates_numericality_of :attr, { only_integer: true }.merge(options)
|
51
|
+
end.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def not_validating_only_integer
|
55
|
+
define_model(:example, attr: :string).new
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher do
|
4
|
+
if active_model_4_0?
|
5
|
+
context 'a model with an absence validation' do
|
6
|
+
it 'accepts' do
|
7
|
+
expect(validating_absence_of(:attr)).to validate_absence_of(:attr)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'does not override the default message with a present' do
|
11
|
+
expect(validating_absence_of(:attr)).to validate_absence_of(:attr).with_message(nil)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'a model without an absence validation' do
|
16
|
+
it 'rejects' do
|
17
|
+
model = define_model(:example, attr: :string).new
|
18
|
+
expect(model).not_to validate_absence_of(:attr)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'an ActiveModel class with an absence validation' do
|
23
|
+
it 'accepts' do
|
24
|
+
expect(active_model_validating_absence_of(:attr)).to validate_absence_of(:attr)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does not override the default message with a blank' do
|
28
|
+
expect(active_model_validating_absence_of(:attr)).to validate_absence_of(:attr).with_message(nil)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'an ActiveModel class without an absence validation' do
|
33
|
+
it 'rejects' do
|
34
|
+
expect(active_model_with(:attr)).not_to validate_absence_of(:attr)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'provides the correct failure message' do
|
38
|
+
message = %{Expected errors to include "must be blank" when attr is set to "an arbitrary value", got no errors}
|
39
|
+
|
40
|
+
expect { expect(active_model_with(:attr)).to validate_absence_of(:attr) }.to fail_with_message(message)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'a has_many association with an absence validation' do
|
45
|
+
it 'requires the attribute to not be set' do
|
46
|
+
expect(having_many(:children, absence: true)).to validate_absence_of(:children)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'a has_many association without an absence validation' do
|
51
|
+
it 'does not require the attribute to not be set' do
|
52
|
+
expect(having_many(:children, absence: false)).
|
53
|
+
not_to validate_absence_of(:children)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'an absent has_and_belongs_to_many association' do
|
58
|
+
it 'accepts' do
|
59
|
+
model = having_and_belonging_to_many(:children, absence: true)
|
60
|
+
expect(model).to validate_absence_of(:children)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'a non-absent has_and_belongs_to_many association' do
|
65
|
+
it 'rejects' do
|
66
|
+
model = having_and_belonging_to_many(:children, absence: false)
|
67
|
+
expect(model).not_to validate_absence_of(:children)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "an i18n translation containing %{attribute} and %{model}" do
|
72
|
+
after { I18n.backend.reload! }
|
73
|
+
|
74
|
+
it "does not raise an exception" do
|
75
|
+
stub_translation("activerecord.errors.messages.present",
|
76
|
+
"%{attribute} must be blank in a %{model}")
|
77
|
+
|
78
|
+
expect {
|
79
|
+
expect(validating_absence_of(:attr)).to validate_absence_of(:attr)
|
80
|
+
}.to_not raise_exception
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "an attribute with a context-dependent validation" do
|
85
|
+
context "without the validation context" do
|
86
|
+
it "does not match" do
|
87
|
+
expect(validating_absence_of(:attr, on: :customisable)).not_to validate_absence_of(:attr)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "with the validation context" do
|
92
|
+
it "matches" do
|
93
|
+
expect(validating_absence_of(:attr, on: :customisable)).to validate_absence_of(:attr).on(:customisable)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def validating_absence_of(attr, options = {})
|
99
|
+
define_model :example, attr => :string do
|
100
|
+
validates_absence_of attr, options
|
101
|
+
end.new
|
102
|
+
end
|
103
|
+
|
104
|
+
def active_model_with(attr, &block)
|
105
|
+
define_active_model_class('Example', accessors: [attr], &block).new
|
106
|
+
end
|
107
|
+
|
108
|
+
def active_model_validating_absence_of(attr)
|
109
|
+
active_model_with(attr) do
|
110
|
+
validates_absence_of attr
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def having_many(plural_name, options = {})
|
115
|
+
define_model plural_name.to_s.singularize
|
116
|
+
define_model :parent do
|
117
|
+
has_many plural_name
|
118
|
+
if options[:absence]
|
119
|
+
validates_absence_of plural_name
|
120
|
+
end
|
121
|
+
end.new
|
122
|
+
end
|
123
|
+
|
124
|
+
def having_and_belonging_to_many(plural_name, options = {})
|
125
|
+
create_table 'children_parents', id: false do |t|
|
126
|
+
t.integer "#{plural_name.to_s.singularize}_id"
|
127
|
+
t.integer :parent_id
|
128
|
+
end
|
129
|
+
|
130
|
+
define_model plural_name.to_s.singularize
|
131
|
+
define_model :parent do
|
132
|
+
has_and_belongs_to_many plural_name
|
133
|
+
if options[:absence]
|
134
|
+
validates_absence_of plural_name
|
135
|
+
end
|
136
|
+
end.new
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidateAcceptanceOfMatcher do
|
4
|
+
context 'a model with an acceptance validation' do
|
5
|
+
it 'accepts when the attributes match' do
|
6
|
+
expect(validating_acceptance).to matcher
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'does not overwrite the default message with nil' do
|
10
|
+
expect(validating_acceptance).to matcher.with_message(nil)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'a model without an acceptance validation' do
|
15
|
+
it 'rejects' do
|
16
|
+
expect(define_model(:example, attr: :string).new).not_to matcher
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'an attribute which must be accepted with a custom message' do
|
21
|
+
it 'accepts when the message matches' do
|
22
|
+
expect(validating_acceptance(message: 'custom')).
|
23
|
+
to matcher.with_message(/custom/)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'rejects when the message does not match' do
|
27
|
+
expect(validating_acceptance(message: 'custom')).
|
28
|
+
not_to matcher.with_message(/wrong/)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def matcher
|
33
|
+
validate_acceptance_of(:attr)
|
34
|
+
end
|
35
|
+
|
36
|
+
def validating_acceptance(options = {})
|
37
|
+
define_model(:example, attr: :string) do
|
38
|
+
validates_acceptance_of :attr, options
|
39
|
+
end.new
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidateConfirmationOfMatcher do
|
4
|
+
context '#description' do
|
5
|
+
it 'states that the confirmation must match its base attribute' do
|
6
|
+
expect(matcher.description).to eq 'require attr_confirmation to match attr'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'a model with a confirmation validation' do
|
11
|
+
it 'accepts' do
|
12
|
+
expect(validating_confirmation).to matcher
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'does not override the default message with a blank' do
|
16
|
+
expect(validating_confirmation).to matcher.with_message(nil)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'a model without a confirmation validation' do
|
21
|
+
it 'rejects' do
|
22
|
+
expect(define_model(:example, attr: :string).new).not_to matcher
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'a confirmation validation with a custom message' do
|
27
|
+
it 'accepts when the message matches' do
|
28
|
+
expect(validating_confirmation(message: 'custom')).
|
29
|
+
to matcher.with_message(/custom/)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'rejects when the messages do not match' do
|
33
|
+
expect(validating_confirmation(message: 'custom')).
|
34
|
+
not_to matcher.with_message(/wrong/)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def matcher
|
39
|
+
validate_confirmation_of(:attr)
|
40
|
+
end
|
41
|
+
|
42
|
+
def validating_confirmation(options = {})
|
43
|
+
define_model(:example, attr: :string) do
|
44
|
+
validates_confirmation_of :attr, options
|
45
|
+
end.new
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,331 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do
|
4
|
+
|
5
|
+
context 'with a model with a numericality validation' do
|
6
|
+
it 'accepts' do
|
7
|
+
expect(validating_numericality).to matcher
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'does not override the default message with a blank' do
|
11
|
+
expect(validating_numericality).to matcher.with_message(nil)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with a model without a numericality validation' do
|
16
|
+
it 'rejects' do
|
17
|
+
expect(not_validating_numericality).not_to matcher
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'rejects with the ActiveRecord :not_a_number message' do
|
21
|
+
the_matcher = matcher
|
22
|
+
|
23
|
+
the_matcher.matches?(define_model(:example, attr: :string).new)
|
24
|
+
|
25
|
+
expect(the_matcher.failure_message_when_negated)
|
26
|
+
.to include 'Did not expect errors to include "is not a number"'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'rejects with the ActiveRecord :not_an_integer message' do
|
30
|
+
the_matcher = matcher.only_integer
|
31
|
+
expect do
|
32
|
+
expect(not_validating_numericality).to the_matcher
|
33
|
+
end.to fail_with_message_including(
|
34
|
+
'Expected errors to include "must be an integer"'
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'rejects with the ActiveRecord :odd message' do
|
39
|
+
the_matcher = matcher.odd
|
40
|
+
expect do
|
41
|
+
expect(not_validating_numericality).to the_matcher
|
42
|
+
end.to fail_with_message_including(
|
43
|
+
'Expected errors to include "must be odd"'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'rejects with the ActiveRecord :even message' do
|
48
|
+
the_matcher = matcher.even
|
49
|
+
expect do
|
50
|
+
expect(not_validating_numericality).to the_matcher
|
51
|
+
end.to fail_with_message_including(
|
52
|
+
'Expected errors to include "must be even"'
|
53
|
+
)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with the allow_nil option' do
|
58
|
+
it 'allows nil values for that attribute' do
|
59
|
+
expect(validating_numericality(allow_nil: true)).to matcher.allow_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'rejects when the model does not allow nil' do
|
63
|
+
the_matcher = matcher.allow_nil
|
64
|
+
expect {
|
65
|
+
expect(validating_numericality).to the_matcher
|
66
|
+
}.to fail_with_message_including('Did not expect errors to include "is not a number"')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'with the only_integer option' do
|
71
|
+
it 'allows integer values for that attribute' do
|
72
|
+
expect(validating_numericality(only_integer: true)).to matcher.only_integer
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'rejects when the model does not enforce integer values' do
|
76
|
+
expect(validating_numericality).not_to matcher.only_integer
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'rejects with the ActiveRecord :not_an_integer message' do
|
80
|
+
the_matcher = matcher.only_integer
|
81
|
+
expect do
|
82
|
+
expect(validating_numericality).to the_matcher
|
83
|
+
end.to fail_with_message_including(
|
84
|
+
'Expected errors to include "must be an integer"'
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'with the odd option' do
|
90
|
+
it 'allows odd number values for that attribute' do
|
91
|
+
expect(validating_numericality(odd: true)).to matcher.odd
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'rejects when the model does not enforce odd number values' do
|
95
|
+
expect(validating_numericality).not_to matcher.odd
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'rejects with the ActiveRecord :odd message' do
|
99
|
+
the_matcher = matcher.odd
|
100
|
+
expect do
|
101
|
+
expect(validating_numericality).to the_matcher
|
102
|
+
end.to fail_with_message_including(
|
103
|
+
'Expected errors to include "must be odd"'
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'with the even option' do
|
109
|
+
it 'allows even number values for that attribute' do
|
110
|
+
expect(validating_numericality(even: true)).to matcher.even
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'rejects when the model does not enforce even number values' do
|
114
|
+
expect(validating_numericality).not_to matcher.even
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'rejects with the ActiveRecord :even message' do
|
118
|
+
the_matcher = matcher.even
|
119
|
+
expect do
|
120
|
+
expect(validating_numericality).to the_matcher
|
121
|
+
end.to fail_with_message_including(
|
122
|
+
'Expected errors to include "must be even"'
|
123
|
+
)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'with multiple options together' do
|
128
|
+
context 'the success cases' do
|
129
|
+
it do
|
130
|
+
expect(validating_numericality(only_integer: true, greater_than: 18))
|
131
|
+
.to matcher.only_integer.is_greater_than(18)
|
132
|
+
end
|
133
|
+
|
134
|
+
it do
|
135
|
+
expect(validating_numericality(even: true, greater_than: 18))
|
136
|
+
.to matcher.even.is_greater_than(18)
|
137
|
+
end
|
138
|
+
it do
|
139
|
+
expect(validating_numericality(odd: true, less_than_or_equal_to: 99))
|
140
|
+
.to matcher.odd.is_less_than_or_equal_to(99)
|
141
|
+
end
|
142
|
+
|
143
|
+
it do
|
144
|
+
expect(validating_numericality(
|
145
|
+
only_integer: true,
|
146
|
+
greater_than: 18,
|
147
|
+
less_than: 99)
|
148
|
+
).to matcher.only_integer.is_greater_than(18).is_less_than(99)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'the failure cases with different validators' do
|
153
|
+
it do
|
154
|
+
expect(validating_numericality(even: true, greater_than: 18))
|
155
|
+
.not_to matcher.only_integer.is_greater_than(18)
|
156
|
+
end
|
157
|
+
|
158
|
+
it do
|
159
|
+
expect(validating_numericality(greater_than: 18))
|
160
|
+
.not_to matcher.only_integer.is_greater_than(18)
|
161
|
+
end
|
162
|
+
|
163
|
+
it do
|
164
|
+
expect(
|
165
|
+
validating_numericality(even: true, greater_than_or_equal_to: 18)
|
166
|
+
).not_to matcher.even.is_greater_than(18)
|
167
|
+
end
|
168
|
+
|
169
|
+
it do
|
170
|
+
expect(validating_numericality(odd: true, greater_than: 18))
|
171
|
+
.not_to matcher.even.is_greater_than(18)
|
172
|
+
end
|
173
|
+
|
174
|
+
it do
|
175
|
+
expect(validating_numericality(
|
176
|
+
odd: true,
|
177
|
+
greater_than_or_equal_to: 99
|
178
|
+
)
|
179
|
+
).not_to matcher.odd.is_less_than_or_equal_to(99)
|
180
|
+
end
|
181
|
+
|
182
|
+
it do
|
183
|
+
expect(validating_numericality(
|
184
|
+
only_integer: true,
|
185
|
+
greater_than_or_equal_to: 18,
|
186
|
+
less_than: 99
|
187
|
+
)
|
188
|
+
).not_to matcher.only_integer.is_greater_than(18).is_less_than(99)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'the failure cases with wrong values' do
|
193
|
+
it do
|
194
|
+
expect(validating_numericality(only_integer: true, greater_than: 19))
|
195
|
+
.not_to matcher.only_integer.is_greater_than(18)
|
196
|
+
end
|
197
|
+
|
198
|
+
it do
|
199
|
+
expect(validating_numericality(only_integer: true, greater_than: 17))
|
200
|
+
.not_to matcher.only_integer.is_greater_than(18)
|
201
|
+
end
|
202
|
+
|
203
|
+
it do
|
204
|
+
expect(validating_numericality(even: true, greater_than: 20))
|
205
|
+
.not_to matcher.even.is_greater_than(18)
|
206
|
+
end
|
207
|
+
|
208
|
+
it do
|
209
|
+
expect(validating_numericality(even: true, greater_than: 16))
|
210
|
+
.not_to matcher.even.is_greater_than(18)
|
211
|
+
end
|
212
|
+
|
213
|
+
it do
|
214
|
+
expect(validating_numericality(odd: true, less_than_or_equal_to: 101))
|
215
|
+
.not_to matcher.odd.is_less_than_or_equal_to(99)
|
216
|
+
end
|
217
|
+
|
218
|
+
it do
|
219
|
+
expect(validating_numericality(odd: true, less_than_or_equal_to: 97))
|
220
|
+
.not_to matcher.odd.is_less_than_or_equal_to(99)
|
221
|
+
end
|
222
|
+
|
223
|
+
it do
|
224
|
+
expect(validating_numericality(only_integer: true,
|
225
|
+
greater_than: 19,
|
226
|
+
less_than: 99))
|
227
|
+
.not_to matcher.only_integer.is_greater_than(18).is_less_than(99)
|
228
|
+
end
|
229
|
+
|
230
|
+
it do
|
231
|
+
expect(validating_numericality(only_integer: true,
|
232
|
+
greater_than: 18,
|
233
|
+
less_than: 100))
|
234
|
+
.not_to matcher.only_integer.is_greater_than(18).is_less_than(99)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'with a custom validation message' do
|
240
|
+
it 'accepts when the messages match' do
|
241
|
+
expect(validating_numericality(message: 'custom')).
|
242
|
+
to matcher.with_message(/custom/)
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'rejects when the messages do not match' do
|
246
|
+
expect(validating_numericality(message: 'custom')).
|
247
|
+
not_to matcher.with_message(/wrong/)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'when the subject is stubbed' do
|
252
|
+
it 'retains stubs on submatchers' do
|
253
|
+
subject = define_model :example, attr: :string do
|
254
|
+
validates_numericality_of :attr, odd: true
|
255
|
+
before_validation :set_attr!
|
256
|
+
def set_attr!; self.attr = 5 end
|
257
|
+
end.new
|
258
|
+
|
259
|
+
subject.stubs(:set_attr!)
|
260
|
+
expect(subject).to matcher.odd
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
describe '#description' do
|
265
|
+
context 'without submatchers' do
|
266
|
+
it { expect(matcher.description).to eq 'only allow numbers for attr' }
|
267
|
+
end
|
268
|
+
|
269
|
+
context 'with only integer option' do
|
270
|
+
it do
|
271
|
+
expect(matcher.only_integer.description)
|
272
|
+
.to eq 'only allow integers for attr'
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
[:odd, :even].each do |type|
|
277
|
+
context "with #{type} option" do
|
278
|
+
it do
|
279
|
+
expect(matcher.__send__(type).description)
|
280
|
+
.to eq "only allow #{type} numbers for attr"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
[:is_greater_than,
|
286
|
+
:is_greater_than_or_equal_to,
|
287
|
+
:is_less_than,
|
288
|
+
:is_less_than_or_equal_to,
|
289
|
+
:is_equal_to ].each do |comparison|
|
290
|
+
context "with #{comparison} option" do
|
291
|
+
it do
|
292
|
+
expect(matcher.__send__(comparison, 18).description)
|
293
|
+
.to eq(
|
294
|
+
'only allow numbers for attr which are ' +
|
295
|
+
"#{comparison.to_s.sub('is_', '').gsub('_', ' ')} 18"
|
296
|
+
)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context 'with odd, is_greater_than_or_equal_to option' do
|
302
|
+
it do
|
303
|
+
expect(matcher.odd.is_greater_than_or_equal_to(18).description)
|
304
|
+
.to eq(
|
305
|
+
'only allow odd numbers for attr ' +
|
306
|
+
'which are greater than or equal to 18'
|
307
|
+
)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'with only integer, is_greater_than and less_than_or_equal_to option' do
|
312
|
+
it { expect(matcher.only_integer.is_greater_than(18).is_less_than_or_equal_to(100).description).
|
313
|
+
to eq "only allow integers for attr which are greater than 18 and less than or equal to 100" }
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
def validating_numericality(options = {})
|
319
|
+
define_model :example, attr: :string do
|
320
|
+
validates_numericality_of :attr, options
|
321
|
+
end.new
|
322
|
+
end
|
323
|
+
|
324
|
+
def not_validating_numericality
|
325
|
+
define_model(:example, attr: :string).new
|
326
|
+
end
|
327
|
+
|
328
|
+
def matcher
|
329
|
+
validate_numericality_of(:attr)
|
330
|
+
end
|
331
|
+
end
|