mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Merge branch 'all-matcher' into 'release/0.8'
All matcher See merge request arctic-fox/spectator!14
This commit is contained in:
commit
db9715341e
4 changed files with 73 additions and 3 deletions
|
@ -296,7 +296,7 @@ Items not marked as completed may have partial implementations.
|
||||||
- [X] `be_empty`
|
- [X] `be_empty`
|
||||||
- [X] `have_key`
|
- [X] `have_key`
|
||||||
- [X] `have_value`
|
- [X] `have_value`
|
||||||
- [ ] `all`
|
- [X] `all`
|
||||||
- [ ] `all_satisfy`
|
- [ ] `all_satisfy`
|
||||||
- [X] Truthy matchers - `be`, `be_true`, `be_truthy`, `be_false`, `be_falsey`, `be_nil`
|
- [X] Truthy matchers - `be`, `be_true`, `be_truthy`, `be_false`, `be_falsey`, `be_nil`
|
||||||
- [X] Error matchers - `raise_error`
|
- [X] Error matchers - `raise_error`
|
||||||
|
|
|
@ -526,6 +526,19 @@ module Spectator::DSL
|
||||||
::Spectator::Matchers::AttributesMatcher.new(%test_value)
|
::Spectator::Matchers::AttributesMatcher.new(%test_value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Verifies that all elements of a collection satisfy some matcher.
|
||||||
|
# The collection should implement `Enumerable`.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# ```
|
||||||
|
# array = [1, 2, 3, 4]
|
||||||
|
# expect(array).to all(be_even) # Fails.
|
||||||
|
# expect(array).to all(be_lt(5)) # Passes.
|
||||||
|
# ```
|
||||||
|
macro all(matcher)
|
||||||
|
::Spectator::Matchers::AllMatcher.new({{matcher}})
|
||||||
|
end
|
||||||
|
|
||||||
# Indicates that some expression's value should change after taking an action.
|
# Indicates that some expression's value should change after taking an action.
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
|
|
57
src/spectator/matchers/all_matcher.cr
Normal file
57
src/spectator/matchers/all_matcher.cr
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
require "../test_value"
|
||||||
|
require "./failed_match_data"
|
||||||
|
require "./matcher"
|
||||||
|
require "./successful_match_data"
|
||||||
|
|
||||||
|
module Spectator::Matchers
|
||||||
|
# Matcher that checks if all elements of a collection apply to some other matcher.
|
||||||
|
struct AllMatcher(TMatcher) < Matcher
|
||||||
|
# Other matcher that all elements must match successfully.
|
||||||
|
private getter matcher
|
||||||
|
|
||||||
|
# Creates the matcher with an expected successful matcher.
|
||||||
|
def initialize(@matcher : TMatcher)
|
||||||
|
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
|
||||||
|
"all #{matcher.description}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Actually performs the test against the expression.
|
||||||
|
def match(actual : TestExpression(T)) : MatchData forall T
|
||||||
|
found = test_values(actual).each do |element|
|
||||||
|
match_data = matcher.match(element)
|
||||||
|
break match_data unless match_data.matched?
|
||||||
|
end
|
||||||
|
found ? found : SuccessfulMatchData.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# Negated matching for this matcher is not supported.
|
||||||
|
# Attempting to call this method will result in a compilation error.
|
||||||
|
#
|
||||||
|
# This syntax has a logical problem.
|
||||||
|
# "All values do not satisfy some condition."
|
||||||
|
# Does this mean that all values don't satisfy the matcher?
|
||||||
|
# What if only one doesn't?
|
||||||
|
# What if the collection is empty?
|
||||||
|
#
|
||||||
|
# RSpec doesn't support this syntax either.
|
||||||
|
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||||
|
{% raise "The `expect { }.to_not all()` syntax is not supported (ambiguous)." %}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Maps all values in the test collection to their own test values.
|
||||||
|
# Each value is given their own label,
|
||||||
|
# which is the original label with an index appended.
|
||||||
|
private def test_values(actual)
|
||||||
|
label_prefix = actual.label
|
||||||
|
actual.value.map_with_index do |value, index|
|
||||||
|
label = "#{label_prefix}[#{index}]"
|
||||||
|
TestValue.new(value, label)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -16,7 +16,7 @@ module Spectator
|
||||||
|
|
||||||
def self.create(proc : -> T, label : String) forall T
|
def self.create(proc : -> T, label : String) forall T
|
||||||
{% if T.id == "ReturnType".id %}
|
{% if T.id == "ReturnType".id %}
|
||||||
wrapper = -> { proc.call; nil }
|
wrapper = ->{ proc.call; nil }
|
||||||
TestBlock(Nil).new(wrapper, label)
|
TestBlock(Nil).new(wrapper, label)
|
||||||
{% else %}
|
{% else %}
|
||||||
TestBlock(T).new(proc, label)
|
TestBlock(T).new(proc, label)
|
||||||
|
@ -31,7 +31,7 @@ module Spectator
|
||||||
|
|
||||||
def self.create(proc : -> T) forall T
|
def self.create(proc : -> T) forall T
|
||||||
{% if T.id == "ReturnType".id %}
|
{% if T.id == "ReturnType".id %}
|
||||||
wrapper = -> { proc.call; nil }
|
wrapper = ->{ proc.call; nil }
|
||||||
TestBlock(Nil).new(wrapper)
|
TestBlock(Nil).new(wrapper)
|
||||||
{% else %}
|
{% else %}
|
||||||
TestBlock(T).new(proc)
|
TestBlock(T).new(proc)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue