diff --git a/src/spectator/expectations/block_expectation.cr b/src/spectator/expectations/block_expectation.cr new file mode 100644 index 0000000..ba30de6 --- /dev/null +++ b/src/spectator/expectations/block_expectation.cr @@ -0,0 +1,31 @@ +require "./expectation" + +module Spectator::Expectations + # Expectation that operates on a block. + # A block produces some value one or more times. + # A matcher checks whether the values produced by the block satisfy some conditions. + # The behavior of the block can be tested by verifying the values produced by it. + class BlockExpectation(ReturnType) < Expectation + # Creates the expectation. + # The `matched` flag should be true if the matcher is satisfied with the partial. + # The `negated` flag should be true if the expectation is inverted. + # See `Expectation#initialize` for details on these two arguments. + # The `partial` and the `matcher` arguments should reference + # the actual and expected value with matcher respectively. + def initialize(matched, negated, + @partial : BlockExpectationPartial(ReturnType), + @matcher : Matchers::Matcher) + super(matched, negated) + end + + # Describes the condition that must be met for the expectation to be satisifed. + private def message : String + @matcher.message(@partial) + end + + # Describes the condition under which the expectation won't be satisifed. + private def negated_message : String + @matcher.negated_message(@partial) + end + end +end diff --git a/src/spectator/expectations/block_expectation_partial.cr b/src/spectator/expectations/block_expectation_partial.cr new file mode 100644 index 0000000..12efac5 --- /dev/null +++ b/src/spectator/expectations/block_expectation_partial.cr @@ -0,0 +1,31 @@ +require "./expectation_partial" + +module Spectator::Expectations + # Expectation partial variation that operates on a block. + struct BlockExpectationPartial(ReturnType) < ExpectationPartial + # Actual value produced by calling the block. + def actual + @block.call + end + + # Creates the expectation partial. + # The label should be a string representation of the block. + # The block is stored for later use. + protected def initialize(label : String, @block : -> ReturnType) + super(label) + end + + # Creates the expectation partial. + # The label is generated by calling `#to_s` on the block. + # The block is stored for later use. + protected def initialize(@block : -> ReturnType) + super(@block.to_s) + end + + # Evaluates the expectation and returns it. + private def eval(matcher, negated = false) : Expectation + matched = matcher.match?(self) + BlockExpectation.new(matched, negated, self, matcher) + end + end +end