jsonapi.rb 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|