super_diff 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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