rspec-expectations/upstream/lib/rspec/matchers/built_in/has.rb in opal-rspec-0.8.0 vs rspec-expectations/upstream/lib/rspec/matchers/built_in/has.rb in opal-rspec-1.0.0.alpha1

- old
+ new

@@ -1,15 +1,18 @@ module RSpec module Matchers module BuiltIn # @api private - # Provides the implementation for `has_<predicate>`. - # Not intended to be instantiated directly. - class Has < BaseMatcher + # Provides the implementation for dynamic predicate matchers. + # Not intended to be inherited directly. + class DynamicPredicate < BaseMatcher + include BeHelpers + def initialize(method_name, *args, &block) @method_name, @args, @block = method_name, args, block end + ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true) # @private def matches?(actual, &block) @actual = actual @block ||= block @@ -18,83 +21,146 @@ # @private def does_not_match?(actual, &block) @actual = actual @block ||= block - predicate_accessible? && !predicate_matches? + predicate_accessible? && predicate_matches?(false) end # @api private # @return [String] def failure_message - validity_message || "expected ##{predicate}#{failure_message_args_description} to return true, got false" + failure_message_expecting(true) end # @api private # @return [String] def failure_message_when_negated - validity_message || "expected ##{predicate}#{failure_message_args_description} to return false, got true" + failure_message_expecting(false) end # @api private # @return [String] def description - [method_description, args_description].compact.join(' ') + "#{method_description}#{args_to_sentence}" end private def predicate_accessible? - !private_predicate? && predicate_exists? + @actual.respond_to? predicate end # support 1.8.7, evaluate once at load time for performance if String === methods.first + # :nocov: def private_predicate? @actual.private_methods.include? predicate.to_s end + # :nocov: else def private_predicate? @actual.private_methods.include? predicate end end - def predicate_exists? - @actual.respond_to? predicate + def predicate_result + @predicate_result = actual.__send__(predicate_method_name, *@args, &@block) end - def predicate_matches? - @actual.__send__(predicate, *@args, &@block) + def predicate_method_name + predicate end - def predicate + def predicate_matches?(value=true) + if RSpec::Expectations.configuration.strict_predicate_matchers? + value == predicate_result + else + value == !!predicate_result + end + end + + def root # On 1.9, there appears to be a bug where String#match can return `false` # rather than the match data object. Changing to Regex#match appears to # work around this bug. For an example of this bug, see: # https://travis-ci.org/rspec/rspec-expectations/jobs/27549635 - @predicate ||= :"has_#{Matchers::HAS_REGEX.match(@method_name.to_s).captures.first}?" + self.class::REGEX.match(@method_name.to_s).captures.first end def method_description - @method_name.to_s.gsub('_', ' ') + EnglishPhrasing.split_words(@method_name) end - def args_description - return nil if @args.empty? - @args.map { |arg| arg.inspect }.join(', ') + def failure_message_expecting(value) + validity_message || + "expected `#{actual_formatted}.#{predicate}#{args_to_s}` to #{expectation_of value}, got #{description_of @predicate_result}" end - def failure_message_args_description - desc = args_description - "(#{desc})" if desc + def expectation_of(value) + if RSpec::Expectations.configuration.strict_predicate_matchers? + "return #{value}" + elsif value + "be truthy" + else + "be falsey" + end end def validity_message + return nil if predicate_accessible? + + "expected #{actual_formatted} to respond to `#{predicate}`#{failure_to_respond_explanation}" + end + + def failure_to_respond_explanation if private_predicate? - "expected #{@actual} to respond to `#{predicate}` but `#{predicate}` is a private method" - elsif !predicate_exists? - "expected #{@actual} to respond to `#{predicate}`" + " but `#{predicate}` is a private method" end + end + end + + # @api private + # Provides the implementation for `has_<predicate>`. + # Not intended to be instantiated directly. + class Has < DynamicPredicate + # :nodoc: + REGEX = Matchers::HAS_REGEX + private + def predicate + @predicate ||= :"has_#{root}?" + end + end + + # @api private + # Provides the implementation of `be_<predicate>`. + # Not intended to be instantiated directly. + class BePredicate < DynamicPredicate + # :nodoc: + REGEX = Matchers::BE_PREDICATE_REGEX + private + def predicate + @predicate ||= :"#{root}?" + end + + def predicate_method_name + actual.respond_to?(predicate) ? predicate : present_tense_predicate + end + + def failure_to_respond_explanation + super || if predicate == :true? + " or perhaps you meant `be true` or `be_truthy`" + elsif predicate == :false? + " or perhaps you meant `be false` or `be_falsey`" + end + end + + def predicate_accessible? + super || actual.respond_to?(present_tense_predicate) + end + + def present_tense_predicate + :"#{root}s?" end end end end end