shoulda-matchers 1.4.2 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|