Skip to content

Commit

Permalink
Exclude more un-diffable objects (#273)
Browse files Browse the repository at this point in the history
Closes #268.

SuperDiff already skips diff output for incomparable types, such as `true`, `false`, and `nil`. We will now also skip diff output when comparing the following types (for which we can't produce a meaningful diff):

* `Symbol`
* `Numeric`
* `Regexp`
* `Class`
* `Module`
  • Loading branch information
lucaseras authored and jas14 committed Nov 8, 2024
1 parent 2234d03 commit ba1ba2c
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Improve inspection of Module. [#263](https://github.com/splitwise/super_diff/pull/263) by [@phorsuedzie](https://github.com/phorsuedzie)
- Fix multiline string diff with blank lines. [#266](https://github.com/splitwise/super_diff/pull/263)
- Improve inspection of Range objects. [#267](https://github.com/splitwise/super_diff/pull/267) by [@lucaseras](https://github.com/lucaseras)
- Skip diffing of more un-diffable types. [#273](https://github.com/splitwise/super_diff/pull/273) by [@lucaseras](https://github.com/lucaseras)

### Other changes

Expand Down
13 changes: 10 additions & 3 deletions lib/super_diff/rspec/differ.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,23 @@ def diff

def worth_diffing?
comparing_inequal_values? && !comparing_primitive_values? &&
!comparing_singleline_strings?
!comparing_proc_values? && !comparing_singleline_strings?
end

def comparing_inequal_values?
!helpers.values_match?(expected, actual)
end

def comparing_primitive_values?
expected.is_a?(Symbol) || expected.is_a?(Integer) ||
[true, false, nil].include?(expected)
# strings are indeed primitives, but we still may want to diff them if
# they are multiline strings (see #comparing_singleline_strings?)
return false if expected.is_a?(String)

SuperDiff.primitive?(expected)
end

def comparing_proc_values?
expected.is_a?(Proc)
end

def comparing_singleline_strings?
Expand Down
306 changes: 306 additions & 0 deletions spec/integration/rspec/eq_matcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,312 @@
end
end

context 'when comparing procs (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
actual = Proc.new { 'hello' }
expected = Proc.new { 'oh, hi!' }
expect(actual).to eq(expected)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(actual).to eq(expected)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual '#<Proc>'
plain ' to eq '
expected '#<Proc>'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing booleans (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
actual = true
expected = false
expect(actual).to eq(expected)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(actual).to eq(expected)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual 'true'
plain ' to eq '
expected 'false'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing nils (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
actual = nil
expected = 'something else'
expect(actual).to eq(expected)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(actual).to eq(expected)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual 'nil'
plain ' to eq '
expected '"something else"'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing symbols (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
actual = :test
expected = :different_symbol
expect(actual).to eq(expected)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(actual).to eq(expected)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual ':test'
plain ' to eq '
expected ':different_symbol'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing numerics (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
actual = 4
expected = 2.5
expect(actual).to eq(expected)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(actual).to eq(expected)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual '4'
plain ' to eq '
expected '2.5'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing regexps (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
actual = /test/
expected = /another regexp/
expect(actual).to eq(expected)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(actual).to eq(expected)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual '/test/'
plain ' to eq '
expected '/another regexp/'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing classes (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
class Test; end
class AnotherClass; end
expect(Test.new).to eq(AnotherClass.new)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(Test.new).to eq(AnotherClass.new)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual '#<Test>'
plain ' to eq '
expected '#<AnotherClass>'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing Modules (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
module Test; end
module AnotherClass; end
expect(Test).to eq(AnotherClass)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(Test).to eq(AnotherClass)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual 'Test'
plain ' to eq '
expected 'AnotherClass'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

context 'when comparing strings (a kind of primitive)' do
it 'generates the correct expectation and does not generate a diff' do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~TEST.strip
actual = 'test'
expected = 'another string'
expect(actual).to eq(expected)
TEST
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: 'expect(actual).to eq(expected)',
newline_before_expectation: false,
expectation: proc do
line do
plain 'Expected '
actual '"test"'
plain ' to eq '
expected '"another string"'
plain '.'
end
end,
diff: nil
)

expect(program).to produce_output_when_run(expected_output).in_color(
color_enabled
).removing_object_ids
end
end
end

it_behaves_like 'a matcher that supports elided diffs' do
let(:matcher) { :eq }
end
Expand Down

0 comments on commit ba1ba2c

Please sign in to comment.