'RSpec request spec post an empty array
I am current developing an API endpoint in rails. I want to be sure the endpoint response with the correct error status if the data I need is invalid. I need an array of ids. One of the invalid values is an empty array.
Valid
{ vendor_district_ids: [2, 4, 5, 6]}
Invalid
{ vendor_district_ids: []}
Request Spec with RSpec
So I want to have a request spec to control my behaviour.
require 'rails_helper'
RSpec.describe Api::PossibleAppointmentCountsController, type: :request do
let(:api_auth_headers) do
{ 'Authorization' => 'Bearer this_is_a_test' }
end
describe 'POST /api/possible_appointments/counts' do
subject(:post_request) do
post api_my_controller_path,
params: { vendor_district_ids: [] },
headers: api_auth_headers
end
before { post_request }
it { expect(response.status).to eq 400 }
end
end
As you can see I use an empty array in my param inside the subject block.
Value inside the controller
In my controller I am fetching the data with
params.require(:vendor_district_ids)
and the value is the following
<ActionController::Parameters {"vendor_district_ids"=>[""], "controller"=>"api/my_controller", "action"=>"create"} permitted: false>
The value of vendor_district_ids is an array with an empty string. I do not have the same value when I make a post with postman.
Value with postman
If I post
{ "vendor_district_ids": [] }
the controller will receive
<ActionController::Parameters {"vendor_district_ids"=>[], "controller"=>"api/my_controller", "action"=>"create"} permitted: false>
And here is the array empty.
Question
Am I doing something wrong inside the request spec or is this a bug from RSpec?
Solution 1:[1]
That is actually caused by rack-test >= 0.7.0 [1].
It converts empty arrays to param[]= which is later decoded as [''].
If you try running the same code with e.g. rack-test 0.6.3 you will see that vendor_district_ids isn't added to the query at all:
# rack-test 0.6.3
Rack::Test::Utils.build_nested_query('a' => [])
# => ""
# rack-test >= 0.7.0
Rack::Test::Utils.build_nested_query('a' => [])
# => "a[]="
Rack::Utils.parse_nested_query('a[]=')
# => {"a"=>[""]}
[1] https://github.com/rack-test/rack-test/commit/ece681de8ffee9d0caff30e9b93f882cc58f14cb
Solution 2:[2]
For everyone wondering — there's a shortcut solution:
post '/posts', params: { ids: [] }, as: :json
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Maciej Majewski |
| Solution 2 | jibiel |
