rspec-expectations icon indicating copy to clipboard operation
rspec-expectations copied to clipboard

`end_with` takes the assumption that the receiver is a hash, or string.

Open envygeeks opened this issue 8 years ago • 3 comments

[14] pry(<REMOVED>)> rtn.class # => Pathutil
[15] pry(<REMOVED>)> rtn.end_with?("/hello") # => true
[16] pry(<REMOVED>)> expect(rtn).to end_with("/hello")

RSpec::Expectations::ExpectationNotMetError
# => : expected #<Pathutil:/hello> to end with "/hello", but it cannot 
#   be indexed using #[]

envygeeks avatar Nov 20 '17 14:11 envygeeks

start_with and end_with don't assume the receiver is a hash; they assume the receiver is an object that implements the [] indexing operator so that the matcher can directly access the elements at the start (using [0], [0, 5], etc for start_with) or at the end (using [-1], [-5, 5], etc for end_with). In fact, the start_with and end_with matchers don't work on hashes, as there internal ordering, where it exists (e.g. MRI 1.9+), is not exposed by the [] operator.

Anyhow, if you want it to work with an object of your own, you can implement [] on it, and the matcher should "just work". start_with and end_with have never checked a predicate like start_with? or end_with?. I think it would be reasonable to do so. Do you want to open a PR adding that?

myronmarston avatar Nov 20 '17 16:11 myronmarston

Something like ?

        # @api private
        # @return [String]
        def failure_message
          super.tap do |msg|
            if @actual_does_not_have_ordered_elements
              msg << ", but it does not have ordered elements"
            elsif !actual.respond_to?(:start_with?)
              msg << ", but #{actual.inspect} does not respond to start_with?"
            elsif !actual.respond_to?(:end_with?)
              msg << ", but #{actual.inspect} does not respond to end_with?"
            elsif !actual.respond_to?(:[])
              msg << ", but it cannot be indexed using #[]"
            end
          end
        end

TravisSpangle avatar Dec 11 '17 21:12 TravisSpangle

@TravisSpangle - the fix for this is going to require a change the match logic (so that if the object responds to the appropriate predicate method, it is used), as well as a change to failure_message so that when the predicate approach was used, the failure message mentions it.

(And sorry about the delayed response...)

myronmarston avatar Feb 11 '18 02:02 myronmarston

Closing due to inactivity during the monorepo migration, and I feel the original access modifier reasoning still stands

JonRowe avatar Nov 27 '24 22:11 JonRowe