Update HaveKeyMatcher to use MatchData

This commit is contained in:
Michael Miller 2019-03-06 02:02:55 -07:00
parent 95b4a349da
commit 3f1d8751fe
2 changed files with 172 additions and 98 deletions

View file

@ -1,108 +1,165 @@
require "../spec_helper" require "../spec_helper"
private struct FakeKeySet
def has_key?(key)
true
end
end
describe Spectator::Matchers::HaveKeyMatcher do describe Spectator::Matchers::HaveKeyMatcher do
describe "#match?" do describe "#match" do
context "against a Hash" do context "returned MatchData" do
context "with an existing key" do describe "#matched?" do
it "is true" do context "against a Hash" do
hash = Hash{"foo" => "bar"} context "with an existing key" do
key = "foo" it "is true" do
partial = new_partial(hash) hash = Hash{"foo" => "bar"}
matcher = Spectator::Matchers::HaveKeyMatcher.new(key) key = "foo"
matcher.match?(partial).should be_true partial = new_partial(hash)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.matched?.should be_true
end
end
context "with a non-existent key" do
it "is false" do
hash = Hash{"foo" => "bar"}
key = "baz"
partial = new_partial(hash)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.matched?.should be_false
end
end
end
context "against a NamedTuple" do
context "with an existing key" do
it "is true" do
tuple = {foo: "bar"}
key = :foo
partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.matched?.should be_true
end
end
context "with a non-existent key" do
it "is false" do
tuple = {foo: "bar"}
key = :baz
partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.matched?.should be_false
end
end
end end
end end
context "with a non-existent key" do describe "#values" do
it "is false" do context "key" do
hash = Hash{"foo" => "bar"} it "is the expected key" do
key = "baz" tuple = {foo: "bar"}
partial = new_partial(hash) key = :baz
matcher = Spectator::Matchers::HaveKeyMatcher.new(key) partial = new_partial(tuple)
matcher.match?(partial).should be_false matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.values[:key].should eq(key)
end
end
context "actual" do
context "when #keys is available" do
it "is the list of keys" do
tuple = {foo: "bar"}
key = :baz
partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.values[:actual].should eq(tuple.keys)
end
end
context "when #keys isn't available" do
it "is the actual value" do
actual = FakeKeySet.new
key = :baz
partial = new_partial(actual)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.values[:actual].should eq(actual)
end
end
end end
end end
end
context "against a NamedTuple" do describe "#message" do
context "with an existing key" do it "contains the actual label" do
it "is true" do
tuple = {foo: "bar"} tuple = {foo: "bar"}
key = :foo key = :foo
partial = new_partial(tuple) label = "blah"
partial = new_partial(tuple, label)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key) matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
matcher.match?(partial).should be_true match_data = matcher.match(partial)
match_data.message.should contain(label)
end end
end
context "with a non-existent key" do it "contains the expected label" do
it "is false" do
tuple = {foo: "bar"} tuple = {foo: "bar"}
key = :baz key = :foo
label = "blah"
partial = new_partial(tuple) partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key) matcher = Spectator::Matchers::HaveKeyMatcher.new(key, label)
matcher.match?(partial).should be_false match_data = matcher.match(partial)
match_data.message.should contain(label)
end
context "when the expected label is omitted" do
it "contains the stringified key" do
tuple = {foo: "bar"}
key = :foo
partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
match_data = matcher.match(partial)
match_data.message.should contain(key.to_s)
end
end end
end end
end
end
describe "#message" do describe "#negated_message" do
it "contains the actual label" do it "contains the actual label" do
tuple = {foo: "bar"} tuple = {foo: "bar"}
key = :foo key = :foo
label = "blah" label = "blah"
partial = new_partial(tuple, label) partial = new_partial(tuple, label)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key) matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
matcher.message(partial).should contain(label) match_data = matcher.match(partial)
end match_data.negated_message.should contain(label)
end
it "contains the expected label" do it "contains the expected label" do
tuple = {foo: "bar"} tuple = {foo: "bar"}
key = :foo key = :foo
label = "blah" label = "blah"
partial = new_partial(tuple) partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key, label) matcher = Spectator::Matchers::HaveKeyMatcher.new(key, label)
matcher.message(partial).should contain(label) match_data = matcher.match(partial)
end match_data.negated_message.should contain(label)
end
context "when the expected label is omitted" do context "when the expected label is omitted" do
it "contains the stringified key" do it "contains the stringified key" do
tuple = {foo: "bar"} tuple = {foo: "bar"}
key = :foo key = :foo
partial = new_partial(tuple) partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key) matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
matcher.message(partial).should contain(key.to_s) match_data = matcher.match(partial)
end match_data.negated_message.should contain(key.to_s)
end end
end end
describe "#negated_message" do
it "contains the actual label" do
tuple = {foo: "bar"}
key = :foo
label = "blah"
partial = new_partial(tuple, label)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
matcher.negated_message(partial).should contain(label)
end
it "contains the expected label" do
tuple = {foo: "bar"}
key = :foo
label = "blah"
partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key, label)
matcher.negated_message(partial).should contain(label)
end
context "when the expected label is omitted" do
it "contains the stringified key" do
tuple = {foo: "bar"}
key = :foo
partial = new_partial(tuple)
matcher = Spectator::Matchers::HaveKeyMatcher.new(key)
matcher.negated_message(partial).should contain(key.to_s)
end end
end end
end end

View file

@ -5,27 +5,44 @@ module Spectator::Matchers
# The set is checked with the `has_key?` method. # The set is checked with the `has_key?` method.
struct HaveKeyMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct HaveKeyMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. private def match?(actual)
def match?(partial) actual.has_key?(expected)
partial.actual.has_key?(expected)
end end
# Determines whether the matcher is satisfied with the partial given to it. # Determines whether the matcher is satisfied with the partial given to it.
# `MatchData` is returned that contains information about the match. # `MatchData` is returned that contains information about the match.
def match(partial) : MatchData def match(partial)
raise NotImplementedError.new("#match") values = ExpectedActual.new(partial, self)
MatchData.new(match?(values.actual), values)
end end
# Describes the condition that satisfies the matcher. # Match data specific to this matcher.
# This is informational and displayed to the end-user. private struct MatchData(ExpectedType, ActualType) < MatchData
def message(partial) # Creates the match data.
"Expected #{partial.label} to have key #{label}" def initialize(matched, @values : ExpectedActual(ExpectedType, ActualType))
end super(matched)
end
# Describes the condition that won't satsify the matcher. # Information about the match.
# This is informational and displayed to the end-user. def values
def negated_message(partial) actual = @values.actual
"Expected #{partial.label} to not have key #{label}" {
key: @values.expected,
actual: actual.responds_to?(:keys) ? actual.keys : actual,
}
end
# Describes the condition that satisfies the matcher.
# This is informational and displayed to the end-user.
def message
"#{@values.actual_label} has key #{@values.expected_label}"
end
# Describes the condition that won't satsify the matcher.
# This is informational and displayed to the end-user.
def negated_message
"#{@values.actual_label} does not have key #{@values.expected_label}"
end
end end
end end
end end