jsonapi-resources 0.0.1
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 +7 -0
- data/.gitignore +20 -0
- data/Gemfile +22 -0
- data/LICENSE.txt +22 -0
- data/README.md +451 -0
- data/Rakefile +24 -0
- data/jsonapi-resources.gemspec +29 -0
- data/lib/jsonapi-resources.rb +2 -0
- data/lib/jsonapi/active_record_operations_processor.rb +17 -0
- data/lib/jsonapi/association.rb +45 -0
- data/lib/jsonapi/error.rb +17 -0
- data/lib/jsonapi/error_codes.rb +16 -0
- data/lib/jsonapi/exceptions.rb +177 -0
- data/lib/jsonapi/operation.rb +151 -0
- data/lib/jsonapi/operation_result.rb +15 -0
- data/lib/jsonapi/operations_processor.rb +47 -0
- data/lib/jsonapi/request.rb +254 -0
- data/lib/jsonapi/resource.rb +417 -0
- data/lib/jsonapi/resource_controller.rb +169 -0
- data/lib/jsonapi/resource_for.rb +25 -0
- data/lib/jsonapi/resource_serializer.rb +209 -0
- data/lib/jsonapi/resources/version.rb +5 -0
- data/lib/jsonapi/routing_ext.rb +104 -0
- data/test/config/database.yml +5 -0
- data/test/controllers/controller_test.rb +940 -0
- data/test/fixtures/active_record.rb +585 -0
- data/test/helpers/functional_helpers.rb +59 -0
- data/test/helpers/hash_helpers.rb +13 -0
- data/test/helpers/value_matchers.rb +60 -0
- data/test/helpers/value_matchers_test.rb +40 -0
- data/test/integration/requests/request_test.rb +39 -0
- data/test/integration/routes/routes_test.rb +85 -0
- data/test/test_helper.rb +98 -0
- data/test/unit/operation/operations_processor_test.rb +188 -0
- data/test/unit/resource/resource_test.rb +45 -0
- data/test/unit/serializer/serializer_test.rb +429 -0
- metadata +193 -0
@@ -0,0 +1,940 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
require File.expand_path('../../fixtures/active_record', __FILE__)
|
3
|
+
|
4
|
+
class PostsControllerTest < ActionController::TestCase
|
5
|
+
def test_index
|
6
|
+
get :index
|
7
|
+
assert_response :success
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_index_filter_by_id
|
11
|
+
get :index, {id: '1'}
|
12
|
+
assert_response :success
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_index_filter_by_title
|
16
|
+
get :index, {title: 'New post'}
|
17
|
+
assert_response :success
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_index_filter_by_ids
|
21
|
+
get :index, {ids: '1,2'}
|
22
|
+
assert_response :success
|
23
|
+
assert_equal 2, json_response['posts'].size
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_index_filter_by_ids_and_include_related
|
27
|
+
get :index, ids: '2', include: 'comments'
|
28
|
+
assert_response :success
|
29
|
+
assert_equal 1, json_response['posts'].size
|
30
|
+
assert_equal 1, json_response['linked']['comments'].size
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_index_filter_by_ids_and_include_related_different_type
|
34
|
+
get :index, {ids: '1,2', include: 'author'}
|
35
|
+
assert_response :success
|
36
|
+
assert_equal 2, json_response['posts'].size
|
37
|
+
assert_equal 1, json_response['linked']['people'].size
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_index_filter_by_ids_and_fields
|
41
|
+
get :index, {ids: '1,2', 'fields' => 'id,title,author'}
|
42
|
+
assert_response :success
|
43
|
+
assert_equal 2, json_response['posts'].size
|
44
|
+
|
45
|
+
# id, title, links
|
46
|
+
assert_equal 3, json_response['posts'][0].size
|
47
|
+
assert json_response['posts'][0].has_key?('id')
|
48
|
+
assert json_response['posts'][0].has_key?('title')
|
49
|
+
assert json_response['posts'][0].has_key?('links')
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_index_filter_by_ids_and_fields_specify_type
|
53
|
+
get :index, {ids: '1,2', 'fields' => {'posts' => 'id,title,author'}}
|
54
|
+
assert_response :success
|
55
|
+
assert_equal 2, json_response['posts'].size
|
56
|
+
|
57
|
+
# id, title, links
|
58
|
+
assert_equal 3, json_response['posts'][0].size
|
59
|
+
assert json_response['posts'][0].has_key?('id')
|
60
|
+
assert json_response['posts'][0].has_key?('title')
|
61
|
+
assert json_response['posts'][0].has_key?('links')
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_index_filter_by_ids_and_fields_specify_unrelated_type
|
65
|
+
get :index, {ids: '1,2', 'fields' => {'currencies' => 'code'}}
|
66
|
+
assert_response :bad_request
|
67
|
+
assert_match /currencies is not a valid resource./, json_response['errors'][0]['detail']
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_index_filter_by_ids_and_fields_2
|
71
|
+
get :index, {ids: '1,2', 'fields' => 'author'}
|
72
|
+
assert_response :success
|
73
|
+
assert_equal 2, json_response['posts'].size
|
74
|
+
|
75
|
+
# links
|
76
|
+
assert_equal 1, json_response['posts'][0].size
|
77
|
+
assert json_response['posts'][0].has_key?('links')
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_filter_association_single
|
81
|
+
get :index, {tags: '5,1'}
|
82
|
+
assert_response :success
|
83
|
+
assert_equal 3, json_response['posts'].size
|
84
|
+
assert_match /New post/, response.body
|
85
|
+
assert_match /JR Solves your serialization woes!/, response.body
|
86
|
+
assert_match /JR How To/, response.body
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_filter_associations_multiple
|
90
|
+
get :index, {tags: '5,1', comments: '3'}
|
91
|
+
assert_response :success
|
92
|
+
assert_equal 1, json_response['posts'].size
|
93
|
+
assert_match /JR Solves your serialization woes!/, response.body
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_filter_associations_multiple_not_found
|
97
|
+
get :index, {tags: '1', comments: '3'}
|
98
|
+
assert_response :success
|
99
|
+
assert_equal 0, json_response.size
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_bad_filter
|
103
|
+
get :index, {post_ids: '1,2'}
|
104
|
+
assert_response :bad_request
|
105
|
+
assert_match /post_ids is not allowed/, response.body
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_bad_filter_value_not_integer_array
|
109
|
+
get :index, {ids: 'asdfg'}
|
110
|
+
assert_response :bad_request
|
111
|
+
assert_match /asdfg is not a valid value for id/, response.body
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_bad_filter_value_not_integer
|
115
|
+
get :index, {id: 'asdfg'}
|
116
|
+
assert_response :bad_request
|
117
|
+
assert_match /asdfg is not a valid value for id/, response.body
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_bad_filter_value_not_found_array
|
121
|
+
get :index, {ids: '5412333'}
|
122
|
+
assert_response :not_found
|
123
|
+
assert_match /5412333 could not be found/, response.body
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_bad_filter_value_not_found
|
127
|
+
get :index, {id: '5412333'}
|
128
|
+
assert_response :not_found
|
129
|
+
assert_match /5412333 could not be found/, json_response['errors'][0]['detail']
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_index_malformed_fields
|
133
|
+
get :index, {ids: '1,2', 'fields' => 'posts'}
|
134
|
+
assert_response :bad_request
|
135
|
+
assert_match /posts is not a valid field for posts./, json_response['errors'][0]['detail']
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_field_not_supported
|
139
|
+
get :index, {ids: '1,2', 'fields' => {'posts' => 'id,title,rank,author'}}
|
140
|
+
assert_response :bad_request
|
141
|
+
assert_match /rank is not a valid field for posts./, json_response['errors'][0]['detail']
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_resource_not_supported
|
145
|
+
get :index, {ids: '1,2', 'fields' => {'posters' => 'id,title'}}
|
146
|
+
assert_response :bad_request
|
147
|
+
assert_match /posters is not a valid resource./, json_response['errors'][0]['detail']
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_index_filter_on_association
|
151
|
+
get :index, {author: '1'}
|
152
|
+
assert_response :success
|
153
|
+
assert_equal 3, json_response['posts'].size
|
154
|
+
end
|
155
|
+
|
156
|
+
# ToDo: test validating the parameter values
|
157
|
+
# def test_index_invalid_filter_value
|
158
|
+
# get :index, {ids: [1,'asdfg1']}
|
159
|
+
# assert_response :bad_request
|
160
|
+
# end
|
161
|
+
|
162
|
+
def test_show_single
|
163
|
+
get :show, {id: '1'}
|
164
|
+
assert_response :success
|
165
|
+
assert_equal 1, json_response['posts'].size
|
166
|
+
assert_equal 'New post', json_response['posts'][0]['title']
|
167
|
+
assert_equal 'A body!!!', json_response['posts'][0]['body']
|
168
|
+
assert_equal [1,2,3], json_response['posts'][0]['links']['tags']
|
169
|
+
assert_equal [1,2], json_response['posts'][0]['links']['comments']
|
170
|
+
assert_nil json_response['linked']
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_show_single_with_includes
|
174
|
+
get :show, {id: '1', include: 'comments'}
|
175
|
+
assert_response :success
|
176
|
+
assert_equal 1, json_response['posts'].size
|
177
|
+
assert_equal 'New post', json_response['posts'][0]['title']
|
178
|
+
assert_equal 'A body!!!', json_response['posts'][0]['body']
|
179
|
+
assert_equal [1,2,3], json_response['posts'][0]['links']['tags']
|
180
|
+
assert_equal [1,2], json_response['posts'][0]['links']['comments']
|
181
|
+
assert_equal 2, json_response['linked']['comments'].size
|
182
|
+
assert_nil json_response['linked']['tags']
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_show_single_with_fields
|
186
|
+
get :show, {id: '1', fields: 'author'}
|
187
|
+
assert_response :success
|
188
|
+
assert_equal 1, json_response['posts'].size
|
189
|
+
assert_nil json_response['posts'][0]['title']
|
190
|
+
assert_nil json_response['posts'][0]['body']
|
191
|
+
assert_equal 1, json_response['posts'][0]['links']['author']
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_show_single_invalid_id_format
|
195
|
+
get :show, {id: 'asdfg'}
|
196
|
+
assert_response :bad_request
|
197
|
+
assert_match /asdfg is not a valid value for id/, response.body
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_show_single_missing_record
|
201
|
+
get :show, {id: '5412333'}
|
202
|
+
assert_response :not_found
|
203
|
+
assert_match /record identified by 5412333 could not be found/, response.body
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_show_malformed_fields_not_list
|
207
|
+
get :show, {id: '1', 'fields' => ''}
|
208
|
+
assert_response :bad_request
|
209
|
+
assert_match /nil is not a valid field for posts./, json_response['errors'][0]['detail']
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_show_malformed_fields_type_not_list
|
213
|
+
get :show, {id: '1', 'fields' => {'posts' => ''}}
|
214
|
+
assert_response :bad_request
|
215
|
+
assert_match /nil is not a valid field for posts./, json_response['errors'][0]['detail']
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_create_simple
|
219
|
+
post :create, { posts: {
|
220
|
+
title: 'JR is Great',
|
221
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
|
222
|
+
links: {
|
223
|
+
author: 3
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
assert_response :created
|
229
|
+
assert_equal 1, json_response['posts'].size
|
230
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
231
|
+
assert_equal 'JR is Great', json_response['posts'][0]['title']
|
232
|
+
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['posts'][0]['body']
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_create_link_to_missing_object
|
236
|
+
post :create, { posts: {
|
237
|
+
title: 'JR is Great',
|
238
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
|
239
|
+
links: {
|
240
|
+
author: 304567
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
assert_response :bad_request
|
246
|
+
# Todo: check if this validation is working
|
247
|
+
assert_match /author - can't be blank/, response.body
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_create_extra_param
|
251
|
+
post :create, { posts: {
|
252
|
+
asdfg: 'aaaa',
|
253
|
+
title: 'JR is Great',
|
254
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
|
255
|
+
links: {
|
256
|
+
author: 3
|
257
|
+
}
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
261
|
+
assert_response :bad_request
|
262
|
+
assert_match /asdfg is not allowed/, response.body
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_create_multiple
|
266
|
+
post :create, { posts: [
|
267
|
+
{
|
268
|
+
title: 'JR is Great',
|
269
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
|
270
|
+
links: {
|
271
|
+
author: 3
|
272
|
+
}
|
273
|
+
},
|
274
|
+
{
|
275
|
+
title: 'Ember is Great',
|
276
|
+
body: 'Ember is the greatest thing since unsliced bread.',
|
277
|
+
links: {
|
278
|
+
author: 3
|
279
|
+
}
|
280
|
+
}
|
281
|
+
]
|
282
|
+
}
|
283
|
+
|
284
|
+
assert_response :created
|
285
|
+
assert_equal json_response['posts'].size, 2
|
286
|
+
assert_equal json_response['posts'][0]['links']['author'], 3
|
287
|
+
assert_match /JR is Great/, response.body
|
288
|
+
assert_match /Ember is Great/, response.body
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_create_simple_missing_posts
|
292
|
+
post :create, { posts_spelled_wrong: {
|
293
|
+
title: 'JR is Great',
|
294
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
|
295
|
+
links: {
|
296
|
+
author: 3
|
297
|
+
}
|
298
|
+
}
|
299
|
+
}
|
300
|
+
|
301
|
+
assert_response :bad_request
|
302
|
+
assert_match /The required parameter, posts, is missing./, json_response['errors'][0]['detail']
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_create_simple_unpermitted_attributes
|
306
|
+
post :create, { posts: {
|
307
|
+
subject: 'JR is Great',
|
308
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
|
309
|
+
links: {
|
310
|
+
author: 3
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
|
315
|
+
assert_response :bad_request
|
316
|
+
assert_match /subject/, json_response['errors'][0]['detail']
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_create_with_links
|
320
|
+
post :create, { posts: {
|
321
|
+
title: 'JR is Great',
|
322
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.',
|
323
|
+
links: {
|
324
|
+
author: 3,
|
325
|
+
tags: [3,4]
|
326
|
+
}
|
327
|
+
}
|
328
|
+
}
|
329
|
+
|
330
|
+
assert_response :created
|
331
|
+
assert_equal 1, json_response['posts'].size
|
332
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
333
|
+
assert_equal 'JR is Great', json_response['posts'][0]['title']
|
334
|
+
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['posts'][0]['body']
|
335
|
+
assert_equal [3,4], json_response['posts'][0]['links']['tags']
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_create_with_links_include_and_fields
|
339
|
+
post :create, { posts: {
|
340
|
+
title: 'JR is Great!',
|
341
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread!',
|
342
|
+
links: {
|
343
|
+
author: 3,
|
344
|
+
tags: [3,4]
|
345
|
+
}
|
346
|
+
},
|
347
|
+
include: 'author,author.posts',
|
348
|
+
fields: 'id,title,author'
|
349
|
+
}
|
350
|
+
|
351
|
+
assert_response :created
|
352
|
+
assert_equal 1, json_response['posts'].size
|
353
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
354
|
+
assert_equal 'JR is Great!', json_response['posts'][0]['title']
|
355
|
+
assert_equal nil, json_response['posts'][0]['body']
|
356
|
+
assert_equal nil, json_response['posts'][0]['links']['tags']
|
357
|
+
assert_not_nil json_response['linked']['posts']
|
358
|
+
assert_not_nil json_response['linked']['people']
|
359
|
+
assert_nil json_response['linked']['tags']
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_update_with_links
|
363
|
+
javascript = Section.find_by(name: 'javascript')
|
364
|
+
|
365
|
+
post :update, {id: 3, posts: {
|
366
|
+
title: 'A great new Post',
|
367
|
+
links: {
|
368
|
+
section: javascript.id,
|
369
|
+
tags: [3,4]
|
370
|
+
}
|
371
|
+
}
|
372
|
+
}
|
373
|
+
|
374
|
+
assert_response :success
|
375
|
+
assert_equal 1, json_response['posts'].size
|
376
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
377
|
+
assert_equal javascript.id, json_response['posts'][0]['links']['section']
|
378
|
+
assert_equal 'A great new Post', json_response['posts'][0]['title']
|
379
|
+
assert_equal 'AAAA', json_response['posts'][0]['body']
|
380
|
+
assert matches_array?([3,4], json_response['posts'][0]['links']['tags'])
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_update_remove_links
|
384
|
+
post :update, {id: 3, posts: {
|
385
|
+
title: 'A great new Post',
|
386
|
+
links: {
|
387
|
+
section: nil,
|
388
|
+
tags: []
|
389
|
+
}
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
assert_response :success
|
394
|
+
assert_equal 1, json_response['posts'].size
|
395
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
396
|
+
assert_equal nil, json_response['posts'][0]['links']['section']
|
397
|
+
assert_equal 'A great new Post', json_response['posts'][0]['title']
|
398
|
+
assert_equal 'AAAA', json_response['posts'][0]['body']
|
399
|
+
assert matches_array?([], json_response['posts'][0]['links']['tags'])
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_update_relationship_has_one
|
403
|
+
ruby = Section.find_by(name: 'ruby')
|
404
|
+
|
405
|
+
post :create_association, {post_id: 3, association: 'section',
|
406
|
+
section: ruby.id }
|
407
|
+
|
408
|
+
assert_response :success
|
409
|
+
assert_equal 1, json_response['posts'].size
|
410
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
411
|
+
assert_equal ruby.id, json_response['posts'][0]['links']['section']
|
412
|
+
assert_equal 'AAAA', json_response['posts'][0]['body']
|
413
|
+
end
|
414
|
+
|
415
|
+
def test_update_relationship_has_many_single
|
416
|
+
post :create_association, {post_id: 3, association: 'tags',
|
417
|
+
tags: [3] }
|
418
|
+
|
419
|
+
assert_response :success
|
420
|
+
post :create_association, {post_id: 3, association: 'tags',
|
421
|
+
tags: [2] }
|
422
|
+
|
423
|
+
assert_response :success
|
424
|
+
post :create_association, {post_id: 3, association: 'tags',
|
425
|
+
tags: [5] }
|
426
|
+
|
427
|
+
assert_response :success
|
428
|
+
post :create_association, {post_id: 3, association: 'tags',
|
429
|
+
tags: [5] }
|
430
|
+
|
431
|
+
assert_response :success
|
432
|
+
|
433
|
+
assert_equal 1, json_response['posts'].size
|
434
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
435
|
+
assert matches_array? [2,3,5], json_response['posts'][0]['links']['tags']
|
436
|
+
assert_equal 'AAAA', json_response['posts'][0]['body']
|
437
|
+
end
|
438
|
+
|
439
|
+
def test_update_relationship_has_many
|
440
|
+
post :create_association, {post_id: 3, association: 'tags',
|
441
|
+
tags: [2,3] }
|
442
|
+
|
443
|
+
assert_response :success
|
444
|
+
assert_equal 1, json_response['posts'].size
|
445
|
+
assert_equal 3, json_response['posts'][0]['links']['author']
|
446
|
+
assert matches_array? [2,3], json_response['posts'][0]['links']['tags']
|
447
|
+
assert_equal 'AAAA', json_response['posts'][0]['body']
|
448
|
+
end
|
449
|
+
|
450
|
+
def test_update_relationship_has_one_mismatch_params
|
451
|
+
ruby = Section.find_by(name: 'ruby')
|
452
|
+
|
453
|
+
post :create_association, {post_id: 3, association: 'section',
|
454
|
+
author: 1 }
|
455
|
+
|
456
|
+
assert_response :bad_request
|
457
|
+
assert_match /The required parameter, section, is missing./, response.body
|
458
|
+
end
|
459
|
+
|
460
|
+
def test_delete_relationship_has_one
|
461
|
+
ruby = Section.find_by(name: 'ruby')
|
462
|
+
|
463
|
+
post :create_association, {post_id: 9, association: 'section',
|
464
|
+
section: ruby.id }
|
465
|
+
|
466
|
+
assert_response :success
|
467
|
+
assert_equal ruby.id, json_response['posts'][0]['links']['section']
|
468
|
+
|
469
|
+
post :destroy_association, {post_id: 9, association: 'section'}
|
470
|
+
|
471
|
+
assert_response :no_content
|
472
|
+
post = Post.find(9)
|
473
|
+
assert_nil post.section
|
474
|
+
end
|
475
|
+
|
476
|
+
def test_delete_relationship_has_many
|
477
|
+
post :create_association, {post_id: 9, association: 'tags',
|
478
|
+
tags: [2,3] }
|
479
|
+
assert_response :success
|
480
|
+
p = Post.find(9)
|
481
|
+
assert_equal [2,3], p.tag_ids
|
482
|
+
|
483
|
+
post :destroy_association, {post_id: 9, association: 'tags', keys: '3'}
|
484
|
+
|
485
|
+
assert_response :no_content
|
486
|
+
assert_equal [2], p.tag_ids
|
487
|
+
end
|
488
|
+
|
489
|
+
|
490
|
+
def test_update_mismatched_keys
|
491
|
+
javascript = Section.find_by(name: 'javascript')
|
492
|
+
|
493
|
+
post :update, {id: 3, posts: {
|
494
|
+
id: 2,
|
495
|
+
title: 'A great new Post',
|
496
|
+
links: {
|
497
|
+
section: javascript.id,
|
498
|
+
tags: [3,4]
|
499
|
+
}
|
500
|
+
}
|
501
|
+
}
|
502
|
+
|
503
|
+
assert_response :bad_request
|
504
|
+
assert_match /The URL does not support the key 2/, response.body
|
505
|
+
end
|
506
|
+
|
507
|
+
def test_update_extra_param
|
508
|
+
javascript = Section.find_by(name: 'javascript')
|
509
|
+
|
510
|
+
post :update, {id: 3, posts: {
|
511
|
+
asdfg: 'aaaa',
|
512
|
+
title: 'A great new Post',
|
513
|
+
links: {
|
514
|
+
section: javascript.id,
|
515
|
+
tags: [3,4]
|
516
|
+
}
|
517
|
+
}
|
518
|
+
}
|
519
|
+
|
520
|
+
assert_response :bad_request
|
521
|
+
assert_match /asdfg is not allowed/, response.body
|
522
|
+
end
|
523
|
+
|
524
|
+
def test_update_extra_param_in_links
|
525
|
+
javascript = Section.find_by(name: 'javascript')
|
526
|
+
|
527
|
+
post :update, {id: 3, posts: {
|
528
|
+
title: 'A great new Post',
|
529
|
+
links: {
|
530
|
+
asdfg: 'aaaa',
|
531
|
+
section: javascript.id,
|
532
|
+
tags: [3,4]
|
533
|
+
}
|
534
|
+
}
|
535
|
+
}
|
536
|
+
|
537
|
+
assert_response :bad_request
|
538
|
+
assert_match /asdfg is not allowed/, response.body
|
539
|
+
end
|
540
|
+
|
541
|
+
def test_update_missing_param
|
542
|
+
javascript = Section.find_by(name: 'javascript')
|
543
|
+
|
544
|
+
post :update, {id: 3, posts_spelled_wrong: {
|
545
|
+
title: 'A great new Post',
|
546
|
+
links: {
|
547
|
+
section: javascript.id,
|
548
|
+
tags: [3,4]
|
549
|
+
}
|
550
|
+
}
|
551
|
+
}
|
552
|
+
|
553
|
+
assert_response :bad_request
|
554
|
+
assert_match /The required parameter, posts, is missing./, response.body
|
555
|
+
end
|
556
|
+
|
557
|
+
def test_update_multiple
|
558
|
+
javascript = Section.find_by(name: 'javascript')
|
559
|
+
|
560
|
+
post :update, {id: [3,9], posts: [
|
561
|
+
{
|
562
|
+
id: 3,
|
563
|
+
title: 'A great new Post QWERTY',
|
564
|
+
links: {
|
565
|
+
section: javascript.id,
|
566
|
+
tags: [3,4]
|
567
|
+
}
|
568
|
+
},
|
569
|
+
{
|
570
|
+
id: 9,
|
571
|
+
title: 'A great new Post ASDFG',
|
572
|
+
links: {
|
573
|
+
section: javascript.id,
|
574
|
+
tags: [3,4]
|
575
|
+
}
|
576
|
+
}
|
577
|
+
]}
|
578
|
+
|
579
|
+
assert_response :success
|
580
|
+
assert_equal json_response['posts'].size, 2
|
581
|
+
assert_equal json_response['posts'][0]['links']['author'], 3
|
582
|
+
assert_equal json_response['posts'][0]['links']['section'], javascript.id
|
583
|
+
assert_equal json_response['posts'][0]['title'], 'A great new Post QWERTY'
|
584
|
+
assert_equal json_response['posts'][0]['body'], 'AAAA'
|
585
|
+
assert_equal json_response['posts'][0]['links']['tags'], [3,4]
|
586
|
+
|
587
|
+
assert_equal json_response['posts'][1]['links']['author'], 3
|
588
|
+
assert_equal json_response['posts'][1]['links']['section'], javascript.id
|
589
|
+
assert_equal json_response['posts'][1]['title'], 'A great new Post ASDFG'
|
590
|
+
assert_equal json_response['posts'][1]['body'], 'AAAA'
|
591
|
+
assert_equal json_response['posts'][1]['links']['tags'], [3,4]
|
592
|
+
end
|
593
|
+
|
594
|
+
def test_update_multiple_missing_keys
|
595
|
+
javascript = Section.find_by(name: 'javascript')
|
596
|
+
|
597
|
+
post :update, {id: [3,9], posts: [
|
598
|
+
{
|
599
|
+
title: 'A great new Post ASDFG',
|
600
|
+
links: {
|
601
|
+
section: javascript.id,
|
602
|
+
tags: [3,4]
|
603
|
+
}
|
604
|
+
},
|
605
|
+
{
|
606
|
+
title: 'A great new Post QWERTY',
|
607
|
+
links: {
|
608
|
+
section: javascript.id,
|
609
|
+
tags: [3,4]
|
610
|
+
}
|
611
|
+
}
|
612
|
+
]}
|
613
|
+
|
614
|
+
assert_response :bad_request
|
615
|
+
assert_match /A key is required/, response.body
|
616
|
+
end
|
617
|
+
|
618
|
+
def test_update_mismatch_keys
|
619
|
+
javascript = Section.find_by(name: 'javascript')
|
620
|
+
|
621
|
+
post :update, {id: [3,9], posts: [
|
622
|
+
{
|
623
|
+
id: 3,
|
624
|
+
title: 'A great new Post ASDFG',
|
625
|
+
links: {
|
626
|
+
section: javascript.id,
|
627
|
+
tags: [3,4]
|
628
|
+
}
|
629
|
+
},
|
630
|
+
{
|
631
|
+
id: 8,
|
632
|
+
title: 'A great new Post QWERTY',
|
633
|
+
links: {
|
634
|
+
section: javascript.id,
|
635
|
+
tags: [3,4]
|
636
|
+
}
|
637
|
+
}
|
638
|
+
]}
|
639
|
+
|
640
|
+
assert_response :bad_request
|
641
|
+
assert_match /The URL does not support the key 8/, response.body
|
642
|
+
end
|
643
|
+
|
644
|
+
def test_update_multiple_count_mismatch
|
645
|
+
javascript = Section.find_by(name: 'javascript')
|
646
|
+
|
647
|
+
post :update, {id: [3,9,2], posts: [
|
648
|
+
{
|
649
|
+
id: 3,
|
650
|
+
title: 'A great new Post QWERTY',
|
651
|
+
links: {
|
652
|
+
section: javascript.id,
|
653
|
+
tags: [3,4]
|
654
|
+
}
|
655
|
+
},
|
656
|
+
{
|
657
|
+
id: 9,
|
658
|
+
title: 'A great new Post ASDFG',
|
659
|
+
links: {
|
660
|
+
section: javascript.id,
|
661
|
+
tags: [3,4]
|
662
|
+
}
|
663
|
+
}
|
664
|
+
]}
|
665
|
+
|
666
|
+
assert_response :bad_request
|
667
|
+
assert_match /Count to key mismatch/, response.body
|
668
|
+
end
|
669
|
+
|
670
|
+
def test_update_unpermitted_attributes
|
671
|
+
post :update, {id: 3, posts: {
|
672
|
+
subject: 'A great new Post',
|
673
|
+
links: {
|
674
|
+
author: 1,
|
675
|
+
tags: [3,4]
|
676
|
+
}
|
677
|
+
}
|
678
|
+
}
|
679
|
+
|
680
|
+
assert_response :bad_request
|
681
|
+
assert_match /author is not allowed./, response.body
|
682
|
+
assert_match /subject is not allowed./, response.body
|
683
|
+
end
|
684
|
+
|
685
|
+
def test_update_bad_attributes
|
686
|
+
post :update, {id: 3, posts: {
|
687
|
+
subject: 'A great new Post',
|
688
|
+
linked_objects: {
|
689
|
+
author: 1,
|
690
|
+
tags: [3,4]
|
691
|
+
}
|
692
|
+
}
|
693
|
+
}
|
694
|
+
|
695
|
+
assert_response :bad_request
|
696
|
+
end
|
697
|
+
|
698
|
+
def test_delete_single
|
699
|
+
initial_count = Post.count
|
700
|
+
post :destroy, {id: '4'}
|
701
|
+
assert_response :no_content
|
702
|
+
assert_equal initial_count - 1, Post.count
|
703
|
+
end
|
704
|
+
|
705
|
+
def test_delete_multiple
|
706
|
+
initial_count = Post.count
|
707
|
+
post :destroy, {id: '5,6'}
|
708
|
+
assert_response :no_content
|
709
|
+
assert_equal initial_count - 2, Post.count
|
710
|
+
end
|
711
|
+
|
712
|
+
def test_delete_multiple_one_does_not_exist
|
713
|
+
initial_count = Post.count
|
714
|
+
post :destroy, {id: '5,6,99999'}
|
715
|
+
assert_response :not_found
|
716
|
+
assert_equal initial_count, Post.count
|
717
|
+
end
|
718
|
+
|
719
|
+
def test_delete_extra_param
|
720
|
+
initial_count = Post.count
|
721
|
+
post :destroy, {id: '4', asdfg: 'aaaa'}
|
722
|
+
assert_response :bad_request
|
723
|
+
assert_equal initial_count, Post.count
|
724
|
+
end
|
725
|
+
|
726
|
+
def test_show_has_one_relationship
|
727
|
+
get :show_association, {post_id: '1', association: 'author'}
|
728
|
+
assert_response :success
|
729
|
+
assert_equal 1, json_response['author']
|
730
|
+
end
|
731
|
+
|
732
|
+
def test_show_has_many_relationship
|
733
|
+
get :show_association, {post_id: '1', association: 'tags'}
|
734
|
+
assert_response :success
|
735
|
+
assert_equal [1,2,3], json_response['tags']
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
739
|
+
class TagsControllerTest < ActionController::TestCase
|
740
|
+
def test_tags_index
|
741
|
+
get :index, {ids: '6,7,8,9', include: 'posts,posts.tags,posts.author.posts'}
|
742
|
+
assert_response :success
|
743
|
+
assert_equal 4, json_response['tags'].size
|
744
|
+
assert_equal 2, json_response['linked']['posts'].size
|
745
|
+
end
|
746
|
+
|
747
|
+
def test_tags_show_multiple
|
748
|
+
get :show, {id: '6,7,8,9'}
|
749
|
+
assert_response :success
|
750
|
+
assert_equal 4, json_response['tags'].size
|
751
|
+
end
|
752
|
+
|
753
|
+
def test_tags_show_multiple_with_include
|
754
|
+
get :show, {id: '6,7,8,9', include: 'posts,posts.tags,posts.author.posts'}
|
755
|
+
assert_response :success
|
756
|
+
assert_equal 4, json_response['tags'].size
|
757
|
+
assert_equal 2, json_response['linked']['posts'].size
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
class ExpenseEntriesControllerTest < ActionController::TestCase
|
762
|
+
def test_expense_entries_index
|
763
|
+
get :index
|
764
|
+
assert_response :success
|
765
|
+
assert_equal 2, json_response['expense_entries'].size
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
class CurrenciesControllerTest < ActionController::TestCase
|
770
|
+
def test_currencies_index
|
771
|
+
get :index
|
772
|
+
assert_response :success
|
773
|
+
assert_equal 2, json_response['currencies'].size
|
774
|
+
end
|
775
|
+
|
776
|
+
def test_currencies_show
|
777
|
+
get :show, {code: 'USD', include: 'expense_entries,expense_entries.currency_codes'}
|
778
|
+
assert_response :success
|
779
|
+
assert_equal 1, json_response['currencies'].size
|
780
|
+
assert_equal 2, json_response['linked']['expense_entries'].size
|
781
|
+
end
|
782
|
+
end
|
783
|
+
|
784
|
+
class PeopleControllerTest < ActionController::TestCase
|
785
|
+
def test_create_validations
|
786
|
+
post :create, { people: {
|
787
|
+
name: 'Steve Jobs',
|
788
|
+
email: 'sj@email.zzz',
|
789
|
+
date_joined: DateTime.parse('2014-1-30 4:20:00 UTC +00:00')
|
790
|
+
}
|
791
|
+
}
|
792
|
+
|
793
|
+
assert_response :success
|
794
|
+
end
|
795
|
+
|
796
|
+
def test_create_validations_missing_attribute
|
797
|
+
post :create, { people: {
|
798
|
+
email: 'sj@email.zzz'
|
799
|
+
}
|
800
|
+
}
|
801
|
+
|
802
|
+
assert_response :bad_request
|
803
|
+
assert_equal 2, json_response['errors'].size
|
804
|
+
assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code']
|
805
|
+
assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][1]['code']
|
806
|
+
assert_match /date_joined - can't be blank/, response.body
|
807
|
+
assert_match /name - can't be blank/, response.body
|
808
|
+
end
|
809
|
+
|
810
|
+
def test_update_validations_missing_attribute
|
811
|
+
post :update, { id: 3, people: {
|
812
|
+
name: ''
|
813
|
+
}
|
814
|
+
}
|
815
|
+
|
816
|
+
assert_response :bad_request
|
817
|
+
assert_equal 1, json_response['errors'].size
|
818
|
+
assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code']
|
819
|
+
assert_match /name - can't be blank/, response.body
|
820
|
+
end
|
821
|
+
|
822
|
+
def test_delete_locked
|
823
|
+
initial_count = Person.count
|
824
|
+
post :destroy, {id: '3'}
|
825
|
+
assert_response :locked
|
826
|
+
assert_equal initial_count, Person.count
|
827
|
+
end
|
828
|
+
|
829
|
+
def test_invalid_filter_value
|
830
|
+
get :index, {name: 'L'}
|
831
|
+
assert_response :bad_request
|
832
|
+
end
|
833
|
+
|
834
|
+
def test_valid_filter_value
|
835
|
+
get :index, {name: 'Joe Author'}
|
836
|
+
assert_response :success
|
837
|
+
assert_equal json_response['people'].size, 1
|
838
|
+
assert_equal json_response['people'][0]['id'], 1
|
839
|
+
assert_equal json_response['people'][0]['name'], 'Joe Author'
|
840
|
+
end
|
841
|
+
end
|
842
|
+
|
843
|
+
class AuthorsControllerTest < ActionController::TestCase
|
844
|
+
def test_get_person_as_author
|
845
|
+
get :index, {id: '1'}
|
846
|
+
assert_response :success
|
847
|
+
assert_equal 1, json_response['authors'].size
|
848
|
+
assert_equal 1, json_response['authors'][0]['id']
|
849
|
+
assert_equal 'Joe Author', json_response['authors'][0]['name']
|
850
|
+
assert_equal nil, json_response['authors'][0]['email']
|
851
|
+
assert_equal 1, json_response['authors'][0]['links'].size
|
852
|
+
assert_equal 3, json_response['authors'][0]['links']['posts'].size
|
853
|
+
end
|
854
|
+
|
855
|
+
def test_get_person_as_author_variable_email
|
856
|
+
get :index, {id: '4'}
|
857
|
+
assert_response :success
|
858
|
+
assert_equal 1, json_response['authors'].size
|
859
|
+
assert_equal 4, json_response['authors'][0]['id']
|
860
|
+
assert_equal 'Tag Crazy Author', json_response['authors'][0]['name']
|
861
|
+
assert_equal 'taggy@xyz.fake', json_response['authors'][0]['email']
|
862
|
+
assert_equal 1, json_response['authors'][0]['links'].size
|
863
|
+
assert_equal 2, json_response['authors'][0]['links']['posts'].size
|
864
|
+
end
|
865
|
+
|
866
|
+
def test_get_person_as_author_by_name_filter
|
867
|
+
get :index, {name: 'thor'}
|
868
|
+
assert_response :success
|
869
|
+
assert_equal 3, json_response['authors'].size
|
870
|
+
assert_equal 1, json_response['authors'][0]['id']
|
871
|
+
assert_equal 'Joe Author', json_response['authors'][0]['name']
|
872
|
+
assert_equal 1, json_response['authors'][0]['links'].size
|
873
|
+
assert_equal 3, json_response['authors'][0]['links']['posts'].size
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
class BreedsControllerTest < ActionController::TestCase
|
878
|
+
def test_poro_index
|
879
|
+
get :index
|
880
|
+
assert_response :success
|
881
|
+
assert_equal 0, json_response['breeds'][0]['id']
|
882
|
+
assert_equal 'persian', json_response['breeds'][0]['name']
|
883
|
+
end
|
884
|
+
|
885
|
+
def test_poro_show
|
886
|
+
get :show, {id: '0'}
|
887
|
+
assert_response :success
|
888
|
+
assert_equal 1, json_response['breeds'].size
|
889
|
+
assert_equal 0, json_response['breeds'][0]['id']
|
890
|
+
assert_equal 'persian', json_response['breeds'][0]['name']
|
891
|
+
end
|
892
|
+
|
893
|
+
def test_poro_show_multiple
|
894
|
+
get :show, {id: '0,2'}
|
895
|
+
assert_response :success
|
896
|
+
assert_equal 2, json_response['breeds'].size
|
897
|
+
assert_equal 0, json_response['breeds'][0]['id']
|
898
|
+
assert_equal 'persian', json_response['breeds'][0]['name']
|
899
|
+
assert_equal 2, json_response['breeds'][1]['id']
|
900
|
+
assert_equal 'sphinx', json_response['breeds'][1]['name']
|
901
|
+
end
|
902
|
+
|
903
|
+
def test_poro_create_simple
|
904
|
+
post :create, { breeds: {
|
905
|
+
name: 'tabby'
|
906
|
+
}
|
907
|
+
}
|
908
|
+
|
909
|
+
assert_response :created
|
910
|
+
assert_equal 1, json_response['breeds'].size
|
911
|
+
assert_equal 'tabby', json_response['breeds'][0]['name']
|
912
|
+
end
|
913
|
+
|
914
|
+
def test_poro_create_update
|
915
|
+
post :create, { breeds: {
|
916
|
+
name: 'calic'
|
917
|
+
}
|
918
|
+
}
|
919
|
+
|
920
|
+
assert_response :created
|
921
|
+
assert_equal 1, json_response['breeds'].size
|
922
|
+
assert_equal 'calic', json_response['breeds'][0]['name']
|
923
|
+
|
924
|
+
post :update, {id: json_response['breeds'][0]['id'], breeds: {
|
925
|
+
name: 'calico'
|
926
|
+
}
|
927
|
+
}
|
928
|
+
assert_response :success
|
929
|
+
assert_equal 1, json_response['breeds'].size
|
930
|
+
assert_equal 'calico', json_response['breeds'][0]['name']
|
931
|
+
end
|
932
|
+
|
933
|
+
def test_poro_delete
|
934
|
+
initial_count = $breed_data.breeds.keys.count
|
935
|
+
post :destroy, {id: '3'}
|
936
|
+
assert_response :no_content
|
937
|
+
assert_equal initial_count - 1, $breed_data.breeds.keys.count
|
938
|
+
end
|
939
|
+
|
940
|
+
end
|