allanberry
allanberry

Reputation: 7765

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.

Upvotes: 2

Views: 932

Answers (2)

sapientpants
sapientpants

Reputation: 445

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.

Upvotes: 3

Taryn East
Taryn East

Reputation: 27747

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?

tl;dr: Yes, yes and as_json :)

tests are a subset of rails functionality - they don't go through the full rails stack (and thus does no conversions based on MIME type).

Yes, I think so - ie you need to serialize it so that rails can unserialize it.

Try running `as_json` on your data... eg

  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
      },
      as: :api_json
    end
    assert_response 201
  end

or similar on your actual data... ie... if you're telling Rails to expect json... then pass it json? :D

Upvotes: 0

Related Questions