mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-10-29 18:28:28 -04:00
182 lines
6.3 KiB
Ruby
182 lines
6.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
RSpec.describe 'API errors' do
|
|
include_context 'with an API member'
|
|
|
|
let(:garden_params) { { data: { type: 'gardens', attributes: { name: 'A new garden' } } }.to_json }
|
|
|
|
describe 'a record that does not exist' do
|
|
before { get '/api/v1/plantings/0', headers: read_headers }
|
|
|
|
it { expect(response).to have_http_status(:not_found) }
|
|
|
|
it 'responds as JSON:API' do
|
|
expect(response.media_type).to eq('application/vnd.api+json')
|
|
end
|
|
|
|
it 'reports the status in the error' do
|
|
expect(json['errors'].first['status']).to eq('404')
|
|
end
|
|
end
|
|
|
|
describe 'a filter that does not exist' do
|
|
before { get '/api/v1/plantings?filter[nonsense]=1', headers: read_headers }
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
|
|
it 'names the filter' do
|
|
expect(json['errors'].first['detail']).to include('nonsense')
|
|
end
|
|
end
|
|
|
|
describe 'a filter on a computed attribute' do
|
|
before { get '/api/v1/plantings?filter[crop-name]=beans', headers: read_headers }
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
end
|
|
|
|
describe 'a query that is not shaped like JSON:API' do
|
|
%w(
|
|
page[limit][x]=5 page[limit][]=5 page[offset][x]=1 page[size][x]=5 page[number][x]=1
|
|
page[limit]=abc page[limit]=-3 page[limit]=0 page[offset]=abc page[offset]=-1 page[size]=0 page[number]=0 page[number]=abc
|
|
page=5 sort[x]=1 sort[]=name include[]=plantings filter=5 filter[]=1 fields=x stats=1 extra_fields=x
|
|
filter[id]=abc
|
|
).each do |query|
|
|
context "with #{query}" do
|
|
before { get "/api/v1/crops?#{query}", headers: read_headers }
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'a page size over the maximum' do
|
|
before { get '/api/v1/plantings?page[limit]=101', headers: read_headers }
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
end
|
|
|
|
describe 'a resource that fails validation' do
|
|
before do
|
|
token
|
|
post '/api/v1/gardens',
|
|
params: { data: { type: 'gardens', attributes: { name: '' } } }.to_json,
|
|
headers: auth_headers
|
|
end
|
|
|
|
it { expect(response).to have_http_status(:unprocessable_entity) }
|
|
|
|
it 'points at the invalid attribute' do
|
|
expect(json['errors'].first['source']['pointer']).to eq('/data/attributes/name')
|
|
end
|
|
|
|
it 'does not create the garden' do
|
|
expect(Garden.where(name: '')).to be_empty
|
|
end
|
|
end
|
|
|
|
describe 'a write that sets an attribute that does not exist' do
|
|
before do
|
|
token
|
|
post '/api/v1/gardens', params: { data: { type: 'gardens', attributes: { name: 'A new garden', nonsense: 1 } } }.to_json,
|
|
headers: auth_headers
|
|
end
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
|
|
it 'does not create the garden' do
|
|
expect(Garden.where(name: 'A new garden')).to be_empty
|
|
end
|
|
end
|
|
|
|
describe 'a write that sets an attribute that cannot be written' do
|
|
before do
|
|
token
|
|
post '/api/v1/gardens', params: { data: { type: 'gardens', attributes: { name: 'A new garden', slug: 'mine' } } }.to_json,
|
|
headers: auth_headers
|
|
end
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
end
|
|
|
|
describe 'a write with a body that is not shaped like JSON:API' do
|
|
{
|
|
'data that is not an object' => { data: 'x' },
|
|
'attributes that are not an object' => { data: { type: 'gardens', attributes: 'x' } },
|
|
'relationships that are not an object' => { data: { type: 'gardens', relationships: 'x' } },
|
|
'a relationship that is not an object' => { data: { type: 'gardens', relationships: { owner: '1' } } },
|
|
'a link that is not an object' => { data: { type: 'gardens', relationships: { owner: { data: '1' } } } },
|
|
'a list of links for a to-one' => { data: { type: 'gardens',
|
|
relationships: { owner: { data: [{ type: 'members', id: '1' }] } } } },
|
|
'a link with attributes' => { data: { type: 'gardens',
|
|
relationships: { owner: { data: { type: 'members', id: '1',
|
|
attributes: { x: 1 } } } } } },
|
|
'no data' => {}
|
|
}.each do |label, body|
|
|
context "with #{label}" do
|
|
before do
|
|
token
|
|
post '/api/v1/gardens', params: body.to_json, headers: auth_headers
|
|
end
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'a resource of the wrong type' do
|
|
before do
|
|
post '/api/v1/gardens',
|
|
params: { data: { type: 'plantings', attributes: { name: 'A new garden' } } }.to_json,
|
|
headers: auth_headers
|
|
end
|
|
|
|
it { expect(response).to have_http_status(:bad_request) }
|
|
|
|
it 'does not create the garden' do
|
|
expect(Garden.where(name: 'A new garden')).to be_empty
|
|
end
|
|
end
|
|
|
|
describe 'writing without a token' do
|
|
before { post '/api/v1/gardens', params: garden_params, headers: write_headers }
|
|
|
|
it { expect(response).to have_http_status(:unauthorized) }
|
|
|
|
it 'does not create the garden' do
|
|
expect(Garden.where(name: 'A new garden')).to be_empty
|
|
end
|
|
end
|
|
|
|
describe 'writing with a token that does not exist' do
|
|
before { post '/api/v1/gardens', params: garden_params, headers: write_headers.merge('Authorization' => 'Bearer nope') }
|
|
|
|
it { expect(response).to have_http_status(:unauthorized) }
|
|
end
|
|
|
|
describe 'writing with a token from another provider' do
|
|
before do
|
|
create(:authentication, member: member, provider: 'flickr', token: 'flickr-token')
|
|
post '/api/v1/gardens', params: garden_params, headers: write_headers.merge('Authorization' => 'Bearer flickr-token')
|
|
end
|
|
|
|
it { expect(response).to have_http_status(:unauthorized) }
|
|
end
|
|
|
|
describe 'reading with a token that does not exist' do
|
|
before { get '/api/v1/crops', headers: read_headers.merge('Authorization' => 'Bearer nope') }
|
|
|
|
it 'is still allowed, because reads are public' do
|
|
expect(response).to have_http_status(:ok)
|
|
end
|
|
end
|
|
|
|
describe 'reading without a token' do
|
|
before { get '/api/v1/gardens', headers: read_headers }
|
|
|
|
it { expect(response).to have_http_status(:ok) }
|
|
end
|
|
end
|