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,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do
|
4
|
+
context '#description' do
|
5
|
+
it 'states that it allows only numeric values' do
|
6
|
+
matcher.description.should == 'only allow numeric values for attr'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'with a model with a numericality validation' do
|
11
|
+
it 'accepts' do
|
12
|
+
validating_numericality.should matcher
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'does not override the default message with a blank' do
|
16
|
+
validating_numericality.should matcher.with_message(nil)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with a model without a numericality validation' do
|
21
|
+
it 'rejects' do
|
22
|
+
define_model(:example, :attr => :string).new.should_not matcher
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'rejects with the ActiveRecord :not_an_integer message' do
|
26
|
+
the_matcher = matcher.only_integer
|
27
|
+
|
28
|
+
the_matcher.matches?(define_model(:example, :attr => :string).new)
|
29
|
+
|
30
|
+
the_matcher.failure_message_for_should.should include 'Expected errors to include "must be an integer"'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with the only_integer option' do
|
35
|
+
it 'allows integer values for that attribute' do
|
36
|
+
validating_numericality(:only_integer => true).should matcher.only_integer
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'rejects when the model does not enforce integer values' do
|
40
|
+
validating_numericality.should_not matcher.only_integer
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'rejects with the ActiveRecord :not_an_integer message' do
|
44
|
+
the_matcher = matcher.only_integer
|
45
|
+
|
46
|
+
the_matcher.matches?(validating_numericality)
|
47
|
+
|
48
|
+
the_matcher.failure_message_for_should.should include 'Expected errors to include "must be an integer"'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with a custom validation message' do
|
53
|
+
it 'accepts when the messages match' do
|
54
|
+
validating_numericality(:message => 'custom').
|
55
|
+
should matcher.with_message(/custom/)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'rejects when the messages do not match' do
|
59
|
+
validating_numericality(:message => 'custom').
|
60
|
+
should_not matcher.with_message(/wrong/)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def validating_numericality(options = {})
|
65
|
+
define_model :example, :attr => :string do
|
66
|
+
validates_numericality_of :attr, options
|
67
|
+
end.new
|
68
|
+
end
|
69
|
+
|
70
|
+
def matcher
|
71
|
+
validate_numericality_of(:attr)
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
|
4
|
+
context 'a model with a presence validation' do
|
5
|
+
it 'accepts' do
|
6
|
+
validating_presence.should matcher
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'does not override the default message with a blank' do
|
10
|
+
validating_presence.should matcher.with_message(nil)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'a model without a presence validation' do
|
15
|
+
it 'rejects' do
|
16
|
+
define_model(:example, :attr => :string).new.should_not matcher
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'an ActiveModel class with a presence validation' do
|
21
|
+
it 'accepts' do
|
22
|
+
active_model_validating_presence.should matcher
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'does not override the default message with a blank' do
|
26
|
+
active_model_validating_presence.should matcher.with_message(nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'an ActiveModel class without a presence validation' do
|
31
|
+
it 'rejects' do
|
32
|
+
define_active_model_class('Example', :accessors => [:attr]).new.
|
33
|
+
should_not matcher
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'a has_many association with a presence validation' do
|
38
|
+
it 'requires the attribute to be set' do
|
39
|
+
has_many_children(:presence => true).should validate_presence_of(:children)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'a has_many association without a presence validation' do
|
44
|
+
it 'does not require the attribute to be set' do
|
45
|
+
has_many_children(:presence => false).
|
46
|
+
should_not validate_presence_of(:children)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'a required has_and_belongs_to_many association' do
|
51
|
+
before do
|
52
|
+
define_model :child
|
53
|
+
@model = define_model :parent do
|
54
|
+
has_and_belongs_to_many :children
|
55
|
+
validates_presence_of :children
|
56
|
+
end.new
|
57
|
+
create_table 'children_parents', :id => false do |t|
|
58
|
+
t.integer :child_id
|
59
|
+
t.integer :parent_id
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'accepts' do
|
64
|
+
@model.should validate_presence_of(:children)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'an optional has_and_belongs_to_many association' do
|
69
|
+
before do
|
70
|
+
define_model :child
|
71
|
+
@model = define_model :parent do
|
72
|
+
has_and_belongs_to_many :children
|
73
|
+
end.new
|
74
|
+
create_table 'children_parents', :id => false do |t|
|
75
|
+
t.integer :child_id
|
76
|
+
t.integer :parent_id
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'rejects' do
|
81
|
+
@model.should_not validate_presence_of(:children)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
if active_model_3_2?
|
86
|
+
context 'a strictly required attribute' do
|
87
|
+
it 'accepts when the :strict options match' do
|
88
|
+
validating_presence(:strict => true).should matcher.strict
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'rejects when the :strict options do not match' do
|
92
|
+
validating_presence(:strict => false).should_not matcher.strict
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'does not override the default message with a blank' do
|
97
|
+
validating_presence(:strict => true).
|
98
|
+
should matcher.strict.with_message(nil)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def matcher
|
103
|
+
validate_presence_of(:attr)
|
104
|
+
end
|
105
|
+
|
106
|
+
def validating_presence(options = {})
|
107
|
+
define_model :example, :attr => :string do
|
108
|
+
validates_presence_of :attr, options
|
109
|
+
end.new
|
110
|
+
end
|
111
|
+
|
112
|
+
def active_model_validating_presence
|
113
|
+
define_active_model_class('Example', :accessors => [:attr]) do
|
114
|
+
validates_presence_of :attr
|
115
|
+
end.new
|
116
|
+
end
|
117
|
+
|
118
|
+
def has_many_children(options = {})
|
119
|
+
define_model :child
|
120
|
+
define_model :parent do
|
121
|
+
has_many :children
|
122
|
+
if options[:presence]
|
123
|
+
validates_presence_of :children
|
124
|
+
end
|
125
|
+
end.new
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
|
4
|
+
context 'a model without a a uniqueness validation' do
|
5
|
+
it 'rejects' do
|
6
|
+
model = define_model(:example, :attr => :string) { attr_accessible :attr } .new
|
7
|
+
Example.create!(:attr => 'value')
|
8
|
+
model.should_not matcher
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'a model with a uniqueness validation' do
|
13
|
+
context 'with an existing record' do
|
14
|
+
it 'requires a unique value for that attribute' do
|
15
|
+
create_existing
|
16
|
+
validating_uniqueness_with_other.should matcher
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'accepts when the subject is an existing record' do
|
20
|
+
create_existing.should matcher
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'rejects when a scope is specified' do
|
24
|
+
create_existing
|
25
|
+
validating_uniqueness_with_other.should_not matcher.scoped_to(:other)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_existing
|
29
|
+
define_model_with_other
|
30
|
+
Example.create!(:attr => 'value', :other => 1)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'without an existing record' do
|
35
|
+
it 'does not require a created instance' do
|
36
|
+
define_model_with_other
|
37
|
+
Example.count.should == 0
|
38
|
+
validating_uniqueness_with_other.should matcher
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def define_model_with_other(options = {})
|
43
|
+
@model ||= define_model(:example, :attr => :string, :other => :integer) do
|
44
|
+
attr_accessible :attr, :other
|
45
|
+
validates_uniqueness_of :attr, options
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def validating_uniqueness_with_other(options = {})
|
50
|
+
define_model_with_other.new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'a model with a uniqueness validation, a custom error, and an existing record' do
|
55
|
+
it 'rejects when the actual message does not match the default message' do
|
56
|
+
validating_uniqueness_with_existing_record(:message => 'Bad value').
|
57
|
+
should_not matcher
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'rejects when the messages do not match' do
|
61
|
+
validating_uniqueness_with_existing_record(:message => 'Bad value').
|
62
|
+
should_not matcher.with_message(/abc/)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'accepts when the messages match' do
|
66
|
+
validating_uniqueness_with_existing_record(:message => 'Bad value').
|
67
|
+
should matcher.with_message(/Bad/)
|
68
|
+
end
|
69
|
+
|
70
|
+
def validating_uniqueness_with_existing_record(options = {})
|
71
|
+
model = define_model(:example, :attr => :string) do
|
72
|
+
attr_accessible :attr
|
73
|
+
validates_uniqueness_of :attr, options
|
74
|
+
end.new
|
75
|
+
Example.create!(:attr => 'value')
|
76
|
+
model
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'a model with a scoped uniqueness validation with an existing value' do
|
81
|
+
it 'accepts when the correct scope is specified' do
|
82
|
+
validating_scoped_uniqueness([:scope1, :scope2]).
|
83
|
+
should matcher.scoped_to(:scope1, :scope2)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'accepts when the subject is an existing record' do
|
87
|
+
define_scoped_model([:scope1, :scope2])
|
88
|
+
create_existing_record.should matcher.scoped_to(:scope1, :scope2)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'rejects when too narrow of a scope is specified' do
|
92
|
+
validating_scoped_uniqueness([:scope1, :scope2]).
|
93
|
+
should_not matcher.scoped_to(:scope1, :scope2, :other)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'rejects when too broad of a scope is specified' do
|
97
|
+
validating_scoped_uniqueness([:scope1, :scope2]).
|
98
|
+
should_not matcher.scoped_to(:scope1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'rejects when a different scope is specified' do
|
102
|
+
validating_scoped_uniqueness([:scope1]).
|
103
|
+
should_not matcher.scoped_to(:other)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'rejects when no scope is specified' do
|
107
|
+
validating_scoped_uniqueness([:scope1]).should_not matcher
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'rejects when a non-existent attribute is specified as a scope' do
|
111
|
+
validating_scoped_uniqueness([:scope1]).
|
112
|
+
should_not matcher.scoped_to(:fake)
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_existing_record
|
116
|
+
@existing ||= Example.create!(:attr => 'value', :scope1 => 1, :scope2 => 2, :other => 3)
|
117
|
+
end
|
118
|
+
|
119
|
+
def define_scoped_model(scope)
|
120
|
+
define_model(:example, :attr => :string, :scope1 => :integer,
|
121
|
+
:scope2 => :integer, :other => :integer) do
|
122
|
+
attr_accessible :attr, :scope1, :scope2, :other
|
123
|
+
validates_uniqueness_of :attr, :scope => scope
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def validating_scoped_uniqueness(scope)
|
128
|
+
model = define_scoped_model(scope).new
|
129
|
+
create_existing_record
|
130
|
+
model
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'a model with a case-sensitive uniqueness validation on a string attribute and an existing record' do
|
135
|
+
it 'accepts a case-sensitive value for that attribute' do
|
136
|
+
case_sensitive_validation_with_existing_value(:string).
|
137
|
+
should matcher
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'rejects a case-insensitive value for that attribute' do
|
141
|
+
case_sensitive_validation_with_existing_value(:string).
|
142
|
+
should_not matcher.case_insensitive
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'a model with a case-sensitive uniqueness validation on an integer attribute with an existing value' do
|
147
|
+
it 'accepts a case-insensitive value for that attribute' do
|
148
|
+
case_sensitive_validation_with_existing_value(:integer).
|
149
|
+
should matcher.case_insensitive
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'accepts a case-sensitive value for that attribute' do
|
153
|
+
case_sensitive_validation_with_existing_value(:integer).should matcher
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def case_sensitive_validation_with_existing_value(attr_type)
|
158
|
+
model = define_model(:example, :attr => attr_type) do
|
159
|
+
attr_accessible :attr
|
160
|
+
validates_uniqueness_of :attr, :case_sensitive => true
|
161
|
+
end.new
|
162
|
+
if attr_type == :string
|
163
|
+
Example.create!(:attr => 'value')
|
164
|
+
elsif attr_type == :integer
|
165
|
+
Example.create!(:attr => 1)
|
166
|
+
else
|
167
|
+
raise 'Must be :string or :integer'
|
168
|
+
end
|
169
|
+
model
|
170
|
+
end
|
171
|
+
|
172
|
+
def matcher
|
173
|
+
validate_uniqueness_of(:attr)
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveRecord::AcceptNestedAttributesForMatcher do
|
4
|
+
it 'accepts an existing declaration' do
|
5
|
+
accepting_children.should accept_nested_attributes_for(:children)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'rejects a missing declaration' do
|
9
|
+
matcher = children_matcher
|
10
|
+
|
11
|
+
matcher.matches?(rejecting_children).should be_false
|
12
|
+
|
13
|
+
matcher.failure_message_for_should.should == 'Expected Parent to accept nested attributes for children (is not declared)'
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'allow_destroy' do
|
17
|
+
it 'accepts a valid truthy value' do
|
18
|
+
matching = accepting_children(:allow_destroy => true)
|
19
|
+
|
20
|
+
matching.should children_matcher.allow_destroy(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'accepts a valid falsey value' do
|
24
|
+
matching = accepting_children(:allow_destroy => false)
|
25
|
+
|
26
|
+
matching.should children_matcher.allow_destroy(false)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'rejects an invalid truthy value' do
|
30
|
+
matcher = children_matcher
|
31
|
+
matching = accepting_children(:allow_destroy => true)
|
32
|
+
|
33
|
+
matcher.allow_destroy(false).matches?(matching).should be_false
|
34
|
+
matcher.failure_message_for_should.should =~ /should not allow destroy/
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'rejects an invalid falsey value' do
|
38
|
+
matcher = children_matcher
|
39
|
+
matching = accepting_children(:allow_destroy => false)
|
40
|
+
|
41
|
+
matcher.allow_destroy(true).matches?(matching).should be_false
|
42
|
+
matcher.failure_message_for_should.should =~ /should allow destroy/
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'limit' do
|
47
|
+
it 'accepts a correct value' do
|
48
|
+
accepting_children(:limit => 3).should children_matcher.limit(3)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'rejects a false value' do
|
52
|
+
matcher = children_matcher
|
53
|
+
rejecting = accepting_children(:limit => 3)
|
54
|
+
|
55
|
+
matcher.limit(2).matches?(rejecting).should be_false
|
56
|
+
matcher.failure_message_for_should.should =~ /limit should be 2, got 3/
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'update_only' do
|
61
|
+
it 'accepts a valid truthy value' do
|
62
|
+
accepting_children(:update_only => true).
|
63
|
+
should children_matcher.update_only(true)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'accepts a valid falsey value' do
|
67
|
+
accepting_children(:update_only => false).
|
68
|
+
should children_matcher.update_only(false)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'rejects an invalid truthy value' do
|
72
|
+
matcher = children_matcher.update_only(false)
|
73
|
+
rejecting = accepting_children(:update_only => true)
|
74
|
+
|
75
|
+
matcher.matches?(rejecting).should be_false
|
76
|
+
matcher.failure_message_for_should.should =~ /should not be update only/
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'rejects an invalid falsey value' do
|
80
|
+
matcher = children_matcher.update_only(true)
|
81
|
+
rejecting = accepting_children(:update_only => false)
|
82
|
+
|
83
|
+
matcher.matches?(rejecting).should be_false
|
84
|
+
matcher.failure_message_for_should.should =~ /should be update only/
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def accepting_children(options = {})
|
89
|
+
define_model :child, :parent_id => :integer
|
90
|
+
define_model :parent do
|
91
|
+
has_many :children
|
92
|
+
accepts_nested_attributes_for :children, options
|
93
|
+
end.new
|
94
|
+
end
|
95
|
+
|
96
|
+
def children_matcher
|
97
|
+
accept_nested_attributes_for(:children)
|
98
|
+
end
|
99
|
+
|
100
|
+
def rejecting_children
|
101
|
+
define_model :child, :parent_id => :integer
|
102
|
+
define_model :parent do
|
103
|
+
has_many :children
|
104
|
+
end.new
|
105
|
+
end
|
106
|
+
end
|