jsonapi-resources 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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