super_diff 0.1.0 → 0.2.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 (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,57 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Integration with RSpec's #be_truthy matcher", type: :integration do
4
+ it "produces the correct failure message when used in the positive" do
5
+ as_both_colored_and_uncolored do |color_enabled|
6
+ program =
7
+ make_plain_test_program(<<~TEST.strip, color_enabled: color_enabled)
8
+ expect(nil).to be_truthy
9
+ TEST
10
+
11
+ expected_output = build_expected_output(
12
+ color_enabled: color_enabled,
13
+ snippet: %|expect(nil).to be_truthy|,
14
+ expectation: proc {
15
+ line do
16
+ plain "Expected "
17
+ beta %|nil|
18
+ plain " to be "
19
+ alpha %|truthy|
20
+ plain "."
21
+ end
22
+ },
23
+ )
24
+
25
+ expect(program).
26
+ to produce_output_when_run(expected_output).
27
+ in_color(color_enabled)
28
+ end
29
+ end
30
+
31
+ it "produces the correct failure message when used in the negative" do
32
+ as_both_colored_and_uncolored do |color_enabled|
33
+ program =
34
+ make_plain_test_program(<<~TEST.strip, color_enabled: color_enabled)
35
+ expect(true).not_to be_truthy
36
+ TEST
37
+
38
+ expected_output = build_expected_output(
39
+ color_enabled: color_enabled,
40
+ snippet: %|expect(true).not_to be_truthy|,
41
+ expectation: proc {
42
+ line do
43
+ plain "Expected "
44
+ beta %|true|
45
+ plain " not to be "
46
+ alpha %|truthy|
47
+ plain "."
48
+ end
49
+ },
50
+ )
51
+
52
+ expect(program).
53
+ to produce_output_when_run(expected_output).
54
+ in_color(color_enabled)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,368 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Integration with RSpec's #contain_exactly matcher", type: :integration do
4
+ context "when a few number of values are given" do
5
+ it "produces the correct failure message when used in the positive" do
6
+ as_both_colored_and_uncolored do |color_enabled|
7
+ snippet = <<~TEST.strip
8
+ expected = ["Einie", "Marty"]
9
+ actual = ["Marty", "Jennifer", "Doc"]
10
+ expect(actual).to contain_exactly(*expected)
11
+ TEST
12
+ program = make_plain_test_program(
13
+ snippet,
14
+ color_enabled: color_enabled,
15
+ )
16
+
17
+ expected_output = build_expected_output(
18
+ color_enabled: color_enabled,
19
+ snippet: %|expect(actual).to contain_exactly(*expected)|,
20
+ expectation: proc {
21
+ line do
22
+ plain "Expected "
23
+ beta %|["Marty", "Jennifer", "Doc"]|
24
+ plain " to contain exactly "
25
+ alpha %|"Einie"|
26
+ plain " and "
27
+ alpha %|"Marty"|
28
+ plain "."
29
+ end
30
+ },
31
+ diff: proc {
32
+ plain_line %| [|
33
+ plain_line %| "Marty",|
34
+ plain_line %| "Jennifer",|
35
+ plain_line %| "Doc",|
36
+ alpha_line %|- "Einie"|
37
+ plain_line %| ]|
38
+ },
39
+ )
40
+
41
+ expect(program).
42
+ to produce_output_when_run(expected_output).
43
+ in_color(color_enabled)
44
+ end
45
+ end
46
+
47
+ it "produces the correct failure message when used in the negative" do
48
+ as_both_colored_and_uncolored do |color_enabled|
49
+ snippet = <<~TEST.strip
50
+ values = ["Einie", "Marty"]
51
+ expect(values).not_to contain_exactly(*values)
52
+ TEST
53
+ program = make_plain_test_program(
54
+ snippet,
55
+ color_enabled: color_enabled,
56
+ )
57
+
58
+ expected_output = build_expected_output(
59
+ color_enabled: color_enabled,
60
+ snippet: %|expect(values).not_to contain_exactly(*values)|,
61
+ expectation: proc {
62
+ line do
63
+ plain "Expected "
64
+ beta %|["Einie", "Marty"]|
65
+ plain " not to contain exactly "
66
+ alpha %|"Einie"|
67
+ plain " and "
68
+ alpha %|"Marty"|
69
+ plain "."
70
+ end
71
+ },
72
+ )
73
+
74
+ expect(program).
75
+ to produce_output_when_run(expected_output).
76
+ in_color(color_enabled)
77
+ end
78
+ end
79
+ end
80
+
81
+ context "when a large number of values are given" do
82
+ context "and they are only simple strings" do
83
+ it "produces the correct failure message when used in the positive" do
84
+ as_both_colored_and_uncolored do |color_enabled|
85
+ snippet = <<~TEST.strip
86
+ expected = [
87
+ "Doc Brown",
88
+ "Marty McFly",
89
+ "Biff Tannen",
90
+ "George McFly",
91
+ "Lorraine McFly"
92
+ ]
93
+ actual = [
94
+ "Marty McFly",
95
+ "Doc Brown",
96
+ "Einie",
97
+ "Lorraine McFly"
98
+ ]
99
+ expect(actual).to contain_exactly(*expected)
100
+ TEST
101
+ program = make_plain_test_program(
102
+ snippet,
103
+ color_enabled: color_enabled,
104
+ )
105
+
106
+ expected_output = build_expected_output(
107
+ color_enabled: color_enabled,
108
+ snippet: %|expect(actual).to contain_exactly(*expected)|,
109
+ expectation: proc {
110
+ line do
111
+ plain " Expected "
112
+ beta %|["Marty McFly", "Doc Brown", "Einie", "Lorraine McFly"]|
113
+ end
114
+
115
+ line do
116
+ plain "to contain exactly "
117
+ alpha %|"Doc Brown"|
118
+ plain ", "
119
+ alpha %|"Marty McFly"|
120
+ plain ", "
121
+ alpha %|"Biff Tannen"|
122
+ plain ", "
123
+ alpha %|"George McFly"|
124
+ plain " and "
125
+ alpha %|"Lorraine McFly"|
126
+ end
127
+ },
128
+ diff: proc {
129
+ plain_line %| [|
130
+ plain_line %| "Marty McFly",|
131
+ plain_line %| "Doc Brown",|
132
+ plain_line %| "Einie",|
133
+ plain_line %| "Lorraine McFly",|
134
+ alpha_line %|- "Biff Tannen",|
135
+ alpha_line %|- "George McFly"|
136
+ plain_line %| ]|
137
+ },
138
+ )
139
+
140
+ expect(program).
141
+ to produce_output_when_run(expected_output).
142
+ in_color(color_enabled)
143
+ end
144
+ end
145
+
146
+ it "produces the correct failure message when used in the negative" do
147
+ as_both_colored_and_uncolored do |color_enabled|
148
+ snippet = <<~TEST.strip
149
+ values = [
150
+ "Marty McFly",
151
+ "Doc Brown",
152
+ "Einie",
153
+ "Lorraine McFly"
154
+ ]
155
+ expect(values).not_to contain_exactly(*values)
156
+ TEST
157
+ program = make_plain_test_program(
158
+ snippet,
159
+ color_enabled: color_enabled,
160
+ )
161
+
162
+ expected_output = build_expected_output(
163
+ color_enabled: color_enabled,
164
+ snippet: %|expect(values).not_to contain_exactly(*values)|,
165
+ newline_before_expectation: true,
166
+ expectation: proc {
167
+ line do
168
+ plain " Expected "
169
+ beta %|["Marty McFly", "Doc Brown", "Einie", "Lorraine McFly"]|
170
+ end
171
+
172
+ line do
173
+ plain "not to contain exactly "
174
+ alpha %|"Marty McFly"|
175
+ plain ", "
176
+ alpha %|"Doc Brown"|
177
+ plain ", "
178
+ alpha %|"Einie"|
179
+ plain " and "
180
+ alpha %|"Lorraine McFly"|
181
+ end
182
+ },
183
+ )
184
+
185
+ expect(program).
186
+ to produce_output_when_run(expected_output).
187
+ in_color(color_enabled)
188
+ end
189
+ end
190
+ end
191
+
192
+ context "and some of them are regexen" do
193
+ it "produces the correct failure message when used in the positive" do
194
+ as_both_colored_and_uncolored do |color_enabled|
195
+ snippet = <<~TEST
196
+ expected = [
197
+ / Brown$/,
198
+ "Marty McFly",
199
+ "Biff Tannen",
200
+ /Georg McFly/,
201
+ /Lorrain McFly/
202
+ ]
203
+ actual = [
204
+ "Marty McFly",
205
+ "Doc Brown",
206
+ "Einie",
207
+ "Lorraine McFly"
208
+ ]
209
+ expect(actual).to contain_exactly(*expected)
210
+ TEST
211
+ program = make_plain_test_program(
212
+ snippet,
213
+ color_enabled: color_enabled,
214
+ )
215
+
216
+ expected_output = build_expected_output(
217
+ color_enabled: color_enabled,
218
+ snippet: %|expect(actual).to contain_exactly(*expected)|,
219
+ expectation: proc {
220
+ line do
221
+ plain " Expected "
222
+ beta %|["Marty McFly", "Doc Brown", "Einie", "Lorraine McFly"]|
223
+ end
224
+
225
+ line do
226
+ plain "to contain exactly "
227
+ alpha %|/ Brown$/|
228
+ plain ", "
229
+ alpha %|"Marty McFly"|
230
+ plain ", "
231
+ alpha %|"Biff Tannen"|
232
+ plain ", "
233
+ alpha %|/Georg McFly/|
234
+ plain " and "
235
+ alpha %|/Lorrain McFly/|
236
+ end
237
+ },
238
+ diff: proc {
239
+ plain_line %| [|
240
+ plain_line %| "Marty McFly",|
241
+ plain_line %| "Doc Brown",|
242
+ plain_line %| "Einie",|
243
+ plain_line %| "Lorraine McFly",|
244
+ alpha_line %|- "Biff Tannen",|
245
+ alpha_line %|- /Georg McFly/,|
246
+ alpha_line %|- /Lorrain McFly/|
247
+ plain_line %| ]|
248
+ },
249
+ )
250
+
251
+ expect(program).
252
+ to produce_output_when_run(expected_output).
253
+ in_color(color_enabled)
254
+ end
255
+ end
256
+
257
+ it "produces the correct failure message when used in the negative" do
258
+ as_both_colored_and_uncolored do |color_enabled|
259
+ snippet = <<~TEST
260
+ values = [
261
+ / Brown$/,
262
+ "Marty McFly",
263
+ "Biff Tannen",
264
+ /Georg McFly/,
265
+ /Lorrain McFly/
266
+ ]
267
+ expect(values).not_to contain_exactly(*values)
268
+ TEST
269
+ program = make_plain_test_program(
270
+ snippet,
271
+ color_enabled: color_enabled,
272
+ )
273
+
274
+ expected_output = build_expected_output(
275
+ color_enabled: color_enabled,
276
+ snippet: %|expect(values).not_to contain_exactly(*values)|,
277
+ newline_before_expectation: true,
278
+ expectation: proc {
279
+ line do
280
+ plain " Expected "
281
+ beta %|[/ Brown$/, "Marty McFly", "Biff Tannen", /Georg McFly/, /Lorrain McFly/]|
282
+ end
283
+
284
+ line do
285
+ plain "not to contain exactly "
286
+ alpha %|/ Brown$/|
287
+ plain ", "
288
+ alpha %|"Marty McFly"|
289
+ plain ", "
290
+ alpha %|"Biff Tannen"|
291
+ plain ", "
292
+ alpha %|/Georg McFly/|
293
+ plain " and "
294
+ alpha %|/Lorrain McFly/|
295
+ end
296
+ },
297
+ )
298
+
299
+ expect(program).
300
+ to produce_output_when_run(expected_output).
301
+ in_color(color_enabled)
302
+ end
303
+ end
304
+ end
305
+
306
+ context "and some of them are fuzzy objects" do
307
+ it "produces the correct failure message" do
308
+ as_both_colored_and_uncolored do |color_enabled|
309
+ snippet = <<~TEST.strip
310
+ expected = [
311
+ a_hash_including(foo: "bar"),
312
+ a_collection_containing_exactly("zing"),
313
+ an_object_having_attributes(baz: "qux"),
314
+ ]
315
+ actual = [
316
+ { foo: "bar" },
317
+ double(baz: "qux"),
318
+ { blargh: "riddle" }
319
+ ]
320
+ expect(actual).to contain_exactly(*expected)
321
+ TEST
322
+ program = make_plain_test_program(
323
+ snippet,
324
+ color_enabled: color_enabled,
325
+ )
326
+
327
+ expected_output = build_expected_output(
328
+ color_enabled: color_enabled,
329
+ snippet: %|expect(actual).to contain_exactly(*expected)|,
330
+ expectation: proc {
331
+ line do
332
+ plain " Expected "
333
+ beta %|[{ foo: "bar" }, #<Double (anonymous)>, { blargh: "riddle" }]|
334
+ end
335
+
336
+ line do
337
+ plain "to contain exactly "
338
+ alpha %|#<a hash including (foo: "bar")>|
339
+ plain ", "
340
+ alpha %|#<a collection containing exactly ("zing")>|
341
+ plain " and "
342
+ alpha %|#<an object having attributes (baz: "qux")>|
343
+ end
344
+ },
345
+ diff: proc {
346
+ plain_line %| [|
347
+ plain_line %| {|
348
+ plain_line %| foo: "bar"|
349
+ plain_line %| },|
350
+ plain_line %| #<Double (anonymous)>,|
351
+ plain_line %| {|
352
+ plain_line %| blargh: "riddle"|
353
+ plain_line %| },|
354
+ alpha_line %|- #<a collection containing exactly (|
355
+ alpha_line %|- "zing"|
356
+ alpha_line %|- )>|
357
+ plain_line %| ]|
358
+ },
359
+ )
360
+
361
+ expect(program).
362
+ to produce_output_when_run(expected_output).
363
+ in_color(color_enabled)
364
+ end
365
+ end
366
+ end
367
+ end
368
+ end
@@ -0,0 +1,874 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
4
+ context "when comparing two different integers" do
5
+ it "produces the correct failure message when used in the positive" do
6
+ as_both_colored_and_uncolored do |color_enabled|
7
+ snippet = %|expect(1).to eq(42)|
8
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
9
+
10
+ expected_output = build_expected_output(
11
+ color_enabled: color_enabled,
12
+ snippet: snippet,
13
+ expectation: proc {
14
+ line do
15
+ plain "Expected "
16
+ beta %|1|
17
+ plain " to eq "
18
+ alpha %|42|
19
+ plain "."
20
+ end
21
+ },
22
+ )
23
+
24
+ expect(program).
25
+ to produce_output_when_run(expected_output).
26
+ in_color(color_enabled)
27
+ end
28
+ end
29
+
30
+ it "produces the correct failure message when used in the negative" do
31
+ as_both_colored_and_uncolored do |color_enabled|
32
+ snippet = %|expect(42).not_to eq(42)|
33
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
34
+
35
+ expected_output = build_expected_output(
36
+ color_enabled: color_enabled,
37
+ snippet: snippet,
38
+ expectation: proc {
39
+ line do
40
+ plain "Expected "
41
+ beta %|42|
42
+ plain " not to eq "
43
+ alpha %|42|
44
+ plain "."
45
+ end
46
+ },
47
+ )
48
+
49
+ expect(program).
50
+ to produce_output_when_run(expected_output).
51
+ in_color(color_enabled)
52
+ end
53
+ end
54
+ end
55
+
56
+ context "when comparing two different symbols" do
57
+ it "produces the correct failure message when used in the positive" do
58
+ as_both_colored_and_uncolored do |color_enabled|
59
+ snippet = %|expect(:bar).to eq(:foo)|
60
+ program = make_plain_test_program(
61
+ snippet,
62
+ color_enabled: color_enabled,
63
+ )
64
+
65
+ expected_output = build_expected_output(
66
+ color_enabled: color_enabled,
67
+ snippet: snippet,
68
+ expectation: proc {
69
+ line do
70
+ plain "Expected "
71
+ beta %|:bar|
72
+ plain " to eq "
73
+ alpha %|:foo|
74
+ plain "."
75
+ end
76
+ },
77
+ )
78
+
79
+ expect(program).
80
+ to produce_output_when_run(expected_output).
81
+ in_color(color_enabled)
82
+ end
83
+ end
84
+
85
+ it "produces the correct failure message when used in the negative" do
86
+ as_both_colored_and_uncolored do |color_enabled|
87
+ snippet = %|expect(:foo).not_to eq(:foo)|
88
+ program = make_plain_test_program(
89
+ snippet,
90
+ color_enabled: color_enabled,
91
+ )
92
+
93
+ expected_output = build_expected_output(
94
+ color_enabled: color_enabled,
95
+ snippet: snippet,
96
+ expectation: proc {
97
+ line do
98
+ plain "Expected "
99
+ beta %|:foo|
100
+ plain " not to eq "
101
+ alpha %|:foo|
102
+ plain "."
103
+ end
104
+ },
105
+ )
106
+
107
+ expect(program).
108
+ to produce_output_when_run(expected_output).
109
+ in_color(color_enabled)
110
+ end
111
+ end
112
+ end
113
+
114
+ context "when comparing two single-line strings" do
115
+ it "produces the correct failure message when used in the positive" do
116
+ as_both_colored_and_uncolored do |color_enabled|
117
+ snippet = %|expect("Jennifer").to eq("Marty")|
118
+ program = make_plain_test_program(
119
+ snippet,
120
+ color_enabled: color_enabled,
121
+ )
122
+
123
+ expected_output = build_expected_output(
124
+ color_enabled: color_enabled,
125
+ snippet: %|expect("Jennifer").to eq("Marty")|,
126
+ expectation: proc {
127
+ line do
128
+ plain "Expected "
129
+ beta %|"Jennifer"|
130
+ plain " to eq "
131
+ alpha %|"Marty"|
132
+ plain "."
133
+ end
134
+ },
135
+ )
136
+
137
+ expect(program).
138
+ to produce_output_when_run(expected_output).
139
+ in_color(color_enabled)
140
+ end
141
+ end
142
+
143
+ it "produces the correct failure message when used in the negative" do
144
+ as_both_colored_and_uncolored do |color_enabled|
145
+ snippet = %|expect("Jennifer").to eq("Marty")|
146
+ program = make_plain_test_program(
147
+ snippet,
148
+ color_enabled: color_enabled,
149
+ )
150
+
151
+ expected_output = build_expected_output(
152
+ color_enabled: color_enabled,
153
+ snippet: %|expect("Jennifer").to eq("Marty")|,
154
+ expectation: proc {
155
+ line do
156
+ plain "Expected "
157
+ beta %|"Jennifer"|
158
+ plain " to eq "
159
+ alpha %|"Marty"|
160
+ plain "."
161
+ end
162
+ },
163
+ )
164
+
165
+ expect(program).
166
+ to produce_output_when_run(expected_output).
167
+ in_color(color_enabled)
168
+ end
169
+ end
170
+ end
171
+
172
+ context "when comparing a single-line string with a multi-line string" do
173
+ it "produces the correct failure message" do
174
+ as_both_colored_and_uncolored do |color_enabled|
175
+ snippet = <<~TEST.strip
176
+ expected = "Something entirely different"
177
+ actual = "This is a line\\nAnd that's another line\\n"
178
+ expect(actual).to eq(expected)
179
+ TEST
180
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
181
+
182
+ expected_output = build_expected_output(
183
+ color_enabled: color_enabled,
184
+ snippet: %|expect(actual).to eq(expected)|,
185
+ expectation: proc {
186
+ line do
187
+ plain "Expected "
188
+ beta %|"This is a line\\nAnd that's another line\\n"|
189
+ plain " to eq "
190
+ alpha %|"Something entirely different"|
191
+ plain "."
192
+ end
193
+ },
194
+ diff: proc {
195
+ alpha_line %|- Something entirely different|
196
+ beta_line %|+ This is a line\\n|
197
+ beta_line %|+ And that's another line\\n|
198
+ },
199
+ )
200
+
201
+ expect(program).
202
+ to produce_output_when_run(expected_output).
203
+ in_color(color_enabled)
204
+ end
205
+ end
206
+ end
207
+
208
+ context "when comparing a multi-line string with a single-line string" do
209
+ it "produces the correct failure message" do
210
+ as_both_colored_and_uncolored do |color_enabled|
211
+ snippet = <<~TEST.strip
212
+ expected = "This is a line\\nAnd that's another line\\n"
213
+ actual = "Something entirely different"
214
+ expect(actual).to eq(expected)
215
+ TEST
216
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
217
+
218
+ expected_output = build_expected_output(
219
+ color_enabled: color_enabled,
220
+ snippet: %|expect(actual).to eq(expected)|,
221
+ expectation: proc {
222
+ line do
223
+ plain "Expected "
224
+ beta %|"Something entirely different"|
225
+ plain " to eq "
226
+ alpha %|"This is a line\\nAnd that's another line\\n"|
227
+ plain "."
228
+ end
229
+ },
230
+ diff: proc {
231
+ alpha_line %|- This is a line\\n|
232
+ alpha_line %|- And that's another line\\n|
233
+ beta_line %|+ Something entirely different|
234
+ },
235
+ )
236
+
237
+ expect(program).
238
+ to produce_output_when_run(expected_output).
239
+ in_color(color_enabled)
240
+ end
241
+ end
242
+ end
243
+
244
+ context "when comparing two multi-line strings" do
245
+ it "produces the correct failure message when used in the positive" do
246
+ as_both_colored_and_uncolored do |color_enabled|
247
+ snippet = <<~TEST.strip
248
+ expected = "This is a line\\nAnd that's a line\\nAnd there's a line too\\n"
249
+ actual = "This is a line\\nSomething completely different\\nAnd there's a line too\\n"
250
+ expect(actual).to eq(expected)
251
+ TEST
252
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
253
+
254
+ expected_output = build_expected_output(
255
+ color_enabled: color_enabled,
256
+ snippet: %|expect(actual).to eq(expected)|,
257
+ expectation: proc {
258
+ line do
259
+ plain "Expected "
260
+ beta %|"This is a line\\nSomething completely different\\nAnd there's a line too\\n"|
261
+ end
262
+
263
+ line do
264
+ plain " to eq "
265
+ alpha %|"This is a line\\nAnd that's a line\\nAnd there's a line too\\n"|
266
+ end
267
+ },
268
+ diff: proc {
269
+ plain_line %| This is a line\\n|
270
+ alpha_line %|- And that's a line\\n|
271
+ beta_line %|+ Something completely different\\n|
272
+ plain_line %| And there's a line too\\n|
273
+ },
274
+ )
275
+
276
+ expect(program).
277
+ to produce_output_when_run(expected_output).
278
+ in_color(color_enabled)
279
+ end
280
+ end
281
+
282
+ it "produces the correct failure message when used in the negative" do
283
+ as_both_colored_and_uncolored do |color_enabled|
284
+ snippet = <<~TEST.strip
285
+ string = "This is a line\\nAnd that's a line\\nAnd there's a line too\\n"
286
+ expect(string).not_to eq(string)
287
+ TEST
288
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
289
+
290
+ expected_output = build_expected_output(
291
+ color_enabled: color_enabled,
292
+ snippet: %|expect(string).not_to eq(string)|,
293
+ newline_before_expectation: true,
294
+ expectation: proc {
295
+ line do
296
+ plain " Expected "
297
+ beta %|"This is a line\\nAnd that's a line\\nAnd there's a line too\\n"|
298
+ end
299
+
300
+ line do
301
+ plain "not to eq "
302
+ alpha %|"This is a line\\nAnd that's a line\\nAnd there's a line too\\n"|
303
+ end
304
+ },
305
+ )
306
+
307
+ expect(program).
308
+ to produce_output_when_run(expected_output).
309
+ in_color(color_enabled)
310
+ end
311
+ end
312
+ end
313
+
314
+ context "when comparing two arrays with other data structures inside" do
315
+ it "produces the correct failure message when used in the positive" do
316
+ as_both_colored_and_uncolored do |color_enabled|
317
+ snippet = <<~TEST
318
+ expected = [
319
+ [
320
+ :h1,
321
+ [:span, [:text, "Hello world"]],
322
+ {
323
+ class: "header",
324
+ data: {
325
+ "sticky" => true,
326
+ person: SuperDiff::Test::Person.new(name: "Marty", age: 60)
327
+ }
328
+ }
329
+ ]
330
+ ]
331
+ actual = [
332
+ [
333
+ :h2,
334
+ [:span, [:text, "Goodbye world"]],
335
+ {
336
+ id: "hero",
337
+ class: "header",
338
+ data: {
339
+ "sticky" => false,
340
+ role: "deprecated",
341
+ person: SuperDiff::Test::Person.new(name: "Doc", age: 60)
342
+ }
343
+ }
344
+ ],
345
+ :br
346
+ ]
347
+ expect(actual).to eq(expected)
348
+ TEST
349
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
350
+
351
+ expected_output = build_expected_output(
352
+ color_enabled: color_enabled,
353
+ snippet: %|expect(actual).to eq(expected)|,
354
+ expectation: proc {
355
+ line do
356
+ plain "Expected "
357
+ beta %|[[:h2, [:span, [:text, "Goodbye world"]], { id: "hero", class: "header", data: { "sticky" => false, :role => "deprecated", :person => #<SuperDiff::Test::Person name: "Doc", age: 60> } }], :br]|
358
+ end
359
+
360
+ line do
361
+ plain " to eq "
362
+ alpha %|[[:h1, [:span, [:text, "Hello world"]], { class: "header", data: { "sticky" => true, :person => #<SuperDiff::Test::Person name: "Marty", age: 60> } }]]|
363
+ end
364
+ },
365
+ diff: proc {
366
+ plain_line %| [|
367
+ plain_line %| [|
368
+ alpha_line %|- :h1,|
369
+ beta_line %|+ :h2,|
370
+ plain_line %| [|
371
+ plain_line %| :span,|
372
+ plain_line %| [|
373
+ plain_line %| :text,|
374
+ alpha_line %|- "Hello world"|
375
+ beta_line %|+ "Goodbye world"|
376
+ plain_line %| ]|
377
+ plain_line %| ],|
378
+ plain_line %| {|
379
+ beta_line %|+ id: "hero",|
380
+ plain_line %| class: "header",|
381
+ plain_line %| data: {|
382
+ alpha_line %|- "sticky" => true,|
383
+ beta_line %|+ "sticky" => false,|
384
+ beta_line %|+ role: "deprecated",|
385
+ plain_line %| person: #<SuperDiff::Test::Person {|
386
+ alpha_line %|- name: "Marty",|
387
+ beta_line %|+ name: "Doc",|
388
+ plain_line %| age: 60|
389
+ plain_line %| }>|
390
+ plain_line %| }|
391
+ plain_line %| }|
392
+ plain_line %| ],|
393
+ beta_line %|+ :br|
394
+ plain_line %| ]|
395
+ },
396
+ )
397
+
398
+ expect(program).
399
+ to produce_output_when_run(expected_output).
400
+ in_color(color_enabled)
401
+ end
402
+ end
403
+
404
+ it "produces the correct failure message when used in the negative" do
405
+ as_both_colored_and_uncolored do |color_enabled|
406
+ snippet = <<~TEST
407
+ value = [
408
+ [
409
+ :h1,
410
+ [:span, [:text, "Hello world"]],
411
+ {
412
+ class: "header",
413
+ data: {
414
+ "sticky" => true,
415
+ person: SuperDiff::Test::Person.new(name: "Marty", age: 60)
416
+ }
417
+ }
418
+ ]
419
+ ]
420
+ expect(value).not_to eq(value)
421
+ TEST
422
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
423
+
424
+ expected_output = build_expected_output(
425
+ color_enabled: color_enabled,
426
+ snippet: %|expect(value).not_to eq(value)|,
427
+ newline_before_expectation: true,
428
+ expectation: proc {
429
+ line do
430
+ plain " Expected "
431
+ beta %|[[:h1, [:span, [:text, "Hello world"]], { class: "header", data: { "sticky" => true, :person => #<SuperDiff::Test::Person name: "Marty", age: 60> } }]]|
432
+ end
433
+
434
+ line do
435
+ plain "not to eq "
436
+ alpha %|[[:h1, [:span, [:text, "Hello world"]], { class: "header", data: { "sticky" => true, :person => #<SuperDiff::Test::Person name: "Marty", age: 60> } }]]|
437
+ end
438
+ },
439
+ )
440
+
441
+ expect(program).
442
+ to produce_output_when_run(expected_output).
443
+ in_color(color_enabled)
444
+ end
445
+ end
446
+ end
447
+
448
+ context "when comparing two hashes with other data structures inside" do
449
+ it "produces the correct failure message when used in the positive" do
450
+ as_both_colored_and_uncolored do |color_enabled|
451
+ snippet = <<~TEST.strip
452
+ expected = {
453
+ customer: {
454
+ person: SuperDiff::Test::Person.new(name: "Marty McFly", age: 17),
455
+ shipping_address: {
456
+ line_1: "123 Main St.",
457
+ city: "Hill Valley",
458
+ state: "CA",
459
+ zip: "90382"
460
+ }
461
+ },
462
+ items: [
463
+ {
464
+ name: "Fender Stratocaster",
465
+ cost: 100_000,
466
+ options: ["red", "blue", "green"]
467
+ },
468
+ { name: "Chevy 4x4" }
469
+ ]
470
+ }
471
+ actual = {
472
+ customer: {
473
+ person: SuperDiff::Test::Person.new(name: "Marty McFly, Jr.", age: 17),
474
+ shipping_address: {
475
+ line_1: "456 Ponderosa Ct.",
476
+ city: "Hill Valley",
477
+ state: "CA",
478
+ zip: "90382"
479
+ }
480
+ },
481
+ items: [
482
+ {
483
+ name: "Fender Stratocaster",
484
+ cost: 100_000,
485
+ options: ["red", "blue", "green"]
486
+ },
487
+ { name: "Mattel Hoverboard" }
488
+ ]
489
+ }
490
+ expect(actual).to eq(expected)
491
+ TEST
492
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
493
+
494
+ expected_output = build_expected_output(
495
+ color_enabled: color_enabled,
496
+ snippet: %|expect(actual).to eq(expected)|,
497
+ expectation: proc {
498
+ line do
499
+ plain "Expected "
500
+ beta %|{ customer: { person: #<SuperDiff::Test::Person name: "Marty McFly, Jr.", age: 17>, shipping_address: { line_1: "456 Ponderosa Ct.", city: "Hill Valley", state: "CA", zip: "90382" } }, items: [{ name: "Fender Stratocaster", cost: 100000, options: ["red", "blue", "green"] }, { name: "Mattel Hoverboard" }] }|
501
+ end
502
+
503
+ line do
504
+ plain " to eq "
505
+ alpha %|{ customer: { person: #<SuperDiff::Test::Person name: "Marty McFly", age: 17>, shipping_address: { line_1: "123 Main St.", city: "Hill Valley", state: "CA", zip: "90382" } }, items: [{ name: "Fender Stratocaster", cost: 100000, options: ["red", "blue", "green"] }, { name: "Chevy 4x4" }] }|
506
+ end
507
+ },
508
+ diff: proc {
509
+ plain_line %| {|
510
+ plain_line %| customer: {|
511
+ plain_line %| person: #<SuperDiff::Test::Person {|
512
+ alpha_line %|- name: "Marty McFly",|
513
+ beta_line %|+ name: "Marty McFly, Jr.",|
514
+ plain_line %| age: 17|
515
+ plain_line %| }>,|
516
+ plain_line %| shipping_address: {|
517
+ alpha_line %|- line_1: "123 Main St.",|
518
+ beta_line %|+ line_1: "456 Ponderosa Ct.",|
519
+ plain_line %| city: "Hill Valley",|
520
+ plain_line %| state: "CA",|
521
+ plain_line %| zip: "90382"|
522
+ plain_line %| }|
523
+ plain_line %| },|
524
+ plain_line %| items: [|
525
+ plain_line %| {|
526
+ plain_line %| name: "Fender Stratocaster",|
527
+ plain_line %| cost: 100000,|
528
+ plain_line %| options: [|
529
+ plain_line %| "red",|
530
+ plain_line %| "blue",|
531
+ plain_line %| "green"|
532
+ plain_line %| ]|
533
+ plain_line %| },|
534
+ plain_line %| {|
535
+ alpha_line %|- name: "Chevy 4x4"|
536
+ beta_line %|+ name: "Mattel Hoverboard"|
537
+ plain_line %| }|
538
+ plain_line %| ]|
539
+ plain_line %| }|
540
+ },
541
+ )
542
+
543
+ expect(program).
544
+ to produce_output_when_run(expected_output).
545
+ in_color(color_enabled)
546
+ end
547
+ end
548
+
549
+ it "produces the correct failure message when used in the negative" do
550
+ as_both_colored_and_uncolored do |color_enabled|
551
+ snippet = <<~TEST.strip
552
+ value = {
553
+ customer: {
554
+ person: SuperDiff::Test::Person.new(name: "Marty McFly", age: 17),
555
+ shipping_address: {
556
+ line_1: "123 Main St.",
557
+ city: "Hill Valley",
558
+ state: "CA",
559
+ zip: "90382"
560
+ }
561
+ },
562
+ items: [
563
+ {
564
+ name: "Fender Stratocaster",
565
+ cost: 100_000,
566
+ options: ["red", "blue", "green"]
567
+ },
568
+ { name: "Chevy 4x4" }
569
+ ]
570
+ }
571
+ expect(value).not_to eq(value)
572
+ TEST
573
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
574
+
575
+ expected_output = build_expected_output(
576
+ color_enabled: color_enabled,
577
+ snippet: %|expect(value).not_to eq(value)|,
578
+ newline_before_expectation: true,
579
+ expectation: proc {
580
+ line do
581
+ plain " Expected "
582
+ beta %|{ customer: { person: #<SuperDiff::Test::Person name: "Marty McFly", age: 17>, shipping_address: { line_1: "123 Main St.", city: "Hill Valley", state: "CA", zip: "90382" } }, items: [{ name: "Fender Stratocaster", cost: 100000, options: ["red", "blue", "green"] }, { name: "Chevy 4x4" }] }|
583
+ end
584
+
585
+ line do
586
+ plain "not to eq "
587
+ alpha %|{ customer: { person: #<SuperDiff::Test::Person name: "Marty McFly", age: 17>, shipping_address: { line_1: "123 Main St.", city: "Hill Valley", state: "CA", zip: "90382" } }, items: [{ name: "Fender Stratocaster", cost: 100000, options: ["red", "blue", "green"] }, { name: "Chevy 4x4" }] }|
588
+ end
589
+ },
590
+ )
591
+
592
+ expect(program).
593
+ to produce_output_when_run(expected_output).
594
+ in_color(color_enabled)
595
+ end
596
+ end
597
+ end
598
+
599
+ context "when comparing two different kinds of custom objects" do
600
+ it "produces the correct failure message when used in the positive" do
601
+ as_both_colored_and_uncolored do |color_enabled|
602
+ snippet = <<~TEST.strip
603
+ expected = SuperDiff::Test::Person.new(
604
+ name: "Marty",
605
+ age: 31,
606
+ )
607
+ actual = SuperDiff::Test::Customer.new(
608
+ name: "Doc",
609
+ shipping_address: :some_shipping_address,
610
+ phone: "1234567890",
611
+ )
612
+ expect(actual).to eq(expected)
613
+ TEST
614
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
615
+
616
+ expected_output = build_expected_output(
617
+ color_enabled: color_enabled,
618
+ snippet: %|expect(actual).to eq(expected)|,
619
+ newline_before_expectation: true,
620
+ expectation: proc {
621
+ line do
622
+ plain "Expected "
623
+ beta %|#<SuperDiff::Test::Customer name: "Doc", shipping_address: :some_shipping_address, phone: "1234567890">|
624
+ end
625
+
626
+ line do
627
+ plain " to eq "
628
+ alpha %|#<SuperDiff::Test::Person name: "Marty", age: 31>|
629
+ end
630
+ },
631
+ )
632
+
633
+ expect(program).
634
+ to produce_output_when_run(expected_output).
635
+ in_color(color_enabled)
636
+ end
637
+ end
638
+
639
+ it "produces the correct failure message when used in the negative" do
640
+ as_both_colored_and_uncolored do |color_enabled|
641
+ snippet = <<~TEST.strip
642
+ value = SuperDiff::Test::Person.new(
643
+ name: "Marty",
644
+ age: 31,
645
+ )
646
+ expect(value).not_to eq(value)
647
+ TEST
648
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
649
+
650
+ expected_output = build_expected_output(
651
+ color_enabled: color_enabled,
652
+ snippet: %|expect(value).not_to eq(value)|,
653
+ newline_before_expectation: true,
654
+ expectation: proc {
655
+ line do
656
+ plain " Expected "
657
+ beta %|#<SuperDiff::Test::Person name: "Marty", age: 31>|
658
+ end
659
+
660
+ line do
661
+ plain "not to eq "
662
+ alpha %|#<SuperDiff::Test::Person name: "Marty", age: 31>|
663
+ end
664
+ },
665
+ )
666
+
667
+ expect(program).
668
+ to produce_output_when_run(expected_output).
669
+ in_color(color_enabled)
670
+ end
671
+ end
672
+ end
673
+
674
+ context "when comparing two different kinds of non-custom objects" do
675
+ it "produces the correct failure message when used in the positive" do
676
+ as_both_colored_and_uncolored do |color_enabled|
677
+ snippet = <<~TEST.strip
678
+ expected = SuperDiff::Test::Item.new(
679
+ name: "camera",
680
+ quantity: 3,
681
+ )
682
+ actual = SuperDiff::Test::Player.new(
683
+ handle: "mcmire",
684
+ character: "Jon",
685
+ inventory: ["sword"],
686
+ shields: 11.4,
687
+ health: 4,
688
+ ultimate: true,
689
+ )
690
+ expect(actual).to eq(expected)
691
+ TEST
692
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
693
+
694
+ expected_output = build_expected_output(
695
+ color_enabled: color_enabled,
696
+ snippet: %|expect(actual).to eq(expected)|,
697
+ newline_before_expectation: true,
698
+ expectation: proc {
699
+ if SuperDiff::Test.jruby?
700
+ else
701
+ line do
702
+ plain "Expected "
703
+ beta %|#<SuperDiff::Test::Player @handle="mcmire", @character="Jon", @inventory=["sword"], @shields=11.4, @health=4, @ultimate=true>|
704
+ end
705
+
706
+ line do
707
+ plain " to eq "
708
+ alpha %|#<SuperDiff::Test::Item @name="camera", @quantity=3>|
709
+ end
710
+ end
711
+ },
712
+ )
713
+
714
+ expect(program).
715
+ to produce_output_when_run(expected_output).
716
+ in_color(color_enabled).
717
+ removing_object_ids
718
+ end
719
+ end
720
+
721
+ it "produces the correct failure message when used in the negative" do
722
+ as_both_colored_and_uncolored do |color_enabled|
723
+ snippet = <<~TEST.strip
724
+ value = SuperDiff::Test::Item.new(
725
+ name: "camera",
726
+ quantity: 3,
727
+ )
728
+ expect(value).not_to eq(value)
729
+ TEST
730
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
731
+
732
+ expected_output = build_expected_output(
733
+ color_enabled: color_enabled,
734
+ snippet: %|expect(value).not_to eq(value)|,
735
+ newline_before_expectation: true,
736
+ expectation: proc {
737
+ if SuperDiff::Test.jruby?
738
+ else
739
+ line do
740
+ plain " Expected "
741
+ beta %|#<SuperDiff::Test::Item @name="camera", @quantity=3>|
742
+ end
743
+
744
+ line do
745
+ plain "not to eq "
746
+ alpha %|#<SuperDiff::Test::Item @name="camera", @quantity=3>|
747
+ end
748
+ end
749
+ },
750
+ )
751
+
752
+ expect(program).
753
+ to produce_output_when_run(expected_output).
754
+ in_color(color_enabled).
755
+ removing_object_ids
756
+ end
757
+ end
758
+ end
759
+
760
+ context "when comparing two data structures where one contains an empty array" do
761
+ it "formats the array correctly in the diff" do
762
+ as_both_colored_and_uncolored do |color_enabled|
763
+ snippet = <<~TEST.strip
764
+ expected = { foo: nil }
765
+ actual = { foo: [] }
766
+ expect(actual).to eq(expected)
767
+ TEST
768
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
769
+
770
+ expected_output = build_expected_output(
771
+ color_enabled: color_enabled,
772
+ snippet: %|expect(actual).to eq(expected)|,
773
+ newline_before_expectation: true,
774
+ expectation: proc {
775
+ line do
776
+ plain "Expected "
777
+ beta %|{ foo: [] }|
778
+ plain " to eq "
779
+ alpha %|{ foo: nil }|
780
+ plain "."
781
+ end
782
+ },
783
+ diff: proc {
784
+ plain_line %| {|
785
+ alpha_line %|- foo: nil|
786
+ beta_line %|+ foo: []|
787
+ plain_line %| }|
788
+ }
789
+ )
790
+
791
+ expect(program).
792
+ to produce_output_when_run(expected_output).
793
+ in_color(color_enabled)
794
+ end
795
+ end
796
+ end
797
+
798
+ context "when comparing two data structures where one contains an empty hash" do
799
+ it "formats the hash correctly in the diff" do
800
+ as_both_colored_and_uncolored do |color_enabled|
801
+ snippet = <<~TEST.strip
802
+ expected = { foo: nil }
803
+ actual = { foo: {} }
804
+ expect(actual).to eq(expected)
805
+ TEST
806
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
807
+
808
+ expected_output = build_expected_output(
809
+ color_enabled: color_enabled,
810
+ snippet: %|expect(actual).to eq(expected)|,
811
+ newline_before_expectation: true,
812
+ expectation: proc {
813
+ line do
814
+ plain "Expected "
815
+ beta %|{ foo: {} }|
816
+ plain " to eq "
817
+ alpha %|{ foo: nil }|
818
+ plain "."
819
+ end
820
+ },
821
+ diff: proc {
822
+ plain_line %| {|
823
+ alpha_line %|- foo: nil|
824
+ beta_line %|+ foo: {}|
825
+ plain_line %| }|
826
+ }
827
+ )
828
+
829
+ expect(program).
830
+ to produce_output_when_run(expected_output).
831
+ in_color(color_enabled)
832
+ end
833
+ end
834
+ end
835
+
836
+ context "when comparing two data structures where one contains an empty object" do
837
+ it "formats the object correctly in the diff" do
838
+ as_both_colored_and_uncolored do |color_enabled|
839
+ snippet = <<~TEST.strip
840
+ expected = { foo: nil }
841
+ actual = { foo: SuperDiff::Test::EmptyClass.new }
842
+ expect(actual).to eq(expected)
843
+ TEST
844
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
845
+
846
+ expected_output = build_expected_output(
847
+ color_enabled: color_enabled,
848
+ snippet: %|expect(actual).to eq(expected)|,
849
+ newline_before_expectation: true,
850
+ expectation: proc {
851
+ line do
852
+ plain "Expected "
853
+ beta %|{ foo: #<SuperDiff::Test::EmptyClass> }|
854
+ plain " to eq "
855
+ alpha %|{ foo: nil }|
856
+ plain "."
857
+ end
858
+ },
859
+ diff: proc {
860
+ plain_line %| {|
861
+ alpha_line %|- foo: nil|
862
+ beta_line %|+ foo: #<SuperDiff::Test::EmptyClass>|
863
+ plain_line %| }|
864
+ }
865
+ )
866
+
867
+ expect(program).
868
+ to produce_output_when_run(expected_output).
869
+ in_color(color_enabled).
870
+ removing_object_ids
871
+ end
872
+ end
873
+ end
874
+ end