super_diff 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +65 -26
  3. data/lib/super_diff/active_record/differs/active_record_relation.rb +1 -2
  4. data/lib/super_diff/active_record/differs.rb +1 -1
  5. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_model.rb +22 -18
  6. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_relation.rb +14 -7
  7. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders.rb +2 -2
  8. data/lib/super_diff/active_record/object_inspection.rb +1 -1
  9. data/lib/super_diff/active_record/operation_tree_builders/active_record_model.rb +1 -2
  10. data/lib/super_diff/active_record/operation_tree_builders/active_record_relation.rb +1 -2
  11. data/lib/super_diff/active_record/operation_tree_builders.rb +2 -2
  12. data/lib/super_diff/active_record/operation_tree_flatteners.rb +1 -1
  13. data/lib/super_diff/active_record/operation_trees.rb +1 -1
  14. data/lib/super_diff/active_record.rb +7 -15
  15. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +5 -6
  16. data/lib/super_diff/active_support/differs.rb +1 -1
  17. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/hash_with_indifferent_access.rb +20 -11
  18. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/ordered_options.rb +46 -0
  19. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders.rb +5 -1
  20. data/lib/super_diff/active_support/object_inspection.rb +1 -1
  21. data/lib/super_diff/active_support/operation_tree_builders/hash_with_indifferent_access.rb +5 -6
  22. data/lib/super_diff/active_support/operation_tree_builders.rb +1 -1
  23. data/lib/super_diff/active_support/operation_tree_flatteners.rb +1 -1
  24. data/lib/super_diff/active_support/operation_trees.rb +1 -1
  25. data/lib/super_diff/active_support.rb +6 -10
  26. data/lib/super_diff/colorized_document_extensions.rb +2 -4
  27. data/lib/super_diff/configuration.rb +14 -8
  28. data/lib/super_diff/csi/color.rb +4 -4
  29. data/lib/super_diff/csi/colorized_document.rb +12 -16
  30. data/lib/super_diff/csi/document.rb +8 -19
  31. data/lib/super_diff/csi/eight_bit_color.rb +19 -19
  32. data/lib/super_diff/csi/four_bit_color.rb +82 -31
  33. data/lib/super_diff/csi/twenty_four_bit_color.rb +12 -11
  34. data/lib/super_diff/csi/uncolorized_document.rb +2 -6
  35. data/lib/super_diff/csi.rb +10 -14
  36. data/lib/super_diff/diff_formatters/collection.rb +35 -41
  37. data/lib/super_diff/differs/date_like.rb +15 -0
  38. data/lib/super_diff/differs/default_object.rb +1 -1
  39. data/lib/super_diff/differs/defaults.rb +2 -1
  40. data/lib/super_diff/differs/main.rb +2 -13
  41. data/lib/super_diff/differs.rb +1 -0
  42. data/lib/super_diff/equality_matchers/array.rb +10 -12
  43. data/lib/super_diff/equality_matchers/base.rb +1 -1
  44. data/lib/super_diff/equality_matchers/default.rb +2 -4
  45. data/lib/super_diff/equality_matchers/defaults.rb +1 -1
  46. data/lib/super_diff/equality_matchers/hash.rb +10 -12
  47. data/lib/super_diff/equality_matchers/multiline_string.rb +11 -13
  48. data/lib/super_diff/equality_matchers/primitive.rb +10 -12
  49. data/lib/super_diff/equality_matchers/singleline_string.rb +10 -12
  50. data/lib/super_diff/equality_matchers.rb +1 -1
  51. data/lib/super_diff/errors.rb +2 -6
  52. data/lib/super_diff/gem_version.rb +3 -3
  53. data/lib/super_diff/helpers.rb +10 -10
  54. data/lib/super_diff/implementation_checks.rb +2 -2
  55. data/lib/super_diff/line.rb +3 -3
  56. data/lib/super_diff/object_inspection/inspection_tree.rb +64 -73
  57. data/lib/super_diff/object_inspection/inspection_tree_builders/array.rb +29 -14
  58. data/lib/super_diff/object_inspection/inspection_tree_builders/custom_object.rb +17 -13
  59. data/lib/super_diff/object_inspection/inspection_tree_builders/date_like.rb +51 -0
  60. data/lib/super_diff/object_inspection/inspection_tree_builders/default_object.rb +43 -27
  61. data/lib/super_diff/object_inspection/inspection_tree_builders/defaults.rb +2 -1
  62. data/lib/super_diff/object_inspection/inspection_tree_builders/hash.rb +35 -18
  63. data/lib/super_diff/object_inspection/inspection_tree_builders/primitive.rb +3 -5
  64. data/lib/super_diff/object_inspection/inspection_tree_builders/time_like.rb +30 -36
  65. data/lib/super_diff/object_inspection/inspection_tree_builders.rb +13 -9
  66. data/lib/super_diff/object_inspection/nodes/as_lines_when_rendering_to_lines.rb +11 -22
  67. data/lib/super_diff/object_inspection/nodes/as_prefix_when_rendering_to_lines.rb +1 -5
  68. data/lib/super_diff/object_inspection/nodes/as_prelude_when_rendering_to_lines.rb +1 -5
  69. data/lib/super_diff/object_inspection/nodes/as_single_line.rb +3 -7
  70. data/lib/super_diff/object_inspection/nodes/base.rb +9 -14
  71. data/lib/super_diff/object_inspection/nodes/inspection.rb +26 -34
  72. data/lib/super_diff/object_inspection/nodes/nesting.rb +1 -1
  73. data/lib/super_diff/object_inspection/nodes/only_when.rb +2 -6
  74. data/lib/super_diff/object_inspection/nodes/text.rb +1 -5
  75. data/lib/super_diff/object_inspection/nodes/when_empty.rb +2 -6
  76. data/lib/super_diff/object_inspection/nodes/when_non_empty.rb +2 -6
  77. data/lib/super_diff/object_inspection/nodes/when_rendering_to_lines.rb +1 -1
  78. data/lib/super_diff/object_inspection/nodes/when_rendering_to_string.rb +1 -5
  79. data/lib/super_diff/object_inspection/nodes.rb +7 -7
  80. data/lib/super_diff/object_inspection.rb +3 -3
  81. data/lib/super_diff/operation_tree_builders/array.rb +12 -11
  82. data/lib/super_diff/operation_tree_builders/base.rb +17 -15
  83. data/lib/super_diff/operation_tree_builders/custom_object.rb +8 -6
  84. data/lib/super_diff/operation_tree_builders/date_like.rb +15 -0
  85. data/lib/super_diff/operation_tree_builders/default_object.rb +29 -21
  86. data/lib/super_diff/operation_tree_builders/defaults.rb +1 -1
  87. data/lib/super_diff/operation_tree_builders/hash.rb +23 -24
  88. data/lib/super_diff/operation_tree_builders/main.rb +4 -11
  89. data/lib/super_diff/operation_tree_builders/multiline_string.rb +3 -3
  90. data/lib/super_diff/operation_tree_builders/time_like.rb +1 -11
  91. data/lib/super_diff/operation_tree_builders.rb +2 -1
  92. data/lib/super_diff/operation_tree_flatteners/base.rb +1 -5
  93. data/lib/super_diff/operation_tree_flatteners/collection.rb +13 -16
  94. data/lib/super_diff/operation_tree_flatteners/default_object.rb +1 -2
  95. data/lib/super_diff/operation_tree_flatteners/hash.rb +2 -10
  96. data/lib/super_diff/operation_tree_flatteners/multiline_string.rb +2 -1
  97. data/lib/super_diff/operation_tree_flatteners.rb +3 -3
  98. data/lib/super_diff/operation_trees/base.rb +3 -5
  99. data/lib/super_diff/operation_trees/default_object.rb +1 -3
  100. data/lib/super_diff/operations/binary_operation.rb +2 -2
  101. data/lib/super_diff/operations/unary_operation.rb +1 -1
  102. data/lib/super_diff/rails.rb +2 -1
  103. data/lib/super_diff/recursion_guard.rb +5 -4
  104. data/lib/super_diff/rspec/augmented_matcher.rb +4 -5
  105. data/lib/super_diff/rspec/differ.rb +6 -13
  106. data/lib/super_diff/rspec/differs/collection_containing_exactly.rb +3 -2
  107. data/lib/super_diff/rspec/differs/collection_including.rb +1 -1
  108. data/lib/super_diff/rspec/differs/hash_including.rb +1 -1
  109. data/lib/super_diff/rspec/differs.rb +3 -3
  110. data/lib/super_diff/rspec/matcher_text_builders/base.rb +13 -15
  111. data/lib/super_diff/rspec/matcher_text_builders/be_predicate.rb +5 -7
  112. data/lib/super_diff/rspec/matcher_text_builders/have_predicate.rb +3 -5
  113. data/lib/super_diff/rspec/matcher_text_builders/raise_error.rb +2 -10
  114. data/lib/super_diff/rspec/matcher_text_builders/respond_to.rb +2 -6
  115. data/lib/super_diff/rspec/matcher_text_builders.rb +5 -8
  116. data/lib/super_diff/rspec/matcher_text_template.rb +13 -16
  117. data/lib/super_diff/rspec/monkey_patches.rb +180 -123
  118. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_containing_exactly.rb +14 -7
  119. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_including.rb +21 -13
  120. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/double.rb +35 -36
  121. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/generic_describable_matcher.rb +19 -0
  122. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/hash_including.rb +21 -15
  123. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/instance_of.rb +11 -10
  124. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/kind_of.rb +11 -10
  125. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/object_having_attributes.rb +14 -7
  126. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/value_within.rb +10 -11
  127. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders.rb +13 -9
  128. data/lib/super_diff/rspec/object_inspection.rb +1 -1
  129. data/lib/super_diff/rspec/operation_tree_builders/collection_containing_exactly.rb +11 -10
  130. data/lib/super_diff/rspec/operation_tree_builders/collection_including.rb +7 -6
  131. data/lib/super_diff/rspec/operation_tree_builders/hash_including.rb +11 -10
  132. data/lib/super_diff/rspec/operation_tree_builders/object_having_attributes.rb +22 -17
  133. data/lib/super_diff/rspec/operation_tree_builders.rb +4 -4
  134. data/lib/super_diff/rspec.rb +17 -18
  135. data/lib/super_diff/tiered_lines_elider.rb +87 -115
  136. data/lib/super_diff/tiered_lines_formatter.rb +5 -9
  137. data/lib/super_diff/version.rb +1 -1
  138. data/lib/super_diff.rb +13 -9
  139. data/spec/examples.txt +541 -483
  140. data/spec/integration/rails/active_record_spec.rb +3 -1
  141. data/spec/integration/rails/engines_spec.rb +25 -0
  142. data/spec/integration/rails/hash_with_indifferent_access_spec.rb +3 -1
  143. data/spec/integration/rspec/be_falsey_matcher_spec.rb +40 -35
  144. data/spec/integration/rspec/be_matcher_spec.rb +360 -320
  145. data/spec/integration/rspec/be_nil_matcher_spec.rb +38 -34
  146. data/spec/integration/rspec/be_predicate_matcher_spec.rb +376 -359
  147. data/spec/integration/rspec/be_truthy_matcher_spec.rb +38 -33
  148. data/spec/integration/rspec/contain_exactly_matcher_spec.rb +257 -254
  149. data/spec/integration/rspec/eq_matcher_spec.rb +695 -585
  150. data/spec/integration/rspec/generic_describable_matchers_spec.rb +177 -0
  151. data/spec/integration/rspec/have_attributes_matcher_spec.rb +312 -304
  152. data/spec/integration/rspec/have_predicate_matcher_spec.rb +291 -297
  153. data/spec/integration/rspec/include_matcher_spec.rb +327 -225
  154. data/spec/integration/rspec/magic_metadata_spec.rb +51 -0
  155. data/spec/integration/rspec/match_array_matcher_spec.rb +294 -291
  156. data/spec/integration/rspec/match_matcher_spec.rb +916 -903
  157. data/spec/integration/rspec/raise_error_matcher_spec.rb +1208 -449
  158. data/spec/integration/rspec/respond_to_matcher_spec.rb +702 -697
  159. data/spec/integration/rspec/third_party_matcher_spec.rb +142 -138
  160. data/spec/integration/rspec/unhandled_errors_spec.rb +88 -84
  161. data/spec/internal/log/test.log +0 -0
  162. data/spec/spec_helper.rb +20 -20
  163. data/spec/support/command_runner.rb +34 -57
  164. data/spec/support/integration/helpers.rb +44 -32
  165. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +28 -23
  166. data/spec/support/integration/matchers.rb +34 -0
  167. data/spec/support/integration/test_programs/base.rb +17 -22
  168. data/spec/support/integration/test_programs/plain.rb +6 -0
  169. data/spec/support/integration/test_programs/rspec_active_record.rb +4 -1
  170. data/spec/support/integration/test_programs/rspec_active_support.rb +4 -1
  171. data/spec/support/integration/test_programs/rspec_rails.rb +4 -1
  172. data/spec/support/integration/test_programs/rspec_rails_engine.rb +20 -0
  173. data/spec/support/models/active_record/person.rb +6 -4
  174. data/spec/support/models/active_record/shipping_address.rb +9 -10
  175. data/spec/support/models/customer.rb +2 -4
  176. data/spec/support/models/player.rb +3 -6
  177. data/spec/support/models/shipping_address.rb +4 -13
  178. data/spec/support/shared_examples/active_record.rb +258 -240
  179. data/spec/support/shared_examples/active_support.rb +174 -51
  180. data/spec/support/shared_examples/elided_diffs.rb +447 -423
  181. data/spec/support/shared_examples/hash_with_indifferent_access.rb +500 -464
  182. data/spec/support/shared_examples/key.rb +123 -0
  183. data/spec/support/unit/helpers.rb +1 -3
  184. data/spec/support/unit/matchers/match_output.rb +12 -13
  185. data/spec/unit/active_record/object_inspection_spec.rb +222 -206
  186. data/spec/unit/active_support/object_inspection_spec.rb +170 -0
  187. data/spec/unit/equality_matchers/main_spec.rb +1049 -984
  188. data/spec/unit/helpers_spec.rb +14 -21
  189. data/spec/unit/operation_tree_flatteners/array_spec.rb +557 -524
  190. data/spec/unit/operation_tree_flatteners/custom_object_spec.rb +619 -601
  191. data/spec/unit/operation_tree_flatteners/default_object_spec.rb +619 -621
  192. data/spec/unit/operation_tree_flatteners/hash_spec.rb +595 -556
  193. data/spec/unit/operation_tree_flatteners/multiline_string_spec.rb +102 -92
  194. data/spec/unit/rspec/matchers/be_compared_to_spec.rb +3 -3
  195. data/spec/unit/rspec/matchers/be_predicate_spec.rb +3 -3
  196. data/spec/unit/rspec/matchers/contain_exactly_spec.rb +1 -1
  197. data/spec/unit/rspec/matchers/have_attributes_spec.rb +1 -1
  198. data/spec/unit/rspec/matchers/have_predicate_spec.rb +2 -2
  199. data/spec/unit/rspec/matchers/include_spec.rb +2 -2
  200. data/spec/unit/rspec/matchers/match_array_spec.rb +2 -2
  201. data/spec/unit/rspec/matchers/raise_error_spec.rb +43 -11
  202. data/spec/unit/rspec/matchers/respond_to_spec.rb +23 -16
  203. data/spec/unit/rspec/object_inspection/rspec_matcher_spec.rb +91 -0
  204. data/spec/unit/rspec/object_inspection_spec.rb +351 -326
  205. data/spec/unit/super_diff_spec.rb +1594 -1437
  206. data/spec/unit/tiered_lines_elider_spec.rb +3508 -3536
  207. data/spec/unit/tiered_lines_formatter_spec.rb +54 -116
  208. data/super_diff.gemspec +13 -12
  209. metadata +88 -75
  210. data/lib/super_diff/errors/no_diff_formatter_available_error.rb +0 -21
  211. data/lib/super_diff/errors/no_operational_sequencer_available_error.rb +0 -22
  212. data/spec/tmp/warnings_logger/all_warnings.txt +0 -2
@@ -60,19 +60,22 @@ module RSpec
60
60
  if code_or_symbol
61
61
  if (config_method = config_colors_to_methods[code_or_symbol])
62
62
  console_code_for RSpec.configuration.__send__(config_method)
63
- elsif RSpec::Core::Formatters::ConsoleCodes::VT100_CODE_VALUES.key?(code_or_symbol)
63
+ elsif RSpec::Core::Formatters::ConsoleCodes::VT100_CODE_VALUES.key?(
64
+ code_or_symbol
65
+ )
64
66
  code_or_symbol
65
67
  else
66
- RSpec::Core::Formatters::ConsoleCodes::VT100_CODES.fetch(code_or_symbol) do
68
+ RSpec::Core::Formatters::ConsoleCodes::VT100_CODES.fetch(
67
69
  code_or_symbol
68
- end
70
+ ) { code_or_symbol }
69
71
  end
70
72
  end
71
73
  end
72
74
 
73
75
  # Patch so it does not apply a color if code_or_symbol is nil
74
76
  def wrap(text, code_or_symbol)
75
- if RSpec.configuration.color_enabled? && code = console_code_for(code_or_symbol)
77
+ if SuperDiff.configuration.color_enabled? &&
78
+ code = console_code_for(code_or_symbol)
76
79
  "\e[#{code}m#{text}\e[0m"
77
80
  else
78
81
  text
@@ -86,50 +89,56 @@ module RSpec
86
89
  RESET_CODE = "\e[0m"
87
90
 
88
91
  SuperDiff.insert_overrides(self) do
89
- def initialize(exception, example, options={})
90
- @exception = exception
91
- @example = example
92
- @message_color = options.fetch(:message_color) { RSpec.configuration.failure_color }
93
- @description = options.fetch(:description) { example.full_description }
94
- @detail_formatter = options.fetch(:detail_formatter) { Proc.new {} }
95
- @extra_detail_formatter = options.fetch(:extra_detail_formatter) { Proc.new {} }
96
- @backtrace_formatter = options.fetch(:backtrace_formatter) { RSpec.configuration.backtrace_formatter }
97
- @indentation = options.fetch(:indentation, 2)
98
- @skip_shared_group_trace = options.fetch(:skip_shared_group_trace, false)
92
+ def initialize(exception, example, options = {})
93
+ @exception = exception
94
+ @example = example
95
+ @message_color =
96
+ options.fetch(:message_color) do
97
+ RSpec.configuration.failure_color
98
+ end
99
+ @description =
100
+ options.fetch(:description) { example.full_description }
101
+ @detail_formatter = options.fetch(:detail_formatter) { Proc.new {} }
102
+ @extra_detail_formatter =
103
+ options.fetch(:extra_detail_formatter) { Proc.new {} }
104
+ @backtrace_formatter =
105
+ options.fetch(:backtrace_formatter) do
106
+ RSpec.configuration.backtrace_formatter
107
+ end
108
+ @indentation = options.fetch(:indentation, 2)
109
+ @skip_shared_group_trace =
110
+ options.fetch(:skip_shared_group_trace, false)
99
111
  # Patch to convert options[:failure_lines] to groups
100
112
  if options.include?(:failure_lines)
101
113
  @failure_line_groups = [
102
- {
103
- lines: options[:failure_lines],
104
- already_colorized: false
105
- }
114
+ { lines: options[:failure_lines], already_colorized: false }
106
115
  ]
107
116
  end
108
117
  end
109
118
 
110
119
  # Override to only color uncolored lines in red
111
120
  # and to not color empty lines
112
- def colorized_message_lines(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
113
- lines = failure_line_groups.flat_map do |group|
114
- if group[:already_colorized]
115
- group[:lines]
116
- else
117
- group[:lines].map do |line|
118
- if line.strip.empty?
119
- line
120
- else
121
- indentation = line[/^[ ]+/]
122
- rest = colorizer.wrap(line.sub(/^[ ]+/, ''), message_color)
123
-
124
- if indentation
125
- indentation + rest
121
+ def colorized_message_lines(
122
+ colorizer = ::RSpec::Core::Formatters::ConsoleCodes
123
+ )
124
+ lines =
125
+ failure_line_groups.flat_map do |group|
126
+ if group[:already_colorized]
127
+ group[:lines]
128
+ else
129
+ group[:lines].map do |line|
130
+ if line.strip.empty?
131
+ line
126
132
  else
127
- rest
133
+ indentation = line[/^[ ]+/]
134
+ rest =
135
+ colorizer.wrap(line.sub(/^[ ]+/, ""), message_color)
136
+
137
+ indentation ? indentation + rest : rest
128
138
  end
129
139
  end
130
140
  end
131
141
  end
132
- end
133
142
 
134
143
  add_shared_group_lines(lines, colorizer)
135
144
  end
@@ -158,25 +167,24 @@ module RSpec
158
167
  @failure_line_groups
159
168
  else
160
169
  @failure_line_groups = [
161
- {
162
- lines: failure_slash_error_lines,
163
- already_colorized: true
164
- }
170
+ { lines: failure_slash_error_lines, already_colorized: true }
165
171
  ]
166
172
 
167
173
  sections = [failure_slash_error_lines, exception_lines]
168
- separate_groups = (
169
- sections.any? { |section| section.size > 1 } &&
170
- !exception_lines.first.empty?
171
- )
174
+ separate_groups =
175
+ (
176
+ sections.any? { |section| section.size > 1 } &&
177
+ !exception_lines.first.empty?
178
+ )
172
179
 
173
180
  if separate_groups
174
- @failure_line_groups << { lines: [''], already_colorized: true }
181
+ @failure_line_groups << { lines: [""], already_colorized: true }
175
182
  end
176
183
 
177
- already_colorized = exception_lines.any? do |line|
178
- SuperDiff::Csi.already_colorized?(line)
179
- end
184
+ already_colorized =
185
+ exception_lines.any? do |line|
186
+ SuperDiff::Csi.already_colorized?(line)
187
+ end
180
188
 
181
189
  if already_colorized
182
190
  @failure_line_groups << {
@@ -210,7 +218,10 @@ module RSpec
210
218
  }
211
219
  end
212
220
  end
213
-
221
+ @failure_line_groups << {
222
+ lines: extra_failure_lines,
223
+ already_colorized: true
224
+ }
214
225
  @failure_line_groups
215
226
  end
216
227
  end
@@ -225,15 +236,32 @@ module RSpec
225
236
  lines[0] = failure_slash_error + lines[0].strip
226
237
  else
227
238
  least_indentation = SnippetExtractor.least_indentation_from(lines)
228
- lines = lines.map do |line|
229
- line.sub(/^#{least_indentation}/, ' ')
230
- end
239
+ lines =
240
+ lines.map { |line| line.sub(/^#{least_indentation}/, " ") }
231
241
  lines.unshift(failure_slash_error)
232
242
  end
233
243
 
234
244
  lines
235
245
  end
236
246
 
247
+ # Override to ensure that each item in the array returned is one and
248
+ # only one line and doesn't contain any newline characters
249
+ def extra_failure_lines
250
+ @extra_failure_lines ||=
251
+ begin
252
+ original_lines = Array(example.metadata[:extra_failure_lines])
253
+ normalized_lines =
254
+ original_lines.flat_map { |line| line.split("\n") }
255
+ unless normalized_lines.empty?
256
+ unless normalized_lines.first == ""
257
+ normalized_lines.unshift("")
258
+ end
259
+ normalized_lines.push("") unless normalized_lines.last == ""
260
+ end
261
+ normalized_lines
262
+ end
263
+ end
264
+
237
265
  # Exclude this file from being included in backtraces, so that the
238
266
  # SnippetExtractor prints the right thing
239
267
  def find_failed_line
@@ -243,7 +271,8 @@ module RSpec
243
271
  exception_backtrace.find do |line|
244
272
  next unless (line_path = line[/(.+?):(\d+)(|:\d+)/, 1])
245
273
  path = File.expand_path(line_path)
246
- path != __FILE__ && (loaded_spec_files.include?(path) || path =~ line_regex)
274
+ path != __FILE__ &&
275
+ (loaded_spec_files.include?(path) || path =~ line_regex)
247
276
  end || exception_backtrace.first
248
277
  end
249
278
  end
@@ -286,36 +315,38 @@ module RSpec
286
315
  def from(expected)
287
316
  return expected if self === expected
288
317
 
289
- text =
290
- colorizer.wrap("Diff:", SuperDiff.configuration.header_color) +
291
- "\n\n" +
292
- colorizer.wrap(
293
- " (Key) ──────────────────────────┐",
294
- SuperDiff.configuration.border_color
295
- ) +
296
- "\n" +
297
- colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
298
- colorizer.wrap(
299
- "‹-› in expected, not in actual",
300
- SuperDiff.configuration.expected_color
301
- ) +
302
- colorizer.wrap(" │", SuperDiff.configuration.border_color) +
303
- "\n" +
304
- colorizer.wrap("", SuperDiff.configuration.border_color) +
305
- colorizer.wrap(
306
- "‹+› in actual, not in expected",
307
- SuperDiff.configuration.actual_color
308
- ) +
309
- colorizer.wrap(" │", SuperDiff.configuration.border_color) +
310
- "\n" +
311
- colorizer.wrap("", SuperDiff.configuration.border_color) +
312
- " in both expected and actual" +
313
- colorizer.wrap(" ", SuperDiff.configuration.border_color) +
314
- "\n" +
315
- colorizer.wrap(
316
- "└─────────────────────────────────┘",
317
- SuperDiff.configuration.border_color
318
- )
318
+ text = colorizer.wrap("Diff:", SuperDiff.configuration.header_color)
319
+
320
+ if SuperDiff.configuration.key_enabled?
321
+ text +=
322
+ "\n\n" +
323
+ colorizer.wrap(
324
+ "┌ (Key) ──────────────────────────┐",
325
+ SuperDiff.configuration.border_color
326
+ ) + "\n" +
327
+ colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
328
+ colorizer.wrap(
329
+ "‹-› in expected, not in actual",
330
+ SuperDiff.configuration.expected_color
331
+ ) +
332
+ colorizer.wrap("", SuperDiff.configuration.border_color) +
333
+ "\n" +
334
+ colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
335
+ colorizer.wrap(
336
+ "‹+› in actual, not in expected",
337
+ SuperDiff.configuration.actual_color
338
+ ) +
339
+ colorizer.wrap("", SuperDiff.configuration.border_color) +
340
+ "\n" +
341
+ colorizer.wrap(" ", SuperDiff.configuration.border_color) +
342
+ " › in both expected and actual" +
343
+ colorizer.wrap("", SuperDiff.configuration.border_color) +
344
+ "\n" +
345
+ colorizer.wrap(
346
+ "└─────────────────────────────────┘",
347
+ SuperDiff.configuration.border_color
348
+ )
349
+ end
319
350
 
320
351
  new([[expected, text]])
321
352
  end
@@ -330,22 +361,21 @@ module RSpec
330
361
  def message_with_diff(message, differ, actual)
331
362
  diff = diffs(differ, actual)
332
363
 
333
- if diff.empty?
334
- message
335
- else
336
- "#{message.rstrip}\n\n#{diff}"
337
- end
364
+ diff.empty? ? message : "#{message.rstrip}\n\n#{diff}"
338
365
  end
339
366
 
340
367
  private
341
368
 
342
369
  # Add extra line breaks in between diffs, and colorize the word "Diff"
343
370
  def diffs(differ, actual)
344
- @expected_list.map do |(expected, diff_label)|
345
- diff = differ.diff(actual, expected)
346
- next if diff.strip.empty?
347
- diff_label + diff
348
- end.compact.join("\n\n")
371
+ @expected_list
372
+ .map do |(expected, diff_label)|
373
+ diff = differ.diff(actual, expected)
374
+ next if diff.strip.empty?
375
+ diff_label + diff
376
+ end
377
+ .compact
378
+ .join("\n\n")
349
379
  end
350
380
  end
351
381
  end
@@ -366,7 +396,7 @@ module RSpec
366
396
 
367
397
  SuperDiff.insert_overrides(self) do
368
398
  def expected_action_for_matcher_text
369
- if [:==, :===, :=~].include?(@operator)
399
+ if %i[== === =~].include?(@operator)
370
400
  "#{@operator}"
371
401
  else
372
402
  "be #{@operator}"
@@ -415,7 +445,7 @@ module RSpec
415
445
  if SuperDiff::RSpec.rspec_version < "3.10"
416
446
  expected
417
447
  else
418
- predicate.to_s.chomp('?')
448
+ predicate.to_s.chomp("?")
419
449
  end
420
450
  end
421
451
 
@@ -507,7 +537,7 @@ module RSpec
507
537
 
508
538
  # Override to use (...) as delimiters rather than {...}
509
539
  def expected_for_matcher_text
510
- super.sub(/^\{ /, '(').gsub(/ \}$/, ')')
540
+ super.sub(/^\{ /, "(").gsub(/ \}$/, ")")
511
541
  end
512
542
 
513
543
  # Override so that the differ knows that this is a partial object
@@ -538,14 +568,17 @@ module RSpec
538
568
  # Override this method to skip non-existent attributes, and to use
539
569
  # public_send
540
570
  def cache_all_values
541
- @values = @expected.keys.inject({}) do |hash, attribute_key|
542
- if @actual.respond_to?(attribute_key)
543
- actual_value = @actual.public_send(attribute_key)
544
- hash.merge(attribute_key => actual_value)
545
- else
546
- hash
547
- end
548
- end
571
+ @values =
572
+ @expected
573
+ .keys
574
+ .inject({}) do |hash, attribute_key|
575
+ if @actual.respond_to?(attribute_key)
576
+ actual_value = @actual.public_send(attribute_key)
577
+ hash.merge(attribute_key => actual_value)
578
+ else
579
+ hash
580
+ end
581
+ end
549
582
  end
550
583
 
551
584
  def actual_has_attribute?(attribute_key, attribute_value)
@@ -624,7 +657,8 @@ module RSpec
624
657
  if actual.respond_to?(:include?)
625
658
  message
626
659
  elsif message.end_with?(".")
627
- message.sub("\.$", ", ") + "but it does not respond to `include?`."
660
+ message.sub("\.$", ", ") +
661
+ "but it does not respond to `include?`."
628
662
  else
629
663
  message + "\n\nBut it does not respond to `include?`."
630
664
  end
@@ -649,9 +683,10 @@ module RSpec
649
683
  # Update to use (...) as delimiter instead of {...}
650
684
  def readable_list_of(items)
651
685
  if items && items.all? { |item| item.is_a?(Hash) }
652
- description_of(items.inject(:merge)).
653
- sub(/^\{ /, '(').
654
- sub(/ \}$/, ')')
686
+ description_of(items.inject(:merge)).sub(/^\{ /, "(").sub(
687
+ / \}$/,
688
+ ")"
689
+ )
655
690
  else
656
691
  super
657
692
  end
@@ -687,25 +722,36 @@ module RSpec
687
722
  SuperDiff.insert_overrides(self, SuperDiff::RSpec::AugmentedMatcher)
688
723
 
689
724
  SuperDiff.insert_overrides(self) do
725
+ def expected_action_for_description
726
+ "raise"
727
+ end
728
+
690
729
  def actual_for_matcher_text
691
730
  if @actual_error
692
731
  "#<#{@actual_error.class.name} #{@actual_error.message.inspect}>"
732
+ else
733
+ "exception-free block"
693
734
  end
694
735
  end
695
736
 
696
737
  def actual_for_diff
697
- if @actual_error
698
- @actual_error.message
699
- end
738
+ @actual_error.message if @actual_error
700
739
  end
701
740
 
702
741
  def expected_for_matcher_text
703
- if @expected_message
704
- "#<#{@expected_error.name} #{description_of(@expected_message)}>"
705
- elsif @expected_error.is_a? Regexp
706
- "#<Exception #{description_of(@expected_error)}>"
742
+ case @expected_message
743
+ when nil
744
+ if RSpec::Matchers.is_a_describable_matcher?(@expected_error)
745
+ description_of(@expected_error)
746
+ elsif @expected_error.is_a?(Regexp)
747
+ "a kind of Exception with message matching #{description_of(@expected_error)}"
748
+ else
749
+ "a kind of #{@expected_error}"
750
+ end
751
+ when Regexp
752
+ "#{described_expected_error} with message matching #{description_of(@expected_message)}"
707
753
  else
708
- "#<#{@expected_error.name}>"
754
+ "#{described_expected_error} with message #{description_of(@expected_message)}"
709
755
  end
710
756
  end
711
757
 
@@ -718,16 +764,22 @@ module RSpec
718
764
  end
719
765
 
720
766
  def expected_action_for_failure_message
721
- if @actual_error
722
- "match"
723
- else
724
- "raise error"
725
- end
767
+ @actual_error ? "match" : "raise"
726
768
  end
727
769
 
728
770
  def matcher_text_builder_class
729
771
  SuperDiff::RSpec::MatcherTextBuilders::RaiseError
730
772
  end
773
+
774
+ private
775
+
776
+ def described_expected_error
777
+ if @expected_error.is_a?(Class)
778
+ "a kind of #{@expected_error}"
779
+ else
780
+ description_of(@expected_error)
781
+ end
782
+ end
731
783
  end
732
784
 
733
785
  def self.matcher_name
@@ -770,13 +822,18 @@ module RSpec
770
822
 
771
823
  SuperDiff.insert_overrides(self) do
772
824
  def self.prepended(base)
773
- base.class_eval do
774
- alias_matcher :an_array_matching, :match_array
775
- end
825
+ base.class_eval { alias_matcher :an_array_matching, :match_array }
776
826
  end
777
827
 
778
828
  def match_array(items)
779
- BuiltIn::MatchArray.new(items.is_a?(String) ? [items] : items)
829
+ # This is a bit strange, but this is fundamentally different from
830
+ # splatting `items` in the argument list. It's functionally equivalent
831
+ # to, though not quite the same as:
832
+ #
833
+ # items.is_a?(Array) ? items : [items]
834
+ #
835
+ items = *items
836
+ BuiltIn::MatchArray.new(items)
780
837
  end
781
838
  end
782
839
  end
@@ -8,17 +8,24 @@ module SuperDiff
8
8
  end
9
9
 
10
10
  def call
11
- SuperDiff::ObjectInspection::InspectionTree.new do
12
- as_lines_when_rendering_to_lines(collection_bookend: :open) do
13
- add_text "#<a collection containing exactly ("
11
+ SuperDiff::ObjectInspection::InspectionTree.new do |t1|
12
+ # stree-ignore
13
+ t1.as_lines_when_rendering_to_lines(
14
+ collection_bookend: :open
15
+ ) do |t2|
16
+ t2.add_text "#<a collection containing exactly ("
14
17
  end
15
18
 
16
- nested do |aliased_matcher|
17
- insert_array_inspection_of(aliased_matcher.expected)
19
+ # stree-ignore
20
+ t1.nested do |t2|
21
+ t2.insert_array_inspection_of(object.expected)
18
22
  end
19
23
 
20
- as_lines_when_rendering_to_lines(collection_bookend: :close) do
21
- add_text ")>"
24
+ # stree-ignore
25
+ t1.as_lines_when_rendering_to_lines(
26
+ collection_bookend: :close
27
+ ) do |t2|
28
+ t2.add_text ")>"
22
29
  end
23
30
  end
24
31
  end
@@ -4,26 +4,34 @@ module SuperDiff
4
4
  module InspectionTreeBuilders
5
5
  class CollectionIncluding < SuperDiff::ObjectInspection::InspectionTreeBuilders::Base
6
6
  def self.applies_to?(value)
7
- SuperDiff::RSpec.a_collection_including_something?(value) || SuperDiff::RSpec.array_including_something?(value)
7
+ SuperDiff::RSpec.a_collection_including_something?(value) ||
8
+ SuperDiff::RSpec.array_including_something?(value)
8
9
  end
9
10
 
10
11
  def call
11
- SuperDiff::ObjectInspection::InspectionTree.new do
12
- as_lines_when_rendering_to_lines(collection_bookend: :open) do
13
- add_text "#<a collection including ("
12
+ SuperDiff::ObjectInspection::InspectionTree.new do |t1|
13
+ # stree-ignore
14
+ t1.as_lines_when_rendering_to_lines(
15
+ collection_bookend: :open
16
+ ) do |t2|
17
+ t2.add_text "#<a collection including ("
14
18
  end
15
19
 
16
- nested do |value|
17
- array = if SuperDiff::RSpec.a_collection_including_something?(value)
18
- value.expecteds
19
- else
20
- value.instance_variable_get(:@expected)
21
- end
22
- insert_array_inspection_of(array)
20
+ t1.nested do |t2|
21
+ if SuperDiff::RSpec.a_collection_including_something?(object)
22
+ t2.insert_array_inspection_of(object.expecteds)
23
+ else
24
+ t2.insert_array_inspection_of(
25
+ object.instance_variable_get(:@expected)
26
+ )
27
+ end
23
28
  end
24
29
 
25
- as_lines_when_rendering_to_lines(collection_bookend: :close) do
26
- add_text ")>"
30
+ # stree-ignore
31
+ t1.as_lines_when_rendering_to_lines(
32
+ collection_bookend: :close
33
+ ) do |t2|
34
+ t2.add_text ")>"
27
35
  end
28
36
  end
29
37
  end
@@ -8,53 +8,51 @@ module SuperDiff
8
8
  end
9
9
 
10
10
  def call
11
- builder = self
12
- empty = -> { empty? }
13
- nonempty = -> { !empty? }
14
-
15
- SuperDiff::ObjectInspection::InspectionTree.new do
16
- only_when empty do
17
- as_lines_when_rendering_to_lines do
18
- add_text do |object|
19
- inspected_class = builder.inspected_class
20
- inspected_name = builder.inspected_name
21
- "#<#{inspected_class} #{inspected_name}>"
22
- end
11
+ SuperDiff::ObjectInspection::InspectionTree.new do |t1|
12
+ t1.only_when method(:empty?) do |t2|
13
+ t2.as_lines_when_rendering_to_lines do |t3|
14
+ t3.add_text("#<#{inspected_class} #{inspected_name}>")
23
15
  end
24
16
  end
25
17
 
26
- only_when nonempty do
27
- as_lines_when_rendering_to_lines(collection_bookend: :open) do
28
- add_text do |object|
29
- inspected_class = builder.inspected_class
30
- inspected_name = builder.inspected_name
31
- "#<#{inspected_class} #{inspected_name}"
32
- end
18
+ t1.only_when method(:nonempty?) do |t2|
19
+ t2.as_lines_when_rendering_to_lines(
20
+ collection_bookend: :open
21
+ ) do |t3|
22
+ t3.add_text("#<#{inspected_class} #{inspected_name}")
33
23
 
34
- when_rendering_to_lines do
35
- add_text " {"
24
+ # stree-ignore
25
+ t3.when_rendering_to_lines do |t4|
26
+ t4.add_text " {"
36
27
  end
37
28
  end
38
29
 
39
- when_rendering_to_string do
40
- add_text " "
30
+ # stree-ignore
31
+ t2.when_rendering_to_string do |t3|
32
+ t3.add_text " "
41
33
  end
42
34
 
43
- nested do |object|
44
- insert_hash_inspection_of(builder.doubled_methods)
35
+ # stree-ignore
36
+ t2.nested do |t3|
37
+ t3.insert_hash_inspection_of doubled_methods
45
38
  end
46
39
 
47
- as_lines_when_rendering_to_lines(collection_bookend: :close) do
48
- when_rendering_to_lines do
49
- add_text "}"
40
+ t2.as_lines_when_rendering_to_lines(
41
+ collection_bookend: :close
42
+ ) do |t3|
43
+ # stree-ignore
44
+ t3.when_rendering_to_lines do |t4|
45
+ t4.add_text "}"
50
46
  end
51
47
 
52
- add_text ">"
48
+ t3.add_text ">"
53
49
  end
54
50
  end
55
51
  end
56
52
  end
57
53
 
54
+ private
55
+
58
56
  def empty?
59
57
  doubled_methods.empty?
60
58
  end
@@ -85,16 +83,17 @@ module SuperDiff
85
83
  end
86
84
 
87
85
  def doubled_methods
88
- @_doubled_methods ||= doubled_method_names.reduce({}) do |hash, key|
89
- hash.merge(key => object.public_send(key))
90
- end
86
+ @_doubled_methods ||=
87
+ doubled_method_names.reduce({}) do |hash, key|
88
+ hash.merge(key => object.public_send(key))
89
+ end
91
90
  end
92
91
 
93
92
  def doubled_method_names
94
- object.
95
- __send__(:__mock_proxy).
96
- instance_variable_get("@method_doubles").
97
- keys
93
+ object
94
+ .__send__(:__mock_proxy)
95
+ .instance_variable_get("@method_doubles")
96
+ .keys
98
97
  end
99
98
  end
100
99
  end