jsonapi.rb 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -0
- data/lib/jsonapi/active_model_error_serializer.rb +0 -3
- data/lib/jsonapi/error_serializer.rb +6 -1
- data/lib/jsonapi/pagination.rb +25 -5
- data/lib/jsonapi/rails.rb +12 -2
- data/lib/jsonapi/version.rb +1 -1
- data/spec/deserialization_spec.rb +87 -0
- data/spec/dummy.rb +163 -0
- data/spec/errors_spec.rb +168 -0
- data/spec/fetching_spec.rb +65 -0
- data/spec/filtering_spec.rb +101 -0
- data/spec/pagination_spec.rb +246 -0
- data/spec/spec_helper.rb +87 -0
- metadata +14 -17
- data/.github/ISSUE_TEMPLATE.md +0 -16
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- data/.github/workflows/ci.yml +0 -36
- data/.gitignore +0 -3
- data/.rspec +0 -3
- data/.rubocop.yml +0 -36
- data/.yardstick.yml +0 -29
- data/Gemfile +0 -4
- data/Rakefile +0 -34
- data/jsonapi.rb.gemspec +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07512bb6e4135e51e0f94a3399ec068e7aa53a13d6eb65b44f5c87be8e4310e4
|
4
|
+
data.tar.gz: 128306af20f37d9fb7563a9cbc30f88f68dc3f761783a02eb9db539886c67bc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6658f11bc2501360cb8be91a05d14d427102905476cd1e0d2a020b1d9db36ce77857127090dc37f27dfb9292c187f3ad8028ea47ab8b26f06ffe7648276009fe
|
7
|
+
data.tar.gz: 2cfb89517aba924c3282d3f8f65a1281606407c0e11b97159ebab7b58c75dbf02fbf65962793a031b07e87e9e2cd90a31b87f6e5d0d54a91c769c0eed82e7088
|
data/README.md
CHANGED
@@ -290,6 +290,7 @@ class MyController < ActionController::Base
|
|
290
290
|
render jsonapi: paginated
|
291
291
|
end
|
292
292
|
end
|
293
|
+
|
293
294
|
end
|
294
295
|
```
|
295
296
|
|
@@ -306,6 +307,17 @@ use the `jsonapi_pagination_meta` method:
|
|
306
307
|
end
|
307
308
|
|
308
309
|
```
|
310
|
+
|
311
|
+
If you want to change the default number of items per page or define a custom logic to handle page size, use the
|
312
|
+
`jsonapi_page_size` method:
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
def jsonapi_page_size(pagination_params)
|
316
|
+
per_page = pagination_params[:size].to_f.to_i
|
317
|
+
per_page = 30 if per_page > 30
|
318
|
+
per_page
|
319
|
+
end
|
320
|
+
```
|
309
321
|
### Deserialization
|
310
322
|
|
311
323
|
`JSONAPI::Deserialization` provides a helper to transform a `JSONAPI` document
|
@@ -5,7 +5,6 @@ module JSONAPI
|
|
5
5
|
class ErrorSerializer
|
6
6
|
include JSONAPI::Serializer
|
7
7
|
|
8
|
-
set_id :object_id
|
9
8
|
set_type :error
|
10
9
|
|
11
10
|
# Object/Hash attribute helpers.
|
@@ -15,6 +14,12 @@ module JSONAPI
|
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
17
|
+
# Overwrite the ID extraction method, to skip validations
|
18
|
+
#
|
19
|
+
# @return [NilClass]
|
20
|
+
def self.id_from_record(_record, _params)
|
21
|
+
end
|
22
|
+
|
18
23
|
# Remap the root key to `errors`
|
19
24
|
#
|
20
25
|
# @return [Hash]
|
data/lib/jsonapi/pagination.rb
CHANGED
@@ -43,6 +43,8 @@ module JSONAPI
|
|
43
43
|
original_url = request.base_url + request.path + '?'
|
44
44
|
|
45
45
|
pagination.each do |page_name, number|
|
46
|
+
next if page_name == :records
|
47
|
+
|
46
48
|
original_params[:page][:number] = number
|
47
49
|
links[page_name] = original_url + CGI.unescape(
|
48
50
|
original_params.to_query
|
@@ -63,7 +65,7 @@ module JSONAPI
|
|
63
65
|
numbers = { current: page }
|
64
66
|
|
65
67
|
if resources.respond_to?(:unscope)
|
66
|
-
total = resources.unscope(:limit, :offset, :order).
|
68
|
+
total = resources.unscope(:limit, :offset, :order).size
|
67
69
|
else
|
68
70
|
# Try to fetch the cached size first
|
69
71
|
total = resources.instance_variable_get(:@original_size)
|
@@ -82,6 +84,10 @@ module JSONAPI
|
|
82
84
|
numbers[:last] = last_page
|
83
85
|
end
|
84
86
|
|
87
|
+
if total.present?
|
88
|
+
numbers[:records] = total
|
89
|
+
end
|
90
|
+
|
85
91
|
numbers
|
86
92
|
end
|
87
93
|
|
@@ -89,16 +95,30 @@ module JSONAPI
|
|
89
95
|
#
|
90
96
|
# @return [Array] with the offset, limit and the current page number
|
91
97
|
def jsonapi_pagination_params
|
92
|
-
def_per_page = self.class.const_get(:JSONAPI_PAGE_SIZE).to_i
|
93
|
-
|
94
98
|
pagination = params[:page].try(:slice, :number, :size) || {}
|
95
|
-
per_page = pagination
|
96
|
-
per_page = def_per_page if per_page > def_per_page || per_page < 1
|
99
|
+
per_page = jsonapi_page_size(pagination)
|
97
100
|
num = [1, pagination[:number].to_f.to_i].max
|
98
101
|
|
99
102
|
[(num - 1) * per_page, per_page, num]
|
100
103
|
end
|
101
104
|
|
105
|
+
# Retrieves the default page size
|
106
|
+
#
|
107
|
+
# @param per_page_param [Hash] opts the paginations params
|
108
|
+
# @option opts [String] :number the page number requested
|
109
|
+
# @option opts [String] :size the page size requested
|
110
|
+
#
|
111
|
+
# @return [Integer]
|
112
|
+
def jsonapi_page_size(pagination_params)
|
113
|
+
per_page = pagination_params[:size].to_f.to_i
|
114
|
+
|
115
|
+
return self.class
|
116
|
+
.const_get(:JSONAPI_PAGE_SIZE)
|
117
|
+
.to_i if per_page < 1
|
118
|
+
|
119
|
+
per_page
|
120
|
+
end
|
121
|
+
|
102
122
|
# Fallback to Rack's parsed query string when Rails is not available
|
103
123
|
#
|
104
124
|
# @return [Hash]
|
data/lib/jsonapi/rails.rb
CHANGED
@@ -55,8 +55,18 @@ module JSONAPI
|
|
55
55
|
model_serializer = JSONAPI::Rails.serializer_class(model, false)
|
56
56
|
end
|
57
57
|
|
58
|
-
details =
|
59
|
-
|
58
|
+
details = {}
|
59
|
+
if ::Rails::VERSION::MAJOR >= 6 && ::Rails::VERSION::MINOR >= 1
|
60
|
+
resource.map do |error|
|
61
|
+
attr = error.attribute
|
62
|
+
details[attr] ||= []
|
63
|
+
details[attr] << error.detail.merge(message: error.message)
|
64
|
+
end
|
65
|
+
elsif resource.respond_to?(:details)
|
66
|
+
details = resource.details
|
67
|
+
else
|
68
|
+
details = resource.messages
|
69
|
+
end
|
60
70
|
|
61
71
|
details.each do |error_key, error_hashes|
|
62
72
|
error_hashes.each do |error_hash|
|
data/lib/jsonapi/version.rb
CHANGED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe JSONAPI::Deserialization do
|
4
|
+
let(:jsonapi_deserialize) { UsersController.new.method(:jsonapi_deserialize) }
|
5
|
+
let(:document) do
|
6
|
+
{
|
7
|
+
data: {
|
8
|
+
id: 1,
|
9
|
+
type: 'note',
|
10
|
+
attributes: {
|
11
|
+
title: 'Title 1',
|
12
|
+
date: '2015-12-20'
|
13
|
+
},
|
14
|
+
relationships: {
|
15
|
+
author: {
|
16
|
+
data: {
|
17
|
+
type: 'user',
|
18
|
+
id: 2
|
19
|
+
}
|
20
|
+
},
|
21
|
+
second_author: {
|
22
|
+
data: nil
|
23
|
+
},
|
24
|
+
notes: {
|
25
|
+
data: [
|
26
|
+
{
|
27
|
+
type: 'note',
|
28
|
+
id: 3
|
29
|
+
},
|
30
|
+
{
|
31
|
+
type: 'note',
|
32
|
+
id: 4
|
33
|
+
}
|
34
|
+
]
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#jsonapi_deserialize' do
|
42
|
+
it do
|
43
|
+
expect(jsonapi_deserialize.call(document)).to eq(
|
44
|
+
'id' => 1,
|
45
|
+
'date' => '2015-12-20',
|
46
|
+
'title' => 'Title 1',
|
47
|
+
'author_id' => 2,
|
48
|
+
'second_author_id' => nil,
|
49
|
+
'note_ids' => [3, 4]
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with `only`' do
|
54
|
+
it do
|
55
|
+
expect(jsonapi_deserialize.call(document, only: :notes)).to eq(
|
56
|
+
'note_ids' => [3, 4]
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with `except`' do
|
62
|
+
it do
|
63
|
+
expect(
|
64
|
+
jsonapi_deserialize.call(document, except: [:date, :title])
|
65
|
+
).to eq(
|
66
|
+
'id' => 1,
|
67
|
+
'author_id' => 2,
|
68
|
+
'second_author_id' => nil,
|
69
|
+
'note_ids' => [3, 4]
|
70
|
+
)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'with `polymorphic`' do
|
75
|
+
it do
|
76
|
+
expect(
|
77
|
+
jsonapi_deserialize.call(
|
78
|
+
document, only: :author, polymorphic: :author
|
79
|
+
)
|
80
|
+
).to eq(
|
81
|
+
'author_id' => 2,
|
82
|
+
'author_type' => User.name
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/spec/dummy.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'active_record'
|
3
|
+
require 'action_controller/railtie'
|
4
|
+
require 'jsonapi'
|
5
|
+
require 'ransack'
|
6
|
+
|
7
|
+
Rails.logger = Logger.new(STDOUT)
|
8
|
+
Rails.logger.level = ENV['LOG_LEVEL'] || Logger::WARN
|
9
|
+
|
10
|
+
JSONAPI::Rails.install!
|
11
|
+
|
12
|
+
ActiveRecord::Base.logger = Rails.logger
|
13
|
+
ActiveRecord::Base.establish_connection(
|
14
|
+
ENV['DATABASE_URL'] || 'sqlite3::memory:'
|
15
|
+
)
|
16
|
+
|
17
|
+
ActiveRecord::Schema.define do
|
18
|
+
create_table :users, force: true do |t|
|
19
|
+
t.string :first_name
|
20
|
+
t.string :last_name
|
21
|
+
t.timestamps
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :notes, force: true do |t|
|
25
|
+
t.string :title
|
26
|
+
t.integer :user_id
|
27
|
+
t.integer :quantity
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class User < ActiveRecord::Base
|
33
|
+
has_many :notes
|
34
|
+
end
|
35
|
+
|
36
|
+
class Note < ActiveRecord::Base
|
37
|
+
validates_format_of :title, without: /BAD_TITLE/
|
38
|
+
validates_numericality_of :quantity, less_than: 100, if: :quantity?
|
39
|
+
belongs_to :user, required: true
|
40
|
+
end
|
41
|
+
|
42
|
+
class CustomNoteSerializer
|
43
|
+
include JSONAPI::Serializer
|
44
|
+
|
45
|
+
set_type :note
|
46
|
+
belongs_to :user
|
47
|
+
attributes(:title, :quantity, :created_at, :updated_at)
|
48
|
+
end
|
49
|
+
|
50
|
+
class UserSerializer
|
51
|
+
include JSONAPI::Serializer
|
52
|
+
|
53
|
+
has_many :notes, serializer: CustomNoteSerializer
|
54
|
+
attributes(:last_name, :created_at, :updated_at)
|
55
|
+
|
56
|
+
attribute :first_name do |object, params|
|
57
|
+
if params[:first_name_upcase]
|
58
|
+
object.first_name.upcase
|
59
|
+
else
|
60
|
+
object.first_name
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Dummy < Rails::Application
|
66
|
+
secrets.secret_key_base = '_'
|
67
|
+
config.hosts << 'www.example.com' if config.respond_to?(:hosts)
|
68
|
+
|
69
|
+
routes.draw do
|
70
|
+
scope defaults: { format: :jsonapi } do
|
71
|
+
resources :users, only: [:index]
|
72
|
+
resources :notes, only: [:update]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class UsersController < ActionController::Base
|
78
|
+
include JSONAPI::Fetching
|
79
|
+
include JSONAPI::Filtering
|
80
|
+
include JSONAPI::Pagination
|
81
|
+
include JSONAPI::Deserialization
|
82
|
+
|
83
|
+
def index
|
84
|
+
allowed_fields = [
|
85
|
+
:first_name, :last_name, :created_at,
|
86
|
+
:notes_created_at, :notes_quantity
|
87
|
+
]
|
88
|
+
options = { sort_with_expressions: true }
|
89
|
+
|
90
|
+
jsonapi_filter(User.all, allowed_fields, options) do |filtered|
|
91
|
+
result = filtered.result
|
92
|
+
|
93
|
+
if params[:sort].to_s.include?('notes_quantity')
|
94
|
+
render jsonapi: result.group('id').to_a
|
95
|
+
return
|
96
|
+
end
|
97
|
+
|
98
|
+
result = result.to_a if params[:as_list]
|
99
|
+
|
100
|
+
jsonapi_paginate(result) do |paginated|
|
101
|
+
render jsonapi: paginated
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
def jsonapi_meta(resources)
|
108
|
+
{
|
109
|
+
many: true,
|
110
|
+
pagination: jsonapi_pagination_meta(resources)
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def jsonapi_serializer_params
|
115
|
+
{
|
116
|
+
first_name_upcase: params[:upcase]
|
117
|
+
}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class NotesController < ActionController::Base
|
122
|
+
include JSONAPI::Errors
|
123
|
+
include JSONAPI::Deserialization
|
124
|
+
|
125
|
+
def update
|
126
|
+
raise_error! if params[:id] == 'tada'
|
127
|
+
|
128
|
+
note = Note.find(params[:id])
|
129
|
+
|
130
|
+
if note.update(note_params)
|
131
|
+
render jsonapi: note
|
132
|
+
else
|
133
|
+
note.errors.add(:title, message: 'has typos') if note.errors.key?(:title)
|
134
|
+
|
135
|
+
render jsonapi_errors: note.errors, status: :unprocessable_entity
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
def render_jsonapi_internal_server_error(exception)
|
141
|
+
Rails.logger.error(exception)
|
142
|
+
super(exception)
|
143
|
+
end
|
144
|
+
|
145
|
+
def jsonapi_serializer_class(resource, is_collection)
|
146
|
+
JSONAPI::Rails.serializer_class(resource, is_collection)
|
147
|
+
rescue NameError
|
148
|
+
klass = resource.class
|
149
|
+
klass = resource.first.class if is_collection
|
150
|
+
"Custom#{klass.name}Serializer".constantize
|
151
|
+
end
|
152
|
+
|
153
|
+
def note_params
|
154
|
+
# Will trigger required attribute error handling
|
155
|
+
params.require(:data).require(:attributes).require(:title)
|
156
|
+
|
157
|
+
jsonapi_deserialize(params)
|
158
|
+
end
|
159
|
+
|
160
|
+
def jsonapi_meta(resources)
|
161
|
+
{ single: true }
|
162
|
+
end
|
163
|
+
end
|
data/spec/errors_spec.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe NotesController, type: :request do
|
4
|
+
describe 'PUT /notes/:id' do
|
5
|
+
let(:note) { create_note }
|
6
|
+
let(:note_id) { note.id }
|
7
|
+
let(:user) { note.user }
|
8
|
+
let(:user_id) { user.id }
|
9
|
+
let(:note_params) do
|
10
|
+
{
|
11
|
+
data: {
|
12
|
+
attributes: { title: FFaker::Company.name },
|
13
|
+
relationships: { user: { data: { id: user_id } } }
|
14
|
+
}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
let(:params) { note_params }
|
18
|
+
|
19
|
+
before do
|
20
|
+
put(note_path(note_id), params: params.to_json, headers: jsonapi_headers)
|
21
|
+
end
|
22
|
+
|
23
|
+
it do
|
24
|
+
expect(response).to have_http_status(:ok)
|
25
|
+
expect(response_json['data']).to have_id(note.id.to_s)
|
26
|
+
expect(response_json['meta']).to eq('single' => true)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with a missing parameter in the payload' do
|
30
|
+
let(:params) { {} }
|
31
|
+
|
32
|
+
it do
|
33
|
+
expect(response).to have_http_status(:unprocessable_entity)
|
34
|
+
expect(response_json['errors'].size).to eq(1)
|
35
|
+
expect(response_json['errors'][0]['status']).to eq('422')
|
36
|
+
expect(response_json['errors'][0]['title'])
|
37
|
+
.to eq(Rack::Utils::HTTP_STATUS_CODES[422])
|
38
|
+
expect(response_json['errors'][0]['source']).to eq('pointer' => '')
|
39
|
+
expect(response_json['errors'][0]['detail']).to be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with an invalid payload' do
|
44
|
+
let(:params) do
|
45
|
+
payload = note_params.dup
|
46
|
+
payload[:data][:relationships][:user][:data][:id] = nil
|
47
|
+
payload
|
48
|
+
end
|
49
|
+
|
50
|
+
it do
|
51
|
+
expect(response).to have_http_status(:unprocessable_entity)
|
52
|
+
expect(response_json['errors'].size).to eq(1)
|
53
|
+
expect(response_json['errors'][0]['status']).to eq('422')
|
54
|
+
expect(response_json['errors'][0]['code']).to include('blank')
|
55
|
+
expect(response_json['errors'][0]['title'])
|
56
|
+
.to eq(Rack::Utils::HTTP_STATUS_CODES[422])
|
57
|
+
expect(response_json['errors'][0]['source'])
|
58
|
+
.to eq('pointer' => '/data/relationships/user')
|
59
|
+
if Rails::VERSION::MAJOR >= 6 && Rails::VERSION::MINOR >= 1
|
60
|
+
expect(response_json['errors'][0]['detail'])
|
61
|
+
.to eq('User must exist')
|
62
|
+
else
|
63
|
+
expect(response_json['errors'][0]['detail'])
|
64
|
+
.to eq('User can\'t be blank')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'required by validations' do
|
69
|
+
let(:params) do
|
70
|
+
payload = note_params.dup
|
71
|
+
payload[:data][:attributes][:title] = 'BAD_TITLE'
|
72
|
+
payload[:data][:attributes][:quantity] = 100 + rand(10)
|
73
|
+
payload
|
74
|
+
end
|
75
|
+
|
76
|
+
it do
|
77
|
+
expect(response).to have_http_status(:unprocessable_entity)
|
78
|
+
expect(response_json['errors'].size).to eq(3)
|
79
|
+
expect(response_json['errors'][0]['status']).to eq('422')
|
80
|
+
expect(response_json['errors'][0]['code']).to include('invalid')
|
81
|
+
expect(response_json['errors'][0]['title'])
|
82
|
+
.to eq(Rack::Utils::HTTP_STATUS_CODES[422])
|
83
|
+
expect(response_json['errors'][0]['source'])
|
84
|
+
.to eq('pointer' => '/data/attributes/title')
|
85
|
+
expect(response_json['errors'][0]['detail'])
|
86
|
+
.to eq('Title is invalid')
|
87
|
+
|
88
|
+
expect(response_json['errors'][1]['status']).to eq('422')
|
89
|
+
|
90
|
+
if Rails::VERSION::MAJOR >= 5
|
91
|
+
expect(response_json['errors'][1]['code']).to eq('invalid')
|
92
|
+
else
|
93
|
+
expect(response_json['errors'][1]['code']).to eq('has_typos')
|
94
|
+
end
|
95
|
+
|
96
|
+
expect(response_json['errors'][1]['title'])
|
97
|
+
.to eq(Rack::Utils::HTTP_STATUS_CODES[422])
|
98
|
+
expect(response_json['errors'][1]['source'])
|
99
|
+
.to eq('pointer' => '/data/attributes/title')
|
100
|
+
expect(response_json['errors'][1]['detail'])
|
101
|
+
.to eq('Title has typos')
|
102
|
+
|
103
|
+
expect(response_json['errors'][2]['status']).to eq('422')
|
104
|
+
|
105
|
+
if Rails::VERSION::MAJOR >= 5
|
106
|
+
expect(response_json['errors'][2]['code']).to eq('less_than')
|
107
|
+
else
|
108
|
+
expect(response_json['errors'][2]['code'])
|
109
|
+
.to eq('must_be_less_than_100')
|
110
|
+
end
|
111
|
+
|
112
|
+
expect(response_json['errors'][2]['title'])
|
113
|
+
.to eq(Rack::Utils::HTTP_STATUS_CODES[422])
|
114
|
+
expect(response_json['errors'][2]['source'])
|
115
|
+
.to eq('pointer' => '/data/attributes/quantity')
|
116
|
+
expect(response_json['errors'][2]['detail'])
|
117
|
+
.to eq('Quantity must be less than 100')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'as a param attribute' do
|
122
|
+
let(:params) do
|
123
|
+
payload = note_params.dup
|
124
|
+
payload[:data][:attributes].delete(:title)
|
125
|
+
# To have any attribtues in the payload...
|
126
|
+
payload[:data][:attributes][:created_at] = nil
|
127
|
+
payload
|
128
|
+
end
|
129
|
+
|
130
|
+
it do
|
131
|
+
expect(response).to have_http_status(:unprocessable_entity)
|
132
|
+
expect(response_json['errors'][0]['source'])
|
133
|
+
.to eq('pointer' => '/data/attributes/title')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'with a bad note ID' do
|
139
|
+
let(:user_id) { nil }
|
140
|
+
let(:note_id) { rand(10) }
|
141
|
+
|
142
|
+
it do
|
143
|
+
expect(response).to have_http_status(:not_found)
|
144
|
+
expect(response_json['errors'].size).to eq(1)
|
145
|
+
expect(response_json['errors'][0]['status']).to eq('404')
|
146
|
+
expect(response_json['errors'][0]['title'])
|
147
|
+
.to eq(Rack::Utils::HTTP_STATUS_CODES[404])
|
148
|
+
expect(response_json['errors'][0]['source']).to be_nil
|
149
|
+
expect(response_json['errors'][0]['detail']).to be_nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'with an exception' do
|
154
|
+
let(:user_id) { nil }
|
155
|
+
let(:note_id) { 'tada' }
|
156
|
+
|
157
|
+
it do
|
158
|
+
expect(response).to have_http_status(:internal_server_error)
|
159
|
+
expect(response_json['errors'].size).to eq(1)
|
160
|
+
expect(response_json['errors'][0]['status']).to eq('500')
|
161
|
+
expect(response_json['errors'][0]['title'])
|
162
|
+
.to eq(Rack::Utils::HTTP_STATUS_CODES[500])
|
163
|
+
expect(response_json['errors'][0]['source']).to be_nil
|
164
|
+
expect(response_json['errors'][0]['detail']).to be_nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|