From fa6618e1ba99fe51ea54bdf6c0bf4b6424a9e02b Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Sat, 13 Feb 2021 19:21:21 -0700 Subject: [PATCH] Move ObjectInspection.inspect It isn't good to name a method `inspect`, even if it's on the class level. This prevents the class from being inspected, which can easily happen automatically in an IRB console. --- lib/super_diff.rb | 8 + lib/super_diff/diff_formatters/collection.rb | 2 +- lib/super_diff/equality_matchers/array.rb | 4 +- lib/super_diff/equality_matchers/default.rb | 4 +- lib/super_diff/equality_matchers/hash.rb | 4 +- .../equality_matchers/multiline_string.rb | 4 +- lib/super_diff/equality_matchers/primitive.rb | 4 +- .../equality_matchers/singleline_string.rb | 4 +- lib/super_diff/object_inspection.rb | 8 - .../object_inspection/nodes/inspection.rb | 2 +- lib/super_diff/rspec/monkey_patches.rb | 4 +- .../inspectors/main_spec.rb} | 138 +- spec/unit/super_diff_spec.rb | 1228 +++++++++++++++++ 13 files changed, 1321 insertions(+), 93 deletions(-) rename spec/unit/{object_inspection_spec.rb => object_inspection/inspectors/main_spec.rb} (90%) create mode 100644 spec/unit/super_diff_spec.rb diff --git a/lib/super_diff.rb b/lib/super_diff.rb index 7377acf1..57e7e28f 100644 --- a/lib/super_diff.rb +++ b/lib/super_diff.rb @@ -30,6 +30,14 @@ def self.configuration @_configuration ||= Configuration.new end + def self.inspect_object(object, as_single_line:, indent_level: 0) + ObjectInspection::Inspectors::Main.call( + object, + as_single_line: as_single_line, + indent_level: indent_level, + ) + end + def self.time_like?(value) # Check for ActiveSupport's #acts_like_time? for their time-like objects # (like ActiveSupport::TimeWithZone). diff --git a/lib/super_diff/diff_formatters/collection.rb b/lib/super_diff/diff_formatters/collection.rb index af96d3da..5c4defa2 100644 --- a/lib/super_diff/diff_formatters/collection.rb +++ b/lib/super_diff/diff_formatters/collection.rb @@ -94,7 +94,7 @@ def build_chunk_for(operation, prefix:, icon:) end def build_chunk_by_inspecting(value, prefix:, icon:) - inspection = ObjectInspection.inspect( + inspection = SuperDiff.inspect_object( value, as_single_line: false, ) diff --git a/lib/super_diff/equality_matchers/array.rb b/lib/super_diff/equality_matchers/array.rb index c4cd0f22..e6c74e3c 100644 --- a/lib/super_diff/equality_matchers/array.rb +++ b/lib/super_diff/equality_matchers/array.rb @@ -13,14 +13,14 @@ def fail Helpers.style( :expected, "Expected: " + - ObjectInspection.inspect(expected, as_single_line: true), + SuperDiff.inspect_object(expected, as_single_line: true), ) } #{ Helpers.style( :actual, " Actual: " + - ObjectInspection.inspect(actual, as_single_line: true), + SuperDiff.inspect_object(actual, as_single_line: true), ) } diff --git a/lib/super_diff/equality_matchers/default.rb b/lib/super_diff/equality_matchers/default.rb index ca062855..7c3e9db6 100644 --- a/lib/super_diff/equality_matchers/default.rb +++ b/lib/super_diff/equality_matchers/default.rb @@ -21,7 +21,7 @@ def expected_line Helpers.style( :expected, "Expected: " + - ObjectInspection.inspect(expected, as_single_line: true), + SuperDiff.inspect_object(expected, as_single_line: true), ) end @@ -29,7 +29,7 @@ def actual_line Helpers.style( :actual, " Actual: " + - ObjectInspection.inspect(actual, as_single_line: true), + SuperDiff.inspect_object(actual, as_single_line: true), ) end diff --git a/lib/super_diff/equality_matchers/hash.rb b/lib/super_diff/equality_matchers/hash.rb index e19c2479..044f1c5e 100644 --- a/lib/super_diff/equality_matchers/hash.rb +++ b/lib/super_diff/equality_matchers/hash.rb @@ -13,14 +13,14 @@ def fail Helpers.style( :expected, "Expected: " + - ObjectInspection.inspect(expected, as_single_line: true), + SuperDiff.inspect_object(expected, as_single_line: true), ) } #{ Helpers.style( :actual, " Actual: " + - ObjectInspection.inspect(actual, as_single_line: true), + SuperDiff.inspect_object(actual, as_single_line: true), ) } diff --git a/lib/super_diff/equality_matchers/multiline_string.rb b/lib/super_diff/equality_matchers/multiline_string.rb index 118921dc..0fb83680 100644 --- a/lib/super_diff/equality_matchers/multiline_string.rb +++ b/lib/super_diff/equality_matchers/multiline_string.rb @@ -14,14 +14,14 @@ def fail Helpers.style( :expected, "Expected: " + - ObjectInspection.inspect(expected, as_single_line: true), + SuperDiff.inspect_object(expected, as_single_line: true), ) } #{ Helpers.style( :actual, " Actual: " + - ObjectInspection.inspect(actual, as_single_line: true), + SuperDiff.inspect_object(actual, as_single_line: true), ) } diff --git a/lib/super_diff/equality_matchers/primitive.rb b/lib/super_diff/equality_matchers/primitive.rb index cbb97422..08688986 100644 --- a/lib/super_diff/equality_matchers/primitive.rb +++ b/lib/super_diff/equality_matchers/primitive.rb @@ -17,14 +17,14 @@ def fail Helpers.style( :expected, "Expected: " + - ObjectInspection.inspect(expected, as_single_line: true), + SuperDiff.inspect_object(expected, as_single_line: true), ) } #{ Helpers.style( :actual, " Actual: " + - ObjectInspection.inspect(actual, as_single_line: true), + SuperDiff.inspect_object(actual, as_single_line: true), ) } OUTPUT diff --git a/lib/super_diff/equality_matchers/singleline_string.rb b/lib/super_diff/equality_matchers/singleline_string.rb index 0ec6c963..4902430b 100644 --- a/lib/super_diff/equality_matchers/singleline_string.rb +++ b/lib/super_diff/equality_matchers/singleline_string.rb @@ -13,14 +13,14 @@ def fail Helpers.style( :expected, "Expected: " + - ObjectInspection.inspect(expected, as_single_line: true), + SuperDiff.inspect_object(expected, as_single_line: true), ) } #{ Helpers.style( :actual, " Actual: " + - ObjectInspection.inspect(actual, as_single_line: true), + SuperDiff.inspect_object(actual, as_single_line: true), ) } OUTPUT diff --git a/lib/super_diff/object_inspection.rb b/lib/super_diff/object_inspection.rb index 471bd79c..e54f50c9 100644 --- a/lib/super_diff/object_inspection.rb +++ b/lib/super_diff/object_inspection.rb @@ -3,13 +3,5 @@ module ObjectInspection autoload :InspectionTree, "super_diff/object_inspection/inspection_tree" autoload :Inspectors, "super_diff/object_inspection/inspectors" autoload :Nodes, "super_diff/object_inspection/nodes" - - def self.inspect(object, as_single_line:, indent_level: 0) - Inspectors::Main.call( - object, - as_single_line: as_single_line, - indent_level: indent_level, - ) - end end end diff --git a/lib/super_diff/object_inspection/nodes/inspection.rb b/lib/super_diff/object_inspection/nodes/inspection.rb index 6952c63a..9f52a429 100644 --- a/lib/super_diff/object_inspection/nodes/inspection.rb +++ b/lib/super_diff/object_inspection/nodes/inspection.rb @@ -10,7 +10,7 @@ def evaluate(object, indent_level:, as_single_line:) immediate_value end - SuperDiff::ObjectInspection.inspect( + SuperDiff.inspect_object( value, indent_level: indent_level, as_single_line: as_single_line, diff --git a/lib/super_diff/rspec/monkey_patches.rb b/lib/super_diff/rspec/monkey_patches.rb index 372e0350..cd1b440f 100644 --- a/lib/super_diff/rspec/monkey_patches.rb +++ b/lib/super_diff/rspec/monkey_patches.rb @@ -255,12 +255,12 @@ module Support class ObjectFormatter # Override to use our formatting algorithm def self.format(value) - SuperDiff::ObjectInspection.inspect(value, as_single_line: true) + SuperDiff.inspect_object(value, as_single_line: true) end # Override to use our formatting algorithm def format(value) - SuperDiff::ObjectInspection.inspect(value, as_single_line: true) + SuperDiff.inspect_object(value, as_single_line: true) end end end diff --git a/spec/unit/object_inspection_spec.rb b/spec/unit/object_inspection/inspectors/main_spec.rb similarity index 90% rename from spec/unit/object_inspection_spec.rb rename to spec/unit/object_inspection/inspectors/main_spec.rb index 10dbbdb8..dd109666 100644 --- a/spec/unit/object_inspection_spec.rb +++ b/spec/unit/object_inspection/inspectors/main_spec.rb @@ -1,18 +1,18 @@ require "spec_helper" -RSpec.describe SuperDiff::ObjectInspection do - describe ".inspect" do +RSpec.describe SuperDiff::ObjectInspection::Inspectors::Main do + describe ".call" do context "given nil" do context "given as_single_line: true" do it "returns nil, inspected" do - inspection = described_class.inspect(nil, as_single_line: true) + inspection = described_class.call(nil, as_single_line: true) expect(inspection).to eq("nil") end end context "given as_single_line: false" do it "returns nil, inspected" do - inspection = described_class.inspect(nil, as_single_line: false) + inspection = described_class.call(nil, as_single_line: false) expect(inspection).to eq("nil") end end @@ -21,14 +21,14 @@ context "given true" do context "given as_single_line: true" do it "returns nil, inspected" do - inspection = described_class.inspect(nil, as_single_line: true) + inspection = described_class.call(nil, as_single_line: true) expect(inspection).to eq("nil") end end context "given as_single_line: false" do it "returns nil, inspected" do - inspection = described_class.inspect(nil, as_single_line: false) + inspection = described_class.call(nil, as_single_line: false) expect(inspection).to eq("nil") end end @@ -37,14 +37,14 @@ context "given false" do context "given as_single_line: false" do it "returns false, inspected" do - inspection = described_class.inspect(false, as_single_line: false) + inspection = described_class.call(false, as_single_line: false) expect(inspection).to eq("false") end end context "given as_single_line: false" do it "returns false, inspected" do - inspection = described_class.inspect(false, as_single_line: false) + inspection = described_class.call(false, as_single_line: false) expect(inspection).to eq("false") end end @@ -53,14 +53,14 @@ context "given a number" do context "given as_single_line: true" do it "returns the number as a string" do - inspection = described_class.inspect(3, as_single_line: true) + inspection = described_class.call(3, as_single_line: true) expect(inspection).to eq("3") end end context "given as_single_line: false" do it "returns the number as a string" do - inspection = described_class.inspect(3, as_single_line: false) + inspection = described_class.call(3, as_single_line: false) expect(inspection).to eq("3") end end @@ -69,14 +69,14 @@ context "given a symbol" do context "given as_single_line: true" do it "returns the symbol, inspected" do - inspection = described_class.inspect(:foo, as_single_line: true) + inspection = described_class.call(:foo, as_single_line: true) expect(inspection).to eq(":foo") end end context "given as_single_line: false" do it "returns the symbol, inspected" do - inspection = described_class.inspect(:foo, as_single_line: false) + inspection = described_class.call(:foo, as_single_line: false) expect(inspection).to eq(":foo") end end @@ -85,14 +85,14 @@ context "given a regex" do context "given as_single_line: true" do it "returns the regex, inspected" do - inspection = described_class.inspect(/foo/, as_single_line: true) + inspection = described_class.call(/foo/, as_single_line: true) expect(inspection).to eq("/foo/") end end context "given as_single_line: false" do it "returns the regex, inspected" do - inspection = described_class.inspect(/foo/, as_single_line: false) + inspection = described_class.call(/foo/, as_single_line: false) expect(inspection).to eq("/foo/") end end @@ -100,7 +100,7 @@ context "given a single-line string" do it "returns the string surrounded by quotes" do - inspection = described_class.inspect("Marty", as_single_line: true) + inspection = described_class.call("Marty", as_single_line: true) expect(inspection).to eq('"Marty"') end end @@ -108,7 +108,7 @@ context "given a multi-line string" do context "that does not contain color codes" do it "returns the string surrounded by quotes, with newline characters escaped" do - inspection = described_class.inspect( + inspection = described_class.call( "This is a line\nAnd that's a line\nAnd there's a line too", as_single_line: true, ) @@ -141,7 +141,7 @@ colorize("And there's a line too", colors[2]), ].join("\n") - inspection = described_class.inspect( + inspection = described_class.call( string_to_inspect, as_single_line: true, ) @@ -158,7 +158,7 @@ context "containing only primitive values" do context "given as_single_line: true" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( ["foo", 2, :baz], as_single_line: true, ) @@ -168,7 +168,7 @@ context "given as_single_line: false" do it "returns a representation of the array across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( ["foo", 2, :baz], as_single_line: false, ) @@ -186,7 +186,7 @@ context "containing other arrays" do context "given as_single_line: true" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( [ "foo", ["bar", "baz"], @@ -200,7 +200,7 @@ context "given as_single_line: false" do it "returns a representation of the array across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( [ "foo", ["bar", "baz"], @@ -225,14 +225,14 @@ context "which is empty" do context "given as_single_line: true" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect([], as_single_line: true) + inspection = described_class.call([], as_single_line: true) expect(inspection).to eq(%([])) end end context "given as_single_line: false" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect([], as_single_line: false) + inspection = described_class.call([], as_single_line: false) expect(inspection).to eq(%([])) end end @@ -244,7 +244,7 @@ context "where all of the keys are symbols" do context "given as_single_line: true" do it "returns a representation of the hash on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( # rubocop:disable Style/HashSyntax { :foo => "bar", :baz => "qux" }, # rubocop:enable Style/HashSyntax @@ -256,7 +256,7 @@ context "given as_single_line: false" do it "returns a representation of the hash across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( # rubocop:disable Style/HashSyntax { :foo => "bar", :baz => "qux" }, # rubocop:enable Style/HashSyntax @@ -275,7 +275,7 @@ context "where only some of the keys are symbols" do context "given as_single_line: true" do it "returns a representation of the hash on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( { :foo => "bar", 2 => "baz" }, as_single_line: true, ) @@ -285,7 +285,7 @@ context "given as_single_line: false" do it "returns a representation of the hash across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( { :foo => "bar", 2 => "baz" }, as_single_line: false, ) @@ -314,7 +314,7 @@ :number_of_products => 2, # rubocop:enable Style/HashSyntax } - inspection = described_class.inspect( + inspection = described_class.call( value_to_inspect, as_single_line: true, ) @@ -338,7 +338,7 @@ :number_of_products => 2, # rubocop:enable Style/HashSyntax } - inspection = described_class.inspect( + inspection = described_class.call( value_to_inspect, as_single_line: false, ) @@ -365,14 +365,14 @@ context "which is empty" do context "given as_single_line: true" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect({}, as_single_line: true) + inspection = described_class.call({}, as_single_line: true) expect(inspection).to eq(%({})) end end context "given as_single_line: false" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect({}, as_single_line: false) + inspection = described_class.call({}, as_single_line: false) expect(inspection).to eq(%({})) end end @@ -382,7 +382,7 @@ context "given a class" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Person, as_single_line: true, ) @@ -392,7 +392,7 @@ context "given as_single_line: false" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Person, as_single_line: false, ) @@ -405,7 +405,7 @@ context "containing only primitive values" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Person.new(name: "Doc", age: 58), as_single_line: true, ) @@ -417,7 +417,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Person.new(name: "Doc", age: 58), as_single_line: false, ) @@ -434,7 +434,7 @@ context "containing other custom objects" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Customer.new( name: "Marty McFly", shipping_address: SuperDiff::Test::ShippingAddress.new( @@ -458,7 +458,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Customer.new( name: "Marty McFly", shipping_address: SuperDiff::Test::ShippingAddress.new( @@ -494,7 +494,7 @@ context "containing only primitive values" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Item.new( name: "mac and cheese", quantity: 2, @@ -511,7 +511,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Item.new( name: "mac and cheese", quantity: 2, @@ -532,7 +532,7 @@ context "containing other custom objects" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Order.new([ SuperDiff::Test::Item.new(name: "ham", quantity: 1), SuperDiff::Test::Item.new(name: "eggs", quantity: 2), @@ -550,7 +550,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Order.new([ SuperDiff::Test::Item.new(name: "ham", quantity: 1), SuperDiff::Test::Item.new(name: "eggs", quantity: 2), @@ -584,7 +584,7 @@ context "which is empty" do context "given as_single_line: true" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::EmptyClass.new, as_single_line: true, ) @@ -596,7 +596,7 @@ context "given as_single_line: false" do it "returns a representation of the array on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::EmptyClass.new, as_single_line: false, ) @@ -611,7 +611,7 @@ context "given a hash-including-" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( a_hash_including(foo: "bar", baz: "qux"), as_single_line: true, ) @@ -624,7 +624,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( a_hash_including(foo: "bar", baz: "qux"), as_single_line: false, ) @@ -642,7 +642,7 @@ context "given a collection-including-" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( a_collection_including(1, 2, 3), as_single_line: true, ) @@ -655,7 +655,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( a_collection_including(1, 2, 3), as_single_line: false, ) @@ -674,7 +674,7 @@ context "given a fuzzy object" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( an_object_having_attributes(foo: "bar", baz: "qux"), as_single_line: true, ) @@ -687,7 +687,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( an_object_having_attributes(foo: "bar", baz: "qux"), as_single_line: false, ) @@ -705,7 +705,7 @@ context "given a collection-containing-exactly-" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( a_collection_containing_exactly("foo", "bar", "baz"), as_single_line: true, ) @@ -718,7 +718,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( a_collection_containing_exactly("foo", "bar", "baz"), as_single_line: false, ) @@ -737,7 +737,7 @@ context "given a kind-of-" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( a_kind_of(Symbol), as_single_line: true, ) @@ -748,7 +748,7 @@ context "given as_single_line: false" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( a_kind_of(Symbol), as_single_line: false, ) @@ -761,7 +761,7 @@ context "given an-instance-of-" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( an_instance_of(Symbol), as_single_line: true, ) @@ -772,7 +772,7 @@ context "given as_single_line: false" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( an_instance_of(Symbol), as_single_line: false, ) @@ -785,7 +785,7 @@ context "given a-value-within-" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( a_value_within(1).of(Time.utc(2020, 4, 9)), as_single_line: true, ) @@ -798,7 +798,7 @@ context "given as_single_line: false" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( a_value_within(1).of(Time.utc(2020, 4, 9)), as_single_line: false, ) @@ -814,7 +814,7 @@ context "that is anonymous" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( double(foo: "bar", baz: "qux"), as_single_line: true, ) @@ -825,7 +825,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( double(foo: "bar", baz: "qux"), as_single_line: false, ) @@ -839,7 +839,7 @@ context "given an ActiveRecord object", active_record: true do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Models::ActiveRecord::Person.new( name: "Elliot", age: 31, @@ -855,7 +855,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Models::ActiveRecord::Person.new( name: "Elliot", age: 31, @@ -886,7 +886,7 @@ age: 17, ) - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Models::ActiveRecord::Person.all, as_single_line: true, ) @@ -908,7 +908,7 @@ age: 17, ) - inspection = described_class.inspect( + inspection = described_class.call( SuperDiff::Test::Models::ActiveRecord::Person.all, as_single_line: false, ) @@ -934,7 +934,7 @@ context "given a HashWithIndifferentAccess", active_record: true do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( HashWithIndifferentAccess.new({ line_1: "123 Main St.", city: "Hill Valley", @@ -952,7 +952,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( HashWithIndifferentAccess.new({ line_1: "123 Main St.", city: "Hill Valley", @@ -977,7 +977,7 @@ context "given a combination of all kinds of values" do context "given as_single_line: true" do it "returns a representation of the object on a single line" do - inspection = described_class.inspect( + inspection = described_class.call( { state: :down, errors: [ @@ -1031,7 +1031,7 @@ context "given as_single_line: false" do it "returns a representation of the object across multiple lines" do - inspection = described_class.inspect( + inspection = described_class.call( { state: :down, errors: [ @@ -1140,7 +1140,7 @@ it "replaces the reference with ∙∙∙" do value = ["a", "b", "c"] value.insert(1, value) - inspection = described_class.inspect(value, as_single_line: true) + inspection = described_class.call(value, as_single_line: true) expect(inspection).to eq(%(["a", ∙∙∙, "b", "c"])) end end @@ -1149,7 +1149,7 @@ it "replaces the reference with ∙∙∙" do value = ["a", "b", "c"] value.insert(1, value) - inspection = described_class.inspect(value, as_single_line: false) + inspection = described_class.call(value, as_single_line: false) expect(inspection).to eq(<<~INSPECTION.rstrip) [ "a", diff --git a/spec/unit/super_diff_spec.rb b/spec/unit/super_diff_spec.rb new file mode 100644 index 00000000..24ba93be --- /dev/null +++ b/spec/unit/super_diff_spec.rb @@ -0,0 +1,1228 @@ +require "spec_helper" + +RSpec.describe SuperDiff do + describe ".inspect_object" do + context "given nil" do + context "given as_single_line: true" do + it "returns nil, inspected" do + inspection = described_class.inspect_object( + nil, + as_single_line: true, + ) + expect(inspection).to eq("nil") + end + end + + context "given as_single_line: false" do + it "returns nil, inspected" do + inspection = described_class.inspect_object( + nil, + as_single_line: false, + ) + expect(inspection).to eq("nil") + end + end + end + + context "given true" do + context "given as_single_line: true" do + it "returns nil, inspected" do + inspection = described_class.inspect_object( + nil, + as_single_line: true, + ) + expect(inspection).to eq("nil") + end + end + + context "given as_single_line: false" do + it "returns nil, inspected" do + inspection = described_class.inspect_object( + nil, + as_single_line: false, + ) + expect(inspection).to eq("nil") + end + end + end + + context "given false" do + context "given as_single_line: false" do + it "returns false, inspected" do + inspection = described_class.inspect_object( + false, + as_single_line: false, + ) + expect(inspection).to eq("false") + end + end + + context "given as_single_line: false" do + it "returns false, inspected" do + inspection = described_class.inspect_object( + false, + as_single_line: false, + ) + expect(inspection).to eq("false") + end + end + end + + context "given a number" do + context "given as_single_line: true" do + it "returns the number as a string" do + inspection = described_class.inspect_object( + 3, + as_single_line: true, + ) + expect(inspection).to eq("3") + end + end + + context "given as_single_line: false" do + it "returns the number as a string" do + inspection = described_class.inspect_object( + 3, + as_single_line: false, + ) + expect(inspection).to eq("3") + end + end + end + + context "given a symbol" do + context "given as_single_line: true" do + it "returns the symbol, inspected" do + inspection = described_class.inspect_object( + :foo, + as_single_line: true, + ) + expect(inspection).to eq(":foo") + end + end + + context "given as_single_line: false" do + it "returns the symbol, inspected" do + inspection = described_class.inspect_object( + :foo, + as_single_line: false, + ) + expect(inspection).to eq(":foo") + end + end + end + + context "given a regex" do + context "given as_single_line: true" do + it "returns the regex, inspected" do + inspection = described_class.inspect_object( + /foo/, + as_single_line: true, + ) + expect(inspection).to eq("/foo/") + end + end + + context "given as_single_line: false" do + it "returns the regex, inspected" do + inspection = described_class.inspect_object( + /foo/, + as_single_line: false, + ) + expect(inspection).to eq("/foo/") + end + end + end + + context "given a single-line string" do + it "returns the string surrounded by quotes" do + inspection = described_class.inspect_object( + "Marty", + as_single_line: true, + ) + expect(inspection).to eq('"Marty"') + end + end + + context "given a multi-line string" do + context "that does not contain color codes" do + it "returns the string surrounded by quotes, with newline characters escaped" do + inspection = described_class.inspect_object( + "This is a line\nAnd that's a line\nAnd there's a line too", + as_single_line: true, + ) + expect(inspection).to eq( + %("This is a line\\nAnd that's a line\\nAnd there's a line too"), + ) + end + end + + context "that contains color codes" do + it "escapes the color codes" do + colors = [ + SuperDiff::Csi::FourBitColor.new(:blue, layer: :foreground), + SuperDiff::Csi::EightBitColor.new( + red: 3, + green: 8, + blue: 4, + layer: :foreground, + ), + SuperDiff::Csi::TwentyFourBitColor.new( + red: 47, + green: 164, + blue: 59, + layer: :foreground, + ), + ] + string_to_inspect = [ + colorize("This is a line", colors[0]), + colorize("And that's a line", colors[1]), + colorize("And there's a line too", colors[2]), + ].join("\n") + + inspection = described_class.inspect_object( + string_to_inspect, + as_single_line: true, + ) + # TODO: Figure out how to represent a colorized string inside of an + # already colorized string + expect(inspection).to eq(<<~INSPECTION.rstrip) + "\\e[34mThis is a line\\e[0m\\n\\e[38;5;176mAnd that's a line\\e[0m\\n\\e[38;2;47;59;164mAnd there's a line too\\e[0m" + INSPECTION + end + end + end + + context "given an array" do + context "containing only primitive values" do + context "given as_single_line: true" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + ["foo", 2, :baz], + as_single_line: true, + ) + expect(inspection).to eq(%(["foo", 2, :baz])) + end + end + + context "given as_single_line: false" do + it "returns a representation of the array across multiple lines" do + inspection = described_class.inspect_object( + ["foo", 2, :baz], + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + [ + "foo", + 2, + :baz + ] + INSPECTION + end + end + end + + context "containing other arrays" do + context "given as_single_line: true" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + [ + "foo", + ["bar", "baz"], + "qux", + ], + as_single_line: true, + ) + expect(inspection).to eq(%(["foo", ["bar", "baz"], "qux"])) + end + end + + context "given as_single_line: false" do + it "returns a representation of the array across multiple lines" do + inspection = described_class.inspect_object( + [ + "foo", + ["bar", "baz"], + "qux", + ], + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + [ + "foo", + [ + "bar", + "baz" + ], + "qux" + ] + INSPECTION + end + end + end + + context "which is empty" do + context "given as_single_line: true" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + [], + as_single_line: true, + ) + expect(inspection).to eq(%([])) + end + end + + context "given as_single_line: false" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + [], + as_single_line: false, + ) + expect(inspection).to eq(%([])) + end + end + end + end + + context "given a hash" do + context "containing only primitive values" do + context "where all of the keys are symbols" do + context "given as_single_line: true" do + it "returns a representation of the hash on a single line" do + inspection = described_class.inspect_object( + # rubocop:disable Style/HashSyntax + { :foo => "bar", :baz => "qux" }, + # rubocop:enable Style/HashSyntax + as_single_line: true, + ) + expect(inspection).to eq(%({ foo: "bar", baz: "qux" })) + end + end + + context "given as_single_line: false" do + it "returns a representation of the hash across multiple lines" do + inspection = described_class.inspect_object( + # rubocop:disable Style/HashSyntax + { :foo => "bar", :baz => "qux" }, + # rubocop:enable Style/HashSyntax + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + { + foo: "bar", + baz: "qux" + } + INSPECTION + end + end + end + + context "where only some of the keys are symbols" do + context "given as_single_line: true" do + it "returns a representation of the hash on a single line" do + inspection = described_class.inspect_object( + { :foo => "bar", 2 => "baz" }, + as_single_line: true, + ) + expect(inspection).to eq(%({ :foo => "bar", 2 => "baz" })) + end + end + + context "given as_single_line: false" do + it "returns a representation of the hash across multiple lines" do + inspection = described_class.inspect_object( + { :foo => "bar", 2 => "baz" }, + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + { + :foo => "bar", + 2 => "baz" + } + INSPECTION + end + end + end + end + + context "containing other hashes" do + context "given as_single_line: true" do + it "returns a representation of the hash on a single line" do + # TODO: Update this with a key/value pair before AND after + value_to_inspect = { + # rubocop:disable Style/HashSyntax + :category_name => "Appliances", + :products_by_sku => { + "EMDL-2934" => { :id => 4, :name => "Jordan Air" }, + "KDS-3912" => { :id => 8, :name => "Chevy Impala" }, + }, + :number_of_products => 2, + # rubocop:enable Style/HashSyntax + } + inspection = described_class.inspect_object( + value_to_inspect, + as_single_line: true, + ) + # rubocop:disable Metrics/LineLength + expect(inspection).to eq( + %({ category_name: "Appliances", products_by_sku: { "EMDL-2934" => { id: 4, name: "Jordan Air" }, "KDS-3912" => { id: 8, name: "Chevy Impala" } }, number_of_products: 2 }), + ) + # rubocop:enable Metrics/LineLength + end + end + + context "given as_single_line: false" do + it "returns a representation of the array across multiple lines" do + value_to_inspect = { + # rubocop:disable Style/HashSyntax + :category_name => "Appliances", + :products_by_sku => { + "EMDL-2934" => { :id => 4, :name => "George Foreman Grill" }, + "KDS-3912" => { :id => 8, :name => "Magic Bullet" }, + }, + :number_of_products => 2, + # rubocop:enable Style/HashSyntax + } + inspection = described_class.inspect_object( + value_to_inspect, + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + { + category_name: "Appliances", + products_by_sku: { + "EMDL-2934" => { + id: 4, + name: "George Foreman Grill" + }, + "KDS-3912" => { + id: 8, + name: "Magic Bullet" + } + }, + number_of_products: 2 + } + INSPECTION + end + end + end + + context "which is empty" do + context "given as_single_line: true" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + {}, + as_single_line: true, + ) + expect(inspection).to eq(%({})) + end + end + + context "given as_single_line: false" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + {}, + as_single_line: false, + ) + expect(inspection).to eq(%({})) + end + end + end + end + + context "given a class" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::Person, + as_single_line: true, + ) + expect(inspection).to eq("SuperDiff::Test::Person") + end + end + + context "given as_single_line: false" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::Person, + as_single_line: false, + ) + expect(inspection).to eq("SuperDiff::Test::Person") + end + end + end + + context "given a custom object" do + context "containing only primitive values" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::Person.new(name: "Doc", age: 58), + as_single_line: true, + ) + expect(inspection).to eq( + %(#), + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + SuperDiff::Test::Person.new(name: "Doc", age: 58), + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + # + INSPECTION + end + end + end + + context "containing other custom objects" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::Customer.new( + name: "Marty McFly", + shipping_address: SuperDiff::Test::ShippingAddress.new( + line_1: "123 Main St.", + line_2: "", + city: "Hill Valley", + state: "CA", + zip: "90382", + ), + phone: "111-222-3333", + ), + as_single_line: true, + ) + expect(inspection).to eq( + # rubocop:disable Metrics/LineLength + %(#, phone: "111-222-3333">), + # rubocop:enable Metrics/LineLength + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + SuperDiff::Test::Customer.new( + name: "Marty McFly", + shipping_address: SuperDiff::Test::ShippingAddress.new( + line_1: "123 Main St.", + line_2: "", + city: "Hill Valley", + state: "CA", + zip: "90382", + ), + phone: "111-222-3333", + ), + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + #, + phone: "111-222-3333" + }> + INSPECTION + end + end + end + end + + context "given a non-custom object" do + context "containing only primitive values" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::Item.new( + name: "mac and cheese", + quantity: 2, + ), + as_single_line: true, + ) + expect(inspection).to match( + # rubocop:disable Metrics/LineLength + /\A#\Z/, + # rubocop:enable Metrics/LineLength + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + SuperDiff::Test::Item.new( + name: "mac and cheese", + quantity: 2, + ), + as_single_line: false, + ) + regexp = <<~INSPECTION.rstrip + # + INSPECTION + expect(inspection).to match(/\A#{regexp}\Z/) + end + end + end + + context "containing other custom objects" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::Order.new([ + SuperDiff::Test::Item.new(name: "ham", quantity: 1), + SuperDiff::Test::Item.new(name: "eggs", quantity: 2), + SuperDiff::Test::Item.new(name: "cheese", quantity: 1), + ]), + as_single_line: true, + ) + expect(inspection).to match( + # rubocop:disable Metrics/LineLength + /\A#, #, #\]>\Z/, + # rubocop:enable Metrics/LineLength + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + SuperDiff::Test::Order.new([ + SuperDiff::Test::Item.new(name: "ham", quantity: 1), + SuperDiff::Test::Item.new(name: "eggs", quantity: 2), + SuperDiff::Test::Item.new(name: "cheese", quantity: 1), + ]), + as_single_line: false, + ) + regexp = <<~INSPECTION.rstrip + #, + #, + # + \\] + \\}> + INSPECTION + expect(inspection).to match(/\A#{regexp}\Z/) + end + end + end + + context "which is empty" do + context "given as_single_line: true" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::EmptyClass.new, + as_single_line: true, + ) + expect(inspection).to match( + /#/, + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the array on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::EmptyClass.new, + as_single_line: false, + ) + expect(inspection).to match( + /#/, + ) + end + end + end + end + + context "given a hash-including-" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + a_hash_including(foo: "bar", baz: "qux"), + as_single_line: true, + ) + + expect(inspection).to eq( + %(#), + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + a_hash_including(foo: "bar", baz: "qux"), + as_single_line: false, + ) + + expect(inspection).to eq(<<~INSPECTION.rstrip) + # + INSPECTION + end + end + end + + context "given a collection-including-" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + a_collection_including(1, 2, 3), + as_single_line: true, + ) + + expect(inspection).to eq( + %(#), + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + a_collection_including(1, 2, 3), + as_single_line: false, + ) + + expect(inspection).to eq(<<~INSPECTION.rstrip) + # + INSPECTION + end + end + end + + context "given a fuzzy object" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + an_object_having_attributes(foo: "bar", baz: "qux"), + as_single_line: true, + ) + + expect(inspection).to eq( + %(#), + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + an_object_having_attributes(foo: "bar", baz: "qux"), + as_single_line: false, + ) + + expect(inspection).to eq(<<~INSPECTION.rstrip) + # + INSPECTION + end + end + end + + context "given a collection-containing-exactly-" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + a_collection_containing_exactly("foo", "bar", "baz"), + as_single_line: true, + ) + + expect(inspection).to eq( + %(#), + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + a_collection_containing_exactly("foo", "bar", "baz"), + as_single_line: false, + ) + + expect(inspection).to eq(<<~INSPECTION.rstrip) + # + INSPECTION + end + end + end + + context "given a kind-of-" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + a_kind_of(Symbol), + as_single_line: true, + ) + + expect(inspection).to eq(%(#)) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + a_kind_of(Symbol), + as_single_line: false, + ) + + expect(inspection).to eq(%(#)) + end + end + end + + context "given an-instance-of-" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + an_instance_of(Symbol), + as_single_line: true, + ) + + expect(inspection).to eq(%(#)) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + an_instance_of(Symbol), + as_single_line: false, + ) + + expect(inspection).to eq(%(#)) + end + end + end + + context "given a-value-within-" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + a_value_within(1).of(Time.utc(2020, 4, 9)), + as_single_line: true, + ) + + expect(inspection).to eq( + %(#), + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + a_value_within(1).of(Time.utc(2020, 4, 9)), + as_single_line: false, + ) + + expect(inspection).to eq( + %(#), + ) + end + end + end + + context "given a Double" do + context "that is anonymous" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + double(foo: "bar", baz: "qux"), + as_single_line: true, + ) + + expect(inspection).to eq("#") + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + double(foo: "bar", baz: "qux"), + as_single_line: false, + ) + + expect(inspection).to eq("#") + end + end + end + end + + context "given an ActiveRecord object", active_record: true do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + SuperDiff::Test::Models::ActiveRecord::Person.new( + name: "Elliot", + age: 31, + ), + as_single_line: true, + ) + + # rubocop:disable Metrics/LineLength + expect(inspection).to eq( + %(#), + ) + # rubocop:enable Metrics/LineLength + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + SuperDiff::Test::Models::ActiveRecord::Person.new( + name: "Elliot", + age: 31, + ), + as_single_line: false, + ) + + expect(inspection).to eq(<<~INSPECTION.rstrip) + # + INSPECTION + end + end + end + + context "given an ActiveRecord::Relation object", active_record: true do + context "given as_single_line: true" do + it "returns a representation of the Relation on a single line" do + SuperDiff::Test::Models::ActiveRecord::Person.create!( + name: "Marty", + age: 19, + ) + SuperDiff::Test::Models::ActiveRecord::Person.create!( + name: "Jennifer", + age: 17, + ) + + inspection = described_class.inspect_object( + SuperDiff::Test::Models::ActiveRecord::Person.all, + as_single_line: true, + ) + + # rubocop:disable Metrics/LineLength + expect(inspection).to eq( + %(#, #]>), + ) + # rubocop:enable Metrics/LineLength + end + end + + context "given as_single_line: false" do + it "returns a representation of the Relation across multiple lines" do + SuperDiff::Test::Models::ActiveRecord::Person.create!( + name: "Marty", + age: 19, + ) + SuperDiff::Test::Models::ActiveRecord::Person.create!( + name: "Jennifer", + age: 17, + ) + + inspection = described_class.inspect_object( + SuperDiff::Test::Models::ActiveRecord::Person.all, + as_single_line: false, + ) + + expect(inspection).to eq(<<~INSPECTION.rstrip) + #, + # + ]> + INSPECTION + end + end + end + + context "given a HashWithIndifferentAccess", active_record: true do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + HashWithIndifferentAccess.new({ + line_1: "123 Main St.", + city: "Hill Valley", + state: "CA", + zip: "90382", + }), + as_single_line: true, + ) + + # rubocop:disable Metrics/LineLength + expect(inspection).to eq( + %(# "123 Main St.", "city" => "Hill Valley", "state" => "CA", "zip" => "90382" }>), + ) + # rubocop:enable Metrics/LineLength + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + HashWithIndifferentAccess.new({ + line_1: "123 Main St.", + city: "Hill Valley", + state: "CA", + zip: "90382", + }), + as_single_line: false, + ) + + expect(inspection).to eq(<<~INSPECTION.rstrip) + # "123 Main St.", + "city" => "Hill Valley", + "state" => "CA", + "zip" => "90382" + }> + INSPECTION + end + end + end + + context "given a combination of all kinds of values" do + context "given as_single_line: true" do + it "returns a representation of the object on a single line" do + inspection = described_class.inspect_object( + { + state: :down, + errors: [ + "Container A-234 is partially damaged", + "Vessel B042 was attacked by raccoons", + "Product FDK-3429 is out of stock", + ], + mission_critical: true, + serviceable: false, + outstanding_orders: [ + SuperDiff::Test::Order.new([ + SuperDiff::Test::Item.new(name: "ham", quantity: 1), + SuperDiff::Test::Item.new(name: "eggs", quantity: 2), + SuperDiff::Test::Item.new(name: "cheese", quantity: 1), + ]), + ], + customers: [ + SuperDiff::Test::Customer.new( + name: "Marty McFly", + shipping_address: SuperDiff::Test::ShippingAddress.new( + line_1: "123 Baltic Ave.", + line_2: "", + city: "Hill Valley", + state: "CA", + zip: "90382", + ), + phone: "111-111-1111", + ), + SuperDiff::Test::Customer.new( + name: "Doc Brown", + shipping_address: SuperDiff::Test::ShippingAddress.new( + line_1: "456 Park Place", + line_2: "", + city: "Beverly Hills", + state: "CA", + zip: "90210", + ), + phone: "222-222-2222", + ), + ], + }, + as_single_line: true, + ) + expect(inspection).to match( + # rubocop:disable Metrics/LineLength + /\A\{ state: :down, errors: \["Container A-234 is partially damaged", "Vessel B042 was attacked by raccoons", "Product FDK-3429 is out of stock"\], mission_critical: true, serviceable: false, outstanding_orders: \[#, #, #\]>\], customers: \[#, phone: "111-111-1111">, #, phone: "222-222-2222">\] \}\Z/, + # rubocop:enable Metrics/LineLength + ) + end + end + + context "given as_single_line: false" do + it "returns a representation of the object across multiple lines" do + inspection = described_class.inspect_object( + { + state: :down, + errors: [ + "Container A-234 is partially damaged", + "Vessel B042 was attacked by raccoons", + "Product FDK-3429 is out of stock", + ], + mission_critical: true, + serviceable: false, + outstanding_orders: [ + SuperDiff::Test::Order.new([ + SuperDiff::Test::Item.new(name: "ham", quantity: 1), + SuperDiff::Test::Item.new(name: "eggs", quantity: 2), + SuperDiff::Test::Item.new(name: "cheese", quantity: 1), + ]), + ], + customers: [ + SuperDiff::Test::Customer.new( + name: "Marty McFly", + shipping_address: SuperDiff::Test::ShippingAddress.new( + line_1: "123 Baltic Ave.", + line_2: "", + city: "Hill Valley", + state: "CA", + zip: "90382", + ), + phone: "111-111-1111", + ), + SuperDiff::Test::Customer.new( + name: "Doc Brown", + shipping_address: SuperDiff::Test::ShippingAddress.new( + line_1: "456 Park Place", + line_2: "", + city: "Beverly Hills", + state: "CA", + zip: "90210", + ), + phone: "222-222-2222", + ), + ], + }, + as_single_line: false, + ) + regexp = <<~INSPECTION.rstrip + \\{ + state: :down, + errors: \\[ + "Container A-234 is partially damaged", + "Vessel B042 was attacked by raccoons", + "Product FDK-3429 is out of stock" + \\], + mission_critical: true, + serviceable: false, + outstanding_orders: \\[ + #, + #, + # + \\] + \\}> + \\], + customers: \\[ + #, + phone: "111-111-1111" + \\}>, + #, + phone: "222-222-2222" + \\}> + \\] + \\} + INSPECTION + expect(inspection).to match(/\A#{regexp}\Z/) + end + end + end + end + + context "given a data structure that refers to itself somewhere inside of it" do + context "given as_single_line: true" do + it "replaces the reference with ∙∙∙" do + value = ["a", "b", "c"] + value.insert(1, value) + inspection = described_class.inspect_object(value, as_single_line: true) + expect(inspection).to eq(%(["a", ∙∙∙, "b", "c"])) + end + end + + context "given as_single_line: false" do + it "replaces the reference with ∙∙∙" do + value = ["a", "b", "c"] + value.insert(1, value) + inspection = described_class.inspect_object( + value, + as_single_line: false, + ) + expect(inspection).to eq(<<~INSPECTION.rstrip) + [ + "a", + ∙∙∙, + "b", + "c" + ] + INSPECTION + end + end + end + + def colorize(*args, **opts, &block) + SuperDiff::Helpers.style(*args, **opts, &block).to_s.chomp + end +end