2022-09-03 22:41:03 +00:00
|
|
|
require "../spec_helper"
|
|
|
|
|
|
|
|
# https://gitlab.com/arctic-fox/spectator/-/wikis/Custom-Matchers
|
|
|
|
Spectator.describe "Custom Matchers Docs" do
|
|
|
|
context "value matcher" do
|
|
|
|
# Sub-type of Matcher to suit our needs.
|
|
|
|
# Notice this is a struct.
|
|
|
|
struct MultipleOfMatcher(ExpectedType) < Spectator::Matchers::ValueMatcher(ExpectedType)
|
|
|
|
# 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 : String
|
|
|
|
"is a multiple of #{expected.label}"
|
|
|
|
end
|
|
|
|
|
|
|
|
# Checks whether the matcher is satisfied with the expression given to it.
|
|
|
|
private def match?(actual : Spectator::Expression(T)) : Bool forall T
|
|
|
|
actual.value % expected.value == 0
|
|
|
|
end
|
|
|
|
|
|
|
|
# Message displayed when the matcher isn't satisfied.
|
|
|
|
# The message should typically only contain the test expression labels.
|
|
|
|
private def failure_message(actual : Spectator::Expression(T)) : String forall T
|
|
|
|
"#{actual.label} is not a multiple of #{expected.label}"
|
|
|
|
end
|
|
|
|
|
|
|
|
# Message displayed when the matcher isn't satisfied and is negated.
|
|
|
|
# This is essentially what would satisfy the matcher if it wasn't negated.
|
|
|
|
# The message should typically only contain the test expression labels.
|
|
|
|
private def failure_message_when_negated(actual : Spectator::Expression(T)) : String forall T
|
|
|
|
"#{actual.label} is a multiple of #{expected.label}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# The DSL portion of the matcher.
|
|
|
|
# This captures the test expression and creates an instance of the matcher.
|
|
|
|
macro be_a_multiple_of(expected)
|
|
|
|
%value = ::Spectator::Value.new({{expected}}, {{expected.stringify}})
|
|
|
|
MultipleOfMatcher.new(%value)
|
|
|
|
end
|
|
|
|
|
|
|
|
specify do
|
|
|
|
expect(9).to be_a_multiple_of(3)
|
|
|
|
# or negated:
|
|
|
|
expect(5).to_not be_a_multiple_of(2)
|
|
|
|
end
|
|
|
|
|
|
|
|
specify "failure messages" do
|
|
|
|
expect { expect(9).to be_a_multiple_of(5) }.to raise_error(Spectator::ExpectationFailed, "9 is not a multiple of 5")
|
|
|
|
expect { expect(6).to_not be_a_multiple_of(3) }.to raise_error(Spectator::ExpectationFailed, "6 is a multiple of 3")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "standard matcher" do
|
|
|
|
struct OddMatcher < Spectator::Matchers::StandardMatcher
|
|
|
|
def description : String
|
|
|
|
"is odd"
|
|
|
|
end
|
|
|
|
|
|
|
|
private def match?(actual : Spectator::Expression(T)) : Bool forall T
|
|
|
|
actual.value % 2 == 1
|
|
|
|
end
|
|
|
|
|
|
|
|
private def failure_message(actual : Spectator::Expression(T)) : String forall T
|
|
|
|
"#{actual.label} is not odd"
|
|
|
|
end
|
|
|
|
|
|
|
|
private def failure_message_when_negated(actual : Spectator::Expression(T)) : String forall T
|
|
|
|
"#{actual.label} is odd"
|
|
|
|
end
|
|
|
|
|
|
|
|
private def does_not_match?(actual : Spectator::Expression(T)) : Bool forall T
|
|
|
|
actual.value % 2 == 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
macro be_odd
|
2022-10-08 20:05:53 +00:00
|
|
|
OddMatcher.new
|
|
|
|
end
|
2022-09-03 22:41:03 +00:00
|
|
|
|
|
|
|
specify do
|
|
|
|
expect(9).to be_odd
|
|
|
|
expect(2).to_not be_odd
|
|
|
|
end
|
|
|
|
|
|
|
|
specify "failure messages" do
|
|
|
|
expect { expect(2).to be_odd }.to raise_error(Spectator::ExpectationFailed, "2 is not odd")
|
|
|
|
expect { expect(3).to_not be_odd }.to raise_error(Spectator::ExpectationFailed, "3 is odd")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|