shoulda-matchers 2.5.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/.gitignore +8 -7
  2. data/.travis.yml +4 -0
  3. data/Appraisals +8 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +77 -66
  7. data/MIT-LICENSE +1 -1
  8. data/NEWS.md +63 -1
  9. data/README.md +189 -33
  10. data/Rakefile +6 -5
  11. data/features/rails_integration.feature +1 -1
  12. data/features/step_definitions/rails_steps.rb +7 -6
  13. data/gemfiles/3.0.gemfile +2 -2
  14. data/gemfiles/3.0.gemfile.lock +14 -5
  15. data/gemfiles/3.1.gemfile +2 -2
  16. data/gemfiles/3.1.gemfile.lock +14 -5
  17. data/gemfiles/3.2.gemfile +2 -2
  18. data/gemfiles/3.2.gemfile.lock +16 -7
  19. data/gemfiles/4.0.0.gemfile +2 -2
  20. data/gemfiles/4.0.0.gemfile.lock +15 -6
  21. data/gemfiles/4.0.1.gemfile +2 -2
  22. data/gemfiles/4.0.1.gemfile.lock +15 -6
  23. data/gemfiles/4.1.gemfile +19 -0
  24. data/gemfiles/4.1.gemfile.lock +176 -0
  25. data/lib/shoulda/matchers.rb +17 -1
  26. data/lib/shoulda/matchers/action_controller.rb +4 -2
  27. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +100 -0
  28. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  29. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +4 -4
  30. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +1 -1
  31. data/lib/shoulda/matchers/action_controller/route_matcher.rb +12 -12
  32. data/lib/shoulda/matchers/action_controller/route_params.rb +1 -1
  33. data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +2 -1
  34. data/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb +167 -0
  35. data/lib/shoulda/matchers/active_model.rb +4 -2
  36. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +23 -5
  37. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +0 -4
  38. data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +66 -14
  39. data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +8 -8
  40. data/lib/shoulda/matchers/active_model/errors.rb +40 -0
  41. data/lib/shoulda/matchers/active_model/helpers.rb +6 -6
  42. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +33 -14
  43. data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +26 -0
  44. data/lib/shoulda/matchers/active_model/numericality_matchers/{odd_even_number_matcher.rb → numeric_type_matcher.rb} +9 -20
  45. data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +26 -0
  46. data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +5 -21
  47. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +1 -1
  48. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +71 -22
  49. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +6 -1
  50. data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +25 -6
  51. data/lib/shoulda/matchers/active_record.rb +1 -0
  52. data/lib/shoulda/matchers/active_record/association_matcher.rb +67 -13
  53. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +40 -0
  54. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +24 -1
  55. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +1 -1
  56. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +1 -1
  57. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  58. data/lib/shoulda/matchers/assertion_error.rb +7 -2
  59. data/lib/shoulda/matchers/error.rb +24 -0
  60. data/lib/shoulda/matchers/independent.rb +10 -0
  61. data/lib/shoulda/matchers/independent/delegate_matcher.rb +157 -0
  62. data/lib/shoulda/matchers/independent/delegate_matcher/stubbed_target.rb +34 -0
  63. data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +36 -0
  64. data/lib/shoulda/matchers/integrations/rspec.rb +13 -14
  65. data/lib/shoulda/matchers/integrations/test_unit.rb +11 -9
  66. data/lib/shoulda/matchers/version.rb +1 -1
  67. data/lib/shoulda/matchers/warn.rb +7 -0
  68. data/shoulda-matchers.gemspec +2 -1
  69. data/spec/shoulda/matchers/action_controller/callback_matcher_spec.rb +79 -0
  70. data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +3 -3
  71. data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +11 -11
  72. data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +21 -21
  73. data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +10 -10
  74. data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +45 -18
  75. data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +8 -8
  76. data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +19 -19
  77. data/spec/shoulda/matchers/action_controller/route_params_spec.rb +6 -6
  78. data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +11 -11
  79. data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +44 -44
  80. data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +205 -0
  81. data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +24 -24
  82. data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +37 -37
  83. data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +17 -21
  84. data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +24 -24
  85. data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +173 -67
  86. data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +40 -40
  87. data/spec/shoulda/matchers/active_model/exception_message_finder_spec.rb +20 -20
  88. data/spec/shoulda/matchers/active_model/helpers_spec.rb +27 -25
  89. data/spec/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +126 -13
  90. data/spec/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +59 -0
  91. data/spec/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +59 -0
  92. data/spec/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +27 -26
  93. data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +15 -15
  94. data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +8 -8
  95. data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +9 -9
  96. data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +229 -44
  97. data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +44 -25
  98. data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +110 -62
  99. data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +19 -19
  100. data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +30 -30
  101. data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +378 -192
  102. data/spec/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +4 -0
  103. data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +33 -33
  104. data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +21 -17
  105. data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +8 -8
  106. data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +14 -14
  107. data/spec/shoulda/matchers/independent/delegate_matcher/stubbed_target_spec.rb +43 -0
  108. data/spec/shoulda/matchers/independent/delegate_matcher_spec.rb +184 -0
  109. data/spec/spec_helper.rb +4 -0
  110. data/spec/support/activemodel_helpers.rb +2 -2
  111. data/spec/support/capture_helpers.rb +19 -0
  112. data/spec/support/controller_builder.rb +22 -3
  113. data/spec/support/fail_with_message_including_matcher.rb +33 -0
  114. data/spec/support/model_builder.rb +1 -1
  115. data/spec/support/shared_examples/numerical_submatcher.rb +19 -0
  116. data/spec/support/shared_examples/numerical_type_submatcher.rb +17 -0
  117. data/spec/support/test_application.rb +23 -0
  118. metadata +90 -22
  119. checksums.yaml +0 -7
  120. data/spec/shoulda/matchers/active_model/numericality_matchers/odd_even_number_matcher_spec.rb +0 -97
  121. data/spec/support/shared_examples/numerical_submatcher_spec.rb +0 -23
@@ -3,52 +3,52 @@ require 'spec_helper'
3
3
  describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
4
4
  context 'a model with a presence validation' do
5
5
  it 'accepts' do
6
- validating_presence.should matcher
6
+ expect(validating_presence).to matcher
7
7
  end
8
8
 
9
9
  it 'does not override the default message with a blank' do
10
- validating_presence.should matcher.with_message(nil)
10
+ expect(validating_presence).to matcher.with_message(nil)
11
11
  end
12
12
  end
13
13
 
14
14
  context 'a model without a presence validation' do
15
15
  it 'rejects' do
16
- define_model(:example, :attr => :string).new.should_not matcher
16
+ expect(define_model(:example, attr: :string).new).not_to matcher
17
17
  end
18
18
  end
19
19
 
20
20
  context 'an ActiveModel class with a presence validation' do
21
21
  it 'accepts' do
22
- active_model_validating_presence.should matcher
22
+ expect(active_model_validating_presence).to matcher
23
23
  end
24
24
 
25
25
  it 'does not override the default message with a blank' do
26
- active_model_validating_presence.should matcher.with_message(nil)
26
+ expect(active_model_validating_presence).to matcher.with_message(nil)
27
27
  end
28
28
  end
29
29
 
30
30
  context 'an ActiveModel class without a presence validation' do
31
31
  it 'rejects' do
32
- active_model.should_not matcher
32
+ expect(active_model).not_to matcher
33
33
  end
34
34
 
35
35
  it 'provides the correct failure message' do
36
36
  message = %{Expected errors to include "can't be blank" when attr is set to nil, got no errors}
37
37
 
38
- expect { active_model.should matcher }.to fail_with_message(message)
38
+ expect { expect(active_model).to matcher }.to fail_with_message(message)
39
39
  end
40
40
  end
41
41
 
42
42
  context 'a has_many association with a presence validation' do
43
43
  it 'requires the attribute to be set' do
44
- has_many_children(:presence => true).should validate_presence_of(:children)
44
+ expect(has_many_children(presence: true)).to validate_presence_of(:children)
45
45
  end
46
46
  end
47
47
 
48
48
  context 'a has_many association without a presence validation' do
49
49
  it 'does not require the attribute to be set' do
50
- has_many_children(:presence => false).
51
- should_not validate_presence_of(:children)
50
+ expect(has_many_children(presence: false)).
51
+ not_to validate_presence_of(:children)
52
52
  end
53
53
  end
54
54
 
@@ -59,14 +59,14 @@ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
59
59
  has_and_belongs_to_many :children
60
60
  validates_presence_of :children
61
61
  end.new
62
- create_table 'children_parents', :id => false do |t|
62
+ create_table 'children_parents', id: false do |t|
63
63
  t.integer :child_id
64
64
  t.integer :parent_id
65
65
  end
66
66
  end
67
67
 
68
68
  it 'accepts' do
69
- @model.should validate_presence_of(:children)
69
+ expect(@model).to validate_presence_of(:children)
70
70
  end
71
71
  end
72
72
 
@@ -76,14 +76,14 @@ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
76
76
  @model = define_model :parent do
77
77
  has_and_belongs_to_many :children
78
78
  end.new
79
- create_table 'children_parents', :id => false do |t|
79
+ create_table 'children_parents', id: false do |t|
80
80
  t.integer :child_id
81
81
  t.integer :parent_id
82
82
  end
83
83
  end
84
84
 
85
85
  it 'rejects' do
86
- @model.should_not validate_presence_of(:children)
86
+ expect(@model).not_to validate_presence_of(:children)
87
87
  end
88
88
  end
89
89
 
@@ -98,7 +98,7 @@ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
98
98
 
99
99
  it "does not raise an exception" do
100
100
  expect {
101
- validating_presence.should validate_presence_of(:attr)
101
+ expect(validating_presence).to validate_presence_of(:attr)
102
102
  }.to_not raise_exception
103
103
  end
104
104
  end
@@ -106,30 +106,30 @@ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
106
106
  if active_model_3_2?
107
107
  context 'a strictly required attribute' do
108
108
  it 'accepts when the :strict options match' do
109
- validating_presence(:strict => true).should matcher.strict
109
+ expect(validating_presence(strict: true)).to matcher.strict
110
110
  end
111
111
 
112
112
  it 'rejects when the :strict options do not match' do
113
- validating_presence(:strict => false).should_not matcher.strict
113
+ expect(validating_presence(strict: false)).not_to matcher.strict
114
114
  end
115
115
  end
116
116
 
117
117
  it 'does not override the default message with a blank' do
118
- validating_presence(:strict => true).
119
- should matcher.strict.with_message(nil)
118
+ expect(validating_presence(strict: true)).
119
+ to matcher.strict.with_message(nil)
120
120
  end
121
121
  end
122
122
 
123
123
  context "an attribute with a context-dependent validation" do
124
124
  context "without the validation context" do
125
125
  it "does not match" do
126
- validating_presence(:on => :customisable).should_not matcher
126
+ expect(validating_presence(on: :customisable)).not_to matcher
127
127
  end
128
128
  end
129
129
 
130
130
  context "with the validation context" do
131
131
  it "matches" do
132
- validating_presence(:on => :customisable).should matcher.on(:customisable)
132
+ expect(validating_presence(on: :customisable)).to matcher.on(:customisable)
133
133
  end
134
134
  end
135
135
  end
@@ -138,24 +138,43 @@ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
138
138
  context 'with the validation context' do
139
139
  it 'does not raise an exception' do
140
140
  expect {
141
- active_resource_model.should validate_presence_of(:attr)
141
+ expect(active_resource_model).to validate_presence_of(:attr)
142
142
  }.to_not raise_exception
143
143
  end
144
144
  end
145
145
  end
146
146
 
147
+ if rails_4_x?
148
+ context 'against a pre-set password in a model that has_secure_password' do
149
+ it 'raises an error to instruct the user' do
150
+ user_class = define_model :user, password_digest: :string do
151
+ has_secure_password
152
+ validates_presence_of :password
153
+ end
154
+
155
+ user = user_class.new
156
+ user.password = 'something'
157
+
158
+ error_class = Shoulda::Matchers::ActiveModel::CouldNotSetPasswordError
159
+ expect {
160
+ expect(user).to validate_presence_of(:password)
161
+ }.to raise_error(error_class)
162
+ end
163
+ end
164
+ end
165
+
147
166
  def matcher
148
167
  validate_presence_of(:attr)
149
168
  end
150
169
 
151
170
  def validating_presence(options = {})
152
- define_model :example, :attr => :string do
171
+ define_model :example, attr: :string do
153
172
  validates_presence_of :attr, options
154
173
  end.new
155
174
  end
156
175
 
157
176
  def active_model(&block)
158
- define_active_model_class('Example', :accessors => [:attr], &block).new
177
+ define_active_model_class('Example', accessors: [:attr], &block).new
159
178
  end
160
179
 
161
180
  def active_model_validating_presence
@@ -173,7 +192,7 @@ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
173
192
  end
174
193
 
175
194
  def active_resource_model
176
- define_active_resource_class :foo, :attr => :string do
195
+ define_active_resource_class :foo, attr: :string do
177
196
  validates_presence_of :attr
178
197
  end.new
179
198
  end
@@ -5,7 +5,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
5
5
  it 'rejects' do
6
6
  model = define_model(:example, attr: :string) { attr_accessible :attr } .new
7
7
  Example.create!(attr: 'value')
8
- model.should_not matcher
8
+ expect(model).not_to matcher
9
9
  end
10
10
  end
11
11
 
@@ -16,23 +16,23 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
16
16
  attr_accessible :attr
17
17
  validates_uniqueness_of :attr
18
18
  end.new
19
- model.should matcher
19
+ expect(model).to matcher
20
20
  end
21
21
  end
22
22
 
23
23
  context 'with an existing record' do
24
24
  it 'requires a unique value for that attribute' do
25
25
  create_existing
26
- validating_uniqueness_with_other.should matcher
26
+ expect(validating_uniqueness_with_other).to matcher
27
27
  end
28
28
 
29
29
  it 'accepts when the subject is an existing record' do
30
- create_existing.should matcher
30
+ expect(create_existing).to matcher
31
31
  end
32
32
 
33
33
  it 'rejects when a scope is specified' do
34
34
  create_existing
35
- validating_uniqueness_with_other.should_not matcher.scoped_to(:other)
35
+ expect(validating_uniqueness_with_other).not_to matcher.scoped_to(:other)
36
36
  end
37
37
 
38
38
  def create_existing
@@ -44,8 +44,8 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
44
44
  context 'without an existing record' do
45
45
  it 'does not require a created instance' do
46
46
  define_model_with_other
47
- Example.count.should eq 0
48
- validating_uniqueness_with_other.should matcher
47
+ expect(Example.count).to eq 0
48
+ expect(validating_uniqueness_with_other).to matcher
49
49
  end
50
50
  end
51
51
 
@@ -63,18 +63,18 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
63
63
 
64
64
  context 'a model with a uniqueness validation, a custom error, and an existing record' do
65
65
  it 'rejects when the actual message does not match the default message' do
66
- validating_uniqueness_with_existing_record(message: 'Bad value').
67
- should_not matcher
66
+ expect(validating_uniqueness_with_existing_record(message: 'Bad value')).
67
+ not_to matcher
68
68
  end
69
69
 
70
70
  it 'rejects when the messages do not match' do
71
- validating_uniqueness_with_existing_record(message: 'Bad value').
72
- should_not matcher.with_message(/abc/)
71
+ expect(validating_uniqueness_with_existing_record(message: 'Bad value')).
72
+ not_to matcher.with_message(/abc/)
73
73
  end
74
74
 
75
75
  it 'accepts when the messages match' do
76
- validating_uniqueness_with_existing_record(message: 'Bad value').
77
- should matcher.with_message(/Bad/)
76
+ expect(validating_uniqueness_with_existing_record(message: 'Bad value')).
77
+ to matcher.with_message(/Bad/)
78
78
  end
79
79
 
80
80
  def validating_uniqueness_with_existing_record(options = {})
@@ -89,119 +89,119 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
89
89
 
90
90
  context 'a model with a scoped uniqueness validation with an existing value' do
91
91
  it 'accepts when the correct scope is specified' do
92
- validating_scoped_uniqueness([:scope1, :scope2]).
93
- should matcher.scoped_to(:scope1, :scope2)
92
+ expect(validating_scoped_uniqueness([:scope1, :scope2])).
93
+ to matcher.scoped_to(:scope1, :scope2)
94
94
  end
95
95
 
96
96
  it 'accepts when the subject is an existing record' do
97
97
  define_scoped_model([:scope1, :scope2])
98
- create_existing_record.should matcher.scoped_to(:scope1, :scope2)
98
+ expect(create_existing_record).to matcher.scoped_to(:scope1, :scope2)
99
99
  end
100
100
 
101
101
  it 'rejects when too narrow of a scope is specified' do
102
- validating_scoped_uniqueness([:scope1, :scope2]).
103
- should_not matcher.scoped_to(:scope1, :scope2, :other)
102
+ expect(validating_scoped_uniqueness([:scope1, :scope2])).
103
+ not_to matcher.scoped_to(:scope1, :scope2, :other)
104
104
  end
105
105
 
106
106
  it 'rejects when too broad of a scope is specified' do
107
- validating_scoped_uniqueness([:scope1, :scope2]).
108
- should_not matcher.scoped_to(:scope1)
107
+ expect(validating_scoped_uniqueness([:scope1, :scope2])).
108
+ not_to matcher.scoped_to(:scope1)
109
109
  end
110
110
 
111
111
  it 'rejects when a different scope is specified' do
112
- validating_scoped_uniqueness([:scope1]).
113
- should_not matcher.scoped_to(:other)
112
+ expect(validating_scoped_uniqueness([:scope1])).
113
+ not_to matcher.scoped_to(:other)
114
114
  end
115
115
 
116
116
  it 'rejects when no scope is specified' do
117
- validating_scoped_uniqueness([:scope1]).should_not matcher
117
+ expect(validating_scoped_uniqueness([:scope1])).not_to matcher
118
118
  end
119
119
 
120
120
  it 'rejects when a non-existent attribute is specified as a scope' do
121
- validating_scoped_uniqueness([:scope1]).
122
- should_not matcher.scoped_to(:fake)
121
+ expect(validating_scoped_uniqueness([:scope1])).
122
+ not_to matcher.scoped_to(:fake)
123
123
  end
124
124
 
125
125
  context 'when the scoped attribute is a date' do
126
126
  it "accepts" do
127
- validating_scoped_uniqueness([:scope1], :date, scope1: Date.today).
128
- should matcher.scoped_to(:scope1)
127
+ expect(validating_scoped_uniqueness([:scope1], :date, scope1: Date.today)).
128
+ to matcher.scoped_to(:scope1)
129
129
  end
130
130
 
131
131
  context 'with an existing record that conflicts with scope.next' do
132
132
  it 'accepts' do
133
- validating_scoped_uniqueness_with_conflicting_next(:scope1, :date, scope1: Date.today).
134
- should matcher.scoped_to(:scope1)
133
+ expect(validating_scoped_uniqueness_with_conflicting_next(:scope1, :date, scope1: Date.today)).
134
+ to matcher.scoped_to(:scope1)
135
135
  end
136
136
  end
137
137
 
138
138
  context 'when too narrow of a scope is specified' do
139
139
  it 'rejects' do
140
- validating_scoped_uniqueness([:scope1, :scope2], :date, scope1: Date.today, scope2: Date.today).
141
- should_not matcher.scoped_to(:scope1, :scope2, :other)
140
+ expect(validating_scoped_uniqueness([:scope1, :scope2], :date, scope1: Date.today, scope2: Date.today)).
141
+ not_to matcher.scoped_to(:scope1, :scope2, :other)
142
142
  end
143
143
  end
144
144
 
145
145
  context 'when too broad of a scope is specified' do
146
146
  it 'rejects' do
147
- validating_scoped_uniqueness([:scope1, :scope2], :date, scope1: Date.today, scope2: Date.today).
148
- should_not matcher.scoped_to(:scope1)
147
+ expect(validating_scoped_uniqueness([:scope1, :scope2], :date, scope1: Date.today, scope2: Date.today)).
148
+ not_to matcher.scoped_to(:scope1)
149
149
  end
150
150
  end
151
151
  end
152
152
 
153
153
  context 'when the scoped attribute is a datetime' do
154
154
  it 'accepts' do
155
- validating_scoped_uniqueness([:scope1], :datetime, scope1: DateTime.now).
156
- should matcher.scoped_to(:scope1)
155
+ expect(validating_scoped_uniqueness([:scope1], :datetime, scope1: DateTime.now)).
156
+ to matcher.scoped_to(:scope1)
157
157
  end
158
158
 
159
159
  context 'with an existing record that conflicts with scope.next' do
160
160
  it 'accepts' do
161
- validating_scoped_uniqueness_with_conflicting_next(:scope1, :datetime, scope1: DateTime.now).
162
- should matcher.scoped_to(:scope1)
161
+ expect(validating_scoped_uniqueness_with_conflicting_next(:scope1, :datetime, scope1: DateTime.now)).
162
+ to matcher.scoped_to(:scope1)
163
163
  end
164
164
  end
165
165
 
166
166
  context 'with a nil value' do
167
167
  it 'accepts' do
168
- validating_scoped_uniqueness([:scope1], :datetime, scope1: nil).
169
- should matcher.scoped_to(:scope1)
168
+ expect(validating_scoped_uniqueness([:scope1], :datetime, scope1: nil)).
169
+ to matcher.scoped_to(:scope1)
170
170
  end
171
171
  end
172
172
 
173
173
  context 'when too narrow of a scope is specified' do
174
174
  it 'rejects' do
175
- validating_scoped_uniqueness([:scope1, :scope2], :datetime, scope1: DateTime.now, scope2: DateTime.now).
176
- should_not matcher.scoped_to(:scope1, :scope2, :other)
175
+ expect(validating_scoped_uniqueness([:scope1, :scope2], :datetime, scope1: DateTime.now, scope2: DateTime.now)).
176
+ not_to matcher.scoped_to(:scope1, :scope2, :other)
177
177
  end
178
178
  end
179
179
 
180
180
  context 'when too broad of a scope is specified' do
181
181
  it 'rejects' do
182
- validating_scoped_uniqueness([:scope1, :scope2], :datetime, scope1: DateTime.now, scope2: DateTime.now).
183
- should_not matcher.scoped_to(:scope1)
182
+ expect(validating_scoped_uniqueness([:scope1, :scope2], :datetime, scope1: DateTime.now, scope2: DateTime.now)).
183
+ not_to matcher.scoped_to(:scope1)
184
184
  end
185
185
  end
186
186
  end
187
187
 
188
188
  context 'when the scoped attribute is a uuid' do
189
189
  it 'accepts' do
190
- validating_scoped_uniqueness([:scope1], :uuid, scope1: SecureRandom.uuid).
191
- should matcher.scoped_to(:scope1)
190
+ expect(validating_scoped_uniqueness([:scope1], :uuid, scope1: SecureRandom.uuid)).
191
+ to matcher.scoped_to(:scope1)
192
192
  end
193
193
 
194
194
  context 'with an existing record that conflicts with scope.next' do
195
195
  it 'accepts' do
196
- validating_scoped_uniqueness_with_conflicting_next(:scope1, :uuid, scope1: SecureRandom.uuid).
197
- should matcher.scoped_to(:scope1)
196
+ expect(validating_scoped_uniqueness_with_conflicting_next(:scope1, :uuid, scope1: SecureRandom.uuid)).
197
+ to matcher.scoped_to(:scope1)
198
198
  end
199
199
  end
200
200
 
201
201
  context 'with a nil value' do
202
202
  it 'accepts' do
203
- validating_scoped_uniqueness([:scope1], :uuid, scope1: nil).
204
- should matcher.scoped_to(:scope1)
203
+ expect(validating_scoped_uniqueness([:scope1], :uuid, scope1: nil)).
204
+ to matcher.scoped_to(:scope1)
205
205
  end
206
206
  end
207
207
 
@@ -211,7 +211,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
211
211
  scope1: SecureRandom.uuid,
212
212
  scope2: SecureRandom.uuid
213
213
  )
214
- record.should_not matcher.scoped_to(:scope1, :scope2, :other)
214
+ expect(record).not_to matcher.scoped_to(:scope1, :scope2, :other)
215
215
  end
216
216
  end
217
217
 
@@ -221,7 +221,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
221
221
  scope1: SecureRandom.uuid,
222
222
  scope2: SecureRandom.uuid
223
223
  )
224
- record.should_not matcher.scoped_to(:scope1)
224
+ expect(record).not_to matcher.scoped_to(:scope1)
225
225
  end
226
226
  end
227
227
  end
@@ -263,24 +263,24 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
263
263
 
264
264
  context 'a model with a case-sensitive uniqueness validation on a string attribute and an existing record' do
265
265
  it 'accepts a case-sensitive value for that attribute' do
266
- case_sensitive_validation_with_existing_value(:string).
267
- should matcher
266
+ expect(case_sensitive_validation_with_existing_value(:string)).
267
+ to matcher
268
268
  end
269
269
 
270
270
  it 'rejects a case-insensitive value for that attribute' do
271
- case_sensitive_validation_with_existing_value(:string).
272
- should_not matcher.case_insensitive
271
+ expect(case_sensitive_validation_with_existing_value(:string)).
272
+ not_to matcher.case_insensitive
273
273
  end
274
274
  end
275
275
 
276
276
  context 'a model with a case-sensitive uniqueness validation on an integer attribute with an existing value' do
277
277
  it 'accepts a case-insensitive value for that attribute' do
278
- case_sensitive_validation_with_existing_value(:integer).
279
- should matcher.case_insensitive
278
+ expect(case_sensitive_validation_with_existing_value(:integer)).
279
+ to matcher.case_insensitive
280
280
  end
281
281
 
282
282
  it 'accepts a case-sensitive value for that attribute' do
283
- case_sensitive_validation_with_existing_value(:integer).should matcher
283
+ expect(case_sensitive_validation_with_existing_value(:integer)).to matcher
284
284
  end
285
285
  end
286
286
 
@@ -289,13 +289,25 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
289
289
  it "should allow_nil" do
290
290
  model = define_model_with_allow_nil
291
291
  Example.create!(attr: nil)
292
- model.should matcher.allow_nil
292
+ expect(model).to matcher.allow_nil
293
+ end
294
+ end
295
+
296
+ if active_model_3_1?
297
+ context 'when the subject has a secure password' do
298
+ it 'allows nil on the attribute' do
299
+ model = define_model(:example, attr: :string, password_digest: :string) do |m|
300
+ validates_uniqueness_of :attr, allow_nil: true
301
+ has_secure_password
302
+ end.new
303
+ expect(model).to matcher.allow_nil
304
+ end
293
305
  end
294
306
  end
295
307
 
296
308
  it "should create a nil and verify that it is allowed" do
297
309
  model = define_model_with_allow_nil
298
- model.should matcher.allow_nil
310
+ expect(model).to matcher.allow_nil
299
311
  Example.all.any?{ |instance| instance.attr.nil? }
300
312
  end
301
313
 
@@ -312,13 +324,13 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
312
324
  it "should not allow_nil" do
313
325
  model = define_model_without_allow_nil
314
326
  Example.create!(attr: nil)
315
- model.should_not matcher.allow_nil
327
+ expect(model).not_to matcher.allow_nil
316
328
  end
317
329
  end
318
330
 
319
331
  it "should not allow_nil" do
320
332
  model = define_model_without_allow_nil
321
- model.should_not matcher.allow_nil
333
+ expect(model).not_to matcher.allow_nil
322
334
  end
323
335
 
324
336
  def define_model_without_allow_nil
@@ -329,6 +341,42 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
329
341
  end
330
342
  end
331
343
 
344
+ context "a model with non-nullable attribute" do
345
+ context "of type" do
346
+ [:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |type|
347
+ context type do
348
+ it "does not raise an error" do
349
+ model = define_model_with_non_nullable(type)
350
+ expect { expect(model).to matcher }.not_to raise_error
351
+ end
352
+ end
353
+ end
354
+ end
355
+
356
+ context "that is a primary key" do
357
+ it "does not cause duplicate entry errors by re-using default values for primary keys" do
358
+ create_table :examples, id: false do |t|
359
+ t.string :attr
360
+ t.integer :non_nullable, primary: true
361
+ end
362
+ model_class = define_model(:example, attr: :string) do
363
+ validates_uniqueness_of :attr
364
+ end
365
+ model_1 = model_class.new
366
+ model_2 = model_class.new
367
+ expect(model_1).to matcher
368
+ expect { expect(model_2).to matcher }.not_to raise_error
369
+ end
370
+ end
371
+
372
+ def define_model_with_non_nullable(type)
373
+ define_model(:example, attr: :string, non_nullable: { type: type, options: { null: false } }) do
374
+ attr_accessible :attr, :non_nullable
375
+ validates_uniqueness_of :attr
376
+ end.new
377
+ end
378
+ end
379
+
332
380
  def case_sensitive_validation_with_existing_value(attr_type)
333
381
  model = define_model(:example, attr: attr_type) do
334
382
  attr_accessible :attr