shoulda-matchers 3.1.0 → 5.2.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.
Files changed (288) hide show
  1. checksums.yaml +5 -5
  2. data/{MIT-LICENSE → LICENSE} +1 -1
  3. data/README.md +407 -232
  4. data/docs/errors/NonCaseSwappableValueError.md +2 -2
  5. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +7 -80
  6. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +4 -3
  7. data/lib/shoulda/matchers/action_controller/flash_store.rb +2 -4
  8. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +36 -30
  9. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +8 -10
  10. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +7 -9
  11. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +18 -15
  12. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +3 -2
  13. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +3 -3
  14. data/lib/shoulda/matchers/action_controller/route_matcher.rb +88 -29
  15. data/lib/shoulda/matchers/action_controller/route_params.rb +2 -2
  16. data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +4 -4
  17. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +3 -3
  18. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
  19. data/lib/shoulda/matchers/action_controller.rb +2 -0
  20. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
  21. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -9
  22. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
  23. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
  24. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
  25. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +42 -39
  26. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
  27. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +52 -26
  28. data/lib/shoulda/matchers/active_model/helpers.rb +2 -2
  29. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -30
  30. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +2 -1
  31. data/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
  32. data/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
  33. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
  34. data/lib/shoulda/matchers/active_model/qualifiers.rb +2 -0
  35. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +30 -6
  36. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +8 -3
  37. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +31 -16
  38. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +52 -16
  39. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +137 -84
  40. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +159 -46
  41. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +130 -66
  42. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +251 -24
  43. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +12 -9
  44. data/lib/shoulda/matchers/active_model/validation_matcher.rb +38 -6
  45. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
  46. data/lib/shoulda/matchers/active_model/validator.rb +4 -9
  47. data/lib/shoulda/matchers/active_model.rb +3 -5
  48. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +10 -7
  49. data/lib/shoulda/matchers/active_record/association_matcher.rb +386 -111
  50. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
  51. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
  52. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
  53. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
  54. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +14 -15
  55. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +30 -8
  56. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +34 -11
  57. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +69 -0
  58. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
  59. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +74 -0
  60. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
  61. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
  62. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +458 -42
  63. data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +185 -0
  64. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +63 -23
  65. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +164 -48
  66. data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +106 -0
  67. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +13 -11
  68. data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
  69. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
  70. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +18 -18
  71. data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
  72. data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
  73. data/lib/shoulda/matchers/active_record/uniqueness.rb +1 -1
  74. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +430 -200
  75. data/lib/shoulda/matchers/active_record.rb +28 -20
  76. data/lib/shoulda/matchers/configuration.rb +12 -1
  77. data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
  78. data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
  79. data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
  80. data/lib/shoulda/matchers/doublespeak/object_double.rb +6 -2
  81. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
  82. data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
  83. data/lib/shoulda/matchers/doublespeak.rb +2 -1
  84. data/lib/shoulda/matchers/error.rb +1 -1
  85. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +109 -29
  86. data/lib/shoulda/matchers/independent.rb +2 -2
  87. data/lib/shoulda/matchers/integrations/configuration.rb +8 -4
  88. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  89. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
  90. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  91. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  92. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  93. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  94. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  95. data/lib/shoulda/matchers/rails_shim.rb +172 -51
  96. data/lib/shoulda/matchers/routing.rb +2 -2
  97. data/lib/shoulda/matchers/util/word_wrap.rb +17 -12
  98. data/lib/shoulda/matchers/util.rb +39 -5
  99. data/lib/shoulda/matchers/version.rb +1 -1
  100. data/lib/shoulda/matchers/warn.rb +4 -3
  101. data/shoulda-matchers.gemspec +33 -15
  102. metadata +31 -338
  103. data/.gitignore +0 -12
  104. data/.hound.yml +0 -3
  105. data/.hound_config/ruby.yml +0 -12
  106. data/.travis.yml +0 -19
  107. data/.yardopts +0 -10
  108. data/Appraisals +0 -73
  109. data/CONTRIBUTING.md +0 -101
  110. data/Gemfile +0 -15
  111. data/Gemfile.lock +0 -70
  112. data/NEWS.md +0 -986
  113. data/Rakefile +0 -39
  114. data/custom_plan.rb +0 -88
  115. data/doc_config/gh-pages/index.html.erb +0 -9
  116. data/doc_config/yard/setup.rb +0 -22
  117. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -5967
  118. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +0 -12
  119. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +0 -62
  120. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +0 -69
  121. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +0 -312
  122. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -32
  123. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +0 -1
  124. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +0 -8
  125. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -298
  126. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +0 -1
  127. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +0 -289
  128. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +0 -6
  129. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +0 -8
  130. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +0 -14
  131. data/doc_config/yard/templates/default/layout/html/fonts.erb +0 -1
  132. data/doc_config/yard/templates/default/layout/html/footer.erb +0 -6
  133. data/doc_config/yard/templates/default/layout/html/layout.erb +0 -23
  134. data/doc_config/yard/templates/default/layout/html/search.erb +0 -13
  135. data/doc_config/yard/templates/default/layout/html/setup.rb +0 -40
  136. data/doc_config/yard/templates/default/method_details/html/source.erb +0 -10
  137. data/doc_config/yard/templates/default/module/html/box_info.erb +0 -31
  138. data/gemfiles/4.0.0.gemfile +0 -38
  139. data/gemfiles/4.0.0.gemfile.lock +0 -223
  140. data/gemfiles/4.0.1.gemfile +0 -38
  141. data/gemfiles/4.0.1.gemfile.lock +0 -225
  142. data/gemfiles/4.1.gemfile +0 -38
  143. data/gemfiles/4.1.gemfile.lock +0 -220
  144. data/gemfiles/4.2.gemfile +0 -38
  145. data/gemfiles/4.2.gemfile.lock +0 -243
  146. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +0 -159
  147. data/lib/shoulda/matchers/independent/delegate_method_matcher/stubbed_target.rb +0 -37
  148. data/script/SUPPORTED_VERSIONS +0 -1
  149. data/script/install_gems_in_all_appraisals +0 -14
  150. data/script/run_all_tests +0 -14
  151. data/script/update_gem_in_all_appraisals +0 -15
  152. data/script/update_gems_in_all_appraisals +0 -14
  153. data/spec/acceptance/active_model_integration_spec.rb +0 -23
  154. data/spec/acceptance/independent_matchers_spec.rb +0 -125
  155. data/spec/acceptance/multiple_libraries_integration_spec.rb +0 -55
  156. data/spec/acceptance/rails_integration_spec.rb +0 -156
  157. data/spec/acceptance_spec_helper.rb +0 -23
  158. data/spec/doublespeak_spec_helper.rb +0 -2
  159. data/spec/report_warnings.rb +0 -7
  160. data/spec/spec_helper.rb +0 -21
  161. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +0 -133
  162. data/spec/support/acceptance/helpers/active_model_helpers.rb +0 -11
  163. data/spec/support/acceptance/helpers/array_helpers.rb +0 -13
  164. data/spec/support/acceptance/helpers/base_helpers.rb +0 -19
  165. data/spec/support/acceptance/helpers/command_helpers.rb +0 -55
  166. data/spec/support/acceptance/helpers/file_helpers.rb +0 -19
  167. data/spec/support/acceptance/helpers/gem_helpers.rb +0 -31
  168. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -11
  169. data/spec/support/acceptance/helpers/n_unit_helpers.rb +0 -25
  170. data/spec/support/acceptance/helpers/pluralization_helpers.rb +0 -13
  171. data/spec/support/acceptance/helpers/rails_version_helpers.rb +0 -11
  172. data/spec/support/acceptance/helpers/rspec_helpers.rb +0 -24
  173. data/spec/support/acceptance/helpers/ruby_version_helpers.rb +0 -9
  174. data/spec/support/acceptance/helpers/step_helpers.rb +0 -127
  175. data/spec/support/acceptance/helpers.rb +0 -31
  176. data/spec/support/acceptance/matchers/have_output.rb +0 -31
  177. data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +0 -55
  178. data/spec/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +0 -103
  179. data/spec/support/tests/bundle.rb +0 -94
  180. data/spec/support/tests/command_runner.rb +0 -230
  181. data/spec/support/tests/current_bundle.rb +0 -61
  182. data/spec/support/tests/database.rb +0 -28
  183. data/spec/support/tests/database_adapters/postgresql.rb +0 -25
  184. data/spec/support/tests/database_adapters/sqlite3.rb +0 -26
  185. data/spec/support/tests/database_configuration.rb +0 -33
  186. data/spec/support/tests/database_configuration_registry.rb +0 -28
  187. data/spec/support/tests/filesystem.rb +0 -100
  188. data/spec/support/tests/version.rb +0 -45
  189. data/spec/support/unit/active_record/create_table.rb +0 -54
  190. data/spec/support/unit/attribute.rb +0 -47
  191. data/spec/support/unit/capture.rb +0 -40
  192. data/spec/support/unit/change_value.rb +0 -111
  193. data/spec/support/unit/create_model_arguments/basic.rb +0 -135
  194. data/spec/support/unit/create_model_arguments/has_many.rb +0 -15
  195. data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +0 -74
  196. data/spec/support/unit/helpers/active_model_helpers.rb +0 -27
  197. data/spec/support/unit/helpers/active_model_versions.rb +0 -28
  198. data/spec/support/unit/helpers/active_record_versions.rb +0 -24
  199. data/spec/support/unit/helpers/active_resource_builder.rb +0 -27
  200. data/spec/support/unit/helpers/allow_value_matcher_helpers.rb +0 -15
  201. data/spec/support/unit/helpers/class_builder.rb +0 -90
  202. data/spec/support/unit/helpers/column_type_helpers.rb +0 -26
  203. data/spec/support/unit/helpers/confirmation_matcher_helpers.rb +0 -17
  204. data/spec/support/unit/helpers/controller_builder.rb +0 -63
  205. data/spec/support/unit/helpers/database_helpers.rb +0 -20
  206. data/spec/support/unit/helpers/i18n_faker.rb +0 -15
  207. data/spec/support/unit/helpers/mailer_builder.rb +0 -12
  208. data/spec/support/unit/helpers/model_builder.rb +0 -114
  209. data/spec/support/unit/helpers/rails_versions.rb +0 -28
  210. data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +0 -44
  211. data/spec/support/unit/i18n.rb +0 -7
  212. data/spec/support/unit/load_environment.rb +0 -12
  213. data/spec/support/unit/matchers/deprecate.rb +0 -60
  214. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +0 -51
  215. data/spec/support/unit/matchers/fail_with_message_matcher.rb +0 -62
  216. data/spec/support/unit/matchers/print_warning_including.rb +0 -59
  217. data/spec/support/unit/model_creation_strategies/active_model.rb +0 -111
  218. data/spec/support/unit/model_creation_strategies/active_record.rb +0 -77
  219. data/spec/support/unit/model_creators/active_model.rb +0 -39
  220. data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +0 -95
  221. data/spec/support/unit/model_creators/active_record/has_many.rb +0 -67
  222. data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +0 -42
  223. data/spec/support/unit/model_creators/active_record.rb +0 -43
  224. data/spec/support/unit/model_creators/basic.rb +0 -97
  225. data/spec/support/unit/model_creators.rb +0 -19
  226. data/spec/support/unit/rails_application.rb +0 -126
  227. data/spec/support/unit/record_builder_with_i18n_validation_message.rb +0 -69
  228. data/spec/support/unit/record_validating_confirmation_builder.rb +0 -51
  229. data/spec/support/unit/record_with_different_error_attribute_builder.rb +0 -92
  230. data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +0 -79
  231. data/spec/support/unit/shared_examples/numerical_submatcher.rb +0 -17
  232. data/spec/support/unit/shared_examples/set_session_or_flash.rb +0 -360
  233. data/spec/support/unit/validation_matcher_scenario.rb +0 -62
  234. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +0 -82
  235. data/spec/unit/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +0 -28
  236. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +0 -592
  237. data/spec/unit/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +0 -42
  238. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +0 -76
  239. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +0 -62
  240. data/spec/unit/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +0 -90
  241. data/spec/unit/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +0 -31
  242. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +0 -330
  243. data/spec/unit/shoulda/matchers/action_controller/route_params_spec.rb +0 -30
  244. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +0 -67
  245. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +0 -17
  246. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +0 -562
  247. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -115
  248. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +0 -823
  249. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -86
  250. data/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +0 -20
  251. data/spec/unit/shoulda/matchers/active_model/helpers_spec.rb +0 -162
  252. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +0 -266
  253. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +0 -91
  254. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +0 -149
  255. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -207
  256. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -1015
  257. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -288
  258. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +0 -1837
  259. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -380
  260. data/spec/unit/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -107
  261. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +0 -1242
  262. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +0 -251
  263. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +0 -168
  264. data/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +0 -111
  265. data/spec/unit/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +0 -85
  266. data/spec/unit/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +0 -41
  267. data/spec/unit/shoulda/matchers/active_record/serialize_matcher_spec.rb +0 -86
  268. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +0 -1418
  269. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +0 -190
  270. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +0 -21
  271. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +0 -271
  272. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +0 -77
  273. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +0 -72
  274. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +0 -101
  275. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +0 -80
  276. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +0 -27
  277. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher/stubbed_target_spec.rb +0 -43
  278. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +0 -517
  279. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +0 -242
  280. data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +0 -252
  281. data/spec/unit_spec_helper.rb +0 -46
  282. data/spec/warnings_spy/filesystem.rb +0 -45
  283. data/spec/warnings_spy/partitioner.rb +0 -36
  284. data/spec/warnings_spy/reader.rb +0 -53
  285. data/spec/warnings_spy/reporter.rb +0 -88
  286. data/spec/warnings_spy.rb +0 -64
  287. data/tasks/documentation.rb +0 -199
  288. data/zeus.json +0 -11
@@ -1,70 +1,191 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- class RailsShim
5
- def self.verb_for_update
6
- if action_pack_gte_4_1?
4
+ module RailsShim # rubocop:disable Metrics/ModuleLength
5
+ class << self
6
+ def action_pack_version
7
+ Gem::Version.new(::ActionPack::VERSION::STRING)
8
+ rescue NameError
9
+ Gem::Version.new('0')
10
+ end
11
+
12
+ def active_record_gte_6?
13
+ Gem::Requirement.new('>= 6').satisfied_by?(active_record_version)
14
+ end
15
+
16
+ def active_record_version
17
+ Gem::Version.new(::ActiveRecord::VERSION::STRING)
18
+ rescue NameError
19
+ Gem::Version.new('0')
20
+ end
21
+
22
+ def active_model_version
23
+ Gem::Version.new(::ActiveModel::VERSION::STRING)
24
+ rescue NameError
25
+ Gem::Version.new('0')
26
+ end
27
+
28
+ def active_model_gte_7?
29
+ Gem::Requirement.new('>= 7').satisfied_by?(active_model_version)
30
+ end
31
+
32
+ def active_model_lt_7?
33
+ Gem::Requirement.new('< 7').satisfied_by?(active_model_version)
34
+ end
35
+
36
+ def generate_validation_message(
37
+ record,
38
+ attribute,
39
+ type,
40
+ model_name,
41
+ options
42
+ )
43
+ if record && record.errors.respond_to?(:generate_message)
44
+ record.errors.generate_message(attribute.to_sym, type, options)
45
+ else
46
+ simply_generate_validation_message(
47
+ attribute,
48
+ type,
49
+ model_name,
50
+ options,
51
+ )
52
+ end
53
+ rescue RangeError
54
+ simply_generate_validation_message(
55
+ attribute,
56
+ type,
57
+ model_name,
58
+ options,
59
+ )
60
+ end
61
+
62
+ def serialized_attributes_for(model)
63
+ attribute_types_for(model).
64
+ inject({}) do |hash, (attribute_name, attribute_type)|
65
+ if attribute_type.is_a?(::ActiveRecord::Type::Serialized)
66
+ hash.merge(attribute_name => attribute_type.coder)
67
+ else
68
+ hash
69
+ end
70
+ end
71
+ rescue NotImplementedError
72
+ {}
73
+ end
74
+
75
+ def attribute_serialization_coder_for(model, attribute_name)
76
+ serialized_attributes_for(model)[attribute_name.to_s]
77
+ end
78
+
79
+ def verb_for_update
7
80
  :patch
8
- else
9
- :put
10
81
  end
11
- end
12
82
 
13
- def self.type_cast_default_for(model, column)
14
- if model.respond_to?(:column_defaults)
15
- # Rails 4.2
16
- model.column_defaults[column.name]
17
- else
18
- column.default
83
+ def parent_of(mod)
84
+ if mod.respond_to?(:module_parent)
85
+ mod.module_parent
86
+ else
87
+ mod.parent
88
+ end
19
89
  end
20
- end
21
90
 
22
- def self.serialized_attributes_for(model)
23
- if defined?(::ActiveRecord::Type::Serialized)
24
- # Rails 5+
25
- model.columns.select do |column|
26
- column.cast_type.is_a?(::ActiveRecord::Type::Serialized)
27
- end.inject({}) do |hash, column|
28
- hash[column.name.to_s] = column.cast_type.coder
29
- hash
91
+ def has_secure_password?(record, attribute_name)
92
+ if secure_password_module
93
+ attribute_name == :password &&
94
+ record.class.ancestors.include?(secure_password_module)
95
+ else
96
+ record.respond_to?("authenticate_#{attribute_name}")
30
97
  end
31
- else
32
- model.serialized_attributes
33
98
  end
34
- end
35
99
 
36
- def self.generate_validation_message(record, attribute, type, model_name, options)
37
- if record && record.errors.respond_to?(:generate_message)
38
- record.errors.generate_message(attribute.to_sym, type, options)
39
- else
40
- simply_generate_validation_message(attribute, type, model_name, options)
100
+ def digestible_attributes_in(record)
101
+ record.methods.inject([]) do |array, method_name|
102
+ match = method_name.to_s.match(
103
+ /\A(\w+)_(?:confirmation|digest)=\Z/,
104
+ )
105
+
106
+ if match
107
+ array.concat([match[1].to_sym])
108
+ else
109
+ array
110
+ end
111
+ end
41
112
  end
42
- rescue RangeError
43
- simply_generate_validation_message(attribute, type, model_name, options)
44
- end
45
113
 
46
- def self.simply_generate_validation_message(attribute, type, model_name, options)
47
- default_translation_keys = [
48
- :"activerecord.errors.models.#{model_name}.#{type}",
49
- :"activerecord.errors.messages.#{type}",
50
- :"errors.attributes.#{attribute}.#{type}",
51
- :"errors.messages.#{type}"
52
- ]
53
- primary_translation_key = :"activerecord.errors.models.#{model_name}.attributes.#{attribute}.#{type}"
54
- translate_options = { default: default_translation_keys }.merge(options)
55
- I18n.translate(primary_translation_key, translate_options)
56
- end
114
+ def secure_password_module
115
+ ::ActiveModel::SecurePassword::InstanceMethodsOnActivation
116
+ rescue NameError
117
+ nil
118
+ end
57
119
 
58
- def self.active_record_major_version
59
- ::ActiveRecord::VERSION::MAJOR
60
- end
120
+ def attribute_types_for(model)
121
+ if model.respond_to?(:attribute_types)
122
+ model.attribute_types
123
+ elsif model.respond_to?(:type_for_attribute)
124
+ model.columns.inject({}) do |hash, column|
125
+ key = column.name.to_s
126
+ value = model.type_for_attribute(column.name)
127
+ hash.merge(key => value)
128
+ end
129
+ else
130
+ raise NotImplementedError
131
+ end
132
+ end
61
133
 
62
- def self.action_pack_gte_4_1?
63
- Gem::Requirement.new('>= 4.1').satisfied_by?(action_pack_version)
64
- end
134
+ def attribute_type_for(model, attribute_name)
135
+ attribute_types_for(model)[attribute_name.to_s]
136
+ rescue NotImplementedError
137
+ if model.respond_to?(:type_for_attribute)
138
+ model.type_for_attribute(attribute_name)
139
+ else
140
+ FakeAttributeType.new(model, attribute_name)
141
+ end
142
+ end
65
143
 
66
- def self.action_pack_version
67
- Gem::Version.new(::ActionPack::VERSION::STRING)
144
+ def supports_full_attributes_api?(model)
145
+ defined?(::ActiveModel::Attributes) &&
146
+ model.respond_to?(:attribute_types)
147
+ end
148
+
149
+ private
150
+
151
+ def simply_generate_validation_message(
152
+ attribute,
153
+ type,
154
+ model_name,
155
+ options
156
+ )
157
+ default_translation_keys = [
158
+ :"activemodel.errors.models.#{model_name}.attributes.#{attribute}
159
+ .#{type}",
160
+ :"activemodel.errors.models.#{model_name}.#{type}",
161
+ :"activemodel.errors.messages.#{type}",
162
+ :"activerecord.errors.models.#{model_name}.attributes.#{attribute}
163
+ .#{type}",
164
+ :"activerecord.errors.models.#{model_name}.#{type}",
165
+ :"activerecord.errors.messages.#{type}",
166
+ :"errors.attributes.#{attribute}.#{type}",
167
+ :"errors.messages.#{type}",
168
+ ]
169
+ primary_translation_key = default_translation_keys.shift
170
+ translate_options =
171
+ { default: default_translation_keys }.merge(options)
172
+ I18n.translate(primary_translation_key, translate_options)
173
+ end
174
+
175
+ class FakeAttributeType
176
+ def initialize(model, attribute_name)
177
+ @model = model
178
+ @attribute_name = attribute_name
179
+ end
180
+
181
+ def coder
182
+ nil
183
+ end
184
+
185
+ private
186
+
187
+ attr_reader :model, :attribute_name
188
+ end
68
189
  end
69
190
  end
70
191
  end
@@ -2,8 +2,8 @@ module Shoulda
2
2
  module Matchers
3
3
  # @private
4
4
  module Routing
5
- def route(method, path)
6
- ActionController::RouteMatcher.new(method, path, self)
5
+ def route(method, path, port: nil)
6
+ ActionController::RouteMatcher.new(self, method, path, port: port)
7
7
  end
8
8
  end
9
9
  end
@@ -1,10 +1,16 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- def self.word_wrap(document, options = {})
5
- Document.new(document, options).wrap
4
+ module WordWrap
5
+ TERMINAL_WIDTH = 72
6
+
7
+ def word_wrap(document, options = {})
8
+ Document.new(document, **options).wrap
9
+ end
6
10
  end
7
11
 
12
+ extend WordWrap
13
+
8
14
  # @private
9
15
  class Document
10
16
  def initialize(document, indent: 0)
@@ -35,10 +41,10 @@ module Shoulda
35
41
 
36
42
  # @private
37
43
  class Text < ::String
38
- LIST_ITEM_REGEXP = /\A((?:[a-z0-9]+(?:\)|\.)|\*) )/
44
+ LIST_ITEM_REGEXP = /\A((?:[a-z0-9]+(?:\)|\.)|\*) )/.freeze
39
45
 
40
46
  def indented?
41
- self =~ /\A[ ]+/
47
+ self =~ /\A +/
42
48
  end
43
49
 
44
50
  def list_item?
@@ -82,11 +88,11 @@ module Shoulda
82
88
  end
83
89
 
84
90
  def combine_list_item_lines(lines)
85
- lines.reduce([]) do |combined_lines, line|
91
+ lines.inject([]) do |combined_lines, line|
86
92
  if line.list_item?
87
93
  combined_lines << line
88
94
  else
89
- combined_lines.last << (' ' + line).squeeze(' ')
95
+ combined_lines.last << (" #{line}").squeeze(' ')
90
96
  end
91
97
 
92
98
  combined_lines
@@ -108,8 +114,7 @@ module Shoulda
108
114
 
109
115
  # @private
110
116
  class Line
111
- TERMINAL_WIDTH = 72
112
- OFFSETS = { left: -1, right: +1 }
117
+ OFFSETS = { left: -1, right: +1 }.freeze
113
118
 
114
119
  def initialize(line, indent: 0)
115
120
  @indent = indent
@@ -164,10 +169,10 @@ module Shoulda
164
169
  end
165
170
  end
166
171
 
167
- def wrap_line(line, direction: :left)
172
+ def wrap_line(line)
168
173
  index = nil
169
174
 
170
- if line.length > TERMINAL_WIDTH
175
+ if line.length > Shoulda::Matchers::WordWrap::TERMINAL_WIDTH
171
176
  index = determine_where_to_break_line(line, direction: :left)
172
177
 
173
178
  if index == -1
@@ -180,7 +185,7 @@ module Shoulda
180
185
  leftover = ''
181
186
  else
182
187
  fitted_line = line[0..index].rstrip
183
- leftover = line[index + 1 .. -1]
188
+ leftover = line[index + 1..]
184
189
  end
185
190
 
186
191
  { fitted_line: fitted_line, leftover: leftover }
@@ -188,7 +193,7 @@ module Shoulda
188
193
 
189
194
  def determine_where_to_break_line(line, args)
190
195
  direction = args.fetch(:direction)
191
- index = TERMINAL_WIDTH
196
+ index = Shoulda::Matchers::WordWrap::TERMINAL_WIDTH
192
197
  offset = OFFSETS.fetch(direction)
193
198
 
194
199
  while line[index] !~ /\s/ && (0...line.length).cover?(index)
@@ -4,9 +4,13 @@ module Shoulda
4
4
  module Matchers
5
5
  # @private
6
6
  module Util
7
+ MAXIMUM_LENGTH_OF_VALUE_TO_DISPLAY = 500
8
+
7
9
  def self.deconstantize(path)
8
- if defined?(ActiveSupport::Inflector) &&
10
+ if (
11
+ defined?(ActiveSupport::Inflector) &&
9
12
  ActiveSupport::Inflector.respond_to?(:deconstantize)
13
+ )
10
14
  ActiveSupport::Inflector.deconstantize(path)
11
15
  else
12
16
  path.to_s[0...(path.to_s.rindex('::') || 0)]
@@ -14,8 +18,10 @@ module Shoulda
14
18
  end
15
19
 
16
20
  def self.safe_constantize(camel_cased_word)
17
- if defined?(ActiveSupport::Inflector) &&
21
+ if (
22
+ defined?(ActiveSupport::Inflector) &&
18
23
  ActiveSupport::Inflector.respond_to?(:safe_constantize)
24
+ )
19
25
  ActiveSupport::Inflector.safe_constantize(camel_cased_word)
20
26
  else
21
27
  begin
@@ -27,12 +33,14 @@ module Shoulda
27
33
  end
28
34
 
29
35
  def self.indent(string, width)
36
+ return if !string
37
+
30
38
  indentation = ' ' * width
31
39
  string.split(/[\n\r]/).map { |line| indentation + line }.join("\n")
32
40
  end
33
41
 
34
42
  def self.a_or_an(next_word)
35
- if next_word =~ /\A[aeiou]/i
43
+ if next_word =~ /\A[aeiou]/i && next_word != 'unique'
36
44
  "an #{next_word}"
37
45
  else
38
46
  "a #{next_word}"
@@ -40,7 +48,19 @@ module Shoulda
40
48
  end
41
49
 
42
50
  def self.inspect_value(value)
43
- "‹#{value.inspect}›"
51
+ case value
52
+ when Hash
53
+ inspect_hash(value)
54
+ when Range
55
+ inspect_range(value)
56
+ else
57
+ inspected_value = value.inspect
58
+ if inspected_value.length > MAXIMUM_LENGTH_OF_VALUE_TO_DISPLAY
59
+ "‹#{inspected_value[0, MAXIMUM_LENGTH_OF_VALUE_TO_DISPLAY]}...›"
60
+ else
61
+ "‹#{inspected_value}›"
62
+ end
63
+ end
44
64
  end
45
65
 
46
66
  def self.inspect_values(values)
@@ -51,6 +71,20 @@ module Shoulda
51
71
  "#{inspect_value(range.first)} to #{inspect_value(range.last)}"
52
72
  end
53
73
 
74
+ def self.inspect_hash(hash)
75
+ output = '‹{'
76
+
77
+ output << hash.map { |key, value|
78
+ if key.is_a?(Symbol)
79
+ "#{key}: #{value.inspect}"
80
+ else
81
+ "#{key.inspect} => #{value.inspect}"
82
+ end
83
+ }.join(', ')
84
+
85
+ output << '}›'
86
+ end
87
+
54
88
  def self.dummy_value_for(column_type, array: false)
55
89
  if array
56
90
  [dummy_value_for(column_type, array: false)]
@@ -63,7 +97,7 @@ module Shoulda
63
97
  when :datetime, :timestamp
64
98
  DateTime.new(2100, 1, 1)
65
99
  when :time
66
- Time.new(2100, 1, 1)
100
+ Time.new(2000, 1, 1)
67
101
  when :uuid
68
102
  SecureRandom.uuid
69
103
  when :boolean
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- VERSION = '3.1.0'.freeze
4
+ VERSION = '5.2.0'.freeze
5
5
  end
6
6
  end
@@ -1,16 +1,17 @@
1
1
  module Shoulda
2
2
  module Matchers
3
+ # @private
3
4
  TERMINAL_MAX_WIDTH = 72
4
5
 
5
6
  # @private
6
7
  def self.warn(message)
7
- header = "Warning from shoulda-matchers:"
8
- divider = "*" * TERMINAL_MAX_WIDTH
8
+ header = 'Warning from shoulda-matchers:'
9
+ divider = '*' * TERMINAL_MAX_WIDTH
9
10
  wrapped_message = word_wrap(message)
10
11
  full_message = [
11
12
  divider,
12
13
  [header, wrapped_message.strip].join("\n\n"),
13
- divider
14
+ divider,
14
15
  ].join("\n")
15
16
 
16
17
  Kernel.warn(full_message)
@@ -2,22 +2,40 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
2
2
  require 'shoulda/matchers/version'
3
3
 
4
4
  Gem::Specification.new do |s|
5
- s.name = "shoulda-matchers"
5
+ s.name = 'shoulda-matchers'
6
6
  s.version = Shoulda::Matchers::VERSION.dup
7
- s.authors = ["Tammer Saleh", "Joe Ferris", "Ryan McGeary", "Dan Croak",
8
- "Matt Jankowski", "Stafford Brunk", "Elliot Winkler"]
9
- s.date = Time.now.strftime("%Y-%m-%d")
10
- s.email = "support@thoughtbot.com"
11
- s.homepage = "http://thoughtbot.com/community/"
12
- s.summary = "Making tests easy on the fingers and eyes"
13
- s.license = "MIT"
14
- s.description = "Making tests easy on the fingers and eyes"
7
+ s.authors = [
8
+ 'Tammer Saleh',
9
+ 'Joe Ferris',
10
+ 'Ryan McGeary',
11
+ 'Dan Croak',
12
+ 'Matt Jankowski',
13
+ 'Stafford Brunk',
14
+ 'Elliot Winkler',
15
+ ]
16
+ s.date = Time.now.strftime('%Y-%m-%d')
17
+ s.email = 'support@thoughtbot.com'
18
+ s.homepage = 'https://matchers.shoulda.io/'
19
+ s.summary = 'Simple one-liner tests for common Rails functionality'
20
+ s.license = 'MIT'
21
+ s.description = <<~DESC.tr("\n", ' ').squeeze(' ')
22
+ Shoulda Matchers provides RSpec- and Minitest-compatible one-liners to test
23
+ common Rails functionality that, if written by hand, would be much
24
+ longer, more complex, and error-prone.
25
+ DESC
15
26
 
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ["lib"]
27
+ s.metadata = {
28
+ 'bug_tracker_uri' => 'https://github.com/thoughtbot/shoulda-matchers/issues',
29
+ 'changelog_uri' => 'https://github.com/thoughtbot/shoulda-matchers/blob/main/CHANGELOG.md',
30
+ 'documentation_uri' => 'https://matchers.shoulda.io/docs',
31
+ 'homepage_uri' => 'https://matchers.shoulda.io',
32
+ 'source_code_uri' => 'https://github.com/thoughtbot/shoulda-matchers',
33
+ }
20
34
 
21
- s.required_ruby_version = '>= 2.0.0'
22
- s.add_dependency('activesupport', '>= 4.0.0')
35
+ s.files = Dir['{docs,lib}/**/*', 'README.md', 'LICENSE',
36
+ 'shoulda-matchers.gemspec']
37
+ s.require_paths = ['lib']
38
+
39
+ s.required_ruby_version = '>= 2.6.0'
40
+ s.add_dependency('activesupport', '>= 5.2.0')
23
41
  end