shoulda-matchers 2.7.0 → 2.8.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -3
  3. data/Appraisals +18 -0
  4. data/CONTRIBUTING.md +13 -29
  5. data/Gemfile +1 -4
  6. data/Gemfile.lock +2 -10
  7. data/NEWS.md +100 -14
  8. data/README.md +62 -58
  9. data/Rakefile +9 -16
  10. data/gemfiles/3.0.gemfile +11 -12
  11. data/gemfiles/3.0.gemfile.lock +15 -10
  12. data/gemfiles/3.1.gemfile +11 -12
  13. data/gemfiles/3.1.gemfile.lock +14 -10
  14. data/gemfiles/3.1_1.9.2.gemfile +12 -11
  15. data/gemfiles/3.1_1.9.2.gemfile.lock +14 -3
  16. data/gemfiles/3.2.gemfile +11 -12
  17. data/gemfiles/3.2.gemfile.lock +15 -10
  18. data/gemfiles/3.2_1.9.2.gemfile +12 -11
  19. data/gemfiles/3.2_1.9.2.gemfile.lock +14 -2
  20. data/gemfiles/4.0.0.gemfile +10 -12
  21. data/gemfiles/4.0.0.gemfile.lock +13 -10
  22. data/gemfiles/4.0.1.gemfile +10 -12
  23. data/gemfiles/4.0.1.gemfile.lock +13 -10
  24. data/gemfiles/4.1.gemfile +13 -15
  25. data/gemfiles/4.1.gemfile.lock +45 -50
  26. data/gemfiles/4.2.gemfile +36 -0
  27. data/gemfiles/4.2.gemfile.lock +245 -0
  28. data/lib/shoulda/matchers.rb +3 -1
  29. data/lib/shoulda/matchers/action_controller.rb +1 -1
  30. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  31. data/lib/shoulda/matchers/action_controller/route_params.rb +9 -4
  32. data/lib/shoulda/matchers/action_controller/{set_the_flash_matcher.rb → set_flash_matcher.rb} +34 -26
  33. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +125 -69
  34. data/lib/shoulda/matchers/active_model.rb +1 -2
  35. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +18 -5
  36. data/lib/shoulda/matchers/active_model/exception_message_finder.rb +2 -2
  37. data/lib/shoulda/matchers/active_model/helpers.rb +4 -4
  38. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +10 -3
  39. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +1 -1
  40. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +3 -1
  41. data/lib/shoulda/matchers/active_model/{ensure_length_of_matcher.rb → validate_length_of_matcher.rb} +30 -20
  42. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +21 -0
  43. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -2
  44. data/lib/shoulda/matchers/active_record.rb +2 -0
  45. data/lib/shoulda/matchers/active_record/association_matcher.rb +96 -2
  46. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +1 -1
  47. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +3 -3
  48. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +22 -2
  49. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +30 -4
  50. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +19 -3
  51. data/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
  52. data/lib/shoulda/matchers/active_record/uniqueness/model.rb +45 -0
  53. data/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +36 -0
  54. data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +50 -0
  55. data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +24 -0
  56. data/lib/shoulda/matchers/{active_model → active_record}/validate_uniqueness_of_matcher.rb +76 -16
  57. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +117 -51
  58. data/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +1 -1
  59. data/lib/shoulda/matchers/matcher_context.rb +35 -0
  60. data/lib/shoulda/matchers/rails_shim.rb +23 -0
  61. data/lib/shoulda/matchers/util.rb +28 -0
  62. data/lib/shoulda/matchers/version.rb +1 -1
  63. data/script/SUPPORTED_VERSIONS +1 -1
  64. data/spec/acceptance/active_model_integration_spec.rb +20 -0
  65. data/spec/acceptance/independent_matchers_spec.rb +64 -0
  66. data/spec/acceptance/rails_integration_spec.rb +142 -0
  67. data/spec/acceptance_spec_helper.rb +23 -0
  68. data/spec/support/acceptance/helpers.rb +29 -0
  69. data/spec/support/acceptance/helpers/active_model_helpers.rb +11 -0
  70. data/spec/support/acceptance/helpers/array_helpers.rb +13 -0
  71. data/spec/support/acceptance/helpers/base_helpers.rb +14 -0
  72. data/spec/support/acceptance/helpers/command_helpers.rb +51 -0
  73. data/spec/support/acceptance/helpers/file_helpers.rb +19 -0
  74. data/spec/support/acceptance/helpers/gem_helpers.rb +31 -0
  75. data/spec/support/acceptance/helpers/minitest_helpers.rb +19 -0
  76. data/spec/support/acceptance/helpers/pluralization_helpers.rb +13 -0
  77. data/spec/support/acceptance/helpers/rails_version_helpers.rb +11 -0
  78. data/spec/support/acceptance/helpers/rspec_helpers.rb +26 -0
  79. data/spec/support/acceptance/helpers/ruby_version_helpers.rb +9 -0
  80. data/spec/support/acceptance/helpers/step_helpers.rb +117 -0
  81. data/spec/support/acceptance/matchers/have_output.rb +31 -0
  82. data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +55 -0
  83. data/spec/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +103 -0
  84. data/spec/support/tests/bundle.rb +94 -0
  85. data/spec/support/tests/command_runner.rb +214 -0
  86. data/spec/support/tests/filesystem.rb +77 -0
  87. data/spec/support/tests/version.rb +45 -0
  88. data/spec/support/unit/capture.rb +34 -0
  89. data/spec/support/unit/helpers/active_model_helpers.rb +25 -0
  90. data/spec/support/unit/helpers/active_model_versions.rb +20 -0
  91. data/spec/support/unit/helpers/active_resource_builder.rb +27 -0
  92. data/spec/support/unit/helpers/allow_value_matcher_helpers.rb +15 -0
  93. data/spec/support/unit/helpers/class_builder.rb +72 -0
  94. data/spec/support/unit/helpers/confirmation_matcher_helpers.rb +17 -0
  95. data/spec/support/unit/helpers/controller_builder.rb +91 -0
  96. data/spec/support/unit/helpers/i18n_faker.rb +15 -0
  97. data/spec/support/unit/helpers/mailer_builder.rb +12 -0
  98. data/spec/support/unit/helpers/model_builder.rb +102 -0
  99. data/spec/support/unit/helpers/rails_versions.rb +28 -0
  100. data/spec/support/unit/i18n.rb +7 -0
  101. data/spec/support/unit/matchers/deprecate.rb +60 -0
  102. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +50 -0
  103. data/spec/support/unit/matchers/fail_with_message_matcher.rb +50 -0
  104. data/spec/support/unit/matchers/print_warning_including.rb +59 -0
  105. data/spec/support/unit/rails_application.rb +110 -0
  106. data/spec/support/unit/record_builder_with_i18n_validation_message.rb +69 -0
  107. data/spec/support/unit/record_validating_confirmation_builder.rb +56 -0
  108. data/spec/support/unit/record_with_different_error_attribute_builder.rb +92 -0
  109. data/spec/support/{shared_examples → unit/shared_examples}/numerical_submatcher.rb +0 -2
  110. data/spec/support/{shared_examples → unit/shared_examples}/numerical_type_submatcher.rb +0 -2
  111. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/callback_matcher_spec.rb +2 -2
  112. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/filter_param_matcher_spec.rb +2 -2
  113. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/redirect_to_matcher_spec.rb +3 -3
  114. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/render_template_matcher_spec.rb +2 -4
  115. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/render_with_layout_matcher_spec.rb +9 -6
  116. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/rescue_from_matcher_spec.rb +2 -2
  117. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/respond_with_matcher_spec.rb +2 -2
  118. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +126 -0
  119. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/route_params_spec.rb +2 -2
  120. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +167 -0
  121. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +294 -0
  122. data/spec/{shoulda → unit/shoulda}/matchers/action_controller/strong_parameters_matcher_spec.rb +19 -11
  123. data/spec/{shoulda → unit/shoulda}/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +2 -2
  124. data/spec/{shoulda → unit/shoulda}/matchers/active_model/allow_value_matcher_spec.rb +49 -21
  125. data/spec/{shoulda → unit/shoulda}/matchers/active_model/disallow_value_matcher_spec.rb +8 -4
  126. data/spec/{shoulda → unit/shoulda}/matchers/active_model/exception_message_finder_spec.rb +4 -4
  127. data/spec/{shoulda → unit/shoulda}/matchers/active_model/have_secure_password_matcher_spec.rb +2 -2
  128. data/spec/{shoulda → unit/shoulda}/matchers/active_model/helpers_spec.rb +7 -3
  129. data/spec/{shoulda → unit/shoulda}/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +1 -1
  130. data/spec/{shoulda → unit/shoulda}/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +1 -1
  131. data/spec/{shoulda → unit/shoulda}/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +1 -1
  132. data/spec/{shoulda → unit/shoulda}/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +1 -1
  133. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validate_absence_of_matcher_spec.rb +3 -3
  134. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validate_acceptance_of_matcher_spec.rb +2 -2
  135. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +63 -0
  136. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validate_exclusion_of_matcher_spec.rb +5 -4
  137. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validate_inclusion_of_matcher_spec.rb +7 -14
  138. data/spec/{shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb → unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb} +43 -23
  139. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validate_numericality_of_matcher_spec.rb +3 -4
  140. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validate_presence_of_matcher_spec.rb +3 -3
  141. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +127 -2
  142. data/spec/{shoulda → unit/shoulda}/matchers/active_model/validation_message_finder_spec.rb +8 -6
  143. data/spec/{shoulda → unit/shoulda}/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +2 -2
  144. data/spec/{shoulda → unit/shoulda}/matchers/active_record/association_matcher_spec.rb +217 -26
  145. data/spec/{shoulda → unit/shoulda}/matchers/active_record/association_matchers/model_reflection_spec.rb +2 -2
  146. data/spec/{shoulda → unit/shoulda}/matchers/active_record/define_enum_for_matcher_spec.rb +2 -2
  147. data/spec/{shoulda → unit/shoulda}/matchers/active_record/have_db_column_matcher_spec.rb +2 -2
  148. data/spec/{shoulda → unit/shoulda}/matchers/active_record/have_db_index_matcher_spec.rb +8 -5
  149. data/spec/{shoulda → unit/shoulda}/matchers/active_record/have_readonly_attributes_matcher_spec.rb +2 -2
  150. data/spec/{shoulda → unit/shoulda}/matchers/active_record/serialize_matcher_spec.rb +3 -3
  151. data/spec/{shoulda → unit/shoulda}/matchers/doublespeak/double_collection_spec.rb +29 -7
  152. data/spec/{shoulda → unit/shoulda}/matchers/doublespeak/double_implementation_registry_spec.rb +1 -1
  153. data/spec/{shoulda → unit/shoulda}/matchers/doublespeak/double_spec.rb +20 -10
  154. data/spec/{shoulda → unit/shoulda}/matchers/doublespeak/object_double_spec.rb +1 -1
  155. data/spec/{shoulda → unit/shoulda}/matchers/doublespeak/proxy_implementation_spec.rb +13 -6
  156. data/spec/{shoulda → unit/shoulda}/matchers/doublespeak/stub_implementation_spec.rb +2 -2
  157. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +77 -0
  158. data/spec/{shoulda → unit/shoulda}/matchers/doublespeak_spec.rb +11 -3
  159. data/spec/{shoulda → unit/shoulda}/matchers/independent/delegate_method_matcher/stubbed_target_spec.rb +1 -1
  160. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +517 -0
  161. data/spec/unit_spec_helper.rb +66 -0
  162. data/spec/warnings_spy/partitioner.rb +10 -3
  163. data/spec/warnings_spy/reader.rb +9 -20
  164. data/spec/warnings_spy/reporter.rb +2 -1
  165. metadata +212 -149
  166. data/features/activemodel_integration.feature +0 -15
  167. data/features/rails_integration.feature +0 -160
  168. data/features/step_definitions/activemodel_steps.rb +0 -21
  169. data/features/step_definitions/rails_steps.rb +0 -227
  170. data/features/support/env.rb +0 -6
  171. data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +0 -70
  172. data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +0 -113
  173. data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +0 -153
  174. data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +0 -47
  175. data/spec/shoulda/matchers/doublespeak/world_spec.rb +0 -70
  176. data/spec/shoulda/matchers/independent/delegate_method_matcher_spec.rb +0 -309
  177. data/spec/spec_helper.rb +0 -42
  178. data/spec/support/active_model_versions.rb +0 -13
  179. data/spec/support/active_resource_builder.rb +0 -29
  180. data/spec/support/activemodel_helpers.rb +0 -23
  181. data/spec/support/capture_helpers.rb +0 -19
  182. data/spec/support/class_builder.rb +0 -46
  183. data/spec/support/controller_builder.rb +0 -102
  184. data/spec/support/fail_with_message_including_matcher.rb +0 -44
  185. data/spec/support/fail_with_message_matcher.rb +0 -44
  186. data/spec/support/i18n_faker.rb +0 -10
  187. data/spec/support/mailer_builder.rb +0 -10
  188. data/spec/support/model_builder.rb +0 -81
  189. data/spec/support/rails_versions.rb +0 -26
  190. data/spec/support/test_application.rb +0 -120
@@ -1,9 +1,9 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  module ActiveModel
4
- # The `ensure_length_of` matcher tests usage of the `validates_length_of`
5
- # matcher. Note that this matcher is intended to be used against string
6
- # columns and not integer columns.
4
+ # The `validate_length_of` matcher tests usage of the
5
+ # `validates_length_of` matcher. Note that this matcher is intended to be
6
+ # used against string columns and not integer columns.
7
7
  #
8
8
  # #### Qualifiers
9
9
  #
@@ -23,13 +23,13 @@ module Shoulda
23
23
  # # RSpec
24
24
  #
25
25
  # describe User do
26
- # it { should ensure_length_of(:bio).is_at_least(15) }
26
+ # it { should validate_length_of(:bio).is_at_least(15) }
27
27
  # end
28
28
  #
29
29
  # # Test::Unit
30
30
  #
31
31
  # class UserTest < ActiveSupport::TestCase
32
- # should ensure_length_of(:bio).is_at_least(15)
32
+ # should validate_length_of(:bio).is_at_least(15)
33
33
  # end
34
34
  #
35
35
  # ##### is_at_most
@@ -47,12 +47,12 @@ module Shoulda
47
47
  #
48
48
  # # RSpec
49
49
  # describe User do
50
- # it { should ensure_length_of(:status_update).is_at_most(140) }
50
+ # it { should validate_length_of(:status_update).is_at_most(140) }
51
51
  # end
52
52
  #
53
53
  # # Test::Unit
54
54
  # class UserTest < ActiveSupport::TestCase
55
- # should ensure_length_of(:status_update).is_at_most(140)
55
+ # should validate_length_of(:status_update).is_at_most(140)
56
56
  # end
57
57
  #
58
58
  # ##### is_equal_to
@@ -70,12 +70,12 @@ module Shoulda
70
70
  #
71
71
  # # RSpec
72
72
  # describe User do
73
- # it { should ensure_length_of(:favorite_superhero).is_equal_to(6) }
73
+ # it { should validate_length_of(:favorite_superhero).is_equal_to(6) }
74
74
  # end
75
75
  #
76
76
  # # Test::Unit
77
77
  # class UserTest < ActiveSupport::TestCase
78
- # should ensure_length_of(:favorite_superhero).is_equal_to(6)
78
+ # should validate_length_of(:favorite_superhero).is_equal_to(6)
79
79
  # end
80
80
  #
81
81
  # ##### is_at_least + is_at_most
@@ -93,14 +93,14 @@ module Shoulda
93
93
  # # RSpec
94
94
  # describe User do
95
95
  # it do
96
- # should ensure_length_of(:password).
96
+ # should validate_length_of(:password).
97
97
  # is_at_least(5).is_at_most(30)
98
98
  # end
99
99
  # end
100
100
  #
101
101
  # # Test::Unit
102
102
  # class UserTest < ActiveSupport::TestCase
103
- # should ensure_length_of(:password).
103
+ # should validate_length_of(:password).
104
104
  # is_at_least(5).is_at_most(30)
105
105
  # end
106
106
  #
@@ -120,7 +120,7 @@ module Shoulda
120
120
  # # RSpec
121
121
  # describe User do
122
122
  # it do
123
- # should ensure_length_of(:password).
123
+ # should validate_length_of(:password).
124
124
  # is_at_least(10).
125
125
  # with_message("Password isn't long enough")
126
126
  # end
@@ -128,7 +128,7 @@ module Shoulda
128
128
  #
129
129
  # # Test::Unit
130
130
  # class UserTest < ActiveSupport::TestCase
131
- # should ensure_length_of(:password).
131
+ # should validate_length_of(:password).
132
132
  # is_at_least(10).
133
133
  # with_message("Password isn't long enough")
134
134
  # end
@@ -149,7 +149,7 @@ module Shoulda
149
149
  # # RSpec
150
150
  # describe User do
151
151
  # it do
152
- # should ensure_length_of(:secret_key).
152
+ # should validate_length_of(:secret_key).
153
153
  # is_at_least(15).
154
154
  # with_short_message('Secret key must be more than 15 characters')
155
155
  # end
@@ -157,7 +157,7 @@ module Shoulda
157
157
  #
158
158
  # # Test::Unit
159
159
  # class UserTest < ActiveSupport::TestCase
160
- # should ensure_length_of(:secret_key).
160
+ # should validate_length_of(:secret_key).
161
161
  # is_at_least(15).
162
162
  # with_short_message('Secret key must be more than 15 characters')
163
163
  # end
@@ -178,7 +178,7 @@ module Shoulda
178
178
  # # RSpec
179
179
  # describe User do
180
180
  # it do
181
- # should ensure_length_of(:secret_key).
181
+ # should validate_length_of(:secret_key).
182
182
  # is_at_most(100).
183
183
  # with_long_message('Secret key must be less than 100 characters')
184
184
  # end
@@ -186,19 +186,29 @@ module Shoulda
186
186
  #
187
187
  # # Test::Unit
188
188
  # class UserTest < ActiveSupport::TestCase
189
- # should ensure_length_of(:secret_key).
189
+ # should validate_length_of(:secret_key).
190
190
  # is_at_most(100).
191
191
  # with_long_message('Secret key must be less than 100 characters')
192
192
  # end
193
193
  #
194
- # @return [EnsureLengthOfMatcher]
194
+ # @return [ValidateLengthOfMatcher]
195
195
  #
196
+ def validate_length_of(attr)
197
+ ValidateLengthOfMatcher.new(attr)
198
+ end
199
+
200
+ # @deprecated Use {#validate_length_of} instead.
201
+ # @return [ValidateLengthOfMatcher]
196
202
  def ensure_length_of(attr)
197
- EnsureLengthOfMatcher.new(attr)
203
+ Shoulda::Matchers.warn_about_deprecated_method(
204
+ :ensure_length_of,
205
+ :validate_length_of
206
+ )
207
+ validate_length_of(attr)
198
208
  end
199
209
 
200
210
  # @private
201
- class EnsureLengthOfMatcher < ValidationMatcher
211
+ class ValidateLengthOfMatcher < ValidationMatcher
202
212
  include Helpers
203
213
 
204
214
  def initialize(attribute)
@@ -57,6 +57,27 @@ module Shoulda
57
57
  #
58
58
  # #### Qualifiers
59
59
  #
60
+ # ##### on
61
+ #
62
+ # Use `on` if your validation applies only under a certain context.
63
+ #
64
+ # class Robot
65
+ # include ActiveModel::Model
66
+ # attr_accessor :arms
67
+ #
68
+ # validates_presence_of :arms, on: :create
69
+ # end
70
+ #
71
+ # # RSpec
72
+ # describe Robot do
73
+ # it { should validate_presence_of(:arms).on(:create) }
74
+ # end
75
+ #
76
+ # # Test::Unit
77
+ # class RobotTest < ActiveSupport::TestCase
78
+ # should validate_presence_of(:arms).on(:create)
79
+ # end
80
+ #
60
81
  # ##### with_message
61
82
  #
62
83
  # Use `with_message` if you are using a custom validation message.
@@ -29,9 +29,9 @@ module Shoulda
29
29
 
30
30
  def messages_description
31
31
  if errors.empty?
32
- 'no errors'
32
+ ' no errors'
33
33
  else
34
- "errors: #{pretty_error_messages(validated_instance)}"
34
+ " errors:\n#{pretty_error_messages(validated_instance)}"
35
35
  end
36
36
  end
37
37
 
@@ -16,6 +16,8 @@ require "shoulda/matchers/active_record/have_readonly_attribute_matcher"
16
16
  require "shoulda/matchers/active_record/serialize_matcher"
17
17
  require "shoulda/matchers/active_record/accept_nested_attributes_for_matcher"
18
18
  require "shoulda/matchers/active_record/define_enum_for_matcher"
19
+ require "shoulda/matchers/active_record/uniqueness"
20
+ require "shoulda/matchers/active_record/validate_uniqueness_of_matcher"
19
21
 
20
22
  module Shoulda
21
23
  module Matchers
@@ -100,6 +100,28 @@ module Shoulda
100
100
  # should belong_to(:ancient_city).class_name('City')
101
101
  # end
102
102
  #
103
+ # ##### with_primary_key
104
+ #
105
+ # Use `with_primary_key` to test usage of the `:primary_key` option.
106
+ #
107
+ # class Person < ActiveRecord::Base
108
+ # belongs_to :great_country, primary_key: 'country_id'
109
+ # end
110
+ #
111
+ # # RSpec
112
+ # describe Person do
113
+ # it do
114
+ # should belong_to(:great_country).
115
+ # with_primary_key('country_id')
116
+ # end
117
+ # end
118
+ #
119
+ # # Test::Unit
120
+ # class PersonTest < ActiveSupport::TestCase
121
+ # should belong_to(:great_country).
122
+ # with_primary_key('country_id')
123
+ # end
124
+ #
103
125
  # ##### with_foreign_key
104
126
  #
105
127
  # Use `with_foreign_key` to test usage of the `:foreign_key` option.
@@ -295,6 +317,24 @@ module Shoulda
295
317
  # should have_many(:hopes).class_name('Dream')
296
318
  # end
297
319
  #
320
+ # ##### with_primary_key
321
+ #
322
+ # Use `with_primary_key` to test usage of the `:primary_key` option.
323
+ #
324
+ # class Person < ActiveRecord::Base
325
+ # has_many :worries, primary_key: 'worrier_id'
326
+ # end
327
+ #
328
+ # # RSpec
329
+ # describe Person do
330
+ # it { should have_many(:worries).with_primary_key('worrier_id') }
331
+ # end
332
+ #
333
+ # # Test::Unit
334
+ # class PersonTest < ActiveSupport::TestCase
335
+ # should have_many(:worries).with_primary_key('worrier_id')
336
+ # end
337
+ #
298
338
  # ##### with_foreign_key
299
339
  #
300
340
  # Use `with_foreign_key` to test usage of the `:foreign_key` option.
@@ -511,6 +551,24 @@ module Shoulda
511
551
  # should have_one(:contract).dependent(:nullify)
512
552
  # end
513
553
  #
554
+ # ##### with_primary_key
555
+ #
556
+ # Use `with_primary_key` to test usage of the `:primary_key` option.
557
+ #
558
+ # class Person < ActiveRecord::Base
559
+ # has_one :job, primary_key: 'worker_id'
560
+ # end
561
+ #
562
+ # # RSpec
563
+ # describe Person do
564
+ # it { should have_one(:job).with_primary_key('worker_id') }
565
+ # end
566
+ #
567
+ # # Test::Unit
568
+ # class PersonTest < ActiveSupport::TestCase
569
+ # should have_one(:job).with_primary_key('worker_id')
570
+ # end
571
+ #
514
572
  # ##### with_foreign_key
515
573
  #
516
574
  # Use `with_foreign_key` to test usage of the `:foreign_key` option.
@@ -814,6 +872,11 @@ module Shoulda
814
872
  self
815
873
  end
816
874
 
875
+ def with_primary_key(primary_key)
876
+ @options[:primary_key] = primary_key
877
+ self
878
+ end
879
+
817
880
  def validate(validate = true)
818
881
  @options[:validate] = validate
819
882
  self
@@ -846,6 +909,7 @@ module Shoulda
846
909
  macro_correct? &&
847
910
  (polymorphic? || class_exists?) &&
848
911
  foreign_key_exists? &&
912
+ primary_key_exists? &&
849
913
  class_name_correct? &&
850
914
  join_table_correct? &&
851
915
  autosave_correct? &&
@@ -889,7 +953,7 @@ module Shoulda
889
953
  end
890
954
 
891
955
  def missing_options
892
- missing_options = [missing, failing_submatchers.map(&:missing_option)]
956
+ missing_options = [missing, missing_options_for_failing_submatchers]
893
957
  missing_options.flatten.compact.join(', ')
894
958
  end
895
959
 
@@ -899,6 +963,14 @@ module Shoulda
899
963
  end
900
964
  end
901
965
 
966
+ def missing_options_for_failing_submatchers
967
+ if defined?(@failing_submatchers)
968
+ @failing_submatchers.map(&:missing_option)
969
+ else
970
+ []
971
+ end
972
+ end
973
+
902
974
  def association_exists?
903
975
  if reflection.nil?
904
976
  @missing = "no association called #{name}"
@@ -920,10 +992,19 @@ module Shoulda
920
992
  end
921
993
  end
922
994
 
995
+ def macro_supports_primary_key?
996
+ macro == :belongs_to ||
997
+ ([:has_many, :has_one].include?(macro) && !through?)
998
+ end
999
+
923
1000
  def foreign_key_exists?
924
1001
  !(belongs_foreign_key_missing? || has_foreign_key_missing?)
925
1002
  end
926
1003
 
1004
+ def primary_key_exists?
1005
+ !macro_supports_primary_key? || primary_key_correct?(model_class)
1006
+ end
1007
+
927
1008
  def belongs_foreign_key_missing?
928
1009
  macro == :belongs_to && !class_has_foreign_key?(model_class)
929
1010
  end
@@ -936,7 +1017,7 @@ module Shoulda
936
1017
 
937
1018
  def class_name_correct?
938
1019
  if options.key?(:class_name)
939
- if option_verifier.correct_for_string?(:class_name, options[:class_name])
1020
+ if option_verifier.correct_for_constant?(:class_name, options[:class_name])
940
1021
  true
941
1022
  else
942
1023
  @missing = "#{name} should resolve to #{options[:class_name]} for class_name"
@@ -1026,6 +1107,19 @@ module Shoulda
1026
1107
  end
1027
1108
  end
1028
1109
 
1110
+ def primary_key_correct?(klass)
1111
+ if options.key?(:primary_key)
1112
+ if option_verifier.correct_for_string?(:primary_key, options[:primary_key])
1113
+ true
1114
+ else
1115
+ @missing = "#{klass} does not have a #{options[:primary_key]} primary key"
1116
+ false
1117
+ end
1118
+ else
1119
+ true
1120
+ end
1121
+ end
1122
+
1029
1123
  def foreign_key
1030
1124
  if foreign_key_reflection
1031
1125
  if foreign_key_reflection.respond_to?(:foreign_key)
@@ -51,7 +51,7 @@ module Shoulda
51
51
 
52
52
  def missing_columns
53
53
  @missing_columns ||= expected_join_table_columns.select do |key|
54
- !actual_join_table_columns.include?(key)
54
+ !actual_join_table_columns.include?(key.to_s)
55
55
  end
56
56
  end
57
57
 
@@ -48,10 +48,10 @@ module Shoulda
48
48
  def foreign_key
49
49
  if has_and_belongs_to_many_reflection
50
50
  has_and_belongs_to_many_reflection.foreign_key
51
- elsif reflection.respond_to?(:primary_key_name)
52
- reflection.primary_key_name
53
- else
51
+ elsif reflection.respond_to?(:foreign_key)
54
52
  reflection.foreign_key
53
+ else
54
+ reflection.primary_key_name
55
55
  end
56
56
  end
57
57
 
@@ -24,6 +24,10 @@ module Shoulda
24
24
  correct_for?(:hash, name, expected_value)
25
25
  end
26
26
 
27
+ def correct_for_constant?(name, expected_unresolved_value)
28
+ correct_for?(:constant, name, expected_unresolved_value)
29
+ end
30
+
27
31
  def correct_for_relation_clause?(name, expected_value)
28
32
  correct_for?(:relation_clause, name, expected_value)
29
33
  end
@@ -50,7 +54,7 @@ module Shoulda
50
54
  if expected_value.nil?
51
55
  true
52
56
  else
53
- expected_value = type_cast(type, expected_value_for(name, expected_value))
57
+ expected_value = type_cast(type, expected_value_for(type, name, expected_value))
54
58
  actual_value = type_cast(type, actual_value_for(name))
55
59
  expected_value == actual_value
56
60
  end
@@ -65,9 +69,11 @@ module Shoulda
65
69
  end
66
70
  end
67
71
 
68
- def expected_value_for(name, value)
72
+ def expected_value_for(type, name, value)
69
73
  if RELATION_OPTIONS.include?(name)
70
74
  expected_value_for_relation_clause(name, value)
75
+ elsif type == :constant
76
+ expected_value_for_constant(value)
71
77
  else
72
78
  value
73
79
  end
@@ -78,6 +84,20 @@ module Shoulda
78
84
  reflector.extract_relation_clause_from(relation, name)
79
85
  end
80
86
 
87
+ def expected_value_for_constant(name)
88
+ namespace = Shoulda::Matchers::Util.deconstantize(
89
+ reflector.model_class.to_s
90
+ )
91
+
92
+ ["#{namespace}::#{name}", name].each do |path|
93
+ constant = Shoulda::Matchers::Util.safe_constantize(path)
94
+
95
+ if constant
96
+ return constant
97
+ end
98
+ end
99
+ end
100
+
81
101
  def actual_value_for_relation_clause(name)
82
102
  reflector.extract_relation_clause_from(reflector.association_relation, name)
83
103
  end