Closed aximuseng closed 4 years ago
You’ll have to show more code for anyone to answer.
From what you’ve shown so far I don’t think this issue has anything to do with Pundit.
I updated the post with more detail. Pundit work great in the app and I don’t think that Pundit is the problem - just that I may be missing something.
You will only receive the context and record in the initializer.
def initialize(context, record)
@user = context.user
@enrollment = context.enrollment
@record = record
end
To clarify - are you saying I can just add this initializer to my tests?
No. I’m saying your ApplicationPolicy initializer is wrong :)
I ended up with this working (in my app):
def initialize(enrollment, record)
@user = enrollment.user
@enrollment = enrollment
@record = record
end
This is still fails in Minitest. You suggested code failed but I figured out is perhaps should be:
def initialize(context, record)
@user = context.user
@enrollment = context
@record = record
end
This worked in my app but tests still fail:
NoMethodError: undefined method 'user' for nil:NilClass
In my Application controller my enrollment is set via a session variable. I am honestly at a lost where the magic happens and Pundit has the enrollment / context passed to it via the initialization.
To make matters worse I didn't build this - I had a contractor build this years ago. It works great except the tests. I would also be happen to just disable authorization in the tests completely and then I can write specific policy tests to confirm that my auth is good.
You’ll have to show current_enrollment
. It returns nil in your test for some reason. Also, show the test.
It's nil because its based on a session variable session[:enrollment_id]
. I did some more digging and it doesn't look good.
Here is one of my controller tests where I added the session (only to find out you can't do this anymore):
test "should get index" do
get wells_url, session: { enrollment_id: 10 }
assert_response :success
end
After the user authenticates my ApplicationController has a method where if the session[:enrollment_id] is not set it looks up the current_users enrollments and sets the last one and then switches tenants etc. This is then used in the current_enrollment
method.
I can't seem to find anywhere how you can set the session in a controller test - this may be a dead end. Can I just disable pundit completely in these tests?
Try controller.session[...] = ...
If that doesn’t work, call the endpoint that sets that variable in your controller.
However, as I said above, this isn’t related to Pundit really so I’ll close it.
Thanks for your help - I agree it's not Pundit. controller.session[...] =
didn't work. Also tried calling the method that sets that variable and I get NameError: undefined local variable or method 'set_identity'
.
Also tried calling the method that sets that variable and I get NameError: undefined local variable or method 'set_identity'.
I meant actually posting to it in the test.
post login_or_what_it_is_url, params: { ... }
Talk about a rabbit hole - I had a line in my application controller that was intended to skip the setting of the enrollment etc. if the user was not signed in but I had added another redundant conditional that fails in the test but passes in dev/ pro. The tests run fine now. Thanks again.
My app uses additional context:
https://github.com/varvet/pundit#additional-context
Here is my application policy:
In my application controller:
So here is a typical policy:
The enrollment model has various helpers for my authorzation scheme. I tried this in both my test_helper.rb and individual tests:
enrollment = enrollments(:administrator)
Thats a valid fixture but my tests will fail with:
NoMethodError: undefined method 'has_role?' for nil:NilClass.
Clearly the enrollment in the policy is not set. Done lots of searching on this but could not find another similar question etc. Also tried setting pundit_user in my tests - no luck.