I have been tearing my hair trying to make the test to pass. I have a JSON API that looks like this:
{
\"data\": [
{
\"id\": \"b99f8173-0492-457f
In RSpec you never* need to explicitly format the params.
post :create, params: { foo: 'bar' }, format: :json
This will properly format the hash { foo: 'bar' }
as JSON in the request body.
To create a hash which matches the JSONAPI.org structure you can create a helper:
# support/api_spec_helper.rb
module APISpecHelper
def to_json_api(model)
{
data: {
type: ActiveModel::Naming.plural(model),
attributes: model.attributes
}.tap do |hash|
hash[:id] = model.id if model.persisted?
end
}
end
end
You can also use the JSONAPI-RB gem or ActiveModel::Serializers to constuct/deconstruct JSONAPI responses/params.
require 'rails_helper'
require 'api_spec_helper'
RSpec.request "Manufacturer organizations" do
include APISpecHelper
describe "POST '/manufacturer_organizations'" do
let(:valid_params) do
to_json_api(FactoryGirl.build(:manufacturer_organization))
end
let(:invalid_params) do
to_json_api(ManufacturerOrganization.new(
foo: 'bad_value'
))
end
describe "with valid attributes" do
it "creates a manufacturer organization" do
expect do
post '/manufacturer_organizations', params: valid_params, format: :json
end.to change(ManufacturerOrganization, :count).by(+1)
end
it "has the correct response" do
post '/manufacturer_organizations', params: valid_params, format: :json
expect(response).to have_status :created
expect(response.headers[:location]).to eq(
manufacturer_organization_path(ManufacturerOrganization.last)
)
end
end
describe "with valid attributes" do
it "does not create a manufacturer organization" do
expect do
post '/manufacturer_organizations', params: invalid_params, format: :json
end.to_not change(ManufacturerOrganization, :count)
end
it "has the correct response" do
post '/manufacturer_organizations', params: invalid_params, format: :json
expect(response).to have_status :unproccessable_entity
end
end
end
end
Returning the correct response codes is pretty simple:
def create
@resource = Resource.create(some_params)
if @resource.save
# you can respond by pointing at the newly created resource but with no body
head :created, location: @resource
# or
render json: @resource,
status: :created,
location: @resource
else
render json: { errors: @resource.errors.full_messages },
status: :unprocessable_entity
end
end
If a POST request did not include a Client-Generated ID and the requested resource has been created successfully, the server MUST return a 201 Created status code.
http://jsonapi.org/format/#crudOther Responses
A server MAY respond with other HTTP status codes.
A server MAY include error details with error responses.
The commonly accepted practice is to use 422 - Unprocessable Entity for validation errors.
One small concern is that you should use a serializer to give the correct JSON response and also serialize the correct error objects.