shoulda-matchers 4.0.0.rc1 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +72 -40
  4. data/lib/shoulda/matchers/action_controller.rb +2 -0
  5. data/lib/shoulda/matchers/active_model.rb +2 -3
  6. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +1 -0
  7. data/lib/shoulda/matchers/active_record.rb +2 -0
  8. data/lib/shoulda/matchers/active_record/association_matcher.rb +34 -0
  9. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +27 -4
  10. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +27 -4
  11. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1 -1
  12. data/lib/shoulda/matchers/independent.rb +2 -1
  13. data/lib/shoulda/matchers/rails_shim.rb +5 -9
  14. data/lib/shoulda/matchers/version.rb +1 -1
  15. data/lib/shoulda/matchers/warn.rb +1 -0
  16. data/shoulda-matchers.gemspec +11 -3
  17. metadata +13 -340
  18. data/.gitignore +0 -12
  19. data/.hound.yml +0 -3
  20. data/.hound/ruby.yml +0 -1062
  21. data/.python-version +0 -1
  22. data/.rubocop.yml +0 -15
  23. data/.travis.yml +0 -21
  24. data/.yardopts +0 -10
  25. data/Appraisals +0 -105
  26. data/CONTRIBUTING.md +0 -172
  27. data/Gemfile +0 -15
  28. data/Gemfile.lock +0 -59
  29. data/MAINTAINING.md +0 -250
  30. data/NEWS.md +0 -1235
  31. data/Rakefile +0 -46
  32. data/bin/setup +0 -190
  33. data/custom_plan.rb +0 -104
  34. data/doc_config/gh-pages/index.html.erb +0 -9
  35. data/doc_config/yard/setup.rb +0 -22
  36. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -5967
  37. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +0 -12
  38. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +0 -66
  39. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +0 -69
  40. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +0 -312
  41. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -26
  42. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +0 -1
  43. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +0 -8
  44. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -281
  45. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +0 -1
  46. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +0 -289
  47. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +0 -6
  48. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +0 -35
  49. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +0 -14
  50. data/doc_config/yard/templates/default/layout/html/fonts.erb +0 -1
  51. data/doc_config/yard/templates/default/layout/html/footer.erb +0 -6
  52. data/doc_config/yard/templates/default/layout/html/layout.erb +0 -23
  53. data/doc_config/yard/templates/default/layout/html/search.erb +0 -13
  54. data/doc_config/yard/templates/default/layout/html/setup.rb +0 -40
  55. data/doc_config/yard/templates/default/method_details/html/source.erb +0 -10
  56. data/doc_config/yard/templates/default/module/html/box_info.erb +0 -31
  57. data/gemfiles/4.2.gemfile +0 -39
  58. data/gemfiles/4.2.gemfile.lock +0 -246
  59. data/gemfiles/5.0.gemfile +0 -37
  60. data/gemfiles/5.0.gemfile.lock +0 -238
  61. data/gemfiles/5.1.gemfile +0 -38
  62. data/gemfiles/5.1.gemfile.lock +0 -254
  63. data/gemfiles/5.2.gemfile +0 -40
  64. data/gemfiles/5.2.gemfile.lock +0 -273
  65. data/script/install_gems_in_all_appraisals +0 -16
  66. data/script/run_all_tests +0 -16
  67. data/script/supported_ruby_versions +0 -7
  68. data/script/update_gem_in_all_appraisals +0 -17
  69. data/script/update_gems_in_all_appraisals +0 -16
  70. data/spec/acceptance/active_model_integration_spec.rb +0 -23
  71. data/spec/acceptance/independent_matchers_spec.rb +0 -125
  72. data/spec/acceptance/multiple_libraries_integration_spec.rb +0 -55
  73. data/spec/acceptance/rails_integration_spec.rb +0 -156
  74. data/spec/acceptance_spec_helper.rb +0 -23
  75. data/spec/doublespeak_spec_helper.rb +0 -2
  76. data/spec/report_warnings.rb +0 -7
  77. data/spec/spec_helper.rb +0 -20
  78. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +0 -133
  79. data/spec/support/acceptance/helpers.rb +0 -33
  80. data/spec/support/acceptance/helpers/active_model_helpers.rb +0 -11
  81. data/spec/support/acceptance/helpers/array_helpers.rb +0 -13
  82. data/spec/support/acceptance/helpers/base_helpers.rb +0 -19
  83. data/spec/support/acceptance/helpers/command_helpers.rb +0 -68
  84. data/spec/support/acceptance/helpers/file_helpers.rb +0 -19
  85. data/spec/support/acceptance/helpers/gem_helpers.rb +0 -31
  86. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -11
  87. data/spec/support/acceptance/helpers/n_unit_helpers.rb +0 -25
  88. data/spec/support/acceptance/helpers/pluralization_helpers.rb +0 -13
  89. data/spec/support/acceptance/helpers/rails_migration_helpers.rb +0 -21
  90. data/spec/support/acceptance/helpers/rails_version_helpers.rb +0 -11
  91. data/spec/support/acceptance/helpers/rspec_helpers.rb +0 -24
  92. data/spec/support/acceptance/helpers/ruby_version_helpers.rb +0 -9
  93. data/spec/support/acceptance/helpers/step_helpers.rb +0 -127
  94. data/spec/support/acceptance/matchers/have_output.rb +0 -31
  95. data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +0 -55
  96. data/spec/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +0 -103
  97. data/spec/support/tests/bundle.rb +0 -94
  98. data/spec/support/tests/command_runner.rb +0 -230
  99. data/spec/support/tests/current_bundle.rb +0 -55
  100. data/spec/support/tests/database.rb +0 -28
  101. data/spec/support/tests/database_adapters/postgresql.rb +0 -25
  102. data/spec/support/tests/database_adapters/sqlite3.rb +0 -26
  103. data/spec/support/tests/database_configuration.rb +0 -33
  104. data/spec/support/tests/database_configuration_registry.rb +0 -28
  105. data/spec/support/tests/filesystem.rb +0 -100
  106. data/spec/support/tests/version.rb +0 -45
  107. data/spec/support/unit/active_record/create_table.rb +0 -54
  108. data/spec/support/unit/attribute.rb +0 -45
  109. data/spec/support/unit/capture.rb +0 -46
  110. data/spec/support/unit/change_value.rb +0 -111
  111. data/spec/support/unit/create_model_arguments/basic.rb +0 -135
  112. data/spec/support/unit/create_model_arguments/has_many.rb +0 -15
  113. data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +0 -74
  114. data/spec/support/unit/helpers/action_pack_versions.rb +0 -22
  115. data/spec/support/unit/helpers/active_model_helpers.rb +0 -27
  116. data/spec/support/unit/helpers/active_model_versions.rb +0 -32
  117. data/spec/support/unit/helpers/active_record_versions.rb +0 -44
  118. data/spec/support/unit/helpers/active_resource_builder.rb +0 -27
  119. data/spec/support/unit/helpers/allow_value_matcher_helpers.rb +0 -15
  120. data/spec/support/unit/helpers/class_builder.rb +0 -90
  121. data/spec/support/unit/helpers/column_type_helpers.rb +0 -26
  122. data/spec/support/unit/helpers/confirmation_matcher_helpers.rb +0 -17
  123. data/spec/support/unit/helpers/controller_builder.rb +0 -63
  124. data/spec/support/unit/helpers/database_helpers.rb +0 -20
  125. data/spec/support/unit/helpers/i18n_faker.rb +0 -15
  126. data/spec/support/unit/helpers/mailer_builder.rb +0 -12
  127. data/spec/support/unit/helpers/message_helpers.rb +0 -19
  128. data/spec/support/unit/helpers/model_builder.rb +0 -114
  129. data/spec/support/unit/helpers/rails_versions.rb +0 -42
  130. data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +0 -44
  131. data/spec/support/unit/i18n.rb +0 -7
  132. data/spec/support/unit/load_environment.rb +0 -12
  133. data/spec/support/unit/matchers/deprecate.rb +0 -60
  134. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +0 -51
  135. data/spec/support/unit/matchers/fail_with_message_matcher.rb +0 -64
  136. data/spec/support/unit/matchers/print_warning_including.rb +0 -67
  137. data/spec/support/unit/model_creation_strategies/active_model.rb +0 -111
  138. data/spec/support/unit/model_creation_strategies/active_record.rb +0 -77
  139. data/spec/support/unit/model_creators.rb +0 -19
  140. data/spec/support/unit/model_creators/active_model.rb +0 -39
  141. data/spec/support/unit/model_creators/active_record.rb +0 -42
  142. data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +0 -95
  143. data/spec/support/unit/model_creators/active_record/has_many.rb +0 -67
  144. data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +0 -42
  145. data/spec/support/unit/model_creators/basic.rb +0 -102
  146. data/spec/support/unit/rails_application.rb +0 -151
  147. data/spec/support/unit/record_builder_with_i18n_validation_message.rb +0 -69
  148. data/spec/support/unit/record_validating_confirmation_builder.rb +0 -54
  149. data/spec/support/unit/record_with_different_error_attribute_builder.rb +0 -92
  150. data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +0 -79
  151. data/spec/support/unit/shared_examples/numerical_submatcher.rb +0 -17
  152. data/spec/support/unit/shared_examples/set_session_or_flash.rb +0 -360
  153. data/spec/support/unit/validation_matcher_scenario.rb +0 -60
  154. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +0 -82
  155. data/spec/unit/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +0 -28
  156. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +0 -629
  157. data/spec/unit/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +0 -42
  158. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +0 -76
  159. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +0 -62
  160. data/spec/unit/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +0 -90
  161. data/spec/unit/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +0 -31
  162. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +0 -330
  163. data/spec/unit/shoulda/matchers/action_controller/route_params_spec.rb +0 -30
  164. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +0 -67
  165. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +0 -17
  166. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +0 -562
  167. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -117
  168. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +0 -829
  169. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -86
  170. data/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +0 -20
  171. data/spec/unit/shoulda/matchers/active_model/helpers_spec.rb +0 -162
  172. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +0 -290
  173. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +0 -109
  174. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +0 -172
  175. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -264
  176. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -1049
  177. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -335
  178. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +0 -1865
  179. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -406
  180. data/spec/unit/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -107
  181. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +0 -1672
  182. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +0 -251
  183. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +0 -690
  184. data/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +0 -111
  185. data/spec/unit/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +0 -85
  186. data/spec/unit/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +0 -41
  187. data/spec/unit/shoulda/matchers/active_record/have_secure_token_matcher_spec.rb +0 -169
  188. data/spec/unit/shoulda/matchers/active_record/serialize_matcher_spec.rb +0 -86
  189. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +0 -1682
  190. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +0 -190
  191. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +0 -21
  192. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +0 -271
  193. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +0 -77
  194. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +0 -72
  195. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +0 -101
  196. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +0 -78
  197. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +0 -27
  198. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher/stubbed_target_spec.rb +0 -43
  199. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +0 -650
  200. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +0 -406
  201. data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +0 -252
  202. data/spec/unit_spec_helper.rb +0 -54
  203. data/spec/warnings_spy.rb +0 -64
  204. data/spec/warnings_spy/filesystem.rb +0 -45
  205. data/spec/warnings_spy/partitioner.rb +0 -36
  206. data/spec/warnings_spy/reader.rb +0 -53
  207. data/spec/warnings_spy/reporter.rb +0 -88
  208. data/tasks/documentation.rb +0 -199
  209. data/zeus.json +0 -11
@@ -1,117 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveModel::AllowMassAssignmentOfMatcher, type: :model do
4
- if action_pack_lt_5?
5
- context '#description' do
6
- context 'without a role' do
7
- it 'includes the attribute name' do
8
- expect(described_class.new(:attr).description).
9
- to eq 'allow mass assignment of attr'
10
- end
11
- end
12
-
13
- if active_model_3_1?
14
- context 'with a role' do
15
- it 'includes the attribute name and the role' do
16
- expect(described_class.new(:attr).as(:admin).description).
17
- to eq 'allow mass assignment of attr as admin'
18
- end
19
- end
20
- end
21
- end
22
-
23
- context 'an attribute that is blacklisted from mass-assignment' do
24
- it 'rejects being mass-assignable' do
25
- model = define_model(:example, blacklisted: :string) do
26
- attr_protected :blacklisted
27
- end.new
28
-
29
- expect(model).not_to allow_mass_assignment_of(:blacklisted)
30
- end
31
- end
32
-
33
- context 'an attribute that is not whitelisted for mass-assignment' do
34
- it 'rejects being mass-assignable' do
35
- model = define_model(:example, not_whitelisted: :string,
36
- whitelisted: :string) do
37
- attr_accessible :whitelisted
38
- end.new
39
-
40
- expect(model).not_to allow_mass_assignment_of(:not_whitelisted)
41
- end
42
- end
43
-
44
- context 'an attribute that is whitelisted for mass-assignment' do
45
- it 'accepts being mass-assignable' do
46
- expect(define_model(:example, whitelisted: :string) do
47
- attr_accessible :whitelisted
48
- end.new).to allow_mass_assignment_of(:whitelisted)
49
- end
50
- end
51
-
52
- context 'an attribute not included in the mass-assignment blacklist' do
53
- it 'accepts being mass-assignable' do
54
- model = define_model(:example, not_blacklisted: :string,
55
- blacklisted: :string) do
56
- attr_protected :blacklisted
57
- end.new
58
-
59
- expect(model).to allow_mass_assignment_of(:not_blacklisted)
60
- end
61
- end
62
-
63
- unless active_model_3_2? || active_model_4_0?
64
- context 'an attribute on a class with no protected attributes' do
65
- it 'accepts being mass-assignable' do
66
- expect(no_protected_attributes).to allow_mass_assignment_of(:attr)
67
- end
68
-
69
- it 'assigns a negative failure message' do
70
- matcher = allow_mass_assignment_of(:attr)
71
-
72
- expect(matcher.matches?(no_protected_attributes)).to eq true
73
-
74
- expect(matcher.failure_message_when_negated).not_to be_nil
75
- end
76
- end
77
-
78
- def no_protected_attributes
79
- define_model(:example, attr: :string).new
80
- end
81
- end
82
-
83
- context 'an attribute on a class with all protected attributes' do
84
- it 'rejects being mass-assignable' do
85
- expect(all_protected_attributes).not_to allow_mass_assignment_of(:attr)
86
- end
87
-
88
- def all_protected_attributes
89
- define_model(:example, attr: :string) do
90
- attr_accessible nil
91
- end.new
92
- end
93
- end
94
-
95
- if active_model_3_1?
96
- context 'an attribute included in the mass-assignment whitelist for admin role only' do
97
- it 'rejects being mass-assignable' do
98
- expect(mass_assignable_as_admin).not_to allow_mass_assignment_of(:attr)
99
- end
100
-
101
- it 'accepts being mass-assignable for admin' do
102
- expect(mass_assignable_as_admin).to allow_mass_assignment_of(:attr).as(:admin)
103
- end
104
-
105
- def mass_assignable_as_admin
106
- define_model(:example, attr: :string) do
107
- attr_accessible :attr, as: :admin
108
- end.new
109
- end
110
- end
111
- end
112
-
113
- def define_model(name, columns, &block)
114
- super(name, columns, whitelist_attributes: false, &block)
115
- end
116
- end
117
- end
@@ -1,829 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveModel, type: :model do
4
- describe '#allow_values' do
5
- it 'is aliased to #allow_value' do
6
- expect(method(:allow_values)).to eq(method(:allow_value))
7
- end
8
- end
9
- end
10
-
11
- describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
12
- context "#description" do
13
- it 'describes itself with two values' do
14
- matcher = allow_value('foo', 'bar').for(:baz)
15
-
16
- expect(matcher.description).to eq(
17
- 'allow :baz to be ‹"foo"› or ‹"bar"›'
18
- )
19
- end
20
-
21
- it 'describes itself with more than two values' do
22
- matcher = allow_value('foo', 'bar', 'qux').for(:baz)
23
-
24
- expect(matcher.description).to eq(
25
- 'allow :baz to be ‹"foo"›, ‹"bar"›, or ‹"qux"›'
26
- )
27
- end
28
-
29
- it 'describes itself with a single value' do
30
- matcher = allow_value('foo').for(:baz)
31
-
32
- expect(matcher.description).to eq 'allow :baz to be ‹"foo"›'
33
- end
34
-
35
- if active_model_3_2?
36
- it 'describes itself with a strict validation' do
37
- strict_matcher = allow_value('xyz').for(:attr).strict
38
-
39
- expect(strict_matcher.description).to eq(
40
- 'allow :attr to be ‹"xyz"›, raising a validation exception on failure'
41
- )
42
- end
43
- end
44
- end
45
-
46
- describe '#_after_setting_value' do
47
- it 'sets a block which is yielded after each value is set on the attribute' do
48
- attribute = :attr
49
- record = define_model(:example, attribute => :string).new
50
- matcher = described_class.new('a', 'b', 'c').for(attribute)
51
- call_count = 0
52
-
53
- matcher._after_setting_value { call_count += 1 }
54
- matcher.matches?(record)
55
-
56
- expect(call_count).to eq 3
57
- end
58
- end
59
-
60
- context 'an attribute with a validation' do
61
- context 'given one good value' do
62
- context 'when used in the positive' do
63
- it 'accepts' do
64
- expect(validating_format(with: /abc/)).
65
- to allow_value('abcde').for(:attr)
66
- end
67
- end
68
-
69
- context 'when used in the negative' do
70
- it 'rejects with an appropriate failure message' do
71
- assertion = lambda do
72
- expect(validating_format(with: /abc/)).
73
- not_to allow_value('abcde').for(:attr)
74
- end
75
-
76
- message = <<-MESSAGE
77
- After setting :attr to ‹"abcde"›, the matcher expected the Example to be
78
- invalid, but it was valid instead.
79
- MESSAGE
80
-
81
- expect(&assertion).to fail_with_message(message)
82
- end
83
- end
84
- end
85
-
86
- context 'given several good values' do
87
- context 'when used in the positive' do
88
- it 'accepts' do
89
- expect(validating_format(with: /abc/)).
90
- to allow_value('abcde', 'deabc').for(:attr)
91
- end
92
- end
93
-
94
- context 'when used in the negative' do
95
- it 'rejects with an appropriate failure message' do
96
- assertion = lambda do
97
- expect(validating_format(with: /abc/)).
98
- not_to allow_value('abcde', 'deabc').for(:attr)
99
- end
100
-
101
- message = <<-MESSAGE
102
- After setting :attr to ‹"abcde"›, the matcher expected the Example to be
103
- invalid, but it was valid instead.
104
- MESSAGE
105
-
106
- expect(&assertion).to fail_with_message(message)
107
- end
108
- end
109
- end
110
-
111
- context 'given one bad value' do
112
- context 'when used in the positive' do
113
- it 'rejects with an appropriate failure message' do
114
- assertion = lambda do
115
- expect(validating_format(with: /abc/)).
116
- to allow_value('xyz').for(:attr)
117
- end
118
-
119
- message = <<-MESSAGE
120
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
121
- valid, but it was invalid instead, producing these validation errors:
122
-
123
- * attr: ["is invalid"]
124
- MESSAGE
125
-
126
- expect(&assertion).to fail_with_message(message)
127
- end
128
- end
129
-
130
- context 'when used in the negative' do
131
- it 'accepts' do
132
- expect(validating_format(with: /abc/)).
133
- not_to allow_value('xyz').for(:attr)
134
- end
135
- end
136
- end
137
-
138
- context 'given several bad values' do
139
- context 'when used in the positive' do
140
- it 'rejects with an appropriate failure message' do
141
- assertion = lambda do
142
- expect(validating_format(with: /abc/)).
143
- to allow_value('xyz', 'zyx', nil, []).
144
- for(:attr).
145
- ignoring_interference_by_writer
146
- end
147
-
148
- message = <<-MESSAGE
149
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
150
- valid, but it was invalid instead, producing these validation errors:
151
-
152
- * attr: ["is invalid"]
153
- MESSAGE
154
-
155
- expect(&assertion).to fail_with_message(message)
156
- end
157
- end
158
-
159
- context 'when used in the negative' do
160
- it 'accepts' do
161
- expect(validating_format(with: /abc/)).
162
- not_to allow_value('xyz', 'zyx', nil, []).
163
- for(:attr).
164
- ignoring_interference_by_writer
165
- end
166
- end
167
- end
168
-
169
- context 'given good values along with bad values' do
170
- context 'when used in the positive' do
171
- it 'rejects with an appropriate failure message' do
172
- assertion = lambda do
173
- expect(validating_format(with: /abc/)).
174
- to allow_value('abc', 'xyz').
175
- for(:attr).
176
- ignoring_interference_by_writer
177
- end
178
-
179
- message = <<-MESSAGE
180
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
181
- valid, but it was invalid instead, producing these validation errors:
182
-
183
- * attr: ["is invalid"]
184
- MESSAGE
185
-
186
- expect(&assertion).to fail_with_message(message)
187
- end
188
- end
189
-
190
- context 'when used in the negative' do
191
- it 'rejects with an appropriate failure message' do
192
- assertion = lambda do
193
- expect(validating_format(with: /abc/)).
194
- not_to allow_value('abc', 'xyz').
195
- for(:attr).
196
- ignoring_interference_by_writer
197
- end
198
-
199
- message = <<-MESSAGE
200
- After setting :attr to ‹"abc"›, the matcher expected the Example to be
201
- invalid, but it was valid instead.
202
- MESSAGE
203
-
204
- expect(&assertion).to fail_with_message(message)
205
- end
206
- end
207
- end
208
-
209
- context 'given bad values along with good values' do
210
- context 'when used in the positive' do
211
- it 'rejects with an appropriate failure message' do
212
- assertion = lambda do
213
- expect(validating_format(with: /abc/)).
214
- to allow_value('xyz', 'abc').
215
- for(:attr).
216
- ignoring_interference_by_writer
217
- end
218
-
219
- message = <<-MESSAGE
220
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
221
- valid, but it was invalid instead, producing these validation errors:
222
-
223
- * attr: ["is invalid"]
224
- MESSAGE
225
-
226
- expect(&assertion).to fail_with_message(message)
227
- end
228
- end
229
-
230
- context 'when used in the negative' do
231
- it 'rejects with an appropriate failure message' do
232
- assertion = lambda do
233
- expect(validating_format(with: /abc/)).
234
- not_to allow_value('xyz', 'abc').
235
- for(:attr).
236
- ignoring_interference_by_writer
237
- end
238
-
239
- message = <<-MESSAGE
240
- After setting :attr to ‹"abc"›, the matcher expected the Example to be
241
- invalid, but it was valid instead.
242
- MESSAGE
243
-
244
- expect(&assertion).to fail_with_message(message)
245
- end
246
- end
247
- end
248
- end
249
-
250
- context 'an attribute with a validation and a custom message' do
251
- it 'allows a good value' do
252
- expect(validating_format(with: /abc/, message: 'bad value')).
253
- to allow_value('abcde').for(:attr).with_message(/bad/)
254
- end
255
-
256
- it 'rejects a bad value with an appropriate failure message' do
257
- message = <<-MESSAGE
258
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
259
- valid, but it was invalid instead, producing these validation errors:
260
-
261
- * attr: ["bad value"]
262
- MESSAGE
263
-
264
- assertion = lambda do
265
- expect(validating_format(with: /abc/, message: 'bad value')).
266
- to allow_value('xyz').for(:attr).with_message(/bad/)
267
- end
268
-
269
- expect(&assertion).to fail_with_message(message)
270
- end
271
-
272
- context 'when the custom messages do not match' do
273
- it 'rejects with an appropriate failure message' do
274
- message = <<-MESSAGE
275
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
276
- invalid and to produce a validation error matching ‹/different/› on
277
- :attr. The record was indeed invalid, but it produced these validation
278
- errors instead:
279
-
280
- * attr: ["bad value"]
281
- MESSAGE
282
-
283
- assertion = lambda do
284
- expect(validating_format(with: /abc/, message: 'bad value')).
285
- not_to allow_value('xyz').for(:attr).with_message(/different/)
286
- end
287
-
288
- expect(&assertion).to fail_with_message(message)
289
- end
290
- end
291
-
292
- context 'when interpolation values are provided along with a custom message' do
293
- context 'when the messages match' do
294
- it 'accepts' do
295
- options = {
296
- attribute_name: :attr,
297
- attribute_type: :string
298
- }
299
-
300
- record = record_with_custom_validation(options) do
301
- if self.attr == 'xyz'
302
- self.errors.add :attr, :greater_than, count: 2
303
- end
304
- end
305
-
306
- expect(record).
307
- not_to allow_value('xyz').
308
- for(:attr).
309
- with_message(:greater_than, values: { count: 2 })
310
- end
311
- end
312
-
313
- context 'when the messages do not match' do
314
- it 'rejects with an appropriate failure message' do
315
- options = {
316
- attribute_name: :attr,
317
- attribute_type: :string
318
- }
319
-
320
- record = record_with_custom_validation(options) do
321
- if self.attr == 'xyz'
322
- self.errors.add :attr, "some other error"
323
- end
324
- end
325
-
326
- assertion = lambda do
327
- expect(record).
328
- not_to allow_value('xyz').
329
- for(:attr).
330
- with_message(:greater_than, values: { count: 2 })
331
- end
332
-
333
- message = <<-MESSAGE
334
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
335
- invalid and to produce the validation error "must be greater than 2" on
336
- :attr. The record was indeed invalid, but it produced these validation
337
- errors instead:
338
-
339
- * attr: ["some other error"]
340
- MESSAGE
341
-
342
- expect(&assertion).to fail_with_message(message)
343
- end
344
- end
345
- end
346
- end
347
-
348
- context 'when the attribute being validated is different than the attribute that receives the validation error' do
349
- include UnitTests::AllowValueMatcherHelpers
350
-
351
- context 'when the validation error message was provided directly' do
352
- context 'given a valid value' do
353
- it 'accepts' do
354
- builder = builder_for_record_with_different_error_attribute
355
- expect(builder.record).
356
- to allow_value(builder.valid_value).
357
- for(builder.attribute_to_validate).
358
- with_message(
359
- builder.message,
360
- against: builder.attribute_that_receives_error
361
- )
362
- end
363
- end
364
-
365
- context 'given an invalid value' do
366
- it 'rejects' do
367
- builder = builder_for_record_with_different_error_attribute
368
- invalid_value = "#{builder.valid_value} (invalid)"
369
-
370
- expect(builder.record).
371
- not_to allow_value(invalid_value).
372
- for(builder.attribute_to_validate).
373
- with_message(
374
- builder.message,
375
- against: builder.attribute_that_receives_error
376
- )
377
- end
378
-
379
- context 'if the messages do not match' do
380
- it 'technically accepts' do
381
- builder = builder_for_record_with_different_error_attribute(
382
- message: "a different error"
383
- )
384
- invalid_value = "#{builder.valid_value} (invalid)"
385
-
386
- assertion = lambda do
387
- expect(builder.record).
388
- not_to allow_value(invalid_value).
389
- for(builder.attribute_to_validate).
390
- with_message(
391
- "some error",
392
- against: builder.attribute_that_receives_error
393
- )
394
- end
395
-
396
- message = <<-MESSAGE
397
- After setting :#{builder.attribute_to_validate} to ‹"#{invalid_value}"›, the
398
- matcher expected the #{builder.model.name} to be invalid and to produce the validation
399
- error "some error" on :#{builder.attribute_that_receives_error}. The record was
400
- indeed invalid, but it produced these validation errors instead:
401
-
402
- * #{builder.attribute_that_receives_error}: ["a different error"]
403
- MESSAGE
404
-
405
- expect(&assertion).to fail_with_message(message)
406
- end
407
- end
408
- end
409
- end
410
-
411
- context 'when the validation error message was provided via i18n' do
412
- it 'passes given a valid value' do
413
- builder = builder_for_record_with_different_error_attribute_using_i18n
414
- expect(builder.record).
415
- to allow_value(builder.valid_value).
416
- for(builder.attribute_to_validate).
417
- with_message(
418
- builder.validation_message_key,
419
- against: builder.attribute_that_receives_error
420
- )
421
- end
422
-
423
- it 'fails given an invalid value' do
424
- builder = builder_for_record_with_different_error_attribute_using_i18n
425
- invalid_value = "#{builder.valid_value} (invalid)"
426
- expect(builder.record).
427
- not_to allow_value(invalid_value).
428
- for(builder.attribute_to_validate).
429
- with_message(
430
- builder.validation_message_key,
431
- against: builder.attribute_that_receives_error
432
- )
433
- end
434
- end
435
- end
436
-
437
- context "an attribute with a context-dependent validation" do
438
- context "without the validation context" do
439
- it "allows a bad value" do
440
- expect(validating_format(with: /abc/, on: :customisable)).to allow_value("xyz").for(:attr)
441
- end
442
- end
443
-
444
- context "with the validation context" do
445
- it "allows a good value" do
446
- expect(validating_format(with: /abc/, on: :customisable)).to allow_value("abcde").for(:attr).on(:customisable)
447
- end
448
-
449
- it "rejects a bad value" do
450
- expect(validating_format(with: /abc/, on: :customisable)).not_to allow_value("xyz").for(:attr).on(:customisable)
451
- end
452
- end
453
- end
454
-
455
- context 'an attribute with several validations' do
456
- let(:model) do
457
- define_model :example, attr: :string do
458
- validates_presence_of :attr
459
- validates_length_of :attr, within: 1..5
460
- validates_numericality_of :attr, greater_than_or_equal_to: 1,
461
- less_than_or_equal_to: 50000
462
- end.new
463
- end
464
-
465
- bad_values = [nil, '', 'abc', '0', '50001', '123456', []]
466
-
467
- it 'matches given a good value' do
468
- expect(model).to allow_value('12345').for(:attr)
469
- end
470
-
471
- it 'does not match given a bad value' do
472
- bad_values.each do |bad_value|
473
- expect(model).
474
- not_to allow_value(bad_value).
475
- for(:attr).
476
- ignoring_interference_by_writer
477
- end
478
- end
479
-
480
- it 'does not match given multiple bad values' do
481
- expect(model).
482
- not_to allow_value(*bad_values).
483
- for(:attr).
484
- ignoring_interference_by_writer
485
- end
486
-
487
- it "does not match given good values along with bad values" do
488
- message = <<-MESSAGE.strip_heredoc
489
- After setting :attr to ‹"12345"›, the matcher expected the Example to be
490
- invalid, but it was valid instead.
491
- MESSAGE
492
-
493
- assertion = lambda do
494
- expect(model).not_to allow_value('12345', *bad_values).for(:attr)
495
- end
496
-
497
- expect(&assertion).to fail_with_message(message)
498
- end
499
-
500
- it "does not match given bad values along with good values" do
501
- message = <<-MESSAGE.strip_heredoc
502
- After setting :attr to ‹"12345"›, the matcher expected the Example to be
503
- invalid, but it was valid instead.
504
- MESSAGE
505
-
506
- assertion = lambda do
507
- expect(model).not_to allow_value(*bad_values, '12345').for(:attr)
508
- end
509
-
510
- expect(&assertion).to fail_with_message(message)
511
- end
512
- end
513
-
514
- context 'with a single value' do
515
- it 'allows you to call description before calling matches?' do
516
- model = define_model(:example, attr: :string).new
517
- matcher = described_class.new('foo').for(:attr)
518
- matcher.description
519
-
520
- expect { matcher.matches?(model) }.not_to raise_error
521
- end
522
- end
523
-
524
- context 'with no values' do
525
- it 'raises an error' do
526
- expect { allow_value.for(:baz) }.
527
- to raise_error(ArgumentError, /at least one argument/)
528
- end
529
- end
530
-
531
- if active_model_3_2?
532
- context 'an attribute with a strict format validation' do
533
- context 'when qualified with strict' do
534
- it 'rejects a bad value, providing the correct failure message' do
535
- message = <<-MESSAGE.strip_heredoc
536
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
537
- valid, but it was invalid instead, raising a validation exception with
538
- the message "Attr is invalid".
539
- MESSAGE
540
-
541
- assertion = lambda do
542
- expect(validating_format(with: /abc/, strict: true)).
543
- to allow_value('xyz').for(:attr).strict
544
- end
545
-
546
- expect(&assertion).to fail_with_message(message)
547
- end
548
-
549
- context 'qualified with a custom message' do
550
- it 'rejects a bad value when the failure messages do not match' do
551
- message = <<-MESSAGE.strip_heredoc
552
- After setting :attr to ‹"xyz"›, the matcher expected the Example to be
553
- invalid and to raise a validation exception with message matching
554
- ‹/abc/›. The record was indeed invalid, but the exception message was
555
- "Attr is invalid" instead.
556
- MESSAGE
557
-
558
- assertion = lambda do
559
- expect(validating_format(with: /abc/, strict: true)).
560
- not_to allow_value('xyz').for(:attr).with_message(/abc/).strict
561
- end
562
-
563
- expect(&assertion).to fail_with_message(message)
564
- end
565
- end
566
- end
567
- end
568
- end
569
-
570
- context 'when the attribute interferes with attempts to be set' do
571
- context 'when the attribute cannot be changed from nil to non-nil' do
572
- context 'and the record remains valid' do
573
- it 'accepts (and does not raise an AttributeChangedValueError)' do
574
- model = define_active_model_class 'Example', accessors: [:name] do
575
- def name=(_value)
576
- nil
577
- end
578
- end
579
-
580
- expect(model.new).to allow_value('anything').for(:name)
581
- end
582
- end
583
-
584
- context 'and the record becomes invalid' do
585
- it 'rejects with an appropriate failure message' do
586
- model = define_active_model_class 'Example', accessors: [:name] do
587
- validates_presence_of :name
588
-
589
- def name=(_value)
590
- nil
591
- end
592
- end
593
-
594
- assertion = lambda do
595
- expect(model.new).to allow_value('anything').for(:name)
596
- end
597
-
598
- message = <<-MESSAGE.strip
599
- After setting :name to ‹"anything"› -- which was read back as ‹nil› --
600
- the matcher expected the Example to be valid, but it was invalid
601
- instead, producing these validation errors:
602
-
603
- * name: ["can't be blank"]
604
-
605
- As indicated in the message above, :name seems to be changing certain
606
- values as they are set, and this could have something to do with why
607
- this test is failing. If you've overridden the writer method for this
608
- attribute, then you may need to change it to make this test pass, or do
609
- something else entirely.
610
- MESSAGE
611
-
612
- expect(&assertion).to fail_with_message(message)
613
- end
614
- end
615
- end
616
-
617
- context 'when the attribute cannot be changed from non-nil to nil' do
618
- context 'and the record remains valid' do
619
- it 'accepts (and does not raise an AttributeChangedValueError)' do
620
- model = define_active_model_class 'Example', accessors: [:name] do
621
- def name=(value)
622
- if value
623
- super(value)
624
- end
625
- end
626
- end
627
-
628
- record = model.new(name: 'some name')
629
-
630
- expect(record).to allow_value(nil).for(:name)
631
- end
632
- end
633
-
634
- context 'and the record becomes invalid' do
635
- it 'rejects with an appropriate failure message' do
636
- model = define_active_model_class 'Example', accessors: [:name] do
637
- validates_absence_of :name
638
-
639
- def name=(value)
640
- if value
641
- super(value)
642
- end
643
- end
644
- end
645
-
646
- record = model.new(name: 'some name')
647
-
648
- assertion = lambda do
649
- expect(record).to allow_value(nil).for(:name)
650
- end
651
-
652
- message = <<-MESSAGE.strip
653
- After setting :name to ‹nil› -- which was read back as ‹"some name"› --
654
- the matcher expected the Example to be valid, but it was invalid
655
- instead, producing these validation errors:
656
-
657
- * name: ["must be blank"]
658
-
659
- As indicated in the message above, :name seems to be changing certain
660
- values as they are set, and this could have something to do with why
661
- this test is failing. If you've overridden the writer method for this
662
- attribute, then you may need to change it to make this test pass, or do
663
- something else entirely.
664
- MESSAGE
665
-
666
- expect(&assertion).to fail_with_message(message)
667
- end
668
- end
669
- end
670
-
671
- context 'when the attribute cannot be changed from a non-nil value to another non-nil value' do
672
- context 'and the record remains valid' do
673
- it 'accepts (and does not raise an AttributeChangedValueError)' do
674
- model = define_active_model_class 'Example', accessors: [:name] do
675
- def name=(_value)
676
- super('constant name')
677
- end
678
- end
679
-
680
- record = model.new(name: 'some name')
681
-
682
- expect(record).to allow_value('another name').for(:name)
683
- end
684
- end
685
-
686
- context 'and the record becomes invalid' do
687
- it 'rejects with an appropriate failure message' do
688
- model = define_active_model_class 'Example', accessors: [:name] do
689
- validates_format_of :name, with: /another name/
690
-
691
- def name=(value)
692
- super('constant name')
693
- end
694
- end
695
-
696
- record = model.new(name: 'some name')
697
-
698
- assertion = lambda do
699
- expect(record).to allow_value('another name').for(:name)
700
- end
701
-
702
- message = <<-MESSAGE.strip
703
- After setting :name to ‹"another name"› -- which was read back as
704
- ‹"constant name"› -- the matcher expected the Example to be valid, but
705
- it was invalid instead, producing these validation errors:
706
-
707
- * name: ["is invalid"]
708
-
709
- As indicated in the message above, :name seems to be changing certain
710
- values as they are set, and this could have something to do with why
711
- this test is failing. If you've overridden the writer method for this
712
- attribute, then you may need to change it to make this test pass, or do
713
- something else entirely.
714
- MESSAGE
715
-
716
- expect(&assertion).to fail_with_message(message)
717
- end
718
- end
719
- end
720
- end
721
-
722
- context 'when the attribute does not exist on the model' do
723
- context 'when the assertion is positive' do
724
- it 'raises an AttributeDoesNotExistError' do
725
- model = define_class('Example')
726
-
727
- assertion = lambda do
728
- expect(model.new).to allow_value('foo').for(:nonexistent)
729
- end
730
-
731
- message = <<-MESSAGE.rstrip
732
- The matcher attempted to set :nonexistent on the Example to "foo", but
733
- that attribute does not exist.
734
- MESSAGE
735
-
736
- expect(&assertion).to raise_error(
737
- described_class::AttributeDoesNotExistError,
738
- message
739
- )
740
- end
741
- end
742
-
743
- context 'when the assertion is negative' do
744
- it 'raises an AttributeDoesNotExistError' do
745
- model = define_class('Example')
746
-
747
- assertion = lambda do
748
- expect(model.new).not_to allow_value('foo').for(:nonexistent)
749
- end
750
-
751
- message = <<-MESSAGE.rstrip
752
- The matcher attempted to set :nonexistent on the Example to "foo", but
753
- that attribute does not exist.
754
- MESSAGE
755
-
756
- expect(&assertion).to raise_error(
757
- described_class::AttributeDoesNotExistError,
758
- message
759
- )
760
- end
761
- end
762
- end
763
-
764
- context 'given attributes to preset on the record before validation' do
765
- context 'when the assertion is positive' do
766
- context 'if any attributes do not exist on the model' do
767
- it 'raises an AttributeDoesNotExistError' do
768
- model = define_active_model_class('Example', accessors: [:existent])
769
-
770
- allow_value_matcher = allow_value('foo').for(:existent).tap do |matcher|
771
- matcher.values_to_preset = { nonexistent: 'some value' }
772
- end
773
-
774
- assertion = lambda do
775
- expect(model.new).to(allow_value_matcher)
776
- end
777
-
778
- message = <<-MESSAGE.rstrip
779
- The matcher attempted to set :nonexistent on the Example to "some
780
- value", but that attribute does not exist.
781
- MESSAGE
782
-
783
- expect(&assertion).to raise_error(
784
- described_class::AttributeDoesNotExistError,
785
- message
786
- )
787
- end
788
- end
789
- end
790
-
791
- context 'when the assertion is negative' do
792
- context 'if any attributes do not exist on the model' do
793
- it 'raises an AttributeDoesNotExistError' do
794
- model = define_active_model_class('Example', accessors: [:existent])
795
-
796
- allow_value_matcher = allow_value('foo').for(:existent).tap do |matcher|
797
- matcher.values_to_preset = { nonexistent: 'some value' }
798
- end
799
-
800
- assertion = lambda do
801
- expect(model.new).not_to(allow_value_matcher)
802
- end
803
-
804
- message = <<-MESSAGE.rstrip
805
- The matcher attempted to set :nonexistent on the Example to "some
806
- value", but that attribute does not exist.
807
- MESSAGE
808
-
809
- expect(&assertion).to raise_error(
810
- described_class::AttributeDoesNotExistError,
811
- message
812
- )
813
- end
814
- end
815
- end
816
- end
817
-
818
- context 'given an ActiveRecord model' do
819
- context 'where the attribute under test is an enum and the given value is a value in that enum' do
820
- it 'accepts' do
821
- model = define_model('Shipment', status: :integer) do
822
- enum status: { pending: 1, shipped: 2, delivered: 3 }
823
- end
824
-
825
- expect(model.new).to allow_value(1).for(:status)
826
- end
827
- end
828
- end
829
- end