Closed TheNeikos closed 8 years ago
Is there a way to get someone who might know what the issue is to look at this? This is pretty much stopping me from correctly writing tests for my views. (Since I can still debug them using the Browser, as that works just fine.)
In a moment of 'I cannot break it further than not working' I tried including Pundit in the ApplicationHelper, and it worked, so I guess that is one way that is more elegant.
Still don't think that is the correct way though.
I would just stub the view
For example
before do
allow(view).to receive(:policy).and_return(double("some policy", new?: true))
end
Here is the relevant doc, that might help you.
It seems like view specs do not inherit helper methods from the controller (which makes sense if you think about it), so this is really somewhat expected and @deepredsky's workaround is the right one.
In addition to @deepredsky's solution, you could instantiate the policy:
allow(view).to receive(:policy) do |record|
Pundit.policy(user, record)
end
Can someone help me figure out how to apply the solutions presented by @deepredsky and @koenpunt in specs for a view helper method that uses policy
?
So far all of my attempts ended in X does not implement: policy
, where X is whatever I'm trying to stub for, like view
for example.
Edit:
Solved with without_partial_double_verification
Combining the content above from @sLe1tner and @koenpunt , here is a full solution for the future sufferers which come across this page.
spec/rails_helper.rb
config.include PunditSpecHelper, type: :view
spec/support/pundit_spec_helper.rb
module PunditSpecHelper
def enable_pundit(view, user)
without_partial_double_verification do
allow(view).to receive(:policy) do |record|
Pundit.policy(user, record)
end
end
end
end
Example usage in a view:
require 'rails_helper'
RSpec.describe 'countries/index', type: :view do
before(:each) do
assign(:countries, [create(:uk), create(:germany)])
end
let(:user) { create(:admin) }
it 'renders a list of countries' do
enable_pundit(view, user)
render
expect(rendered).to match('my content')
# more expectations here...
end
end
Up until now - we were simply including Pundit at the top of our view specs like this...
require 'spec_helper'
include Pundit
describe "users/show.html.haml", type: :view do
...
end
But then started getting some very bizarre random failures and tracked it down to a certain file load order.
rspec spec/features/feature_spec_1.rb spec/features/featur_spec_2.rb spec/views/users/show.html.haml_spec
The feature spec would fail miserably with an invalid current_user
even though the feature spec passes perfectly everywhere else.
NameError at /users186579971 =============================== undefined local variable or method `current_user' for #<#:0x0000558fa8a57570> Did you mean? current_page? > To access an interactive console with this error, point your browser to:
So our solution was to include a the Pundit policy method in our view specs via module like this...
def policy(user, record)
policy = PolicyFinder.new(record).policy
policy&.new(user, pundit_model(record))
rescue ArgumentError
raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called"
end
Then in spec_helper.rb
config.include PunditSpecHelper, type: :view
I hope this may save someone else some time. Thanks all for your contributions to this great gem.
I have included Pundit in my ApplicationController, however, by adding a
byebug
just belowinclude Pundit
I am certain that it does never get actually loaded when testing views in RSpec.Which means that right now, including the pundit rspec helper is not useful and has to be worked around using instance variables that are then injected, hardly ideal and hopefully just temporary.
I have also included
pundit/rspec
in myspec/spec_helper.rb
at the top. My gemfile:The code The test output