jsonapi-resources 0.3.3 → 0.4.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +274 -102
  3. data/jsonapi-resources.gemspec +1 -0
  4. data/lib/jsonapi-resources.rb +15 -0
  5. data/lib/jsonapi/active_record_operations_processor.rb +21 -10
  6. data/lib/jsonapi/acts_as_resource_controller.rb +175 -0
  7. data/lib/jsonapi/configuration.rb +11 -0
  8. data/lib/jsonapi/error_codes.rb +7 -4
  9. data/lib/jsonapi/exceptions.rb +23 -15
  10. data/lib/jsonapi/formatter.rb +5 -5
  11. data/lib/jsonapi/include_directives.rb +67 -0
  12. data/lib/jsonapi/operation.rb +185 -65
  13. data/lib/jsonapi/operation_result.rb +38 -5
  14. data/lib/jsonapi/operation_results.rb +33 -0
  15. data/lib/jsonapi/operations_processor.rb +49 -9
  16. data/lib/jsonapi/paginator.rb +31 -17
  17. data/lib/jsonapi/request.rb +347 -163
  18. data/lib/jsonapi/resource.rb +159 -56
  19. data/lib/jsonapi/resource_controller.rb +1 -234
  20. data/lib/jsonapi/resource_serializer.rb +55 -69
  21. data/lib/jsonapi/resources/version.rb +1 -1
  22. data/lib/jsonapi/response_document.rb +87 -0
  23. data/lib/jsonapi/routing_ext.rb +17 -11
  24. data/test/controllers/controller_test.rb +602 -326
  25. data/test/fixtures/active_record.rb +96 -6
  26. data/test/fixtures/line_items.yml +7 -1
  27. data/test/fixtures/numeros_telefone.yml +3 -0
  28. data/test/fixtures/purchase_orders.yml +6 -0
  29. data/test/integration/requests/request_test.rb +129 -60
  30. data/test/integration/routes/routes_test.rb +17 -17
  31. data/test/test_helper.rb +23 -5
  32. data/test/unit/jsonapi_request/jsonapi_request_test.rb +48 -0
  33. data/test/unit/operation/operations_processor_test.rb +242 -54
  34. data/test/unit/resource/resource_test.rb +108 -2
  35. data/test/unit/serializer/include_directives_test.rb +108 -0
  36. data/test/unit/serializer/response_document_test.rb +61 -0
  37. data/test/unit/serializer/serializer_test.rb +679 -520
  38. metadata +26 -2
@@ -18,37 +18,37 @@ class RoutesTest < ActionDispatch::IntegrationTest
18
18
  end
19
19
 
20
20
  def test_routing_posts_links_author_show
21
- assert_routing({path: '/posts/1/links/author', method: :get},
21
+ assert_routing({path: '/posts/1/relationships/author', method: :get},
22
22
  {controller: 'posts', action: 'show_association', post_id: '1', association: 'author'})
23
23
  end
24
24
 
25
25
  def test_routing_posts_links_author_destroy
26
- assert_routing({path: '/posts/1/links/author', method: :delete},
26
+ assert_routing({path: '/posts/1/relationships/author', method: :delete},
27
27
  {controller: 'posts', action: 'destroy_association', post_id: '1', association: 'author'})
28
28
  end
29
29
 
30
30
  def test_routing_posts_links_author_update
31
- assert_routing({path: '/posts/1/links/author', method: :patch},
31
+ assert_routing({path: '/posts/1/relationships/author', method: :patch},
32
32
  {controller: 'posts', action: 'update_association', post_id: '1', association: 'author'})
33
33
  end
34
34
 
35
35
  def test_routing_posts_links_tags_show
36
- assert_routing({path: '/posts/1/links/tags', method: :get},
36
+ assert_routing({path: '/posts/1/relationships/tags', method: :get},
37
37
  {controller: 'posts', action: 'show_association', post_id: '1', association: 'tags'})
38
38
  end
39
39
 
40
40
  def test_routing_posts_links_tags_destroy
41
- assert_routing({path: '/posts/1/links/tags/1,2', method: :delete},
41
+ assert_routing({path: '/posts/1/relationships/tags/1,2', method: :delete},
42
42
  {controller: 'posts', action: 'destroy_association', post_id: '1', keys: '1,2', association: 'tags'})
43
43
  end
44
44
 
45
45
  def test_routing_posts_links_tags_create
46
- assert_routing({path: '/posts/1/links/tags', method: :post},
46
+ assert_routing({path: '/posts/1/relationships/tags', method: :post},
47
47
  {controller: 'posts', action: 'create_association', post_id: '1', association: 'tags'})
48
48
  end
49
49
 
50
50
  def test_routing_posts_links_tags_update_acts_as_set
51
- assert_routing({path: '/posts/1/links/tags', method: :patch},
51
+ assert_routing({path: '/posts/1/relationships/tags', method: :patch},
52
52
  {controller: 'posts', action: 'update_association', post_id: '1', association: 'tags'})
53
53
  end
54
54
 
@@ -64,13 +64,13 @@ class RoutesTest < ActionDispatch::IntegrationTest
64
64
  end
65
65
 
66
66
  def test_routing_v1_posts_links_writer_show
67
- assert_routing({path: '/api/v1/posts/1/links/writer', method: :get},
67
+ assert_routing({path: '/api/v1/posts/1/relationships/writer', method: :get},
68
68
  {controller: 'api/v1/posts', action: 'show_association', post_id: '1', association: 'writer'})
69
69
  end
70
70
 
71
71
  # V2
72
72
  def test_routing_v2_posts_links_author_show
73
- assert_routing({path: '/api/v2/posts/1/links/author', method: :get},
73
+ assert_routing({path: '/api/v2/posts/1/relationships/author', method: :get},
74
74
  {controller: 'api/v2/posts', action: 'show_association', post_id: '1', association: 'author'})
75
75
  end
76
76
 
@@ -93,14 +93,14 @@ class RoutesTest < ActionDispatch::IntegrationTest
93
93
 
94
94
  def test_routing_v4_isoCurrencies_resources
95
95
  assert_routing({path: '/api/v4/isoCurrencies/USD', method: :get},
96
- {action: 'show', controller: 'api/v4/iso_currencies', code: 'USD'})
96
+ {action: 'show', controller: 'api/v4/iso_currencies', id: 'USD'})
97
97
  end
98
98
 
99
99
  def test_routing_v4_expenseEntries_resources
100
100
  assert_routing({path: '/api/v4/expenseEntries/1', method: :get},
101
101
  {action: 'show', controller: 'api/v4/expense_entries', id: '1'})
102
102
 
103
- assert_routing({path: '/api/v4/expenseEntries/1/links/isoCurrency', method: :get},
103
+ assert_routing({path: '/api/v4/expenseEntries/1/relationships/isoCurrency', method: :get},
104
104
  {controller: 'api/v4/expense_entries', action: 'show_association', expense_entry_id: '1', association: 'iso_currency'})
105
105
  end
106
106
 
@@ -112,14 +112,14 @@ class RoutesTest < ActionDispatch::IntegrationTest
112
112
 
113
113
  def test_routing_v5_isoCurrencies_resources
114
114
  assert_routing({path: '/api/v5/iso-currencies/USD', method: :get},
115
- {action: 'show', controller: 'api/v5/iso_currencies', code: 'USD'})
115
+ {action: 'show', controller: 'api/v5/iso_currencies', id: 'USD'})
116
116
  end
117
117
 
118
118
  def test_routing_v5_expenseEntries_resources
119
119
  assert_routing({path: '/api/v5/expense-entries/1', method: :get},
120
120
  {action: 'show', controller: 'api/v5/expense_entries', id: '1'})
121
121
 
122
- assert_routing({path: '/api/v5/expense-entries/1/links/iso-currency', method: :get},
122
+ assert_routing({path: '/api/v5/expense-entries/1/relationships/iso-currency', method: :get},
123
123
  {controller: 'api/v5/expense_entries', action: 'show_association', expense_entry_id: '1', association: 'iso_currency'})
124
124
  end
125
125
 
@@ -129,14 +129,14 @@ class RoutesTest < ActionDispatch::IntegrationTest
129
129
  end
130
130
 
131
131
  def test_routing_author_links_posts_create_not_acts_as_set
132
- assert_routing({path: '/api/v5/authors/1/links/posts', method: :post},
132
+ assert_routing({path: '/api/v5/authors/1/relationships/posts', method: :post},
133
133
  {controller: 'api/v5/authors', action: 'create_association', author_id: '1', association: 'posts'})
134
134
  end
135
135
 
136
136
  #primary_key
137
137
  def test_routing_primary_key_jsonapi_resources
138
138
  assert_routing({path: '/iso_currencies/USD', method: :get},
139
- {action: 'show', controller: 'iso_currencies', code: 'USD'})
139
+ {action: 'show', controller: 'iso_currencies', id: 'USD'})
140
140
  end
141
141
 
142
142
  # ToDo: Refute routing
@@ -146,12 +146,12 @@ class RoutesTest < ActionDispatch::IntegrationTest
146
146
  # end
147
147
 
148
148
  # def test_routing_posts_links_author_except_destroy
149
- # assert_routing({ path: '/api/v3/posts/1/links/author', method: :delete },
149
+ # assert_routing({ path: '/api/v3/posts/1/relationships/author', method: :delete },
150
150
  # { controller: 'api/v3/posts', action: 'destroy_association', post_id: '1', association: 'author' })
151
151
  # end
152
152
  #
153
153
  # def test_routing_posts_links_tags_only_create_show
154
- # assert_routing({ path: '/api/v3/posts/1/links/tags/1,2', method: :delete },
154
+ # assert_routing({ path: '/api/v3/posts/1/relationships/tags/1,2', method: :delete },
155
155
  # { controller: 'api/v3/posts', action: 'destroy_association', post_id: '1', keys: '1,2', association: 'tags' })
156
156
  # end
157
157
 
@@ -57,6 +57,16 @@ if Rails::VERSION::MAJOR >= 4 && Rails::VERSION::MINOR < 1
57
57
  end
58
58
  end
59
59
 
60
+ def count_queries(&block)
61
+ @query_count = 0
62
+ ActiveSupport::Notifications.subscribe('sql.active_record') do
63
+ @query_count = @query_count + 1
64
+ end
65
+ yield block
66
+ ActiveSupport::Notifications.unsubscribe('sql.active_record')
67
+ @query_count
68
+ end
69
+
60
70
  TestApp.initialize!
61
71
 
62
72
  require File.expand_path('../fixtures/active_record', __FILE__)
@@ -78,6 +88,7 @@ TestApp.routes.draw do
78
88
  jsonapi_resources :moons
79
89
  jsonapi_resources :preferences
80
90
  jsonapi_resources :facts
91
+ jsonapi_resources :categories
81
92
 
82
93
  namespace :api do
83
94
  namespace :v1 do
@@ -131,6 +142,8 @@ TestApp.routes.draw do
131
142
 
132
143
  jsonapi_resources :iso_currencies do
133
144
  end
145
+
146
+ jsonapi_resources :books
134
147
  end
135
148
 
136
149
  JSONAPI.configuration.route_format = :dasherized_route
@@ -160,6 +173,10 @@ TestApp.routes.draw do
160
173
  jsonapi_resources :purchase_orders
161
174
  jsonapi_resources :line_items
162
175
  end
176
+
177
+ namespace :v8 do
178
+ jsonapi_resources :numeros_telefone
179
+ end
163
180
  end
164
181
  end
165
182
 
@@ -199,7 +216,7 @@ end
199
216
 
200
217
  class DateWithTimezoneValueFormatter < JSONAPI::ValueFormatter
201
218
  class << self
202
- def format(raw_value, context)
219
+ def format(raw_value)
203
220
  raw_value.in_time_zone('Eastern Time (US & Canada)').to_s
204
221
  end
205
222
  end
@@ -207,7 +224,7 @@ end
207
224
 
208
225
  class DateValueFormatter < JSONAPI::ValueFormatter
209
226
  class << self
210
- def format(raw_value, context)
227
+ def format(raw_value)
211
228
  raw_value.strftime('%m/%d/%Y')
212
229
  end
213
230
  end
@@ -215,12 +232,13 @@ end
215
232
 
216
233
  class TitleValueFormatter < JSONAPI::ValueFormatter
217
234
  class << self
218
- def format(raw_value, source)
219
- super(raw_value, source).titlecase
235
+ def format(raw_value)
236
+ super(raw_value).titlecase
220
237
  end
221
238
 
222
- def unformat(value, context)
239
+ def unformat(value)
223
240
  value.to_s.downcase
224
241
  end
225
242
  end
226
243
  end
244
+
@@ -1,5 +1,16 @@
1
1
  require File.expand_path('../../../test_helper', __FILE__)
2
2
 
3
+ class CatResource < JSONAPI::Resource
4
+ attribute :id
5
+ attribute :name
6
+ attribute :breed
7
+
8
+ has_one :mother, class_name: 'Cat'
9
+ has_one :father, class_name: 'Cat'
10
+
11
+ filters :name
12
+ end
13
+
3
14
  class JSONAPIRequestTest < ActiveSupport::TestCase
4
15
  def test_parse_includes_underscored
5
16
  params = ActionController::Parameters.new(
@@ -149,4 +160,41 @@ class JSONAPIRequestTest < ActiveSupport::TestCase
149
160
  refute request.errors.empty?
150
161
  assert_equal 'expense_entries is not a valid resource.', request.errors[0].detail
151
162
  end
163
+
164
+ def test_parse_filters_with_valid_filters
165
+ setup_request
166
+ @request.parse_filters({name: 'Whiskers'})
167
+ assert_equal(@request.filters[:name], 'Whiskers')
168
+ assert_equal(@request.errors, [])
169
+ end
170
+
171
+ def test_parse_filters_with_non_valid_filter
172
+ setup_request
173
+ @request.parse_filters({breed: 'Whiskers'}) # breed is not a set filter
174
+ assert_equal(@request.filters, {})
175
+ assert_equal(@request.errors.count, 1)
176
+ assert_equal(@request.errors.first.title, "Filter not allowed")
177
+ end
178
+
179
+ def test_parse_filters_with_no_filters
180
+ setup_request
181
+ @request.parse_filters(nil)
182
+ assert_equal(@request.filters, {})
183
+ assert_equal(@request.errors, [])
184
+ end
185
+
186
+ def test_parse_filters_with_invalid_filters_param
187
+ setup_request
188
+ @request.parse_filters('noeach') # String does not implement #each
189
+ assert_equal(@request.filters, {})
190
+ assert_equal(@request.errors.count, 1)
191
+ assert_equal(@request.errors.first.title, "Invalid filters syntax")
192
+ end
193
+
194
+ private
195
+
196
+ def setup_request
197
+ @request = JSONAPI::Request.new
198
+ @request.resource_klass = CatResource
199
+ end
152
200
  end
@@ -1,9 +1,5 @@
1
1
  require File.expand_path('../../../test_helper', __FILE__)
2
2
 
3
- require 'jsonapi/operation'
4
- require 'jsonapi/operation_result'
5
- require 'jsonapi/operations_processor'
6
-
7
3
  class TestOperationsProcessor < JSONAPI::OperationsProcessor
8
4
  before_operation :log_before_operation
9
5
 
@@ -68,18 +64,17 @@ class OperationsProcessorTest < Minitest::Test
68
64
  count = Planet.count
69
65
 
70
66
  operations = [
71
- JSONAPI::CreateResourceOperation.new(PlanetResource, {attributes: {'name' => 'earth', 'description' => 'The best planet ever.'}})
67
+ JSONAPI::CreateResourceOperation.new(PlanetResource, data: {attributes: {'name' => 'earth', 'description' => 'The best planet ever.'}})
72
68
  ]
73
69
 
74
70
  request = JSONAPI::Request.new
75
71
  request.operations = operations
76
72
 
77
- results = op.process(request)
73
+ operation_results = op.process(request)
78
74
 
79
- assert_kind_of(Array, results)
80
- assert_kind_of(JSONAPI::OperationResult, results[0])
81
- assert_equal(:created, results[0].code)
82
- assert_equal(results.size, 1)
75
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
76
+ assert_equal(:created, operation_results.results[0].code)
77
+ assert_equal(operation_results.results.size, 1)
83
78
  assert_equal(Planet.count, count + 1)
84
79
  end
85
80
 
@@ -89,18 +84,18 @@ class OperationsProcessorTest < Minitest::Test
89
84
  count = Planet.count
90
85
 
91
86
  operations = [
92
- JSONAPI::CreateResourceOperation.new(PlanetResource, {attributes: {'name' => 'earth', 'description' => 'The best planet for life.'}}),
93
- JSONAPI::CreateResourceOperation.new(PlanetResource, {attributes: {'name' => 'mars', 'description' => 'The red planet.'}}),
94
- JSONAPI::CreateResourceOperation.new(PlanetResource, {attributes: {'name' => 'venus', 'description' => 'A very hot planet.'}})
87
+ JSONAPI::CreateResourceOperation.new(PlanetResource, data: {attributes: {'name' => 'earth', 'description' => 'The best planet for life.'}}),
88
+ JSONAPI::CreateResourceOperation.new(PlanetResource, data: {attributes: {'name' => 'mars', 'description' => 'The red planet.'}}),
89
+ JSONAPI::CreateResourceOperation.new(PlanetResource, data: {attributes: {'name' => 'venus', 'description' => 'A very hot planet.'}})
95
90
  ]
96
91
 
97
92
  request = JSONAPI::Request.new
98
93
  request.operations = operations
99
94
 
100
- results = op.process(request)
95
+ operation_results = op.process(request)
101
96
 
102
- assert_kind_of(Array, results)
103
- assert_equal(results.size, 3)
97
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
98
+ assert_equal(operation_results.results.size, 3)
104
99
  assert_equal(Planet.count, count + 3)
105
100
  end
106
101
 
@@ -113,42 +108,63 @@ class OperationsProcessorTest < Minitest::Test
113
108
  assert_equal(saturn.planet_type_id, planetoid.id)
114
109
 
115
110
  operations = [
116
- JSONAPI::ReplaceHasOneAssociationOperation.new(PlanetResource, saturn.id, :planet_type, gas_giant.id)
111
+ JSONAPI::ReplaceHasOneAssociationOperation.new(
112
+ PlanetResource,
113
+ {
114
+ resource_id: saturn.id,
115
+ association_type: :planet_type,
116
+ key_value: gas_giant.id
117
+ }
118
+ )
117
119
  ]
118
120
 
119
121
  request = JSONAPI::Request.new
120
122
  request.operations = operations
121
123
 
122
- results = op.process(request)
124
+ operation_results = op.process(request)
123
125
 
124
- assert_kind_of(Array, results)
125
- assert_kind_of(JSONAPI::OperationResult, results[0])
126
- assert_equal(:no_content, results[0].code)
126
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
127
+ assert_kind_of(JSONAPI::OperationResult, operation_results.results[0])
128
+ assert_equal(:no_content, operation_results.results[0].code)
127
129
 
128
130
  saturn.reload
129
131
  assert_equal(saturn.planet_type_id, gas_giant.id)
130
132
 
131
133
  # Remove link
132
134
  operations = [
133
- JSONAPI::ReplaceHasOneAssociationOperation.new(PlanetResource, saturn.id, :planet_type, nil)
135
+ JSONAPI::ReplaceHasOneAssociationOperation.new(
136
+ PlanetResource,
137
+ {
138
+ resource_id: saturn.id,
139
+ association_type: :planet_type,
140
+ key_value: nil
141
+ }
142
+ )
134
143
  ]
135
144
 
136
145
  request = JSONAPI::Request.new
137
146
  request.operations = operations
138
147
 
139
- results = op.process(request)
148
+ op.process(request)
140
149
  saturn.reload
141
150
  assert_equal(saturn.planet_type_id, nil)
142
151
 
143
152
  # Reset
144
153
  operations = [
145
- JSONAPI::ReplaceHasOneAssociationOperation.new(PlanetResource, saturn.id, :planet_type, 5)
154
+ JSONAPI::ReplaceHasOneAssociationOperation.new(
155
+ PlanetResource,
156
+ {
157
+ resource_id: saturn.id,
158
+ association_type: :planet_type,
159
+ key_value: 5
160
+ }
161
+ )
146
162
  ]
147
163
 
148
164
  request = JSONAPI::Request.new
149
165
  request.operations = operations
150
166
 
151
- results = op.process(request)
167
+ op.process(request)
152
168
  saturn.reload
153
169
  assert_equal(saturn.planet_type_id, 5)
154
170
  end
@@ -169,13 +185,20 @@ class OperationsProcessorTest < Minitest::Test
169
185
  betaz.save!
170
186
 
171
187
  operations = [
172
- JSONAPI::CreateHasManyAssociationOperation.new(PlanetTypeResource, gas_giant.id, :planets, [betax.id, betay.id, betaz.id])
188
+ JSONAPI::CreateHasManyAssociationOperation.new(
189
+ PlanetTypeResource,
190
+ {
191
+ resource_id: gas_giant.id,
192
+ association_type: :planets,
193
+ data: [betax.id, betay.id, betaz.id]
194
+ }
195
+ )
173
196
  ]
174
197
 
175
198
  request = JSONAPI::Request.new
176
199
  request.operations = operations
177
200
 
178
- results = op.process(request)
201
+ op.process(request)
179
202
 
180
203
  betax.reload
181
204
  betay.reload
@@ -210,13 +233,20 @@ class OperationsProcessorTest < Minitest::Test
210
233
  betaz.save!
211
234
 
212
235
  operations = [
213
- JSONAPI::ReplaceHasManyAssociationOperation.new(PlanetTypeResource, gas_giant.id, :planets, [betax.id, betay.id, betaz.id])
236
+ JSONAPI::ReplaceHasManyAssociationOperation.new(
237
+ PlanetTypeResource,
238
+ {
239
+ resource_id: gas_giant.id,
240
+ association_type: :planets,
241
+ data: [betax.id, betay.id, betaz.id]
242
+ }
243
+ )
214
244
  ]
215
245
 
216
246
  request = JSONAPI::Request.new
217
247
  request.operations = operations
218
248
 
219
- results = op.process(request)
249
+ op.process(request)
220
250
 
221
251
  betax.reload
222
252
  betay.reload
@@ -243,19 +273,25 @@ class OperationsProcessorTest < Minitest::Test
243
273
  assert_equal(saturn.name, 'Satern')
244
274
 
245
275
  operations = [
246
- JSONAPI::ReplaceFieldsOperation.new(PlanetResource, 1, {attributes: {'name' => 'saturn'}}),
276
+ JSONAPI::ReplaceFieldsOperation.new(
277
+ PlanetResource,
278
+ {
279
+ resource_id: 1,
280
+ data: {attributes: {'name' => 'saturn'}}
281
+ }
282
+ )
247
283
  ]
248
284
 
249
285
  request = JSONAPI::Request.new
250
286
  request.operations = operations
251
287
 
252
- results = op.process(request)
288
+ operation_results = op.process(request)
253
289
 
254
- assert_kind_of(Array, results)
255
- assert_equal(results.size, 1)
290
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
291
+ assert_equal(operation_results.results.size, 1)
256
292
 
257
- assert_kind_of(JSONAPI::OperationResult, results[0])
258
- assert_equal(:ok, results[0].code)
293
+ assert_kind_of(JSONAPI::ResourceOperationResult, operation_results.results[0])
294
+ assert_equal(:ok, operation_results.results[0].code)
259
295
 
260
296
  saturn = Planet.find(1)
261
297
 
@@ -268,51 +304,203 @@ class OperationsProcessorTest < Minitest::Test
268
304
  op = JSONAPI::OperationsProcessor.new
269
305
 
270
306
  count = Planet.count
271
- pluto = Planet.find(2)
272
- assert_equal(pluto.name, 'Pluto')
307
+ makemake = Planet.find(2)
308
+ assert_equal(makemake.name, 'Makemake')
273
309
 
274
310
  operations = [
275
- JSONAPI::RemoveResourceOperation.new(PlanetResource, 2),
311
+ JSONAPI::RemoveResourceOperation.new(PlanetResource, resource_id: 2),
276
312
  ]
277
313
 
278
314
  request = JSONAPI::Request.new
279
315
  request.operations = operations
280
316
 
281
- results = op.process(request)
317
+ operation_results = op.process(request)
282
318
 
283
- assert_kind_of(Array, results)
284
- assert_equal(results.size, 1)
319
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
320
+ assert_equal(operation_results.results.size, 1)
285
321
 
286
- assert_kind_of(JSONAPI::OperationResult, results[0])
287
- assert_equal(:no_content, results[0].code)
322
+ assert_kind_of(JSONAPI::OperationResult, operation_results.results[0])
323
+ assert_equal(:no_content, operation_results.results[0].code)
288
324
  assert_equal(Planet.count, count - 1)
289
325
  end
290
326
 
291
327
  def test_rollback_from_error
292
- op = JSONAPI::ActiveRecordOperationsProcessor.new
328
+ op = ActiveRecordOperationsProcessor.new
293
329
 
294
330
  count = Planet.count
295
331
 
296
332
  operations = [
297
- JSONAPI::RemoveResourceOperation.new(PlanetResource, 3),
298
- JSONAPI::RemoveResourceOperation.new(PlanetResource, 4),
299
- JSONAPI::RemoveResourceOperation.new(PlanetResource, 4)
333
+ JSONAPI::RemoveResourceOperation.new(PlanetResource, resource_id: 3),
334
+ JSONAPI::RemoveResourceOperation.new(PlanetResource, resource_id: 4),
335
+ JSONAPI::RemoveResourceOperation.new(PlanetResource, resource_id: 4)
300
336
  ]
301
337
 
302
338
  request = JSONAPI::Request.new
303
339
  request.operations = operations
304
340
 
305
- results = op.process(request)
341
+ operation_results = op.process(request)
342
+
343
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
306
344
 
307
345
  assert_equal(Planet.count, count)
308
346
 
309
- assert_kind_of(Array, results)
310
- assert_equal(results.size, 3)
347
+ assert_equal(operation_results.results.size, 3)
311
348
 
312
- assert_kind_of(JSONAPI::OperationResult, results[0])
313
- assert_equal(:no_content, results[0].code)
314
- assert_equal(:no_content, results[1].code)
315
- assert_equal(404, results[2].code)
349
+ assert_kind_of(JSONAPI::OperationResult, operation_results.results[0])
350
+ assert_equal(:no_content, operation_results.results[0].code)
351
+ assert_equal(:no_content, operation_results.results[1].code)
352
+ assert_equal(404, operation_results.results[2].code)
316
353
  end
317
354
 
355
+ def test_show_operation
356
+ op = JSONAPI::OperationsProcessor.new
357
+
358
+ operations = [
359
+ JSONAPI::ShowOperation.new(PlanetResource, {id: '1'})
360
+ ]
361
+
362
+ request = JSONAPI::Request.new
363
+ request.operations = operations
364
+
365
+ operation_results = op.process(request)
366
+
367
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
368
+ assert_equal(operation_results.results.size, 1)
369
+ refute operation_results.has_errors?
370
+ end
371
+
372
+ def test_show_operation_error
373
+ op = JSONAPI::OperationsProcessor.new
374
+
375
+ operations = [
376
+ JSONAPI::ShowOperation.new(PlanetResource, {id: '145'})
377
+ ]
378
+
379
+ request = JSONAPI::Request.new
380
+ request.operations = operations
381
+
382
+ operation_results = op.process(request)
383
+
384
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
385
+ assert_equal(operation_results.results.size, 1)
386
+ assert operation_results.has_errors?
387
+ end
388
+
389
+ def test_show_association_operation
390
+ op = JSONAPI::OperationsProcessor.new
391
+
392
+ operations = [
393
+ JSONAPI::ShowAssociationOperation.new(PlanetResource, {parent_key: '1', association_type: :planet_type})
394
+ ]
395
+
396
+ request = JSONAPI::Request.new
397
+ request.operations = operations
398
+
399
+ operation_results = op.process(request)
400
+
401
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
402
+ assert_equal(operation_results.results.size, 1)
403
+ refute operation_results.has_errors?
404
+ end
405
+
406
+ def test_show_association_operation_error
407
+ op = JSONAPI::OperationsProcessor.new
408
+
409
+ operations = [
410
+ JSONAPI::ShowAssociationOperation.new(PlanetResource, {parent_key: '145', association_type: :planet_type})
411
+ ]
412
+
413
+ request = JSONAPI::Request.new
414
+ request.operations = operations
415
+
416
+ operation_results = op.process(request)
417
+
418
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
419
+ assert_equal(operation_results.results.size, 1)
420
+ assert operation_results.has_errors?
421
+ end
422
+
423
+ def test_show_related_resource_operation
424
+ op = JSONAPI::OperationsProcessor.new
425
+
426
+ operations = [
427
+ JSONAPI::ShowRelatedResourceOperation.new(PlanetResource,
428
+ {
429
+ source_klass: PlanetResource,
430
+ source_id: '1',
431
+ association_type: :planet_type})
432
+ ]
433
+
434
+ request = JSONAPI::Request.new
435
+ request.operations = operations
436
+
437
+ operation_results = op.process(request)
438
+
439
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
440
+ assert_equal(operation_results.results.size, 1)
441
+ refute operation_results.has_errors?
442
+ end
443
+
444
+ def test_show_related_resource_operation_error
445
+ op = JSONAPI::OperationsProcessor.new
446
+
447
+ operations = [
448
+ JSONAPI::ShowRelatedResourceOperation.new(PlanetResource,
449
+ {
450
+ source_klass: PlanetResource,
451
+ source_id: '145',
452
+ association_type: :planet_type})
453
+ ]
454
+
455
+ request = JSONAPI::Request.new
456
+ request.operations = operations
457
+
458
+ operation_results = op.process(request)
459
+
460
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
461
+ assert_equal(operation_results.results.size, 1)
462
+ assert operation_results.has_errors?
463
+ end
464
+
465
+ def test_show_related_resources_operation
466
+ op = JSONAPI::OperationsProcessor.new
467
+
468
+ operations = [
469
+ JSONAPI::ShowRelatedResourcesOperation.new(PlanetResource,
470
+ {
471
+ source_klass: PlanetResource,
472
+ source_id: '1',
473
+ association_type: :moons})
474
+ ]
475
+
476
+ request = JSONAPI::Request.new
477
+ request.operations = operations
478
+
479
+ operation_results = op.process(request)
480
+
481
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
482
+ assert_equal(operation_results.results.size, 1)
483
+ refute operation_results.has_errors?
484
+ end
485
+
486
+ def test_show_related_resources_operation_error
487
+ op = JSONAPI::OperationsProcessor.new
488
+
489
+ operations = [
490
+ JSONAPI::ShowRelatedResourcesOperation.new(PlanetResource,
491
+ {
492
+ source_klass: PlanetResource,
493
+ source_id: '145',
494
+ association_type: :moons})
495
+ ]
496
+
497
+ request = JSONAPI::Request.new
498
+ request.operations = operations
499
+
500
+ operation_results = op.process(request)
501
+
502
+ assert_kind_of(JSONAPI::OperationResults, operation_results)
503
+ assert_equal(operation_results.results.size, 1)
504
+ assert operation_results.has_errors?
505
+ end
318
506
  end