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,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
|
+
expect(described_class.new(:attr).description).
|
8
|
+
to eq '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
|
+
expect(described_class.new(:attr).as(:admin).description).
|
16
|
+
to eq '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
|
+
expect(model).not_to 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
|
+
expect(model).not_to 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
|
+
expect(define_model(:example, whitelisted: :string) do
|
46
|
+
attr_accessible :whitelisted
|
47
|
+
end.new).to 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
|
+
expect(model).to allow_mass_assignment_of(:not_blacklisted)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
unless active_model_3_2? || active_model_4_0?
|
63
|
+
context 'an attribute on a class with no protected attributes' do
|
64
|
+
it 'accepts being mass-assignable' do
|
65
|
+
expect(no_protected_attributes).to 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
|
+
expect(matcher.matches?(no_protected_attributes)).to eq true
|
72
|
+
|
73
|
+
expect(matcher.failure_message_when_negated).not_to 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
|
+
expect(all_protected_attributes).not_to 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
|
+
expect(mass_assignable_as_admin).not_to allow_mass_assignment_of(:attr)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'accepts being mass-assignable for admin' do
|
101
|
+
expect(mass_assignable_as_admin).to 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,170 @@
|
|
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
|
+
expect(matcher.description).to eq '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
|
+
expect(matcher.description).to eq '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
|
+
expect(strict_matcher.description).
|
22
|
+
to eq %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
|
+
expect(validating_format(with: /abc/)).to allow_value('abcde').for(:attr)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'rejects a bad value' do
|
33
|
+
expect(validating_format(with: /abc/)).not_to allow_value('xyz').for(:attr)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'allows several good values' do
|
37
|
+
expect(validating_format(with: /abc/)).
|
38
|
+
to allow_value('abcde', 'deabc').for(:attr)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'rejects several bad values' do
|
42
|
+
expect(validating_format(with: /abc/)).
|
43
|
+
not_to 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
|
+
expect(validating_format(with: /abc/, message: 'bad value')).
|
50
|
+
to allow_value('abcde').for(:attr).with_message(/bad/)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'rejects a bad value' do
|
54
|
+
expect(validating_format(with: /abc/, message: 'bad value')).
|
55
|
+
not_to allow_value('xyz').for(:attr).with_message(/bad/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'an attribute where the message occurs on another attribute' do
|
60
|
+
it 'allows a good value' do
|
61
|
+
expect(record_with_custom_validation).to \
|
62
|
+
allow_value('good value').for(:attr).with_message(/some message/, against: :attr2)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'rejects a bad value' do
|
66
|
+
expect(record_with_custom_validation).not_to \
|
67
|
+
allow_value('bad value').for(:attr).with_message(/some message/, against: :attr2)
|
68
|
+
end
|
69
|
+
|
70
|
+
def record_with_custom_validation
|
71
|
+
define_model :example, attr: :string, attr2: :string do
|
72
|
+
validate :custom_validation
|
73
|
+
|
74
|
+
def custom_validation
|
75
|
+
if self[:attr] != 'good value'
|
76
|
+
self.errors[:attr2] << 'some message'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end.new
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "an attribute with a context-dependent validation" do
|
84
|
+
context "without the validation context" do
|
85
|
+
it "allows a bad value" do
|
86
|
+
expect(validating_format(with: /abc/, on: :customisable)).to allow_value("xyz").for(:attr)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "with the validation context" do
|
91
|
+
it "allows a good value" do
|
92
|
+
expect(validating_format(with: /abc/, on: :customisable)).to allow_value("abcde").for(:attr).on(:customisable)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "rejects a bad value" do
|
96
|
+
expect(validating_format(with: /abc/, on: :customisable)).not_to allow_value("xyz").for(:attr).on(:customisable)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'an attribute with several validations' do
|
102
|
+
let(:model) do
|
103
|
+
define_model :example, attr: :string do
|
104
|
+
validates_presence_of :attr
|
105
|
+
validates_length_of :attr, within: 1..5
|
106
|
+
validates_numericality_of :attr, greater_than_or_equal_to: 1,
|
107
|
+
less_than_or_equal_to: 50000
|
108
|
+
end.new
|
109
|
+
end
|
110
|
+
bad_values = [nil, '', 'abc', '0', '50001', '123456', []]
|
111
|
+
|
112
|
+
it 'allows a good value' do
|
113
|
+
expect(model).to allow_value('12345').for(:attr)
|
114
|
+
end
|
115
|
+
|
116
|
+
bad_values.each do |bad_value|
|
117
|
+
it "rejects a bad value (#{bad_value.inspect})" do
|
118
|
+
expect(model).not_to allow_value(bad_value).for(:attr)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it "rejects several bad values (#{bad_values.map(&:inspect).join(', ')})" do
|
123
|
+
expect(model).not_to allow_value(*bad_values).for(:attr)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "rejects a mix of both good and bad values" do
|
127
|
+
expect(model).not_to allow_value('12345', *bad_values).for(:attr)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'with a single value' do
|
132
|
+
it 'allows you to call description before calling matches?' do
|
133
|
+
model = define_model(:example, attr: :string).new
|
134
|
+
matcher = described_class.new('foo').for(:attr)
|
135
|
+
matcher.description
|
136
|
+
|
137
|
+
expect { matcher.matches?(model) }.not_to raise_error
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'with no values' do
|
142
|
+
it 'raises an error' do
|
143
|
+
expect { allow_value.for(:baz) }.
|
144
|
+
to raise_error(ArgumentError, /at least one argument/)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
if active_model_3_2?
|
149
|
+
context 'an attribute with a strict format validation' do
|
150
|
+
it 'strictly rejects a bad value' do
|
151
|
+
expect(validating_format(with: /abc/, strict: true)).
|
152
|
+
not_to allow_value('xyz').for(:attr).strict
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'strictly allows a bad value with a different message' do
|
156
|
+
expect(validating_format(with: /abc/, strict: true)).
|
157
|
+
to allow_value('xyz').for(:attr).with_message(/abc/).strict
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'provides a useful negative failure message' do
|
161
|
+
matcher = allow_value('xyz').for(:attr).strict.with_message(/abc/)
|
162
|
+
|
163
|
+
matcher.matches?(validating_format(with: /abc/, strict: true))
|
164
|
+
|
165
|
+
expect(matcher.failure_message_when_negated).to eq 'Expected exception to include /abc/ ' +
|
166
|
+
'when attr is set to "xyz", got Attr is invalid'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher do
|
4
|
+
context 'an attribute with a format validation' do
|
5
|
+
it 'does not match if the value is allowed' do
|
6
|
+
expect(validating_format(with: /abc/)).not_to matcher('abcde').for(:attr)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'matches if the value is not allowed' do
|
10
|
+
expect(validating_format(with: /abc/)).to matcher('xyz').for(:attr)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "an attribute with a context-dependent validation" do
|
15
|
+
context "without the validation context" do
|
16
|
+
it "does not match" do
|
17
|
+
expect(validating_format(with: /abc/, on: :customisable)).not_to matcher("xyz").for(:attr)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with the validation context" do
|
22
|
+
it "disallows a bad value" do
|
23
|
+
expect(validating_format(with: /abc/, on: :customisable)).to matcher("xyz").for(:attr).on(:customisable)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "does not match a good value" do
|
27
|
+
expect(validating_format(with: /abc/, on: :customisable)).not_to matcher("abcde").for(:attr).on(:customisable)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'an attribute with a format validation and a custom message' do
|
33
|
+
it 'does not match if the value and message are both correct' do
|
34
|
+
expect(validating_format(with: /abc/, message: 'good message')).
|
35
|
+
not_to matcher('abcde').for(:attr).with_message('good message')
|
36
|
+
end
|
37
|
+
|
38
|
+
it "delegates its failure message to its allow matcher's negative failure message" do
|
39
|
+
allow_matcher = stub_everything(failure_message_when_negated: 'allow matcher failure')
|
40
|
+
Shoulda::Matchers::ActiveModel::AllowValueMatcher.stubs(:new).returns(allow_matcher)
|
41
|
+
|
42
|
+
matcher = matcher('abcde').for(:attr).with_message('good message')
|
43
|
+
matcher.matches?(validating_format(with: /abc/, message: 'good message'))
|
44
|
+
|
45
|
+
expect(matcher.failure_message).to eq 'allow matcher failure'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'matches if the message is correct but the value is not' do
|
49
|
+
expect(validating_format(with: /abc/, message: 'good message')).
|
50
|
+
to matcher('xyz').for(:attr).with_message('good message')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'an attribute where the message occurs on another attribute' do
|
55
|
+
it 'matches if the message is correct but the value is not' do
|
56
|
+
expect(record_with_custom_validation).to \
|
57
|
+
matcher('bad value').for(:attr).with_message(/some message/, against: :attr2)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'does not match if the value and message are both correct' do
|
61
|
+
expect(record_with_custom_validation).not_to \
|
62
|
+
matcher('good value').for(:attr).with_message(/some message/, against: :attr2)
|
63
|
+
end
|
64
|
+
|
65
|
+
def record_with_custom_validation
|
66
|
+
define_model :example, attr: :string, attr2: :string do
|
67
|
+
validate :custom_validation
|
68
|
+
|
69
|
+
def custom_validation
|
70
|
+
if self[:attr] != 'good value'
|
71
|
+
self.errors[:attr2] << 'some message'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end.new
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def matcher(value)
|
79
|
+
described_class.new(value)
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,95 @@
|
|
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
|
+
expect(validating_exclusion(in: 2..5)).
|
7
|
+
to ensure_exclusion_of(:attr).in_range(2..5)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'rejects ensuring excluded value' do
|
11
|
+
expect(validating_exclusion(in: 2..5)).
|
12
|
+
not_to ensure_exclusion_of(:attr).in_range(2..6)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'does not override the default message with a blank' do
|
16
|
+
expect(validating_exclusion(in: 2..5)).
|
17
|
+
to ensure_exclusion_of(:attr).in_range(2..5).with_message(nil)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'an attribute which must be excluded from a range with excluded end' do
|
22
|
+
it 'accepts ensuring the correct range' do
|
23
|
+
expect(validating_exclusion(in: 2...5)).
|
24
|
+
to ensure_exclusion_of(:attr).in_range(2...5)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'rejects ensuring excluded value' do
|
28
|
+
expect(validating_exclusion(in: 2...5)).
|
29
|
+
not_to ensure_exclusion_of(:attr).in_range(2...4)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'an attribute with a custom validation message' do
|
34
|
+
it 'accepts ensuring the correct range' do
|
35
|
+
expect(validating_exclusion(in: 2..4, message: 'not good')).
|
36
|
+
to ensure_exclusion_of(:attr).in_range(2..4).with_message(/not good/)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'an attribute with custom range validations' do
|
41
|
+
it 'accepts ensuring the correct range and messages' do
|
42
|
+
model = custom_validation do
|
43
|
+
if attr >= 2 && attr <= 5
|
44
|
+
errors.add(:attr, 'should be out of this range')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
expect(model).to ensure_exclusion_of(:attr).in_range(2..5).
|
49
|
+
with_message(/should be out of this range/)
|
50
|
+
|
51
|
+
model = custom_validation do
|
52
|
+
if attr >= 2 && attr <= 4
|
53
|
+
errors.add(:attr, 'should be out of this range')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
expect(model).to ensure_exclusion_of(:attr).in_range(2...5).
|
58
|
+
with_message(/should be out of this range/)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'an attribute which must be excluded from an array' do
|
63
|
+
it 'accepts with correct array' do
|
64
|
+
expect(validating_exclusion(in: %w(one two))).
|
65
|
+
to ensure_exclusion_of(:attr).in_array(%w(one two))
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'rejects when only part of array matches' do
|
69
|
+
expect(validating_exclusion(in: %w(one two))).
|
70
|
+
not_to ensure_exclusion_of(:attr).in_array(%w(one wrong_value))
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'rejects when array does not match at all' do
|
74
|
+
expect(validating_exclusion(in: %w(one two))).
|
75
|
+
not_to ensure_exclusion_of(:attr).in_array(%w(cat dog))
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'has correct description' do
|
79
|
+
expect(ensure_exclusion_of(:attr).in_array([true, 'dog']).description).
|
80
|
+
to eq 'ensure exclusion of attr in [true, "dog"]'
|
81
|
+
end
|
82
|
+
|
83
|
+
def validating_exclusion(options)
|
84
|
+
define_model(:example, attr: :string) do
|
85
|
+
validates_exclusion_of :attr, options
|
86
|
+
end.new
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def validating_exclusion(options)
|
91
|
+
define_model(:example, attr: :integer) do
|
92
|
+
validates_exclusion_of :attr, options
|
93
|
+
end.new
|
94
|
+
end
|
95
|
+
end
|