Display last item and full list when #last is used

Only perform one check with #responds_to?.
This commit is contained in:
Michael Miller 2019-03-05 13:52:59 -07:00
parent 52f8c52a58
commit 27409f4a92
1 changed files with 46 additions and 16 deletions

View File

@ -6,23 +6,31 @@ module Spectator::Matchers
# Otherwise, it is treated as an `Indexable` and the `last` value is compared against. # Otherwise, it is treated as an `Indexable` and the `last` value is compared against.
struct EndWithMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct EndWithMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
private def match?(actual) private def match_ends_with?(actual)
if actual.responds_to?(:ends_with?) actual.ends_with?(expected)
actual.ends_with?(expected) end
else
expected === actual.last # Determines whether the matcher is satisfied with the value given to it.
end private def match_last?(actual)
expected === actual
end end
# Determines whether the matcher is satisfied with the partial given to it. # Determines whether the matcher is satisfied with the partial given to it.
# `MatchData` is returned that contains information about the match. # `MatchData` is returned that contains information about the match.
def match(partial) def match(partial)
values = ExpectedActual.new(partial, self) values = ExpectedActual.new(partial, self)
MatchData.new(match?(values.actual), values) actual = values.actual
if actual.responds_to?(:ends_with?)
EndsWithMatchData.new(match_ends_with?(actual), values)
else
last = actual.last
LastMatchData.new(match_last?(last), values, last)
end
end end
# Match data specific to this matcher. # Match data specific to this matcher.
private struct MatchData(ExpectedType, ActualType) < MatchData # This type is used when the actual value responds to `ends_with?`.
private struct EndsWithMatchData(ExpectedType, ActualType) < MatchData
# Creates the match data. # Creates the match data.
def initialize(matched, @values : ExpectedActual(ExpectedType, ActualType)) def initialize(matched, @values : ExpectedActual(ExpectedType, ActualType))
super(matched) super(matched)
@ -39,21 +47,43 @@ module Spectator::Matchers
# Describes the condition that satisfies the matcher. # Describes the condition that satisfies the matcher.
# This is informational and displayed to the end-user. # This is informational and displayed to the end-user.
def message def message
"#{@values.actual_label} ends with #{@values.expected_label} (using #{comparison_method})" "#{@values.actual_label} ends with #{@values.expected_label} (using #ends_with?)"
end end
# Describes the condition that won't satsify the matcher. # Describes the condition that won't satsify the matcher.
# This is informational and displayed to the end-user. # This is informational and displayed to the end-user.
def negated_message def negated_message
"#{@values.actual_label} does not end with #{@values.expected_label} (using #{comparison_method})" "#{@values.actual_label} does not end with #{@values.expected_label} (using #ends_with?)"
end
end
# Match data specific to this matcher.
# This type is used when the actual value does not respond to `ends_with?`.
private struct LastMatchData(ExpectedType, ActualType, LastType) < MatchData
# Creates the match data.
def initialize(matched, @values : ExpectedActual(ExpectedType, ActualType), @last : LastType)
super(matched)
end end
private def comparison_method # Information about the match.
if @values.actual.responds_to?(:ends_with?) def values
"#ends_with?" {
else expected: @values.expected,
"expected === actual.last" actual: @last,
end list: @values.actual,
}
end
# Describes the condition that satisfies the matcher.
# This is informational and displayed to the end-user.
def message
"#{@values.actual_label} ends with #{@values.expected_label} (using expected === actual.last)"
end
# Describes the condition that won't satsify the matcher.
# This is informational and displayed to the end-user.
def negated_message
"#{@values.actual_label} does not end with #{@values.expected_label} (using expected === actual.last)"
end end
end end
end end