Private Method Conflict Between Helpers Causes Incorrect Method Call
Closed this issue · 6 comments
What Ruby, Rails and RSpec versions are you using?
Ruby version: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux-gnu]
Rails version: 7.1.3.4
RSpec version: 3.13
- rspec-core 3.13.0
- rspec-expectations 3.13.1
- rspec-mocks 3.13.1
- rspec-rails 6.1.3
- rspec-support 3.13.1
Observed behaviour
If two helpers share the name of a private method, the tests will call the last one in alphabetical order.
Expected behaviour
Each Helper should maintain its own methods.
Can you provide an example reproduction?
- Create a Helper:
# frozen_string_literal: true
module HelperOneHelper
def super_def
private_def
end
private
def private_def
"HelperOne"
end
end
- Create anotherone sharing the name of the private method
# frozen_string_literal: true
module HelperTwoHelper
def super_def_two
private_def
end
private
def private_def
"HelperTwo"
end
end
- Create the test for the first Helper
# spec/helpers/helper_one_helper_spec.rb
require 'rails_helper'
RSpec.describe HelperOneHelper, type: :helper do
describe '#super_def' do
it 'calls the private method and returns the expected string' do
expect(helper.super_def).to eq("HelperOne")
end
end
end
Example
clone https://github.com/OsvaldoGDelRio/helper-failure
run rspec
As far as I can see here is the origin of this:
/var/lib/gems/3.1.0/gems/rspec-rails-6.1.3/lib/rspec/rails/example/helper_example_group.rb
def helper
_view.tap do |v|
v.extend(ApplicationHelper) if defined?(ApplicationHelper)
v.assign(view_assigns)
end
end
How would it work in the controller if you include both?
How would it work in the controller if you include both?
The same way, it uses the method from the last Helper, in this case Helper two. I guess Rspec is just following the same behavior. Surprisingly, I guess we should give different names for the private methods or encapsulate them into another module.
👋 Method conflicts like this will cause this behaviour, its not something specific to RSpec except that we include both the helper module under test and ApplicationHelper
, this is by design.
The only case I can think of is when you include helper A in controller X, and helper B in controller Y.
If A & B’s overlap, this will work in controllers, but not in specs.
Or am I talking nonsense?
Is this something worth fixing?
If they work in controllers they will work in specs, all we do is essentially:
class ThisTestsHelper
include ApplicationHelper
include ModuleUnderTest
end
So these must be in ApplicationHelper
and must overlap.