Add negation wrappers

Fixes the reported expected values when the expectation is negated.
This commit is contained in:
Michael Miller 2019-03-06 21:39:28 -07:00
parent a9d1f1aabc
commit ee7a91c3dd
24 changed files with 118 additions and 23 deletions

View file

@ -21,7 +21,13 @@ module Spectator::Expectations
# Information about the match. # Information about the match.
# Returned value and type will something that has key-value pairs (like a `NamedTuple`). # Returned value and type will something that has key-value pairs (like a `NamedTuple`).
def values def values
@match_data.values @match_data.values.tap do |values|
if @negated
values.each_value do |value|
value.negate if value.responds_to?(:negate)
end
end
end
end end
# Text that indicates the condition that must be met for the expectation to be satisifed. # Text that indicates the condition that must be met for the expectation to be satisifed.

View file

@ -0,0 +1,28 @@
module Spectator::Matchers
# Selects a value based on whether the value is negated.
# This is used when a matcher is negated.
private class AlternativeValue(T1, T2)
# Negatable value.
getter value
# Creates the wrapper.
def initialize(@value1 : T1, @value2 : T2)
@negated = false
end
# Negates (toggles) the value.
def negate
@negated = !@negated
end
# Produces a stringified value.
def to_s(io)
io << @negated ? @value1 : @value2
end
# Produces a stringified value with additional information.
def inspect(io)
(@negated ? @value1 : @value2).inspect(io)
end
end
end

View file

@ -49,7 +49,7 @@ module Spectator::Matchers
{% begin %} {% begin %}
{ {
{% for attribute in ExpectedType.keys %} {% for attribute in ExpectedType.keys %}
{{"expected " + attribute.stringify}}: @values.expected[{{attribute.symbolize}}], {{"expected " + attribute.stringify}}: NegatableValue.new(@values.expected[{{attribute.symbolize}}]),
{{"actual " + attribute.stringify}}: @values.actual[{{attribute.symbolize}}], {{"actual " + attribute.stringify}}: @values.actual[{{attribute.symbolize}}],
{% end %} {% end %}
} }

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: @values.expected, expected: NegatableValue.new(@values.expected),
actual: @values.actual, actual: @values.actual,
} }
end end

View file

@ -28,7 +28,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
subset: @values.expected, subset: NegatableValue.new(@values.expected),
superset: @values.actual, superset: @values.actual,
} }
end end

View file

@ -27,7 +27,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: [] of Nil, expected: NegatableValue.new([] of Nil),
actual: @actual, actual: @actual,
} }
end end

View file

@ -39,7 +39,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: @values.expected, expected: NegatableValue.new(@values.expected),
actual: @values.actual, actual: @values.actual,
} }
end end

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: @values.expected, expected: NegatableValue.new(@values.expected),
actual: @values.actual, actual: @values.actual,
} }
end end

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: PrefixedValue.new(">=", @values.expected), expected: NegatablePrefixedValue.new(">=", "<", @values.expected),
actual: PrefixedValue.new(actual_operator, @values.actual), actual: PrefixedValue.new(actual_operator, @values.actual),
} }
end end

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: PrefixedValue.new(">", @values.expected), expected: NegatablePrefixedValue.new(">", "<=", @values.expected),
actual: PrefixedValue.new(actual_operator, @values.actual), actual: PrefixedValue.new(actual_operator, @values.actual),
} }
end end

View file

@ -27,7 +27,7 @@ module Spectator::Matchers
def values def values
actual = @values.actual actual = @values.actual
{ {
key: @values.expected, key: NegatableValue.new(@values.expected),
actual: actual.responds_to?(:keys) ? actual.keys : actual, actual: actual.responds_to?(:keys) ? actual.keys : actual,
} }
end end

View file

@ -51,7 +51,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
subset: @values.expected, subset: NegatableValue.new(@values.expected),
superset: @values.actual, superset: @values.actual,
} }
end end

View file

@ -27,7 +27,7 @@ module Spectator::Matchers
def values def values
actual = @values.actual actual = @values.actual
{ {
value: @values.expected, value: NegatableValue.new(@values.expected),
actual: actual.responds_to?(:values) ? actual.values : actual, actual: actual.responds_to?(:values) ? actual.values : actual,
} }
end end

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: PrefixedValue.new("Not", @values.expected), expected: NegatablePrefixedValue.new("Not", "", @values.expected),
actual: @values.actual, actual: @values.actual,
} }
end end

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: PrefixedValue.new("<=", @values.expected), expected: NegatablePrefixedValue.new("<=", ">", @values.expected),
actual: PrefixedValue.new(actual_operator, @values.actual), actual: PrefixedValue.new(actual_operator, @values.actual),
} }
end end

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: PrefixedValue.new("<", @values.expected), expected: NegatablePrefixedValue.new("<", ">=", @values.expected),
actual: PrefixedValue.new(actual_operator, @values.actual), actual: PrefixedValue.new(actual_operator, @values.actual),
} }
end end

View file

@ -0,0 +1,27 @@
module Spectator::Matchers
# Wraps a prefixed value that can be negated.
# This is used when a matcher is negated.
private class NegatablePrefixedValue(T)
# Creates the wrapper.
def initialize(@positive_prefix : String, @negative_prefix : String, @value : T)
@negated = false
end
# Negates (toggles) the value.
def negate
@negated = !@negated
end
# Produces a stringified value.
def to_s(io)
io << @negated ? @negative_prefix : @positive_prefix
io << @value
end
# Produces a stringified value with additional information.
def inspect(io)
io << @negated ? @negative_prefix : @positive_prefix
@value.inspect(io)
end
end
end

View file

@ -0,0 +1,32 @@
module Spectator::Matchers
# Wraps an expected value that can be negated.
# This is used when a matcher is negated.
private class NegatableValue(T)
# Negatable value.
getter value
# Creates the wrapper.
def initialize(@value : T)
@negated = false
end
# Negates (toggles) the value.
def negate
@negated = !@negated
end
# Produces a stringified value.
# The string will be prefixed with "Not" when negated.
def to_s(io)
io << "Not " if @negated
io << @value
end
# Produces a stringified value with additional information.
# The string will be prefixed with "Not" when negated.
def inspect(io)
io << "Not " if @negated
@value.inspect(io)
end
end
end

View file

@ -27,7 +27,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: nil, expected: NegatableValue.new(nil),
actual: @actual, actual: @actual,
} }
end end

View file

@ -67,8 +67,8 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
lower: PrefixedValue.new(">=", range.begin), lower: NegatablePrefixedValue.new(">=", "<", range.begin),
upper: PrefixedValue.new(exclusive? ? "<" : "<=", range.end), upper: NegatablePrefixedValue.new(exclusive? ? "<" : "<=", exclusive? ? ">=" : ">", range.end),
actual: @values.actual, actual: @values.actual,
} }
end end
@ -112,7 +112,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
set: @values.expected, set: NegatableValue.new(@values.expected),
actual: @values.actual, actual: @values.actual,
} }
end end

View file

@ -26,7 +26,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: @values.expected, expected: NegatableValue.new(@values.expected),
actual: @values.actual, actual: @values.actual,
} }
end end

View file

@ -39,7 +39,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: @values.expected, expected: NegatableValue.new(@values.expected),
actual: @values.actual, actual: @values.actual,
} }
end end

View file

@ -96,8 +96,10 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
truthy = "Not false or nil"
falsey = "false or nil"
{ {
expected: @truthy ? "Not false or nil" : "false or nil", expected: AlternativeValue.new(@truthy ? truthy : falsey, @truthy ? falsey : truthy),
actual: @actual, actual: @actual,
truthy: !!@actual, truthy: !!@actual,
} }

View file

@ -32,7 +32,7 @@ module Spectator::Matchers
# Information about the match. # Information about the match.
def values def values
{ {
expected: ExpectedType, expected: NegatableValue.new(ExpectedType),
actual: ActualType, actual: ActualType,
} }
end end