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