super_diff 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_model.rb +24 -12
  3. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_relation.rb +15 -6
  4. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/hash_with_indifferent_access.rb +23 -8
  5. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/ordered_options.rb +46 -0
  6. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders.rb +4 -0
  7. data/lib/super_diff/active_support.rb +2 -1
  8. data/lib/super_diff/differs/date_like.rb +15 -0
  9. data/lib/super_diff/differs/defaults.rb +1 -0
  10. data/lib/super_diff/differs.rb +1 -0
  11. data/lib/super_diff/errors.rb +0 -4
  12. data/lib/super_diff/object_inspection/inspection_tree.rb +25 -20
  13. data/lib/super_diff/object_inspection/inspection_tree_builders/array.rb +31 -12
  14. data/lib/super_diff/object_inspection/inspection_tree_builders/custom_object.rb +19 -9
  15. data/lib/super_diff/object_inspection/inspection_tree_builders/date_like.rb +51 -0
  16. data/lib/super_diff/object_inspection/inspection_tree_builders/default_object.rb +46 -21
  17. data/lib/super_diff/object_inspection/inspection_tree_builders/defaults.rb +1 -0
  18. data/lib/super_diff/object_inspection/inspection_tree_builders/hash.rb +39 -14
  19. data/lib/super_diff/object_inspection/inspection_tree_builders/primitive.rb +3 -5
  20. data/lib/super_diff/object_inspection/inspection_tree_builders/time_like.rb +31 -20
  21. data/lib/super_diff/object_inspection/inspection_tree_builders.rb +4 -0
  22. data/lib/super_diff/object_inspection/nodes/as_lines_when_rendering_to_lines.rb +3 -2
  23. data/lib/super_diff/operation_tree_builders/date_like.rb +15 -0
  24. data/lib/super_diff/operation_tree_builders/defaults.rb +1 -1
  25. data/lib/super_diff/operation_tree_builders.rb +1 -0
  26. data/lib/super_diff/rspec/matcher_text_builders/raise_error.rb +3 -7
  27. data/lib/super_diff/rspec/monkey_patches.rb +59 -8
  28. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_containing_exactly.rb +14 -7
  29. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_including.rb +19 -13
  30. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/double.rb +30 -26
  31. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/generic_describable_matcher.rb +19 -0
  32. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/hash_including.rb +19 -14
  33. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/instance_of.rb +9 -10
  34. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/kind_of.rb +9 -10
  35. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/object_having_attributes.rb +14 -7
  36. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/value_within.rb +10 -11
  37. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders.rb +4 -0
  38. data/lib/super_diff/rspec.rb +10 -9
  39. data/lib/super_diff/version.rb +1 -1
  40. data/lib/super_diff.rb +9 -0
  41. data/spec/examples.txt +543 -493
  42. data/spec/integration/rails/engines_spec.rb +8 -3
  43. data/spec/integration/rspec/contain_exactly_matcher_spec.rb +19 -19
  44. data/spec/integration/rspec/eq_matcher_spec.rb +111 -39
  45. data/spec/integration/rspec/generic_describable_matchers_spec.rb +177 -0
  46. data/spec/integration/rspec/have_attributes_matcher_spec.rb +25 -25
  47. data/spec/integration/rspec/include_matcher_spec.rb +23 -23
  48. data/spec/integration/rspec/magic_metadata_spec.rb +51 -0
  49. data/spec/integration/rspec/match_array_matcher_spec.rb +30 -30
  50. data/spec/integration/rspec/match_matcher_spec.rb +93 -93
  51. data/spec/integration/rspec/raise_error_matcher_spec.rb +813 -69
  52. data/spec/internal/log/test.log +0 -0
  53. data/spec/spec_helper.rb +3 -0
  54. data/spec/support/integration/helpers.rb +15 -10
  55. data/spec/support/integration/matchers.rb +34 -0
  56. data/spec/support/integration/test_programs/base.rb +6 -6
  57. data/spec/support/integration/test_programs/rspec_rails_engine.rb +3 -13
  58. data/spec/support/shared_examples/active_record.rb +33 -33
  59. data/spec/support/shared_examples/active_support.rb +125 -4
  60. data/spec/support/shared_examples/elided_diffs.rb +48 -48
  61. data/spec/support/shared_examples/hash_with_indifferent_access.rb +88 -88
  62. data/spec/support/shared_examples/key.rb +10 -10
  63. data/spec/unit/active_support/object_inspection_spec.rb +170 -0
  64. data/spec/unit/rspec/matchers/raise_error_spec.rb +43 -11
  65. data/spec/unit/rspec/object_inspection/rspec_matcher_spec.rb +91 -0
  66. data/spec/unit/rspec/object_inspection_spec.rb +2 -2
  67. data/spec/unit/super_diff_spec.rb +64 -0
  68. metadata +17 -4
  69. data/lib/super_diff/errors/no_diff_formatter_available_error.rb +0 -21
  70. data/lib/super_diff/errors/no_operational_sequencer_available_error.rb +0 -22
@@ -1,16 +1,21 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe "Integration with Rails engines", type: :integration do
3
+ RSpec.describe "Integration with Rails engines",
4
+ type: :integration,
5
+ active_support: true do
4
6
  context "when ActiveRecord is not loaded via Combustion" do
5
7
  it "does not fail to load" do
6
8
  as_both_colored_and_uncolored do |color_enabled|
7
9
  program =
8
- make_rspec_rails_engine_program(
10
+ make_rspec_rails_engine_with_action_controller_program(
9
11
  "expect(true).to be(true)",
10
- combustion_initialize: [:action_controller],
11
12
  color_enabled: color_enabled
12
13
  )
13
14
 
15
+ expect(program).to produce_output_when_run(
16
+ "1 example, 0 failures"
17
+ ).in_color(color_enabled)
18
+
14
19
  expect(program).not_to produce_output_when_run(
15
20
  "uninitialized constant ActiveRecord"
16
21
  ).in_color(color_enabled)
@@ -6,8 +6,8 @@ RSpec.describe "Integration with RSpec's #contain_exactly matcher",
6
6
  it "produces the correct failure message when used in the positive" do
7
7
  as_both_colored_and_uncolored do |color_enabled|
8
8
  snippet = <<~TEST.strip
9
- expected = ["Einie", "Marty"]
10
9
  actual = ["Marty", "Jennifer", "Doc"]
10
+ expected = ["Einie", "Marty"]
11
11
  expect(actual).to contain_exactly(*expected)
12
12
  TEST
13
13
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -84,6 +84,12 @@ RSpec.describe "Integration with RSpec's #contain_exactly matcher",
84
84
  it "produces the correct failure message when used in the positive" do
85
85
  as_both_colored_and_uncolored do |color_enabled|
86
86
  snippet = <<~TEST.strip
87
+ actual = [
88
+ "Marty McFly",
89
+ "Doc Brown",
90
+ "Einie",
91
+ "Lorraine McFly"
92
+ ]
87
93
  expected = [
88
94
  "Doc Brown",
89
95
  "Marty McFly",
@@ -91,12 +97,6 @@ RSpec.describe "Integration with RSpec's #contain_exactly matcher",
91
97
  "George McFly",
92
98
  "Lorraine McFly"
93
99
  ]
94
- actual = [
95
- "Marty McFly",
96
- "Doc Brown",
97
- "Einie",
98
- "Lorraine McFly"
99
- ]
100
100
  expect(actual).to contain_exactly(*expected)
101
101
  TEST
102
102
  program =
@@ -196,6 +196,12 @@ RSpec.describe "Integration with RSpec's #contain_exactly matcher",
196
196
  it "produces the correct failure message when used in the positive" do
197
197
  as_both_colored_and_uncolored do |color_enabled|
198
198
  snippet = <<~TEST
199
+ actual = [
200
+ "Marty McFly",
201
+ "Doc Brown",
202
+ "Einie",
203
+ "Lorraine McFly"
204
+ ]
199
205
  expected = [
200
206
  / Brown$/,
201
207
  "Marty McFly",
@@ -203,12 +209,6 @@ RSpec.describe "Integration with RSpec's #contain_exactly matcher",
203
209
  /Georg McFly/,
204
210
  /Lorrain McFly/
205
211
  ]
206
- actual = [
207
- "Marty McFly",
208
- "Doc Brown",
209
- "Einie",
210
- "Lorraine McFly"
211
- ]
212
212
  expect(actual).to contain_exactly(*expected)
213
213
  TEST
214
214
  program =
@@ -308,20 +308,20 @@ RSpec.describe "Integration with RSpec's #contain_exactly matcher",
308
308
  end
309
309
  end
310
310
 
311
- context "and some of them are fuzzy objects" do
311
+ context "and some of them are RSpec matchers" do
312
312
  it "produces the correct failure message" do
313
313
  as_both_colored_and_uncolored do |color_enabled|
314
314
  snippet = <<~TEST.strip
315
- expected = [
316
- a_hash_including(foo: "bar"),
317
- a_collection_containing_exactly("zing"),
318
- an_object_having_attributes(baz: "qux"),
319
- ]
320
315
  actual = [
321
316
  { foo: "bar" },
322
317
  double(baz: "qux"),
323
318
  { blargh: "riddle" }
324
319
  ]
320
+ expected = [
321
+ a_hash_including(foo: "bar"),
322
+ a_collection_containing_exactly("zing"),
323
+ an_object_having_attributes(baz: "qux"),
324
+ ]
325
325
  expect(actual).to contain_exactly(*expected)
326
326
  TEST
327
327
  program =
@@ -173,16 +173,16 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
173
173
  it "produces the correct failure message when used in the positive" do
174
174
  as_both_colored_and_uncolored do |color_enabled|
175
175
  snippet = <<~RUBY
176
- expected = Time.utc(2011, 12, 13, 14, 15, 16)
177
- actual = Time.utc(2011, 12, 13, 14, 15, 16, 500_000)
178
- expect(expected).to eq(actual)
176
+ actual = Time.utc(2011, 12, 13, 14, 15, 16)
177
+ expected = Time.utc(2011, 12, 13, 14, 15, 16, 500_000)
178
+ expect(actual).to eq(expected)
179
179
  RUBY
180
180
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
181
181
 
182
182
  expected_output =
183
183
  build_expected_output(
184
184
  color_enabled: color_enabled,
185
- snippet: "expect(expected).to eq(actual)",
185
+ snippet: "expect(actual).to eq(expected)",
186
186
  expectation:
187
187
  proc do
188
188
  line do
@@ -252,12 +252,84 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
252
252
  end
253
253
  end
254
254
 
255
+ context "when comparing two different Date instances" do
256
+ it "produces the correct failure message when used in the positive" do
257
+ as_both_colored_and_uncolored do |color_enabled|
258
+ snippet = <<~RUBY
259
+ actual = Date.new(2023, 10, 14)
260
+ expected = Date.new(2023, 10, 31)
261
+ expect(actual).to eq(expected)
262
+ RUBY
263
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
264
+
265
+ expected_output =
266
+ build_expected_output(
267
+ color_enabled: color_enabled,
268
+ snippet: "expect(actual).to eq(expected)",
269
+ expectation:
270
+ proc do
271
+ line do
272
+ plain "Expected "
273
+ actual "#<Date 2023-10-14>"
274
+ plain " to eq "
275
+ expected "#<Date 2023-10-31>"
276
+ plain "."
277
+ end
278
+ end,
279
+ diff:
280
+ proc do
281
+ plain_line " #<Date {"
282
+ plain_line " year: 2023,"
283
+ plain_line " month: 10,"
284
+ expected_line "- day: 31"
285
+ actual_line "+ day: 14"
286
+ plain_line " }>"
287
+ end
288
+ )
289
+
290
+ expect(program).to produce_output_when_run(expected_output).in_color(
291
+ color_enabled
292
+ )
293
+ end
294
+ end
295
+
296
+ it "produces the correct failure message when used in the negative" do
297
+ as_both_colored_and_uncolored do |color_enabled|
298
+ snippet = <<~RUBY
299
+ date = Date.new(2023, 10, 14)
300
+ expect(date).not_to eq(date)
301
+ RUBY
302
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
303
+
304
+ expected_output =
305
+ build_expected_output(
306
+ color_enabled: color_enabled,
307
+ snippet: "expect(date).not_to eq(date)",
308
+ expectation:
309
+ proc do
310
+ line do
311
+ plain "Expected "
312
+ actual "#<Date 2023-10-14>"
313
+ plain " not to eq "
314
+ expected "#<Date 2023-10-14>"
315
+ plain "."
316
+ end
317
+ end
318
+ )
319
+
320
+ expect(program).to produce_output_when_run(expected_output).in_color(
321
+ color_enabled
322
+ )
323
+ end
324
+ end
325
+ end
326
+
255
327
  context "when comparing a single-line string with a multi-line string" do
256
328
  it "produces the correct failure message" do
257
329
  as_both_colored_and_uncolored do |color_enabled|
258
330
  snippet = <<~TEST.strip
259
- expected = "Something entirely different"
260
331
  actual = "This is a line\\nAnd that's another line\\n"
332
+ expected = "Something entirely different"
261
333
  expect(actual).to eq(expected)
262
334
  TEST
263
335
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -295,8 +367,8 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
295
367
  it "produces the correct failure message" do
296
368
  as_both_colored_and_uncolored do |color_enabled|
297
369
  snippet = <<~TEST.strip
298
- expected = "This is a line\\nAnd that's another line\\n"
299
370
  actual = "Something entirely different"
371
+ expected = "This is a line\\nAnd that's another line\\n"
300
372
  expect(actual).to eq(expected)
301
373
  TEST
302
374
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -334,8 +406,8 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
334
406
  it "produces the correct failure message when used in the positive" do
335
407
  as_both_colored_and_uncolored do |color_enabled|
336
408
  snippet = <<~TEST.strip
337
- expected = "This is a line\\nAnd that's a line\\nAnd there's a line too\\n"
338
409
  actual = "This is a line\\nSomething completely different\\nAnd there's a line too\\n"
410
+ expected = "This is a line\\nAnd that's a line\\nAnd there's a line too\\n"
339
411
  expect(actual).to eq(expected)
340
412
  TEST
341
413
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -409,19 +481,6 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
409
481
  it "produces the correct failure message when used in the positive" do
410
482
  as_both_colored_and_uncolored do |color_enabled|
411
483
  snippet = <<~TEST
412
- expected = [
413
- [
414
- :h1,
415
- [:span, [:text, "Hello world"]],
416
- {
417
- class: "header",
418
- data: {
419
- "sticky" => true,
420
- person: SuperDiff::Test::Person.new(name: "Marty", age: 60)
421
- }
422
- }
423
- ]
424
- ]
425
484
  actual = [
426
485
  [
427
486
  :h2,
@@ -438,6 +497,19 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
438
497
  ],
439
498
  :br
440
499
  ]
500
+ expected = [
501
+ [
502
+ :h1,
503
+ [:span, [:text, "Hello world"]],
504
+ {
505
+ class: "header",
506
+ data: {
507
+ "sticky" => true,
508
+ person: SuperDiff::Test::Person.new(name: "Marty", age: 60)
509
+ }
510
+ }
511
+ ]
512
+ ]
441
513
  expect(actual).to eq(expected)
442
514
  TEST
443
515
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -548,11 +620,11 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
548
620
  it "produces the correct failure message when used in the positive" do
549
621
  as_both_colored_and_uncolored do |color_enabled|
550
622
  snippet = <<~TEST.strip
551
- expected = {
623
+ actual = {
552
624
  customer: {
553
- person: SuperDiff::Test::Person.new(name: "Marty McFly", age: 17),
625
+ person: SuperDiff::Test::Person.new(name: "Marty McFly, Jr.", age: 17),
554
626
  shipping_address: {
555
- line_1: "123 Main St.",
627
+ line_1: "456 Ponderosa Ct.",
556
628
  city: "Hill Valley",
557
629
  state: "CA",
558
630
  zip: "90382"
@@ -564,14 +636,14 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
564
636
  cost: 100_000,
565
637
  options: ["red", "blue", "green"]
566
638
  },
567
- { name: "Chevy 4x4" }
639
+ { name: "Mattel Hoverboard" }
568
640
  ]
569
641
  }
570
- actual = {
642
+ expected = {
571
643
  customer: {
572
- person: SuperDiff::Test::Person.new(name: "Marty McFly, Jr.", age: 17),
644
+ person: SuperDiff::Test::Person.new(name: "Marty McFly", age: 17),
573
645
  shipping_address: {
574
- line_1: "456 Ponderosa Ct.",
646
+ line_1: "123 Main St.",
575
647
  city: "Hill Valley",
576
648
  state: "CA",
577
649
  zip: "90382"
@@ -583,7 +655,7 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
583
655
  cost: 100_000,
584
656
  options: ["red", "blue", "green"]
585
657
  },
586
- { name: "Mattel Hoverboard" }
658
+ { name: "Chevy 4x4" }
587
659
  ]
588
660
  }
589
661
  expect(actual).to eq(expected)
@@ -704,15 +776,15 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
704
776
  it "produces the correct failure message when used in the positive" do
705
777
  as_both_colored_and_uncolored do |color_enabled|
706
778
  snippet = <<~TEST.strip
707
- expected = SuperDiff::Test::Person.new(
708
- name: "Marty",
709
- age: 31,
710
- )
711
779
  actual = SuperDiff::Test::Customer.new(
712
780
  name: "Doc",
713
781
  shipping_address: :some_shipping_address,
714
782
  phone: "1234567890",
715
783
  )
784
+ expected = SuperDiff::Test::Person.new(
785
+ name: "Marty",
786
+ age: 31,
787
+ )
716
788
  expect(actual).to eq(expected)
717
789
  TEST
718
790
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -783,10 +855,6 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
783
855
  it "produces the correct failure message when used in the positive" do
784
856
  as_both_colored_and_uncolored do |color_enabled|
785
857
  snippet = <<~TEST.strip
786
- expected = SuperDiff::Test::Item.new(
787
- name: "camera",
788
- quantity: 3,
789
- )
790
858
  actual = SuperDiff::Test::Player.new(
791
859
  handle: "mcmire",
792
860
  character: "Jon",
@@ -795,6 +863,10 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
795
863
  health: 4,
796
864
  ultimate: true,
797
865
  )
866
+ expected = SuperDiff::Test::Item.new(
867
+ name: "camera",
868
+ quantity: 3,
869
+ )
798
870
  expect(actual).to eq(expected)
799
871
  TEST
800
872
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -865,8 +937,8 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
865
937
  it "formats the array correctly in the diff" do
866
938
  as_both_colored_and_uncolored do |color_enabled|
867
939
  snippet = <<~TEST.strip
868
- expected = { foo: nil }
869
940
  actual = { foo: [] }
941
+ expected = { foo: nil }
870
942
  expect(actual).to eq(expected)
871
943
  TEST
872
944
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -906,8 +978,8 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
906
978
  it "formats the hash correctly in the diff" do
907
979
  as_both_colored_and_uncolored do |color_enabled|
908
980
  snippet = <<~TEST.strip
909
- expected = { foo: nil }
910
981
  actual = { foo: {} }
982
+ expected = { foo: nil }
911
983
  expect(actual).to eq(expected)
912
984
  TEST
913
985
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -947,8 +1019,8 @@ RSpec.describe "Integration with RSpec's #eq matcher", type: :integration do
947
1019
  it "formats the object correctly in the diff" do
948
1020
  as_both_colored_and_uncolored do |color_enabled|
949
1021
  snippet = <<~TEST.strip
950
- expected = { foo: nil }
951
1022
  actual = { foo: SuperDiff::Test::EmptyClass.new }
1023
+ expected = { foo: nil }
952
1024
  expect(actual).to eq(expected)
953
1025
  TEST
954
1026
  program = make_plain_test_program(snippet, color_enabled: color_enabled)
@@ -0,0 +1,177 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Integration with describable matchers not handled specially",
4
+ type: :integration do
5
+ context "when the expected value contains a built-in matcher (not an aliased matcher)" do
6
+ it "produces the correct failure message when used in the positive" do
7
+ as_both_colored_and_uncolored do |color_enabled|
8
+ snippet = <<~TEST.strip
9
+ actual = {
10
+ number: "not a number"
11
+ }
12
+ expected = hash_including(
13
+ number: be_a(Numeric)
14
+ )
15
+ expect(actual).to match(expected)
16
+ TEST
17
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
18
+
19
+ expected_output =
20
+ build_expected_output(
21
+ color_enabled: color_enabled,
22
+ snippet: "expect(actual).to match(expected)",
23
+ expectation:
24
+ proc do
25
+ line do
26
+ plain "Expected "
27
+ actual %|{ number: "not a number" }|
28
+ plain " to match "
29
+ expected "#<a hash including (number: #<be a kind of Numeric>)>"
30
+ plain "."
31
+ end
32
+ end,
33
+ diff:
34
+ proc do
35
+ plain_line " {"
36
+ expected_line "- number: #<be a kind of Numeric>"
37
+ actual_line %|+ number: "not a number"|
38
+ plain_line " }"
39
+ end
40
+ )
41
+
42
+ expect(program).to produce_output_when_run(expected_output).in_color(
43
+ color_enabled
44
+ )
45
+ end
46
+ end
47
+
48
+ it "produces the correct failure message when used in the negative" do
49
+ as_both_colored_and_uncolored do |color_enabled|
50
+ snippet = <<~TEST.strip
51
+ actual = {
52
+ number: 4
53
+ }
54
+ expected = hash_including(
55
+ number: be_a(Numeric)
56
+ )
57
+ expect(actual).not_to match(expected)
58
+ TEST
59
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
60
+
61
+ expected_output =
62
+ build_expected_output(
63
+ color_enabled: color_enabled,
64
+ snippet: "expect(actual).not_to match(expected)",
65
+ expectation:
66
+ proc do
67
+ line do
68
+ plain "Expected "
69
+ actual "{ number: 4 }"
70
+ plain " not to match "
71
+ expected "#<a hash including (number: #<be a kind of Numeric>)>"
72
+ plain "."
73
+ end
74
+ end
75
+ )
76
+
77
+ expect(program).to produce_output_when_run(expected_output).in_color(
78
+ color_enabled
79
+ )
80
+ end
81
+ end
82
+ end
83
+
84
+ context "when the expected value contains a custom matcher defined via RSpec::Matchers::DSL" do
85
+ it "produces the correct failure message" do
86
+ as_both_colored_and_uncolored do |color_enabled|
87
+ snippet = <<~TEST.strip
88
+ actual = {
89
+ number: "something else"
90
+ }
91
+ expected = hash_including(
92
+ number: failing_custom_matcher_from_dsl(42)
93
+ )
94
+ expect(actual).to match(expected)
95
+ TEST
96
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
97
+
98
+ expected_output =
99
+ build_expected_output(
100
+ color_enabled: color_enabled,
101
+ snippet: "expect(actual).to match(expected)",
102
+ newline_before_expectation: true,
103
+ expectation:
104
+ proc do
105
+ line do
106
+ plain "Expected "
107
+ actual %|{ number: "something else" }|
108
+ end
109
+
110
+ line do
111
+ plain "to match "
112
+ expected "#<a hash including (number: #<custom matcher defined via the DSL with value 42>)>"
113
+ end
114
+ end,
115
+ diff:
116
+ proc do
117
+ plain_line " {"
118
+ expected_line "- number: #<custom matcher defined via the DSL with value 42>"
119
+ actual_line %|+ number: "something else"|
120
+ plain_line " }"
121
+ end
122
+ )
123
+
124
+ expect(program).to produce_output_when_run(expected_output).in_color(
125
+ color_enabled
126
+ )
127
+ end
128
+ end
129
+ end
130
+
131
+ context "when the expected value contains a custom matcher defined from scratch" do
132
+ it "produces the correct failure message" do
133
+ as_both_colored_and_uncolored do |color_enabled|
134
+ snippet = <<~TEST.strip
135
+ actual = {
136
+ number: "something else"
137
+ }
138
+ expected = hash_including(
139
+ number: failing_custom_matcher_from_scratch(42)
140
+ )
141
+ expect(actual).to match(expected)
142
+ TEST
143
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
144
+
145
+ expected_output =
146
+ build_expected_output(
147
+ color_enabled: color_enabled,
148
+ snippet: "expect(actual).to match(expected)",
149
+ newline_before_expectation: true,
150
+ expectation:
151
+ proc do
152
+ line do
153
+ plain "Expected "
154
+ actual %|{ number: "something else" }|
155
+ end
156
+
157
+ line do
158
+ plain "to match "
159
+ expected "#<a hash including (number: #<custom matcher defined from scratch with value 42>)>"
160
+ end
161
+ end,
162
+ diff:
163
+ proc do
164
+ plain_line " {"
165
+ expected_line "- number: #<custom matcher defined from scratch with value 42>"
166
+ actual_line %|+ number: "something else"|
167
+ plain_line " }"
168
+ end
169
+ )
170
+
171
+ expect(program).to produce_output_when_run(expected_output).in_color(
172
+ color_enabled
173
+ )
174
+ end
175
+ end
176
+ end
177
+ end