Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: date like objects support #198

Merged
merged 8 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lib/super_diff.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "attr_extras/explicit"
require "diff-lcs"
require "patience_diff"
require "date"

module SuperDiff
autoload(
Expand Down Expand Up @@ -57,6 +58,14 @@ def self.time_like?(value)
value.is_a?(Time)
end

def self.date_like?(value)
# Check for ActiveSupport's #acts_like_date? for their date-like objects
# In case class is both time-like and date-like, we should treat it as
# time-like. This is governed by the order of `Differs::DEFAULTS` entries
(value.respond_to?(:acts_like_date?) && value.acts_like_date?) ||
value.is_a?(Date)
end

def self.primitive?(value)
case value
when true, false, nil, Symbol, Numeric, Regexp, Class
Expand Down
1 change: 1 addition & 0 deletions lib/super_diff/differs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Differs
autoload :Main, "super_diff/differs/main"
autoload :MultilineString, "super_diff/differs/multiline_string"
autoload :TimeLike, "super_diff/differs/time_like"
autoload :DateLike, "super_diff/differs/date_like"
end
end

Expand Down
15 changes: 15 additions & 0 deletions lib/super_diff/differs/date_like.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module SuperDiff
module Differs
class DateLike < Base
def self.applies_to?(expected, actual)
SuperDiff.date_like?(expected) && SuperDiff.date_like?(actual)
end

protected

def operation_tree_builder_class
OperationTreeBuilders::DateLike
end
end
end
end
1 change: 1 addition & 0 deletions lib/super_diff/differs/defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Differs
Array,
Hash,
TimeLike,
DateLike,
MultilineString,
CustomObject,
DefaultObject
Expand Down
4 changes: 4 additions & 0 deletions lib/super_diff/object_inspection/inspection_tree_builders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ module InspectionTreeBuilders
:TimeLike,
"super_diff/object_inspection/inspection_tree_builders/time_like"
)
autoload(
:DateLike,
"super_diff/object_inspection/inspection_tree_builders/date_like"
)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module SuperDiff
module ObjectInspection
module InspectionTreeBuilders
class DateLike < Base
def self.applies_to?(value)
SuperDiff.date_like?(value)
end

def call
InspectionTree.new do
as_lines_when_rendering_to_lines(collection_bookend: :open) do
add_text { |date| "#<#{date.class} " }

when_rendering_to_lines { add_text "{" }
end

when_rendering_to_string do
add_text { |date| date.strftime("%Y-%m-%d") }
end

when_rendering_to_lines do
nested do |date|
insert_separated_list(%i[year month day]) do |name|
add_text name.to_s
add_text ": "
add_inspection_of date.public_send(name)
end
end
end

as_lines_when_rendering_to_lines(collection_bookend: :close) do
when_rendering_to_lines { add_text "}" }

add_text ">"
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module InspectionTreeBuilders
Hash,
Primitive,
TimeLike,
DateLike,
DefaultObject
].freeze
end
Expand Down
1 change: 1 addition & 0 deletions lib/super_diff/operation_tree_builders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module OperationTreeBuilders
"super_diff/operation_tree_builders/multiline_string"
)
autoload :TimeLike, "super_diff/operation_tree_builders/time_like"
autoload :DateLike, "super_diff/operation_tree_builders/date_like"
end
end

Expand Down
15 changes: 15 additions & 0 deletions lib/super_diff/operation_tree_builders/date_like.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module SuperDiff
module OperationTreeBuilders
class DateLike < CustomObject
def self.applies_to?(expected, actual)
SuperDiff.date_like?(expected) && SuperDiff.date_like?(actual)
end

protected

def attribute_names
%w[year month day]
end
end
end
end
2 changes: 1 addition & 1 deletion lib/super_diff/operation_tree_builders/defaults.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module SuperDiff
module OperationTreeBuilders
DEFAULTS = [Array, Hash, TimeLike, CustomObject].freeze
DEFAULTS = [Array, Hash, TimeLike, DateLike, CustomObject].freeze
end
end
72 changes: 72 additions & 0 deletions spec/integration/rspec/eq_matcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,78 @@
end
end

context "when comparing two different Date instances" do
it "produces the correct failure message when used in the positive" do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~RUBY
expected = Date.new(2023, 10, 14)
actual = Date.new(2023, 10, 31)
expect(expected).to eq(actual)
RUBY
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: "expect(expected).to eq(actual)",
expectation:
proc do
line do
plain "Expected "
actual "#<Date 2023-10-14>"
plain " to eq "
expected "#<Date 2023-10-31>"
plain "."
end
end,
diff:
proc do
plain_line " #<Date {"
plain_line " year: 2023,"
plain_line " month: 10,"
expected_line "- day: 31"
actual_line "+ day: 14"
plain_line " }>"
end
)

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

it "produces the correct failure message when used in the negative" do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~RUBY
date = Date.new(2023, 10, 14)
expect(date).not_to eq(date)
RUBY
program = make_plain_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: "expect(date).not_to eq(date)",
expectation:
proc do
line do
plain "Expected "
actual "#<Date 2023-10-14>"
plain " not to eq "
expected "#<Date 2023-10-14>"
plain "."
end
end
)

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

context "when comparing a single-line string with a multi-line string" do
it "produces the correct failure message" do
as_both_colored_and_uncolored do |color_enabled|
Expand Down
79 changes: 79 additions & 0 deletions spec/support/shared_examples/active_support.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,83 @@
end
end
end

context "when comparing Date instance and date-like DateTime instance for same day",
active_record: true do
it "produces the correct failure message when used in the positive" do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~RUBY
expected = Date.new(2023, 10, 14)
actual = DateTime.new(2023, 10, 14, 18, 22, 26)
expect(expected).to eq(actual)
RUBY
program =
make_rspec_rails_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: "expect(expected).to eq(actual)",
expectation:
proc do
line do
plain "Expected "
actual "#<Date 2023-10-14>"
plain " to eq "
expected "#<DateTime 2023-10-14 18:22:26 +00:00 (+00:00)>"
plain "."
end
end
)

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

context "when comparing Date instance and date-like DateTime instance for another day",
active_record: true do
it "produces the diff for date like objects comparison" do
as_both_colored_and_uncolored do |color_enabled|
snippet = <<~RUBY
expected = Date.new(2023, 10, 14)
actual = DateTime.new(2023, 10, 31, 18, 22, 26)
expect(expected).to eq(actual)
RUBY
program =
make_rspec_rails_test_program(snippet, color_enabled: color_enabled)

expected_output =
build_expected_output(
color_enabled: color_enabled,
snippet: "expect(expected).to eq(actual)",
expectation:
proc do
line do
plain "Expected "
actual "#<Date 2023-10-14>"
plain " to eq "
expected "#<DateTime 2023-10-31 18:22:26 +00:00 (+00:00)>"
plain "."
end
end,
diff:
proc do
plain_line " #<Date {"
plain_line " year: 2023,"
plain_line " month: 10,"
expected_line "- day: 31"
actual_line "+ day: 14"
plain_line " }>"
end
)

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