super_diff 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +117 -89
  3. data/lib/super_diff.rb +33 -47
  4. data/lib/super_diff/active_record.rb +41 -0
  5. data/lib/super_diff/active_record/diff_formatters.rb +10 -0
  6. data/lib/super_diff/active_record/diff_formatters/active_record_relation.rb +23 -0
  7. data/lib/super_diff/active_record/differs.rb +10 -0
  8. data/lib/super_diff/active_record/differs/active_record_relation.rb +30 -0
  9. data/lib/super_diff/active_record/object_inspection.rb +14 -0
  10. data/lib/super_diff/active_record/object_inspection/inspectors.rb +16 -0
  11. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_model.rb +38 -0
  12. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_relation.rb +18 -0
  13. data/lib/super_diff/active_record/object_inspection/map_extension.rb +18 -0
  14. data/lib/super_diff/active_record/operation_sequences.rb +10 -0
  15. data/lib/super_diff/active_record/operation_sequences/active_record_relation.rb +16 -0
  16. data/lib/super_diff/active_record/operational_sequencers.rb +14 -0
  17. data/lib/super_diff/active_record/operational_sequencers/active_record_model.rb +19 -0
  18. data/lib/super_diff/active_record/operational_sequencers/active_record_relation.rb +24 -0
  19. data/lib/super_diff/active_support.rb +33 -0
  20. data/lib/super_diff/active_support/diff_formatters.rb +10 -0
  21. data/lib/super_diff/active_support/diff_formatters/hash_with_indifferent_access.rb +36 -0
  22. data/lib/super_diff/active_support/differs.rb +10 -0
  23. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +36 -0
  24. data/lib/super_diff/active_support/object_inspection.rb +14 -0
  25. data/lib/super_diff/active_support/object_inspection/inspectors.rb +12 -0
  26. data/lib/super_diff/active_support/object_inspection/inspectors/hash_with_indifferent_access.rb +18 -0
  27. data/lib/super_diff/active_support/object_inspection/map_extension.rb +15 -0
  28. data/lib/super_diff/active_support/operation_sequences.rb +10 -0
  29. data/lib/super_diff/active_support/operation_sequences/hash_with_indifferent_access.rb +16 -0
  30. data/lib/super_diff/active_support/operational_sequencers.rb +10 -0
  31. data/lib/super_diff/active_support/operational_sequencers/hash_with_indifferent_access.rb +21 -0
  32. data/lib/super_diff/colorized_document_extensions.rb +17 -0
  33. data/lib/super_diff/csi.rb +45 -15
  34. data/lib/super_diff/csi/bold_sequence.rb +9 -0
  35. data/lib/super_diff/csi/color.rb +62 -0
  36. data/lib/super_diff/csi/color_sequence_block.rb +28 -0
  37. data/lib/super_diff/csi/colorized_document.rb +72 -0
  38. data/lib/super_diff/csi/document.rb +183 -0
  39. data/lib/super_diff/csi/eight_bit_color.rb +72 -26
  40. data/lib/super_diff/csi/four_bit_color.rb +63 -29
  41. data/lib/super_diff/csi/twenty_four_bit_color.rb +79 -18
  42. data/lib/super_diff/csi/uncolorized_document.rb +29 -0
  43. data/lib/super_diff/diff_formatter.rb +10 -15
  44. data/lib/super_diff/diff_formatters.rb +10 -1
  45. data/lib/super_diff/diff_formatters/base.rb +12 -17
  46. data/lib/super_diff/diff_formatters/collection.rb +81 -50
  47. data/lib/super_diff/diff_formatters/{object.rb → custom_object.rb} +12 -9
  48. data/lib/super_diff/diff_formatters/default_object.rb +48 -0
  49. data/lib/super_diff/diff_formatters/multiline_string.rb +31 -0
  50. data/lib/super_diff/differ.rb +35 -32
  51. data/lib/super_diff/differs.rb +16 -1
  52. data/lib/super_diff/differs/array.rb +2 -2
  53. data/lib/super_diff/differs/base.rb +11 -21
  54. data/lib/super_diff/differs/custom_object.rb +26 -0
  55. data/lib/super_diff/differs/default_object.rb +25 -0
  56. data/lib/super_diff/differs/empty.rb +1 -1
  57. data/lib/super_diff/differs/hash.rb +2 -2
  58. data/lib/super_diff/differs/{multi_line_string.rb → multiline_string.rb} +6 -5
  59. data/lib/super_diff/equality_matcher.rb +9 -22
  60. data/lib/super_diff/equality_matchers.rb +19 -1
  61. data/lib/super_diff/equality_matchers/array.rb +6 -4
  62. data/lib/super_diff/equality_matchers/base.rb +8 -16
  63. data/lib/super_diff/equality_matchers/default.rb +60 -0
  64. data/lib/super_diff/equality_matchers/hash.rb +6 -4
  65. data/lib/super_diff/equality_matchers/{multi_line_string.rb → multiline_string.rb} +9 -6
  66. data/lib/super_diff/equality_matchers/primitive.rb +34 -0
  67. data/lib/super_diff/equality_matchers/{single_line_string.rb → singleline_string.rb} +7 -5
  68. data/lib/super_diff/helpers.rb +17 -81
  69. data/lib/super_diff/no_differ_available_error.rb +22 -0
  70. data/lib/super_diff/{errors.rb → no_operational_sequencer_available_error.rb} +0 -0
  71. data/lib/super_diff/object_inspection.rb +24 -0
  72. data/lib/super_diff/object_inspection/inspection_tree.rb +144 -0
  73. data/lib/super_diff/object_inspection/inspector.rb +27 -0
  74. data/lib/super_diff/object_inspection/inspectors.rb +18 -0
  75. data/lib/super_diff/object_inspection/inspectors/array.rb +22 -0
  76. data/lib/super_diff/object_inspection/inspectors/custom_object.rb +27 -0
  77. data/lib/super_diff/object_inspection/inspectors/default_object.rb +47 -0
  78. data/lib/super_diff/object_inspection/inspectors/hash.rb +22 -0
  79. data/lib/super_diff/object_inspection/inspectors/primitive.rb +13 -0
  80. data/lib/super_diff/object_inspection/inspectors/string.rb +13 -0
  81. data/lib/super_diff/object_inspection/map.rb +28 -0
  82. data/lib/super_diff/object_inspection/nodes.rb +49 -0
  83. data/lib/super_diff/object_inspection/nodes/base.rb +86 -0
  84. data/lib/super_diff/object_inspection/nodes/break.rb +15 -0
  85. data/lib/super_diff/object_inspection/nodes/inspection.rb +15 -0
  86. data/lib/super_diff/object_inspection/nodes/nesting.rb +16 -0
  87. data/lib/super_diff/object_inspection/nodes/text.rb +15 -0
  88. data/lib/super_diff/object_inspection/nodes/when_empty.rb +30 -0
  89. data/lib/super_diff/object_inspection/nodes/when_multiline.rb +22 -0
  90. data/lib/super_diff/object_inspection/nodes/when_non_empty.rb +30 -0
  91. data/lib/super_diff/object_inspection/nodes/when_singleline.rb +24 -0
  92. data/lib/super_diff/operation_sequences.rb +9 -0
  93. data/lib/super_diff/operation_sequences/base.rb +1 -1
  94. data/lib/super_diff/operation_sequences/{object.rb → custom_object.rb} +4 -3
  95. data/lib/super_diff/operation_sequences/default_object.rb +25 -0
  96. data/lib/super_diff/operational_sequencer.rb +23 -18
  97. data/lib/super_diff/operational_sequencers.rb +12 -1
  98. data/lib/super_diff/operational_sequencers/array.rb +65 -62
  99. data/lib/super_diff/operational_sequencers/base.rb +18 -26
  100. data/lib/super_diff/operational_sequencers/custom_object.rb +35 -0
  101. data/lib/super_diff/operational_sequencers/{object.rb → default_object.rb} +21 -11
  102. data/lib/super_diff/operational_sequencers/hash.rb +8 -5
  103. data/lib/super_diff/operational_sequencers/{multi_line_string.rb → multiline_string.rb} +11 -6
  104. data/lib/super_diff/operations.rb +6 -0
  105. data/lib/super_diff/operations/binary_operation.rb +14 -34
  106. data/lib/super_diff/operations/unary_operation.rb +11 -2
  107. data/lib/super_diff/rails.rb +1 -0
  108. data/lib/super_diff/recursion_guard.rb +47 -0
  109. data/lib/super_diff/rspec-rails.rb +2 -0
  110. data/lib/super_diff/rspec.rb +52 -8
  111. data/lib/super_diff/rspec/augmented_matcher.rb +98 -0
  112. data/lib/super_diff/rspec/configuration.rb +31 -0
  113. data/lib/super_diff/rspec/differ.rb +60 -16
  114. data/lib/super_diff/rspec/differs.rb +13 -0
  115. data/lib/super_diff/rspec/differs/collection_containing_exactly.rb +23 -0
  116. data/lib/super_diff/rspec/differs/partial_array.rb +22 -0
  117. data/lib/super_diff/rspec/differs/partial_hash.rb +22 -0
  118. data/lib/super_diff/rspec/differs/partial_object.rb +22 -0
  119. data/lib/super_diff/rspec/matcher_text_builders.rb +24 -0
  120. data/lib/super_diff/rspec/matcher_text_builders/base.rb +155 -0
  121. data/lib/super_diff/rspec/matcher_text_builders/be_predicate.rb +78 -0
  122. data/lib/super_diff/rspec/matcher_text_builders/contain_exactly.rb +14 -0
  123. data/lib/super_diff/rspec/matcher_text_builders/match.rb +23 -0
  124. data/lib/super_diff/rspec/matcher_text_builders/raise_error.rb +13 -0
  125. data/lib/super_diff/rspec/matcher_text_builders/respond_to.rb +99 -0
  126. data/lib/super_diff/rspec/matcher_text_template.rb +240 -0
  127. data/lib/super_diff/rspec/monkey_patches.rb +601 -98
  128. data/lib/super_diff/rspec/object_inspection.rb +8 -0
  129. data/lib/super_diff/rspec/object_inspection/inspectors.rb +24 -0
  130. data/lib/super_diff/rspec/object_inspection/inspectors/collection_containing_exactly.rb +19 -0
  131. data/lib/super_diff/rspec/object_inspection/inspectors/partial_array.rb +22 -0
  132. data/lib/super_diff/rspec/object_inspection/inspectors/partial_hash.rb +21 -0
  133. data/lib/super_diff/rspec/object_inspection/inspectors/partial_object.rb +21 -0
  134. data/lib/super_diff/rspec/object_inspection/map_extension.rb +23 -0
  135. data/lib/super_diff/rspec/operational_sequencers.rb +22 -0
  136. data/lib/super_diff/rspec/operational_sequencers/collection_containing_exactly.rb +97 -0
  137. data/lib/super_diff/rspec/operational_sequencers/partial_array.rb +23 -0
  138. data/lib/super_diff/rspec/operational_sequencers/partial_hash.rb +32 -0
  139. data/lib/super_diff/rspec/operational_sequencers/partial_object.rb +64 -0
  140. data/lib/super_diff/version.rb +1 -1
  141. data/spec/examples.txt +328 -46
  142. data/spec/integration/rails/active_record_spec.rb +19 -0
  143. data/spec/integration/rails/hash_with_indifferent_access_spec.rb +19 -0
  144. data/spec/integration/rspec/be_falsey_matcher_spec.rb +53 -0
  145. data/spec/integration/rspec/be_matcher_spec.rb +565 -0
  146. data/spec/integration/rspec/be_nil_matcher_spec.rb +53 -0
  147. data/spec/integration/rspec/be_predicate_matcher_spec.rb +546 -0
  148. data/spec/integration/rspec/be_truthy_matcher_spec.rb +57 -0
  149. data/spec/integration/rspec/contain_exactly_matcher_spec.rb +368 -0
  150. data/spec/integration/rspec/eq_matcher_spec.rb +874 -0
  151. data/spec/integration/rspec/have_attributes_matcher_spec.rb +299 -0
  152. data/spec/integration/rspec/include_matcher_spec.rb +350 -0
  153. data/spec/integration/rspec/match_matcher_spec.rb +1258 -0
  154. data/spec/integration/rspec/raise_error_matcher_spec.rb +350 -0
  155. data/spec/integration/rspec/respond_to_matcher_spec.rb +994 -0
  156. data/spec/integration/rspec/unhandled_errors_spec.rb +94 -0
  157. data/spec/spec_helper.rb +19 -4
  158. data/spec/support/colorizer.rb +9 -0
  159. data/spec/support/command_runner.rb +4 -0
  160. data/spec/support/integration/helpers.rb +179 -0
  161. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +79 -41
  162. data/spec/support/models/a.rb +11 -0
  163. data/spec/support/models/active_record/person.rb +26 -0
  164. data/spec/support/models/active_record/shipping_address.rb +29 -0
  165. data/spec/support/models/customer.rb +24 -0
  166. data/spec/support/models/empty_class.rb +6 -0
  167. data/spec/support/models/item.rb +10 -0
  168. data/spec/support/models/order.rb +9 -0
  169. data/spec/support/models/person.rb +20 -0
  170. data/spec/support/models/player.rb +33 -0
  171. data/spec/support/models/shipping_address.rb +34 -0
  172. data/spec/support/ruby_versions.rb +7 -0
  173. data/spec/support/shared_examples/active_record.rb +338 -0
  174. data/spec/support/shared_examples/hash_with_indifferent_access.rb +233 -0
  175. data/spec/unit/equality_matcher_spec.rb +579 -171
  176. data/spec/unit/object_inspection_spec.rb +1092 -0
  177. data/spec/unit/rspec/matchers/be_compared_to_spec.rb +23 -0
  178. data/spec/unit/rspec/matchers/be_falsey_spec.rb +9 -0
  179. data/spec/unit/rspec/matchers/be_nil_spec.rb +9 -0
  180. data/spec/unit/rspec/matchers/be_predicate_spec.rb +31 -0
  181. data/spec/unit/rspec/matchers/be_spec.rb +17 -0
  182. data/spec/unit/rspec/matchers/be_truthy_spec.rb +9 -0
  183. data/spec/unit/rspec/matchers/contain_exactly_spec.rb +11 -0
  184. data/spec/unit/rspec/matchers/eq_spec.rb +9 -0
  185. data/spec/unit/rspec/matchers/have_attributes_spec.rb +11 -0
  186. data/spec/unit/rspec/matchers/include_spec.rb +21 -0
  187. data/spec/unit/rspec/matchers/match_spec.rb +9 -0
  188. data/spec/unit/rspec/matchers/raise_error_spec.rb +29 -0
  189. data/spec/unit/rspec/matchers/respond_to_spec.rb +78 -0
  190. data/super_diff.gemspec +4 -2
  191. metadata +231 -34
  192. data/lib/super_diff/csi/color_helper.rb +0 -52
  193. data/lib/super_diff/csi/eight_bit_sequence.rb +0 -27
  194. data/lib/super_diff/csi/four_bit_sequence.rb +0 -24
  195. data/lib/super_diff/csi/sequence.rb +0 -22
  196. data/lib/super_diff/csi/twenty_four_bit_sequence.rb +0 -27
  197. data/lib/super_diff/diff_formatters/multi_line_string.rb +0 -31
  198. data/lib/super_diff/differs/object.rb +0 -68
  199. data/lib/super_diff/equality_matchers/object.rb +0 -18
  200. data/lib/super_diff/value_inspection.rb +0 -11
  201. data/spec/integration/rspec_spec.rb +0 -261
  202. data/spec/support/color_helper.rb +0 -49
  203. data/spec/support/person.rb +0 -23
  204. data/spec/support/person_diff_formatter.rb +0 -15
  205. data/spec/support/person_operation_sequence.rb +0 -14
  206. data/spec/support/person_operational_sequencer.rb +0 -19
@@ -0,0 +1,1092 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe SuperDiff::ObjectInspection do
4
+ describe ".inspect" do
5
+ context "given nil" do
6
+ context "given as_single_line: true" do
7
+ it "returns nil, inspected" do
8
+ inspection = described_class.inspect(nil, as_single_line: true)
9
+ expect(inspection).to eq("nil")
10
+ end
11
+ end
12
+
13
+ context "given as_single_line: false" do
14
+ it "returns nil, inspected" do
15
+ inspection = described_class.inspect(nil, as_single_line: false)
16
+ expect(inspection).to eq("nil")
17
+ end
18
+ end
19
+ end
20
+
21
+ context "given true" do
22
+ context "given as_single_line: true" do
23
+ it "returns nil, inspected" do
24
+ inspection = described_class.inspect(nil, as_single_line: true)
25
+ expect(inspection).to eq("nil")
26
+ end
27
+ end
28
+
29
+ context "given as_single_line: false" do
30
+ it "returns nil, inspected" do
31
+ inspection = described_class.inspect(nil, as_single_line: false)
32
+ expect(inspection).to eq("nil")
33
+ end
34
+ end
35
+ end
36
+
37
+ context "given false" do
38
+ context "given as_single_line: false" do
39
+ it "returns false, inspected" do
40
+ inspection = described_class.inspect(false, as_single_line: false)
41
+ expect(inspection).to eq("false")
42
+ end
43
+ end
44
+
45
+ context "given as_single_line: false" do
46
+ it "returns false, inspected" do
47
+ inspection = described_class.inspect(false, as_single_line: false)
48
+ expect(inspection).to eq("false")
49
+ end
50
+ end
51
+ end
52
+
53
+ context "given a number" do
54
+ context "given as_single_line: true" do
55
+ it "returns the number as a string" do
56
+ inspection = described_class.inspect(3, as_single_line: true)
57
+ expect(inspection).to eq("3")
58
+ end
59
+ end
60
+
61
+ context "given as_single_line: false" do
62
+ it "returns the number as a string" do
63
+ inspection = described_class.inspect(3, as_single_line: false)
64
+ expect(inspection).to eq("3")
65
+ end
66
+ end
67
+ end
68
+
69
+ context "given a symbol" do
70
+ context "given as_single_line: true" do
71
+ it "returns the symbol, inspected" do
72
+ inspection = described_class.inspect(:foo, as_single_line: true)
73
+ expect(inspection).to eq(":foo")
74
+ end
75
+ end
76
+
77
+ context "given as_single_line: false" do
78
+ it "returns the symbol, inspected" do
79
+ inspection = described_class.inspect(:foo, as_single_line: false)
80
+ expect(inspection).to eq(":foo")
81
+ end
82
+ end
83
+ end
84
+
85
+ context "given a regex" do
86
+ context "given as_single_line: true" do
87
+ it "returns the regex, inspected" do
88
+ inspection = described_class.inspect(/foo/, as_single_line: true)
89
+ expect(inspection).to eq("/foo/")
90
+ end
91
+ end
92
+
93
+ context "given as_single_line: false" do
94
+ it "returns the regex, inspected" do
95
+ inspection = described_class.inspect(/foo/, as_single_line: false)
96
+ expect(inspection).to eq("/foo/")
97
+ end
98
+ end
99
+ end
100
+
101
+ context "given a single-line string" do
102
+ it "returns the string surrounded by quotes" do
103
+ inspection = described_class.inspect("Marty", as_single_line: true)
104
+ expect(inspection).to eq('"Marty"')
105
+ end
106
+ end
107
+
108
+ context "given a multi-line string" do
109
+ context "that does not contain color codes" do
110
+ it "returns the string surrounded by quotes, with newline characters escaped" do
111
+ inspection = described_class.inspect(
112
+ "This is a line\nAnd that's a line\nAnd there's a line too",
113
+ as_single_line: true,
114
+ )
115
+ expect(inspection).to eq(
116
+ %("This is a line\\nAnd that's a line\\nAnd there's a line too"),
117
+ )
118
+ end
119
+ end
120
+
121
+ context "that contains color codes" do
122
+ it "escapes the color codes" do
123
+ colors = [
124
+ SuperDiff::Csi::FourBitColor.new(:blue, layer: :foreground),
125
+ SuperDiff::Csi::EightBitColor.new(
126
+ red: 3,
127
+ green: 8,
128
+ blue: 4,
129
+ layer: :foreground,
130
+ ),
131
+ SuperDiff::Csi::TwentyFourBitColor.new(
132
+ red: 47,
133
+ green: 164,
134
+ blue: 59,
135
+ layer: :foreground,
136
+ ),
137
+ ]
138
+ string_to_inspect = [
139
+ colorize("This is a line", colors[0]),
140
+ colorize("And that's a line", colors[1]),
141
+ colorize("And there's a line too", colors[2]),
142
+ ].join("\n")
143
+
144
+ inspection = described_class.inspect(
145
+ string_to_inspect,
146
+ as_single_line: true,
147
+ )
148
+ # TODO: Figure out how to represent a colorized string inside of an
149
+ # already colorized string
150
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
151
+ "\\e[34mThis is a line\\e[0m\\n\\e[38;5;176mAnd that's a line\\e[0m\\n\\e[38;2;47;59;164mAnd there's a line too\\e[0m"
152
+ INSPECTION
153
+ end
154
+ end
155
+ end
156
+
157
+ context "given an array" do
158
+ context "containing only primitive values" do
159
+ context "given as_single_line: true" do
160
+ it "returns a representation of the array on a single line" do
161
+ inspection = described_class.inspect(
162
+ ["foo", 2, :baz],
163
+ as_single_line: true,
164
+ )
165
+ expect(inspection).to eq(%(["foo", 2, :baz]))
166
+ end
167
+ end
168
+
169
+ context "given as_single_line: false" do
170
+ it "returns a representation of the array across multiple lines" do
171
+ inspection = described_class.inspect(
172
+ ["foo", 2, :baz],
173
+ as_single_line: false,
174
+ )
175
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
176
+ [
177
+ "foo",
178
+ 2,
179
+ :baz
180
+ ]
181
+ INSPECTION
182
+ end
183
+ end
184
+ end
185
+
186
+ context "containing other arrays" do
187
+ context "given as_single_line: true" do
188
+ it "returns a representation of the array on a single line" do
189
+ inspection = described_class.inspect(
190
+ [
191
+ "foo",
192
+ ["bar", "baz"],
193
+ "qux",
194
+ ],
195
+ as_single_line: true,
196
+ )
197
+ expect(inspection).to eq(%(["foo", ["bar", "baz"], "qux"]))
198
+ end
199
+ end
200
+
201
+ context "given as_single_line: false" do
202
+ it "returns a representation of the array across multiple lines" do
203
+ inspection = described_class.inspect(
204
+ [
205
+ "foo",
206
+ ["bar", "baz"],
207
+ "qux",
208
+ ],
209
+ as_single_line: false,
210
+ )
211
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
212
+ [
213
+ "foo",
214
+ [
215
+ "bar",
216
+ "baz"
217
+ ],
218
+ "qux"
219
+ ]
220
+ INSPECTION
221
+ end
222
+ end
223
+ end
224
+
225
+ context "which is empty" do
226
+ context "given as_single_line: true" do
227
+ it "returns a representation of the array on a single line" do
228
+ inspection = described_class.inspect([], as_single_line: true)
229
+ expect(inspection).to eq(%([]))
230
+ end
231
+ end
232
+
233
+ context "given as_single_line: false" do
234
+ it "returns a representation of the array on a single line" do
235
+ inspection = described_class.inspect([], as_single_line: false)
236
+ expect(inspection).to eq(%([]))
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ context "given a hash" do
243
+ context "containing only primitive values" do
244
+ context "where all of the keys are symbols" do
245
+ context "given as_single_line: true" do
246
+ it "returns a representation of the hash on a single line" do
247
+ inspection = described_class.inspect(
248
+ # rubocop:disable Style/HashSyntax
249
+ { :foo => "bar", :baz => "qux" },
250
+ # rubocop:enable Style/HashSyntax
251
+ as_single_line: true,
252
+ )
253
+ expect(inspection).to eq(%({ foo: "bar", baz: "qux" }))
254
+ end
255
+ end
256
+
257
+ context "given as_single_line: false" do
258
+ it "returns a representation of the hash across multiple lines" do
259
+ inspection = described_class.inspect(
260
+ # rubocop:disable Style/HashSyntax
261
+ { :foo => "bar", :baz => "qux" },
262
+ # rubocop:enable Style/HashSyntax
263
+ as_single_line: false,
264
+ )
265
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
266
+ {
267
+ foo: "bar",
268
+ baz: "qux"
269
+ }
270
+ INSPECTION
271
+ end
272
+ end
273
+ end
274
+
275
+ context "where only some of the keys are symbols" do
276
+ context "given as_single_line: true" do
277
+ it "returns a representation of the hash on a single line" do
278
+ inspection = described_class.inspect(
279
+ { :foo => "bar", 2 => "baz" },
280
+ as_single_line: true,
281
+ )
282
+ expect(inspection).to eq(%({ :foo => "bar", 2 => "baz" }))
283
+ end
284
+ end
285
+
286
+ context "given as_single_line: false" do
287
+ it "returns a representation of the hash across multiple lines" do
288
+ inspection = described_class.inspect(
289
+ { :foo => "bar", 2 => "baz" },
290
+ as_single_line: false,
291
+ )
292
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
293
+ {
294
+ :foo => "bar",
295
+ 2 => "baz"
296
+ }
297
+ INSPECTION
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ context "containing other hashes" do
304
+ context "given as_single_line: true" do
305
+ it "returns a representation of the hash on a single line" do
306
+ # TODO: Update this with a key/value pair before AND after
307
+ value_to_inspect = {
308
+ # rubocop:disable Style/HashSyntax
309
+ :category_name => "Appliances",
310
+ :products_by_sku => {
311
+ "EMDL-2934" => { :id => 4, :name => "Jordan Air" },
312
+ "KDS-3912" => { :id => 8, :name => "Chevy Impala" },
313
+ },
314
+ :number_of_products => 2,
315
+ # rubocop:enable Style/HashSyntax
316
+ }
317
+ inspection = described_class.inspect(
318
+ value_to_inspect,
319
+ as_single_line: true,
320
+ )
321
+ # rubocop:disable Metrics/LineLength
322
+ expect(inspection).to eq(
323
+ %({ category_name: "Appliances", products_by_sku: { "EMDL-2934" => { id: 4, name: "Jordan Air" }, "KDS-3912" => { id: 8, name: "Chevy Impala" } }, number_of_products: 2 }),
324
+ )
325
+ # rubocop:enable Metrics/LineLength
326
+ end
327
+ end
328
+
329
+ context "given as_single_line: false" do
330
+ it "returns a representation of the array across multiple lines" do
331
+ value_to_inspect = {
332
+ # rubocop:disable Style/HashSyntax
333
+ :category_name => "Appliances",
334
+ :products_by_sku => {
335
+ "EMDL-2934" => { :id => 4, :name => "George Foreman Grill" },
336
+ "KDS-3912" => { :id => 8, :name => "Magic Bullet" },
337
+ },
338
+ :number_of_products => 2,
339
+ # rubocop:enable Style/HashSyntax
340
+ }
341
+ inspection = described_class.inspect(
342
+ value_to_inspect,
343
+ as_single_line: false,
344
+ )
345
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
346
+ {
347
+ category_name: "Appliances",
348
+ products_by_sku: {
349
+ "EMDL-2934" => {
350
+ id: 4,
351
+ name: "George Foreman Grill"
352
+ },
353
+ "KDS-3912" => {
354
+ id: 8,
355
+ name: "Magic Bullet"
356
+ }
357
+ },
358
+ number_of_products: 2
359
+ }
360
+ INSPECTION
361
+ end
362
+ end
363
+ end
364
+
365
+ context "which is empty" do
366
+ context "given as_single_line: true" do
367
+ it "returns a representation of the array on a single line" do
368
+ inspection = described_class.inspect({}, as_single_line: true)
369
+ expect(inspection).to eq(%({}))
370
+ end
371
+ end
372
+
373
+ context "given as_single_line: false" do
374
+ it "returns a representation of the array on a single line" do
375
+ inspection = described_class.inspect({}, as_single_line: false)
376
+ expect(inspection).to eq(%({}))
377
+ end
378
+ end
379
+ end
380
+ end
381
+
382
+ context "given a class" do
383
+ context "given as_single_line: true" do
384
+ it "returns a representation of the object on a single line" do
385
+ inspection = described_class.inspect(
386
+ SuperDiff::Test::Person,
387
+ as_single_line: true,
388
+ )
389
+ expect(inspection).to eq("SuperDiff::Test::Person")
390
+ end
391
+ end
392
+
393
+ context "given as_single_line: false" do
394
+ it "returns a representation of the object on a single line" do
395
+ inspection = described_class.inspect(
396
+ SuperDiff::Test::Person,
397
+ as_single_line: false,
398
+ )
399
+ expect(inspection).to eq("SuperDiff::Test::Person")
400
+ end
401
+ end
402
+ end
403
+
404
+ context "given a custom object" do
405
+ context "containing only primitive values" do
406
+ context "given as_single_line: true" do
407
+ it "returns a representation of the object on a single line" do
408
+ inspection = described_class.inspect(
409
+ SuperDiff::Test::Person.new(name: "Doc", age: 58),
410
+ as_single_line: true,
411
+ )
412
+ expect(inspection).to eq(
413
+ %(#<SuperDiff::Test::Person name: "Doc", age: 58>),
414
+ )
415
+ end
416
+ end
417
+
418
+ context "given as_single_line: false" do
419
+ it "returns a representation of the object across multiple lines" do
420
+ inspection = described_class.inspect(
421
+ SuperDiff::Test::Person.new(name: "Doc", age: 58),
422
+ as_single_line: false,
423
+ )
424
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
425
+ #<SuperDiff::Test::Person {
426
+ name: "Doc",
427
+ age: 58
428
+ }>
429
+ INSPECTION
430
+ end
431
+ end
432
+ end
433
+
434
+ context "containing other custom objects" do
435
+ context "given as_single_line: true" do
436
+ it "returns a representation of the object on a single line" do
437
+ inspection = described_class.inspect(
438
+ SuperDiff::Test::Customer.new(
439
+ name: "Marty McFly",
440
+ shipping_address: SuperDiff::Test::ShippingAddress.new(
441
+ line_1: "123 Main St.",
442
+ line_2: "",
443
+ city: "Hill Valley",
444
+ state: "CA",
445
+ zip: "90382",
446
+ ),
447
+ phone: "111-222-3333",
448
+ ),
449
+ as_single_line: true,
450
+ )
451
+ expect(inspection).to eq(
452
+ # rubocop:disable Metrics/LineLength
453
+ %(#<SuperDiff::Test::Customer name: "Marty McFly", shipping_address: #<SuperDiff::Test::ShippingAddress line_1: "123 Main St.", line_2: "", city: "Hill Valley", state: "CA", zip: "90382">, phone: "111-222-3333">),
454
+ # rubocop:enable Metrics/LineLength
455
+ )
456
+ end
457
+ end
458
+
459
+ context "given as_single_line: false" do
460
+ it "returns a representation of the object across multiple lines" do
461
+ inspection = described_class.inspect(
462
+ SuperDiff::Test::Customer.new(
463
+ name: "Marty McFly",
464
+ shipping_address: SuperDiff::Test::ShippingAddress.new(
465
+ line_1: "123 Main St.",
466
+ line_2: "",
467
+ city: "Hill Valley",
468
+ state: "CA",
469
+ zip: "90382",
470
+ ),
471
+ phone: "111-222-3333",
472
+ ),
473
+ as_single_line: false,
474
+ )
475
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
476
+ #<SuperDiff::Test::Customer {
477
+ name: "Marty McFly",
478
+ shipping_address: #<SuperDiff::Test::ShippingAddress {
479
+ line_1: "123 Main St.",
480
+ line_2: "",
481
+ city: "Hill Valley",
482
+ state: "CA",
483
+ zip: "90382"
484
+ }>,
485
+ phone: "111-222-3333"
486
+ }>
487
+ INSPECTION
488
+ end
489
+ end
490
+ end
491
+ end
492
+
493
+ context "given a non-custom object" do
494
+ context "containing only primitive values" do
495
+ context "given as_single_line: true" do
496
+ it "returns a representation of the object on a single line" do
497
+ inspection = described_class.inspect(
498
+ SuperDiff::Test::Item.new(
499
+ name: "mac and cheese",
500
+ quantity: 2,
501
+ ),
502
+ as_single_line: true,
503
+ )
504
+ expect(inspection).to match(
505
+ # rubocop:disable Metrics/LineLength
506
+ /\A#<SuperDiff::Test::Item:0x[a-z0-9]+ @name="mac and cheese", @quantity=2>\Z/,
507
+ # rubocop:enable Metrics/LineLength
508
+ )
509
+ end
510
+ end
511
+
512
+ context "given as_single_line: false" do
513
+ it "returns a representation of the object across multiple lines" do
514
+ inspection = described_class.inspect(
515
+ SuperDiff::Test::Item.new(
516
+ name: "mac and cheese",
517
+ quantity: 2,
518
+ ),
519
+ as_single_line: false,
520
+ )
521
+ regexp = <<~INSPECTION.rstrip
522
+ #<SuperDiff::Test::Item:0x[a-z0-9]+ \\{
523
+ @name="mac and cheese",
524
+ @quantity=2
525
+ \\}>
526
+ INSPECTION
527
+ expect(inspection).to match(/\A#{regexp}\Z/)
528
+ end
529
+ end
530
+ end
531
+
532
+ context "containing other custom objects" do
533
+ context "given as_single_line: true" do
534
+ it "returns a representation of the object on a single line" do
535
+ inspection = described_class.inspect(
536
+ SuperDiff::Test::Order.new([
537
+ SuperDiff::Test::Item.new(name: "ham", quantity: 1),
538
+ SuperDiff::Test::Item.new(name: "eggs", quantity: 2),
539
+ SuperDiff::Test::Item.new(name: "cheese", quantity: 1),
540
+ ]),
541
+ as_single_line: true,
542
+ )
543
+ expect(inspection).to match(
544
+ # rubocop:disable Metrics/LineLength
545
+ /\A#<SuperDiff::Test::Order:0x[a-z0-9]+ @items=\[#<SuperDiff::Test::Item:0x[a-z0-9]+ @name="ham", @quantity=1>, #<SuperDiff::Test::Item:0x[a-z0-9]+ @name="eggs", @quantity=2>, #<SuperDiff::Test::Item:0x[a-z0-9]+ @name="cheese", @quantity=1>\]>\Z/,
546
+ # rubocop:enable Metrics/LineLength
547
+ )
548
+ end
549
+ end
550
+
551
+ context "given as_single_line: false" do
552
+ it "returns a representation of the object across multiple lines" do
553
+ inspection = described_class.inspect(
554
+ SuperDiff::Test::Order.new([
555
+ SuperDiff::Test::Item.new(name: "ham", quantity: 1),
556
+ SuperDiff::Test::Item.new(name: "eggs", quantity: 2),
557
+ SuperDiff::Test::Item.new(name: "cheese", quantity: 1),
558
+ ]),
559
+ as_single_line: false,
560
+ )
561
+ regexp = <<~INSPECTION.rstrip
562
+ #<SuperDiff::Test::Order:0x[a-z0-9]+ \\{
563
+ @items=\\[
564
+ #<SuperDiff::Test::Item:0x[a-z0-9]+ \\{
565
+ @name="ham",
566
+ @quantity=1
567
+ \\}>,
568
+ #<SuperDiff::Test::Item:0x[a-z0-9]+ \\{
569
+ @name="eggs",
570
+ @quantity=2
571
+ \\}>,
572
+ #<SuperDiff::Test::Item:0x[a-z0-9]+ \\{
573
+ @name="cheese",
574
+ @quantity=1
575
+ \\}>
576
+ \\]
577
+ }>
578
+ INSPECTION
579
+ expect(inspection).to match(/\A#{regexp}\Z/)
580
+ end
581
+ end
582
+ end
583
+
584
+ context "which is empty" do
585
+ context "given as_single_line: true" do
586
+ it "returns a representation of the array on a single line" do
587
+ inspection = described_class.inspect(
588
+ SuperDiff::Test::EmptyClass.new,
589
+ as_single_line: true,
590
+ )
591
+ expect(inspection).to match(
592
+ /#<SuperDiff::Test::EmptyClass:0x[a-z0-9]+>/
593
+ )
594
+ end
595
+ end
596
+
597
+ context "given as_single_line: false" do
598
+ it "returns a representation of the array on a single line" do
599
+ inspection = described_class.inspect(
600
+ SuperDiff::Test::EmptyClass.new,
601
+ as_single_line: false,
602
+ )
603
+ expect(inspection).to match(
604
+ /#<SuperDiff::Test::EmptyClass:0x[a-z0-9]+>/
605
+ )
606
+ end
607
+ end
608
+ end
609
+ end
610
+
611
+ context "given a partial hash" do
612
+ context "given as_single_line: true" do
613
+ it "returns a representation of the partial hash on a single line" do
614
+ inspection = described_class.inspect(
615
+ a_hash_including(foo: "bar", baz: "qux"),
616
+ as_single_line: true,
617
+ )
618
+
619
+ expect(inspection).to eq(
620
+ %(#<a hash including (foo: "bar", baz: "qux")>),
621
+ )
622
+ end
623
+ end
624
+
625
+ context "given as_single_line: false" do
626
+ it "returns a representation of the partial hash across multiple lines" do
627
+ inspection = described_class.inspect(
628
+ a_hash_including(foo: "bar", baz: "qux"),
629
+ as_single_line: false,
630
+ )
631
+
632
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
633
+ #<a hash including (
634
+ foo: "bar",
635
+ baz: "qux"
636
+ )>
637
+ INSPECTION
638
+ end
639
+ end
640
+ end
641
+
642
+ context "given a partial array" do
643
+ context "given as_single_line: true" do
644
+ it "returns a representation of the partial hash on a single line" do
645
+ inspection = described_class.inspect(
646
+ a_collection_including(1, 2, 3),
647
+ as_single_line: true,
648
+ )
649
+
650
+ expect(inspection).to eq(
651
+ %(#<a collection including (1, 2, 3)>),
652
+ )
653
+ end
654
+ end
655
+
656
+ context "given as_single_line: false" do
657
+ it "returns a representation of the partial hash across multiple lines" do
658
+ inspection = described_class.inspect(
659
+ a_collection_including(1, 2, 3),
660
+ as_single_line: false,
661
+ )
662
+
663
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
664
+ #<a collection including (
665
+ 1,
666
+ 2,
667
+ 3
668
+ )>
669
+ INSPECTION
670
+ end
671
+ end
672
+ end
673
+
674
+ context "given a partial object" do
675
+ context "given as_single_line: true" do
676
+ it "returns a representation of the partial object on a single line" do
677
+ inspection = described_class.inspect(
678
+ an_object_having_attributes(foo: "bar", baz: "qux"),
679
+ as_single_line: true,
680
+ )
681
+
682
+ expect(inspection).to eq(
683
+ %(#<an object having attributes (foo: "bar", baz: "qux")>),
684
+ )
685
+ end
686
+ end
687
+
688
+ context "given as_single_line: false" do
689
+ it "returns a representation of the partial object across multiple lines" do
690
+ inspection = described_class.inspect(
691
+ an_object_having_attributes(foo: "bar", baz: "qux"),
692
+ as_single_line: false,
693
+ )
694
+
695
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
696
+ #<an object having attributes (
697
+ foo: "bar",
698
+ baz: "qux"
699
+ )>
700
+ INSPECTION
701
+ end
702
+ end
703
+ end
704
+
705
+ context "given a fuzzy object matching a collection containing exactly <something>" do
706
+ context "given as_single_line: true" do
707
+ it "returns a representation of the partial object on a single line" do
708
+ inspection = described_class.inspect(
709
+ a_collection_containing_exactly("foo", "bar", "baz"),
710
+ as_single_line: true,
711
+ )
712
+
713
+ expect(inspection).to eq(
714
+ %(#<a collection containing exactly ("foo", "bar", "baz")>),
715
+ )
716
+ end
717
+ end
718
+
719
+ context "given as_single_line: false" do
720
+ it "returns a representation of the partial object across multiple lines" do
721
+ inspection = described_class.inspect(
722
+ a_collection_containing_exactly("foo", "bar", "baz"),
723
+ as_single_line: false,
724
+ )
725
+
726
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
727
+ #<a collection containing exactly (
728
+ "foo",
729
+ "bar",
730
+ "baz"
731
+ )>
732
+ INSPECTION
733
+ end
734
+ end
735
+ end
736
+
737
+ context "given a Double" do
738
+ context "that is anonymous" do
739
+ context "given as_single_line: true" do
740
+ it "returns a representation of the partial object on a single line" do
741
+ inspection = described_class.inspect(
742
+ double(foo: "bar", baz: "qux"),
743
+ as_single_line: true,
744
+ )
745
+
746
+ expect(inspection).to eq("#<Double (anonymous)>")
747
+ end
748
+ end
749
+
750
+ context "given as_single_line: false" do
751
+ it "returns a representation of the partial object across multiple lines" do
752
+ inspection = described_class.inspect(
753
+ double(foo: "bar", baz: "qux"),
754
+ as_single_line: false,
755
+ )
756
+
757
+ expect(inspection).to eq("#<Double (anonymous)>")
758
+ end
759
+ end
760
+ end
761
+ end
762
+
763
+ context "given an ActiveRecord object" do
764
+ context "given as_single_line: true" do
765
+ it "returns a representation of the object on a single line" do
766
+ inspection = described_class.inspect(
767
+ SuperDiff::Test::Models::ActiveRecord::Person.new(
768
+ name: "Elliot",
769
+ age: 31,
770
+ ),
771
+ as_single_line: true,
772
+ )
773
+
774
+ expect(inspection).to eq(
775
+ %(#<SuperDiff::Test::Models::ActiveRecord::Person id: nil, age: 31, name: "Elliot">)
776
+ )
777
+ end
778
+ end
779
+
780
+ context "given as_single_line: false" do
781
+ it "returns a representation of the object across multiple lines" do
782
+ inspection = described_class.inspect(
783
+ SuperDiff::Test::Models::ActiveRecord::Person.new(
784
+ name: "Elliot",
785
+ age: 31,
786
+ ),
787
+ as_single_line: false,
788
+ )
789
+
790
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
791
+ #<SuperDiff::Test::Models::ActiveRecord::Person {
792
+ id: nil,
793
+ age: 31,
794
+ name: "Elliot"
795
+ }>
796
+ INSPECTION
797
+ end
798
+ end
799
+ end
800
+
801
+ context "given an ActiveRecord::Relation object" do
802
+ context "given as_single_line: true" do
803
+ it "returns a representation of the Relation on a single line" do
804
+ SuperDiff::Test::Models::ActiveRecord::Person.create!(
805
+ name: "Marty",
806
+ age: 19,
807
+ )
808
+ SuperDiff::Test::Models::ActiveRecord::Person.create!(
809
+ name: "Jennifer",
810
+ age: 17,
811
+ )
812
+
813
+ inspection = described_class.inspect(
814
+ SuperDiff::Test::Models::ActiveRecord::Person.all,
815
+ as_single_line: true,
816
+ )
817
+
818
+ expect(inspection).to eq(
819
+ %(#<ActiveRecord::Relation [#<SuperDiff::Test::Models::ActiveRecord::Person id: 1, age: 19, name: "Marty">, #<SuperDiff::Test::Models::ActiveRecord::Person id: 2, age: 17, name: "Jennifer">]>)
820
+ )
821
+ end
822
+ end
823
+
824
+ context "given as_single_line: false" do
825
+ it "returns a representation of the Relation across multiple lines" do
826
+ SuperDiff::Test::Models::ActiveRecord::Person.create!(
827
+ name: "Marty",
828
+ age: 19,
829
+ )
830
+ SuperDiff::Test::Models::ActiveRecord::Person.create!(
831
+ name: "Jennifer",
832
+ age: 17,
833
+ )
834
+
835
+ inspection = described_class.inspect(
836
+ SuperDiff::Test::Models::ActiveRecord::Person.all,
837
+ as_single_line: false,
838
+ )
839
+
840
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
841
+ #<ActiveRecord::Relation [
842
+ #<SuperDiff::Test::Models::ActiveRecord::Person {
843
+ id: 1,
844
+ age: 19,
845
+ name: "Marty"
846
+ }>,
847
+ #<SuperDiff::Test::Models::ActiveRecord::Person {
848
+ id: 2,
849
+ age: 17,
850
+ name: "Jennifer"
851
+ }>
852
+ ]>
853
+ INSPECTION
854
+ end
855
+ end
856
+ end
857
+
858
+ context "given a HashWithIndifferentAccess" do
859
+ context "given as_single_line: true" do
860
+ it "returns a representation of the object on a single line" do
861
+ inspection = described_class.inspect(
862
+ HashWithIndifferentAccess.new({
863
+ line_1: "123 Main St.",
864
+ city: "Hill Valley",
865
+ state: "CA",
866
+ zip: "90382",
867
+ }),
868
+ as_single_line: true,
869
+ )
870
+
871
+ expect(inspection).to eq(
872
+ %(#<HashWithIndifferentAccess { "line_1" => "123 Main St.", "city" => "Hill Valley", "state" => "CA", "zip" => "90382" }>)
873
+ )
874
+ end
875
+ end
876
+
877
+ context "given as_single_line: false" do
878
+ it "returns a representation of the object across multiple lines" do
879
+ inspection = described_class.inspect(
880
+ HashWithIndifferentAccess.new({
881
+ line_1: "123 Main St.",
882
+ city: "Hill Valley",
883
+ state: "CA",
884
+ zip: "90382",
885
+ }),
886
+ as_single_line: false,
887
+ )
888
+
889
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
890
+ #<HashWithIndifferentAccess {
891
+ "line_1" => "123 Main St.",
892
+ "city" => "Hill Valley",
893
+ "state" => "CA",
894
+ "zip" => "90382"
895
+ }>
896
+ INSPECTION
897
+ end
898
+ end
899
+ end
900
+
901
+ context "given a combination of all kinds of values" do
902
+ context "given as_single_line: true" do
903
+ it "returns a representation of the object on a single line" do
904
+ inspection = described_class.inspect(
905
+ {
906
+ state: :down,
907
+ errors: [
908
+ "Container A-234 is partially damaged",
909
+ "Vessel B042 was attacked by raccoons",
910
+ "Product FDK-3429 is out of stock",
911
+ ],
912
+ mission_critical: true,
913
+ serviceable: false,
914
+ outstanding_orders: [
915
+ SuperDiff::Test::Order.new([
916
+ SuperDiff::Test::Item.new(name: "ham", quantity: 1),
917
+ SuperDiff::Test::Item.new(name: "eggs", quantity: 2),
918
+ SuperDiff::Test::Item.new(name: "cheese", quantity: 1),
919
+ ]),
920
+ ],
921
+ customers: [
922
+ SuperDiff::Test::Customer.new(
923
+ name: "Marty McFly",
924
+ shipping_address: SuperDiff::Test::ShippingAddress.new(
925
+ line_1: "123 Baltic Ave.",
926
+ line_2: "",
927
+ city: "Hill Valley",
928
+ state: "CA",
929
+ zip: "90382",
930
+ ),
931
+ phone: "111-111-1111",
932
+ ),
933
+ SuperDiff::Test::Customer.new(
934
+ name: "Doc Brown",
935
+ shipping_address: SuperDiff::Test::ShippingAddress.new(
936
+ line_1: "456 Park Place",
937
+ line_2: "",
938
+ city: "Beverly Hills",
939
+ state: "CA",
940
+ zip: "90210",
941
+ ),
942
+ phone: "222-222-2222",
943
+ ),
944
+ ],
945
+ },
946
+ as_single_line: true,
947
+ )
948
+ expect(inspection).to match(
949
+ # rubocop:disable Metrics/LineLength
950
+ /\A\{ state: :down, errors: \["Container A-234 is partially damaged", "Vessel B042 was attacked by raccoons", "Product FDK-3429 is out of stock"\], mission_critical: true, serviceable: false, outstanding_orders: \[#<SuperDiff::Test::Order:0x[a-z0-9]+ @items=\[#<SuperDiff::Test::Item:0x[a-z0-9]+ @name="ham", @quantity=1>, #<SuperDiff::Test::Item:0x[a-z0-9]+ @name="eggs", @quantity=2>, #<SuperDiff::Test::Item:0x[a-z0-9]+ @name="cheese", @quantity=1>\]>\], customers: \[#<SuperDiff::Test::Customer name: "Marty McFly", shipping_address: #<SuperDiff::Test::ShippingAddress line_1: "123 Baltic Ave.", line_2: "", city: "Hill Valley", state: "CA", zip: "90382">, phone: "111-111-1111">, #<SuperDiff::Test::Customer name: "Doc Brown", shipping_address: #<SuperDiff::Test::ShippingAddress line_1: "456 Park Place", line_2: "", city: "Beverly Hills", state: "CA", zip: "90210">, phone: "222-222-2222">\] \}\Z/,
951
+ # rubocop:enable Metrics/LineLength
952
+ )
953
+ end
954
+ end
955
+
956
+ context "given as_single_line: false" do
957
+ it "returns a representation of the object across multiple lines" do
958
+ inspection = described_class.inspect(
959
+ {
960
+ state: :down,
961
+ errors: [
962
+ "Container A-234 is partially damaged",
963
+ "Vessel B042 was attacked by raccoons",
964
+ "Product FDK-3429 is out of stock",
965
+ ],
966
+ mission_critical: true,
967
+ serviceable: false,
968
+ outstanding_orders: [
969
+ SuperDiff::Test::Order.new([
970
+ SuperDiff::Test::Item.new(name: "ham", quantity: 1),
971
+ SuperDiff::Test::Item.new(name: "eggs", quantity: 2),
972
+ SuperDiff::Test::Item.new(name: "cheese", quantity: 1),
973
+ ]),
974
+ ],
975
+ customers: [
976
+ SuperDiff::Test::Customer.new(
977
+ name: "Marty McFly",
978
+ shipping_address: SuperDiff::Test::ShippingAddress.new(
979
+ line_1: "123 Baltic Ave.",
980
+ line_2: "",
981
+ city: "Hill Valley",
982
+ state: "CA",
983
+ zip: "90382",
984
+ ),
985
+ phone: "111-111-1111",
986
+ ),
987
+ SuperDiff::Test::Customer.new(
988
+ name: "Doc Brown",
989
+ shipping_address: SuperDiff::Test::ShippingAddress.new(
990
+ line_1: "456 Park Place",
991
+ line_2: "",
992
+ city: "Beverly Hills",
993
+ state: "CA",
994
+ zip: "90210",
995
+ ),
996
+ phone: "222-222-2222",
997
+ ),
998
+ ],
999
+ },
1000
+ as_single_line: false,
1001
+ )
1002
+ regexp = <<~INSPECTION.rstrip
1003
+ \\{
1004
+ state: :down,
1005
+ errors: \\[
1006
+ "Container A-234 is partially damaged",
1007
+ "Vessel B042 was attacked by raccoons",
1008
+ "Product FDK-3429 is out of stock"
1009
+ \\],
1010
+ mission_critical: true,
1011
+ serviceable: false,
1012
+ outstanding_orders: \\[
1013
+ #<SuperDiff::Test::Order:0x[a-z0-9]+ \\{
1014
+ @items=\\[
1015
+ #<SuperDiff::Test::Item:0x[a-z0-9]+ \\{
1016
+ @name="ham",
1017
+ @quantity=1
1018
+ \\}>,
1019
+ #<SuperDiff::Test::Item:0x[a-z0-9]+ \\{
1020
+ @name="eggs",
1021
+ @quantity=2
1022
+ \\}>,
1023
+ #<SuperDiff::Test::Item:0x[a-z0-9]+ \\{
1024
+ @name="cheese",
1025
+ @quantity=1
1026
+ \\}>
1027
+ \\]
1028
+ \\}>
1029
+ \\],
1030
+ customers: \\[
1031
+ #<SuperDiff::Test::Customer \\{
1032
+ name: "Marty McFly",
1033
+ shipping_address: #<SuperDiff::Test::ShippingAddress \\{
1034
+ line_1: "123 Baltic Ave.",
1035
+ line_2: "",
1036
+ city: "Hill Valley",
1037
+ state: "CA",
1038
+ zip: "90382"
1039
+ \\}>,
1040
+ phone: "111-111-1111"
1041
+ \\}>,
1042
+ #<SuperDiff::Test::Customer \\{
1043
+ name: "Doc Brown",
1044
+ shipping_address: #<SuperDiff::Test::ShippingAddress \\{
1045
+ line_1: "456 Park Place",
1046
+ line_2: "",
1047
+ city: "Beverly Hills",
1048
+ state: "CA",
1049
+ zip: "90210"
1050
+ \\}>,
1051
+ phone: "222-222-2222"
1052
+ \\}>
1053
+ \\]
1054
+ \\}
1055
+ INSPECTION
1056
+ expect(inspection).to match(/\A#{regexp}\Z/)
1057
+ end
1058
+ end
1059
+ end
1060
+ end
1061
+
1062
+ context "given a data structure that refers to itself somewhere inside of it" do
1063
+ context "given as_single_line: true" do
1064
+ it "replaces the reference with ∙∙∙" do
1065
+ value = ["a", "b", "c"]
1066
+ value.insert(1, value)
1067
+ inspection = described_class.inspect(value, as_single_line: true)
1068
+ expect(inspection).to eq(%(["a", ∙∙∙, "b", "c"]))
1069
+ end
1070
+ end
1071
+
1072
+ context "given as_single_line: false" do
1073
+ it "replaces the reference with ∙∙∙" do
1074
+ value = ["a", "b", "c"]
1075
+ value.insert(1, value)
1076
+ inspection = described_class.inspect(value, as_single_line: false)
1077
+ expect(inspection).to eq(<<~INSPECTION.rstrip)
1078
+ [
1079
+ "a",
1080
+ ∙∙∙,
1081
+ "b",
1082
+ "c"
1083
+ ]
1084
+ INSPECTION
1085
+ end
1086
+ end
1087
+ end
1088
+
1089
+ def colorize(*args, **opts, &block)
1090
+ SuperDiff::Helpers.style(*args, **opts, &block).to_s.chomp
1091
+ end
1092
+ end