jsonapi-resources 0.7.1.beta1 → 0.7.1.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +248 -74
  3. data/lib/jsonapi-resources.rb +5 -3
  4. data/lib/jsonapi/acts_as_resource_controller.rb +77 -14
  5. data/lib/jsonapi/configuration.rb +77 -16
  6. data/lib/jsonapi/error.rb +12 -0
  7. data/lib/jsonapi/error_codes.rb +2 -0
  8. data/lib/jsonapi/exceptions.rb +29 -9
  9. data/lib/jsonapi/formatter.rb +29 -4
  10. data/lib/jsonapi/link_builder.rb +18 -18
  11. data/lib/jsonapi/mime_types.rb +25 -6
  12. data/lib/jsonapi/naive_cache.rb +30 -0
  13. data/lib/jsonapi/operation.rb +10 -342
  14. data/lib/jsonapi/operation_dispatcher.rb +87 -0
  15. data/lib/jsonapi/operation_result.rb +2 -1
  16. data/lib/jsonapi/paginator.rb +6 -2
  17. data/lib/jsonapi/processor.rb +283 -0
  18. data/lib/jsonapi/relationship.rb +6 -4
  19. data/lib/jsonapi/{request.rb → request_parser.rb} +46 -35
  20. data/lib/jsonapi/resource.rb +88 -13
  21. data/lib/jsonapi/resource_controller.rb +2 -14
  22. data/lib/jsonapi/resource_controller_metal.rb +17 -0
  23. data/lib/jsonapi/resource_serializer.rb +62 -47
  24. data/lib/jsonapi/resources/version.rb +1 -1
  25. data/lib/jsonapi/response_document.rb +13 -2
  26. data/lib/jsonapi/routing_ext.rb +49 -11
  27. metadata +37 -129
  28. data/.gitignore +0 -22
  29. data/.travis.yml +0 -9
  30. data/Gemfile +0 -23
  31. data/Rakefile +0 -20
  32. data/jsonapi-resources.gemspec +0 -29
  33. data/lib/jsonapi/active_record_operations_processor.rb +0 -35
  34. data/lib/jsonapi/operations_processor.rb +0 -120
  35. data/locales/en.yml +0 -80
  36. data/test/config/database.yml +0 -5
  37. data/test/controllers/controller_test.rb +0 -3312
  38. data/test/fixtures/active_record.rb +0 -1486
  39. data/test/fixtures/author_details.yml +0 -9
  40. data/test/fixtures/book_authors.yml +0 -3
  41. data/test/fixtures/book_comments.yml +0 -12
  42. data/test/fixtures/books.yml +0 -7
  43. data/test/fixtures/categories.yml +0 -35
  44. data/test/fixtures/comments.yml +0 -21
  45. data/test/fixtures/comments_tags.yml +0 -20
  46. data/test/fixtures/companies.yml +0 -4
  47. data/test/fixtures/craters.yml +0 -9
  48. data/test/fixtures/customers.yml +0 -11
  49. data/test/fixtures/documents.yml +0 -3
  50. data/test/fixtures/expense_entries.yml +0 -13
  51. data/test/fixtures/facts.yml +0 -11
  52. data/test/fixtures/hair_cuts.yml +0 -3
  53. data/test/fixtures/iso_currencies.yml +0 -17
  54. data/test/fixtures/line_items.yml +0 -37
  55. data/test/fixtures/makes.yml +0 -2
  56. data/test/fixtures/moons.yml +0 -6
  57. data/test/fixtures/numeros_telefone.yml +0 -3
  58. data/test/fixtures/order_flags.yml +0 -7
  59. data/test/fixtures/people.yml +0 -31
  60. data/test/fixtures/pictures.yml +0 -15
  61. data/test/fixtures/planet_types.yml +0 -19
  62. data/test/fixtures/planets.yml +0 -47
  63. data/test/fixtures/posts.yml +0 -102
  64. data/test/fixtures/posts_tags.yml +0 -59
  65. data/test/fixtures/preferences.yml +0 -14
  66. data/test/fixtures/products.yml +0 -3
  67. data/test/fixtures/purchase_orders.yml +0 -23
  68. data/test/fixtures/sections.yml +0 -8
  69. data/test/fixtures/tags.yml +0 -39
  70. data/test/fixtures/vehicles.yml +0 -17
  71. data/test/fixtures/web_pages.yml +0 -3
  72. data/test/helpers/assertions.rb +0 -13
  73. data/test/helpers/functional_helpers.rb +0 -59
  74. data/test/helpers/value_matchers.rb +0 -60
  75. data/test/helpers/value_matchers_test.rb +0 -40
  76. data/test/integration/requests/namespaced_model_test.rb +0 -13
  77. data/test/integration/requests/request_test.rb +0 -932
  78. data/test/integration/routes/routes_test.rb +0 -218
  79. data/test/integration/sti_fields_test.rb +0 -18
  80. data/test/lib/generators/jsonapi/controller_generator_test.rb +0 -25
  81. data/test/lib/generators/jsonapi/resource_generator_test.rb +0 -30
  82. data/test/test_helper.rb +0 -342
  83. data/test/unit/formatters/dasherized_key_formatter_test.rb +0 -8
  84. data/test/unit/jsonapi_request/jsonapi_request_test.rb +0 -199
  85. data/test/unit/operation/operations_processor_test.rb +0 -528
  86. data/test/unit/pagination/offset_paginator_test.rb +0 -245
  87. data/test/unit/pagination/paged_paginator_test.rb +0 -242
  88. data/test/unit/resource/resource_test.rb +0 -560
  89. data/test/unit/serializer/include_directives_test.rb +0 -113
  90. data/test/unit/serializer/link_builder_test.rb +0 -244
  91. data/test/unit/serializer/polymorphic_serializer_test.rb +0 -383
  92. data/test/unit/serializer/response_document_test.rb +0 -61
  93. data/test/unit/serializer/serializer_test.rb +0 -1939
@@ -1,35 +0,0 @@
1
- class ActiveRecordOperationsProcessor < JSONAPI::OperationsProcessor
2
- private
3
-
4
- def transaction
5
- if @transactional
6
- ActiveRecord::Base.transaction do
7
- yield
8
- end
9
- else
10
- yield
11
- end
12
- end
13
-
14
- def rollback
15
- fail ActiveRecord::Rollback if @transactional
16
- end
17
-
18
- # Catch errors that should be handled before JSONAPI::Exceptions::Error
19
- # and other unprocessed exceptions
20
- def process_operation(operation)
21
- with_default_handling do
22
- begin
23
- operation.apply
24
- rescue ActiveRecord::DeleteRestrictionError => e
25
- record_locked_error = JSONAPI::Exceptions::RecordLocked.new(e.message)
26
- return JSONAPI::ErrorsOperationResult.new(record_locked_error.errors[0].code, record_locked_error.errors)
27
-
28
- rescue ActiveRecord::RecordNotFound
29
- key = operation.respond_to?(:associated_key) ? operation.associated_key : :unavailable
30
- record_not_found = JSONAPI::Exceptions::RecordNotFound.new(key)
31
- return JSONAPI::ErrorsOperationResult.new(record_not_found.errors[0].code, record_not_found.errors)
32
- end
33
- end
34
- end
35
- end
@@ -1,120 +0,0 @@
1
- module JSONAPI
2
- class OperationsProcessor
3
- include Callbacks
4
- define_jsonapi_resources_callbacks :operation,
5
- :operations,
6
- :find_operation,
7
- :show_operation,
8
- :show_relationship_operation,
9
- :show_related_resource_operation,
10
- :show_related_resources_operation,
11
- :create_resource_operation,
12
- :remove_resource_operation,
13
- :replace_fields_operation,
14
- :replace_to_one_relationship_operation,
15
- :replace_polymorphic_to_one_relationship_operation,
16
- :create_to_many_relationship_operation,
17
- :replace_to_many_relationship_operation,
18
- :remove_to_many_relationship_operation,
19
- :remove_to_one_relationship_operation
20
-
21
- class << self
22
- def operations_processor_for(operations_processor)
23
- operations_processor_class_name = "#{operations_processor.to_s.camelize}OperationsProcessor"
24
- operations_processor_class_name.safe_constantize
25
- end
26
- end
27
-
28
- def process(request)
29
- @results = JSONAPI::OperationResults.new
30
- @request = request
31
- @operations = request.operations
32
-
33
- # Use transactions if more than one operation and if one of the operations can be transactional
34
- # Even if transactional transactions won't be used unless the derived OperationsProcessor supports them.
35
- @transactional = false
36
- @operations.each do |operation|
37
- @transactional |= operation.transactional
38
- end
39
-
40
- run_callbacks :operations do
41
- transaction do
42
- # Links and meta data global to the set of operations
43
- @operations_meta = {}
44
- @operations_links = {}
45
- @operations.each do |operation|
46
- @operation = operation
47
- # Links and meta data for each operation
48
- @operation_meta = {}
49
- @operation_links = {}
50
- run_callbacks :operation do
51
- @result = nil
52
- run_callbacks @operation.class.name.demodulize.underscore.to_sym do
53
- @result = process_operation(@operation)
54
- end
55
- @result.meta.merge!(@operation_meta)
56
- @result.links.merge!(@operation_links)
57
- @results.add_result(@result)
58
- rollback if @results.has_errors?
59
- end
60
- end
61
- @results.meta = @operations_meta
62
- @results.links = @operations_links
63
- end
64
- end
65
- @results
66
- end
67
-
68
- private
69
-
70
- # The base OperationsProcessor provides no transaction support
71
- # Override the transaction and rollback methods to provide transaction support.
72
- # For ActiveRecord transactions you can use the ActiveRecordOperationsProcessor
73
- def transaction
74
- yield
75
- end
76
-
77
- def rollback
78
- end
79
-
80
- # If overriding in child operation processors, call operation.apply and
81
- # catch errors that should be handled before JSONAPI::Exceptions::Error
82
- # and other unprocessed exceptions
83
- def process_operation(operation)
84
- with_default_handling do
85
- operation.apply
86
- end
87
- end
88
-
89
- def with_default_handling(&block)
90
- yield
91
- rescue JSONAPI::Exceptions::Error => e
92
- raise e
93
-
94
- rescue => e
95
- if JSONAPI.configuration.exception_class_whitelist.any? { |k| e.class.ancestors.include?(k) }
96
- raise e
97
- else
98
- @request.server_error_callbacks.each { |callback| safe_run_callback(callback, e) }
99
-
100
- internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
101
- Rails.logger.error { "Internal Server Error: #{e.message} #{e.backtrace.join("\n")}" }
102
- return JSONAPI::ErrorsOperationResult.new(internal_server_error.errors[0].code, internal_server_error.errors)
103
- end
104
- end
105
-
106
- def safe_run_callback(callback, error)
107
- begin
108
- callback.call(error)
109
- rescue => e
110
- Rails.logger.error { "Error in error handling callback: #{e.message} #{e.backtrace.join("\n")}" }
111
- internal_server_error = JSONAPI::Exceptions::InternalServerError.new(e)
112
- return JSONAPI::ErrorsOperationResult.new(internal_server_error.errors[0].code, internal_server_error.errors)
113
- end
114
- end
115
-
116
- end
117
- end
118
-
119
- class BasicOperationsProcessor < JSONAPI::OperationsProcessor
120
- end
@@ -1,80 +0,0 @@
1
- en:
2
- jsonapi-resources:
3
- exceptions:
4
- internal_server_error:
5
- title: 'Internal Server Error'
6
- detail: 'Internal Server Error'
7
- invalid_resource:
8
- title: 'Invalid resource'
9
- detail: "%{resource} is not a valid resource."
10
- record_not_found:
11
- title: 'Record not found'
12
- detail: "The record identified by %{id} could not be found."
13
- unsupported_media_type:
14
- title: 'Unsupported media type'
15
- detail: "All requests that create or update must use the '%{needed_media_type}' Content-Type. This request specified '%{media_type}.'"
16
- has_many_relation:
17
- title: 'Relation exists'
18
- detail: "The relation to %{id} already exists."
19
- to_many_set_replacement_forbidden:
20
- title: 'Complete replacement forbidden'
21
- detail: 'Complete replacement forbidden for this relationship'
22
- invalid_filter_syntax:
23
- title: 'Invalid filters syntax'
24
- detail: "%{filters} is not a valid syntax for filtering."
25
- filter_not_allowed:
26
- title: "Filter not allowed"
27
- detail: "%{filter} is not allowed."
28
- invalid_filter_value:
29
- title: 'Invalid filter value'
30
- detail: "%{value} is not a valid value for %{filter}."
31
- invalid_field_value:
32
- title: 'Invalid field value'
33
- detail: "%{value} is not a valid value for %{field}."
34
- invalid_field_format:
35
- title: 'Invalid field format'
36
- detail: 'Fields must specify a type.'
37
- invalid_links_object:
38
- title: 'Invalid Links Object'
39
- detail: 'Data is not a valid Links Object.'
40
- type_mismatch:
41
- title: 'Type Mismatch'
42
- detail: "%{type} is not a valid type for this operation."
43
- invalid_field:
44
- title: 'Invalid field'
45
- detail: "%{field} is not a valid field for %{type}."
46
- invalid_include:
47
- title: 'Invalid field'
48
- detail: "%{relationship} is not a valid relationship of %{resource}"
49
- invalid_sort_criteria:
50
- title: 'Invalid sort criteria'
51
- detail: "%{sort_criteria} is not a valid sort criteria for %{resource}"
52
- parameters_not_allowed:
53
- title: 'Param not allowed'
54
- detail: "%{param} is not allowed."
55
- parameter_missing:
56
- title: 'Missing Parameter'
57
- detail: "The required parameter, %{param}, is missing."
58
- count_mismatch:
59
- title: 'Count to key mismatch'
60
- detail: 'The resource collection does not contain the same number of objects as the number of keys.'
61
- key_not_included_in_url:
62
- title: 'Key is not included in URL'
63
- detail: "The URL does not support the key %{key}"
64
- missing_key:
65
- title: 'A key is required'
66
- detail: 'The resource object does not contain a key.'
67
- record_locked:
68
- title: 'Locked resource'
69
- save_failed:
70
- title: 'Save failed or was cancelled'
71
- detail: 'Save failed or was cancelled'
72
- invalid_page_object:
73
- title: 'Invalid Page Object'
74
- detail: 'Invalid Page Object.'
75
- page_parameters_not_allowed:
76
- title: 'Page parameter not allowed'
77
- detail: "%{param} is not an allowed page parameter."
78
- invalid_page_value:
79
- title: 'Invalid page value'
80
- detail: "%{value} is not a valid value for %{page} page parameter."
@@ -1,5 +0,0 @@
1
- test:
2
- adapter: sqlite3
3
- database: test_db
4
- pool: 5
5
- timeout: 5000
@@ -1,3312 +0,0 @@
1
- require File.expand_path('../../test_helper', __FILE__)
2
-
3
- def set_content_type_header!
4
- @request.headers['Content-Type'] = JSONAPI::MEDIA_TYPE
5
- end
6
-
7
- class PostsControllerTest < ActionController::TestCase
8
- def setup
9
- JSONAPI.configuration.raise_if_parameters_not_allowed = true
10
- end
11
-
12
- def test_index
13
- get :index
14
- assert_response :success
15
- assert json_response['data'].is_a?(Array)
16
- end
17
-
18
- def test_exception_class_whitelist
19
- original_config = JSONAPI.configuration.dup
20
- JSONAPI.configuration.operations_processor = :error_raising
21
- # test that the operations processor rescues the error when it
22
- # has not been added to the exception_class_whitelist
23
- get :index
24
- assert_response 500
25
- # test that the operations processor does not rescue the error when it
26
- # has been added to the exception_class_whitelist
27
- JSONAPI.configuration.exception_class_whitelist << PostsController::SpecialError
28
- get :index
29
- assert_response 403
30
- ensure
31
- JSONAPI.configuration = original_config
32
- end
33
-
34
- def test_on_server_error_block_callback_with_exception
35
- original_config = JSONAPI.configuration.dup
36
- JSONAPI.configuration.operations_processor = :error_raising
37
- JSONAPI.configuration.exception_class_whitelist = []
38
-
39
- @controller.class.instance_variable_set(:@callback_message, "none")
40
- BaseController.on_server_error do
41
- @controller.class.instance_variable_set(:@callback_message, "Sent from block")
42
- end
43
-
44
- get :index
45
- assert_equal @controller.class.instance_variable_get(:@callback_message), "Sent from block"
46
-
47
- # test that it renders the default server error response
48
- assert_equal "Internal Server Error", json_response['errors'][0]['title']
49
- assert_equal "Internal Server Error", json_response['errors'][0]['detail']
50
- ensure
51
- JSONAPI.configuration = original_config
52
- end
53
-
54
- def test_on_server_error_method_callback_with_exception
55
- original_config = JSONAPI.configuration.dup
56
- JSONAPI.configuration.operations_processor = :error_raising
57
- JSONAPI.configuration.exception_class_whitelist = []
58
-
59
- #ignores methods that don't exist
60
- @controller.class.on_server_error :set_callback_message, :a_bogus_method
61
- @controller.class.instance_variable_set(:@callback_message, "none")
62
-
63
- get :index
64
- assert_equal @controller.class.instance_variable_get(:@callback_message), "Sent from method"
65
-
66
- # test that it renders the default server error response
67
- assert_equal "Internal Server Error", json_response['errors'][0]['title']
68
- ensure
69
- JSONAPI.configuration = original_config
70
- end
71
-
72
- def test_on_server_error_callback_without_exception
73
-
74
- callback = Proc.new { @controller.class.instance_variable_set(:@callback_message, "Sent from block") }
75
- @controller.class.on_server_error callback
76
- @controller.class.instance_variable_set(:@callback_message, "none")
77
-
78
- get :index
79
- assert_equal @controller.class.instance_variable_get(:@callback_message), "none"
80
-
81
- # test that it does not render error
82
- assert json_response.key?('data')
83
- end
84
-
85
- def test_index_filter_with_empty_result
86
- get :index, {filter: {title: 'post that does not exist'}}
87
- assert_response :success
88
- assert json_response['data'].is_a?(Array)
89
- assert_equal 0, json_response['data'].size
90
- end
91
-
92
- def test_index_filter_by_id
93
- get :index, {filter: {id: '1'}}
94
- assert_response :success
95
- assert json_response['data'].is_a?(Array)
96
- assert_equal 1, json_response['data'].size
97
- end
98
-
99
- def test_index_filter_by_title
100
- get :index, {filter: {title: 'New post'}}
101
- assert_response :success
102
- assert json_response['data'].is_a?(Array)
103
- assert_equal 1, json_response['data'].size
104
- end
105
-
106
- def test_index_filter_by_ids
107
- get :index, {filter: {ids: '1,2'}}
108
- assert_response :success
109
- assert json_response['data'].is_a?(Array)
110
- assert_equal 2, json_response['data'].size
111
- end
112
-
113
- def test_index_filter_by_ids_and_include_related
114
- get :index, {filter: {id: '2'}, include: 'comments'}
115
- assert_response :success
116
- assert_equal 1, json_response['data'].size
117
- assert_equal 1, json_response['included'].size
118
- end
119
-
120
- def test_index_filter_by_ids_and_include_related_different_type
121
- get :index, {filter: {id: '1,2'}, include: 'author'}
122
- assert_response :success
123
- assert_equal 2, json_response['data'].size
124
- assert_equal 1, json_response['included'].size
125
- end
126
-
127
- def test_index_filter_not_allowed
128
- JSONAPI.configuration.allow_filter = false
129
- get :index, {filter: {id: '1'}}
130
- assert_response :bad_request
131
- ensure
132
- JSONAPI.configuration.allow_filter = true
133
- end
134
-
135
- def test_index_include_one_level_query_count
136
- count_queries do
137
- get :index, {include: 'author'}
138
- end
139
- assert_response :success
140
- assert_query_count(2)
141
- end
142
-
143
- def test_index_include_two_levels_query_count
144
- count_queries do
145
- get :index, {include: 'author,author.comments'}
146
- end
147
- assert_response :success
148
- assert_query_count(3)
149
- end
150
-
151
- def test_index_filter_by_ids_and_fields
152
- get :index, {filter: {id: '1,2'}, fields: {posts: 'id,title,author'}}
153
- assert_response :success
154
- assert_equal 2, json_response['data'].size
155
-
156
- # type, id, links, attributes, relationships
157
- assert_equal 5, json_response['data'][0].size
158
- assert json_response['data'][0].key?('type')
159
- assert json_response['data'][0].key?('id')
160
- assert json_response['data'][0]['attributes'].key?('title')
161
- assert json_response['data'][0].key?('links')
162
- end
163
-
164
- def test_index_filter_by_ids_and_fields_specify_type
165
- get :index, {filter: {id: '1,2'}, 'fields' => {'posts' => 'id,title,author'}}
166
- assert_response :success
167
- assert_equal 2, json_response['data'].size
168
-
169
- # type, id, links, attributes, relationships
170
- assert_equal 5, json_response['data'][0].size
171
- assert json_response['data'][0].key?('type')
172
- assert json_response['data'][0].key?('id')
173
- assert json_response['data'][0]['attributes'].key?('title')
174
- assert json_response['data'][0].key?('links')
175
- end
176
-
177
- def test_index_filter_by_ids_and_fields_specify_unrelated_type
178
- get :index, {filter: {id: '1,2'}, 'fields' => {'currencies' => 'code'}}
179
- assert_response :bad_request
180
- assert_match /currencies is not a valid resource./, json_response['errors'][0]['detail']
181
- end
182
-
183
- def test_index_filter_by_ids_and_fields_2
184
- get :index, {filter: {id: '1,2'}, fields: {posts: 'author'}}
185
- assert_response :success
186
- assert_equal 2, json_response['data'].size
187
-
188
- # type, id, links, relationships
189
- assert_equal 4, json_response['data'][0].size
190
- assert json_response['data'][0].key?('type')
191
- assert json_response['data'][0].key?('id')
192
- assert json_response['data'][0]['relationships'].key?('author')
193
- end
194
-
195
- def test_filter_relationship_single
196
- count_queries do
197
- get :index, {filter: {tags: '5,1'}}
198
- end
199
- assert_query_count(1)
200
- assert_response :success
201
- assert_equal 3, json_response['data'].size
202
- assert_match /New post/, response.body
203
- assert_match /JR Solves your serialization woes!/, response.body
204
- assert_match /JR How To/, response.body
205
- end
206
-
207
- def test_filter_relationships_multiple
208
- count_queries do
209
- get :index, {filter: {tags: '5,1', comments: '3'}}
210
- end
211
- assert_query_count(1)
212
- assert_response :success
213
- assert_equal 1, json_response['data'].size
214
- assert_match /JR Solves your serialization woes!/, response.body
215
- end
216
-
217
- def test_filter_relationships_multiple_not_found
218
- get :index, {filter: {tags: '1', comments: '3'}}
219
- assert_response :success
220
- assert_equal 0, json_response['data'].size
221
- end
222
-
223
- def test_bad_filter
224
- get :index, {filter: {post_ids: '1,2'}}
225
- assert_response :bad_request
226
- assert_match /post_ids is not allowed/, response.body
227
- end
228
-
229
- def test_bad_filter_value_not_integer_array
230
- get :index, {filter: {id: 'asdfg'}}
231
- assert_response :bad_request
232
- assert_match /asdfg is not a valid value for id/, response.body
233
- end
234
-
235
- def test_bad_filter_value_not_integer
236
- get :index, {filter: {id: 'asdfg'}}
237
- assert_response :bad_request
238
- assert_match /asdfg is not a valid value for id/, response.body
239
- end
240
-
241
- def test_bad_filter_value_not_found_array
242
- get :index, {filter: {id: '5412333'}}
243
- assert_response :not_found
244
- assert_match /5412333 could not be found/, response.body
245
- end
246
-
247
- def test_bad_filter_value_not_found
248
- get :index, {filter: {id: '5412333'}}
249
- assert_response :not_found
250
- assert_match /5412333 could not be found/, json_response['errors'][0]['detail']
251
- end
252
-
253
- def test_field_not_supported
254
- get :index, {filter: {id: '1,2'}, 'fields' => {'posts' => 'id,title,rank,author'}}
255
- assert_response :bad_request
256
- assert_match /rank is not a valid field for posts./, json_response['errors'][0]['detail']
257
- end
258
-
259
- def test_resource_not_supported
260
- get :index, {filter: {id: '1,2'}, 'fields' => {'posters' => 'id,title'}}
261
- assert_response :bad_request
262
- assert_match /posters is not a valid resource./, json_response['errors'][0]['detail']
263
- end
264
-
265
- def test_index_filter_on_relationship
266
- get :index, {filter: {author: '1'}}
267
- assert_response :success
268
- assert_equal 3, json_response['data'].size
269
- end
270
-
271
- def test_sorting_blank
272
- get :index, {sort: ''}
273
-
274
- assert_response :success
275
- end
276
-
277
- def test_sorting_asc
278
- get :index, {sort: 'title'}
279
-
280
- assert_response :success
281
- assert_equal "A First Post", json_response['data'][0]['attributes']['title']
282
- end
283
-
284
- def test_sorting_desc
285
- get :index, {sort: '-title'}
286
-
287
- assert_response :success
288
- assert_equal "Update This Later - Multiple", json_response['data'][0]['attributes']['title']
289
- end
290
-
291
- def test_sorting_by_multiple_fields
292
- get :index, {sort: 'title,body'}
293
-
294
- assert_response :success
295
- assert_equal '14', json_response['data'][0]['id']
296
- end
297
-
298
- def test_invalid_sort_param
299
- get :index, {sort: 'asdfg'}
300
-
301
- assert_response :bad_request
302
- assert_match /asdfg is not a valid sort criteria for post/, response.body
303
- end
304
-
305
- def test_show_single_with_sort_disallowed
306
- JSONAPI.configuration.allow_sort = false
307
- get :index, {sort: 'title,body'}
308
- assert_response :bad_request
309
- ensure
310
- JSONAPI.configuration.allow_sort = true
311
- end
312
-
313
- def test_excluded_sort_param
314
- get :index, {sort: 'id'}
315
-
316
- assert_response :bad_request
317
- assert_match /id is not a valid sort criteria for post/, response.body
318
- end
319
-
320
- def test_show_single
321
- get :show, {id: '1'}
322
- assert_response :success
323
- assert json_response['data'].is_a?(Hash)
324
- assert_equal 'New post', json_response['data']['attributes']['title']
325
- assert_equal 'A body!!!', json_response['data']['attributes']['body']
326
- assert_nil json_response['included']
327
- end
328
-
329
- def test_show_does_not_include_records_count_in_meta
330
- JSONAPI.configuration.top_level_meta_include_record_count = true
331
- get :show, { id: Post.first.id }
332
- assert_response :success
333
- assert_equal json_response['meta'], nil
334
- ensure
335
- JSONAPI.configuration.top_level_meta_include_record_count = false
336
- end
337
-
338
- def test_show_single_with_includes
339
- get :show, {id: '1', include: 'comments'}
340
- assert_response :success
341
- assert json_response['data'].is_a?(Hash)
342
- assert_equal 'New post', json_response['data']['attributes']['title']
343
- assert_equal 'A body!!!', json_response['data']['attributes']['body']
344
- assert_nil json_response['data']['relationships']['tags']['data']
345
- assert matches_array?([{'type' => 'comments', 'id' => '1'}, {'type' => 'comments', 'id' => '2'}],
346
- json_response['data']['relationships']['comments']['data'])
347
- assert_equal 2, json_response['included'].size
348
- end
349
-
350
- def test_show_single_with_include_disallowed
351
- JSONAPI.configuration.allow_include = false
352
- get :show, {id: '1', include: 'comments'}
353
- assert_response :bad_request
354
- ensure
355
- JSONAPI.configuration.allow_include = true
356
- end
357
-
358
- def test_show_single_with_fields
359
- get :show, {id: '1', fields: {posts: 'author'}}
360
- assert_response :success
361
- assert json_response['data'].is_a?(Hash)
362
- assert_nil json_response['data']['attributes']
363
- end
364
-
365
- def test_show_single_with_fields_string
366
- get :show, {id: '1', fields: 'author'}
367
- assert_response :bad_request
368
- assert_match /Fields must specify a type./, json_response['errors'][0]['detail']
369
- end
370
-
371
- def test_show_single_invalid_id_format
372
- get :show, {id: 'asdfg'}
373
- assert_response :bad_request
374
- assert_match /asdfg is not a valid value for id/, response.body
375
- end
376
-
377
- def test_show_single_missing_record
378
- get :show, {id: '5412333'}
379
- assert_response :not_found
380
- assert_match /record identified by 5412333 could not be found/, response.body
381
- end
382
-
383
- def test_show_malformed_fields_not_list
384
- get :show, {id: '1', 'fields' => ''}
385
- assert_response :bad_request
386
- assert_match /Fields must specify a type./, json_response['errors'][0]['detail']
387
- end
388
-
389
- def test_show_malformed_fields_type_not_list
390
- get :show, {id: '1', 'fields' => {'posts' => ''}}
391
- assert_response :bad_request
392
- assert_match /nil is not a valid field for posts./, json_response['errors'][0]['detail']
393
- end
394
-
395
- def test_create_simple
396
- set_content_type_header!
397
- post :create,
398
- {
399
- data: {
400
- type: 'posts',
401
- attributes: {
402
- title: 'JR is Great',
403
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
404
- },
405
- relationships: {
406
- author: {data: {type: 'people', id: '3'}}
407
- }
408
- }
409
- }
410
-
411
- assert_response :created
412
- assert json_response['data'].is_a?(Hash)
413
- assert_equal 'JR is Great', json_response['data']['attributes']['title']
414
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
415
- end
416
-
417
- def test_create_link_to_missing_object
418
- set_content_type_header!
419
- post :create,
420
- {
421
- data: {
422
- type: 'posts',
423
- attributes: {
424
- title: 'JR is Great',
425
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
426
- },
427
- relationships: {
428
- author: {data: {type: 'people', id: '304567'}}
429
- }
430
- }
431
- }
432
-
433
- assert_response :unprocessable_entity
434
- # TODO: check if this validation is working
435
- assert_match /author - can't be blank/, response.body
436
- end
437
-
438
- def test_create_extra_param
439
- set_content_type_header!
440
- post :create,
441
- {
442
- data: {
443
- type: 'posts',
444
- attributes: {
445
- asdfg: 'aaaa',
446
- title: 'JR is Great',
447
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
448
- },
449
- relationships: {
450
- author: {data: {type: 'people', id: '3'}}
451
- }
452
- }
453
- }
454
-
455
- assert_response :bad_request
456
- assert_match /asdfg is not allowed/, response.body
457
- end
458
-
459
- def test_create_extra_param_allow_extra_params
460
- JSONAPI.configuration.raise_if_parameters_not_allowed = false
461
-
462
- set_content_type_header!
463
- post :create,
464
- {
465
- data: {
466
- type: 'posts',
467
- attributes: {
468
- asdfg: 'aaaa',
469
- title: 'JR is Great',
470
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
471
- },
472
- relationships: {
473
- author: {data: {type: 'people', id: '3'}}
474
- }
475
- },
476
- include: 'author'
477
- }
478
-
479
- assert_response :created
480
- assert json_response['data'].is_a?(Hash)
481
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
482
- assert_equal 'JR is Great', json_response['data']['attributes']['title']
483
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
484
-
485
- assert_equal 1, json_response['meta']["warnings"].count
486
- assert_equal "Param not allowed", json_response['meta']["warnings"][0]["title"]
487
- assert_equal "asdfg is not allowed.", json_response['meta']["warnings"][0]["detail"]
488
- assert_equal '105', json_response['meta']["warnings"][0]["code"]
489
- ensure
490
- JSONAPI.configuration.raise_if_parameters_not_allowed = true
491
- end
492
-
493
- def test_create_with_invalid_data
494
- set_content_type_header!
495
- post :create,
496
- {
497
- data: {
498
- type: 'posts',
499
- attributes: {
500
- title: 'JSONAPIResources is the greatest thing...',
501
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
502
- },
503
- relationships: {
504
- author: nil
505
- }
506
- }
507
- }
508
-
509
- assert_response :unprocessable_entity
510
-
511
- assert_equal "/data/relationships/author", json_response['errors'][0]['source']['pointer']
512
- assert_equal "can't be blank", json_response['errors'][0]['title']
513
- assert_equal "author - can't be blank", json_response['errors'][0]['detail']
514
-
515
- assert_equal "/data/attributes/title", json_response['errors'][1]['source']['pointer']
516
- assert_equal "is too long (maximum is 35 characters)", json_response['errors'][1]['title']
517
- assert_equal "title - is too long (maximum is 35 characters)", json_response['errors'][1]['detail']
518
- end
519
-
520
- def test_create_multiple
521
- set_content_type_header!
522
- post :create,
523
- {
524
- data: [
525
- {
526
- type: 'posts',
527
- attributes: {
528
- title: 'JR is Great',
529
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
530
- },
531
- relationships: {
532
- author: {data: {type: 'people', id: '3'}}
533
- }
534
- },
535
- {
536
- type: 'posts',
537
- attributes: {
538
- title: 'Ember is Great',
539
- body: 'Ember is the greatest thing since unsliced bread.'
540
- },
541
- relationships: {
542
- author: {data: {type: 'people', id: '3'}}
543
- }
544
- }
545
- ]
546
- }
547
-
548
- assert_response :created
549
- assert json_response['data'].is_a?(Array)
550
- assert_equal json_response['data'].size, 2
551
- assert_nil json_response['data'][0]['relationships']['author']['data']
552
- assert_match /JR is Great/, response.body
553
- assert_match /Ember is Great/, response.body
554
- end
555
-
556
- def test_create_multiple_wrong_case
557
- set_content_type_header!
558
- post :create,
559
- {
560
- data: [
561
- {
562
- type: 'posts',
563
- attributes: {
564
- Title: 'JR is Great',
565
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
566
- },
567
- relationships: {
568
- author: {data: {type: 'people', id: '3'}}
569
- }
570
- },
571
- {
572
- type: 'posts',
573
- attributes: {
574
- title: 'Ember is Great',
575
- BODY: 'Ember is the greatest thing since unsliced bread.'
576
- },
577
- relationships: {
578
- author: {data: {type: 'people', id: '3'}}
579
- }
580
- }
581
- ]
582
- }
583
-
584
- assert_response :bad_request
585
- assert_match /Title/, json_response['errors'][0]['detail']
586
- end
587
-
588
- def test_create_simple_missing_posts
589
- set_content_type_header!
590
- post :create,
591
- {
592
- data_spelled_wrong: {
593
- type: 'posts',
594
- attributes: {
595
- title: 'JR is Great',
596
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
597
- },
598
- relationships: {
599
- author: {data: {type: 'people', id: '3'}}
600
- }
601
- }
602
- }
603
-
604
- assert_response :bad_request
605
- assert_match /The required parameter, data, is missing./, json_response['errors'][0]['detail']
606
- end
607
-
608
- def test_create_simple_wrong_type
609
- set_content_type_header!
610
- post :create,
611
- {
612
- data: {
613
- type: 'posts_spelled_wrong',
614
- attributes: {
615
- title: 'JR is Great',
616
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
617
- },
618
- relationships: {
619
- author: {data: {type: 'people', id: '3'}}
620
- }
621
- }
622
- }
623
-
624
- assert_response :bad_request
625
- assert_match /posts_spelled_wrong is not a valid resource./, json_response['errors'][0]['detail']
626
- end
627
-
628
- def test_create_simple_missing_type
629
- set_content_type_header!
630
- post :create,
631
- {
632
- data: {
633
- attributes: {
634
- title: 'JR is Great',
635
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
636
- },
637
- relationships: {
638
- author: {data: {type: 'people', id: '3'}}
639
- }
640
- }
641
- }
642
-
643
- assert_response :bad_request
644
- assert_match /The required parameter, type, is missing./, json_response['errors'][0]['detail']
645
- end
646
-
647
- def test_create_simple_unpermitted_attributes
648
- set_content_type_header!
649
- post :create,
650
- {
651
- data: {
652
- type: 'posts',
653
- attributes: {
654
- subject: 'JR is Great',
655
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
656
- },
657
- relationships: {
658
- author: {data: {type: 'people', id: '3'}}
659
- }
660
- }
661
- }
662
-
663
- assert_response :bad_request
664
- assert_match /subject/, json_response['errors'][0]['detail']
665
- end
666
-
667
- def test_create_simple_unpermitted_attributes_allow_extra_params
668
- JSONAPI.configuration.raise_if_parameters_not_allowed = false
669
-
670
- set_content_type_header!
671
- post :create,
672
- {
673
- data: {
674
- type: 'posts',
675
- attributes: {
676
- title: 'JR is Great',
677
- subject: 'JR is SUPER Great',
678
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
679
- },
680
- relationships: {
681
- author: {data: {type: 'people', id: '3'}}
682
- }
683
- },
684
- include: 'author'
685
- }
686
-
687
- assert_response :created
688
- assert json_response['data'].is_a?(Hash)
689
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
690
- assert_equal 'JR is Great', json_response['data']['attributes']['title']
691
- assert_equal 'JR is Great', json_response['data']['attributes']['subject']
692
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
693
-
694
-
695
- assert_equal 1, json_response['meta']["warnings"].count
696
- assert_equal "Param not allowed", json_response['meta']["warnings"][0]["title"]
697
- assert_equal "subject is not allowed.", json_response['meta']["warnings"][0]["detail"]
698
- assert_equal '105', json_response['meta']["warnings"][0]["code"]
699
- ensure
700
- JSONAPI.configuration.raise_if_parameters_not_allowed = true
701
- end
702
-
703
- def test_create_with_links_to_many_type_ids
704
- set_content_type_header!
705
- post :create,
706
- {
707
- data: {
708
- type: 'posts',
709
- attributes: {
710
- title: 'JR is Great',
711
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
712
- },
713
- relationships: {
714
- author: {data: {type: 'people', id: '3'}},
715
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
716
- }
717
- },
718
- include: 'author'
719
- }
720
-
721
- assert_response :created
722
- assert json_response['data'].is_a?(Hash)
723
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
724
- assert_equal 'JR is Great', json_response['data']['attributes']['title']
725
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
726
- end
727
-
728
- def test_create_with_links_to_many_array
729
- set_content_type_header!
730
- post :create,
731
- {
732
- data: {
733
- type: 'posts',
734
- attributes: {
735
- title: 'JR is Great',
736
- body: 'JSONAPIResources is the greatest thing since unsliced bread.'
737
- },
738
- relationships: {
739
- author: {data: {type: 'people', id: '3'}},
740
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
741
- }
742
- },
743
- include: 'author'
744
- }
745
-
746
- assert_response :created
747
- assert json_response['data'].is_a?(Hash)
748
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
749
- assert_equal 'JR is Great', json_response['data']['attributes']['title']
750
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
751
- end
752
-
753
- def test_create_with_links_include_and_fields
754
- set_content_type_header!
755
- post :create,
756
- {
757
- data: {
758
- type: 'posts',
759
- attributes: {
760
- title: 'JR is Great!',
761
- body: 'JSONAPIResources is the greatest thing since unsliced bread!'
762
- },
763
- relationships: {
764
- author: {data: {type: 'people', id: '3'}},
765
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
766
- }
767
- },
768
- include: 'author,author.posts',
769
- fields: {posts: 'id,title,author'}
770
- }
771
-
772
- assert_response :created
773
- assert json_response['data'].is_a?(Hash)
774
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
775
- assert_equal 'JR is Great!', json_response['data']['attributes']['title']
776
- assert_not_nil json_response['included'].size
777
- end
778
-
779
- def test_update_with_links
780
- set_content_type_header!
781
- javascript = Section.find_by(name: 'javascript')
782
-
783
- put :update,
784
- {
785
- id: 3,
786
- data: {
787
- id: '3',
788
- type: 'posts',
789
- attributes: {
790
- title: 'A great new Post'
791
- },
792
- relationships: {
793
- section: {data: {type: 'sections', id: "#{javascript.id}"}},
794
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
795
- }
796
- },
797
- include: 'tags,author,section'
798
- }
799
-
800
- assert_response :success
801
- assert json_response['data'].is_a?(Hash)
802
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
803
- assert_equal javascript.id.to_s, json_response['data']['relationships']['section']['data']['id']
804
- assert_equal 'A great new Post', json_response['data']['attributes']['title']
805
- assert_equal 'AAAA', json_response['data']['attributes']['body']
806
- assert matches_array?([{'type' => 'tags', 'id' => '3'}, {'type' => 'tags', 'id' => '4'}],
807
- json_response['data']['relationships']['tags']['data'])
808
- end
809
-
810
- def test_update_with_internal_server_error
811
- set_content_type_header!
812
- post_object = Post.find(3)
813
- title = post_object.title
814
-
815
- put :update,
816
- {
817
- id: 3,
818
- data: {
819
- id: '3',
820
- type: 'posts',
821
- attributes: {
822
- title: 'BOOM'
823
- }
824
- }
825
- }
826
-
827
- assert_response 500
828
- post_object = Post.find(3)
829
- assert_equal title, post_object.title
830
- end
831
-
832
- def test_update_with_links_allow_extra_params
833
- JSONAPI.configuration.raise_if_parameters_not_allowed = false
834
-
835
- set_content_type_header!
836
- javascript = Section.find_by(name: 'javascript')
837
-
838
- put :update,
839
- {
840
- id: 3,
841
- data: {
842
- id: '3',
843
- type: 'posts',
844
- attributes: {
845
- title: 'A great new Post',
846
- subject: 'A great new Post',
847
- },
848
- relationships: {
849
- section: {data: {type: 'sections', id: "#{javascript.id}"}},
850
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
851
- }
852
- },
853
- include: 'tags,author,section'
854
- }
855
-
856
- assert_response :success
857
- assert json_response['data'].is_a?(Hash)
858
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
859
- assert_equal javascript.id.to_s, json_response['data']['relationships']['section']['data']['id']
860
- assert_equal 'A great new Post', json_response['data']['attributes']['title']
861
- assert_equal 'AAAA', json_response['data']['attributes']['body']
862
- assert matches_array?([{'type' => 'tags', 'id' => '3'}, {'type' => 'tags', 'id' => '4'}],
863
- json_response['data']['relationships']['tags']['data'])
864
-
865
-
866
- assert_equal 1, json_response['meta']["warnings"].count
867
- assert_equal "Param not allowed", json_response['meta']["warnings"][0]["title"]
868
- assert_equal "subject is not allowed.", json_response['meta']["warnings"][0]["detail"]
869
- assert_equal '105', json_response['meta']["warnings"][0]["code"]
870
- ensure
871
- JSONAPI.configuration.raise_if_parameters_not_allowed = true
872
- end
873
-
874
- def test_update_remove_links
875
- set_content_type_header!
876
- put :update,
877
- {
878
- id: 3,
879
- data: {
880
- id: '3',
881
- type: 'posts',
882
- attributes: {
883
- title: 'A great new Post'
884
- },
885
- relationships: {
886
- section: {data: {type: 'sections', id: 1}},
887
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
888
- }
889
- },
890
- include: 'tags'
891
- }
892
-
893
- assert_response :success
894
-
895
- put :update,
896
- {
897
- id: 3,
898
- data: {
899
- type: 'posts',
900
- id: 3,
901
- attributes: {
902
- title: 'A great new Post'
903
- },
904
- relationships: {
905
- section: nil,
906
- tags: []
907
- }
908
- },
909
- include: 'tags,author,section'
910
- }
911
-
912
- assert_response :success
913
- assert json_response['data'].is_a?(Hash)
914
- assert_equal '3', json_response['data']['relationships']['author']['data']['id']
915
- assert_equal nil, json_response['data']['relationships']['section']['data']
916
- assert_equal 'A great new Post', json_response['data']['attributes']['title']
917
- assert_equal 'AAAA', json_response['data']['attributes']['body']
918
- assert matches_array?([],
919
- json_response['data']['relationships']['tags']['data'])
920
- end
921
-
922
- def test_update_relationship_to_one
923
- set_content_type_header!
924
- ruby = Section.find_by(name: 'ruby')
925
- post_object = Post.find(4)
926
- assert_not_equal ruby.id, post_object.section_id
927
-
928
- put :update_relationship, {post_id: 4, relationship: 'section', data: {type: 'sections', id: "#{ruby.id}"}}
929
-
930
- assert_response :no_content
931
- post_object = Post.find(4)
932
- assert_equal ruby.id, post_object.section_id
933
- end
934
-
935
- def test_update_relationship_to_one_invalid_links_hash_keys_ids
936
- set_content_type_header!
937
- put :update_relationship, {post_id: 3, relationship: 'section', data: {type: 'sections', ids: 'foo'}}
938
-
939
- assert_response :bad_request
940
- assert_match /Invalid Links Object/, response.body
941
- end
942
-
943
- def test_update_relationship_to_one_invalid_links_hash_count
944
- set_content_type_header!
945
- put :update_relationship, {post_id: 3, relationship: 'section', data: {type: 'sections'}}
946
-
947
- assert_response :bad_request
948
- assert_match /Invalid Links Object/, response.body
949
- end
950
-
951
- def test_update_relationship_to_many_not_array
952
- set_content_type_header!
953
- put :update_relationship, {post_id: 3, relationship: 'tags', data: {type: 'tags', id: 2}}
954
-
955
- assert_response :bad_request
956
- assert_match /Invalid Links Object/, response.body
957
- end
958
-
959
- def test_update_relationship_to_one_invalid_links_hash_keys_type_mismatch
960
- set_content_type_header!
961
- put :update_relationship, {post_id: 3, relationship: 'section', data: {type: 'comment', id: '3'}}
962
-
963
- assert_response :bad_request
964
- assert_match /Type Mismatch/, response.body
965
- end
966
-
967
- def test_update_nil_to_many_links
968
- set_content_type_header!
969
- put :update,
970
- {
971
- id: 3,
972
- data: {
973
- type: 'posts',
974
- id: 3,
975
- relationships: {
976
- tags: nil
977
- }
978
- }
979
- }
980
-
981
- assert_response :bad_request
982
- assert_match /Invalid Links Object/, response.body
983
- end
984
-
985
- def test_update_bad_hash_to_many_links
986
- set_content_type_header!
987
- put :update,
988
- {
989
- id: 3,
990
- data: {
991
- type: 'posts',
992
- id: 3,
993
- relationships: {
994
- tags: {data: {typ: 'bad link', idd: 'as'}}
995
- }
996
- }
997
- }
998
-
999
- assert_response :bad_request
1000
- assert_match /Invalid Links Object/, response.body
1001
- end
1002
-
1003
- def test_update_other_to_many_links
1004
- set_content_type_header!
1005
- put :update,
1006
- {
1007
- id: 3,
1008
- data: {
1009
- type: 'posts',
1010
- id: 3,
1011
- relationships: {
1012
- tags: 'bad link'
1013
- }
1014
- }
1015
- }
1016
-
1017
- assert_response :bad_request
1018
- assert_match /Invalid Links Object/, response.body
1019
- end
1020
-
1021
- def test_update_other_to_many_links_data_nil
1022
- set_content_type_header!
1023
- put :update,
1024
- {
1025
- id: 3,
1026
- data: {
1027
- type: 'posts',
1028
- id: 3,
1029
- relationships: {
1030
- tags: {data: nil}
1031
- }
1032
- }
1033
- }
1034
-
1035
- assert_response :bad_request
1036
- assert_match /Invalid Links Object/, response.body
1037
- end
1038
-
1039
- def test_update_relationship_to_one_singular_param_id_nil
1040
- set_content_type_header!
1041
- ruby = Section.find_by(name: 'ruby')
1042
- post_object = Post.find(3)
1043
- post_object.section = ruby
1044
- post_object.save!
1045
-
1046
- put :update_relationship, {post_id: 3, relationship: 'section', data: {type: 'sections', id: nil}}
1047
-
1048
- assert_response :no_content
1049
- assert_equal nil, post_object.reload.section_id
1050
- end
1051
-
1052
- def test_update_relationship_to_one_data_nil
1053
- set_content_type_header!
1054
- ruby = Section.find_by(name: 'ruby')
1055
- post_object = Post.find(3)
1056
- post_object.section = ruby
1057
- post_object.save!
1058
-
1059
- put :update_relationship, {post_id: 3, relationship: 'section', data: nil}
1060
-
1061
- assert_response :no_content
1062
- assert_equal nil, post_object.reload.section_id
1063
- end
1064
-
1065
- def test_remove_relationship_to_one
1066
- set_content_type_header!
1067
- ruby = Section.find_by(name: 'ruby')
1068
- post_object = Post.find(3)
1069
- post_object.section_id = ruby.id
1070
- post_object.save!
1071
-
1072
- put :destroy_relationship, {post_id: 3, relationship: 'section'}
1073
-
1074
- assert_response :no_content
1075
- post_object = Post.find(3)
1076
- assert_equal nil, post_object.section_id
1077
- end
1078
-
1079
- def test_update_relationship_to_one_singular_param
1080
- set_content_type_header!
1081
- ruby = Section.find_by(name: 'ruby')
1082
- post_object = Post.find(3)
1083
- post_object.section_id = nil
1084
- post_object.save!
1085
-
1086
- put :update_relationship, {post_id: 3, relationship: 'section', data: {type: 'sections', id: "#{ruby.id}"}}
1087
-
1088
- assert_response :no_content
1089
- post_object = Post.find(3)
1090
- assert_equal ruby.id, post_object.section_id
1091
- end
1092
-
1093
- def test_update_relationship_to_many_join_table_single
1094
- set_content_type_header!
1095
- put :update_relationship, {post_id: 3, relationship: 'tags', data: []}
1096
- assert_response :no_content
1097
-
1098
- post_object = Post.find(3)
1099
- assert_equal 0, post_object.tags.length
1100
-
1101
- put :update_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', id: 2}]}
1102
-
1103
- assert_response :no_content
1104
- post_object = Post.find(3)
1105
- assert_equal 1, post_object.tags.length
1106
-
1107
- put :update_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', id: 5}]}
1108
-
1109
- assert_response :no_content
1110
- post_object = Post.find(3)
1111
- tags = post_object.tags.collect { |tag| tag.id }
1112
- assert_equal 1, tags.length
1113
- assert matches_array? [5], tags
1114
- end
1115
-
1116
- def test_update_relationship_to_many
1117
- set_content_type_header!
1118
- put :update_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 3}]}
1119
-
1120
- assert_response :no_content
1121
- post_object = Post.find(3)
1122
- assert_equal 2, post_object.tags.collect { |tag| tag.id }.length
1123
- assert matches_array? [2, 3], post_object.tags.collect { |tag| tag.id }
1124
- end
1125
-
1126
- def test_create_relationship_to_many_join_table
1127
- set_content_type_header!
1128
- put :update_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 3}]}
1129
-
1130
- assert_response :no_content
1131
- post_object = Post.find(3)
1132
- assert_equal 2, post_object.tags.collect { |tag| tag.id }.length
1133
- assert matches_array? [2, 3], post_object.tags.collect { |tag| tag.id }
1134
-
1135
- post :create_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', id: 5}]}
1136
-
1137
- assert_response :no_content
1138
- post_object = Post.find(3)
1139
- assert_equal 3, post_object.tags.collect { |tag| tag.id }.length
1140
- assert matches_array? [2, 3, 5], post_object.tags.collect { |tag| tag.id }
1141
- end
1142
-
1143
- def test_create_relationship_to_many_mismatched_type
1144
- set_content_type_header!
1145
- post :create_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'comments', id: 5}]}
1146
-
1147
- assert_response :bad_request
1148
- assert_match /Type Mismatch/, response.body
1149
- end
1150
-
1151
- def test_create_relationship_to_many_missing_id
1152
- set_content_type_header!
1153
- post :create_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', idd: 5}]}
1154
-
1155
- assert_response :bad_request
1156
- assert_match /Data is not a valid Links Object./, response.body
1157
- end
1158
-
1159
- def test_create_relationship_to_many_not_array
1160
- set_content_type_header!
1161
- post :create_relationship, {post_id: 3, relationship: 'tags', data: {type: 'tags', id: 5}}
1162
-
1163
- assert_response :bad_request
1164
- assert_match /Data is not a valid Links Object./, response.body
1165
- end
1166
-
1167
- def test_create_relationship_to_many_missing_data
1168
- set_content_type_header!
1169
- post :create_relationship, {post_id: 3, relationship: 'tags'}
1170
-
1171
- assert_response :bad_request
1172
- assert_match /The required parameter, data, is missing./, response.body
1173
- end
1174
-
1175
- def test_create_relationship_to_many_join
1176
- set_content_type_header!
1177
- post :create_relationship, {post_id: 4, relationship: 'tags', data: [{type: 'tags', id: 1}, {type: 'tags', id: 2}, {type: 'tags', id: 3}]}
1178
- assert_response :no_content
1179
- end
1180
-
1181
- def test_create_relationship_to_many_join_table_record_exists
1182
- set_content_type_header!
1183
- put :update_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 3}]}
1184
-
1185
- assert_response :no_content
1186
- post_object = Post.find(3)
1187
- assert_equal 2, post_object.tags.collect { |tag| tag.id }.length
1188
- assert matches_array? [2, 3], post_object.tags.collect { |tag| tag.id }
1189
-
1190
- post :create_relationship, {post_id: 3, relationship: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 5}]}
1191
-
1192
- assert_response :bad_request
1193
- assert_match /The relation to 2 already exists./, response.body
1194
- end
1195
-
1196
- def test_update_relationship_to_many_missing_tags
1197
- set_content_type_header!
1198
- put :update_relationship, {post_id: 3, relationship: 'tags'}
1199
-
1200
- assert_response :bad_request
1201
- assert_match /The required parameter, data, is missing./, response.body
1202
- end
1203
-
1204
- def test_delete_relationship_to_many
1205
- set_content_type_header!
1206
- put :update_relationship, {post_id: 14, relationship: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 3}]}
1207
- assert_response :no_content
1208
- p = Post.find(14)
1209
- assert_equal [2, 3], p.tag_ids
1210
-
1211
- delete :destroy_relationship, {post_id: 14, relationship: 'tags', data: [{type: 'tags', id: 3}]}
1212
-
1213
- p.reload
1214
- assert_response :no_content
1215
- assert_equal [2], p.tag_ids
1216
- end
1217
-
1218
- def test_delete_relationship_to_many_with_relationship_url_not_matching_type
1219
- set_content_type_header!
1220
- PostResource.has_many :special_tags, relation_name: :special_tags, class_name: "Tag"
1221
- post :create_relationship, {post_id: 14, relationship: 'special_tags', data: [{type: 'tags', id: 2}]}
1222
-
1223
- #check the relationship was created successfully
1224
- assert_equal 1, Post.find(14).special_tags.count
1225
- before_tags = Post.find(14).tags.count
1226
-
1227
- delete :destroy_relationship, {post_id: 14, relationship: 'special_tags', data: [{type: 'tags', id: 2}]}
1228
- assert_equal 0, Post.find(14).special_tags.count, "Relationship that matches URL relationship not destroyed"
1229
-
1230
- #check that the tag association is not affected
1231
- assert_equal Post.find(14).tags.count, before_tags
1232
- ensure
1233
- PostResource.instance_variable_get(:@_relationships).delete(:special_tags)
1234
- end
1235
-
1236
- def test_delete_relationship_to_many_does_not_exist
1237
- set_content_type_header!
1238
- put :update_relationship, {post_id: 14, relationship: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 3}]}
1239
- assert_response :no_content
1240
- p = Post.find(14)
1241
- assert_equal [2, 3], p.tag_ids
1242
-
1243
- delete :destroy_relationship, {post_id: 14, relationship: 'tags', data: [{type: 'tags', id: 4}]}
1244
-
1245
- p.reload
1246
- assert_response :not_found
1247
- assert_equal [2, 3], p.tag_ids
1248
- end
1249
-
1250
- def test_delete_relationship_to_many_with_empty_data
1251
- set_content_type_header!
1252
- put :update_relationship, {post_id: 14, relationship: 'tags', data: [{type: 'tags', id: 2}, {type: 'tags', id: 3}]}
1253
- assert_response :no_content
1254
- p = Post.find(14)
1255
- assert_equal [2, 3], p.tag_ids
1256
-
1257
- put :update_relationship, {post_id: 14, relationship: 'tags', data: [] }
1258
-
1259
- p.reload
1260
- assert_response :no_content
1261
- assert_equal [], p.tag_ids
1262
- end
1263
-
1264
- def test_update_mismatched_keys
1265
- set_content_type_header!
1266
- javascript = Section.find_by(name: 'javascript')
1267
-
1268
- put :update,
1269
- {
1270
- id: 3,
1271
- data: {
1272
- type: 'posts',
1273
- id: 2,
1274
- attributes: {
1275
- title: 'A great new Post'
1276
- },
1277
- relationships: {
1278
- section: {type: 'sections', id: "#{javascript.id}"},
1279
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1280
- }
1281
- }
1282
- }
1283
-
1284
- assert_response :bad_request
1285
- assert_match /The URL does not support the key 2/, response.body
1286
- end
1287
-
1288
- def test_update_extra_param
1289
- set_content_type_header!
1290
- javascript = Section.find_by(name: 'javascript')
1291
-
1292
- put :update,
1293
- {
1294
- id: 3,
1295
- data: {
1296
- type: 'posts',
1297
- id: '3',
1298
- attributes: {
1299
- asdfg: 'aaaa',
1300
- title: 'A great new Post'
1301
- },
1302
- relationships: {
1303
- section: {type: 'sections', id: "#{javascript.id}"},
1304
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1305
- }
1306
- }
1307
- }
1308
-
1309
- assert_response :bad_request
1310
- assert_match /asdfg is not allowed/, response.body
1311
- end
1312
-
1313
- def test_update_extra_param_in_links
1314
- set_content_type_header!
1315
- javascript = Section.find_by(name: 'javascript')
1316
-
1317
- put :update,
1318
- {
1319
- id: 3,
1320
- data: {
1321
- type: 'posts',
1322
- id: '3',
1323
- attributes: {
1324
- title: 'A great new Post'
1325
- },
1326
- relationships: {
1327
- asdfg: 'aaaa',
1328
- section: {type: 'sections', id: "#{javascript.id}"},
1329
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1330
- }
1331
- }
1332
- }
1333
-
1334
- assert_response :bad_request
1335
- assert_match /asdfg is not allowed/, response.body
1336
- end
1337
-
1338
- def test_update_extra_param_in_links_allow_extra_params
1339
- JSONAPI.configuration.raise_if_parameters_not_allowed = false
1340
- JSONAPI.configuration.use_text_errors = true
1341
-
1342
- set_content_type_header!
1343
- javascript = Section.find_by(name: 'javascript')
1344
-
1345
- put :update,
1346
- {
1347
- id: 3,
1348
- data: {
1349
- type: 'posts',
1350
- id: '3',
1351
- attributes: {
1352
- title: 'A great new Post'
1353
- },
1354
- relationships: {
1355
- asdfg: 'aaaa'
1356
- }
1357
- }
1358
- }
1359
-
1360
- assert_response :success
1361
- assert_equal "A great new Post", json_response["data"]["attributes"]["title"]
1362
- assert_equal "Param not allowed", json_response["meta"]["warnings"][0]["title"]
1363
- assert_equal "asdfg is not allowed.", json_response["meta"]["warnings"][0]["detail"]
1364
- assert_equal "PARAM_NOT_ALLOWED", json_response["meta"]["warnings"][0]["code"]
1365
- ensure
1366
- JSONAPI.configuration.raise_if_parameters_not_allowed = true
1367
- JSONAPI.configuration.use_text_errors = false
1368
- end
1369
-
1370
- def test_update_missing_param
1371
- set_content_type_header!
1372
- javascript = Section.find_by(name: 'javascript')
1373
-
1374
- put :update,
1375
- {
1376
- id: 3,
1377
- data_spelled_wrong: {
1378
- type: 'posts',
1379
- attributes: {
1380
- title: 'A great new Post'
1381
- },
1382
- relationships: {
1383
- section: {type: 'sections', id: "#{javascript.id}"},
1384
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1385
- }
1386
- }
1387
- }
1388
-
1389
- assert_response :bad_request
1390
- assert_match /The required parameter, data, is missing./, response.body
1391
- end
1392
-
1393
- def test_update_missing_key
1394
- set_content_type_header!
1395
-
1396
- put :update,
1397
- {
1398
- id: 3,
1399
- data: {
1400
- type: 'posts',
1401
- attributes: {
1402
- title: 'A great new Post'
1403
- }
1404
- }
1405
- }
1406
-
1407
- assert_response :bad_request
1408
- assert_match /The resource object does not contain a key/, response.body
1409
- end
1410
-
1411
- def test_update_missing_type
1412
- set_content_type_header!
1413
- javascript = Section.find_by(name: 'javascript')
1414
-
1415
- put :update,
1416
- {
1417
- id: 3,
1418
- data: {
1419
- id: '3',
1420
- type_spelled_wrong: 'posts',
1421
- attributes: {
1422
- title: 'A great new Post'
1423
- },
1424
- relationships: {
1425
- section: {type: 'sections', id: "#{javascript.id}"},
1426
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1427
- }
1428
- }
1429
- }
1430
-
1431
- assert_response :bad_request
1432
- assert_match /The required parameter, type, is missing./, response.body
1433
- end
1434
-
1435
- def test_update_unknown_key
1436
- set_content_type_header!
1437
- javascript = Section.find_by(name: 'javascript')
1438
-
1439
- put :update,
1440
- {
1441
- id: 3,
1442
- data: {
1443
- id: '3',
1444
- type: 'posts',
1445
- body: 'asdfg',
1446
- attributes: {
1447
- title: 'A great new Post'
1448
- },
1449
- relationships: {
1450
- section: {type: 'sections', id: "#{javascript.id}"},
1451
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1452
- }
1453
- }
1454
- }
1455
-
1456
- assert_response :bad_request
1457
- assert_match /body is not allowed/, response.body
1458
- end
1459
-
1460
- def test_update_multiple
1461
- set_content_type_header!
1462
- javascript = Section.find_by(name: 'javascript')
1463
-
1464
- put :update,
1465
- {
1466
- id: [3, 16],
1467
- data: [
1468
- {
1469
- type: 'posts',
1470
- id: 3,
1471
- attributes: {
1472
- title: 'A great new Post QWERTY'
1473
- },
1474
- relationships: {
1475
- section: {data: {type: 'sections', id: "#{javascript.id}"}},
1476
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
1477
- }
1478
- },
1479
- {
1480
- type: 'posts',
1481
- id: 16,
1482
- attributes: {
1483
- title: 'A great new Post ASDFG'
1484
- },
1485
- relationships: {
1486
- section: {data: {type: 'sections', id: "#{javascript.id}"}},
1487
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
1488
- }
1489
- }
1490
- ],
1491
- include: 'tags'
1492
- }
1493
-
1494
- assert_response :success
1495
- assert_equal json_response['data'].size, 2
1496
- assert_equal json_response['data'][0]['attributes']['title'], 'A great new Post QWERTY'
1497
- assert_equal json_response['data'][0]['attributes']['body'], 'AAAA'
1498
- assert matches_array?([{'type' => 'tags', 'id' => '3'}, {'type' => 'tags', 'id' => '4'}],
1499
- json_response['data'][0]['relationships']['tags']['data'])
1500
-
1501
- assert_equal json_response['data'][1]['attributes']['title'], 'A great new Post ASDFG'
1502
- assert_equal json_response['data'][1]['attributes']['body'], 'Not First!!!!'
1503
- assert matches_array?([{'type' => 'tags', 'id' => '3'}, {'type' => 'tags', 'id' => '4'}],
1504
- json_response['data'][1]['relationships']['tags']['data'])
1505
- end
1506
-
1507
- def test_update_multiple_missing_keys
1508
- set_content_type_header!
1509
- javascript = Section.find_by(name: 'javascript')
1510
-
1511
- put :update,
1512
- {
1513
- id: [3, 9],
1514
- data: [
1515
- {
1516
- type: 'posts',
1517
- attributes: {
1518
- title: 'A great new Post ASDFG'
1519
- },
1520
- relationships: {
1521
- section: {type: 'sections', id: "#{javascript.id}"},
1522
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1523
- }
1524
- },
1525
- {
1526
- type: 'posts',
1527
- attributes: {
1528
- title: 'A great new Post QWERTY'
1529
- },
1530
- relationships: {
1531
- section: {type: 'sections', id: "#{javascript.id}"},
1532
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1533
- }
1534
- }
1535
- ]}
1536
-
1537
- assert_response :bad_request
1538
- assert_match /A key is required/, response.body
1539
- end
1540
-
1541
- def test_update_mismatch_keys
1542
- set_content_type_header!
1543
- javascript = Section.find_by(name: 'javascript')
1544
-
1545
- put :update,
1546
- {
1547
- id: [3, 9],
1548
- data: [
1549
- {
1550
- type: 'posts',
1551
- id: 3,
1552
- attributes: {
1553
- title: 'A great new Post ASDFG'
1554
- },
1555
- relationships: {
1556
- section: {data: {type: 'sections', id: "#{javascript.id}"}},
1557
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
1558
- }
1559
- },
1560
- {
1561
- type: 'posts',
1562
- id: 8,
1563
- attributes: {
1564
- title: 'A great new Post QWERTY'
1565
- },
1566
- relationships: {
1567
- section: {data: {type: 'sections', id: "#{javascript.id}"}},
1568
- tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
1569
- }
1570
- }
1571
- ]}
1572
-
1573
- assert_response :bad_request
1574
- assert_match /The URL does not support the key 8/, response.body
1575
- end
1576
-
1577
- def test_update_multiple_count_mismatch
1578
- set_content_type_header!
1579
- javascript = Section.find_by(name: 'javascript')
1580
-
1581
- put :update,
1582
- {
1583
- id: [3, 9, 2],
1584
- data: [
1585
- {
1586
- type: 'posts',
1587
- id: 3,
1588
- attributes: {
1589
- title: 'A great new Post QWERTY'
1590
- },
1591
- relationships: {
1592
- section: {type: 'sections', id: "#{javascript.id}"},
1593
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1594
- }
1595
- },
1596
- {
1597
- type: 'posts',
1598
- id: 9,
1599
- attributes: {
1600
- title: 'A great new Post ASDFG'
1601
- },
1602
- relationships: {
1603
- section: {type: 'sections', id: "#{javascript.id}"},
1604
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1605
- }
1606
- }
1607
- ]}
1608
-
1609
- assert_response :bad_request
1610
- assert_match /Count to key mismatch/, response.body
1611
- end
1612
-
1613
- def test_update_unpermitted_attributes
1614
- set_content_type_header!
1615
- put :update,
1616
- {
1617
- id: 3,
1618
- data: {
1619
- type: 'posts',
1620
- id: '3',
1621
- attributes: {
1622
- subject: 'A great new Post'
1623
- },
1624
- relationships: {
1625
- author: {type: 'people', id: '1'},
1626
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1627
- }
1628
- }
1629
- }
1630
-
1631
- assert_response :bad_request
1632
- assert_match /author is not allowed./, response.body
1633
- assert_match /subject is not allowed./, response.body
1634
- end
1635
-
1636
- def test_update_bad_attributes
1637
- set_content_type_header!
1638
- put :update,
1639
- {
1640
- id: 3,
1641
- data: {
1642
- type: 'posts',
1643
- attributes: {
1644
- subject: 'A great new Post'
1645
- },
1646
- linked_objects: {
1647
- author: {type: 'people', id: '1'},
1648
- tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
1649
- }
1650
- }
1651
- }
1652
-
1653
- assert_response :bad_request
1654
- end
1655
-
1656
- def test_delete_with_validation_error
1657
- post = Post.create!(title: "can't destroy me", author: Person.first)
1658
- delete :destroy, { id: post.id }
1659
-
1660
- assert_equal "can't destroy me", json_response['errors'][0]['title']
1661
- assert_response :unprocessable_entity
1662
- end
1663
-
1664
- def test_delete_single
1665
- initial_count = Post.count
1666
- delete :destroy, {id: '4'}
1667
- assert_response :no_content
1668
- assert_equal initial_count - 1, Post.count
1669
- end
1670
-
1671
- def test_delete_multiple
1672
- initial_count = Post.count
1673
- delete :destroy, {id: '5,6'}
1674
- assert_response :no_content
1675
- assert_equal initial_count - 2, Post.count
1676
- end
1677
-
1678
- def test_delete_multiple_one_does_not_exist
1679
- initial_count = Post.count
1680
- delete :destroy, {id: '5,6,99999'}
1681
- assert_response :not_found
1682
- assert_equal initial_count, Post.count
1683
- end
1684
-
1685
- def test_show_to_one_relationship
1686
- get :show_relationship, {post_id: '1', relationship: 'author'}
1687
- assert_response :success
1688
- assert_hash_equals json_response,
1689
- {data: {
1690
- type: 'people',
1691
- id: '1'
1692
- },
1693
- links: {
1694
- self: 'http://test.host/posts/1/relationships/author',
1695
- related: 'http://test.host/posts/1/author'
1696
- }
1697
- }
1698
- end
1699
-
1700
- def test_show_to_many_relationship
1701
- get :show_relationship, {post_id: '2', relationship: 'tags'}
1702
- assert_response :success
1703
- assert_hash_equals json_response,
1704
- {
1705
- data: [
1706
- {type: 'tags', id: '5'}
1707
- ],
1708
- links: {
1709
- self: 'http://test.host/posts/2/relationships/tags',
1710
- related: 'http://test.host/posts/2/tags'
1711
- }
1712
- }
1713
- end
1714
-
1715
- def test_show_to_many_relationship_invalid_id
1716
- get :show_relationship, {post_id: '2,1', relationship: 'tags'}
1717
- assert_response :bad_request
1718
- assert_match /2,1 is not a valid value for id/, response.body
1719
- end
1720
-
1721
- def test_show_to_one_relationship_nil
1722
- get :show_relationship, {post_id: '17', relationship: 'author'}
1723
- assert_response :success
1724
- assert_hash_equals json_response,
1725
- {
1726
- data: nil,
1727
- links: {
1728
- self: 'http://test.host/posts/17/relationships/author',
1729
- related: 'http://test.host/posts/17/author'
1730
- }
1731
- }
1732
- end
1733
- end
1734
-
1735
- class TagsControllerTest < ActionController::TestCase
1736
- def test_tags_index
1737
- get :index, {filter: {id: '6,7,8,9'}, include: 'posts.tags,posts.author.posts'}
1738
- assert_response :success
1739
- assert_equal 4, json_response['data'].size
1740
- assert_equal 3, json_response['included'].size
1741
- end
1742
-
1743
- def test_tags_show_multiple
1744
- get :show, {id: '6,7,8,9'}
1745
- assert_response :bad_request
1746
- assert_match /6,7,8,9 is not a valid value for id/, response.body
1747
- end
1748
-
1749
- def test_tags_show_multiple_with_include
1750
- get :show, {id: '6,7,8,9', include: 'posts.tags,posts.author.posts'}
1751
- assert_response :bad_request
1752
- assert_match /6,7,8,9 is not a valid value for id/, response.body
1753
- end
1754
-
1755
- def test_tags_show_multiple_with_nonexistent_ids
1756
- get :show, {id: '6,99,9,100'}
1757
- assert_response :bad_request
1758
- assert_match /6,99,9,100 is not a valid value for id/, response.body
1759
- end
1760
-
1761
- def test_tags_show_multiple_with_nonexistent_ids_at_the_beginning
1762
- get :show, {id: '99,9,100'}
1763
- assert_response :bad_request
1764
- assert_match /99,9,100 is not a valid value for id/, response.body
1765
- end
1766
- end
1767
-
1768
- class ExpenseEntriesControllerTest < ActionController::TestCase
1769
- def setup
1770
- JSONAPI.configuration.json_key_format = :camelized_key
1771
- end
1772
-
1773
- def test_text_error
1774
- JSONAPI.configuration.use_text_errors = true
1775
- get :index, {sort: 'not_in_record'}
1776
- assert_response 400
1777
- assert_equal 'INVALID_SORT_CRITERIA', json_response['errors'][0]['code']
1778
- ensure
1779
- JSONAPI.configuration.use_text_errors = false
1780
- end
1781
-
1782
- def test_expense_entries_index
1783
- get :index
1784
- assert_response :success
1785
- assert json_response['data'].is_a?(Array)
1786
- assert_equal 2, json_response['data'].size
1787
- end
1788
-
1789
- def test_expense_entries_show
1790
- get :show, {id: 1}
1791
- assert_response :success
1792
- assert json_response['data'].is_a?(Hash)
1793
- end
1794
-
1795
- def test_expense_entries_show_include
1796
- get :show, {id: 1, include: 'isoCurrency,employee'}
1797
- assert_response :success
1798
- assert json_response['data'].is_a?(Hash)
1799
- assert_equal 2, json_response['included'].size
1800
- end
1801
-
1802
- def test_expense_entries_show_bad_include_missing_relationship
1803
- get :show, {id: 1, include: 'isoCurrencies,employees'}
1804
- assert_response :bad_request
1805
- assert_match /isoCurrencies is not a valid relationship of expenseEntries/, json_response['errors'][0]['detail']
1806
- assert_match /employees is not a valid relationship of expenseEntries/, json_response['errors'][1]['detail']
1807
- end
1808
-
1809
- def test_expense_entries_show_bad_include_missing_sub_relationship
1810
- get :show, {id: 1, include: 'isoCurrency,employee.post'}
1811
- assert_response :bad_request
1812
- assert_match /post is not a valid relationship of people/, json_response['errors'][0]['detail']
1813
- end
1814
-
1815
- def test_expense_entries_show_fields
1816
- get :show, {id: 1, include: 'isoCurrency,employee', 'fields' => {'expenseEntries' => 'transactionDate'}}
1817
- assert_response :success
1818
- assert json_response['data'].is_a?(Hash)
1819
- assert json_response['data']['attributes'].key?('transactionDate')
1820
- assert_equal 2, json_response['included'].size
1821
- end
1822
-
1823
- def test_expense_entries_show_fields_type_many
1824
- get :show, {id: 1, include: 'isoCurrency,employee', 'fields' => {'expenseEntries' => 'transactionDate',
1825
- 'isoCurrencies' => 'id,name'}}
1826
- assert_response :success
1827
- assert json_response['data'].is_a?(Hash)
1828
- assert json_response['data']['attributes'].key?('transactionDate')
1829
- assert_equal 2, json_response['included'].size
1830
- end
1831
-
1832
- def test_create_expense_entries_underscored
1833
- set_content_type_header!
1834
- original_config = JSONAPI.configuration.dup
1835
- JSONAPI.configuration.json_key_format = :underscored_key
1836
-
1837
- post :create,
1838
- {
1839
- data: {
1840
- type: 'expense_entries',
1841
- attributes: {
1842
- transaction_date: '2014/04/15',
1843
- cost: 50.58
1844
- },
1845
- relationships: {
1846
- employee: {data: {type: 'people', id: '3'}},
1847
- iso_currency: {data: {type: 'iso_currencies', id: 'USD'}}
1848
- }
1849
- },
1850
- include: 'iso_currency,employee',
1851
- fields: {expense_entries: 'id,transaction_date,iso_currency,cost,employee'}
1852
- }
1853
-
1854
- assert_response :created
1855
- assert json_response['data'].is_a?(Hash)
1856
- assert_equal '3', json_response['data']['relationships']['employee']['data']['id']
1857
- assert_equal 'USD', json_response['data']['relationships']['iso_currency']['data']['id']
1858
- assert_equal '50.58', json_response['data']['attributes']['cost']
1859
-
1860
- delete :destroy, {id: json_response['data']['id']}
1861
- assert_response :no_content
1862
- ensure
1863
- JSONAPI.configuration = original_config
1864
- end
1865
-
1866
- def test_create_expense_entries_camelized_key
1867
- set_content_type_header!
1868
- original_config = JSONAPI.configuration.dup
1869
- JSONAPI.configuration.json_key_format = :camelized_key
1870
-
1871
- post :create,
1872
- {
1873
- data: {
1874
- type: 'expense_entries',
1875
- attributes: {
1876
- transactionDate: '2014/04/15',
1877
- cost: 50.58
1878
- },
1879
- relationships: {
1880
- employee: {data: {type: 'people', id: '3'}},
1881
- isoCurrency: {data: {type: 'iso_currencies', id: 'USD'}}
1882
- }
1883
- },
1884
- include: 'isoCurrency,employee',
1885
- fields: {expenseEntries: 'id,transactionDate,isoCurrency,cost,employee'}
1886
- }
1887
-
1888
- assert_response :created
1889
- assert json_response['data'].is_a?(Hash)
1890
- assert_equal '3', json_response['data']['relationships']['employee']['data']['id']
1891
- assert_equal 'USD', json_response['data']['relationships']['isoCurrency']['data']['id']
1892
- assert_equal '50.58', json_response['data']['attributes']['cost']
1893
-
1894
- delete :destroy, {id: json_response['data']['id']}
1895
- assert_response :no_content
1896
- ensure
1897
- JSONAPI.configuration = original_config
1898
- end
1899
-
1900
- def test_create_expense_entries_dasherized_key
1901
- set_content_type_header!
1902
- original_config = JSONAPI.configuration.dup
1903
- JSONAPI.configuration.json_key_format = :dasherized_key
1904
-
1905
- post :create,
1906
- {
1907
- data: {
1908
- type: 'expense_entries',
1909
- attributes: {
1910
- 'transaction-date' => '2014/04/15',
1911
- cost: 50.58
1912
- },
1913
- relationships: {
1914
- employee: {data: {type: 'people', id: '3'}},
1915
- 'iso-currency' => {data: {type: 'iso_currencies', id: 'USD'}}
1916
- }
1917
- },
1918
- include: 'iso-currency,employee',
1919
- fields: {'expense-entries' => 'id,transaction-date,iso-currency,cost,employee'}
1920
- }
1921
-
1922
- assert_response :created
1923
- assert json_response['data'].is_a?(Hash)
1924
- assert_equal '3', json_response['data']['relationships']['employee']['data']['id']
1925
- assert_equal 'USD', json_response['data']['relationships']['iso-currency']['data']['id']
1926
- assert_equal '50.58', json_response['data']['attributes']['cost']
1927
-
1928
- delete :destroy, {id: json_response['data']['id']}
1929
- assert_response :no_content
1930
- ensure
1931
- JSONAPI.configuration = original_config
1932
- end
1933
- end
1934
-
1935
- class IsoCurrenciesControllerTest < ActionController::TestCase
1936
- def after_teardown
1937
- JSONAPI.configuration.json_key_format = :camelized_key
1938
- end
1939
-
1940
- def test_currencies_show
1941
- get :show, {id: 'USD'}
1942
- assert_response :success
1943
- assert json_response['data'].is_a?(Hash)
1944
- end
1945
-
1946
- def test_create_currencies_client_generated_id
1947
- set_content_type_header!
1948
- original_config = JSONAPI.configuration.dup
1949
- JSONAPI.configuration.json_key_format = :underscored_route
1950
-
1951
- post :create,
1952
- {
1953
- data: {
1954
- type: 'iso_currencies',
1955
- id: 'BTC',
1956
- attributes: {
1957
- name: 'Bit Coin',
1958
- 'country_name' => 'global',
1959
- 'minor_unit' => 'satoshi'
1960
- }
1961
- }
1962
- }
1963
-
1964
- assert_response :created
1965
- assert_equal 'BTC', json_response['data']['id']
1966
- assert_equal 'Bit Coin', json_response['data']['attributes']['name']
1967
- assert_equal 'global', json_response['data']['attributes']['country_name']
1968
- assert_equal 'satoshi', json_response['data']['attributes']['minor_unit']
1969
-
1970
- delete :destroy, {id: json_response['data']['id']}
1971
- assert_response :no_content
1972
- ensure
1973
- JSONAPI.configuration = original_config
1974
- end
1975
-
1976
- def test_currencies_primary_key_sort
1977
- get :index, {sort: 'id'}
1978
- assert_response :success
1979
- assert_equal 3, json_response['data'].size
1980
- assert_equal 'CAD', json_response['data'][0]['id']
1981
- assert_equal 'EUR', json_response['data'][1]['id']
1982
- assert_equal 'USD', json_response['data'][2]['id']
1983
- end
1984
-
1985
- def test_currencies_code_sort
1986
- get :index, {sort: 'code'}
1987
- assert_response :bad_request
1988
- end
1989
-
1990
- def test_currencies_json_key_underscored_sort
1991
- original_config = JSONAPI.configuration.dup
1992
- JSONAPI.configuration.json_key_format = :underscored_key
1993
- get :index, {sort: 'country_name'}
1994
- assert_response :success
1995
- assert_equal 3, json_response['data'].size
1996
- assert_equal 'Canada', json_response['data'][0]['attributes']['country_name']
1997
- assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country_name']
1998
- assert_equal 'United States', json_response['data'][2]['attributes']['country_name']
1999
-
2000
- # reverse sort
2001
- get :index, {sort: '-country_name'}
2002
- assert_response :success
2003
- assert_equal 3, json_response['data'].size
2004
- assert_equal 'United States', json_response['data'][0]['attributes']['country_name']
2005
- assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country_name']
2006
- assert_equal 'Canada', json_response['data'][2]['attributes']['country_name']
2007
- ensure
2008
- JSONAPI.configuration = original_config
2009
- end
2010
-
2011
- def test_currencies_json_key_dasherized_sort
2012
- original_config = JSONAPI.configuration.dup
2013
- JSONAPI.configuration.json_key_format = :dasherized_key
2014
- get :index, {sort: 'country-name'}
2015
- assert_response :success
2016
- assert_equal 3, json_response['data'].size
2017
- assert_equal 'Canada', json_response['data'][0]['attributes']['country-name']
2018
- assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country-name']
2019
- assert_equal 'United States', json_response['data'][2]['attributes']['country-name']
2020
-
2021
- # reverse sort
2022
- get :index, {sort: '-country-name'}
2023
- assert_response :success
2024
- assert_equal 3, json_response['data'].size
2025
- assert_equal 'United States', json_response['data'][0]['attributes']['country-name']
2026
- assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country-name']
2027
- assert_equal 'Canada', json_response['data'][2]['attributes']['country-name']
2028
- ensure
2029
- JSONAPI.configuration = original_config
2030
- end
2031
-
2032
- def test_currencies_json_key_custom_json_key_sort
2033
- original_config = JSONAPI.configuration.dup
2034
- JSONAPI.configuration.json_key_format = :upper_camelized_key
2035
- get :index, {sort: 'CountryName'}
2036
- assert_response :success
2037
- assert_equal 3, json_response['data'].size
2038
- assert_equal 'Canada', json_response['data'][0]['attributes']['CountryName']
2039
- assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['CountryName']
2040
- assert_equal 'United States', json_response['data'][2]['attributes']['CountryName']
2041
-
2042
- # reverse sort
2043
- get :index, {sort: '-CountryName'}
2044
- assert_response :success
2045
- assert_equal 3, json_response['data'].size
2046
- assert_equal 'United States', json_response['data'][0]['attributes']['CountryName']
2047
- assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['CountryName']
2048
- assert_equal 'Canada', json_response['data'][2]['attributes']['CountryName']
2049
- ensure
2050
- JSONAPI.configuration = original_config
2051
- end
2052
-
2053
- def test_currencies_json_key_underscored_filter
2054
- original_config = JSONAPI.configuration.dup
2055
- JSONAPI.configuration.json_key_format = :underscored_key
2056
- get :index, {filter: {country_name: 'Canada'}}
2057
- assert_response :success
2058
- assert_equal 1, json_response['data'].size
2059
- assert_equal 'Canada', json_response['data'][0]['attributes']['country_name']
2060
- ensure
2061
- JSONAPI.configuration = original_config
2062
- end
2063
-
2064
- def test_currencies_json_key_camelized_key_filter
2065
- original_config = JSONAPI.configuration.dup
2066
- JSONAPI.configuration.json_key_format = :camelized_key
2067
- get :index, {filter: {'countryName' => 'Canada'}}
2068
- assert_response :success
2069
- assert_equal 1, json_response['data'].size
2070
- assert_equal 'Canada', json_response['data'][0]['attributes']['countryName']
2071
- ensure
2072
- JSONAPI.configuration = original_config
2073
- end
2074
-
2075
- def test_currencies_json_key_custom_json_key_filter
2076
- original_config = JSONAPI.configuration.dup
2077
- JSONAPI.configuration.json_key_format = :upper_camelized_key
2078
- get :index, {filter: {'CountryName' => 'Canada'}}
2079
- assert_response :success
2080
- assert_equal 1, json_response['data'].size
2081
- assert_equal 'Canada', json_response['data'][0]['attributes']['CountryName']
2082
- ensure
2083
- JSONAPI.configuration = original_config
2084
- end
2085
- end
2086
-
2087
- class PeopleControllerTest < ActionController::TestCase
2088
- def setup
2089
- JSONAPI.configuration.json_key_format = :camelized_key
2090
- end
2091
-
2092
- def test_create_validations
2093
- set_content_type_header!
2094
- post :create,
2095
- {
2096
- data: {
2097
- type: 'people',
2098
- attributes: {
2099
- name: 'Steve Jobs',
2100
- email: 'sj@email.zzz',
2101
- dateJoined: DateTime.parse('2014-1-30 4:20:00 UTC +00:00')
2102
- }
2103
- }
2104
- }
2105
-
2106
- assert_response :success
2107
- end
2108
-
2109
- def test_update_link_with_dasherized_type
2110
- original_config = JSONAPI.configuration.dup
2111
- JSONAPI.configuration.json_key_format = :dasherized_key
2112
- set_content_type_header!
2113
- put :update,
2114
- {
2115
- id: 3,
2116
- data: {
2117
- id: '3',
2118
- type: 'people',
2119
- relationships: {
2120
- 'hair-cut' => {
2121
- data: {
2122
- type: 'hair-cuts',
2123
- id: '1'
2124
- }
2125
- }
2126
- }
2127
- }
2128
- }
2129
- assert_response :success
2130
- ensure
2131
- JSONAPI.configuration = original_config
2132
- end
2133
-
2134
- def test_create_validations_missing_attribute
2135
- set_content_type_header!
2136
- post :create,
2137
- {
2138
- data: {
2139
- type: 'people',
2140
- attributes: {
2141
- email: 'sj@email.zzz'
2142
- }
2143
- }
2144
- }
2145
-
2146
- assert_response :unprocessable_entity
2147
- assert_equal 2, json_response['errors'].size
2148
- assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code']
2149
- assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][1]['code']
2150
- assert_match /dateJoined - can't be blank/, response.body
2151
- assert_match /name - can't be blank/, response.body
2152
- end
2153
-
2154
- def test_update_validations_missing_attribute
2155
- set_content_type_header!
2156
- put :update,
2157
- {
2158
- id: 3,
2159
- data: {
2160
- id: '3',
2161
- type: 'people',
2162
- attributes: {
2163
- name: ''
2164
- }
2165
- }
2166
- }
2167
-
2168
- assert_response :unprocessable_entity
2169
- assert_equal 1, json_response['errors'].size
2170
- assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code']
2171
- assert_match /name - can't be blank/, response.body
2172
- end
2173
-
2174
- def test_delete_locked
2175
- initial_count = Person.count
2176
- delete :destroy, {id: '3'}
2177
- assert_response :locked
2178
- assert_equal initial_count, Person.count
2179
- end
2180
-
2181
- def test_invalid_filter_value
2182
- get :index, {filter: {name: 'L'}}
2183
- assert_response :bad_request
2184
- end
2185
-
2186
- def test_valid_filter_value
2187
- get :index, {filter: {name: 'Joe Author'}}
2188
- assert_response :success
2189
- assert_equal json_response['data'].size, 1
2190
- assert_equal json_response['data'][0]['id'], '1'
2191
- assert_equal json_response['data'][0]['attributes']['name'], 'Joe Author'
2192
- end
2193
-
2194
- def test_get_related_resource_no_namespace
2195
- original_config = JSONAPI.configuration.dup
2196
- JSONAPI.configuration.json_key_format = :dasherized_key
2197
- JSONAPI.configuration.route_format = :underscored_key
2198
- get :get_related_resource, {post_id: '2', relationship: 'author', source:'posts'}
2199
- assert_response :success
2200
- assert_hash_equals(
2201
- {
2202
- data: {
2203
- id: '1',
2204
- type: 'people',
2205
- attributes: {
2206
- name: 'Joe Author',
2207
- email: 'joe@xyz.fake',
2208
- "date-joined" => '2013-08-07 16:25:00 -0400'
2209
- },
2210
- links: {
2211
- self: 'http://test.host/people/1'
2212
- },
2213
- relationships: {
2214
- comments: {
2215
- links: {
2216
- self: 'http://test.host/people/1/relationships/comments',
2217
- related: 'http://test.host/people/1/comments'
2218
- }
2219
- },
2220
- posts: {
2221
- links: {
2222
- self: 'http://test.host/people/1/relationships/posts',
2223
- related: 'http://test.host/people/1/posts'
2224
- }
2225
- },
2226
- preferences: {
2227
- links: {
2228
- self: 'http://test.host/people/1/relationships/preferences',
2229
- related: 'http://test.host/people/1/preferences'
2230
- }
2231
- },
2232
- "hair-cut" => {
2233
- "links" => {
2234
- "self" => "http://test.host/people/1/relationships/hair_cut",
2235
- "related" => "http://test.host/people/1/hair_cut"
2236
- }
2237
- },
2238
- vehicles: {
2239
- links: {
2240
- self: "http://test.host/people/1/relationships/vehicles",
2241
- related: "http://test.host/people/1/vehicles"
2242
- }
2243
- }
2244
- }
2245
- }
2246
- },
2247
- json_response
2248
- )
2249
- ensure
2250
- JSONAPI.configuration = original_config
2251
- end
2252
-
2253
- def test_get_related_resource_nil
2254
- get :get_related_resource, {post_id: '17', relationship: 'author', source:'posts'}
2255
- assert_response :success
2256
- assert_hash_equals json_response,
2257
- {
2258
- data: nil
2259
- }
2260
-
2261
- end
2262
- end
2263
-
2264
- class BooksControllerTest < ActionController::TestCase
2265
- def test_books_include_correct_type
2266
- $test_user = Person.find(1)
2267
- get :index, {filter: {id: '1'}, include: 'authors'}
2268
- assert_response :success
2269
- assert_equal 'authors', json_response['included'][0]['type']
2270
- end
2271
- end
2272
-
2273
- class Api::V5::AuthorsControllerTest < ActionController::TestCase
2274
- def test_get_person_as_author
2275
- get :index, {filter: {id: '1'}}
2276
- assert_response :success
2277
- assert_equal 1, json_response['data'].size
2278
- assert_equal '1', json_response['data'][0]['id']
2279
- assert_equal 'authors', json_response['data'][0]['type']
2280
- assert_equal 'Joe Author', json_response['data'][0]['attributes']['name']
2281
- assert_equal nil, json_response['data'][0]['attributes']['email']
2282
- end
2283
-
2284
- def test_show_person_as_author
2285
- get :show, {id: '1'}
2286
- assert_response :success
2287
- assert_equal '1', json_response['data']['id']
2288
- assert_equal 'authors', json_response['data']['type']
2289
- assert_equal 'Joe Author', json_response['data']['attributes']['name']
2290
- assert_equal nil, json_response['data']['attributes']['email']
2291
- end
2292
-
2293
- def test_get_person_as_author_by_name_filter
2294
- get :index, {filter: {name: 'thor'}}
2295
- assert_response :success
2296
- assert_equal 3, json_response['data'].size
2297
- assert_equal '1', json_response['data'][0]['id']
2298
- assert_equal 'Joe Author', json_response['data'][0]['attributes']['name']
2299
- end
2300
-
2301
- def test_meta_serializer_options
2302
- JSONAPI.configuration.json_key_format = :camelized_key
2303
-
2304
- Api::V5::AuthorResource.class_eval do
2305
- def meta(options)
2306
- {
2307
- fixed: 'Hardcoded value',
2308
- computed: "#{self.class._type.to_s}: #{options[:serializer].link_builder.self_link(self)}",
2309
- computed_foo: options[:serialization_options][:foo],
2310
- options[:serializer].format_key('test_key') => 'test value'
2311
- }
2312
- end
2313
- end
2314
-
2315
- get :show, {id: '1'}
2316
- assert_response :success
2317
- assert_equal '1', json_response['data']['id']
2318
- assert_equal 'Hardcoded value', json_response['data']['meta']['fixed']
2319
- assert_equal 'authors: http://test.host/api/v5/authors/1', json_response['data']['meta']['computed']
2320
- assert_equal 'bar', json_response['data']['meta']['computed_foo']
2321
- assert_equal 'test value', json_response['data']['meta']['testKey']
2322
-
2323
- ensure
2324
- JSONAPI.configuration.json_key_format = :dasherized_key
2325
- Api::V5::AuthorResource.class_eval do
2326
- def meta(options)
2327
- # :nocov:
2328
- { }
2329
- # :nocov:
2330
- end
2331
- end
2332
- end
2333
-
2334
- def test_meta_serializer_hash_data
2335
- JSONAPI.configuration.json_key_format = :camelized_key
2336
-
2337
- Api::V5::AuthorResource.class_eval do
2338
- def meta(options)
2339
- {
2340
- custom_hash: {
2341
- fixed: 'Hardcoded value',
2342
- computed: "#{self.class._type.to_s}: #{options[:serializer].link_builder.self_link(self)}",
2343
- computed_foo: options[:serialization_options][:foo],
2344
- options[:serializer].format_key('test_key') => 'test value'
2345
- }
2346
- }
2347
- end
2348
- end
2349
-
2350
- get :show, {id: '1'}
2351
- assert_response :success
2352
- assert_equal '1', json_response['data']['id']
2353
- assert_equal 'Hardcoded value', json_response['data']['meta']['custom_hash']['fixed']
2354
- assert_equal 'authors: http://test.host/api/v5/authors/1', json_response['data']['meta']['custom_hash']['computed']
2355
- assert_equal 'bar', json_response['data']['meta']['custom_hash']['computed_foo']
2356
- assert_equal 'test value', json_response['data']['meta']['custom_hash']['testKey']
2357
-
2358
- ensure
2359
- JSONAPI.configuration.json_key_format = :dasherized_key
2360
- Api::V5::AuthorResource.class_eval do
2361
- def meta(options)
2362
- # :nocov:
2363
- { }
2364
- # :nocov:
2365
- end
2366
- end
2367
- end
2368
- end
2369
-
2370
- class BreedsControllerTest < ActionController::TestCase
2371
- # Note: Breed names go through the TitleValueFormatter
2372
-
2373
- def test_poro_index
2374
- get :index
2375
- assert_response :success
2376
- assert_equal '0', json_response['data'][0]['id']
2377
- assert_equal 'Persian', json_response['data'][0]['attributes']['name']
2378
- end
2379
-
2380
- def test_poro_show
2381
- get :show, {id: '0'}
2382
- assert_response :success
2383
- assert json_response['data'].is_a?(Hash)
2384
- assert_equal '0', json_response['data']['id']
2385
- assert_equal 'Persian', json_response['data']['attributes']['name']
2386
- end
2387
-
2388
- def test_poro_show_multiple
2389
- get :show, {id: '0,2'}
2390
-
2391
- assert_response :bad_request
2392
- assert_match /0,2 is not a valid value for id/, response.body
2393
- end
2394
-
2395
- def test_poro_create_simple
2396
- set_content_type_header!
2397
- post :create,
2398
- {
2399
- data: {
2400
- type: 'breeds',
2401
- attributes: {
2402
- name: 'tabby'
2403
- }
2404
- }
2405
- }
2406
-
2407
- assert_response :accepted
2408
- assert json_response['data'].is_a?(Hash)
2409
- assert_equal 'Tabby', json_response['data']['attributes']['name']
2410
- end
2411
-
2412
- def test_poro_create_validation_error
2413
- set_content_type_header!
2414
- post :create,
2415
- {
2416
- data: {
2417
- type: 'breeds',
2418
- attributes: {
2419
- name: ''
2420
- }
2421
- }
2422
- }
2423
-
2424
- assert_equal 1, json_response['errors'].size
2425
- assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code']
2426
- assert_match /name - can't be blank/, response.body
2427
- end
2428
-
2429
- def test_poro_create_update
2430
- set_content_type_header!
2431
- post :create,
2432
- {
2433
- data: {
2434
- type: 'breeds',
2435
- attributes: {
2436
- name: 'CALIC'
2437
- }
2438
- }
2439
- }
2440
-
2441
- assert_response :accepted
2442
- assert json_response['data'].is_a?(Hash)
2443
- assert_equal 'Calic', json_response['data']['attributes']['name']
2444
-
2445
- put :update,
2446
- {
2447
- id: json_response['data']['id'],
2448
- data: {
2449
- id: json_response['data']['id'],
2450
- type: 'breeds',
2451
- attributes: {
2452
- name: 'calico'
2453
- }
2454
- }
2455
- }
2456
- assert_response :success
2457
- assert json_response['data'].is_a?(Hash)
2458
- assert_equal 'Calico', json_response['data']['attributes']['name']
2459
- end
2460
-
2461
- def test_poro_delete
2462
- initial_count = $breed_data.breeds.keys.count
2463
- delete :destroy, {id: '3'}
2464
- assert_response :no_content
2465
- assert_equal initial_count - 1, $breed_data.breeds.keys.count
2466
- end
2467
-
2468
- end
2469
-
2470
- class Api::V2::PreferencesControllerTest < ActionController::TestCase
2471
- def test_show_singleton_resource_without_id
2472
- get :show
2473
- assert_response :success
2474
- end
2475
-
2476
- def test_update_singleton_resource_without_id
2477
- set_content_type_header!
2478
- patch :update,
2479
- data: {
2480
- id: "1",
2481
- type: "preferences",
2482
- attributes: {
2483
- }
2484
- }
2485
- assert_response :success
2486
- end
2487
- end
2488
-
2489
- class Api::V1::PostsControllerTest < ActionController::TestCase
2490
- def test_show_post_namespaced
2491
- get :show, {id: '1'}
2492
- assert_response :success
2493
- assert_equal 'http://test.host/api/v1/posts/1/relationships/writer', json_response['data']['relationships']['writer']['links']['self']
2494
- end
2495
-
2496
- def test_show_post_namespaced_include
2497
- get :show, {id: '1', include: 'writer'}
2498
- assert_response :success
2499
- assert_equal '1', json_response['data']['relationships']['writer']['data']['id']
2500
- assert_nil json_response['data']['relationships']['tags']
2501
- assert_equal '1', json_response['included'][0]['id']
2502
- assert_equal 'writers', json_response['included'][0]['type']
2503
- assert_equal 'joe@xyz.fake', json_response['included'][0]['attributes']['email']
2504
- end
2505
-
2506
- def test_index_filter_on_relationship_namespaced
2507
- get :index, {filter: {writer: '1'}}
2508
- assert_response :success
2509
- assert_equal 3, json_response['data'].size
2510
- end
2511
-
2512
- def test_sorting_desc_namespaced
2513
- get :index, {sort: '-title'}
2514
-
2515
- assert_response :success
2516
- assert_equal "Update This Later - Multiple", json_response['data'][0]['attributes']['title']
2517
- end
2518
-
2519
- def test_create_simple_namespaced
2520
- set_content_type_header!
2521
- post :create,
2522
- {
2523
- data: {
2524
- type: 'posts',
2525
- attributes: {
2526
- title: 'JR - now with Namespacing',
2527
- body: 'JSONAPIResources is the greatest thing since unsliced bread now that it has namespaced resources.'
2528
- },
2529
- relationships: {
2530
- writer: { data: {type: 'writers', id: '3'}}
2531
- }
2532
- }
2533
- }
2534
-
2535
- assert_response :created
2536
- assert json_response['data'].is_a?(Hash)
2537
- assert_equal 'JR - now with Namespacing', json_response['data']['attributes']['title']
2538
- assert_equal 'JSONAPIResources is the greatest thing since unsliced bread now that it has namespaced resources.',
2539
- json_response['data']['attributes']['body']
2540
- end
2541
-
2542
- end
2543
-
2544
- class FactsControllerTest < ActionController::TestCase
2545
- def test_type_formatting
2546
- original_config = JSONAPI.configuration.dup
2547
- JSONAPI.configuration.json_key_format = :camelized_key
2548
- get :show, {id: '1'}
2549
- assert_response :success
2550
- assert json_response['data'].is_a?(Hash)
2551
- assert_equal 'Jane Author', json_response['data']['attributes']['spouseName']
2552
- assert_equal 'First man to run across Antartica.', json_response['data']['attributes']['bio']
2553
- assert_equal 23.89/45.6, json_response['data']['attributes']['qualityRating']
2554
- assert_equal '47000.56', json_response['data']['attributes']['salary']
2555
- assert_equal '2013-08-07T20:25:00Z', json_response['data']['attributes']['dateTimeJoined']
2556
- assert_equal '1965-06-30', json_response['data']['attributes']['birthday']
2557
- assert_equal '2000-01-01T20:00:00Z', json_response['data']['attributes']['bedtime']
2558
- assert_equal 'abc', json_response['data']['attributes']['photo']
2559
- assert_equal false, json_response['data']['attributes']['cool']
2560
- ensure
2561
- JSONAPI.configuration = original_config
2562
- end
2563
-
2564
- def test_create_with_invalid_data
2565
- original_config = JSONAPI.configuration.dup
2566
- JSONAPI.configuration.json_key_format = :dasherized_key
2567
- set_content_type_header!
2568
- post :create,
2569
- {
2570
- data: {
2571
- type: 'facts',
2572
- attributes: {
2573
- bio: '',
2574
- :"quality-rating" => '',
2575
- :"spouse-name" => '',
2576
- salary: 100000,
2577
- :"date-time-joined" => '',
2578
- birthday: '',
2579
- bedtime: '',
2580
- photo: 'abc',
2581
- cool: false
2582
- },
2583
- relationships: {
2584
- }
2585
- }
2586
- }
2587
-
2588
- assert_response :unprocessable_entity
2589
-
2590
- assert_equal "/data/attributes/spouse-name", json_response['errors'][0]['source']['pointer']
2591
- assert_equal "can't be blank", json_response['errors'][0]['title']
2592
- assert_equal "spouse-name - can't be blank", json_response['errors'][0]['detail']
2593
-
2594
- assert_equal "/data/attributes/bio", json_response['errors'][1]['source']['pointer']
2595
- assert_equal "can't be blank", json_response['errors'][1]['title']
2596
- assert_equal "bio - can't be blank", json_response['errors'][1]['detail']
2597
- ensure
2598
- JSONAPI.configuration = original_config
2599
- end
2600
- end
2601
-
2602
- class Api::V2::BooksControllerTest < ActionController::TestCase
2603
- def setup
2604
- JSONAPI.configuration.json_key_format = :dasherized_key
2605
- $test_user = Person.find(1)
2606
- end
2607
-
2608
- def after_teardown
2609
- Api::V2::BookResource.paginator :offset
2610
- end
2611
-
2612
- def test_books_offset_pagination_no_params
2613
- Api::V2::BookResource.paginator :offset
2614
-
2615
- get :index
2616
- assert_response :success
2617
- assert_equal 10, json_response['data'].size
2618
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2619
- end
2620
-
2621
- def test_books_record_count_in_meta
2622
- Api::V2::BookResource.paginator :offset
2623
- JSONAPI.configuration.top_level_meta_include_record_count = true
2624
- get :index, {include: 'book-comments'}
2625
- JSONAPI.configuration.top_level_meta_include_record_count = false
2626
-
2627
- assert_response :success
2628
- assert_equal 901, json_response['meta']['record-count']
2629
- assert_equal 10, json_response['data'].size
2630
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2631
- end
2632
-
2633
- def test_books_record_count_in_meta_custom_name
2634
- Api::V2::BookResource.paginator :offset
2635
- JSONAPI.configuration.top_level_meta_include_record_count = true
2636
- JSONAPI.configuration.top_level_meta_record_count_key = 'total_records'
2637
-
2638
- get :index, {include: 'book-comments'}
2639
- JSONAPI.configuration.top_level_meta_include_record_count = false
2640
- JSONAPI.configuration.top_level_meta_record_count_key = :record_count
2641
-
2642
- assert_response :success
2643
- assert_equal 901, json_response['meta']['total-records']
2644
- assert_equal 10, json_response['data'].size
2645
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2646
- end
2647
-
2648
- def test_books_offset_pagination_no_params_includes_query_count_one_level
2649
- Api::V2::BookResource.paginator :offset
2650
-
2651
- count_queries do
2652
- get :index, {include: 'book-comments'}
2653
- end
2654
- assert_response :success
2655
- assert_equal 10, json_response['data'].size
2656
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2657
- assert_query_count(3)
2658
- end
2659
-
2660
- def test_books_offset_pagination_no_params_includes_query_count_two_levels
2661
- Api::V2::BookResource.paginator :offset
2662
-
2663
- count_queries do
2664
- get :index, {include: 'book-comments,book-comments.author'}
2665
- end
2666
- assert_response :success
2667
- assert_equal 10, json_response['data'].size
2668
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2669
- assert_query_count(4)
2670
- end
2671
-
2672
- def test_books_offset_pagination
2673
- Api::V2::BookResource.paginator :offset
2674
-
2675
- get :index, {page: {offset: 50, limit: 12}}
2676
- assert_response :success
2677
- assert_equal 12, json_response['data'].size
2678
- assert_equal 'Book 50', json_response['data'][0]['attributes']['title']
2679
- end
2680
-
2681
- def test_books_offset_pagination_bad_page_param
2682
- Api::V2::BookResource.paginator :offset
2683
-
2684
- get :index, {page: {offset_bad: 50, limit: 12}}
2685
- assert_response :bad_request
2686
- assert_match /offset_bad is not an allowed page parameter./, json_response['errors'][0]['detail']
2687
- end
2688
-
2689
- def test_books_offset_pagination_bad_param_value_limit_to_large
2690
- Api::V2::BookResource.paginator :offset
2691
-
2692
- get :index, {page: {offset: 50, limit: 1000}}
2693
- assert_response :bad_request
2694
- assert_match /Limit exceeds maximum page size of 20./, json_response['errors'][0]['detail']
2695
- end
2696
-
2697
- def test_books_offset_pagination_bad_param_value_limit_too_small
2698
- Api::V2::BookResource.paginator :offset
2699
-
2700
- get :index, {page: {offset: 50, limit: -1}}
2701
- assert_response :bad_request
2702
- assert_match /-1 is not a valid value for limit page parameter./, json_response['errors'][0]['detail']
2703
- end
2704
-
2705
- def test_books_offset_pagination_bad_param_offset_less_than_zero
2706
- Api::V2::BookResource.paginator :offset
2707
-
2708
- get :index, {page: {offset: -1, limit: 20}}
2709
- assert_response :bad_request
2710
- assert_match /-1 is not a valid value for offset page parameter./, json_response['errors'][0]['detail']
2711
- end
2712
-
2713
- def test_books_offset_pagination_invalid_page_format
2714
- Api::V2::BookResource.paginator :offset
2715
-
2716
- get :index, {page: 50}
2717
- assert_response :bad_request
2718
- assert_match /Invalid Page Object./, json_response['errors'][0]['detail']
2719
- end
2720
-
2721
- def test_books_paged_pagination_no_params
2722
- Api::V2::BookResource.paginator :paged
2723
-
2724
- get :index
2725
- assert_response :success
2726
- assert_equal 10, json_response['data'].size
2727
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2728
- end
2729
-
2730
- def test_books_paged_pagination_no_page
2731
- Api::V2::BookResource.paginator :paged
2732
-
2733
- get :index, {page: {size: 12}}
2734
- assert_response :success
2735
- assert_equal 12, json_response['data'].size
2736
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2737
- end
2738
-
2739
- def test_books_paged_pagination
2740
- Api::V2::BookResource.paginator :paged
2741
-
2742
- get :index, {page: {number: 3, size: 12}}
2743
- assert_response :success
2744
- assert_equal 12, json_response['data'].size
2745
- assert_equal 'Book 24', json_response['data'][0]['attributes']['title']
2746
- end
2747
-
2748
- def test_books_paged_pagination_bad_page_param
2749
- Api::V2::BookResource.paginator :paged
2750
-
2751
- get :index, {page: {number_bad: 50, size: 12}}
2752
- assert_response :bad_request
2753
- assert_match /number_bad is not an allowed page parameter./, json_response['errors'][0]['detail']
2754
- end
2755
-
2756
- def test_books_paged_pagination_bad_param_value_limit_to_large
2757
- Api::V2::BookResource.paginator :paged
2758
-
2759
- get :index, {page: {number: 50, size: 1000}}
2760
- assert_response :bad_request
2761
- assert_match /size exceeds maximum page size of 20./, json_response['errors'][0]['detail']
2762
- end
2763
-
2764
- def test_books_paged_pagination_bad_param_value_limit_too_small
2765
- Api::V2::BookResource.paginator :paged
2766
-
2767
- get :index, {page: {number: 50, size: -1}}
2768
- assert_response :bad_request
2769
- assert_match /-1 is not a valid value for size page parameter./, json_response['errors'][0]['detail']
2770
- end
2771
-
2772
- def test_books_paged_pagination_invalid_page_format_incorrect
2773
- Api::V2::BookResource.paginator :paged
2774
-
2775
- get :index, {page: 'qwerty'}
2776
- assert_response :bad_request
2777
- assert_match /0 is not a valid value for number page parameter./, json_response['errors'][0]['detail']
2778
- end
2779
-
2780
- def test_books_paged_pagination_invalid_page_format_interpret_int
2781
- Api::V2::BookResource.paginator :paged
2782
-
2783
- get :index, {page: 3}
2784
- assert_response :success
2785
- assert_equal 10, json_response['data'].size
2786
- assert_equal 'Book 20', json_response['data'][0]['attributes']['title']
2787
- end
2788
-
2789
- def test_books_included_paged
2790
- Api::V2::BookResource.paginator :offset
2791
-
2792
- count_queries do
2793
- get :index, {filter: {id: '0'}, include: 'book-comments'}
2794
- end
2795
- assert_response :success
2796
- assert_equal 1, json_response['data'].size
2797
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2798
- assert_query_count(3)
2799
- end
2800
-
2801
- def test_books_banned_non_book_admin
2802
- $test_user = Person.find(1)
2803
- Api::V2::BookResource.paginator :offset
2804
- JSONAPI.configuration.top_level_meta_include_record_count = true
2805
- count_queries do
2806
- get :index, {page: {offset: 50, limit: 12}}
2807
- end
2808
- assert_response :success
2809
- assert_equal 12, json_response['data'].size
2810
- assert_equal 'Book 50', json_response['data'][0]['attributes']['title']
2811
- assert_equal 901, json_response['meta']['record-count']
2812
- assert_query_count(2)
2813
- ensure
2814
- JSONAPI.configuration.top_level_meta_include_record_count = false
2815
- end
2816
-
2817
- def test_books_banned_non_book_admin_includes_switched
2818
- $test_user = Person.find(1)
2819
- Api::V2::BookResource.paginator :offset
2820
- JSONAPI.configuration.top_level_meta_include_record_count = true
2821
- count_queries do
2822
- get :index, {page: {offset: 0, limit: 12}, include: 'book-comments'}
2823
- end
2824
-
2825
- assert_response :success
2826
- assert_equal 12, json_response['data'].size
2827
- assert_equal 130, json_response['included'].size
2828
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2829
- assert_equal 26, json_response['data'][0]['relationships']['book-comments']['data'].size
2830
- assert_equal 'book-comments', json_response['included'][0]['type']
2831
- assert_equal 901, json_response['meta']['record-count']
2832
- assert_query_count(3)
2833
- ensure
2834
- JSONAPI.configuration.top_level_meta_include_record_count = false
2835
- end
2836
-
2837
- def test_books_banned_non_book_admin_includes_nested_includes
2838
- $test_user = Person.find(1)
2839
- JSONAPI.configuration.top_level_meta_include_record_count = true
2840
- Api::V2::BookResource.paginator :offset
2841
- count_queries do
2842
- get :index, {page: {offset: 0, limit: 12}, include: 'book-comments.author'}
2843
- end
2844
- assert_response :success
2845
- assert_equal 12, json_response['data'].size
2846
- assert_equal 131, json_response['included'].size
2847
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2848
- assert_equal 901, json_response['meta']['record-count']
2849
- assert_query_count(4)
2850
- ensure
2851
- JSONAPI.configuration.top_level_meta_include_record_count = false
2852
- end
2853
-
2854
- def test_books_banned_admin
2855
- $test_user = Person.find(5)
2856
- Api::V2::BookResource.paginator :offset
2857
- JSONAPI.configuration.top_level_meta_include_record_count = true
2858
- count_queries do
2859
- get :index, {page: {offset: 50, limit: 12}, filter: {banned: 'true'}}
2860
- end
2861
- assert_response :success
2862
- assert_equal 12, json_response['data'].size
2863
- assert_equal 'Book 651', json_response['data'][0]['attributes']['title']
2864
- assert_equal 99, json_response['meta']['record-count']
2865
- assert_query_count(2)
2866
- ensure
2867
- JSONAPI.configuration.top_level_meta_include_record_count = false
2868
- end
2869
-
2870
- def test_books_not_banned_admin
2871
- $test_user = Person.find(5)
2872
- Api::V2::BookResource.paginator :offset
2873
- JSONAPI.configuration.top_level_meta_include_record_count = true
2874
- count_queries do
2875
- get :index, {page: {offset: 50, limit: 12}, filter: {banned: 'false'}}
2876
- end
2877
- assert_response :success
2878
- assert_equal 12, json_response['data'].size
2879
- assert_equal 'Book 50', json_response['data'][0]['attributes']['title']
2880
- assert_equal 901, json_response['meta']['record-count']
2881
- assert_query_count(2)
2882
- ensure
2883
- JSONAPI.configuration.top_level_meta_include_record_count = false
2884
- end
2885
-
2886
- def test_books_banned_non_book_admin_overlapped
2887
- $test_user = Person.find(1)
2888
- Api::V2::BookResource.paginator :offset
2889
- JSONAPI.configuration.top_level_meta_include_record_count = true
2890
- count_queries do
2891
- get :index, {page: {offset: 590, limit: 20}}
2892
- end
2893
- assert_response :success
2894
- assert_equal 20, json_response['data'].size
2895
- assert_equal 'Book 590', json_response['data'][0]['attributes']['title']
2896
- assert_equal 901, json_response['meta']['record-count']
2897
- assert_query_count(2)
2898
- ensure
2899
- JSONAPI.configuration.top_level_meta_include_record_count = false
2900
- end
2901
-
2902
- def test_books_included_exclude_unapproved
2903
- $test_user = Person.find(1)
2904
- Api::V2::BookResource.paginator :none
2905
-
2906
- count_queries do
2907
- get :index, {filter: {id: '0,1,2,3,4'}, include: 'book-comments'}
2908
- end
2909
- assert_response :success
2910
- assert_equal 5, json_response['data'].size
2911
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2912
- assert_equal 130, json_response['included'].size
2913
- assert_equal 26, json_response['data'][0]['relationships']['book-comments']['data'].size
2914
- assert_query_count(2)
2915
- end
2916
-
2917
- def test_books_included_all_comments_for_admin
2918
- $test_user = Person.find(5)
2919
- Api::V2::BookResource.paginator :none
2920
-
2921
- get :index, {filter: {id: '0,1,2,3,4'}, include: 'book-comments'}
2922
- assert_response :success
2923
- assert_equal 5, json_response['data'].size
2924
- assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
2925
- assert_equal 255, json_response['included'].size
2926
- assert_equal 51, json_response['data'][0]['relationships']['book-comments']['data'].size
2927
- end
2928
-
2929
- def test_books_filter_by_book_comment_id_limited_user
2930
- $test_user = Person.find(1)
2931
- get :index, {filter: {book_comments: '0,52' }}
2932
- assert_response :success
2933
- assert_equal 1, json_response['data'].size
2934
- end
2935
-
2936
- def test_books_filter_by_book_comment_id_admin_user
2937
- $test_user = Person.find(5)
2938
- get :index, {filter: {book_comments: '0,52' }}
2939
- assert_response :success
2940
- assert_equal 2, json_response['data'].size
2941
- end
2942
-
2943
- def test_books_create_unapproved_comment_limited_user_using_relation_name
2944
- set_content_type_header!
2945
- $test_user = Person.find(1)
2946
-
2947
- book_comment = BookComment.create(body: 'Not Approved dummy comment', approved: false)
2948
- post :create_relationship, {book_id: 1, relationship: 'book_comments', data: [{type: 'book_comments', id: book_comment.id}]}
2949
-
2950
- # Note the not_found response is coming from the BookComment's overridden records method, not the relation
2951
- assert_response :not_found
2952
-
2953
- ensure
2954
- book_comment.delete
2955
- end
2956
-
2957
- def test_books_create_approved_comment_limited_user_using_relation_name
2958
- set_content_type_header!
2959
- $test_user = Person.find(1)
2960
-
2961
- book_comment = BookComment.create(body: 'Approved dummy comment', approved: true)
2962
- post :create_relationship, {book_id: 1, relationship: 'book_comments', data: [{type: 'book_comments', id: book_comment.id}]}
2963
- assert_response :success
2964
-
2965
- ensure
2966
- book_comment.delete
2967
- end
2968
-
2969
- def test_books_delete_unapproved_comment_limited_user_using_relation_name
2970
- $test_user = Person.find(1)
2971
-
2972
- book_comment = BookComment.create(book_id: 1, body: 'Not Approved dummy comment', approved: false)
2973
- delete :destroy_relationship, {book_id: 1, relationship: 'book_comments', data: [{type: 'book_comments', id: book_comment.id}]}
2974
- assert_response :not_found
2975
-
2976
- ensure
2977
- book_comment.delete
2978
- end
2979
-
2980
- def test_books_delete_approved_comment_limited_user_using_relation_name
2981
- $test_user = Person.find(1)
2982
-
2983
- book_comment = BookComment.create(book_id: 1, body: 'Approved dummy comment', approved: true)
2984
- delete :destroy_relationship, {book_id: 1, relationship: 'book_comments', data: [{type: 'book_comments', id: book_comment.id}]}
2985
- assert_response :no_content
2986
-
2987
- ensure
2988
- book_comment.delete
2989
- end
2990
- end
2991
-
2992
- class Api::V2::BookCommentsControllerTest < ActionController::TestCase
2993
- def setup
2994
- JSONAPI.configuration.json_key_format = :dasherized_key
2995
- Api::V2::BookCommentResource.paginator :none
2996
- $test_user = Person.find(1)
2997
- end
2998
-
2999
- def test_book_comments_all_for_admin
3000
- $test_user = Person.find(5)
3001
- count_queries do
3002
- get :index
3003
- end
3004
- assert_response :success
3005
- assert_equal 255, json_response['data'].size
3006
- assert_query_count(1)
3007
- end
3008
-
3009
- def test_book_comments_unapproved_context_based
3010
- $test_user = Person.find(5)
3011
- count_queries do
3012
- get :index, {filter: {approved: 'false'}}
3013
- end
3014
- assert_response :success
3015
- assert_equal 125, json_response['data'].size
3016
- assert_query_count(1)
3017
- end
3018
-
3019
- def test_book_comments_exclude_unapproved_context_based
3020
- $test_user = Person.find(1)
3021
- count_queries do
3022
- get :index
3023
- end
3024
- assert_response :success
3025
- assert_equal 130, json_response['data'].size
3026
- assert_query_count(1)
3027
- end
3028
- end
3029
-
3030
- class Api::V4::BooksControllerTest < ActionController::TestCase
3031
- def setup
3032
- JSONAPI.configuration.json_key_format = :camelized_key
3033
- end
3034
-
3035
- def test_books_offset_pagination_meta
3036
- original_config = JSONAPI.configuration.dup
3037
- JSONAPI.configuration.operations_processor = :counting_active_record
3038
- Api::V4::BookResource.paginator :offset
3039
- get :index, {page: {offset: 50, limit: 12}}
3040
- assert_response :success
3041
- assert_equal 12, json_response['data'].size
3042
- assert_equal 'Book 50', json_response['data'][0]['attributes']['title']
3043
- assert_equal 901, json_response['meta']['totalRecords']
3044
- ensure
3045
- JSONAPI.configuration = original_config
3046
- end
3047
-
3048
- def test_books_operation_links
3049
- original_config = JSONAPI.configuration.dup
3050
- JSONAPI.configuration.operations_processor = :counting_active_record
3051
- Api::V4::BookResource.paginator :offset
3052
- get :index, {page: {offset: 50, limit: 12}}
3053
- assert_response :success
3054
- assert_equal 12, json_response['data'].size
3055
- assert_equal 'Book 50', json_response['data'][0]['attributes']['title']
3056
- assert_equal 5, json_response['links'].size
3057
- assert_equal 'https://test_corp.com', json_response['links']['spec']
3058
- ensure
3059
- JSONAPI.configuration = original_config
3060
- end
3061
- end
3062
-
3063
- class CategoriesControllerTest < ActionController::TestCase
3064
- def test_index_default_filter
3065
- get :index
3066
- assert_response :success
3067
- assert json_response['data'].is_a?(Array)
3068
- assert_equal 3, json_response['data'].size
3069
- end
3070
-
3071
- def test_index_default_filter_override
3072
- get :index, { filter: { status: 'inactive' } }
3073
- assert_response :success
3074
- assert json_response['data'].is_a?(Array)
3075
- assert_equal 4, json_response['data'].size
3076
- end
3077
- end
3078
-
3079
- class Api::V1::PlanetsControllerTest < ActionController::TestCase
3080
- def test_save_model_callbacks
3081
- set_content_type_header!
3082
- post :create,
3083
- {
3084
- data: {
3085
- type: 'planets',
3086
- attributes: {
3087
- name: 'Zeus',
3088
- description: 'The largest planet in the solar system. Discovered in 2015.'
3089
- }
3090
- }
3091
- }
3092
-
3093
- assert_response :created
3094
- assert json_response['data'].is_a?(Hash)
3095
- assert_equal 'Zeus', json_response['data']['attributes']['name']
3096
- end
3097
-
3098
- def test_save_model_callbacks_fail
3099
- set_content_type_header!
3100
- post :create,
3101
- {
3102
- data: {
3103
- type: 'planets',
3104
- attributes: {
3105
- name: 'Pluto',
3106
- description: 'Yes, it is a planet.'
3107
- }
3108
- }
3109
- }
3110
-
3111
- assert_response :unprocessable_entity
3112
- assert_match /Save failed or was cancelled/, json_response['errors'][0]['detail']
3113
- end
3114
- end
3115
-
3116
- class Api::V1::MoonsControllerTest < ActionController::TestCase
3117
- def test_get_related_resource
3118
- get :get_related_resource, {crater_id: 'S56D', relationship: 'moon', source: "api/v1/craters"}
3119
- assert_response :success
3120
- assert_hash_equals({
3121
- data: {
3122
- id: "1",
3123
- type: "moons",
3124
- links: {self: "http://test.host/api/v1/moons/1"},
3125
- attributes: {name: "Titan", description: "Best known of the Saturn moons."},
3126
- relationships: {
3127
- planet: {links: {self: "http://test.host/api/v1/moons/1/relationships/planet", related: "http://test.host/api/v1/moons/1/planet"}},
3128
- craters: {links: {self: "http://test.host/api/v1/moons/1/relationships/craters", related: "http://test.host/api/v1/moons/1/craters"}}}
3129
- }
3130
- }, json_response)
3131
- end
3132
-
3133
- def test_get_related_resources_with_select_some_db_columns
3134
- PlanetResource.paginator :paged
3135
- original_config = JSONAPI.configuration.dup
3136
- JSONAPI.configuration.top_level_meta_include_record_count = true
3137
- JSONAPI.configuration.json_key_format = :dasherized_key
3138
- get :get_related_resources, {planet_id: '1', relationship: 'moons', source: 'api/v1/planets'}
3139
- assert_response :success
3140
- assert_equal 1, json_response['meta']['record-count']
3141
- ensure
3142
- JSONAPI.configuration = original_config
3143
- end
3144
- end
3145
-
3146
- class Api::V1::CratersControllerTest < ActionController::TestCase
3147
- def test_show_single
3148
- get :show, {id: 'S56D'}
3149
- assert_response :success
3150
- assert json_response['data'].is_a?(Hash)
3151
- assert_equal 'S56D', json_response['data']['attributes']['code']
3152
- assert_equal 'Very large crater', json_response['data']['attributes']['description']
3153
- assert_nil json_response['included']
3154
- end
3155
-
3156
- def test_get_related_resources
3157
- get :get_related_resources, {moon_id: '1', relationship: 'craters', source: "api/v1/moons"}
3158
- assert_response :success
3159
- assert_hash_equals({
3160
- data: [
3161
- {
3162
- id:"A4D3",
3163
- type:"craters",
3164
- links:{self: "http://test.host/api/v1/craters/A4D3"},
3165
- attributes:{code: "A4D3", description: "Small crater"},
3166
- relationships:{moon: {links: {self: "http://test.host/api/v1/craters/A4D3/relationships/moon", related: "http://test.host/api/v1/craters/A4D3/moon"}}}
3167
- },
3168
- {
3169
- id: "S56D",
3170
- type: "craters",
3171
- links:{self: "http://test.host/api/v1/craters/S56D"},
3172
- attributes:{code: "S56D", description: "Very large crater"},
3173
- relationships:{moon: {links: {self: "http://test.host/api/v1/craters/S56D/relationships/moon", related: "http://test.host/api/v1/craters/S56D/moon"}}}
3174
- }
3175
- ]
3176
- }, json_response)
3177
- end
3178
-
3179
- def test_show_relationship
3180
- get :show_relationship, {crater_id: 'S56D', relationship: 'moon'}
3181
-
3182
- assert_response :success
3183
- assert_equal "moons", json_response['data']['type']
3184
- assert_equal "1", json_response['data']['id']
3185
- end
3186
- end
3187
-
3188
- class CarsControllerTest < ActionController::TestCase
3189
- def setup
3190
- JSONAPI.configuration.json_key_format = :camelized_key
3191
- end
3192
-
3193
- def test_create_sti
3194
- set_content_type_header!
3195
- post :create,
3196
- {
3197
- data: {
3198
- type: 'cars',
3199
- attributes: {
3200
- make: 'Toyota',
3201
- model: 'Tercel',
3202
- serialNumber: 'asasdsdadsa13544235',
3203
- driveLayout: 'FWD'
3204
- }
3205
- }
3206
- }
3207
-
3208
- assert_response :created
3209
- assert json_response['data'].is_a?(Hash)
3210
- assert_equal 'cars', json_response['data']['type']
3211
- assert_equal 'Toyota', json_response['data']['attributes']['make']
3212
- assert_equal 'FWD', json_response['data']['attributes']['driveLayout']
3213
- end
3214
- end
3215
-
3216
- class VehiclesControllerTest < ActionController::TestCase
3217
- def setup
3218
- JSONAPI.configuration.json_key_format = :camelized_key
3219
- end
3220
-
3221
- def test_immutable_create_not_supported
3222
- set_content_type_header!
3223
-
3224
- assert_raises ActionController::UrlGenerationError do
3225
- post :create,
3226
- {
3227
- data: {
3228
- type: 'cars',
3229
- attributes: {
3230
- make: 'Toyota',
3231
- model: 'Corrola',
3232
- serialNumber: 'dsvffsfv',
3233
- driveLayout: 'FWD'
3234
- }
3235
- }
3236
- }
3237
- end
3238
- end
3239
-
3240
- def test_immutable_update_not_supported
3241
- set_content_type_header!
3242
-
3243
- assert_raises ActionController::UrlGenerationError do
3244
- patch :update,
3245
- data: {
3246
- id: '1',
3247
- type: 'cars',
3248
- attributes: {
3249
- make: 'Toyota',
3250
- }
3251
- }
3252
- end
3253
- end
3254
- end
3255
-
3256
- class Api::V7::ClientsControllerTest < ActionController::TestCase
3257
- def test_get_namespaced_model_not_matching_resource_using_model_hint
3258
- get :index
3259
- assert_response :success
3260
- assert_equal 'clients', json_response['data'][0]['type']
3261
- ensure
3262
- Api::V7::ClientResource._model_hints['api/v7/customer'] = 'clients'
3263
- end
3264
-
3265
- def test_get_namespaced_model_not_matching_resource_not_using_model_hint
3266
- Api::V7::ClientResource._model_hints.delete('api/v7/customer')
3267
- get :index
3268
- assert_response :success
3269
- assert_equal 'customers', json_response['data'][0]['type']
3270
- ensure
3271
- Api::V7::ClientResource._model_hints['api/v7/customer'] = 'clients'
3272
- end
3273
- end
3274
-
3275
- class Api::V7::CustomersControllerTest < ActionController::TestCase
3276
- def test_get_namespaced_model_matching_resource
3277
- get :index
3278
- assert_response :success
3279
- assert_equal 'customers', json_response['data'][0]['type']
3280
- end
3281
- end
3282
-
3283
- class Api::V7::CategoriesControllerTest < ActionController::TestCase
3284
- def test_uncaught_error_in_controller_translated_to_internal_server_error
3285
-
3286
- get :show, {id: '1'}
3287
- assert_response 500
3288
- assert_match /Internal Server Error/, json_response['errors'][0]['detail']
3289
- end
3290
-
3291
- def test_not_whitelisted_error_in_controller
3292
- original_config = JSONAPI.configuration.dup
3293
- JSONAPI.configuration.operations_processor = :error_raising
3294
- JSONAPI.configuration.exception_class_whitelist = []
3295
- get :show, {id: '1'}
3296
- assert_response 500
3297
- assert_match /Internal Server Error/, json_response['errors'][0]['detail']
3298
- ensure
3299
- JSONAPI.configuration = original_config
3300
- end
3301
-
3302
- def test_whitelisted_error_in_controller
3303
- original_config = JSONAPI.configuration.dup
3304
- JSONAPI.configuration.operations_processor = :error_raising
3305
- JSONAPI.configuration.exception_class_whitelist = [PostsController::SubSpecialError]
3306
- assert_raises PostsController::SubSpecialError do
3307
- get :show, {id: '1'}
3308
- end
3309
- ensure
3310
- JSONAPI.configuration = original_config
3311
- end
3312
- end