Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

raise error when using custom matcher #163

Closed
masato-bkn opened this issue Dec 1, 2022 · 2 comments · Fixed by #202
Closed

raise error when using custom matcher #163

masato-bkn opened this issue Dec 1, 2022 · 2 comments · Fixed by #202
Labels

Comments

@masato-bkn
Copy link

Hi, all. Thank you for developing a great gem. It could greatly improve my testing experience!

When I ran a test using this gem in my rails project, the title problem occurred.

NoMethodError:
undefined method `keys' for nil:NilClass

        keys = hash.keys
                    ^^^^^

full backtrace is here

test

# result          -> Hash class
# expected_result -> Array class
# resource        -> Active Model

it do
  expect(result).to match(
    'hoge' => expected_result.map do |resource|
      {
        'id' => 'foo',
        'url' => be_a_url,
      }
    end
  )
end

custom matcher

RSpec::Matchers.define :be_a_url do
  match do |actual|
    actual =~ URI::DEFAULT_PARSER.make_regexp
  end
end

environment

- Rails 7.0.4
- ruby 3.1.2
- RSpec 3.11
- super_diff 0.9.0
@mcmire
Copy link
Collaborator

mcmire commented Dec 1, 2022

@masato-bkn Thanks for reporting this, seems like a legit bug. I will look into this shortly!

@jk779
Copy link

jk779 commented Feb 4, 2023

I love this gem so much.

This happend to me multiple times now, my workaround was to un-include super_diff in rails_helper, which makes the problem in my application visible (rather from super_diff) and add it again after that, lol.

I'm using this, but I don't really think it matters whats the matchers logic, regarding the OPs matcher does something very different?

RSpec::Matchers.define :include_or_eq do |expected|
  match do |actual|
    if actual.is_a?(Hash)
      return actual[:any].include? expected if actual.key? :any
      return actual[:all].sort == expected.sort if actual.key? :all

      raise 'Neither :all nor :any key defined :('
    else
      actual == expected
    end
  end
end

I've seen this in

  • rails 6.0, 6.1 and 7.0
  • ruby 2.7 and 3.0
  • rspec 3.x (currently 3.12.0)
  • super_diff 0.9.0 at least, but i'm unsure if this already happened in 0.8

Here is a stack trace: https://gist.github.com/jk779/b7b3d321385c59f9a14b023d61b30447

If it helps, I can provide the code the matcher is used in, because maybe the usage of it is the problem, rather the existence of the matcher itself.

it goes along the lines of this (a helper for mocking authorizations, i'm sure it doesn't make much sense without context ;)

ALL_ACTIONS = %i[read create delete update options].freeze

def mock_allow(subjects: [], actions: ALL_ACTIONS, return_user: false, return_value: true)
  if actions.present?
    subjects.each do |subject|
      actions.each do |action|
        allow(SomeClass)
          .to receive(:something)
            .with(
              anything,
              include_or_eq(subject),
              action,
              { return_user: return_user })
            .and_return return_value
      end
    end
  else
    subjects.each do |subject|
      allow(SomeClass).to(receive(:something).with(
        anything,
        include_or_eq(subject),
        anything,
        { return_user: anything })
      ) { SomeClass.raise_error(code: 403) }
    end
  end
end

mcmire pushed a commit that referenced this issue Nov 13, 2023
I believe this fixes #199 and, I suspect, fixes #163. See
#199 (comment)
for more background. You can reproduce errors like those raised in the
aforementioned issues by checking out
26e1f6c and running `bundle exec rspec
spec/unit/active_support/object_inspection_spec.rb`.

The solution I opted for here was to create a hash-like inspector for
`ActiveSupport::OrderedOptions` that takes precedence over the default
`CustomObject` inspector, which in turn [takes precedence
over](https://github.com/mcmire/super_diff/blob/fb6718a2b60bc8135424295cc069a4b984983f77/lib/super_diff/object_inspection/inspection_tree_builders/defaults.rb#L5-L7)
the `Hash` inspector.

The `OrderedOptions` inspection tree is basically a copy-paste of the
one for `HashWithIndifferentAccess` – let me know if I should try to DRY
those up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants