rspec-expectations 3.9.4 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Changelog.md +57 -2
- data/README.md +1 -1
- data/lib/rspec/expectations/configuration.rb +15 -0
- data/lib/rspec/expectations/expectation_target.rb +42 -6
- data/lib/rspec/expectations/failure_aggregator.rb +24 -6
- data/lib/rspec/expectations/handler.rb +18 -6
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers/built_in/base_matcher.rb +5 -0
- data/lib/rspec/matchers/built_in/be.rb +0 -110
- data/lib/rspec/matchers/built_in/change.rb +22 -0
- data/lib/rspec/matchers/built_in/compound.rb +14 -0
- data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
- data/lib/rspec/matchers/built_in/has.rb +87 -24
- data/lib/rspec/matchers/built_in/include.rb +72 -15
- data/lib/rspec/matchers/built_in/output.rb +7 -0
- data/lib/rspec/matchers/built_in/raise_error.rb +57 -16
- data/lib/rspec/matchers/built_in/respond_to.rb +46 -45
- data/lib/rspec/matchers/built_in/throw_symbol.rb +6 -0
- data/lib/rspec/matchers/built_in/yield.rb +25 -91
- data/lib/rspec/matchers/built_in.rb +2 -1
- data/lib/rspec/matchers/dsl.rb +4 -0
- data/lib/rspec/matchers/matcher_protocol.rb +6 -0
- data/lib/rspec/matchers.rb +41 -39
- data.tar.gz.sig +0 -0
- metadata +10 -9
- metadata.gz.sig +0 -0
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e651e80dd869915779a72a9ea43b38d20327f3dbfaf94a4851eff7974d1f3d0a
         | 
| 4 | 
            +
              data.tar.gz: e1788055c911b97cbad1b3747fe9b9be005a999e2e97e6c361df4c91fa4fda25
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ec1b6b68b80fddae764dbf88312817c35c1e76228c29748e2b89d8d9a69d95384aa4fe9daf7b8a650dd307dd32aca13bae590d8960f0989beea67c54f7f6d7d5
         | 
| 7 | 
            +
              data.tar.gz: 7a8a129e74ccec6299ab3af1c728cab2754a1cc98911507704c3f52a01c33b321250bfe715deef835b61963e22c66ec878500d10c6fea93d4fda7cc39b101676
         | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | Binary file | 
    
        data/Changelog.md
    CHANGED
    
    | @@ -1,3 +1,58 @@ | |
| 1 | 
            +
            ### Development
         | 
| 2 | 
            +
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.0...3-11-maintenance)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            ### 3.11.0 / 2022-02-09
         | 
| 5 | 
            +
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.2...v3.11.0)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Enhancements:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            * Return `true` from `aggregate_failures` when no exception occurs. (Jon Rowe, #1225)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Deprecations:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            * Print a deprecation message when using the implicit block expectation syntax.
         | 
| 14 | 
            +
              (Phil Pirozhkov, #1139)
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            ### 3.10.2 / 2022-01-14
         | 
| 17 | 
            +
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.1...v3.10.2)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            Bug Fixes:
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            * Fix support for dynamic matchers for expectation target checks (Phil Pirozhkov, #1294)
         | 
| 22 | 
            +
            * Fix `expect(array).to include(hash).times`, previously this would fail due to
         | 
| 23 | 
            +
              matching the entire array as a single hash, rather than a member of the hash.
         | 
| 24 | 
            +
              (Slava Kardakov, #1322)
         | 
| 25 | 
            +
            * Ensure `raise_error` matches works with the `error_highlight` option from Ruby 3.1.
         | 
| 26 | 
            +
              (Peter Goldstein, #1339)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            ### 3.10.1 / 2020-12-27
         | 
| 29 | 
            +
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.0...v3.10.1)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            Bug Fixes:
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            * Allow JRuby 9.2.x.x to generate backtraces normally rather than via our
         | 
| 34 | 
            +
              backfill workaround. (#1230, Jon Rowe)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            ### 3.10.0 / 2020-10-30
         | 
| 37 | 
            +
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.3...v3.10.0)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            Enhancements:
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            * Allow `include` matcher to be chained with `once`, `at_least`, etc. for simple cases.
         | 
| 42 | 
            +
              (Marc-André Lafortune, #1168)
         | 
| 43 | 
            +
            * Add an explicit warning when `nil` is passed to `raise_error`. (Phil Pirozhkov, #1143)
         | 
| 44 | 
            +
            * Improve `include` matcher's composability. (Phil Pirozhkov, #1155)
         | 
| 45 | 
            +
            * Mocks expectations can now set a custom failure message.
         | 
| 46 | 
            +
              (Benoit Tigeot and Nicolas Zermati, #1156)
         | 
| 47 | 
            +
            * `aggregate_failures` now shows the backtrace line for each failure. (Fabricio Bedin, #1163)
         | 
| 48 | 
            +
            * Support multiple combinations of `yield_control` modifiers like `at_least`, `at_most`.
         | 
| 49 | 
            +
              (Jon Rowe, #1169)
         | 
| 50 | 
            +
            * Dynamic `have_<n>` matchers now have output consistent with other dynamic matchers.
         | 
| 51 | 
            +
              (Marc-André Lafortune, #1195)
         | 
| 52 | 
            +
            * New config option `strict_predicate_matchers` allows predicate matcher to be strict
         | 
| 53 | 
            +
              (i.e. match for `true` or `false`) instead of the default (match truthy vs `false` or `nil`).
         | 
| 54 | 
            +
              (Marc-André Lafortune, #1196)
         | 
| 55 | 
            +
             | 
| 1 56 | 
             
            ### 3.9.4 / 2020-10-29
         | 
| 2 57 | 
             
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.3...v3.9.4)
         | 
| 3 58 |  | 
| @@ -7,7 +62,6 @@ Bug Fixes: | |
| 7 62 | 
             
              were they would act like keywords and be cast to a hash. (Jon Rowe, #1222)
         | 
| 8 63 |  | 
| 9 64 | 
             
            ### 3.9.3 / 2020-10-23
         | 
| 10 | 
            -
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.2...v3.9.3)
         | 
| 11 65 |  | 
| 12 66 | 
             
            Bug Fixes:
         | 
| 13 67 |  | 
| @@ -22,6 +76,7 @@ Bug Fixes: | |
| 22 76 | 
             
            * Prevent errors from causing false positives when using `be <operator>` comparison, e.g.
         | 
| 23 77 | 
             
              `expect(1).not_to be < 'a'` will now correctly fail rather than pass. (Jon Rowe, #1208)
         | 
| 24 78 |  | 
| 79 | 
            +
             | 
| 25 80 | 
             
            ### 3.9.2 / 2020-05-08
         | 
| 26 81 | 
             
            [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.1...v3.9.2)
         | 
| 27 82 |  | 
| @@ -85,7 +140,7 @@ Bug Fixes: | |
| 85 140 | 
             
            * Prevent composed `all` matchers from leaking into their siblings leading to duplicate
         | 
| 86 141 | 
             
              failures. (Jamie English, #1086)
         | 
| 87 142 | 
             
            * Prevent objects which change their hash on comparison from failing change checks.
         | 
| 88 | 
            -
              (Phil Pirozhkov, # | 
| 143 | 
            +
              (Phil Pirozhkov, #1100)
         | 
| 89 144 | 
             
            * Issue an `ArgumentError` rather than a `NoMethodError` when `be_an_instance_of` and
         | 
| 90 145 | 
             
              `be_kind_of` matchers encounter objects not supporting those methods.
         | 
| 91 146 | 
             
              (Taichi Ishitani, #1107)
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            # RSpec Expectations [](https://github.com/rspec/rspec-expectations/actions) [](https://codeclimate.com/github/rspec/rspec-expectations)
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec::Expectations lets you express expected outcomes on an object in an
         | 
| 4 4 | 
             
            example.
         | 
| @@ -28,6 +28,7 @@ module RSpec | |
| 28 28 |  | 
| 29 29 | 
             
                  def initialize
         | 
| 30 30 | 
             
                    @on_potential_false_positives = :warn
         | 
| 31 | 
            +
                    @strict_predicate_matchers = false
         | 
| 31 32 | 
             
                  end
         | 
| 32 33 |  | 
| 33 34 | 
             
                  # Configures the supported syntax.
         | 
| @@ -185,6 +186,20 @@ module RSpec | |
| 185 186 | 
             
                    @on_potential_false_positives = behavior
         | 
| 186 187 | 
             
                  end
         | 
| 187 188 |  | 
| 189 | 
            +
                  # Configures RSpec to check predicate matchers to `be(true)` / `be(false)` (strict),
         | 
| 190 | 
            +
                  # or `be_truthy` / `be_falsey` (not strict).
         | 
| 191 | 
            +
                  # Historically, the default was `false`, but `true` is recommended.
         | 
| 192 | 
            +
                  def strict_predicate_matchers=(flag)
         | 
| 193 | 
            +
                    raise ArgumentError, "Pass `true` or `false`" unless flag == true || flag == false
         | 
| 194 | 
            +
                    @strict_predicate_matchers = flag
         | 
| 195 | 
            +
                  end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                  attr_reader :strict_predicate_matchers
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                  def strict_predicate_matchers?
         | 
| 200 | 
            +
                    @strict_predicate_matchers
         | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
             | 
| 188 203 | 
             
                  # Indicates what RSpec will do about matcher use which will
         | 
| 189 204 | 
             
                  # potentially cause false positives in tests, generally you want to
         | 
| 190 205 | 
             
                  # avoid such scenarios so this defaults to `true`.
         | 
| @@ -42,7 +42,7 @@ module RSpec | |
| 42 42 | 
             
                    elsif block
         | 
| 43 43 | 
             
                      raise ArgumentError, "You cannot pass both an argument and a block to `expect`."
         | 
| 44 44 | 
             
                    else
         | 
| 45 | 
            -
                      new(value)
         | 
| 45 | 
            +
                      ValueExpectationTarget.new(value)
         | 
| 46 46 | 
             
                    end
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 |  | 
| @@ -57,7 +57,7 @@ module RSpec | |
| 57 57 | 
             
                    #   expect { perform }.to raise_error
         | 
| 58 58 | 
             
                    # @param [Matcher]
         | 
| 59 59 | 
             
                    #   matcher
         | 
| 60 | 
            -
                    # @param [String  | 
| 60 | 
            +
                    # @param [String, Proc] message optional message to display when the expectation fails
         | 
| 61 61 | 
             
                    # @return [Boolean] true if the expectation succeeds (else raises)
         | 
| 62 62 | 
             
                    # @see RSpec::Matchers
         | 
| 63 63 | 
             
                    def to(matcher=nil, message=nil, &block)
         | 
| @@ -70,7 +70,7 @@ module RSpec | |
| 70 70 | 
             
                    #   expect(value).not_to eq(5)
         | 
| 71 71 | 
             
                    # @param [Matcher]
         | 
| 72 72 | 
             
                    #   matcher
         | 
| 73 | 
            -
                    # @param [String  | 
| 73 | 
            +
                    # @param [String, Proc] message optional message to display when the expectation fails
         | 
| 74 74 | 
             
                    # @return [Boolean] false if the negative expectation succeeds (else raises)
         | 
| 75 75 | 
             
                    # @see RSpec::Matchers
         | 
| 76 76 | 
             
                    def not_to(matcher=nil, message=nil, &block)
         | 
| @@ -90,6 +90,44 @@ module RSpec | |
| 90 90 | 
             
                  include InstanceMethods
         | 
| 91 91 | 
             
                end
         | 
| 92 92 |  | 
| 93 | 
            +
                # @private
         | 
| 94 | 
            +
                # Validates the provided matcher to ensure it supports block
         | 
| 95 | 
            +
                # expectations, in order to avoid user confusion when they
         | 
| 96 | 
            +
                # use a block thinking the expectation will be on the return
         | 
| 97 | 
            +
                # value of the block rather than the block itself.
         | 
| 98 | 
            +
                class ValueExpectationTarget < ExpectationTarget
         | 
| 99 | 
            +
                  def to(matcher=nil, message=nil, &block)
         | 
| 100 | 
            +
                    enforce_value_expectation(matcher)
         | 
| 101 | 
            +
                    super
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  def not_to(matcher=nil, message=nil, &block)
         | 
| 105 | 
            +
                    enforce_value_expectation(matcher)
         | 
| 106 | 
            +
                    super
         | 
| 107 | 
            +
                  end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                private
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  def enforce_value_expectation(matcher)
         | 
| 112 | 
            +
                    return if supports_value_expectations?(matcher)
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    RSpec.deprecate(
         | 
| 115 | 
            +
                      "expect(value).to #{RSpec::Support::ObjectFormatter.format(matcher)}",
         | 
| 116 | 
            +
                      :message =>
         | 
| 117 | 
            +
                        "The implicit block expectation syntax is deprecated, you should pass " \
         | 
| 118 | 
            +
                        "a block rather than an argument to `expect` to use the provided " \
         | 
| 119 | 
            +
                        "block expectation matcher or the matcher must implement " \
         | 
| 120 | 
            +
                        "`supports_value_expectations?`. e.g  `expect { value }.to " \
         | 
| 121 | 
            +
                        "#{RSpec::Support::ObjectFormatter.format(matcher)}` not " \
         | 
| 122 | 
            +
                        "`expect(value).to #{RSpec::Support::ObjectFormatter.format(matcher)}`"
         | 
| 123 | 
            +
                    )
         | 
| 124 | 
            +
                  end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  def supports_value_expectations?(matcher)
         | 
| 127 | 
            +
                    !matcher.respond_to?(:supports_value_expectations?) || matcher.supports_value_expectations?
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
             | 
| 93 131 | 
             
                # @private
         | 
| 94 132 | 
             
                # Validates the provided matcher to ensure it supports block
         | 
| 95 133 | 
             
                # expectations, in order to avoid user confusion when they
         | 
| @@ -118,9 +156,7 @@ module RSpec | |
| 118 156 | 
             
                  end
         | 
| 119 157 |  | 
| 120 158 | 
             
                  def supports_block_expectations?(matcher)
         | 
| 121 | 
            -
                    matcher.supports_block_expectations?
         | 
| 122 | 
            -
                  rescue NoMethodError
         | 
| 123 | 
            -
                    false
         | 
| 159 | 
            +
                    matcher.respond_to?(:supports_block_expectations?) && matcher.supports_block_expectations?
         | 
| 124 160 | 
             
                  end
         | 
| 125 161 | 
             
                end
         | 
| 126 162 | 
             
              end
         | 
| @@ -52,10 +52,10 @@ module RSpec | |
| 52 52 |  | 
| 53 53 | 
             
                private
         | 
| 54 54 |  | 
| 55 | 
            -
                  if RSpec::Support::Ruby.jruby?
         | 
| 56 | 
            -
                    # On JRuby, `caller` and `raise` produce different backtraces with | 
| 57 | 
            -
                    # stack frames. It's important that we use `raise` for JRuby to produce | 
| 58 | 
            -
                    # that has a continuous common section with the raised `MultipleExpectationsNotMetError`,
         | 
| 55 | 
            +
                  if RSpec::Support::Ruby.jruby? && RSpec::Support::Ruby.jruby_version < '9.2.0.0'
         | 
| 56 | 
            +
                    # On JRuby 9.1.x.x and before, `caller` and `raise` produce different backtraces with
         | 
| 57 | 
            +
                    # regards to `.java` stack frames. It's important that we use `raise` for JRuby to produce
         | 
| 58 | 
            +
                    # a backtrace that has a continuous common section with the raised `MultipleExpectationsNotMetError`,
         | 
| 59 59 | 
             
                    # so that rspec-core's truncation logic can work properly on it to list the backtrace
         | 
| 60 60 | 
             
                    # relative to the `aggregate_failures` block.
         | 
| 61 61 | 
             
                    def assign_backtrace(failure)
         | 
| @@ -80,7 +80,7 @@ module RSpec | |
| 80 80 | 
             
                    all_errors = failures + other_errors
         | 
| 81 81 |  | 
| 82 82 | 
             
                    case all_errors.size
         | 
| 83 | 
            -
                    when 0 then return  | 
| 83 | 
            +
                    when 0 then return true
         | 
| 84 84 | 
             
                    when 1 then RSpec::Support.notify_failure all_errors.first
         | 
| 85 85 | 
             
                    else RSpec::Support.notify_failure MultipleExpectationsNotMetError.new(self)
         | 
| 86 86 | 
             
                    end
         | 
| @@ -150,11 +150,29 @@ module RSpec | |
| 150 150 | 
             
                  def enumerated(exceptions, index_offset)
         | 
| 151 151 | 
             
                    exceptions.each_with_index.map do |exception, index|
         | 
| 152 152 | 
             
                      index += index_offset
         | 
| 153 | 
            -
                      formatted_message = yield exception
         | 
| 153 | 
            +
                      formatted_message = "#{yield exception}\n#{format_backtrace(exception.backtrace).first}"
         | 
| 154 154 | 
             
                      "#{index_label index}#{indented formatted_message, index}"
         | 
| 155 155 | 
             
                    end
         | 
| 156 156 | 
             
                  end
         | 
| 157 157 |  | 
| 158 | 
            +
                  def exclusion_patterns
         | 
| 159 | 
            +
                    patterns = %w[/lib\d*/ruby/ bin/ exe/rspec /lib/bundler/ /exe/bundle:]
         | 
| 160 | 
            +
                    patterns << "org/jruby/" if RSpec::Support::Ruby.jruby?
         | 
| 161 | 
            +
                    patterns.map! { |s| Regexp.new(s.gsub('/', File::SEPARATOR)) }
         | 
| 162 | 
            +
                  end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  def format_backtrace(backtrace)
         | 
| 165 | 
            +
                    backtrace.map { |l| backtrace_line(l) }.compact.tap { |filtered| filtered.concat backtrace if filtered.empty? }
         | 
| 166 | 
            +
                  end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                  def backtrace_line(line)
         | 
| 169 | 
            +
                    return if [Regexp.union(RSpec::CallerFilter::IGNORE_REGEX, *exclusion_patterns)].any? { |p| line =~ p }
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                    # It changes the current path that is relative to
         | 
| 172 | 
            +
                    # system root to be relative to the project root.
         | 
| 173 | 
            +
                    line.sub(/(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/, '\\1.\\2'.freeze).sub(/\A([^:]+:\d+)$/, '\\1'.freeze)
         | 
| 174 | 
            +
                  end
         | 
| 175 | 
            +
             | 
| 158 176 | 
             
                  def enumerated_failures
         | 
| 159 177 | 
             
                    enumerated(failures, 0, &:message)
         | 
| 160 178 | 
             
                  end
         | 
| @@ -44,10 +44,16 @@ module RSpec | |
| 44 44 |  | 
| 45 45 | 
             
                # @private
         | 
| 46 46 | 
             
                class PositiveExpectationHandler
         | 
| 47 | 
            -
                  def self.handle_matcher(actual, initial_matcher,  | 
| 48 | 
            -
                    ExpectationHelper.with_matcher(self, initial_matcher,  | 
| 47 | 
            +
                  def self.handle_matcher(actual, initial_matcher, custom_message=nil, &block)
         | 
| 48 | 
            +
                    ExpectationHelper.with_matcher(self, initial_matcher, custom_message) do |matcher|
         | 
| 49 49 | 
             
                      return ::RSpec::Matchers::BuiltIn::PositiveOperatorMatcher.new(actual) unless initial_matcher
         | 
| 50 | 
            -
             | 
| 50 | 
            +
             | 
| 51 | 
            +
                      match_result = matcher.matches?(actual, &block)
         | 
| 52 | 
            +
                      if custom_message && match_result.respond_to?(:error_generator)
         | 
| 53 | 
            +
                        match_result.error_generator.opts[:message] = custom_message
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                      match_result || ExpectationHelper.handle_failure(matcher, custom_message, :failure_message)
         | 
| 51 57 | 
             
                    end
         | 
| 52 58 | 
             
                  end
         | 
| 53 59 |  | 
| @@ -66,10 +72,16 @@ module RSpec | |
| 66 72 |  | 
| 67 73 | 
             
                # @private
         | 
| 68 74 | 
             
                class NegativeExpectationHandler
         | 
| 69 | 
            -
                  def self.handle_matcher(actual, initial_matcher,  | 
| 70 | 
            -
                    ExpectationHelper.with_matcher(self, initial_matcher,  | 
| 75 | 
            +
                  def self.handle_matcher(actual, initial_matcher, custom_message=nil, &block)
         | 
| 76 | 
            +
                    ExpectationHelper.with_matcher(self, initial_matcher, custom_message) do |matcher|
         | 
| 71 77 | 
             
                      return ::RSpec::Matchers::BuiltIn::NegativeOperatorMatcher.new(actual) unless initial_matcher
         | 
| 72 | 
            -
             | 
| 78 | 
            +
             | 
| 79 | 
            +
                      negated_match_result = does_not_match?(matcher, actual, &block)
         | 
| 80 | 
            +
                      if custom_message && negated_match_result.respond_to?(:error_generator)
         | 
| 81 | 
            +
                        negated_match_result.error_generator.opts[:message] = custom_message
         | 
| 82 | 
            +
                      end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                      negated_match_result || ExpectationHelper.handle_failure(matcher, custom_message, :failure_message_when_negated)
         | 
| 73 85 | 
             
                    end
         | 
| 74 86 | 
             
                  end
         | 
| 75 87 |  | 
| @@ -186,116 +186,6 @@ module RSpec | |
| 186 186 | 
             
                      @actual.__send__ @operator, @expected
         | 
| 187 187 | 
             
                    end
         | 
| 188 188 | 
             
                  end
         | 
| 189 | 
            -
             | 
| 190 | 
            -
                  # @api private
         | 
| 191 | 
            -
                  # Provides the implementation of `be_<predicate>`.
         | 
| 192 | 
            -
                  # Not intended to be instantiated directly.
         | 
| 193 | 
            -
                  class BePredicate < BaseMatcher
         | 
| 194 | 
            -
                    include BeHelpers
         | 
| 195 | 
            -
             | 
| 196 | 
            -
                    def initialize(*args, &block)
         | 
| 197 | 
            -
                      @expected = parse_expected(args.shift)
         | 
| 198 | 
            -
                      @args = args
         | 
| 199 | 
            -
                      @block = block
         | 
| 200 | 
            -
                    end
         | 
| 201 | 
            -
                    ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
         | 
| 202 | 
            -
             | 
| 203 | 
            -
                    def matches?(actual, &block)
         | 
| 204 | 
            -
                      @actual  = actual
         | 
| 205 | 
            -
                      @block ||= block
         | 
| 206 | 
            -
                      predicate_accessible? && predicate_matches?
         | 
| 207 | 
            -
                    end
         | 
| 208 | 
            -
             | 
| 209 | 
            -
                    def does_not_match?(actual, &block)
         | 
| 210 | 
            -
                      @actual  = actual
         | 
| 211 | 
            -
                      @block ||= block
         | 
| 212 | 
            -
                      predicate_accessible? && !predicate_matches?
         | 
| 213 | 
            -
                    end
         | 
| 214 | 
            -
             | 
| 215 | 
            -
                    # @api private
         | 
| 216 | 
            -
                    # @return [String]
         | 
| 217 | 
            -
                    def failure_message
         | 
| 218 | 
            -
                      failure_message_expecting(true)
         | 
| 219 | 
            -
                    end
         | 
| 220 | 
            -
             | 
| 221 | 
            -
                    # @api private
         | 
| 222 | 
            -
                    # @return [String]
         | 
| 223 | 
            -
                    def failure_message_when_negated
         | 
| 224 | 
            -
                      failure_message_expecting(false)
         | 
| 225 | 
            -
                    end
         | 
| 226 | 
            -
             | 
| 227 | 
            -
                    # @api private
         | 
| 228 | 
            -
                    # @return [String]
         | 
| 229 | 
            -
                    def description
         | 
| 230 | 
            -
                      "#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
         | 
| 231 | 
            -
                    end
         | 
| 232 | 
            -
             | 
| 233 | 
            -
                  private
         | 
| 234 | 
            -
             | 
| 235 | 
            -
                    def predicate_accessible?
         | 
| 236 | 
            -
                      actual.respond_to?(predicate) || actual.respond_to?(present_tense_predicate)
         | 
| 237 | 
            -
                    end
         | 
| 238 | 
            -
             | 
| 239 | 
            -
                    # support 1.8.7, evaluate once at load time for performance
         | 
| 240 | 
            -
                    if String === methods.first
         | 
| 241 | 
            -
                      # :nocov:
         | 
| 242 | 
            -
                      def private_predicate?
         | 
| 243 | 
            -
                        @actual.private_methods.include? predicate.to_s
         | 
| 244 | 
            -
                      end
         | 
| 245 | 
            -
                      # :nocov:
         | 
| 246 | 
            -
                    else
         | 
| 247 | 
            -
                      def private_predicate?
         | 
| 248 | 
            -
                        @actual.private_methods.include? predicate
         | 
| 249 | 
            -
                      end
         | 
| 250 | 
            -
                    end
         | 
| 251 | 
            -
             | 
| 252 | 
            -
                    def predicate_matches?
         | 
| 253 | 
            -
                      method_name = actual.respond_to?(predicate) ? predicate : present_tense_predicate
         | 
| 254 | 
            -
                      @predicate_matches = actual.__send__(method_name, *@args, &@block)
         | 
| 255 | 
            -
                    end
         | 
| 256 | 
            -
             | 
| 257 | 
            -
                    def predicate
         | 
| 258 | 
            -
                      :"#{@expected}?"
         | 
| 259 | 
            -
                    end
         | 
| 260 | 
            -
             | 
| 261 | 
            -
                    def present_tense_predicate
         | 
| 262 | 
            -
                      :"#{@expected}s?"
         | 
| 263 | 
            -
                    end
         | 
| 264 | 
            -
             | 
| 265 | 
            -
                    def parse_expected(expected)
         | 
| 266 | 
            -
                      @prefix, expected = prefix_and_expected(expected)
         | 
| 267 | 
            -
                      expected
         | 
| 268 | 
            -
                    end
         | 
| 269 | 
            -
             | 
| 270 | 
            -
                    def prefix_and_expected(symbol)
         | 
| 271 | 
            -
                      Matchers::BE_PREDICATE_REGEX.match(symbol.to_s).captures.compact
         | 
| 272 | 
            -
                    end
         | 
| 273 | 
            -
             | 
| 274 | 
            -
                    def prefix_to_sentence
         | 
| 275 | 
            -
                      EnglishPhrasing.split_words(@prefix)
         | 
| 276 | 
            -
                    end
         | 
| 277 | 
            -
             | 
| 278 | 
            -
                    def failure_message_expecting(value)
         | 
| 279 | 
            -
                      validity_message ||
         | 
| 280 | 
            -
                        "expected `#{actual_formatted}.#{predicate}#{args_to_s}` to return #{value}, got #{description_of @predicate_matches}"
         | 
| 281 | 
            -
                    end
         | 
| 282 | 
            -
             | 
| 283 | 
            -
                    def validity_message
         | 
| 284 | 
            -
                      return nil if predicate_accessible?
         | 
| 285 | 
            -
             | 
| 286 | 
            -
                      msg = "expected #{actual_formatted} to respond to `#{predicate}`".dup
         | 
| 287 | 
            -
             | 
| 288 | 
            -
                      if private_predicate?
         | 
| 289 | 
            -
                        msg << " but `#{predicate}` is a private method"
         | 
| 290 | 
            -
                      elsif predicate == :true?
         | 
| 291 | 
            -
                        msg << " or perhaps you meant `be true` or `be_truthy`"
         | 
| 292 | 
            -
                      elsif predicate == :false?
         | 
| 293 | 
            -
                        msg << " or perhaps you meant `be false` or `be_falsey`"
         | 
| 294 | 
            -
                      end
         | 
| 295 | 
            -
             | 
| 296 | 
            -
                      msg
         | 
| 297 | 
            -
                    end
         | 
| 298 | 
            -
                  end
         | 
| 299 189 | 
             
                end
         | 
| 300 190 | 
             
              end
         | 
| 301 191 | 
             
            end
         | 
| @@ -77,6 +77,11 @@ module RSpec | |
| 77 77 | 
             
                      true
         | 
| 78 78 | 
             
                    end
         | 
| 79 79 |  | 
| 80 | 
            +
                    # @private
         | 
| 81 | 
            +
                    def supports_value_expectations?
         | 
| 82 | 
            +
                      false
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
             | 
| 80 85 | 
             
                  private
         | 
| 81 86 |  | 
| 82 87 | 
             
                    def initialize(receiver=nil, message=nil, &block)
         | 
| @@ -158,6 +163,11 @@ module RSpec | |
| 158 163 | 
             
                      true
         | 
| 159 164 | 
             
                    end
         | 
| 160 165 |  | 
| 166 | 
            +
                    # @private
         | 
| 167 | 
            +
                    def supports_value_expectations?
         | 
| 168 | 
            +
                      false
         | 
| 169 | 
            +
                    end
         | 
| 170 | 
            +
             | 
| 161 171 | 
             
                  private
         | 
| 162 172 |  | 
| 163 173 | 
             
                    def failure_reason
         | 
| @@ -201,6 +211,11 @@ module RSpec | |
| 201 211 | 
             
                      true
         | 
| 202 212 | 
             
                    end
         | 
| 203 213 |  | 
| 214 | 
            +
                    # @private
         | 
| 215 | 
            +
                    def supports_value_expectations?
         | 
| 216 | 
            +
                      false
         | 
| 217 | 
            +
                    end
         | 
| 218 | 
            +
             | 
| 204 219 | 
             
                  private
         | 
| 205 220 |  | 
| 206 221 | 
             
                    def perform_change(event_proc)
         | 
| @@ -337,6 +352,8 @@ module RSpec | |
| 337 352 | 
             
                  class ChangeDetails
         | 
| 338 353 | 
             
                    attr_reader :actual_after
         | 
| 339 354 |  | 
| 355 | 
            +
                    UNDEFINED = Module.new.freeze
         | 
| 356 | 
            +
             | 
| 340 357 | 
             
                    def initialize(matcher_name, receiver=nil, message=nil, &block)
         | 
| 341 358 | 
             
                      if receiver && !message
         | 
| 342 359 | 
             
                        raise(
         | 
| @@ -351,6 +368,11 @@ module RSpec | |
| 351 368 | 
             
                      @receiver = receiver
         | 
| 352 369 | 
             
                      @message = message
         | 
| 353 370 | 
             
                      @value_proc = block
         | 
| 371 | 
            +
                      # TODO: temporary measure to mute warning of access to an initialized
         | 
| 372 | 
            +
                      # instance variable when a deprecated implicit block expectation
         | 
| 373 | 
            +
                      # syntax is used. This may be removed once `fail` is used, and the
         | 
| 374 | 
            +
                      # matcher never issues this warning.
         | 
| 375 | 
            +
                      @actual_after = UNDEFINED
         | 
| 354 376 | 
             
                    end
         | 
| 355 377 |  | 
| 356 378 | 
             
                    def value_representation
         | 
| @@ -26,11 +26,19 @@ module RSpec | |
| 26 26 | 
             
                      "#{matcher_1.description} #{conjunction} #{matcher_2.description}"
         | 
| 27 27 | 
             
                    end
         | 
| 28 28 |  | 
| 29 | 
            +
                    # @api private
         | 
| 29 30 | 
             
                    def supports_block_expectations?
         | 
| 30 31 | 
             
                      matcher_supports_block_expectations?(matcher_1) &&
         | 
| 31 32 | 
             
                      matcher_supports_block_expectations?(matcher_2)
         | 
| 32 33 | 
             
                    end
         | 
| 33 34 |  | 
| 35 | 
            +
                    # @api private
         | 
| 36 | 
            +
                    def supports_value_expectations?
         | 
| 37 | 
            +
                      matcher_supports_value_expectations?(matcher_1) &&
         | 
| 38 | 
            +
                      matcher_supports_value_expectations?(matcher_2)
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    # @api private
         | 
| 34 42 | 
             
                    def expects_call_stack_jump?
         | 
| 35 43 | 
             
                      NestedEvaluator.matcher_expects_call_stack_jump?(matcher_1) ||
         | 
| 36 44 | 
             
                      NestedEvaluator.matcher_expects_call_stack_jump?(matcher_2)
         | 
| @@ -102,6 +110,12 @@ module RSpec | |
| 102 110 | 
             
                      false
         | 
| 103 111 | 
             
                    end
         | 
| 104 112 |  | 
| 113 | 
            +
                    def matcher_supports_value_expectations?(matcher)
         | 
| 114 | 
            +
                      matcher.supports_value_expectations?
         | 
| 115 | 
            +
                    rescue NoMethodError
         | 
| 116 | 
            +
                      true
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
             | 
| 105 119 | 
             
                    def matcher_is_diffable?(matcher)
         | 
| 106 120 | 
             
                      matcher.diffable?
         | 
| 107 121 | 
             
                    rescue NoMethodError
         |