mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Add matcher docs
This commit is contained in:
parent
37c8dd0865
commit
d5fd21702a
30 changed files with 531 additions and 4 deletions
|
@ -7,15 +7,21 @@ module Spectator::Matchers
|
|||
# Matcher for checking that the contents of one array (or similar type)
|
||||
# has the exact same contents as another and in the same order.
|
||||
struct ArrayMatcher(ExpectedType) < Matcher
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with an expected value.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"contains exactly #{expected.label}"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
actual_elements = actual.value.to_a
|
||||
expected_elements = expected.value.to_a
|
||||
|
@ -31,6 +37,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
actual_elements = actual.value.to_a
|
||||
expected_elements = expected.value.to_a
|
||||
|
@ -45,14 +53,23 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Ensures the arrays elements are compared in order.
|
||||
# This is the default behavior for the matcher.
|
||||
def in_order
|
||||
self
|
||||
end
|
||||
|
||||
# Specifies that the arrays elements can be compared in any order.
|
||||
# The elements can be in a different order, but both arrays must have the same elements.
|
||||
def in_any_order
|
||||
UnorderedArrayMatcher.new(expected)
|
||||
end
|
||||
|
||||
# Compares two arrays to determine whether they contain the same elements, and in the same order.
|
||||
# If the arrays are the same, then `true` is returned.
|
||||
# If they are different, `false` or an integer is returned.
|
||||
# `false` is returned when the sizes of the arrays don't match.
|
||||
# An integer is returned, that is the index of the mismatched elements in the arrays.
|
||||
private def compare_arrays(expected_elements, actual_elements)
|
||||
if expected_elements.size == actual_elements.size
|
||||
index = 0
|
||||
|
@ -66,6 +83,7 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Produces match data for a failure when the array sizes differ.
|
||||
private def failed_size_mismatch(expected_elements, actual_elements, actual_label)
|
||||
FailedMatchData.new("#{actual_label} does not contain exactly #{expected.label} (size mismatch)",
|
||||
expected: expected_elements.inspect,
|
||||
|
@ -75,6 +93,7 @@ module Spectator::Matchers
|
|||
)
|
||||
end
|
||||
|
||||
# Produces match data for a failure when the array content is mismatched.
|
||||
private def failed_content_mismatch(expected_elements, actual_elements, index, actual_label)
|
||||
FailedMatchData.new("#{actual_label} does not contain exactly #{expected.label} (element mismatch)",
|
||||
expected: expected_elements[index].inspect,
|
||||
|
@ -83,6 +102,7 @@ module Spectator::Matchers
|
|||
)
|
||||
end
|
||||
|
||||
# Produces match data for a failure when the arrays are identical, but they shouldn't be (negation).
|
||||
private def failed_content_identical(expected_elements, actual_elements, actual_label)
|
||||
FailedMatchData.new("#{actual_label} contains exactly #{expected.label}",
|
||||
expected: "Not #{expected_elements.inspect}",
|
||||
|
|
|
@ -10,15 +10,21 @@ module Spectator::Matchers
|
|||
# Each key in the tuple is the attribute/method name,
|
||||
# and the corresponding value is the expected value to match against.
|
||||
struct AttributesMatcher(ExpectedType) < Matcher
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with an expected value.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"has attributes #{expected.label}"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -28,6 +34,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -49,6 +57,7 @@ module Spectator::Matchers
|
|||
{% end %}
|
||||
end
|
||||
|
||||
# Checks if all attributes from the snapshot of them are satisified.
|
||||
private def match?(snapshot)
|
||||
# Test that every attribute has the expected value.
|
||||
{% for attribute in ExpectedType.keys %}
|
||||
|
@ -59,6 +68,7 @@ module Spectator::Matchers
|
|||
true
|
||||
end
|
||||
|
||||
# Produces the tuple for the failed match data from a snapshot of the attributes.
|
||||
private def values(snapshot)
|
||||
{% begin %}
|
||||
{
|
||||
|
|
|
@ -4,18 +4,35 @@ module Spectator::Matchers
|
|||
# Common matcher that tests whether two values semantically equal each other.
|
||||
# The values are compared with the === operator.
|
||||
struct CaseMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value === actual.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"matches #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not match #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} matched #{expected.label}"
|
||||
end
|
||||
|
|
|
@ -5,18 +5,35 @@ require "./value_matcher"
|
|||
module Spectator::Matchers
|
||||
# Matcher for checking that a value is in a collection of other values.
|
||||
struct CollectionMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value.includes?(actual.value)
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is in #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not in #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is in #{expected.label}"
|
||||
end
|
||||
|
|
|
@ -4,24 +4,43 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether a value, such as a `String` or `Array`, contains one or more values.
|
||||
# The values are checked with the `includes?` method.
|
||||
struct ContainMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value.all? do |item|
|
||||
actual.value.includes?(item)
|
||||
end
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"contains #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not match #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} contains #{expected.label}"
|
||||
end
|
||||
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
subset: expected.value.inspect,
|
||||
|
|
|
@ -4,18 +4,35 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether a collection is empty.
|
||||
# The values are checked with the `empty?` method.
|
||||
struct EmptyMatcher < StandardMatcher
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value.empty?
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is empty"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not empty"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is empty"
|
||||
end
|
||||
|
|
|
@ -7,15 +7,21 @@ module Spectator::Matchers
|
|||
# The `ends_with?` method is used if it's defined on the actual type.
|
||||
# Otherwise, it is treated as an `Indexable` and the `last` value is compared against.
|
||||
struct EndWithMatcher(ExpectedType) < Matcher
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with an expected value.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"ends with #{expected.label}"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
if (value = actual.value).responds_to?(:ends_with?)
|
||||
match_ends_with(value, actual.label)
|
||||
|
@ -24,6 +30,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the actual value ends with the expected value.
|
||||
# This method expects (and uses) the `#ends_with?` method on the value.
|
||||
private def match_ends_with(actual_value, actual_label)
|
||||
if actual_value.ends_with?(expected.value)
|
||||
SuccessfulMatchData.new
|
||||
|
@ -35,6 +43,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the last element of the value is the expected value.
|
||||
# This method expects that the actual value is a set (enumerable).
|
||||
private def match_last(actual_value, actual_label)
|
||||
list = actual_value.to_a
|
||||
last = list.last
|
||||
|
@ -50,6 +60,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
if actual.value.responds_to?(:ends_with?)
|
||||
negated_match_ends_with(actual)
|
||||
|
@ -58,6 +70,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the actual value does not end with the expected value.
|
||||
# This method expects (and uses) the `#ends_with?` method on the value.
|
||||
private def negated_match_ends_with(actual)
|
||||
if actual.value.ends_with?(expected.value)
|
||||
FailedMatchData.new("#{actual.label} ends with #{expected.label} (using #ends_with?)",
|
||||
|
@ -69,6 +83,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the last element of the value is not the expected value.
|
||||
# This method expects that the actual value is a set (enumerable).
|
||||
private def negated_match_last(actual)
|
||||
list = actual.value.to_a
|
||||
last = list.last
|
||||
|
|
|
@ -4,18 +4,35 @@ module Spectator::Matchers
|
|||
# Common matcher that tests whether two values equal each other.
|
||||
# The values are compared with the == operator.
|
||||
struct EqualityMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value == actual.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"equals #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not equal #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} equals #{expected.label}"
|
||||
end
|
||||
|
|
|
@ -6,15 +6,21 @@ require "./successful_match_data"
|
|||
module Spectator::Matchers
|
||||
# Matcher that tests whether an exception is raised.
|
||||
struct ExceptionMatcher(ExceptionType, ExpectedType) < Matcher
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with no expectation of the message.
|
||||
def initialize
|
||||
@expected = TestValue.new(nil, ExceptionType.to_s)
|
||||
end
|
||||
|
||||
# Creates the matcher with an expected message.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
if (message = @expected)
|
||||
"raises #{ExceptionType} with message #{message}"
|
||||
|
@ -23,6 +29,7 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
exception = capture_exception { actual.value }
|
||||
if exception.nil?
|
||||
|
@ -52,6 +59,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
exception = capture_exception { actual.value }
|
||||
if exception.nil?
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether one value is greater than or equal to another.
|
||||
# The values are compared with the >= operator.
|
||||
struct GreaterThanEqualMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value >= expected.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"greater than or equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is less than #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is greater than or equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: ">= #{expected.value.inspect}",
|
||||
|
@ -27,6 +46,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: "< #{expected.value.inspect}",
|
||||
|
|
|
@ -4,29 +4,50 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether one value is greater than another.
|
||||
# The values are compared with the > operator.
|
||||
struct GreaterThanMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value > expected.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"greater than #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is less than or equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is greater than #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: "> #{expected.value.inspect}",
|
||||
actual: actual.value.inspect,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: "<= #{expected.value.inspect}",
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether a `Hash` (or similar type) has a given key.
|
||||
# The set is checked with the `has_key?` method.
|
||||
struct HaveKeyMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value.has_key?(expected.value)
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"has key #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not have key #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} has key #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
actual_value = actual.value
|
||||
set = actual_value.responds_to?(:keys) ? actual_value.keys : actual_value
|
||||
|
|
|
@ -5,6 +5,7 @@ module Spectator::Matchers
|
|||
# For a `String`, the `includes?` method is used.
|
||||
# Otherwise, it expects an `Enumerable` and iterates over each item until === is true.
|
||||
struct HaveMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
if (value = actual.value).is_a?(String)
|
||||
match_string?(value)
|
||||
|
@ -32,18 +33,36 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"includes #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not include #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} includes #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
subset: expected.value.inspect,
|
||||
|
|
|
@ -7,15 +7,21 @@ module Spectator::Matchers
|
|||
# Each key in the tuple is a predicate (without the '?' and 'has_' prefix) to test.
|
||||
# Each value is a a `Tuple` of arguments to pass to the predicate method.
|
||||
struct HavePredicateMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with a expected values.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"has #{expected.label}"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -25,6 +31,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -34,10 +42,23 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not have #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} has #{expected.label}"
|
||||
end
|
||||
|
@ -54,6 +75,7 @@ module Spectator::Matchers
|
|||
{% end %}
|
||||
end
|
||||
|
||||
# Produces the tuple for the failed match data from a snapshot of the predicate methods.
|
||||
private def values(snapshot)
|
||||
{% begin %}
|
||||
{
|
||||
|
@ -64,6 +86,7 @@ module Spectator::Matchers
|
|||
{% end %}
|
||||
end
|
||||
|
||||
# Checks if all predicate methods from the snapshot of them are satisified.
|
||||
private def match?(snapshot)
|
||||
# Test each predicate and immediately return false if one is false.
|
||||
{% for attribute in ExpectedType.keys %}
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether a `Hash` (or similar type) has a given value.
|
||||
# The set is checked with the `has_value?` method.
|
||||
struct HaveValueMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value.has_value?(expected.value)
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"has value #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not have value #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} has value #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
actual_value = actual.value
|
||||
set = actual_value.responds_to?(:values) ? actual_value.values : actual_value
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether two values do not equal each other.
|
||||
# The values are compared with the != operator.
|
||||
struct InequalityMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value != actual.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is not equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is not equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: "Not #{expected.value.inspect}",
|
||||
|
@ -27,6 +46,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: expected.value.inspect,
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether one value is less than or equal to another.
|
||||
# The values are compared with the <= operator.
|
||||
struct LessThanEqualMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value <= expected.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"less than or equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is greater than #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is less than or equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: "<= #{expected.value.inspect}",
|
||||
|
@ -27,6 +46,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: "> #{expected.value.inspect}",
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether one value is less than another.
|
||||
# The values are compared with the < operator.
|
||||
struct LessThanMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value < expected.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"less than #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is greater than or equal to #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is less than #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: "< #{expected.value.inspect}",
|
||||
|
@ -27,6 +46,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: ">= #{expected.value.inspect}",
|
||||
|
|
|
@ -4,18 +4,35 @@ module Spectator::Matchers
|
|||
# Common matcher that tests whether a value is nil.
|
||||
# The `Object#nil?` method is used for this.
|
||||
struct NilMatcher < StandardMatcher
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value.nil?
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is nil"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not nil"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is nil"
|
||||
end
|
||||
|
|
|
@ -6,15 +6,21 @@ module Spectator::Matchers
|
|||
# Each key in the tuple is a predicate (without the '?') to test.
|
||||
# Each value is a a `Tuple` of arguments to pass to the predicate method.
|
||||
struct PredicateMatcher(ExpectedType) < Matcher
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with a expected values.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is #{expected.label}"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -24,6 +30,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -33,10 +41,23 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is #{expected.label}"
|
||||
end
|
||||
|
@ -53,6 +74,7 @@ module Spectator::Matchers
|
|||
{% end %}
|
||||
end
|
||||
|
||||
# Produces the tuple for the failed match data from a snapshot of the predicate methods.
|
||||
private def values(snapshot)
|
||||
{% begin %}
|
||||
{
|
||||
|
@ -63,6 +85,7 @@ module Spectator::Matchers
|
|||
{% end %}
|
||||
end
|
||||
|
||||
# Checks if all predicate methods from the snapshot of them are satisified.
|
||||
private def match?(snapshot)
|
||||
# Test each predicate and immediately return false if one is false.
|
||||
{% for attribute in ExpectedType.keys %}
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether a value is in a given range.
|
||||
# The `Range#includes?` method is used for this check.
|
||||
struct RangeMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value.includes?(actual.value)
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is in #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not in #{expected.label} (#{exclusivity})"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is in #{expected.label} (#{exclusivity})"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
lower: ">= #{range.begin.inspect}",
|
||||
|
@ -28,6 +47,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
lower: "< #{range.begin.inspect}",
|
||||
|
|
|
@ -4,18 +4,35 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether two references are the same.
|
||||
# The values are compared with the `Reference#same?` method.
|
||||
struct ReferenceMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value.same?(actual.value)
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is #{expected.label}"
|
||||
end
|
||||
|
|
|
@ -6,15 +6,20 @@ module Spectator::Matchers
|
|||
# The `ExpectedType` type param should be a `NamedTuple`,
|
||||
# with each key being the method to check and the value is ignored.
|
||||
struct RespondMatcher(ExpectedType) < Matcher
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"responds to #{label}"
|
||||
end
|
||||
|
||||
# Generated, user-friendly, string for the expected value.
|
||||
private def label
|
||||
# Prefix every method name with # and join them with commas.
|
||||
{{ExpectedType.keys.map { |e| "##{e}".id }.splat.stringify}}
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -24,6 +29,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
snapshot = snapshot_values(actual.value)
|
||||
if match?(snapshot)
|
||||
|
@ -45,6 +52,7 @@ module Spectator::Matchers
|
|||
{% end %}
|
||||
end
|
||||
|
||||
# Produces the tuple for the failed match data from a snapshot of the results.
|
||||
private def values(snapshot)
|
||||
{% begin %}
|
||||
{
|
||||
|
@ -55,6 +63,7 @@ module Spectator::Matchers
|
|||
{% end %}
|
||||
end
|
||||
|
||||
# Checks if all results from the snapshot are satisified.
|
||||
private def match?(snapshot)
|
||||
# The snapshot did the hard work.
|
||||
# Here just check if all values are true.
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether a set has a specified number of elements.
|
||||
# The set's `#size` method is used for this check.
|
||||
struct SizeMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value == actual.value.size
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"has size #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} does not have #{expected.label} elements"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} has #{expected.label} elements"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: expected.value.inspect,
|
||||
|
@ -27,6 +46,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: "Not #{expected.value.inspect}",
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests whether a set has the same number of elements as another set.
|
||||
# The set's `#size` method is used for this check.
|
||||
struct SizeOfMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
expected.value.size == actual.value.size
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is the same size as #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not the same size as #{expected.label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is the same size as #{expected.label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: expected.value.size.inspect,
|
||||
|
@ -27,6 +46,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: "Not #{expected.value.size.inspect}",
|
||||
|
|
|
@ -26,6 +26,7 @@ module Spectator::Matchers
|
|||
private abstract def failure_message(actual : TestExpression(T)) : String forall T
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
|
@ -39,7 +40,7 @@ module Spectator::Matchers
|
|||
{% raise "Negation with #{@type.name} is not supported." %}
|
||||
end
|
||||
|
||||
# Checks whether the matcher is satisifed.
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private abstract def match?(actual : TestExpression(T)) : Bool forall T
|
||||
|
||||
# If the expectation is negated, then this method is called instead of `#match?`.
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
require "./value_matcher"
|
||||
|
||||
# Checks whether the last element of the value is the expected value.
|
||||
# This method expects that the actual value is a set (enumerable).require "./value_matcher"
|
||||
|
||||
module Spectator::Matchers
|
||||
# Matcher that tests whether a value, such as a `String` or `Array`, starts with a value.
|
||||
# The `starts_with?` method is used if it's defined on the actual type.
|
||||
# Otherwise, it is treated as an `Enumerable` and the `first` value is compared against.
|
||||
struct StartWithMatcher(ExpectedType) < Matcher
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with an expected value.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"starts with #{expected.label}"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
if (value = actual.value).responds_to?(:starts_with?)
|
||||
match_starts_with(value, actual.label)
|
||||
|
@ -22,6 +30,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the actual value starts with the expected value.
|
||||
# This method expects (and uses) the `#starts_with?` method on the value.
|
||||
private def match_starts_with(actual_value, actual_label)
|
||||
if actual_value.starts_with?(expected.value)
|
||||
SuccessfulMatchData.new
|
||||
|
@ -33,6 +43,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the first element of the value is the expected value.
|
||||
# This method expects that the actual value is a set (enumerable).
|
||||
private def match_first(actual_value, actual_label)
|
||||
list = actual_value.to_a
|
||||
first = list.first
|
||||
|
@ -48,6 +60,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
if (value = actual.value).responds_to?(:starts_with?)
|
||||
negated_match_starts_with(value, actual.label)
|
||||
|
@ -56,6 +70,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the actual value does not start with the expected value.
|
||||
# This method expects (and uses) the `#starts_with?` method on the value.
|
||||
private def negated_match_starts_with(actual_value, actual_label)
|
||||
if actual_value.starts_with?(expected.value)
|
||||
FailedMatchData.new("#{actual_label} starts with #{expected.label} (using #starts_with?)",
|
||||
|
@ -67,6 +83,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Checks whether the first element of the value is not the expected value.
|
||||
# This method expects that the actual value is a set (enumerable).
|
||||
private def negated_match_first(actual_value, actual_label)
|
||||
list = actual_value.to_a
|
||||
first = list.first
|
||||
|
|
|
@ -15,30 +15,51 @@ module Spectator::Matchers
|
|||
def initialize(@truthy : Bool = true)
|
||||
end
|
||||
|
||||
# Generated, user-friendly, string for the expected value.
|
||||
private def label
|
||||
@truthy ? "truthy" : "falsey"
|
||||
end
|
||||
|
||||
# Generated, user-friendly, string for the unexpected value.
|
||||
private def negated_label
|
||||
@truthy ? "falsey" : "truthy"
|
||||
end
|
||||
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
@truthy == !!actual.value
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is #{label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is #{negated_label}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is #{label}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: @truthy ? "Not false or nil" : "false or nil",
|
||||
|
@ -47,6 +68,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: @truthy ? "false or nil" : "Not false or nil",
|
||||
|
|
|
@ -4,22 +4,41 @@ module Spectator::Matchers
|
|||
# Matcher that tests a value is of a specified type.
|
||||
# The values are compared with the `Object#is_a?` method.
|
||||
struct TypeMatcher(Expected) < StandardMatcher
|
||||
# Checks whether the matcher is satisifed with the expression given to it.
|
||||
private def match?(actual)
|
||||
actual.value.is_a?(Expected)
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"is as #{Expected}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed.
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message(actual)
|
||||
"#{actual.label} is not a #{Expected}"
|
||||
end
|
||||
|
||||
# Message displayed when the matcher isn't satisifed and is negated.
|
||||
# This is essentially what would satisfy the matcher if it wasn't negated.
|
||||
#
|
||||
# This is only called when `#does_not_match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual)
|
||||
"#{actual.label} is a #{Expected}"
|
||||
end
|
||||
|
||||
# Additional information about the match failure.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def values(actual)
|
||||
{
|
||||
expected: Expected.to_s,
|
||||
|
@ -27,6 +46,8 @@ module Spectator::Matchers
|
|||
}
|
||||
end
|
||||
|
||||
# Additional information about the match failure when negated.
|
||||
# The return value is a NamedTuple with Strings for each value.
|
||||
private def negated_values(actual)
|
||||
{
|
||||
expected: "Not #{Expected}",
|
||||
|
|
|
@ -4,15 +4,21 @@ module Spectator::Matchers
|
|||
# Matcher for checking that the contents of one array (or similar type)
|
||||
# has the exact same contents as another, but in any order.
|
||||
struct UnorderedArrayMatcher(ExpectedType) < Matcher
|
||||
# Expected value and label.
|
||||
private getter expected
|
||||
|
||||
# Creates the matcher with an expected value.
|
||||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
# Short text about the matcher's purpose.
|
||||
# This explains what condition satisfies the matcher.
|
||||
# The description is used when the one-liner syntax is used.
|
||||
def description
|
||||
"contains #{expected.label} in any order"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
actual_elements = actual.value.to_a
|
||||
expected_elements = expected.value.to_a
|
||||
|
@ -30,6 +36,8 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
actual_elements = actual.value.to_a
|
||||
expected_elements = expected.value.to_a
|
||||
|
|
Loading…
Reference in a new issue