mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Initial refactor of ArrayMatcher
This commit is contained in:
parent
044202e606
commit
13fad5081b
1 changed files with 59 additions and 116 deletions
|
@ -5,129 +5,72 @@ module Spectator::Matchers
|
||||||
# Matcher for checking that the contents of one array (or similar type)
|
# Matcher for checking that the contents of one array (or similar type)
|
||||||
# has the exact same contents as another and in the same order.
|
# has the exact same contents as another and in the same order.
|
||||||
struct ArrayMatcher(ExpectedType) < ValueMatcher(Enumerable(ExpectedType))
|
struct ArrayMatcher(ExpectedType) < ValueMatcher(Enumerable(ExpectedType))
|
||||||
# Determines whether the matcher is satisfied with the partial given to it.
|
def description
|
||||||
def match(partial, negated = false)
|
"contains exactly #{expected.label}"
|
||||||
actual = partial.actual.to_a
|
end
|
||||||
expected_elements = expected.to_a
|
|
||||||
values = ExpectedActual.new(expected_elements, label, actual, partial.label)
|
private def failure_message(actual)
|
||||||
if values.expected.size == values.actual.size
|
{% raise "This method should never be called" %}
|
||||||
|
end
|
||||||
|
|
||||||
|
private def failure_message_when_negated(actual)
|
||||||
|
{% raise "This method should never be called" %}
|
||||||
|
end
|
||||||
|
|
||||||
|
private def match?(actual)
|
||||||
|
{% raise "This method should never be called" %}
|
||||||
|
end
|
||||||
|
|
||||||
|
private def does_not_match?(actual)
|
||||||
|
{% raise "This method should never be called" %}
|
||||||
|
end
|
||||||
|
|
||||||
|
def match(actual)
|
||||||
|
actual_elements = actual.value.to_a
|
||||||
|
expected_elements = expected.value.to_a
|
||||||
|
if expected_elements.size == actual_elements.size
|
||||||
index = 0
|
index = 0
|
||||||
values.expected.zip(values.actual) do |expected, element|
|
expected_elements.zip(actual_elements) do |expected_element, actual_element|
|
||||||
return ContentMatchData.new(index, values) unless expected == element
|
unless expected_element == actual_element
|
||||||
|
return FailedMatchData.new("#{actual.label} does not contain exactly #{expected.label} (element mismatch)",
|
||||||
|
[
|
||||||
|
LabeledValue.new(expected_element.inspect, "expected"),
|
||||||
|
LabeledValue.new(actual_element.inspect, "actual"),
|
||||||
|
LabeledValue.new(index.to_s, "index"),
|
||||||
|
])
|
||||||
|
end
|
||||||
index += 1
|
index += 1
|
||||||
end
|
end
|
||||||
IdenticalMatchData.new(values)
|
# Success.
|
||||||
|
SuccessfulMatchData.new
|
||||||
else
|
else
|
||||||
SizeMatchData.new(values)
|
# Size mismatch.
|
||||||
|
FailedMatchData.new("#{actual.label} does not contain exactly #{expected.label} (size mismatch)",
|
||||||
|
[
|
||||||
|
LabeledValue.new(expected_elements.inspect, "expected"),
|
||||||
|
LabeledValue.new(actual_elements.inspect, "actual"),
|
||||||
|
LabeledValue.new(expected_elements.size, "expected size"),
|
||||||
|
LabeledValue.new(actual_elements.size, "actual size"),
|
||||||
|
])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates the value matcher.
|
def negated_match(actual)
|
||||||
# The label should be a string representation of the expectation.
|
actual_elements = actual.value.to_a
|
||||||
# The expected value is stored for later use.
|
expected_elements = expected.value.to_a
|
||||||
def initialize(expected : Enumerable(ExpectedType), label : String)
|
if expected_elements.size == actual_elements.size
|
||||||
super
|
index = 0
|
||||||
end
|
expected_elements.zip(actual_elements) do |expected_element, actual_element|
|
||||||
|
return SuccessfulMatchData.new unless expected_element == actual_element
|
||||||
# Creates the value matcher.
|
index += 1
|
||||||
# The label is generated by calling `#to_s` on the expected value.
|
end
|
||||||
# The expected value is stored for later use.
|
FailedMatchData.new("#{actual.label} contains exactly #{expected.label}",
|
||||||
def initialize(expected : Enumerable(ExpectedType))
|
[
|
||||||
super
|
LabeledValue.new("Not #{expected_elements.inspect}", "expected"),
|
||||||
end
|
LabeledValue.new(actual_elements.inspect, "actual"),
|
||||||
|
])
|
||||||
# Returns a matcher that uses the same expected array, but allows unordered items.
|
else
|
||||||
def in_any_order
|
SuccessfulMatchData.new
|
||||||
UnorderedArrayMatcher.new(@expected, @label)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns self.
|
|
||||||
# Exists for syntax to ensure in-order matching is performed.
|
|
||||||
def in_order
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
# Common functionality for all match data for this matcher.
|
|
||||||
private abstract struct CommonMatchData(ExpectedType, ActualType) < MatchData
|
|
||||||
# Creates the match data.
|
|
||||||
def initialize(matched, @values : ExpectedActual(Array(ExpectedType), Array(ActualType)))
|
|
||||||
super(matched)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Basic information about the match.
|
|
||||||
def named_tuple
|
|
||||||
{
|
|
||||||
expected: NegatableMatchDataValue.new(@values.expected),
|
|
||||||
actual: @values.actual,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Describes the condition that satisfies the matcher.
|
|
||||||
# This is informational and displayed to the end-user.
|
|
||||||
def message
|
|
||||||
"#{@values.actual_label} contains exactly #{@values.expected_label}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Match data specific to this matcher.
|
|
||||||
# This type is used when the actual value matches the expected value.
|
|
||||||
private struct IdenticalMatchData(ExpectedType, ActualType) < CommonMatchData(ExpectedType, ActualType)
|
|
||||||
# Creates the match data.
|
|
||||||
def initialize(values : ExpectedActual(Array(ExpectedType), Array(ActualType)))
|
|
||||||
super(true, values)
|
|
||||||
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 contain exactly #{@values.expected_label}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Match data specific to this matcher.
|
|
||||||
# This type is used when the actual size differs from the expected size.
|
|
||||||
private struct SizeMatchData(ExpectedType, ActualType) < CommonMatchData(ExpectedType, ActualType)
|
|
||||||
# Creates the match data.
|
|
||||||
def initialize(values : ExpectedActual(Array(ExpectedType), Array(ActualType)))
|
|
||||||
super(false, values)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Information about the match.
|
|
||||||
def named_tuple
|
|
||||||
super.merge({
|
|
||||||
"expected size": NegatableMatchDataValue.new(@values.expected.size),
|
|
||||||
"actual size": @values.actual.size,
|
|
||||||
})
|
|
||||||
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 contain exactly #{@values.expected_label} (size differs)"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Match data specific to this matcher.
|
|
||||||
# This type is used when the actual contents differs from the expected contents.
|
|
||||||
private struct ContentMatchData(ExpectedType, ActualType) < CommonMatchData(ExpectedType, ActualType)
|
|
||||||
# Creates the match data.
|
|
||||||
def initialize(@index : Int32, values : ExpectedActual(Array(ExpectedType), Array(ActualType)))
|
|
||||||
super(false, values)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Information about the match.
|
|
||||||
def named_tuple
|
|
||||||
super.merge({
|
|
||||||
index: @index,
|
|
||||||
"expected element": NegatableMatchDataValue.new(@values.expected[@index]),
|
|
||||||
"actual element": @values.actual[@index],
|
|
||||||
})
|
|
||||||
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 contain exactly #{@values.expected_label} (content differs)"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue