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,75 +1,93 @@
1
- require 'spec_helper'
1
+ require 'unit_spec_helper'
2
2
 
3
- describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
3
+ describe Shoulda::Matchers::ActiveModel, type: :model do
4
+ describe '#ensure_length_of' do
5
+ it 'is aliased to #validate_length_of' do
6
+ allow(matchers).to receive(:validate_length_of)
7
+
8
+ silence_warnings do
9
+ matchers.ensure_length_of(:attr)
10
+ expect(matchers).to have_received(:validate_length_of).with(:attr)
11
+ end
12
+ end
13
+ end
14
+
15
+ def matchers
16
+ @_matchers ||= Object.new.extend(described_class)
17
+ end
18
+ end
19
+
20
+ describe Shoulda::Matchers::ActiveModel::ValidateLengthOfMatcher, type: :model do
4
21
  context 'an attribute with a non-zero minimum length validation' do
5
22
  it 'accepts ensuring the correct minimum length' do
6
23
  expect(validating_length(minimum: 4)).
7
- to ensure_length_of(:attr).is_at_least(4)
24
+ to validate_length_of(:attr).is_at_least(4)
8
25
  end
9
26
 
10
27
  it 'rejects ensuring a lower minimum length with any message' do
11
28
  expect(validating_length(minimum: 4)).
12
- not_to ensure_length_of(:attr).is_at_least(3).with_short_message(/.*/)
29
+ not_to validate_length_of(:attr).is_at_least(3).with_short_message(/.*/)
13
30
  end
14
31
 
15
32
  it 'rejects ensuring a higher minimum length with any message' do
16
33
  expect(validating_length(minimum: 4)).
17
- not_to ensure_length_of(:attr).is_at_least(5).with_short_message(/.*/)
34
+ not_to validate_length_of(:attr).is_at_least(5).with_short_message(/.*/)
18
35
  end
19
36
 
20
37
  it 'does not override the default message with a blank' do
21
38
  expect(validating_length(minimum: 4)).
22
- to ensure_length_of(:attr).is_at_least(4).with_short_message(nil)
39
+ to validate_length_of(:attr).is_at_least(4).with_short_message(nil)
23
40
  end
24
41
  end
25
42
 
26
43
  context 'an attribute with a minimum length validation of 0' do
27
44
  it 'accepts ensuring the correct minimum length' do
28
45
  expect(validating_length(minimum: 0)).
29
- to ensure_length_of(:attr).is_at_least(0)
46
+ to validate_length_of(:attr).is_at_least(0)
30
47
  end
31
48
  end
32
49
 
33
50
  context 'an attribute with a maximum length' do
34
51
  it 'accepts ensuring the correct maximum length' do
35
52
  expect(validating_length(maximum: 4)).
36
- to ensure_length_of(:attr).is_at_most(4)
53
+ to validate_length_of(:attr).is_at_most(4)
37
54
  end
38
55
 
39
56
  it 'rejects ensuring a lower maximum length with any message' do
40
57
  expect(validating_length(maximum: 4)).
41
- not_to ensure_length_of(:attr).is_at_most(3).with_long_message(/.*/)
58
+ not_to validate_length_of(:attr).is_at_most(3).with_long_message(/.*/)
42
59
  end
43
60
 
44
61
  it 'rejects ensuring a higher maximum length with any message' do
45
62
  expect(validating_length(maximum: 4)).
46
- not_to ensure_length_of(:attr).is_at_most(5).with_long_message(/.*/)
63
+ not_to validate_length_of(:attr).is_at_most(5).with_long_message(/.*/)
47
64
  end
48
65
 
49
66
  it 'does not override the default message with a blank' do
50
67
  expect(validating_length(maximum: 4)).
51
- to ensure_length_of(:attr).is_at_most(4).with_long_message(nil)
68
+ to validate_length_of(:attr).is_at_most(4).with_long_message(nil)
52
69
  end
53
70
  end
54
71
 
55
72
  context 'an attribute with a required exact length' do
56
73
  it 'accepts ensuring the correct length' do
57
- expect(validating_length(is: 4)).to ensure_length_of(:attr).is_equal_to(4)
74
+ expect(validating_length(is: 4)).
75
+ to validate_length_of(:attr).is_equal_to(4)
58
76
  end
59
77
 
60
78
  it 'rejects ensuring a lower maximum length with any message' do
61
79
  expect(validating_length(is: 4)).
62
- not_to ensure_length_of(:attr).is_equal_to(3).with_message(/.*/)
80
+ not_to validate_length_of(:attr).is_equal_to(3).with_message(/.*/)
63
81
  end
64
82
 
65
83
  it 'rejects ensuring a higher maximum length with any message' do
66
84
  expect(validating_length(is: 4)).
67
- not_to ensure_length_of(:attr).is_equal_to(5).with_message(/.*/)
85
+ not_to validate_length_of(:attr).is_equal_to(5).with_message(/.*/)
68
86
  end
69
87
 
70
88
  it 'does not override the default message with a blank' do
71
89
  expect(validating_length(is: 4)).
72
- to ensure_length_of(:attr).is_equal_to(4).with_message(nil)
90
+ to validate_length_of(:attr).is_equal_to(4).with_message(nil)
73
91
  end
74
92
  end
75
93
 
@@ -80,35 +98,35 @@ describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
80
98
  validates_numericality_of :attr
81
99
  end.new
82
100
 
83
- expect(model).to ensure_length_of(:attr).is_equal_to(4)
101
+ expect(model).to validate_length_of(:attr).is_equal_to(4)
84
102
  end
85
103
  end
86
104
 
87
105
  context 'an attribute with a custom minimum length validation' do
88
106
  it 'accepts ensuring the correct minimum length' do
89
107
  expect(validating_length(minimum: 4, too_short: 'foobar')).
90
- to ensure_length_of(:attr).is_at_least(4).with_short_message(/foo/)
108
+ to validate_length_of(:attr).is_at_least(4).with_short_message(/foo/)
91
109
  end
92
110
  end
93
111
 
94
112
  context 'an attribute with a custom maximum length validation' do
95
113
  it 'accepts ensuring the correct minimum length' do
96
114
  expect(validating_length(maximum: 4, too_long: 'foobar')).
97
- to ensure_length_of(:attr).is_at_most(4).with_long_message(/foo/)
115
+ to validate_length_of(:attr).is_at_most(4).with_long_message(/foo/)
98
116
  end
99
117
  end
100
118
 
101
119
  context 'an attribute with a custom equal validation' do
102
120
  it 'accepts ensuring the correct exact length' do
103
121
  expect(validating_length(is: 4, message: 'foobar')).
104
- to ensure_length_of(:attr).is_equal_to(4).with_message(/foo/)
122
+ to validate_length_of(:attr).is_equal_to(4).with_message(/foo/)
105
123
  end
106
124
  end
107
125
 
108
126
  context 'an attribute without a length validation' do
109
127
  it 'rejects ensuring a minimum length' do
110
128
  expect(define_model(:example, attr: :string).new).
111
- not_to ensure_length_of(:attr).is_at_least(1)
129
+ not_to validate_length_of(:attr).is_at_least(1)
112
130
  end
113
131
  end
114
132
 
@@ -124,7 +142,8 @@ describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
124
142
 
125
143
  it "does not raise an exception" do
126
144
  expect {
127
- expect(validating_length(maximum: 4)).to ensure_length_of(:attr).is_at_most(4)
145
+ expect(validating_length(maximum: 4)).
146
+ to validate_length_of(:attr).is_at_most(4)
128
147
  }.to_not raise_exception
129
148
  end
130
149
  end
@@ -138,7 +157,7 @@ describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
138
157
 
139
158
  it "does not raise an exception" do
140
159
  expect {
141
- expect(validating_length(minimum: 4)).to ensure_length_of(:attr).is_at_least(4)
160
+ expect(validating_length(minimum: 4)).to validate_length_of(:attr).is_at_least(4)
142
161
  }.to_not raise_exception
143
162
  end
144
163
  end
@@ -152,7 +171,8 @@ describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
152
171
 
153
172
  it "does not raise an exception" do
154
173
  expect {
155
- expect(validating_length(is: 4)).to ensure_length_of(:attr).is_equal_to(4)
174
+ expect(validating_length(is: 4)).
175
+ to validate_length_of(:attr).is_equal_to(4)
156
176
  }.to_not raise_exception
157
177
  end
158
178
  end
@@ -1,7 +1,6 @@
1
- require 'spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do
1
+ require 'unit_spec_helper'
4
2
 
3
+ describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher, type: :model do
5
4
  context 'with a model with a numericality validation' do
6
5
  it 'accepts' do
7
6
  expect(validating_numericality).to matcher
@@ -278,7 +277,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do
278
277
  def set_attr!; self.attr = 5 end
279
278
  end.new
280
279
 
281
- subject.stubs(:set_attr!)
280
+ allow(subject).to receive(:set_attr!)
282
281
  expect(subject).to matcher.odd
283
282
  end
284
283
  end
@@ -1,6 +1,6 @@
1
- require 'spec_helper'
1
+ require 'unit_spec_helper'
2
2
 
3
- describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
3
+ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher, type: :model do
4
4
  context 'a model with a presence validation' do
5
5
  it 'accepts' do
6
6
  expect(validating_presence).to matcher
@@ -33,7 +33,7 @@ describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
33
33
  end
34
34
 
35
35
  it 'provides the correct failure message' do
36
- message = %{Expected errors to include "can't be blank" when attr is set to nil, got no errors}
36
+ message = %{Expected errors to include "can't be blank" when attr is set to nil,\ngot no errors}
37
37
 
38
38
  expect { expect(active_model).to matcher }.to fail_with_message(message)
39
39
  end
@@ -1,6 +1,6 @@
1
- require 'spec_helper'
1
+ require 'unit_spec_helper'
2
2
 
3
- describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
3
+ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :model do
4
4
  context 'a model without a a uniqueness validation' do
5
5
  it 'rejects' do
6
6
  model = define_model(:example, attr: :string) { attr_accessible :attr } .new
@@ -418,6 +418,131 @@ describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
418
418
  end
419
419
  end
420
420
 
421
+ context 'when the validation allows blank' do
422
+ context 'when there is an existing record with a blank value' do
423
+ it 'accepts' do
424
+ model = model_allowing_blank
425
+ model.create!(attribute_name => '')
426
+ expect(model.new).to matcher.allow_blank
427
+ end
428
+ end
429
+
430
+ context 'when there is not an an existing record with a blank value' do
431
+ it 'still accepts' do
432
+ expect(record_allowing_blank).to matcher.allow_blank
433
+ end
434
+
435
+ it 'automatically creates a record' do
436
+ model = model_allowing_blank
437
+ matcher.allow_blank.matches?(model.new)
438
+
439
+ record_created = model.all.any? do |instance|
440
+ instance.__send__(attribute_name).blank?
441
+ end
442
+
443
+ expect(record_created).to be true
444
+ end
445
+ end
446
+
447
+ def attribute_name
448
+ :attr
449
+ end
450
+
451
+ def model_allowing_blank
452
+ _attribute_name = attribute_name
453
+
454
+ define_model(:example, attribute_name => :string) do
455
+ attr_accessible _attribute_name
456
+ validates_uniqueness_of _attribute_name, allow_blank: true
457
+ end
458
+ end
459
+
460
+ def record_allowing_blank
461
+ model_allowing_blank.new
462
+ end
463
+ end
464
+
465
+ context 'when the validation does not allow blank' do
466
+ context 'when there is an existing entry with a blank value' do
467
+ it 'rejects' do
468
+ model = model_disallowing_blank
469
+ model.create!(attribute_name => '')
470
+ expect(model.new).not_to matcher.allow_blank
471
+ end
472
+ end
473
+
474
+ it 'should not allow_blank' do
475
+ expect(record_disallowing_blank).not_to matcher.allow_blank
476
+ end
477
+
478
+ def attribute_name
479
+ :attr
480
+ end
481
+
482
+ def model_disallowing_blank
483
+ _attribute_name = attribute_name
484
+
485
+ define_model(:example, attribute_name => :string) do
486
+ attr_accessible _attribute_name
487
+ validates_uniqueness_of _attribute_name, allow_blank: false
488
+ end
489
+ end
490
+
491
+ def record_disallowing_blank
492
+ model_disallowing_blank.new
493
+ end
494
+ end
495
+
496
+ context "when testing that a polymorphic *_type column is one of the validation scopes" do
497
+ it "sets that column to a meaningful value that works with other validations on the same column" do
498
+ user_model = define_model :user
499
+ favorite_columns = {
500
+ favoriteable_id: { type: :integer, options: { null: false } },
501
+ favoriteable_type: { type: :string, options: { null: false } }
502
+ }
503
+ favorite_model = define_model :favorite, favorite_columns do
504
+ attr_accessible :favoriteable
505
+ belongs_to :favoriteable, polymorphic: true
506
+ validates :favoriteable, presence: true
507
+ validates :favoriteable_id, uniqueness: { scope: :favoriteable_type }
508
+ end
509
+
510
+ user = user_model.create!
511
+ favorite_model.create!(favoriteable: user)
512
+ new_favorite = favorite_model.new
513
+
514
+ expect(new_favorite).
515
+ to validate_uniqueness_of(:favoriteable_id).
516
+ scoped_to(:favoriteable_type)
517
+ end
518
+
519
+ context "if the model the *_type column refers to is namespaced, and shares the last part of its name with an existing model" do
520
+ it "still works" do
521
+ define_class 'User'
522
+ define_module 'Models'
523
+ user_model = define_model 'Models::User'
524
+ favorite_columns = {
525
+ favoriteable_id: { type: :integer, options: { null: false } },
526
+ favoriteable_type: { type: :string, options: { null: false } }
527
+ }
528
+ favorite_model = define_model 'Models::Favorite', favorite_columns do
529
+ attr_accessible :favoriteable
530
+ belongs_to :favoriteable, polymorphic: true
531
+ validates :favoriteable, presence: true
532
+ validates :favoriteable_id, uniqueness: { scope: :favoriteable_type }
533
+ end
534
+
535
+ user = user_model.create!
536
+ favorite_model.create!(favoriteable: user)
537
+ new_favorite = favorite_model.new
538
+
539
+ expect(new_favorite).
540
+ to validate_uniqueness_of(:favoriteable_id).
541
+ scoped_to(:favoriteable_type)
542
+ end
543
+ end
544
+ end
545
+
421
546
  def case_sensitive_validation_with_existing_value(attr_type)
422
547
  model = define_model(:example, attr: attr_type) do
423
548
  attr_accessible :attr
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require 'unit_spec_helper'
2
2
 
3
3
  describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
4
4
  context '#allow_description' do
@@ -67,8 +67,9 @@ describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
67
67
 
68
68
  description = finder.messages_description
69
69
 
70
- expected_messages = ['is invalid (attribute: "attr", value: "xyz")']
71
- expect(description).to eq "errors: #{expected_messages}"
70
+ expect(description).to eq(
71
+ %{ errors:\n* "is invalid" (attribute: attr, value: "xyz")}
72
+ )
72
73
  end
73
74
 
74
75
  it 'describes errors when there are none' do
@@ -76,7 +77,7 @@ describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
76
77
 
77
78
  description = finder.messages_description
78
79
 
79
- expect(description).to eq 'no errors'
80
+ expect(description).to eq ' no errors'
80
81
  end
81
82
 
82
83
  it 'should not fetch attribute values for errors that were copied from an autosaved belongs_to association' do
@@ -87,8 +88,9 @@ describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
87
88
  end.new
88
89
  finder = Shoulda::Matchers::ActiveModel::ValidationMessageFinder.new(instance, :attribute)
89
90
 
90
- expected_messages = ['is invalid (attribute: "association.association_attribute")']
91
- expect(finder.messages_description).to eq "errors: #{expected_messages}"
91
+ expect(finder.messages_description).to eq(
92
+ %{ errors:\n* "is invalid" (attribute: association.association_attribute)}
93
+ )
92
94
  end
93
95
 
94
96
  end
@@ -1,6 +1,6 @@
1
- require 'spec_helper'
1
+ require 'unit_spec_helper'
2
2
 
3
- describe Shoulda::Matchers::ActiveRecord::AcceptNestedAttributesForMatcher do
3
+ describe Shoulda::Matchers::ActiveRecord::AcceptNestedAttributesForMatcher, type: :model do
4
4
  it 'accepts an existing declaration' do
5
5
  expect(accepting_children).to accept_nested_attributes_for(:children)
6
6
  end
@@ -1,6 +1,6 @@
1
- require 'spec_helper'
1
+ require 'unit_spec_helper'
2
2
 
3
- describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
3
+ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
4
4
  context 'belong_to' do
5
5
  it 'accepts a good association with the default foreign key' do
6
6
  expect(belonging_to_parent).to belong_to(:parent)
@@ -29,6 +29,22 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
29
29
  expect(Child.new).to belong_to(:parent)
30
30
  end
31
31
 
32
+ it 'accepts an association using an existing custom primary key' do
33
+ define_model :parent
34
+ define_model :child, parent_id: :integer, custom_primary_key: :integer do
35
+ belongs_to :parent, primary_key: :custom_primary_key
36
+ end
37
+ expect(Child.new).to belong_to(:parent).with_primary_key(:custom_primary_key)
38
+ end
39
+
40
+ it 'rejects an association with a bad :primary_key option' do
41
+ matcher = belong_to(:parent).with_primary_key(:custom_primary_key)
42
+
43
+ expect(belonging_to_parent).not_to matcher
44
+
45
+ expect(matcher.failure_message).to match(/Child does not have a custom_primary_key primary key/)
46
+ end
47
+
32
48
  it 'accepts a polymorphic association' do
33
49
  define_model :child, parent_type: :string, parent_id: :integer do
34
50
  belongs_to :parent, polymorphic: true
@@ -130,6 +146,31 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
130
146
  }.to fail_with_message(message)
131
147
  end
132
148
 
149
+ it 'accepts an association with a namespaced class name' do
150
+ define_module 'Models'
151
+ define_model 'Models::Organization'
152
+ user_model = define_model 'Models::User', organization_id: :integer do
153
+ belongs_to :organization, class_name: 'Organization'
154
+ end
155
+
156
+ expect(user_model.new).
157
+ to belong_to(:organization).
158
+ class_name('Organization')
159
+ end
160
+
161
+ it 'resolves class_name within the context of the namespace before the global namespace' do
162
+ define_module 'Models'
163
+ define_model 'Organization'
164
+ define_model 'Models::Organization'
165
+ user_model = define_model 'Models::User', organization_id: :integer do
166
+ belongs_to :organization, class_name: 'Organization'
167
+ end
168
+
169
+ expect(user_model.new).
170
+ to belong_to(:organization).
171
+ class_name('Organization')
172
+ end
173
+
133
174
  it 'accepts an association with a matching :autosave option' do
134
175
  define_model :parent, adopter: :boolean
135
176
  define_model :child, parent_id: :integer do
@@ -288,6 +329,22 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
288
329
  expect(Parent.new).not_to have_many(:children)
289
330
  end
290
331
 
332
+ it 'accepts an association using an existing custom primary key' do
333
+ define_model :child, parent_id: :integer
334
+ define_model :parent, custom_primary_key: :integer do
335
+ has_many :children, primary_key: :custom_primary_key
336
+ end
337
+ expect(Parent.new).to have_many(:children).with_primary_key(:custom_primary_key)
338
+ end
339
+
340
+ it 'rejects an association with a bad :primary_key option' do
341
+ matcher = have_many(:children).with_primary_key(:custom_primary_key)
342
+
343
+ expect(having_many_children).not_to matcher
344
+
345
+ expect(matcher.failure_message).to match(/Parent does not have a custom_primary_key primary key/)
346
+ end
347
+
291
348
  it 'rejects an association with a bad :as option' do
292
349
  define_model :child, caretaker_type: :string,
293
350
  caretaker_id: :integer
@@ -325,6 +382,16 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
325
382
  expect(matcher.failure_message).to match(/through relationships, but got it through conceptions/)
326
383
  end
327
384
 
385
+ it 'produces a failure message without exception when association is missing :through option' do
386
+ define_model :child
387
+ define_model :parent
388
+ matcher = have_many(:children).through(:relationships).source(:child)
389
+ failure_message = 'Expected Parent to have a has_many association called children (no association called children)'
390
+
391
+ matcher.matches?(Parent.new)
392
+ expect(matcher.failure_message).to eq failure_message
393
+ end
394
+
328
395
  it 'accepts an association with a valid :dependent option' do
329
396
  expect(having_many_children(dependent: :destroy)).
330
397
  to have_many(:children).dependent(:destroy)
@@ -414,6 +481,31 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
414
481
  }.to fail_with_message(message)
415
482
  end
416
483
 
484
+ it 'accepts an association with a namespaced class name' do
485
+ define_module 'Models'
486
+ define_model 'Models::Friend', user_id: :integer
487
+ friend_model = define_model 'Models::User' do
488
+ has_many :friends, class_name: 'Friend'
489
+ end
490
+
491
+ expect(friend_model.new).
492
+ to have_many(:friends).
493
+ class_name('Friend')
494
+ end
495
+
496
+ it 'resolves class_name within the context of the namespace before the global namespace' do
497
+ define_module 'Models'
498
+ define_model 'Friend'
499
+ define_model 'Models::Friend', user_id: :integer
500
+ friend_model = define_model 'Models::User' do
501
+ has_many :friends, class_name: 'Friend'
502
+ end
503
+
504
+ expect(friend_model.new).
505
+ to have_many(:friends).
506
+ class_name('Friend')
507
+ end
508
+
417
509
  it 'accepts an association with a matching :autosave option' do
418
510
  define_model :child, parent_id: :integer
419
511
  define_model :parent do
@@ -527,6 +619,22 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
527
619
  expect(Person.new).to have_one(:detail).with_foreign_key(:detailed_person_id)
528
620
  end
529
621
 
622
+ it 'accepts an association using an existing custom primary key' do
623
+ define_model :detail, person_id: :integer
624
+ define_model :person, custom_primary_key: :integer do
625
+ has_one :detail, primary_key: :custom_primary_key
626
+ end
627
+ expect(Person.new).to have_one(:detail).with_primary_key(:custom_primary_key)
628
+ end
629
+
630
+ it 'rejects an association with a bad :primary_key option' do
631
+ matcher = have_one(:detail).with_primary_key(:custom_primary_key)
632
+
633
+ expect(having_one_detail).not_to matcher
634
+
635
+ expect(matcher.failure_message).to match(/Person does not have a custom_primary_key primary key/)
636
+ end
637
+
530
638
  it 'rejects an association with a bad :as option' do
531
639
  define_model :detail, detailable_id: :integer,
532
640
  detailable_type: :string
@@ -584,26 +692,6 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
584
692
  expect(having_one_detail).to have_one(:detail).class_name('Detail')
585
693
  end
586
694
 
587
- it 'accepts an association with a matching :autosave option' do
588
- define_model :detail, person_id: :integer, disabled: :boolean
589
- define_model :person do
590
- has_one :detail, autosave: true
591
- end
592
- expect(Person.new).to have_one(:detail).autosave(true)
593
- end
594
-
595
- it 'rejects an association with a non-matching :autosave option with the correct message' do
596
- define_model :detail, person_id: :integer, disabled: :boolean
597
- define_model :person do
598
- has_one :detail, autosave: false
599
- end
600
-
601
- message = 'Expected Person to have a has_one association called detail (detail should have autosave set to true)'
602
- expect {
603
- expect(Person.new).to have_one(:detail).autosave(true)
604
- }.to fail_with_message(message)
605
- end
606
-
607
695
  it 'accepts an association with a valid :class_name option' do
608
696
  define_model :person_detail, person_id: :integer
609
697
  define_model :person do
@@ -632,6 +720,52 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
632
720
  }.to fail_with_message(message)
633
721
  end
634
722
 
723
+ it 'accepts an association with a namespaced class name' do
724
+ define_module 'Models'
725
+ define_model 'Models::Account', user_id: :integer
726
+ user_model = define_model 'Models::User' do
727
+ has_one :account, class_name: 'Account'
728
+ end
729
+
730
+ expect(user_model.new).
731
+ to have_one(:account).
732
+ class_name('Account')
733
+ end
734
+
735
+ it 'resolves class_name within the context of the namespace before the global namespace' do
736
+ define_module 'Models'
737
+ define_model 'Account'
738
+ define_model 'Models::Account', user_id: :integer
739
+ user_model = define_model 'Models::User' do
740
+ has_one :account, class_name: 'Account'
741
+ end
742
+
743
+ expect(user_model.new).
744
+ to have_one(:account).
745
+ class_name('Account')
746
+ end
747
+
748
+ it 'accepts an association with a matching :autosave option' do
749
+ define_model :detail, person_id: :integer, disabled: :boolean
750
+ define_model :person do
751
+ has_one :detail, autosave: true
752
+ end
753
+ expect(Person.new).to have_one(:detail).autosave(true)
754
+ end
755
+
756
+ it 'rejects an association with a non-matching :autosave option with the correct message' do
757
+ define_model :detail, person_id: :integer, disabled: :boolean
758
+ define_model :person do
759
+ has_one :detail, autosave: false
760
+ end
761
+
762
+ message = 'Expected Person to have a has_one association called detail (detail should have autosave set to true)'
763
+ expect {
764
+ expect(Person.new).to have_one(:detail).autosave(true)
765
+ }.to fail_with_message(message)
766
+ end
767
+
768
+
635
769
  it 'accepts an association with a through' do
636
770
  define_model :detail
637
771
 
@@ -747,7 +881,7 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
747
881
 
748
882
  expect do
749
883
  expect(Person.new).to have_and_belong_to_many(:relatives)
750
- end.to fail_with_message_including('missing columns: custom_foreign_key_id, relative_id')
884
+ end.to fail_with_message_including('missing column: relative_id')
751
885
  end
752
886
  end
753
887
 
@@ -766,8 +900,26 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
766
900
 
767
901
  expect do
768
902
  expect(Person.new).to have_and_belong_to_many(:relatives)
769
- end.to fail_with_message_including('missing columns: person_id, custom_association_foreign_key_id')
903
+ end.to fail_with_message_including('missing column: person_id')
904
+ end
905
+
906
+ it 'accepts foreign keys when they are symbols' do
907
+ define_model :relative
908
+ define_model :person do
909
+ has_and_belongs_to_many :relatives,
910
+ foreign_key: :some_foreign_key_id,
911
+ association_foreign_key: :custom_association_foreign_key_id
912
+ end
913
+
914
+ define_model :people_relative,
915
+ id: false,
916
+ custom_association_foreign_key_id: :integer,
917
+ some_foreign_key_id: :integer
918
+
919
+ expect(Person.new).to have_and_belong_to_many(:relatives)
920
+
770
921
  end
922
+
771
923
  end
772
924
 
773
925
  it 'rejects an association of the wrong type' do
@@ -841,6 +993,45 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
841
993
  }.to fail_with_message(message)
842
994
  end
843
995
 
996
+ it 'accepts an association with a namespaced class name' do
997
+ possible_join_table_names = [:groups_users, :models_groups_users, :groups_models_users]
998
+ possible_join_table_names.each do |join_table_name|
999
+ create_table join_table_name, id: false do |t|
1000
+ t.integer :group_id
1001
+ t.integer :user_id
1002
+ end
1003
+ end
1004
+ define_module 'Models'
1005
+ define_model 'Models::Group'
1006
+ user_model = define_model 'Models::User' do
1007
+ has_and_belongs_to_many :groups, class_name: 'Group'
1008
+ end
1009
+
1010
+ expect(user_model.new).
1011
+ to have_and_belong_to_many(:groups).
1012
+ class_name('Group')
1013
+ end
1014
+
1015
+ it 'resolves class_name within the context of the namespace before the global namespace' do
1016
+ possible_join_table_names = [:groups_users, :models_groups_users, :groups_models_users]
1017
+ possible_join_table_names.each do |join_table_name|
1018
+ create_table join_table_name, id: false do |t|
1019
+ t.integer :group_id
1020
+ t.integer :user_id
1021
+ end
1022
+ end
1023
+ define_module 'Models'
1024
+ define_model 'Group'
1025
+ define_model 'Models::Group'
1026
+ user_model = define_model 'Models::User' do
1027
+ has_and_belongs_to_many :groups, class_name: 'Group'
1028
+ end
1029
+
1030
+ expect(user_model.new).
1031
+ to have_and_belong_to_many(:groups).
1032
+ class_name('Group')
1033
+ end
1034
+
844
1035
  it 'accepts an association with a matching :autosave option' do
845
1036
  define_model :relatives, adopted: :boolean
846
1037
  define_model :person do
@@ -907,7 +1098,7 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
907
1098
  args = []
908
1099
  options = {}
909
1100
  if Shoulda::Matchers::RailsShim.active_record_major_version == 4
910
- args << lambda { where(conditions) }
1101
+ args << proc { where(conditions) }
911
1102
  else
912
1103
  options[:conditions] = conditions
913
1104
  end
@@ -919,7 +1110,7 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
919
1110
  args = []
920
1111
  options = {}
921
1112
  if Shoulda::Matchers::RailsShim.active_record_major_version == 4
922
- args << lambda { order(order) }
1113
+ args << proc { order(order) }
923
1114
  else
924
1115
  options[:order] = order
925
1116
  end