rspec_api_documentation icon indicating copy to clipboard operation
rspec_api_documentation copied to clipboard

Conflicts with built-in RSpec matchers

Open reidab opened this issue 8 years ago • 5 comments

Over time, I've run into several situations where I'll declare a parameter, not set a value for it, and end up with a 500 error as my app attempts to parse #<RSpec::Matchers::BuiltIn::Cover:0x007fc442e99d38> or another built-in matcher as JSON.

For example:

  resource 'Widgets' do
    parameter :cover, "url of the widget's cover image"

    put "/api/widgets" do
      example_request "Create a widget" do
        expect(status).to eq 201
      end
    end
  end

The params sent to the server in this case look like:

{"cover"=>#<RSpec::Matchers::BuiltIn::Cover:0x007f9c2e83b608}`

Adding let(:cover) { nil } solves the problem, but it might be good to provide a nicer experience around this. Would it make sense to either blacklist the RSpec::Matchers::BuiltIn classes from being used as param values or warn the user when one makes it through to param serialization?

reidab avatar Mar 19 '16 11:03 reidab

I'm currently experiencing the same issue with

parameter :include

Is there some way to disable the automatic method generation?

outsmartin avatar Jul 13 '16 11:07 outsmartin

The problem isn't automatic method generation, it's RAD seeing a method that matches the parameter name and calling it: dsl/endpoint.rb.

I don't have a good solution for this outside of let(:include) { nil } which isn't good. If you find a nice way around this I'll be happy to look at a PR.

oestrich avatar Jul 13 '16 13:07 oestrich

I ran into this today too. This is what I did to fix the problem:

in my acceptance_helper.rb:

module RspecApiDocumentation::DSL
  module Endpoint
    private

    def set_param(hash, param)
      key = param[:name]

      keys = [param[:scope], key].flatten.compact
      method_name = keys.join('_')

      return hash if in_path?(method_name)

      unless respond_to?(method_name)
        method_name = key
        return hash unless respond_to?(method_name)
      end

      # throw away any values that are set to built matchers.
      current_resp = send(method_name)
      return hash if current_resp.class.name.start_with? 'RSpec::Matchers::BuiltIn::'

      hash.deep_merge(build_param_hash(keys, method_name))
    end
  end
end

This revealed that I had some messiness where I was sending something as the param and that I was defining let(:include) {...} and then trying to use the matcher later, which does not work.

soberstadt avatar Nov 29 '16 21:11 soberstadt

I think I'm running into this with a parameter named :subject. Using let(:subject) { nil } doesn't seem to work either, and I'm getting a Segementation fault: 11. Anyone else run into this? Banging my head against the wall...

I actually defined let!(:subject) { nil } and got stack-level too deep. Might just be skipping this parameter...

jwg2s avatar Mar 20 '18 19:03 jwg2s

subject is a build in rspec function, so my guess is something deep in rspec isn't happy with a let for it.

@jwg2s Can you try:

parameter :subject, "Description", method: :custom_subject

let(:custom_subject) { "hello" }

oestrich avatar Mar 20 '18 21:03 oestrich