-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Bug: Running Feature Tests on multiple endpoints using filters #3085
Comments
I did discover this morning that if you add this to your test class, it will resolve this issue for now.
It might make sense to put this in |
I've just run into this myself. I see how you dig a lot of digging - it is quite elusive and cryptic. Unfortunately the solution seems to be too. Using |
I agree that the suggested fix of resetting the filters service will fix this particular use case. I am wondering, however, about my original suggestion for a fix by altering the Codeigniter::handleRequest() method so that if the $possibleRedirect that comes back from the filters is a request, you set the request to the request that came back from the filters instead of relying on the object instance being the same. It seems to me that this would be a more explicit way to make sure the request being used is the one the filters are intending to be used. |
@caswell-wc I'm not completely following. Maybe if you write it up as a PR or just an edit on your branch I would understand better. |
@MGatner I'm not altering the response, I'm altering the request. In the documentation (https://www.codeigniter.com/user_guide/incoming/filters.html?highlight=filters#before-filters) it says that you can return an altered request to replace the current request. If you look at https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/Filters/Filters.php#L178 you'll see that if you return a request from the filter's before method, the request in the Filters object gets replaced with that. Then after running all filters, if it is running the before filters, it returns the request in the Filters object (https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/Filters/Filters.php#L210). But looking at the code where the filters are run (https://github.com/codeigniter4/CodeIgniter4/blob/develop/system/CodeIgniter.php#L382) It doesn't do anything with that unless it is a response or redirect. What I am proposing is that another check be put below line 391 that looks something like
in order to make it more explicit that we are replacing the request that the controllers are going to use with the request that came back from the filters. |
Ah I see. Yes that’s a good point. I also notice we don’t have any before filters that return a Request nor tests for this scenario. I think it might be a hole. Do you have time & capacity to submit a PR? You seem to have a good understanding of these mechanics. |
I will have to get myself setup to be able to develop on the framework but I will try to find some time to do it. Should we open this issue again or create a new one? |
That would be awesome! FYI the “poorman’s method”:
If you’re planning on developing more I recommend getting an actual environment, but that’s the quick-and-dirty way to get a PR done! |
Describe the bug
I have a Feature Test class with multiple tests on the same endpoint. This endpoint uses a filter to handle authentication which then adds the authenticated user to the request so it can be used in the controller. When I run the tests individually, it works. However, if I try to run all of the tests in the test class, it gives me an error when trying to access the authenticated user that has been added to the request.
After doing A LOT of digging, I think I have found the issue. The filters functionality alters the request object by altering
$this->request
in theFilters
object. This works most of the time because that property points to the same object as the request that later gets passed to the controller. However, in the use case that I described above, they do not. This is because inCodeigniter::handleRequest()
when it gets the filters object usingServices::filters()
, it is getting a shared instance ofFilters
which already exists when the second test runs. So it gets back a Filters instance whoserequest
parameter no longer points to the same request as what gets passed to the controller.A simple solution to this would be to alter Codeigniter::handleRequest() so that when it finishes running the filters, after checking to see if $possibleRedirect is a response, you add this:
CodeIgniter 4 version
v4.0.3
Affected module(s)
CodeIgniter\CodeIgniter
CodeIgniter\Filters\Filters
Expected behavior, and steps to reproduce if appropriate
Context
The text was updated successfully, but these errors were encountered: