From 8c827b6d0919dd0efdd0f705e24826f19b2563d4 Mon Sep 17 00:00:00 2001 From: Lucas Eras Paiva Date: Fri, 8 Nov 2024 16:40:47 -0600 Subject: [PATCH] Exclude more un-diffable objects (#273) 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` --- lib/super_diff/rspec/differ.rb | 13 +- spec/integration/rspec/eq_matcher_spec.rb | 306 ++++++++++++++++++++++ 2 files changed, 316 insertions(+), 3 deletions(-) diff --git a/lib/super_diff/rspec/differ.rb b/lib/super_diff/rspec/differ.rb index fa48d3b8..b0b21af6 100644 --- a/lib/super_diff/rspec/differ.rb +++ b/lib/super_diff/rspec/differ.rb @@ -22,7 +22,7 @@ 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? @@ -30,8 +30,15 @@ def comparing_inequal_values? 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? diff --git a/spec/integration/rspec/eq_matcher_spec.rb b/spec/integration/rspec/eq_matcher_spec.rb index aed869e1..d32aa1c5 100644 --- a/spec/integration/rspec/eq_matcher_spec.rb +++ b/spec/integration/rspec/eq_matcher_spec.rb @@ -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 '#' + plain ' to eq ' + expected '#' + 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 '#' + plain ' to eq ' + expected '#' + 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