Closed cvoege closed 7 years ago
@cvoege is this a new bug since Rails 5 or has this always been the case for you?
@samphippen Hard to tell, since I didn't write this test til I switched to rails 5.
@cvoege could you follow our instructions for building an app which cleanly demonstrates the issue you're having please:
Thanks for the issue. We need a little more detail to be able to reproduce this.
Could you please provide us with a rails app that we can clone that demonstrates the issue. Specifically it'd be great if
1) you could rails new
an application and commit
2) make all the changes necessary to reproduce the issue and commit
then, provide us with a description of how to clone your application and reproduce the issue.
Thanks :)
@samphippen Here you go: https://github.com/cvoege/rspec-params-issue
Also, another issue worth looking at in this same vein.
It seems that in rspec the params object is converted into a query string, and improperly doing so appears to be what causes this bug, but it also causes some other issues like integers and booleans get converted into strings. This works for url-encoded-forms and multipart forms, but if you post JSON as the body of a request you integers and booleans will stay proper integers and booleans.
For example, the following params:
params: {
test1: 5,
test2: false,
test3: 'test'
}
Would convert to:
{
test1: "5",
test2: "false",
test3: "test"
}
As ActionController::Params. This is all well and good for most cases, but again, if we're posting a JSON body it ends up different. So I feel like part of the solution here needs to be to allow a way for us to pass a JSON string as the body of the request.
@cvoege Can you try using as: :json
instead of format: json
? This should ensure the params get encoded as JSON. See http://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html
@cvoege Sorry, that won't work. The IntegrationTest is used for request specs. With type: :request
and post '/questions', as: :json
I can get your specs running (but please note that the post
does not return the response in that case, request specs are different from raw controller specs.
The issue is, in my opinion, not within rspec-rails, but ActionController::TestCase::Behavior
, which does not support JSON payload very well, as it seems.
@tosch Thank you for your input. I'll try that out. If I were to report the ActionController::TestCase bug, would that be in the rails repo itself?
I was looking at this issue as part of Hacktoberfest, https://github.com/rails/rails/commit/3db57bde1ef435a38337f6db298b851c8a4ad10c fixes this. The only thing is that you need to use as
instead of format
and it should work correctly. I don't know exactly what's the difference between these two is supposed to be, but the code fix only addresses as
https://github.com/rails/rails/commit/3db57bde1ef435a38337f6db298b851c8a4ad10c#diff-600d5368b55e46ed961abb4295977ac3R519
I made a fork (https://github.com/orlando/rspec-params-issue) of the reproduction case and:
rails
from master
format
to as
in the Controller testso, in short, if you use as
instead of format
using the rails from master it works correctly
This also closes #710
@samphippen I think we can close this issue, refer to @orlando comment above for more info :)
Wow never thought this could be an issue with Rails 5. Spent a day trying to fix a test and finally found this. For anyone with this issue, try this:
post :create, params: your_post_payload_hash, as: :json
Thank you @emaillenin . Your answer helped me with a similar issue. Actually, Rails seems to have an open issue related to this problem -> https://github.com/rails/rails/issues/23997
What is the workaround for tests that also upload files for their nested attributes? as: :json
doesn't help on that case since it has to be multipart. Any ideas?
You'll need the correct mime type for the json/multipart hybrid, what rails will treat it as. This is all being passed through to the rails test helpers.
So I have a method that takes some nested JSON data as parameters. If I pass this JSON data into my controller as the body of an AJAX request from my application, it parses just fine and I can use the parameters as normal. However, if I use this exact same data as the params: {} of an rspec field, they don't parse right, some data from the third element of the array gets moved into the second element!
I've simplified the data to give you guys an easy to test use case.
Here's a basic spec file to start with, the JSON data in question can be seen in the params of the create test.
And for the controller you can simply print out the params:
And here's how the parameters come out looking when you print them:
And you'll notice they get mangled and for some reason Question 3's details get put into question 2! I tried to work around this by passing the data as a JSON string in the body of a post call, but I can't find any documentation on how to do that in the most recent version, and anything I tried still resulted in this bug. I'd like to again note that I can pass this data exactly into the app without any problems when it's not in a test.