mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Add change.to variant
This commit is contained in:
parent
d2823398ff
commit
535dc6e923
4 changed files with 341 additions and 1 deletions
|
@ -98,6 +98,14 @@ describe Spectator::Matchers::ChangeMatcher do
|
||||||
matcher.from(0).should be_a(Spectator::Matchers::ChangeFromMatcher(Int32, Int32))
|
matcher.from(0).should be_a(Spectator::Matchers::ChangeFromMatcher(Int32, Int32))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "passes along the expected from value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeMatcher.new { i }
|
||||||
|
match_data = matcher.from(0).match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"expected before").value.should eq(0)
|
||||||
|
end
|
||||||
|
|
||||||
it "passes along the expression" do
|
it "passes along the expression" do
|
||||||
i = 0
|
i = 0
|
||||||
partial = new_block_partial { i += 5 }
|
partial = new_block_partial { i += 5 }
|
||||||
|
@ -115,4 +123,37 @@ describe Spectator::Matchers::ChangeMatcher do
|
||||||
match_data.message.should contain(label)
|
match_data.message.should contain(label)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#to" do
|
||||||
|
it "returns a ChangeToMatcher" do
|
||||||
|
i = 0
|
||||||
|
matcher = Spectator::Matchers::ChangeMatcher.new { i }
|
||||||
|
matcher.to(0).should be_a(Spectator::Matchers::ChangeToMatcher(Int32, Int32))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes along the expected to value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeMatcher.new { i }
|
||||||
|
match_data = matcher.to(5).match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"expected after").value.should eq(5)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes along the expression" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeMatcher.new { i }
|
||||||
|
matcher.to(5).match(partial)
|
||||||
|
i.should eq(5) # Local scope `i` will be updated if the expression (closure) was passed on.
|
||||||
|
end
|
||||||
|
|
||||||
|
it "passes along the label" do
|
||||||
|
i = 0
|
||||||
|
label = "EXPRESSION"
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeMatcher.new(label) { i }
|
||||||
|
match_data = matcher.to(5).match(partial)
|
||||||
|
match_data.message.should contain(label)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
191
spec/matchers/change_to_matcher_spec.cr
Normal file
191
spec/matchers/change_to_matcher_spec.cr
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
require "../spec_helper"
|
||||||
|
|
||||||
|
describe Spectator::Matchers::ChangeToMatcher do
|
||||||
|
describe "#match" do
|
||||||
|
context "returned MatchData" do
|
||||||
|
context "with a static expression" do
|
||||||
|
describe "#matched?" do
|
||||||
|
it "is false" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 0 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(i) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.matched?.should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with changing expression" do
|
||||||
|
describe "#matched?" do
|
||||||
|
it "is true" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(i + 5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.matched?.should be_true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#values" do
|
||||||
|
context "expected before" do
|
||||||
|
it "is the negated resulting value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_sans_prefix(match_data.values, :"expected before")[:value].should eq(5)
|
||||||
|
match_data_value_sans_prefix(match_data.values, :"expected before")[:to_s].should start_with("Not ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "actual before" do
|
||||||
|
it "is the initial value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"actual before").value.should eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "expected after" do
|
||||||
|
it "is the expected value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"expected after").value.should eq(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "actual after" do
|
||||||
|
it "is the resulting value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"actual after").value.should eq(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#message" do
|
||||||
|
it "contains the action label" do
|
||||||
|
i = 0
|
||||||
|
label = "ACTION"
|
||||||
|
partial = new_block_partial(label) { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(i + 5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.message.should contain(label)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "contains the expression label" do
|
||||||
|
i = 0
|
||||||
|
label = "EXPRESSION"
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(label, i + 5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.message.should contain(label)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#negated_message" do
|
||||||
|
it "contains the action label" do
|
||||||
|
i = 0
|
||||||
|
label = "ACTION"
|
||||||
|
partial = new_block_partial(label) { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(i + 5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.negated_message.should contain(label)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "contains the expression label" do
|
||||||
|
i = 0
|
||||||
|
label = "EXPRESSION"
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(label, i + 5) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.negated_message.should contain(label)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with the wrong final value" do
|
||||||
|
describe "#matched?" do
|
||||||
|
it "is false" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(2) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.matched?.should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#values" do
|
||||||
|
context "expected before" do
|
||||||
|
it "is the negated resulting value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(2) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_sans_prefix(match_data.values, :"expected before")[:value].should eq(2)
|
||||||
|
match_data_value_sans_prefix(match_data.values, :"expected before")[:to_s].should start_with("Not ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "actual before" do
|
||||||
|
it "is the initial value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(2) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"actual before").value.should eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "expected after" do
|
||||||
|
it "is the expected value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(2) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"expected after").value.should eq(2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "actual after" do
|
||||||
|
it "is the resulting value" do
|
||||||
|
i = 0
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(2) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data_value_with_key(match_data.values, :"actual after").value.should eq(5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#message" do
|
||||||
|
it "contains the expression label" do
|
||||||
|
i = 0
|
||||||
|
label = "EXPRESSION"
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(label, 2) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.message.should contain(label)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#negated_message" do
|
||||||
|
it "contains the expression label" do
|
||||||
|
i = 0
|
||||||
|
label = "EXPRESSION"
|
||||||
|
partial = new_block_partial { i += 5 }
|
||||||
|
matcher = Spectator::Matchers::ChangeToMatcher.new(label, 2) { i }
|
||||||
|
match_data = matcher.match(partial)
|
||||||
|
match_data.negated_message.should contain(label)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,6 @@
|
||||||
require "./change_from_matcher"
|
require "./change_from_matcher"
|
||||||
require "./value_matcher"
|
require "./change_to_matcher"
|
||||||
|
require "./matcher"
|
||||||
|
|
||||||
module Spectator::Matchers
|
module Spectator::Matchers
|
||||||
# Matcher that tests whether an expression changed.
|
# Matcher that tests whether an expression changed.
|
||||||
|
@ -35,6 +36,11 @@ module Spectator::Matchers
|
||||||
ChangeFromMatcher.new(label, value, &@expression)
|
ChangeFromMatcher.new(label, value, &@expression)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Specifies what the resulting value of the expression must be.
|
||||||
|
def to(value : T) forall T
|
||||||
|
ChangeToMatcher.new(label, value, &@expression)
|
||||||
|
end
|
||||||
|
|
||||||
# Match data specific to this matcher.
|
# Match data specific to this matcher.
|
||||||
private struct MatchData(ExpressionType) < MatchData
|
private struct MatchData(ExpressionType) < MatchData
|
||||||
# Creates the match data.
|
# Creates the match data.
|
||||||
|
|
102
src/spectator/matchers/change_to_matcher.cr
Normal file
102
src/spectator/matchers/change_to_matcher.cr
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
require "./value_matcher"
|
||||||
|
|
||||||
|
module Spectator::Matchers
|
||||||
|
# Matcher that tests whether an expression changed to a specific value.
|
||||||
|
struct ChangeToMatcher(ExpressionType, ToType) < Matcher
|
||||||
|
# Textual representation of what the matcher expects.
|
||||||
|
# This shouldn't be used in the conditional logic,
|
||||||
|
# but for verbose output to help the end-user.
|
||||||
|
getter label : String
|
||||||
|
|
||||||
|
# Determines whether the matcher is satisfied with the partial given to it.
|
||||||
|
# `MatchData` is returned that contains information about the match.
|
||||||
|
def match(partial)
|
||||||
|
before = @expression.call # Retrieve the expression's initial value.
|
||||||
|
partial.actual # Invoke action that might change the expression's value.
|
||||||
|
after = @expression.call # Retrieve the expression's value again.
|
||||||
|
if @expected_after != after
|
||||||
|
# Resulting value isn't what was expected.
|
||||||
|
ResultingMatchData.new(before, @expected_after, after, partial.label, label)
|
||||||
|
else
|
||||||
|
# Check if the expression's value changed.
|
||||||
|
same = before == after
|
||||||
|
ChangeMatchData.new(!same, before, @expected_after, after, partial.label, label)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Creates a new change matcher with a custom label.
|
||||||
|
def initialize(@label, @expected_after : ToType, &expression : -> ExpressionType)
|
||||||
|
@expression = expression
|
||||||
|
end
|
||||||
|
|
||||||
|
# Creates a new change matcher.
|
||||||
|
def initialize(@expected_after : ToType, &expression : -> ExpressionType)
|
||||||
|
@label = expression.to_s
|
||||||
|
@expression = expression
|
||||||
|
end
|
||||||
|
|
||||||
|
# Match data for when the resulting value isn't the expected value.
|
||||||
|
private struct ResultingMatchData(ExpressionType, ToType) < MatchData
|
||||||
|
# Creates the match data.
|
||||||
|
def initialize(@before : ExpressionType, @expected_after : ToType, @actual_after : ExpressionType,
|
||||||
|
@action_label : String, @expression_label : String)
|
||||||
|
super(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Do not allow negation of this match data.
|
||||||
|
def override?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Information about the match.
|
||||||
|
def named_tuple
|
||||||
|
{
|
||||||
|
"expected before": NegatableMatchDataValue.new(@expected_after, true),
|
||||||
|
"actual before": @before,
|
||||||
|
"expected after": @expected_after,
|
||||||
|
"actual after": @actual_after,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# This is informational and displayed to the end-user.
|
||||||
|
def message
|
||||||
|
"#{@expression_label} changes to #{@expected_after}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# This is informational and displayed to the end-user.
|
||||||
|
def negated_message
|
||||||
|
"#{@expression_label} did not change to #{@expected_after}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private struct ChangeMatchData(ExpressionType, ToType) < MatchData
|
||||||
|
# Creates the match data.
|
||||||
|
def initialize(matched, @before : ToType, @expected_after : ToType, @actual_after : ExpressionType,
|
||||||
|
@action_label : String, @expression_label : String)
|
||||||
|
super(matched)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Information about the match.
|
||||||
|
def named_tuple
|
||||||
|
{
|
||||||
|
"expected before": NegatableMatchDataValue.new(@expected_after, true),
|
||||||
|
"actual before": @before,
|
||||||
|
"expected after": @expected_after,
|
||||||
|
"actual after": @actual_after,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Describes the condition that satisfies the matcher.
|
||||||
|
# This is informational and displayed to the end-user.
|
||||||
|
def message
|
||||||
|
"#{@action_label} changed #{@expression_label} to #{@expected_after}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Describes the condition that won't satsify the matcher.
|
||||||
|
# This is informational and displayed to the end-user.
|
||||||
|
def negated_message
|
||||||
|
"#{@action_label} did not change #{@expression_label} to #{@expected_after}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue