Skip to content

Commit e64e5ef

Browse files
committed
Fix diffing two different kinds of objects
When comparing two objects that do not share the same class, a diff is being produced. This is really not very useful, so we hide it in that case.
1 parent 4e11fa3 commit e64e5ef

File tree

12 files changed

+245
-63
lines changed

12 files changed

+245
-63
lines changed

lib/super_diff/differs/custom_object.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ module SuperDiff
22
module Differs
33
class CustomObject < Base
44
def self.applies_to?(expected, actual)
5-
expected.respond_to?(:attributes_for_super_diff) &&
5+
expected.class == actual.class &&
6+
expected.respond_to?(:attributes_for_super_diff) &&
67
actual.respond_to?(:attributes_for_super_diff)
78
end
89

lib/super_diff/differs/default_object.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module SuperDiff
22
module Differs
33
class DefaultObject < Base
4-
def self.applies_to?(_expected, _actual)
5-
true
4+
def self.applies_to?(expected, actual)
5+
expected.class == actual.class
66
end
77

88
def call

lib/super_diff/equality_matcher.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ def call
2424
private
2525

2626
def resolved_class
27-
matching_class || EqualityMatchers::Object
28-
end
29-
30-
def matching_class
3127
(EqualityMatchers::DEFAULTS + extra_classes).find do |klass|
3228
klass.applies_to?(expected) && klass.applies_to?(actual)
3329
end

lib/super_diff/equality_matchers.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ module EqualityMatchers
44
autoload :Base, "super_diff/equality_matchers/base"
55
autoload :Hash, "super_diff/equality_matchers/hash"
66
autoload :MultilineString, "super_diff/equality_matchers/multiline_string"
7-
autoload :Object, "super_diff/equality_matchers/object"
7+
autoload :Default, "super_diff/equality_matchers/default"
88
autoload :Primitive, "super_diff/equality_matchers/primitive"
99
autoload(
1010
:SinglelineString,
1111
"super_diff/equality_matchers/singleline_string",
1212
)
1313

1414
DEFAULTS = [
15+
Primitive,
1516
Array,
1617
Hash,
1718
MultilineString,
1819
SinglelineString,
19-
Object,
20-
Primitive,
20+
Default,
2121
].freeze
2222
end
2323
end
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module SuperDiff
2+
module EqualityMatchers
3+
class Default < Base
4+
def self.applies_to?(_value)
5+
true
6+
end
7+
8+
def fail
9+
<<~OUTPUT.strip
10+
Differing objects.
11+
12+
#{expected_line}
13+
#{actual_line}
14+
#{diff_section}
15+
OUTPUT
16+
end
17+
18+
protected
19+
20+
def expected_line
21+
Helpers.style(
22+
:deleted,
23+
"Expected: " +
24+
ObjectInspection.inspect(expected, as_single_line: true),
25+
)
26+
end
27+
28+
def actual_line
29+
Helpers.style(
30+
:inserted,
31+
" Actual: " +
32+
ObjectInspection.inspect(actual, as_single_line: true),
33+
)
34+
end
35+
36+
def diff_section
37+
if diff.blank?
38+
""
39+
else
40+
<<~SECTION
41+
42+
Diff:
43+
44+
#{diff}
45+
SECTION
46+
end
47+
end
48+
49+
def diff
50+
Differ.call(
51+
expected,
52+
actual,
53+
indent_level: 0,
54+
extra_operational_sequencer_classes: extra_operational_sequencer_classes,
55+
extra_diff_formatter_classes: extra_diff_formatter_classes,
56+
)
57+
end
58+
end
59+
end
60+
end

lib/super_diff/equality_matchers/object.rb

Lines changed: 0 additions & 46 deletions
This file was deleted.

lib/super_diff/operational_sequencers/custom_object.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ module SuperDiff
22
module OperationalSequencers
33
class CustomObject < DefaultObject
44
def self.applies_to?(expected, actual)
5-
expected.respond_to?(:attributes_for_super_diff) &&
5+
expected.class == actual.class &&
6+
expected.respond_to?(:attributes_for_super_diff) &&
67
actual.respond_to?(:attributes_for_super_diff)
78
end
89

lib/super_diff/rspec/differ.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def diff
1616
Differs::CollectionContainingExactly,
1717
Differs::PartialArray,
1818
Differs::PartialHash,
19+
Differs::PartialObject,
1920
],
2021
extra_operational_sequencer_classes: [
2122
*RSpec.configuration.extra_operational_sequencer_classes,

lib/super_diff/rspec/differs.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module Differs
77
)
88
autoload :PartialArray, "super_diff/rspec/differs/partial_array"
99
autoload :PartialHash, "super_diff/rspec/differs/partial_hash"
10-
# autoload :PartialObject, "super_diff/rspec/differs/partial_object"
10+
autoload :PartialObject, "super_diff/rspec/differs/partial_object"
1111
end
1212
end
1313
end

spec/integration/rspec_spec.rb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,84 @@
377377
expect(program).to produce_output_when_run(expected_output)
378378
end
379379
end
380+
381+
context "when comparing two different kinds of custom objects" do
382+
it "produces the correct output" do
383+
program = make_plain_test_program(<<~TEST.strip)
384+
expected = SuperDiff::Test::Person.new(
385+
name: "Marty",
386+
age: 31,
387+
)
388+
actual = SuperDiff::Test::Customer.new(
389+
name: "Doc",
390+
shipping_address: :some_shipping_address,
391+
phone: "1234567890",
392+
)
393+
expect(actual).to eq(expected)
394+
TEST
395+
396+
expected_output = build_expected_output(
397+
snippet: %|expect(actual).to eq(expected)|,
398+
newline_before_expectation: true,
399+
expectation: proc {
400+
line do
401+
plain "Expected "
402+
green %|#<SuperDiff::Test::Customer name: "Doc", shipping_address: :some_shipping_address, phone: "1234567890">|
403+
end
404+
405+
line do
406+
plain " to eq "
407+
red %|#<SuperDiff::Test::Person name: "Marty", age: 31>|
408+
end
409+
},
410+
)
411+
412+
expect(program).to produce_output_when_run(expected_output)
413+
end
414+
end
415+
416+
context "when comparing two different kinds of non-custom objects" do
417+
it "produces the correct output" do
418+
program = make_plain_test_program(<<~TEST.strip)
419+
expected = SuperDiff::Test::Item.new(
420+
name: "camera",
421+
quantity: 3,
422+
)
423+
actual = SuperDiff::Test::Player.new(
424+
handle: "mcmire",
425+
character: "Jon",
426+
inventory: ["sword"],
427+
shields: 11.4,
428+
health: 4,
429+
ultimate: true,
430+
)
431+
expect(actual).to eq(expected)
432+
TEST
433+
434+
expected_output = build_expected_output(
435+
snippet: %|expect(actual).to eq(expected)|,
436+
newline_before_expectation: true,
437+
expectation: proc {
438+
if SuperDiff::Test.jruby?
439+
else
440+
line do
441+
plain "Expected "
442+
green %|#<SuperDiff::Test::Player @handle="mcmire", @character="Jon", @inventory=["sword"], @shields=11.4, @health=4, @ultimate=true>|
443+
end
444+
445+
line do
446+
plain " to eq "
447+
red %|#<SuperDiff::Test::Item @name="camera", @quantity=3>|
448+
end
449+
end
450+
},
451+
)
452+
453+
expect(program).
454+
to produce_output_when_run(expected_output).
455+
first_replacing(/#<([\w:]+):0x[a-z0-9]+ /, '#<\1 ')
456+
end
457+
end
380458
end
381459

382460
describe "the #include matcher" do

0 commit comments

Comments
 (0)