ruby-on-railsruby-on-rails-5minitestjson-apijsonapi-resources

Rails 5 API integration tests don't work with jsonapi-resources


I can't test POST requests against my jsonapi-resources Rails 5.1 API. Rails does not seem to allow me to customize request content types, or is doing it wrong.

jsonapi-resources version 0.9.0, edge Rails (I think it's 5.2 beta2)

So, this IntegrationTest code:

require 'test_helper'

class EventsControllerTest < ActionDispatch::IntegrationTest
  setup do
    @event = events(:one)
  end

  test 'should get index' do
    get events_url, as: 'application/vnd.api+json'
    assert_response :success
  end

  test 'should create event' do
    assert_difference('Event.count') do
      post events_url, params: {
        data: {
          type: 'events',
          attributes: {
            name: @event.name,
            body: @event.body
          }
        }
      },
      as: :api_json
    end
    assert_response 201
  end

end

...produces this error:

$ bin/rails test
...

Failure:
EventsControllerTest#test_should_create_event [/Users/aljabear/Projects/visualist/test/controllers/events_controller_test.rb:26]:
...

The GET request works fine. The POST request is borked. Printing out the @request.body after the POST request gives this clue:

{
 "errors":[
    {"title":"Bad Request",
     "detail":"765: unexpected token at 'data[type]=events\u0026data[attributes][name]=Book+1\u0026data[attributes][body]=This+is+body+text.'",
     "code":"400",
     "status":"400"
    }
 ]
}

So, clearly the :api_json content type is not being respected by Rails; I guess it's instead spitting out form URL encoded.

if I do this instead, and print the result:

...
as: :json,
headers: {
  'Content-type': 'application/vnd.api+json',
}
...

I get the following, showing that jsonapi-resources is behaving properly (just very strictly); when I use as: :json, Rails correctly formats things as json, just not when I do :api_json.

{
 "errors":[{
    "title":"Not acceptable",
    "detail":"All requests must use the 'application/vnd.api+json' Accept without media type parameters. This request specified 'application/json'.",
    "code":"406",
    "status":"406"
  }]
}

Is Rails just not bothering to convert the MIME type as requested? Or is this just a serialization issue? How can I force it to do it? Thanks... any clues are welcome.


Solution

  • I'm successfully using code like the following:

    test 'should create event' do
      assert_difference('Event.count') do
        post events_url, params: {
          data: {
            type: 'events',
            attributes: {
              name: @event.name,
              body: @event.body
            }
          }
        },
        as: :json,
        headers: {
          'Accept' => JSONAPI::MEDIA_TYPE,
          'Content-Type' => JSONAPI::MEDIA_TYPE
        }
      end
      assert_response :created
    end
    

    I have a project on GitHub that you can look at to see my code.