lib/rspec/matchers/built_in/exist.rb in rspec-expectations-3.0.0.beta2 vs lib/rspec/matchers/built_in/exist.rb in rspec-expectations-3.0.0.rc1
- old
+ new
@@ -1,26 +1,90 @@
module RSpec
module Matchers
module BuiltIn
+ # @api private
+ # Provides the implementation for `exist`.
+ # Not intended to be instantiated directly.
class Exist < BaseMatcher
def initialize(*expected)
@expected = expected
end
+ # @api private
+ # @return [Boolean]
def matches?(actual)
@actual = actual
- predicates = [:exist?, :exists?].select { |p| @actual.respond_to?(p) }
- existence_values = predicates.map { |p| @actual.__send__(p, *@expected) }
- uniq_truthy_values = existence_values.map { |v| !!v }.uniq
+ @test = ExistenceTest.new @actual, @expected
+ @test.valid_test? && @test.actual_exists?
+ end
- case uniq_truthy_values.size
- when 0; raise NoMethodError.new("#{@actual.inspect} does not respond to either #exist? or #exists?")
- when 1; existence_values.first
- else raise "#exist? and #exists? returned different values:\n\n" +
- " exist?: #{existence_values.first}\n" +
- "exists?: #{existence_values.last}"
+ # @api private
+ # @return [Boolean]
+ def does_not_match?(actual)
+ @actual = actual
+ @test = ExistenceTest.new @actual, @expected
+ @test.valid_test? && !@test.actual_exists?
+ end
+
+ # @api private
+ # @return [String]
+ def failure_message
+ "expected #{@actual.inspect} to exist#{@test.validity_message}"
+ end
+
+ # @api private
+ # @return [String]
+ def failure_message_when_negated
+ "expected #{@actual.inspect} not to exist#{@test.validity_message}"
+ end
+
+ private
+
+ # @api private
+ # Simple class for memoizing actual/expected for this matcher
+ # and examining the match
+ class ExistenceTest < Struct.new(:actual, :expected)
+
+ # @api private
+ # @return [Boolean]
+ def valid_test?
+ uniq_truthy_values.size == 1
end
+
+ # @api private
+ # @return [Boolean]
+ def actual_exists?
+ existence_values.first
+ end
+
+ # @api private
+ # @return [String]
+ def validity_message
+ case uniq_truthy_values.size
+ when 0
+ " but it does not respond to either `exist?` or `exists?`"
+ when 2
+ " but `exist?` and `exists?` returned different values:\n\n"\
+ " exist?: #{existence_values.first}\n"\
+ "exists?: #{existence_values.last}"
+ end
+ end
+
+ private
+
+ def uniq_truthy_values
+ @uniq_truthy_values ||= existence_values.map { |v| !!v }.uniq
+ end
+
+ def existence_values
+ @existence_values ||= predicates.map { |p| actual.__send__(p, *expected) }
+ end
+
+ def predicates
+ @predicates ||= [:exist?, :exists?].select { |p| actual.respond_to?(p) }
+ end
end
+
end
end
end
end