Skip to content

Unexpected error : unable to convert unpermitted parameters to hash #159

Open

Description

@ngouy

When I run a specific spec without supper diff, spec is passing
When I run it with it, it is failing
The spec is using a custom matcher, that is itself a wrapp of a regular matcher:

RSpec::Matchers.define :be_within_last do |expected|
      match do |actual|
        actual = Time.zone.parse(actual) if actual.is_a?(String)
        actual = Time.zone.at(actual) if actual.is_a?(Integer)

        expect(actual).to be_within(expected).of(Time.current)
      end
    end

I have absolutely no clue on how it's working behind the scene. But here is what i can observe with debug breakpoints

It is failing in
object_inspection/inspection_tree_builders/default_object.rb:46
In this context object is an instance a spec: RSpec::ExampleGroups::SurveysSubmissions::SurveysSubmissions::Post::<etc...> "does something"

41:                 insert_separated_list(object.instance_variables.sort) do |name|
42:                   as_prefix_when_rendering_to_lines do
43:                     add_text "#{name}="
44:                   end
45:
46:                   add_inspection_of object.instance_variable_get(name) # here
47:                 end
48:               end

One of the object instance_variable is @controller (which carries an instance of a controller)
So it runs add_inspection_of(@controller)

Which latter on, recursively, goes to the exact same code where object is the actual @controller
In this context, object is now instance of one of a controller

because one of the object.instance_variable is @_params = ActionController::Parameters <instance>
And it runs add_inspection_of(@_params), which triggers:

@_params.to_hash (that then triggers)
@_params.to_h

actionpack-7.0.4/lib/action_controller/metal/strong_parameters.rb:309 ActionController::Parameters#to_h:

305: def to_h
306:   if permitted?
307:     convert_parameters_to_hashes(@parameters, :to_h)
308:   else
309:     binding.pry # breakpoint
310:     raise UnfilteredParameters
311:   end
312: end

Activity

  1. ngouy commented on Nov 1, 2022

    @ngouy
    Author

    If don't use my custom matcher (which is just a wrapper) and use directly the "original" rspec helper, it works

  2. ngouy commented on Nov 1, 2022

    @ngouy
    Author

    found why

    customer matcher has an @matcher_execution_context instance variable, that is "inspected" through the same piece of code with add_inspection_of...
    This context contains the instance of the spec, that contains @controller, that contains @params that is inspected with to_h

    not sure how to solve that

  3. ngouy commented on Nov 1, 2022

    @ngouy
    Author

    and as I understand it, to_h is called from "Ruby" itself because it needs to decompose the *args of

    image

    My args are not even printed when the faulty params are called, to that's my guess of what happens

  4. ngouy commented on Nov 1, 2022

    @ngouy
    Author

    also lets say I override to_h in my action controller params to not raise params and return actual hash, super diff continue and deep_inspect the whole actual @matcher_execution_context which is not pretty to look at

    Takes literally minutes

  5. ngouy commented on Nov 1, 2022

    @ngouy
    Author

    Also for the record: my matcher was not constructed properly and the matching was failing, hence super_diff triggering

    (when the custom matcher runs successfully, the issue is not here)

  6. mcmire commented on Nov 8, 2022

    @mcmire
    Collaborator

    @ngouy You say you're using a custom matcher and that a controller instance ends up being inspected when the matcher fails. Out of curiosity what is the test look like itself?

  7. ngouy commented on Nov 8, 2022

    @ngouy
    Author

    💯 that's exactly that

  8. ngouy commented on Nov 8, 2022

    @ngouy
    Author

    Test is a swagger test and it goes something like

    post "/whatever" do
      response "200", "it does something" do
        run_test! do
          expect(response["created_at"]).to be_within_last(3.seconds) # my custom matcher call
        end
      end
    end
  9. huguesbr commented on Jan 26, 2023

    @huguesbr

    @ngouy @mcmire we're having the same issue when testing using rails controller functional test like

      it "..." do
        get :index
        expect(response).to be_client_error
      end
    
      0) BLRegistry::API::V2::TemplatesController does
         Failure/Error: expect(response).to be_client_error
    
         ActionController::UnfilteredParameters:
           unable to convert unpermitted parameters to hash
    

    We can probably leverage custom diffing object (https://github.com/mcmire/super_diff#diffing-custom-objects) but not sure how complex it is?

    For now the poor man solution is to disable super diff for this controller specs

    # rails_helper.rb
    require "super_diff/rspec-rails" unless defined?(DISABLE_SUPER_DIFF)
    
    # controller_spec.rb
    DISABLE_SUPER_DIFF = true
    require "rails_helper"
    

    Is there any options to disable super diff for a given test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions