super_diff 0.2.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +108 -74
  3. data/lib/super_diff.rb +20 -11
  4. data/lib/super_diff/active_record.rb +21 -23
  5. data/lib/super_diff/active_record/diff_formatters/active_record_relation.rb +3 -3
  6. data/lib/super_diff/active_record/differs/active_record_relation.rb +3 -5
  7. data/lib/super_diff/active_record/monkey_patches.rb +9 -0
  8. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_model.rb +32 -22
  9. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_relation.rb +17 -7
  10. data/lib/super_diff/active_record/operation_tree_builders.rb +14 -0
  11. data/lib/super_diff/active_record/{operational_sequencers → operation_tree_builders}/active_record_model.rb +2 -2
  12. data/lib/super_diff/active_record/{operational_sequencers → operation_tree_builders}/active_record_relation.rb +4 -4
  13. data/lib/super_diff/active_record/{operation_sequences.rb → operation_trees.rb} +2 -2
  14. data/lib/super_diff/active_record/{operation_sequences → operation_trees}/active_record_relation.rb +2 -2
  15. data/lib/super_diff/active_support.rb +16 -19
  16. data/lib/super_diff/active_support/diff_formatters/hash_with_indifferent_access.rb +3 -3
  17. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +3 -5
  18. data/lib/super_diff/active_support/object_inspection/inspectors/hash_with_indifferent_access.rb +17 -7
  19. data/lib/super_diff/active_support/operation_tree_builders.rb +10 -0
  20. data/lib/super_diff/active_support/{operational_sequencers → operation_tree_builders}/hash_with_indifferent_access.rb +2 -2
  21. data/lib/super_diff/active_support/{operation_sequences.rb → operation_trees.rb} +2 -2
  22. data/lib/super_diff/active_support/{operation_sequences → operation_trees}/hash_with_indifferent_access.rb +2 -2
  23. data/lib/super_diff/configuration.rb +60 -0
  24. data/lib/super_diff/csi.rb +4 -0
  25. data/lib/super_diff/diff_formatters.rb +3 -3
  26. data/lib/super_diff/diff_formatters/array.rb +3 -3
  27. data/lib/super_diff/diff_formatters/base.rb +3 -2
  28. data/lib/super_diff/diff_formatters/collection.rb +2 -2
  29. data/lib/super_diff/diff_formatters/custom_object.rb +3 -3
  30. data/lib/super_diff/diff_formatters/default_object.rb +6 -8
  31. data/lib/super_diff/diff_formatters/defaults.rb +10 -0
  32. data/lib/super_diff/diff_formatters/hash.rb +3 -3
  33. data/lib/super_diff/diff_formatters/main.rb +41 -0
  34. data/lib/super_diff/diff_formatters/multiline_string.rb +3 -3
  35. data/lib/super_diff/differs.rb +4 -9
  36. data/lib/super_diff/differs/array.rb +2 -11
  37. data/lib/super_diff/differs/base.rb +20 -3
  38. data/lib/super_diff/differs/custom_object.rb +2 -11
  39. data/lib/super_diff/differs/default_object.rb +2 -8
  40. data/lib/super_diff/differs/defaults.rb +12 -0
  41. data/lib/super_diff/differs/hash.rb +2 -11
  42. data/lib/super_diff/differs/main.rb +48 -0
  43. data/lib/super_diff/differs/multiline_string.rb +2 -14
  44. data/lib/super_diff/differs/time_like.rb +15 -0
  45. data/lib/super_diff/equality_matchers.rb +3 -9
  46. data/lib/super_diff/equality_matchers/array.rb +1 -7
  47. data/lib/super_diff/equality_matchers/base.rb +1 -1
  48. data/lib/super_diff/equality_matchers/default.rb +2 -8
  49. data/lib/super_diff/equality_matchers/defaults.rb +12 -0
  50. data/lib/super_diff/equality_matchers/hash.rb +1 -7
  51. data/lib/super_diff/equality_matchers/main.rb +21 -0
  52. data/lib/super_diff/equality_matchers/multiline_string.rb +1 -7
  53. data/lib/super_diff/errors.rb +16 -0
  54. data/lib/super_diff/errors/no_diff_formatter_available_error.rb +21 -0
  55. data/lib/super_diff/errors/no_differ_available_error.rb +24 -0
  56. data/lib/super_diff/errors/no_operational_sequencer_available_error.rb +22 -0
  57. data/lib/super_diff/implementation_checks.rb +19 -0
  58. data/lib/super_diff/object_inspection.rb +1 -10
  59. data/lib/super_diff/object_inspection/inspection_tree.rb +6 -2
  60. data/lib/super_diff/object_inspection/inspectors.rb +5 -0
  61. data/lib/super_diff/object_inspection/inspectors/array.rb +20 -10
  62. data/lib/super_diff/object_inspection/inspectors/base.rb +36 -0
  63. data/lib/super_diff/object_inspection/inspectors/custom_object.rb +24 -14
  64. data/lib/super_diff/object_inspection/inspectors/default_object.rb +44 -30
  65. data/lib/super_diff/object_inspection/inspectors/defaults.rb +15 -0
  66. data/lib/super_diff/object_inspection/inspectors/hash.rb +20 -10
  67. data/lib/super_diff/object_inspection/inspectors/main.rb +35 -0
  68. data/lib/super_diff/object_inspection/inspectors/primitive.rb +20 -5
  69. data/lib/super_diff/object_inspection/inspectors/string.rb +15 -5
  70. data/lib/super_diff/object_inspection/inspectors/time_like.rb +23 -0
  71. data/lib/super_diff/object_inspection/nodes/inspection.rb +9 -2
  72. data/lib/super_diff/operation_tree_builders.rb +18 -0
  73. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/array.rb +38 -59
  74. data/lib/super_diff/operation_tree_builders/base.rb +98 -0
  75. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/custom_object.rb +3 -3
  76. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/default_object.rb +8 -3
  77. data/lib/super_diff/operation_tree_builders/defaults.rb +5 -0
  78. data/lib/super_diff/operation_tree_builders/hash.rb +226 -0
  79. data/lib/super_diff/operation_tree_builders/main.rb +42 -0
  80. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/multiline_string.rb +3 -3
  81. data/lib/super_diff/operation_tree_builders/time_like.rb +34 -0
  82. data/lib/super_diff/operation_trees.rb +13 -0
  83. data/lib/super_diff/{operation_sequences → operation_trees}/array.rb +5 -1
  84. data/lib/super_diff/operation_trees/base.rb +31 -0
  85. data/lib/super_diff/{operation_sequences → operation_trees}/custom_object.rb +5 -1
  86. data/lib/super_diff/{operation_sequences → operation_trees}/default_object.rb +10 -8
  87. data/lib/super_diff/operation_trees/defaults.rb +5 -0
  88. data/lib/super_diff/{operation_sequences → operation_trees}/hash.rb +5 -1
  89. data/lib/super_diff/operation_trees/main.rb +35 -0
  90. data/lib/super_diff/operation_trees/multiline_string.rb +18 -0
  91. data/lib/super_diff/operations/unary_operation.rb +3 -0
  92. data/lib/super_diff/rspec.rb +54 -22
  93. data/lib/super_diff/rspec/augmented_matcher.rb +1 -1
  94. data/lib/super_diff/rspec/differ.rb +2 -17
  95. data/lib/super_diff/rspec/differs.rb +9 -3
  96. data/lib/super_diff/rspec/differs/collection_containing_exactly.rb +3 -8
  97. data/lib/super_diff/rspec/differs/collection_including.rb +18 -0
  98. data/lib/super_diff/rspec/differs/hash_including.rb +18 -0
  99. data/lib/super_diff/rspec/differs/object_having_attributes.rb +17 -0
  100. data/lib/super_diff/rspec/matcher_text_builders.rb +4 -0
  101. data/lib/super_diff/rspec/matcher_text_builders/be_predicate.rb +26 -7
  102. data/lib/super_diff/rspec/matcher_text_builders/have_predicate.rb +61 -0
  103. data/lib/super_diff/rspec/matcher_text_builders/match.rb +1 -1
  104. data/lib/super_diff/rspec/matcher_text_builders/raise_error.rb +13 -1
  105. data/lib/super_diff/rspec/matcher_text_builders/respond_to.rb +1 -1
  106. data/lib/super_diff/rspec/matcher_text_template.rb +1 -1
  107. data/lib/super_diff/rspec/monkey_patches.rb +226 -115
  108. data/lib/super_diff/rspec/object_inspection.rb +0 -1
  109. data/lib/super_diff/rspec/object_inspection/inspectors.rb +22 -6
  110. data/lib/super_diff/rspec/object_inspection/inspectors/collection_containing_exactly.rb +17 -8
  111. data/lib/super_diff/rspec/object_inspection/inspectors/collection_including.rb +28 -0
  112. data/lib/super_diff/rspec/object_inspection/inspectors/hash_including.rb +31 -0
  113. data/lib/super_diff/rspec/object_inspection/inspectors/instance_of.rb +23 -0
  114. data/lib/super_diff/rspec/object_inspection/inspectors/kind_of.rb +23 -0
  115. data/lib/super_diff/rspec/object_inspection/inspectors/object_having_attributes.rb +31 -0
  116. data/lib/super_diff/rspec/object_inspection/inspectors/primitive.rb +13 -0
  117. data/lib/super_diff/rspec/object_inspection/inspectors/value_within.rb +29 -0
  118. data/lib/super_diff/rspec/operation_tree_builders.rb +22 -0
  119. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/collection_containing_exactly.rb +6 -6
  120. data/lib/super_diff/rspec/{operational_sequencers/partial_array.rb → operation_tree_builders/collection_including.rb} +4 -3
  121. data/lib/super_diff/rspec/operation_tree_builders/hash_including.rb +25 -0
  122. data/lib/super_diff/rspec/{operational_sequencers/partial_object.rb → operation_tree_builders/object_having_attributes.rb} +5 -11
  123. data/lib/super_diff/version.rb +1 -1
  124. data/spec/examples.txt +397 -328
  125. data/spec/integration/rails/active_record_spec.rb +1 -1
  126. data/spec/integration/rails/hash_with_indifferent_access_spec.rb +1 -1
  127. data/spec/integration/rspec/be_predicate_matcher_spec.rb +111 -59
  128. data/spec/integration/rspec/eq_matcher_spec.rb +139 -3
  129. data/spec/integration/rspec/have_attributes_matcher_spec.rb +354 -227
  130. data/spec/integration/rspec/have_predicate_matcher_spec.rb +484 -0
  131. data/spec/integration/rspec/include_matcher_spec.rb +2 -2
  132. data/spec/integration/rspec/match_array_matcher_spec.rb +372 -0
  133. data/spec/integration/rspec/match_matcher_spec.rb +8 -8
  134. data/spec/integration/rspec/raise_error_matcher_spec.rb +605 -226
  135. data/spec/integration/rspec/third_party_matcher_spec.rb +241 -0
  136. data/spec/integration/rspec/unhandled_errors_spec.rb +110 -58
  137. data/spec/spec_helper.rb +18 -7
  138. data/spec/support/command_runner.rb +3 -0
  139. data/spec/support/integration/helpers.rb +14 -90
  140. data/spec/support/integration/matchers.rb +143 -0
  141. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +14 -29
  142. data/spec/support/integration/test_programs/base.rb +120 -0
  143. data/spec/support/integration/test_programs/plain.rb +13 -0
  144. data/spec/support/integration/test_programs/rspec_active_record.rb +17 -0
  145. data/spec/support/integration/test_programs/rspec_rails.rb +17 -0
  146. data/spec/support/models/active_record/person.rb +4 -11
  147. data/spec/support/models/active_record/query.rb +15 -0
  148. data/spec/support/models/active_record/shipping_address.rb +10 -14
  149. data/spec/support/object_id.rb +27 -0
  150. data/spec/support/ruby_versions.rb +4 -0
  151. data/spec/support/shared_examples/active_record.rb +71 -0
  152. data/spec/support/shared_examples/hash_with_indifferent_access.rb +724 -208
  153. data/spec/tmp/integration_spec.rb +15 -0
  154. data/spec/unit/{equality_matcher_spec.rb → equality_matchers/main_spec.rb} +165 -9
  155. data/spec/unit/object_inspection_spec.rb +94 -18
  156. data/spec/unit/rspec/matchers/have_predicate_spec.rb +21 -0
  157. data/spec/unit/rspec/matchers/match_array_spec.rb +11 -0
  158. data/spec/unit/rspec/matchers/raise_error_spec.rb +16 -0
  159. data/super_diff.gemspec +3 -6
  160. metadata +99 -91
  161. data/lib/super_diff/active_record/object_inspection/map_extension.rb +0 -18
  162. data/lib/super_diff/active_record/operational_sequencers.rb +0 -14
  163. data/lib/super_diff/active_support/object_inspection/map_extension.rb +0 -15
  164. data/lib/super_diff/active_support/operational_sequencers.rb +0 -10
  165. data/lib/super_diff/diff_formatter.rb +0 -32
  166. data/lib/super_diff/differ.rb +0 -51
  167. data/lib/super_diff/equality_matcher.rb +0 -32
  168. data/lib/super_diff/no_differ_available_error.rb +0 -22
  169. data/lib/super_diff/no_operational_sequencer_available_error.rb +0 -20
  170. data/lib/super_diff/object_inspection/inspector.rb +0 -27
  171. data/lib/super_diff/object_inspection/map.rb +0 -28
  172. data/lib/super_diff/operation_sequences.rb +0 -9
  173. data/lib/super_diff/operation_sequences/base.rb +0 -11
  174. data/lib/super_diff/operational_sequencer.rb +0 -48
  175. data/lib/super_diff/operational_sequencers.rb +0 -16
  176. data/lib/super_diff/operational_sequencers/base.rb +0 -89
  177. data/lib/super_diff/operational_sequencers/hash.rb +0 -85
  178. data/lib/super_diff/rspec/configuration.rb +0 -31
  179. data/lib/super_diff/rspec/differs/partial_array.rb +0 -22
  180. data/lib/super_diff/rspec/differs/partial_hash.rb +0 -22
  181. data/lib/super_diff/rspec/differs/partial_object.rb +0 -22
  182. data/lib/super_diff/rspec/object_inspection/inspectors/partial_array.rb +0 -22
  183. data/lib/super_diff/rspec/object_inspection/inspectors/partial_hash.rb +0 -21
  184. data/lib/super_diff/rspec/object_inspection/inspectors/partial_object.rb +0 -21
  185. data/lib/super_diff/rspec/object_inspection/map_extension.rb +0 -23
  186. data/lib/super_diff/rspec/operational_sequencers.rb +0 -22
  187. data/lib/super_diff/rspec/operational_sequencers/partial_hash.rb +0 -32
@@ -0,0 +1,484 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Integration with RSpec's #have_<predicate> matcher", type: :integration do
4
+ context "when the predicate method doesn't exist on the object" do
5
+ context "when the predicate method doesn't exist on the object" do
6
+ it "produces the correct failure message" do
7
+ as_both_colored_and_uncolored do |color_enabled|
8
+ snippet = %|expect(:words).to have_power|
9
+ program = make_plain_test_program(
10
+ snippet,
11
+ color_enabled: color_enabled,
12
+ )
13
+
14
+ expected_output = build_expected_output(
15
+ color_enabled: color_enabled,
16
+ snippet: snippet,
17
+ expectation: proc {
18
+ line do
19
+ plain "Expected "
20
+ beta %|:words|
21
+ plain " to respond to "
22
+ alpha %|has_power?|
23
+ plain "."
24
+ end
25
+ },
26
+ )
27
+
28
+ expect(program).
29
+ to produce_output_when_run(expected_output).
30
+ in_color(color_enabled)
31
+ end
32
+ end
33
+ end
34
+
35
+ context "when the inspected version of the actual value is long" do
36
+ it "produces the correct failure message" do
37
+ as_both_colored_and_uncolored do |color_enabled|
38
+ snippet = <<~TEST.strip
39
+ hash = { a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }
40
+ expect(hash).to have_mapping
41
+ TEST
42
+ program = make_plain_test_program(
43
+ snippet,
44
+ color_enabled: color_enabled,
45
+ )
46
+
47
+ expected_output = build_expected_output(
48
+ color_enabled: color_enabled,
49
+ snippet: %|expect(hash).to have_mapping|,
50
+ newline_before_expectation: true,
51
+ expectation: proc {
52
+ line do
53
+ plain " Expected "
54
+ beta %|{ a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }|
55
+ end
56
+
57
+ line do
58
+ plain "to respond to "
59
+ alpha %|has_mapping?|
60
+ end
61
+ },
62
+ )
63
+
64
+ expect(program).
65
+ to produce_output_when_run(expected_output).
66
+ in_color(color_enabled)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ context "when the predicate method exists on the object" do
73
+ context "but is private" do
74
+ context "when the inspected version of the actual value is short" do
75
+ it "produces the correct failure message" do
76
+ as_both_colored_and_uncolored do |color_enabled|
77
+ snippet = <<~TEST.strip
78
+ class Robot
79
+ private def has_arms?; end
80
+ end
81
+
82
+ expect(Robot.new).to have_arms
83
+ TEST
84
+ program = make_plain_test_program(
85
+ snippet,
86
+ color_enabled: color_enabled,
87
+ )
88
+
89
+ expected_output = build_expected_output(
90
+ color_enabled: color_enabled,
91
+ snippet: %|expect(Robot.new).to have_arms|,
92
+ expectation: proc {
93
+ line do
94
+ plain "Expected "
95
+ beta %|#<Robot>|
96
+ plain " to have a public method "
97
+ alpha %|has_arms?|
98
+ plain "."
99
+ end
100
+ },
101
+ )
102
+
103
+ expect(program).
104
+ to produce_output_when_run(expected_output).
105
+ in_color(color_enabled).
106
+ removing_object_ids
107
+ end
108
+ end
109
+ end
110
+
111
+ context "when the inspected version of the actual value is long" do
112
+ it "produces the correct failure message" do
113
+ as_both_colored_and_uncolored do |color_enabled|
114
+ snippet = <<~TEST.strip
115
+ hash = { a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }
116
+
117
+ class << hash
118
+ private def has_mapping?; end
119
+ end
120
+
121
+ expect(hash).to have_mapping
122
+ TEST
123
+ program = make_plain_test_program(
124
+ snippet,
125
+ color_enabled: color_enabled,
126
+ )
127
+
128
+ expected_output = build_expected_output(
129
+ color_enabled: color_enabled,
130
+ snippet: %|expect(hash).to have_mapping|,
131
+ newline_before_expectation: true,
132
+ expectation: proc {
133
+ line do
134
+ plain " Expected "
135
+ beta %|{ a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }|
136
+ end
137
+
138
+ line do
139
+ plain "to have a public method "
140
+ alpha %|has_mapping?|
141
+ end
142
+ },
143
+ )
144
+
145
+ expect(program).
146
+ to produce_output_when_run(expected_output).
147
+ in_color(color_enabled).
148
+ removing_object_ids
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ context "and is public" do
155
+ context "and returns false" do
156
+ context "and takes arguments" do
157
+ context "when the inspected version of the actual value is short" do
158
+ it "produces the correct failure message" do
159
+ as_both_colored_and_uncolored do |color_enabled|
160
+ snippet = <<~TEST.strip
161
+ class Drink
162
+ def has_ingredients?(*); false; end
163
+ end
164
+
165
+ expect(Drink.new).to have_ingredients(:vodka)
166
+ TEST
167
+ program = make_plain_test_program(
168
+ snippet,
169
+ color_enabled: color_enabled,
170
+ )
171
+
172
+ expected_output = build_expected_output(
173
+ color_enabled: color_enabled,
174
+ snippet: %|expect(Drink.new).to have_ingredients(:vodka)|,
175
+ expectation: proc {
176
+ line do
177
+ plain "Expected "
178
+ beta %|#<Drink>|
179
+ plain " to return a truthy result for "
180
+ alpha %|has_ingredients?(:vodka)|
181
+ plain "."
182
+ end
183
+ },
184
+ )
185
+
186
+ expect(program).
187
+ to produce_output_when_run(expected_output).
188
+ in_color(color_enabled).
189
+ removing_object_ids
190
+ end
191
+ end
192
+ end
193
+
194
+ context "when the inspected version of the actual value is long" do
195
+ it "produces the correct failure message" do
196
+ as_both_colored_and_uncolored do |color_enabled|
197
+ snippet = <<~TEST.strip
198
+ hash = { a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }
199
+
200
+ class << hash
201
+ def has_contents?(*args); false; end
202
+ end
203
+
204
+ expect(hash).to have_contents("keys", "upon", "keys")
205
+ TEST
206
+ program = make_plain_test_program(
207
+ snippet,
208
+ color_enabled: color_enabled,
209
+ )
210
+
211
+ expected_output = build_expected_output(
212
+ color_enabled: color_enabled,
213
+ snippet: %|expect(hash).to have_contents("keys", "upon", "keys")|,
214
+ newline_before_expectation: true,
215
+ expectation: proc {
216
+ line do
217
+ plain " Expected "
218
+ beta %|{ a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }|
219
+ end
220
+
221
+ line do
222
+ plain "to return a truthy result for "
223
+ alpha %|has_contents?("keys", "upon", "keys")|
224
+ end
225
+ },
226
+ )
227
+
228
+ expect(program).
229
+ to produce_output_when_run(expected_output).
230
+ in_color(color_enabled).
231
+ removing_object_ids
232
+ end
233
+ end
234
+ end
235
+ end
236
+
237
+ context "and takes no arguments" do
238
+ context "when the inspected version of the actual value is short" do
239
+ it "produces the correct failure message" do
240
+ as_both_colored_and_uncolored do |color_enabled|
241
+ snippet = <<~TEST.strip
242
+ class Robot
243
+ def has_arms?; false; end
244
+ end
245
+
246
+ expect(Robot.new).to have_arms
247
+ TEST
248
+ program = make_plain_test_program(
249
+ snippet,
250
+ color_enabled: color_enabled,
251
+ )
252
+
253
+ expected_output = build_expected_output(
254
+ color_enabled: color_enabled,
255
+ snippet: %|expect(Robot.new).to have_arms|,
256
+ expectation: proc {
257
+ line do
258
+ plain "Expected "
259
+ beta %|#<Robot>|
260
+ plain " to return a truthy result for "
261
+ alpha %|has_arms?|
262
+ plain "."
263
+ end
264
+ },
265
+ )
266
+
267
+ expect(program).
268
+ to produce_output_when_run(expected_output).
269
+ in_color(color_enabled).
270
+ removing_object_ids
271
+ end
272
+ end
273
+ end
274
+
275
+ context "when the inspected version of the actual value is long" do
276
+ it "produces the correct failure message" do
277
+ as_both_colored_and_uncolored do |color_enabled|
278
+ snippet = <<~TEST.strip
279
+ hash = { a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }
280
+
281
+ class << hash
282
+ def has_mapping?; false; end
283
+ end
284
+
285
+ expect(hash).to have_mapping
286
+ TEST
287
+ program = make_plain_test_program(
288
+ snippet,
289
+ color_enabled: color_enabled,
290
+ )
291
+
292
+ expected_output = build_expected_output(
293
+ color_enabled: color_enabled,
294
+ snippet: %|expect(hash).to have_mapping|,
295
+ newline_before_expectation: true,
296
+ expectation: proc {
297
+ line do
298
+ plain " Expected "
299
+ beta %|{ a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }|
300
+ end
301
+
302
+ line do
303
+ plain "to return a truthy result for "
304
+ alpha %|has_mapping?|
305
+ end
306
+ },
307
+ )
308
+
309
+ expect(program).
310
+ to produce_output_when_run(expected_output).
311
+ in_color(color_enabled).
312
+ removing_object_ids
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end
318
+
319
+ context "and returns true" do
320
+ context "and takes arguments" do
321
+ context "when the inspected version of the actual value is short" do
322
+ it "produces the correct failure message" do
323
+ as_both_colored_and_uncolored do |color_enabled|
324
+ snippet = <<~TEST.strip
325
+ class Drink
326
+ def has_ingredients?(*); true; end
327
+ end
328
+
329
+ expect(Drink.new).not_to have_ingredients(:vodka)
330
+ TEST
331
+ program = make_plain_test_program(
332
+ snippet,
333
+ color_enabled: color_enabled,
334
+ )
335
+
336
+ expected_output = build_expected_output(
337
+ color_enabled: color_enabled,
338
+ snippet: %|expect(Drink.new).not_to have_ingredients(:vodka)|,
339
+ expectation: proc {
340
+ line do
341
+ plain "Expected "
342
+ beta %|#<Drink>|
343
+ plain " not to return a truthy result for "
344
+ alpha %|has_ingredients?(:vodka)|
345
+ plain "."
346
+ end
347
+ },
348
+ )
349
+
350
+ expect(program).
351
+ to produce_output_when_run(expected_output).
352
+ in_color(color_enabled).
353
+ removing_object_ids
354
+ end
355
+ end
356
+ end
357
+
358
+ context "when the inspected version of the actual value is long" do
359
+ it "produces the correct failure message" do
360
+ as_both_colored_and_uncolored do |color_enabled|
361
+ snippet = <<~TEST.strip
362
+ hash = { a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }
363
+
364
+ class << hash
365
+ def has_contents?(*args); true; end
366
+ end
367
+
368
+ expect(hash).not_to have_contents("keys", "upon", "keys")
369
+ TEST
370
+ program = make_plain_test_program(
371
+ snippet,
372
+ color_enabled: color_enabled,
373
+ )
374
+
375
+ expected_output = build_expected_output(
376
+ color_enabled: color_enabled,
377
+ snippet: %|expect(hash).not_to have_contents("keys", "upon", "keys")|,
378
+ newline_before_expectation: true,
379
+ expectation: proc {
380
+ line do
381
+ plain " Expected "
382
+ beta %|{ a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }|
383
+ end
384
+
385
+ line do
386
+ plain "not to return a truthy result for "
387
+ alpha %|has_contents?("keys", "upon", "keys")|
388
+ end
389
+ },
390
+ )
391
+
392
+ expect(program).
393
+ to produce_output_when_run(expected_output).
394
+ in_color(color_enabled).
395
+ removing_object_ids
396
+ end
397
+ end
398
+ end
399
+ end
400
+
401
+ context "and takes no arguments" do
402
+ context "when the inspected version of the actual value is short" do
403
+ it "produces the correct failure message when used in the negative" do
404
+ as_both_colored_and_uncolored do |color_enabled|
405
+ snippet = <<~TEST.strip
406
+ class Robot
407
+ def has_arms?; true; end
408
+ end
409
+
410
+ expect(Robot.new).not_to have_arms
411
+ TEST
412
+ program = make_plain_test_program(
413
+ snippet,
414
+ color_enabled: color_enabled,
415
+ )
416
+
417
+ expected_output = build_expected_output(
418
+ color_enabled: color_enabled,
419
+ snippet: %|expect(Robot.new).not_to have_arms|,
420
+ expectation: proc {
421
+ line do
422
+ plain "Expected "
423
+ beta %|#<Robot>|
424
+ plain " not to return a truthy result for "
425
+ alpha %|has_arms?|
426
+ plain "."
427
+ end
428
+ },
429
+ )
430
+
431
+ expect(program).
432
+ to produce_output_when_run(expected_output).
433
+ in_color(color_enabled).
434
+ removing_object_ids
435
+ end
436
+ end
437
+ end
438
+
439
+ context "when the inspected version of the actual value is long" do
440
+ it "produces the correct failure message when used in the negative" do
441
+ as_both_colored_and_uncolored do |color_enabled|
442
+ snippet = <<~TEST.strip
443
+ hash = { a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }
444
+
445
+ class << hash
446
+ def has_mapping?; true; end
447
+ end
448
+
449
+ expect(hash).not_to have_mapping
450
+ TEST
451
+ program = make_plain_test_program(
452
+ snippet,
453
+ color_enabled: color_enabled,
454
+ )
455
+
456
+ expected_output = build_expected_output(
457
+ color_enabled: color_enabled,
458
+ snippet: %|expect(hash).not_to have_mapping|,
459
+ newline_before_expectation: true,
460
+ expectation: proc {
461
+ line do
462
+ plain " Expected "
463
+ beta %|{ a: "lot", of: "keys", and: "things", like: "that", lets: "add", more: "keys" }|
464
+ end
465
+
466
+ line do
467
+ plain "not to return a truthy result for "
468
+ alpha %|has_mapping?|
469
+ end
470
+ },
471
+ )
472
+
473
+ expect(program).
474
+ to produce_output_when_run(expected_output).
475
+ in_color(color_enabled).
476
+ removing_object_ids
477
+ end
478
+ end
479
+ end
480
+ end
481
+ end
482
+ end
483
+ end
484
+ end