mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Initial code for basic change matcher
This commit is contained in:
parent
1521107934
commit
3e1ee7eb6d
3 changed files with 173 additions and 0 deletions
81
spec/matchers/change_matcher_spec.cr
Normal file
81
spec/matchers/change_matcher_spec.cr
Normal file
|
@ -0,0 +1,81 @@
|
|||
require "../spec_helper"
|
||||
|
||||
describe Spectator::Matchers::ChangeMatcher do
|
||||
describe "#match" do
|
||||
context "returned MatchData" do
|
||||
context "with changing expression" do
|
||||
describe "#matched?" do
|
||||
it "is true" do
|
||||
i = 0
|
||||
partial = new_block_partial { i += 5 }
|
||||
matcher = Spectator::Matchers::ChangeMatcher.new { i }
|
||||
match_data = matcher.match(partial)
|
||||
match_data.matched?.should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#values" do
|
||||
context "before" do
|
||||
it "is the initial value" do
|
||||
i = 0
|
||||
partial = new_block_partial { i += 5 }
|
||||
matcher = Spectator::Matchers::ChangeMatcher.new { i }
|
||||
match_data = matcher.match(partial)
|
||||
match_data_value_with_key(match_data.values, :before).value.should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "after" do
|
||||
it "is the resulting value" do
|
||||
i = 0
|
||||
partial = new_block_partial { i += 5 }
|
||||
matcher = Spectator::Matchers::ChangeMatcher.new { i }
|
||||
match_data = matcher.match(partial)
|
||||
match_data_value_with_key(match_data.values, :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::ChangeMatcher.new { 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::ChangeMatcher.new(label) { 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::ChangeMatcher.new { 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::ChangeMatcher.new(label) { i }
|
||||
match_data = matcher.match(partial)
|
||||
match_data.negated_message.should contain(label)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -506,6 +506,38 @@ module Spectator::DSL
|
|||
::Spectator::Matchers::AttributesMatcher.new(::Spectator::TestValue.new({{expected}}, {{expected.double_splat.stringify}}))
|
||||
end
|
||||
|
||||
# Indicates that some expression's value should change after taking an action.
|
||||
#
|
||||
# Examples:
|
||||
# ```
|
||||
# i = 0
|
||||
# expect { i += 1 }.to change { i }
|
||||
# expect { i += 0 }.to_not change { i }
|
||||
# ```
|
||||
#
|
||||
# ```
|
||||
# i = 0
|
||||
# expect { i += 5 }.to change { i }.from(0).to(5)
|
||||
# ```
|
||||
#
|
||||
# ```
|
||||
# i = 0
|
||||
# expect { i += 5 }.to change { i }.to(5)
|
||||
# ```
|
||||
#
|
||||
# ```
|
||||
# i = 0
|
||||
# expect { i += 5 }.to change { i }.from(0)
|
||||
# ```
|
||||
#
|
||||
# ```
|
||||
# i = 0
|
||||
# expect { i += 42 }.to change { i }.by(42)
|
||||
# ```
|
||||
macro change(&expression)
|
||||
::Spectator::Matchers::ChangeMatcher.new("`" + {{expression.body.stringify}} + "`") {{expression}}
|
||||
end
|
||||
|
||||
# Indicates that some block should raise an error.
|
||||
#
|
||||
# Examples:
|
||||
|
|
60
src/spectator/matchers/change_matcher.cr
Normal file
60
src/spectator/matchers/change_matcher.cr
Normal file
|
@ -0,0 +1,60 @@
|
|||
require "./value_matcher"
|
||||
|
||||
module Spectator::Matchers
|
||||
# Matcher that tests whether an expression changed.
|
||||
struct ChangeMatcher(ExpressionType) < ValueMatcher(ExpressionType)
|
||||
# Determines whether the matcher is satisfied with the value given to it.
|
||||
private def match?(after)
|
||||
expected != after
|
||||
end
|
||||
|
||||
# Determines whether the matcher is satisfied with the partial given to it.
|
||||
# `MatchData` is returned that contains information about the match.
|
||||
def match(partial)
|
||||
partial.actual # Invoke action that might change the expression's value.
|
||||
after = @expression.call # Retrieve the expression's value.
|
||||
MatchData.new(match?(after), expected, after, partial.label, label)
|
||||
end
|
||||
|
||||
# Creates a new change matcher with a custom label.
|
||||
def initialize(label : String, &expression : -> ExpressionType)
|
||||
super(yield, label)
|
||||
@expression = expression
|
||||
end
|
||||
|
||||
# Creates a new change matcher.
|
||||
def initialize(&expression : -> ExpressionType)
|
||||
super(yield, expression.to_s)
|
||||
@expression = expression
|
||||
end
|
||||
|
||||
# Match data specific to this matcher.
|
||||
private struct MatchData(ExpressionType) < MatchData
|
||||
# Creates the match data.
|
||||
def initialize(matched, @before : ExpressionType, @after : ExpressionType,
|
||||
@action_label : String, @expression_label : String)
|
||||
super(matched)
|
||||
end
|
||||
|
||||
# Information about the match.
|
||||
def named_tuple
|
||||
{
|
||||
before: @before,
|
||||
after: @after
|
||||
}
|
||||
end
|
||||
|
||||
# Describes the condition that satisfies the matcher.
|
||||
# This is informational and displayed to the end-user.
|
||||
def message
|
||||
"#{@action_label} changes #{@expression_label}"
|
||||
end
|
||||
|
||||
# Describes the condition that won't satsify the matcher.
|
||||
# This is informational and displayed to the end-user.
|
||||
def negated_message
|
||||
"#{@action_label} does not change #{@expression_label}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue