mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Implement predicate matcher
Took a trick I learned from `have_attributes` and applied it here.
This commit is contained in:
parent
5da222d7a0
commit
89208b8ed1
2 changed files with 54 additions and 0 deletions
|
@ -408,5 +408,25 @@ module Spectator::DSL
|
|||
macro have_attributes(**expected)
|
||||
::Spectator::Matchers::AttributesMatcher.new({{expected.double_splat.stringify}}, {{expected}})
|
||||
end
|
||||
|
||||
# Used to create predicate matchers.
|
||||
# Any missing method that starts with `be_` will be handled.
|
||||
# All other method names will be ignored and raise a compile-time error.
|
||||
#
|
||||
# This can be used to simply check a predicate method that ends in `?`.
|
||||
# For instance:
|
||||
# ```
|
||||
# expect("foobar").to be_ascii_only
|
||||
# # Is equivalent to:
|
||||
# expect("foobar".ascii_only?).to be_true
|
||||
# ```
|
||||
macro method_missing(call)
|
||||
{% if call.name.starts_with?("be_") %}
|
||||
{% method_name = call.name[3..-1] %} # Remove `be_` prefix.
|
||||
::Spectator::Matchers::PredicateMatcher.new({{method_name.stringify}}, { {{method_name}}: nil })
|
||||
{% else %}
|
||||
{% raise "Undefined local variable or method '#{call}'" %}
|
||||
{% end %}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
34
src/spectator/matchers/predicate_matcher.cr
Normal file
34
src/spectator/matchers/predicate_matcher.cr
Normal file
|
@ -0,0 +1,34 @@
|
|||
require "./value_matcher"
|
||||
|
||||
module Spectator::Matchers
|
||||
# Matcher that tests one or more predicates (methods ending in `?`).
|
||||
# The `ExpectedType` type param should be a `NamedTuple`.
|
||||
# Each key in the tuple is a predicate (without the `?`) to test.
|
||||
struct PredicateMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
# Determines whether the matcher is satisfied with the value given to it.
|
||||
# True is returned if the match was successful, false otherwise.
|
||||
def match?(partial)
|
||||
actual = partial.actual
|
||||
|
||||
# Test each predicate and immediately return false if one is false.
|
||||
{% for attribute in ExpectedType.keys %}
|
||||
return false unless actual.{{attribute}}?
|
||||
{% end %}
|
||||
|
||||
# All checks passed if this point is reached.
|
||||
true
|
||||
end
|
||||
|
||||
# Describes the condition that satisfies the matcher.
|
||||
# This is informational and displayed to the end-user.
|
||||
def message(partial)
|
||||
"Expected #{partial.label} to be #{label}"
|
||||
end
|
||||
|
||||
# Describes the condition that won't satsify the matcher.
|
||||
# This is informational and displayed to the end-user.
|
||||
def negated_message(partial)
|
||||
"Expected #{partial.label} to not be #{label}"
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue