Passing the Request Test
Explore how to pass request tests by debugging the registrations controller in Rails. Understand parameter permissions, strong parameters, and status code handling to ensure your tests accurately reflect application behavior. This lesson guides you through solving common request test failures and adjusting expectations for realistic outcomes.
We'll cover the following...
Why did the test fail?
Now, we need to find out why the test is failing.
We could look at the test.log file, but it’s of no help in this case. So, we’ll have to check out the registrations controller. To do that, we’’ll use the generator that Devise provides.
$ rails g devise:controllers users -c=registrations
create app/controllers/users/registrations_controller.rb
The generator also gives us some code to add into our config/routes.rb file.
It’s now a lot easier to see what happens with the request.
Let’s uncomment the create action in the registrations controller and add a breakpoint (with pry).
The test should now stop at the breakpoint we’ve just added.
Note: You need to add the code above to the SPA.
--require spec_helper
Type params at the prompt now and hit “Enter”.
> params
This gives us the following output.
=> <ActionController::Parameters {"email"=>"jdoe@email.com", "password"=>"secret1234", "controller"=>"users/registrations", "action"=>"create"} permitted: false>
Notice the part where it says permitted: false. It means that there’s something wrong with the strong parameter permission. Let’s try overriding that rule by writing the following at the prompt:
> params.permit(:email, :password)
It should produce the following output:
=> <ActionController::Parameters {"email"=>"jdoe@email.com", "password"=>"secret1234"} permitted: true>
Now we’re getting somewhere. Let’s also see if the params that we’re sending are enough to create a valid user.
> User.new(params.permit(:email, :password)).valid?
=> true
This means that the params are okay. It’s just that Devise has a different default setting for them. We don’t want to change that setting, because the feature test works just fine. Therefore, there’s nothing wrong with the code.
Because the feature test works, it makes it easy to find how the params are structured. Simply run the feature tests and look at the log/test.log file. Notice that the params are wrapped in a user hash.
$ tail -f log/test.log
Parameters: {"utf8"=>"✓", "user"=>{"email"=>"jdoe@example.com", "name"=>"jdoe", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
Passing the test
Let’s change the test and wrap those params inside a hash that has a user key.
Comment out the create method in registrations_controller.rb again and rerun the request test. Notice that the error has changed.
Failure/Error: expect(response).to have_http_status(200)
expected the response to have status code 200 but it was 302
The problem with testing code that’s already written is that we need to reverse engineer it as we did here. It’s not ideal, but it’s fine for the sake of this example.
So, the controller is actually returning a 302 status code, rather than a 200. That makes a lot of sense because the user is redirected after registration. Let’s change the test by replacing the expected status code from 200 to 302.
If we run the test now, it passes.
--require spec_helper