jsonapi-resources 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +274 -102
- data/jsonapi-resources.gemspec +1 -0
- data/lib/jsonapi-resources.rb +15 -0
- data/lib/jsonapi/active_record_operations_processor.rb +21 -10
- data/lib/jsonapi/acts_as_resource_controller.rb +175 -0
- data/lib/jsonapi/configuration.rb +11 -0
- data/lib/jsonapi/error_codes.rb +7 -4
- data/lib/jsonapi/exceptions.rb +23 -15
- data/lib/jsonapi/formatter.rb +5 -5
- data/lib/jsonapi/include_directives.rb +67 -0
- data/lib/jsonapi/operation.rb +185 -65
- data/lib/jsonapi/operation_result.rb +38 -5
- data/lib/jsonapi/operation_results.rb +33 -0
- data/lib/jsonapi/operations_processor.rb +49 -9
- data/lib/jsonapi/paginator.rb +31 -17
- data/lib/jsonapi/request.rb +347 -163
- data/lib/jsonapi/resource.rb +159 -56
- data/lib/jsonapi/resource_controller.rb +1 -234
- data/lib/jsonapi/resource_serializer.rb +55 -69
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/response_document.rb +87 -0
- data/lib/jsonapi/routing_ext.rb +17 -11
- data/test/controllers/controller_test.rb +602 -326
- data/test/fixtures/active_record.rb +96 -6
- data/test/fixtures/line_items.yml +7 -1
- data/test/fixtures/numeros_telefone.yml +3 -0
- data/test/fixtures/purchase_orders.yml +6 -0
- data/test/integration/requests/request_test.rb +129 -60
- data/test/integration/routes/routes_test.rb +17 -17
- data/test/test_helper.rb +23 -5
- data/test/unit/jsonapi_request/jsonapi_request_test.rb +48 -0
- data/test/unit/operation/operations_processor_test.rb +242 -54
- data/test/unit/resource/resource_test.rb +108 -2
- data/test/unit/serializer/include_directives_test.rb +108 -0
- data/test/unit/serializer/response_document_test.rb +61 -0
- data/test/unit/serializer/serializer_test.rb +679 -520
- metadata +26 -2
@@ -18,6 +18,7 @@ module JSONAPI
|
|
18
18
|
|
19
19
|
@fields = options.fetch(:fields, {})
|
20
20
|
@include = options.fetch(:include, [])
|
21
|
+
@include_directives = options[:include_directives]
|
21
22
|
@key_formatter = options.fetch(:key_formatter, JSONAPI.configuration.key_formatter)
|
22
23
|
@route_formatter = options.fetch(:route_formatter, JSONAPI.configuration.route_formatter)
|
23
24
|
@base_url = options.fetch(:base_url, '')
|
@@ -28,10 +29,9 @@ module JSONAPI
|
|
28
29
|
is_resource_collection = source.respond_to?(:to_ary)
|
29
30
|
|
30
31
|
@included_objects = {}
|
32
|
+
@include_directives ||= JSONAPI::IncludeDirectives.new(@include)
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
process_primary(source, requested_associations)
|
34
|
+
process_primary(source, @include_directives.include_directives)
|
35
35
|
|
36
36
|
included_objects = []
|
37
37
|
primary_objects = []
|
@@ -47,11 +47,7 @@ module JSONAPI
|
|
47
47
|
|
48
48
|
primary_hash = {data: is_resource_collection ? primary_objects : primary_objects[0]}
|
49
49
|
|
50
|
-
if included_objects.size > 0
|
51
|
-
primary_hash[:included] = included_objects
|
52
|
-
else
|
53
|
-
primary_hash
|
54
|
-
end
|
50
|
+
primary_hash[:included] = included_objects if included_objects.size > 0
|
55
51
|
primary_hash
|
56
52
|
end
|
57
53
|
|
@@ -72,34 +68,11 @@ module JSONAPI
|
|
72
68
|
end
|
73
69
|
|
74
70
|
private
|
75
|
-
# Convert an array of associated objects to include along with the primary document in the form of
|
76
|
-
# ['comments','author','comments.tags','author.posts'] into a structure that tells what we need to include
|
77
|
-
# from each association.
|
78
|
-
def parse_includes(includes)
|
79
|
-
requested_associations = {}
|
80
|
-
includes.each do |include|
|
81
|
-
include = include.to_s.underscore
|
82
|
-
|
83
|
-
pos = include.index('.')
|
84
|
-
if pos
|
85
|
-
association_name = include[0, pos].to_sym
|
86
|
-
requested_associations[association_name] ||= {}
|
87
|
-
requested_associations[association_name].store(:include_children, true)
|
88
|
-
requested_associations[association_name].store(:include_related, parse_includes([include[pos+1, include.length]]))
|
89
|
-
else
|
90
|
-
association_name = include.to_sym
|
91
|
-
requested_associations[association_name] ||= {}
|
92
|
-
requested_associations[association_name].store(:include, true)
|
93
|
-
end
|
94
|
-
end if includes.is_a?(Array)
|
95
|
-
return requested_associations
|
96
|
-
end
|
97
|
-
|
98
71
|
# Process the primary source object(s). This will then serialize associated object recursively based on the
|
99
72
|
# requested includes. Fields are controlled fields option for each resource type, such
|
100
73
|
# as fields: { people: [:id, :email, :comments], posts: [:id, :title, :author], comments: [:id, :body, :post]}
|
101
74
|
# The fields options controls both fields and included links references.
|
102
|
-
def process_primary(source,
|
75
|
+
def process_primary(source, include_directives)
|
103
76
|
if source.respond_to?(:to_ary)
|
104
77
|
source.each do |resource|
|
105
78
|
id = resource.id
|
@@ -107,25 +80,37 @@ module JSONAPI
|
|
107
80
|
set_primary(@primary_class_name, id)
|
108
81
|
end
|
109
82
|
|
110
|
-
add_included_object(@primary_class_name, id, object_hash(resource,
|
83
|
+
add_included_object(@primary_class_name, id, object_hash(resource, include_directives), true)
|
111
84
|
end
|
112
85
|
else
|
113
86
|
return {} if source.nil?
|
114
87
|
|
115
88
|
resource = source
|
116
89
|
id = resource.id
|
117
|
-
add_included_object(@primary_class_name, id, object_hash(source,
|
90
|
+
add_included_object(@primary_class_name, id, object_hash(source, include_directives), true)
|
118
91
|
end
|
119
92
|
end
|
120
93
|
|
121
94
|
# Returns a serialized hash for the source model
|
122
|
-
def object_hash(source,
|
123
|
-
obj_hash =
|
124
|
-
|
95
|
+
def object_hash(source, include_directives)
|
96
|
+
obj_hash = {}
|
97
|
+
|
98
|
+
id_format = source.class._attribute_options(:id)[:format]
|
99
|
+
#protect against ids that were declared as an attribute, but did not have a format set.
|
100
|
+
id_format = 'id' if id_format == :default
|
101
|
+
obj_hash['id'] = format_value(source.id, id_format)
|
125
102
|
|
126
103
|
obj_hash['type'] = format_key(source.class._type.to_s)
|
127
|
-
|
128
|
-
|
104
|
+
|
105
|
+
links = relationship_links(source)
|
106
|
+
obj_hash['links'] = links unless links.empty?
|
107
|
+
|
108
|
+
attributes = attribute_hash(source)
|
109
|
+
obj_hash['attributes'] = attributes unless attributes.empty?
|
110
|
+
|
111
|
+
relationships = relationship_data(source, include_directives)
|
112
|
+
obj_hash['relationships'] = relationships unless relationships.nil? || relationships.empty?
|
113
|
+
|
129
114
|
return obj_hash
|
130
115
|
end
|
131
116
|
|
@@ -142,20 +127,13 @@ module JSONAPI
|
|
142
127
|
|
143
128
|
fields.each_with_object({}) do |name, hash|
|
144
129
|
format = source.class._attribute_options(name)[:format]
|
145
|
-
|
146
|
-
|
130
|
+
unless name == :id
|
131
|
+
hash[format_key(name)] = format_value(source.send(name), format)
|
147
132
|
end
|
148
|
-
hash[format_key(name)] = format_value(
|
149
|
-
source.send(name),
|
150
|
-
format,
|
151
|
-
source
|
152
|
-
)
|
153
133
|
end
|
154
134
|
end
|
155
135
|
|
156
|
-
|
157
|
-
# class's fetchable method
|
158
|
-
def links_hash(source, requested_associations)
|
136
|
+
def relationship_data(source, include_directives)
|
159
137
|
associations = source.class._associations
|
160
138
|
requested = requested_fields(source.class._type)
|
161
139
|
fields = associations.keys
|
@@ -167,15 +145,14 @@ module JSONAPI
|
|
167
145
|
|
168
146
|
included_associations = source.fetchable_fields & associations.keys
|
169
147
|
|
170
|
-
|
171
|
-
links[:self] = self_href(source)
|
148
|
+
data = {}
|
172
149
|
|
173
|
-
associations.each_with_object(
|
150
|
+
associations.each_with_object(data) do |(name, association), hash|
|
174
151
|
if included_associations.include? name
|
175
|
-
ia =
|
152
|
+
ia = include_directives[:include_related][name]
|
176
153
|
|
177
154
|
include_linkage = ia && ia[:include]
|
178
|
-
include_linked_children = ia && ia[:
|
155
|
+
include_linked_children = ia && !ia[:include_related].empty?
|
179
156
|
|
180
157
|
if field_set.include?(name)
|
181
158
|
hash[format_key(name)] = link_object(source, association, include_linkage)
|
@@ -193,9 +170,9 @@ module JSONAPI
|
|
193
170
|
id = resource.id
|
194
171
|
associations_only = already_serialized?(type, id)
|
195
172
|
if include_linkage && !associations_only
|
196
|
-
add_included_object(type, id, object_hash(resource, ia
|
173
|
+
add_included_object(type, id, object_hash(resource, ia))
|
197
174
|
elsif include_linked_children || associations_only
|
198
|
-
|
175
|
+
relationship_data(resource, ia)
|
199
176
|
end
|
200
177
|
end
|
201
178
|
elsif association.is_a?(JSONAPI::Association::HasMany)
|
@@ -204,9 +181,9 @@ module JSONAPI
|
|
204
181
|
id = resource.id
|
205
182
|
associations_only = already_serialized?(type, id)
|
206
183
|
if include_linkage && !associations_only
|
207
|
-
add_included_object(type, id, object_hash(resource, ia
|
184
|
+
add_included_object(type, id, object_hash(resource, ia))
|
208
185
|
elsif include_linked_children || associations_only
|
209
|
-
|
186
|
+
relationship_data(resource, ia)
|
210
187
|
end
|
211
188
|
end
|
212
189
|
end
|
@@ -215,6 +192,13 @@ module JSONAPI
|
|
215
192
|
end
|
216
193
|
end
|
217
194
|
|
195
|
+
def relationship_links(source)
|
196
|
+
links = {}
|
197
|
+
links[:self] = self_href(source)
|
198
|
+
|
199
|
+
links
|
200
|
+
end
|
201
|
+
|
218
202
|
def formatted_module_path(source)
|
219
203
|
source.class.name =~ /::[^:]+\Z/ ? (@route_formatter.format($`).freeze.gsub('::', '/') + '/').downcase : ''
|
220
204
|
end
|
@@ -233,7 +217,7 @@ module JSONAPI
|
|
233
217
|
end
|
234
218
|
|
235
219
|
def self_link(source, association)
|
236
|
-
"#{self_href(source)}/
|
220
|
+
"#{self_href(source)}/relationships/#{format_route(association.name)}"
|
237
221
|
end
|
238
222
|
|
239
223
|
def related_link(source, association)
|
@@ -263,17 +247,19 @@ module JSONAPI
|
|
263
247
|
|
264
248
|
def link_object_has_one(source, association)
|
265
249
|
link_object_hash = {}
|
266
|
-
link_object_hash[:
|
267
|
-
link_object_hash[:
|
268
|
-
link_object_hash[:
|
250
|
+
link_object_hash[:links] = {}
|
251
|
+
link_object_hash[:links][:self] = self_link(source, association)
|
252
|
+
link_object_hash[:links][:related] = related_link(source, association)
|
253
|
+
link_object_hash[:data] = has_one_linkage(source, association)
|
269
254
|
link_object_hash
|
270
255
|
end
|
271
256
|
|
272
257
|
def link_object_has_many(source, association, include_linkage)
|
273
258
|
link_object_hash = {}
|
274
|
-
link_object_hash[:
|
275
|
-
link_object_hash[:
|
276
|
-
link_object_hash[:
|
259
|
+
link_object_hash[:links] = {}
|
260
|
+
link_object_hash[:links][:self] = self_link(source, association)
|
261
|
+
link_object_hash[:links][:related] = related_link(source, association)
|
262
|
+
link_object_hash[:data] = has_many_linkage(source, association) if include_linkage
|
277
263
|
link_object_hash
|
278
264
|
end
|
279
265
|
|
@@ -291,9 +277,9 @@ module JSONAPI
|
|
291
277
|
value = source.send(foreign_key)
|
292
278
|
|
293
279
|
if association.is_a?(JSONAPI::Association::HasMany)
|
294
|
-
value.map { |value| IdValueFormatter.format(value
|
280
|
+
value.map { |value| IdValueFormatter.format(value) }
|
295
281
|
elsif association.is_a?(JSONAPI::Association::HasOne)
|
296
|
-
IdValueFormatter.format(value
|
282
|
+
IdValueFormatter.format(value)
|
297
283
|
end
|
298
284
|
end
|
299
285
|
|
@@ -324,9 +310,9 @@ module JSONAPI
|
|
324
310
|
@key_formatter.format(key)
|
325
311
|
end
|
326
312
|
|
327
|
-
def format_value(value, format
|
313
|
+
def format_value(value, format)
|
328
314
|
value_formatter = JSONAPI::ValueFormatter.value_formatter_for(format)
|
329
|
-
value_formatter.format(value
|
315
|
+
value_formatter.format(value)
|
330
316
|
end
|
331
317
|
end
|
332
318
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module JSONAPI
|
2
|
+
class ResponseDocument
|
3
|
+
def initialize(operation_results, options = {})
|
4
|
+
@operation_results = operation_results
|
5
|
+
@options = options
|
6
|
+
|
7
|
+
@key_formatter = @options.fetch(:key_formatter, JSONAPI.configuration.key_formatter)
|
8
|
+
end
|
9
|
+
|
10
|
+
def contents
|
11
|
+
hash = results_to_hash
|
12
|
+
|
13
|
+
meta = top_level_meta
|
14
|
+
hash.merge!(meta: meta) unless meta.empty?
|
15
|
+
|
16
|
+
hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def status
|
20
|
+
if @operation_results.has_errors?
|
21
|
+
@operation_results.all_errors[0].status
|
22
|
+
else
|
23
|
+
@operation_results.results[0].code
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def serializer
|
30
|
+
@serializer ||= @options.fetch(:resource_serializer_klass, JSONAPI::ResourceSerializer).new(
|
31
|
+
@options.fetch(:primary_resource_klass),
|
32
|
+
include_directives: @options[:include_directives],
|
33
|
+
fields: @options[:fields],
|
34
|
+
base_url: @options.fetch(:base_url, ''),
|
35
|
+
key_formatter: @key_formatter,
|
36
|
+
route_formatter: @options.fetch(:route_formatter, JSONAPI.configuration.route_formatter)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def top_level_meta
|
41
|
+
meta = @options.fetch(:base_meta, {})
|
42
|
+
|
43
|
+
meta.merge!(@operation_results.meta)
|
44
|
+
|
45
|
+
@operation_results.results.each do |result|
|
46
|
+
meta.merge!(result.meta)
|
47
|
+
end
|
48
|
+
|
49
|
+
meta.deep_transform_keys { |key| @key_formatter.format(key) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def results_to_hash
|
53
|
+
if @operation_results.has_errors?
|
54
|
+
{errors: @operation_results.all_errors}
|
55
|
+
else
|
56
|
+
if @operation_results.results.length == 1
|
57
|
+
result = @operation_results.results[0]
|
58
|
+
|
59
|
+
case result
|
60
|
+
when JSONAPI::ResourceOperationResult
|
61
|
+
serializer.serialize_to_hash(result.resource)
|
62
|
+
when JSONAPI::ResourcesOperationResult
|
63
|
+
serializer.serialize_to_hash(result.resources)
|
64
|
+
when JSONAPI::LinksObjectOperationResult
|
65
|
+
serializer.serialize_to_links_hash(result.parent_resource,
|
66
|
+
result.association)
|
67
|
+
when JSONAPI::OperationResult
|
68
|
+
{}
|
69
|
+
end
|
70
|
+
|
71
|
+
elsif @operation_results.results.length > 1
|
72
|
+
resources = []
|
73
|
+
@operation_results.results.each do |result|
|
74
|
+
case result
|
75
|
+
when JSONAPI::ResourceOperationResult
|
76
|
+
resources.push(result.resource)
|
77
|
+
when JSONAPI::ResourcesOperationResult
|
78
|
+
resources.concat(result.resources)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
serializer.serialize_to_hash(resources)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/jsonapi/routing_ext.rb
CHANGED
@@ -58,8 +58,7 @@ module ActionDispatch
|
|
58
58
|
options[:controller] ||= @resource_type
|
59
59
|
options.merge!(res.routing_resource_options)
|
60
60
|
|
61
|
-
|
62
|
-
options[:param] ||= res._primary_key
|
61
|
+
options[:param] = :id
|
63
62
|
|
64
63
|
options[:path] = format_route(@resource_type)
|
65
64
|
|
@@ -91,21 +90,22 @@ module ActionDispatch
|
|
91
90
|
options = links.extract_options!.dup
|
92
91
|
|
93
92
|
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix)
|
93
|
+
options[:controller] ||= res._type.to_s
|
94
94
|
|
95
95
|
methods = links_methods(options)
|
96
96
|
|
97
97
|
if methods.include?(:show)
|
98
|
-
match "
|
98
|
+
match "relationships/#{formatted_association_name}", controller: options[:controller],
|
99
99
|
action: 'show_association', association: link_type.to_s, via: [:get]
|
100
100
|
end
|
101
101
|
|
102
102
|
if methods.include?(:update)
|
103
|
-
match "
|
103
|
+
match "relationships/#{formatted_association_name}", controller: options[:controller],
|
104
104
|
action: 'update_association', association: link_type.to_s, via: [:put, :patch]
|
105
105
|
end
|
106
106
|
|
107
107
|
if methods.include?(:destroy)
|
108
|
-
match "
|
108
|
+
match "relationships/#{formatted_association_name}", controller: options[:controller],
|
109
109
|
action: 'destroy_association', association: link_type.to_s, via: [:delete]
|
110
110
|
end
|
111
111
|
end
|
@@ -116,54 +116,60 @@ module ActionDispatch
|
|
116
116
|
options = links.extract_options!.dup
|
117
117
|
|
118
118
|
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix)
|
119
|
+
options[:controller] ||= res._type.to_s
|
119
120
|
|
120
121
|
methods = links_methods(options)
|
121
122
|
|
122
123
|
if methods.include?(:show)
|
123
|
-
match "
|
124
|
+
match "relationships/#{formatted_association_name}", controller: options[:controller],
|
124
125
|
action: 'show_association', association: link_type.to_s, via: [:get]
|
125
126
|
end
|
126
127
|
|
127
128
|
if methods.include?(:create)
|
128
|
-
match "
|
129
|
+
match "relationships/#{formatted_association_name}", controller: options[:controller],
|
129
130
|
action: 'create_association', association: link_type.to_s, via: [:post]
|
130
131
|
end
|
131
132
|
|
132
133
|
if methods.include?(:update)
|
133
|
-
match "
|
134
|
+
match "relationships/#{formatted_association_name}", controller: options[:controller],
|
134
135
|
action: 'update_association', association: link_type.to_s, via: [:put, :patch]
|
135
136
|
end
|
136
137
|
|
137
138
|
if methods.include?(:destroy)
|
138
|
-
match "
|
139
|
+
match "relationships/#{formatted_association_name}/:keys", controller: options[:controller],
|
139
140
|
action: 'destroy_association', association: link_type.to_s, via: [:delete]
|
140
141
|
end
|
141
142
|
end
|
142
143
|
|
143
144
|
def jsonapi_related_resource(*association)
|
144
145
|
source = JSONAPI::Resource.resource_for(resource_type_with_module_prefix)
|
146
|
+
options = association.extract_options!.dup
|
145
147
|
|
146
148
|
association_name = association.first
|
147
149
|
association = source._associations[association_name]
|
148
150
|
|
149
151
|
formatted_association_name = format_route(association.name)
|
150
152
|
related_resource = JSONAPI::Resource.resource_for(resource_type_with_module_prefix(association.class_name.underscore.pluralize))
|
153
|
+
options[:controller] ||= related_resource._type.to_s
|
151
154
|
|
152
|
-
|
155
|
+
|
156
|
+
match "#{formatted_association_name}", controller: options[:controller],
|
153
157
|
association: association.name, source: resource_type_with_module_prefix(source._type),
|
154
158
|
action: 'get_related_resource', via: [:get]
|
155
159
|
end
|
156
160
|
|
157
161
|
def jsonapi_related_resources(*association)
|
158
162
|
source = JSONAPI::Resource.resource_for(resource_type_with_module_prefix)
|
163
|
+
options = association.extract_options!.dup
|
159
164
|
|
160
165
|
association_name = association.first
|
161
166
|
association = source._associations[association_name]
|
162
167
|
|
163
168
|
formatted_association_name = format_route(association.name)
|
164
169
|
related_resource = JSONAPI::Resource.resource_for(resource_type_with_module_prefix(association.class_name.underscore))
|
170
|
+
options[:controller] ||= related_resource._type.to_s
|
165
171
|
|
166
|
-
match "#{formatted_association_name}", controller:
|
172
|
+
match "#{formatted_association_name}", controller: options[:controller],
|
167
173
|
association: association.name, source: resource_type_with_module_prefix(source._type),
|
168
174
|
action: 'get_related_resources', via: [:get]
|
169
175
|
end
|
@@ -4,10 +4,6 @@ def set_content_type_header!
|
|
4
4
|
@request.headers['Content-Type'] = JSONAPI::MEDIA_TYPE
|
5
5
|
end
|
6
6
|
|
7
|
-
class ConfigControllerTest < ActionController::TestCase
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
7
|
class PostsControllerTest < ActionController::TestCase
|
12
8
|
def test_index
|
13
9
|
get :index
|
@@ -57,16 +53,32 @@ class PostsControllerTest < ActionController::TestCase
|
|
57
53
|
assert_equal 1, json_response['included'].size
|
58
54
|
end
|
59
55
|
|
56
|
+
def test_index_include_one_level_query_count
|
57
|
+
query_count = count_queries do
|
58
|
+
get :index, {include: 'author'}
|
59
|
+
end
|
60
|
+
assert_response :success
|
61
|
+
assert_equal 2, query_count
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_index_include_two_levels_query_count
|
65
|
+
query_count = count_queries do
|
66
|
+
get :index, {include: 'author,author.comments'}
|
67
|
+
end
|
68
|
+
assert_response :success
|
69
|
+
assert_equal 3, query_count
|
70
|
+
end
|
71
|
+
|
60
72
|
def test_index_filter_by_ids_and_fields
|
61
73
|
get :index, {filter: {id: '1,2'}, fields: {posts: 'id,title,author'}}
|
62
74
|
assert_response :success
|
63
75
|
assert_equal 2, json_response['data'].size
|
64
76
|
|
65
|
-
# type, id,
|
66
|
-
assert_equal
|
77
|
+
# type, id, links, attributes, relationships
|
78
|
+
assert_equal 5, json_response['data'][0].size
|
67
79
|
assert json_response['data'][0].has_key?('type')
|
68
80
|
assert json_response['data'][0].has_key?('id')
|
69
|
-
assert json_response['data'][0].has_key?('title')
|
81
|
+
assert json_response['data'][0]['attributes'].has_key?('title')
|
70
82
|
assert json_response['data'][0].has_key?('links')
|
71
83
|
end
|
72
84
|
|
@@ -75,11 +87,11 @@ class PostsControllerTest < ActionController::TestCase
|
|
75
87
|
assert_response :success
|
76
88
|
assert_equal 2, json_response['data'].size
|
77
89
|
|
78
|
-
# type, id,
|
79
|
-
assert_equal
|
90
|
+
# type, id, links, attributes, relationships
|
91
|
+
assert_equal 5, json_response['data'][0].size
|
80
92
|
assert json_response['data'][0].has_key?('type')
|
81
93
|
assert json_response['data'][0].has_key?('id')
|
82
|
-
assert json_response['data'][0].has_key?('title')
|
94
|
+
assert json_response['data'][0]['attributes'].has_key?('title')
|
83
95
|
assert json_response['data'][0].has_key?('links')
|
84
96
|
end
|
85
97
|
|
@@ -94,11 +106,11 @@ class PostsControllerTest < ActionController::TestCase
|
|
94
106
|
assert_response :success
|
95
107
|
assert_equal 2, json_response['data'].size
|
96
108
|
|
97
|
-
#
|
98
|
-
assert_equal
|
109
|
+
# type, id, links, relationships
|
110
|
+
assert_equal 4, json_response['data'][0].size
|
99
111
|
assert json_response['data'][0].has_key?('type')
|
100
112
|
assert json_response['data'][0].has_key?('id')
|
101
|
-
assert json_response['data'][0]['
|
113
|
+
assert json_response['data'][0]['relationships'].has_key?('author')
|
102
114
|
end
|
103
115
|
|
104
116
|
def test_filter_association_single
|
@@ -172,58 +184,35 @@ class PostsControllerTest < ActionController::TestCase
|
|
172
184
|
end
|
173
185
|
|
174
186
|
def test_sorting_asc
|
175
|
-
get :index, {sort: '
|
176
|
-
|
177
|
-
assert_response :success
|
178
|
-
assert_equal "A First Post", json_response['data'][0]['title']
|
179
|
-
end
|
180
|
-
|
181
|
-
# Plus symbol may be replaced by a space
|
182
|
-
def test_sorting_asc_with_space
|
183
|
-
get :index, {sort: ' title'}
|
184
|
-
|
185
|
-
assert_response :success
|
186
|
-
assert_equal "A First Post", json_response['data'][0]['title']
|
187
|
-
end
|
188
|
-
|
189
|
-
# Plus symbol may be sent uriencoded ('%2b')
|
190
|
-
def test_sorting_asc_with_encoded_plus
|
191
|
-
get :index, {sort: '%2btitle'}
|
187
|
+
get :index, {sort: 'title'}
|
192
188
|
|
193
189
|
assert_response :success
|
194
|
-
assert_equal "A First Post", json_response['data'][0]['title']
|
190
|
+
assert_equal "A First Post", json_response['data'][0]['attributes']['title']
|
195
191
|
end
|
196
192
|
|
197
193
|
def test_sorting_desc
|
198
194
|
get :index, {sort: '-title'}
|
199
195
|
|
200
196
|
assert_response :success
|
201
|
-
assert_equal "Update This Later - Multiple", json_response['data'][0]['title']
|
197
|
+
assert_equal "Update This Later - Multiple", json_response['data'][0]['attributes']['title']
|
202
198
|
end
|
203
199
|
|
204
200
|
def test_sorting_by_multiple_fields
|
205
|
-
get :index, {sort: '
|
201
|
+
get :index, {sort: 'title,body'}
|
206
202
|
|
207
203
|
assert_response :success
|
208
204
|
assert_equal '14', json_response['data'][0]['id']
|
209
205
|
end
|
210
206
|
|
211
207
|
def test_invalid_sort_param
|
212
|
-
get :index, {sort: '
|
208
|
+
get :index, {sort: 'asdfg'}
|
213
209
|
|
214
210
|
assert_response :bad_request
|
215
211
|
assert_match /asdfg is not a valid sort criteria for post/, response.body
|
216
212
|
end
|
217
213
|
|
218
|
-
def test_invalid_sort_param_missing_direction
|
219
|
-
get :index, {sort: 'title'}
|
220
|
-
|
221
|
-
assert_response :bad_request
|
222
|
-
assert_match /title must start with a direction/, response.body
|
223
|
-
end
|
224
|
-
|
225
214
|
def test_excluded_sort_param
|
226
|
-
get :index, {sort: '
|
215
|
+
get :index, {sort: 'id'}
|
227
216
|
|
228
217
|
assert_response :bad_request
|
229
218
|
assert_match /id is not a valid sort criteria for post/, response.body
|
@@ -233,8 +222,8 @@ class PostsControllerTest < ActionController::TestCase
|
|
233
222
|
get :show, {id: '1'}
|
234
223
|
assert_response :success
|
235
224
|
assert json_response['data'].is_a?(Hash)
|
236
|
-
assert_equal 'New post', json_response['data']['title']
|
237
|
-
assert_equal 'A body!!!', json_response['data']['body']
|
225
|
+
assert_equal 'New post', json_response['data']['attributes']['title']
|
226
|
+
assert_equal 'A body!!!', json_response['data']['attributes']['body']
|
238
227
|
assert_nil json_response['included']
|
239
228
|
end
|
240
229
|
|
@@ -242,11 +231,11 @@ class PostsControllerTest < ActionController::TestCase
|
|
242
231
|
get :show, {id: '1', include: 'comments'}
|
243
232
|
assert_response :success
|
244
233
|
assert json_response['data'].is_a?(Hash)
|
245
|
-
assert_equal 'New post', json_response['data']['title']
|
246
|
-
assert_equal 'A body!!!', json_response['data']['body']
|
247
|
-
assert_nil json_response['data']['
|
234
|
+
assert_equal 'New post', json_response['data']['attributes']['title']
|
235
|
+
assert_equal 'A body!!!', json_response['data']['attributes']['body']
|
236
|
+
assert_nil json_response['data']['relationships']['tags']['data']
|
248
237
|
assert matches_array?([{'type' => 'comments', 'id' => '1'}, {'type' => 'comments', 'id' => '2'}],
|
249
|
-
json_response['data']['
|
238
|
+
json_response['data']['relationships']['comments']['data'])
|
250
239
|
assert_equal 2, json_response['included'].size
|
251
240
|
end
|
252
241
|
|
@@ -254,9 +243,8 @@ class PostsControllerTest < ActionController::TestCase
|
|
254
243
|
get :show, {id: '1', fields: {posts: 'author'}}
|
255
244
|
assert_response :success
|
256
245
|
assert json_response['data'].is_a?(Hash)
|
257
|
-
assert_nil json_response['data']['
|
258
|
-
|
259
|
-
assert_equal '1', json_response['data']['links']['author']['linkage']['id']
|
246
|
+
assert_nil json_response['data']['attributes']
|
247
|
+
assert_equal '1', json_response['data']['relationships']['author']['data']['id']
|
260
248
|
end
|
261
249
|
|
262
250
|
def test_show_single_with_fields_string
|
@@ -295,19 +283,21 @@ class PostsControllerTest < ActionController::TestCase
|
|
295
283
|
{
|
296
284
|
data: {
|
297
285
|
type: 'posts',
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
286
|
+
attributes: {
|
287
|
+
title: 'JR is Great',
|
288
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
289
|
+
},
|
290
|
+
relationships: {
|
291
|
+
author: {data: {type: 'people', id: '3'}}
|
302
292
|
}
|
303
293
|
}
|
304
294
|
}
|
305
295
|
|
306
296
|
assert_response :created
|
307
297
|
assert json_response['data'].is_a?(Hash)
|
308
|
-
assert_equal '3', json_response['data']['
|
309
|
-
assert_equal 'JR is Great', json_response['data']['title']
|
310
|
-
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['body']
|
298
|
+
assert_equal '3', json_response['data']['relationships']['author']['data']['id']
|
299
|
+
assert_equal 'JR is Great', json_response['data']['attributes']['title']
|
300
|
+
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
|
311
301
|
end
|
312
302
|
|
313
303
|
def test_create_link_to_missing_object
|
@@ -316,10 +306,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
316
306
|
{
|
317
307
|
data: {
|
318
308
|
type: 'posts',
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
309
|
+
attributes: {
|
310
|
+
title: 'JR is Great',
|
311
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
312
|
+
},
|
313
|
+
relationships: {
|
314
|
+
author: {data: {type: 'people', id: '304567'}}
|
323
315
|
}
|
324
316
|
}
|
325
317
|
}
|
@@ -335,11 +327,13 @@ class PostsControllerTest < ActionController::TestCase
|
|
335
327
|
{
|
336
328
|
data: {
|
337
329
|
type: 'posts',
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
330
|
+
attributes: {
|
331
|
+
asdfg: 'aaaa',
|
332
|
+
title: 'JR is Great',
|
333
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
334
|
+
},
|
335
|
+
relationships: {
|
336
|
+
author: {data: {type: 'people', id: '3'}}
|
343
337
|
}
|
344
338
|
}
|
345
339
|
}
|
@@ -354,9 +348,11 @@ class PostsControllerTest < ActionController::TestCase
|
|
354
348
|
{
|
355
349
|
data: {
|
356
350
|
type: 'posts',
|
357
|
-
|
358
|
-
|
359
|
-
|
351
|
+
attributes: {
|
352
|
+
title: 'JSONAPIResources is the greatest thing...',
|
353
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
354
|
+
},
|
355
|
+
relationships: {
|
360
356
|
author: nil
|
361
357
|
}
|
362
358
|
}
|
@@ -380,18 +376,22 @@ class PostsControllerTest < ActionController::TestCase
|
|
380
376
|
data: [
|
381
377
|
{
|
382
378
|
type: 'posts',
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
379
|
+
attributes: {
|
380
|
+
title: 'JR is Great',
|
381
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
382
|
+
},
|
383
|
+
relationships: {
|
384
|
+
author: {data: {type: 'people', id: '3'}}
|
387
385
|
}
|
388
386
|
},
|
389
387
|
{
|
390
388
|
type: 'posts',
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
389
|
+
attributes: {
|
390
|
+
title: 'Ember is Great',
|
391
|
+
body: 'Ember is the greatest thing since unsliced bread.'
|
392
|
+
},
|
393
|
+
relationships: {
|
394
|
+
author: {data: {type: 'people', id: '3'}}
|
395
395
|
}
|
396
396
|
}
|
397
397
|
]
|
@@ -400,7 +400,7 @@ class PostsControllerTest < ActionController::TestCase
|
|
400
400
|
assert_response :created
|
401
401
|
assert json_response['data'].is_a?(Array)
|
402
402
|
assert_equal json_response['data'].size, 2
|
403
|
-
assert_equal json_response['data'][0]['
|
403
|
+
assert_equal json_response['data'][0]['relationships']['author']['data']['id'], '3'
|
404
404
|
assert_match /JR is Great/, response.body
|
405
405
|
assert_match /Ember is Great/, response.body
|
406
406
|
end
|
@@ -412,18 +412,22 @@ class PostsControllerTest < ActionController::TestCase
|
|
412
412
|
data: [
|
413
413
|
{
|
414
414
|
type: 'posts',
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
415
|
+
attributes: {
|
416
|
+
Title: 'JR is Great',
|
417
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
418
|
+
},
|
419
|
+
relationships: {
|
420
|
+
author: {data: {type: 'people', id: '3'}}
|
419
421
|
}
|
420
422
|
},
|
421
423
|
{
|
422
424
|
type: 'posts',
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
425
|
+
attributes: {
|
426
|
+
title: 'Ember is Great',
|
427
|
+
BODY: 'Ember is the greatest thing since unsliced bread.'
|
428
|
+
},
|
429
|
+
relationships: {
|
430
|
+
author: {data: {type: 'people', id: '3'}}
|
427
431
|
}
|
428
432
|
}
|
429
433
|
]
|
@@ -439,10 +443,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
439
443
|
{
|
440
444
|
data_spelled_wrong: {
|
441
445
|
type: 'posts',
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
+
attributes: {
|
447
|
+
title: 'JR is Great',
|
448
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
449
|
+
},
|
450
|
+
relationships: {
|
451
|
+
author: {data: {type: 'people', id: '3'}}
|
446
452
|
}
|
447
453
|
}
|
448
454
|
}
|
@@ -457,10 +463,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
457
463
|
{
|
458
464
|
data: {
|
459
465
|
type: 'posts_spelled_wrong',
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
466
|
+
attributes: {
|
467
|
+
title: 'JR is Great',
|
468
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
469
|
+
},
|
470
|
+
relationships: {
|
471
|
+
author: {data: {type: 'people', id: '3'}}
|
464
472
|
}
|
465
473
|
}
|
466
474
|
}
|
@@ -474,10 +482,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
474
482
|
post :create,
|
475
483
|
{
|
476
484
|
data: {
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
485
|
+
attributes: {
|
486
|
+
title: 'JR is Great',
|
487
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
488
|
+
},
|
489
|
+
relationships: {
|
490
|
+
author: {data: {type: 'people', id: '3'}}
|
481
491
|
}
|
482
492
|
}
|
483
493
|
}
|
@@ -492,10 +502,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
492
502
|
{
|
493
503
|
data: {
|
494
504
|
type: 'posts',
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
505
|
+
attributes: {
|
506
|
+
subject: 'JR is Great',
|
507
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
508
|
+
},
|
509
|
+
relationships: {
|
510
|
+
author: {data: {type: 'people', id: '3'}}
|
499
511
|
}
|
500
512
|
}
|
501
513
|
}
|
@@ -510,20 +522,22 @@ class PostsControllerTest < ActionController::TestCase
|
|
510
522
|
{
|
511
523
|
data: {
|
512
524
|
type: 'posts',
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
525
|
+
attributes: {
|
526
|
+
title: 'JR is Great',
|
527
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
528
|
+
},
|
529
|
+
relationships: {
|
530
|
+
author: {data: {type: 'people', id: '3'}},
|
531
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
518
532
|
}
|
519
533
|
}
|
520
534
|
}
|
521
535
|
|
522
536
|
assert_response :created
|
523
537
|
assert json_response['data'].is_a?(Hash)
|
524
|
-
assert_equal '3', json_response['data']['
|
525
|
-
assert_equal 'JR is Great', json_response['data']['title']
|
526
|
-
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['body']
|
538
|
+
assert_equal '3', json_response['data']['relationships']['author']['data']['id']
|
539
|
+
assert_equal 'JR is Great', json_response['data']['attributes']['title']
|
540
|
+
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
|
527
541
|
end
|
528
542
|
|
529
543
|
def test_create_with_links_has_many_array
|
@@ -532,20 +546,22 @@ class PostsControllerTest < ActionController::TestCase
|
|
532
546
|
{
|
533
547
|
data: {
|
534
548
|
type: 'posts',
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
549
|
+
attributes: {
|
550
|
+
title: 'JR is Great',
|
551
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread.'
|
552
|
+
},
|
553
|
+
relationships: {
|
554
|
+
author: {data: {type: 'people', id: '3'}},
|
555
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
540
556
|
}
|
541
557
|
}
|
542
558
|
}
|
543
559
|
|
544
560
|
assert_response :created
|
545
561
|
assert json_response['data'].is_a?(Hash)
|
546
|
-
assert_equal '3', json_response['data']['
|
547
|
-
assert_equal 'JR is Great', json_response['data']['title']
|
548
|
-
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['body']
|
562
|
+
assert_equal '3', json_response['data']['relationships']['author']['data']['id']
|
563
|
+
assert_equal 'JR is Great', json_response['data']['attributes']['title']
|
564
|
+
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread.', json_response['data']['attributes']['body']
|
549
565
|
end
|
550
566
|
|
551
567
|
def test_create_with_links_include_and_fields
|
@@ -554,11 +570,13 @@ class PostsControllerTest < ActionController::TestCase
|
|
554
570
|
{
|
555
571
|
data: {
|
556
572
|
type: 'posts',
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
573
|
+
attributes: {
|
574
|
+
title: 'JR is Great!',
|
575
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread!'
|
576
|
+
},
|
577
|
+
relationships: {
|
578
|
+
author: {data: {type: 'people', id: '3'}},
|
579
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
562
580
|
}
|
563
581
|
},
|
564
582
|
include: 'author,author.posts',
|
@@ -567,8 +585,8 @@ class PostsControllerTest < ActionController::TestCase
|
|
567
585
|
|
568
586
|
assert_response :created
|
569
587
|
assert json_response['data'].is_a?(Hash)
|
570
|
-
assert_equal '3', json_response['data']['
|
571
|
-
assert_equal 'JR is Great!', json_response['data']['title']
|
588
|
+
assert_equal '3', json_response['data']['relationships']['author']['data']['id']
|
589
|
+
assert_equal 'JR is Great!', json_response['data']['attributes']['title']
|
572
590
|
assert_not_nil json_response['included'].size
|
573
591
|
end
|
574
592
|
|
@@ -582,10 +600,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
582
600
|
data: {
|
583
601
|
id: '3',
|
584
602
|
type: 'posts',
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
603
|
+
attributes: {
|
604
|
+
title: 'A great new Post'
|
605
|
+
},
|
606
|
+
relationships: {
|
607
|
+
section: {data: {type: 'sections', id: "#{javascript.id}"}},
|
608
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
589
609
|
}
|
590
610
|
},
|
591
611
|
include: 'tags'
|
@@ -593,12 +613,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
593
613
|
|
594
614
|
assert_response :success
|
595
615
|
assert json_response['data'].is_a?(Hash)
|
596
|
-
assert_equal '3', json_response['data']['
|
597
|
-
assert_equal javascript.id.to_s, json_response['data']['
|
598
|
-
assert_equal 'A great new Post', json_response['data']['title']
|
599
|
-
assert_equal 'AAAA', json_response['data']['body']
|
616
|
+
assert_equal '3', json_response['data']['relationships']['author']['data']['id']
|
617
|
+
assert_equal javascript.id.to_s, json_response['data']['relationships']['section']['data']['id']
|
618
|
+
assert_equal 'A great new Post', json_response['data']['attributes']['title']
|
619
|
+
assert_equal 'AAAA', json_response['data']['attributes']['body']
|
600
620
|
assert matches_array?([{'type' => 'tags', 'id' => '3'}, {'type' => 'tags', 'id' => '4'}],
|
601
|
-
json_response['data']['
|
621
|
+
json_response['data']['relationships']['tags']['data'])
|
602
622
|
end
|
603
623
|
|
604
624
|
def test_update_remove_links
|
@@ -609,10 +629,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
609
629
|
data: {
|
610
630
|
id: '3',
|
611
631
|
type: 'posts',
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
632
|
+
attributes: {
|
633
|
+
title: 'A great new Post'
|
634
|
+
},
|
635
|
+
relationships: {
|
636
|
+
section: {data: {type: 'sections', id: 1}},
|
637
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
616
638
|
}
|
617
639
|
},
|
618
640
|
include: 'tags'
|
@@ -626,8 +648,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
626
648
|
data: {
|
627
649
|
type: 'posts',
|
628
650
|
id: 3,
|
629
|
-
|
630
|
-
|
651
|
+
attributes: {
|
652
|
+
title: 'A great new Post'
|
653
|
+
},
|
654
|
+
relationships: {
|
631
655
|
section: nil,
|
632
656
|
tags: []
|
633
657
|
}
|
@@ -637,12 +661,12 @@ class PostsControllerTest < ActionController::TestCase
|
|
637
661
|
|
638
662
|
assert_response :success
|
639
663
|
assert json_response['data'].is_a?(Hash)
|
640
|
-
assert_equal '3', json_response['data']['
|
641
|
-
assert_equal nil, json_response['data']['
|
642
|
-
assert_equal 'A great new Post', json_response['data']['title']
|
643
|
-
assert_equal 'AAAA', json_response['data']['body']
|
664
|
+
assert_equal '3', json_response['data']['relationships']['author']['data']['id']
|
665
|
+
assert_equal nil, json_response['data']['relationships']['section']['data']
|
666
|
+
assert_equal 'A great new Post', json_response['data']['attributes']['title']
|
667
|
+
assert_equal 'AAAA', json_response['data']['attributes']['body']
|
644
668
|
assert matches_array?([],
|
645
|
-
json_response['data']['
|
669
|
+
json_response['data']['relationships']['tags']['data'])
|
646
670
|
end
|
647
671
|
|
648
672
|
def test_update_relationship_has_one
|
@@ -698,7 +722,7 @@ class PostsControllerTest < ActionController::TestCase
|
|
698
722
|
data: {
|
699
723
|
type: 'posts',
|
700
724
|
id: 3,
|
701
|
-
|
725
|
+
relationships: {
|
702
726
|
tags: nil
|
703
727
|
}
|
704
728
|
}
|
@@ -716,8 +740,8 @@ class PostsControllerTest < ActionController::TestCase
|
|
716
740
|
data: {
|
717
741
|
type: 'posts',
|
718
742
|
id: 3,
|
719
|
-
|
720
|
-
tags: {
|
743
|
+
relationships: {
|
744
|
+
tags: {data: {typ: 'bad link', idd: 'as'}}
|
721
745
|
}
|
722
746
|
}
|
723
747
|
}
|
@@ -734,7 +758,7 @@ class PostsControllerTest < ActionController::TestCase
|
|
734
758
|
data: {
|
735
759
|
type: 'posts',
|
736
760
|
id: 3,
|
737
|
-
|
761
|
+
relationships: {
|
738
762
|
tags: 'bad link'
|
739
763
|
}
|
740
764
|
}
|
@@ -744,7 +768,7 @@ class PostsControllerTest < ActionController::TestCase
|
|
744
768
|
assert_match /Invalid Links Object/, response.body
|
745
769
|
end
|
746
770
|
|
747
|
-
def
|
771
|
+
def test_update_other_has_many_links_data_nil
|
748
772
|
set_content_type_header!
|
749
773
|
put :update,
|
750
774
|
{
|
@@ -752,8 +776,8 @@ class PostsControllerTest < ActionController::TestCase
|
|
752
776
|
data: {
|
753
777
|
type: 'posts',
|
754
778
|
id: 3,
|
755
|
-
|
756
|
-
tags: {
|
779
|
+
relationships: {
|
780
|
+
tags: {data: nil}
|
757
781
|
}
|
758
782
|
}
|
759
783
|
}
|
@@ -979,8 +1003,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
979
1003
|
data: {
|
980
1004
|
type: 'posts',
|
981
1005
|
id: 2,
|
982
|
-
|
983
|
-
|
1006
|
+
attributes: {
|
1007
|
+
title: 'A great new Post'
|
1008
|
+
},
|
1009
|
+
relationships: {
|
984
1010
|
section: {type: 'sections', id: "#{javascript.id}"},
|
985
1011
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
986
1012
|
}
|
@@ -1001,9 +1027,11 @@ class PostsControllerTest < ActionController::TestCase
|
|
1001
1027
|
data: {
|
1002
1028
|
type: 'posts',
|
1003
1029
|
id: '3',
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1030
|
+
attributes: {
|
1031
|
+
asdfg: 'aaaa',
|
1032
|
+
title: 'A great new Post'
|
1033
|
+
},
|
1034
|
+
relationships: {
|
1007
1035
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1008
1036
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1009
1037
|
}
|
@@ -1024,8 +1052,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
1024
1052
|
data: {
|
1025
1053
|
type: 'posts',
|
1026
1054
|
id: '3',
|
1027
|
-
|
1028
|
-
|
1055
|
+
attributes: {
|
1056
|
+
title: 'A great new Post'
|
1057
|
+
},
|
1058
|
+
relationships: {
|
1029
1059
|
asdfg: 'aaaa',
|
1030
1060
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1031
1061
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
@@ -1046,8 +1076,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
1046
1076
|
id: 3,
|
1047
1077
|
data_spelled_wrong: {
|
1048
1078
|
type: 'posts',
|
1049
|
-
|
1050
|
-
|
1079
|
+
attributes: {
|
1080
|
+
title: 'A great new Post'
|
1081
|
+
},
|
1082
|
+
relationships: {
|
1051
1083
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1052
1084
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1053
1085
|
}
|
@@ -1066,7 +1098,9 @@ class PostsControllerTest < ActionController::TestCase
|
|
1066
1098
|
id: 3,
|
1067
1099
|
data: {
|
1068
1100
|
type: 'posts',
|
1069
|
-
|
1101
|
+
attributes: {
|
1102
|
+
title: 'A great new Post'
|
1103
|
+
}
|
1070
1104
|
}
|
1071
1105
|
}
|
1072
1106
|
|
@@ -1084,8 +1118,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
1084
1118
|
data: {
|
1085
1119
|
id: '3',
|
1086
1120
|
type_spelled_wrong: 'posts',
|
1087
|
-
|
1088
|
-
|
1121
|
+
attributes: {
|
1122
|
+
title: 'A great new Post'
|
1123
|
+
},
|
1124
|
+
relationships: {
|
1089
1125
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1090
1126
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1091
1127
|
}
|
@@ -1096,6 +1132,31 @@ class PostsControllerTest < ActionController::TestCase
|
|
1096
1132
|
assert_match /The required parameter, type, is missing./, response.body
|
1097
1133
|
end
|
1098
1134
|
|
1135
|
+
def test_update_unknown_key
|
1136
|
+
set_content_type_header!
|
1137
|
+
javascript = Section.find_by(name: 'javascript')
|
1138
|
+
|
1139
|
+
put :update,
|
1140
|
+
{
|
1141
|
+
id: 3,
|
1142
|
+
data: {
|
1143
|
+
id: '3',
|
1144
|
+
type: 'posts',
|
1145
|
+
body: 'asdfg',
|
1146
|
+
attributes: {
|
1147
|
+
title: 'A great new Post'
|
1148
|
+
},
|
1149
|
+
relationships: {
|
1150
|
+
section: {type: 'sections', id: "#{javascript.id}"},
|
1151
|
+
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1152
|
+
}
|
1153
|
+
}
|
1154
|
+
}
|
1155
|
+
|
1156
|
+
assert_response :bad_request
|
1157
|
+
assert_match /body is not allowed/, response.body
|
1158
|
+
end
|
1159
|
+
|
1099
1160
|
def test_update_multiple
|
1100
1161
|
set_content_type_header!
|
1101
1162
|
javascript = Section.find_by(name: 'javascript')
|
@@ -1107,19 +1168,23 @@ class PostsControllerTest < ActionController::TestCase
|
|
1107
1168
|
{
|
1108
1169
|
type: 'posts',
|
1109
1170
|
id: 3,
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1171
|
+
attributes: {
|
1172
|
+
title: 'A great new Post QWERTY'
|
1173
|
+
},
|
1174
|
+
relationships: {
|
1175
|
+
section: {data: {type: 'sections', id: "#{javascript.id}"}},
|
1176
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
1114
1177
|
}
|
1115
1178
|
},
|
1116
1179
|
{
|
1117
1180
|
type: 'posts',
|
1118
1181
|
id: 16,
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1182
|
+
attributes: {
|
1183
|
+
title: 'A great new Post ASDFG'
|
1184
|
+
},
|
1185
|
+
relationships: {
|
1186
|
+
section: {data: {type: 'sections', id: "#{javascript.id}"}},
|
1187
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
1123
1188
|
}
|
1124
1189
|
}
|
1125
1190
|
],
|
@@ -1128,19 +1193,19 @@ class PostsControllerTest < ActionController::TestCase
|
|
1128
1193
|
|
1129
1194
|
assert_response :success
|
1130
1195
|
assert_equal json_response['data'].size, 2
|
1131
|
-
assert_equal json_response['data'][0]['
|
1132
|
-
assert_equal json_response['data'][0]['
|
1133
|
-
assert_equal json_response['data'][0]['title'], 'A great new Post QWERTY'
|
1134
|
-
assert_equal json_response['data'][0]['body'], 'AAAA'
|
1196
|
+
assert_equal json_response['data'][0]['relationships']['author']['data']['id'], '3'
|
1197
|
+
assert_equal json_response['data'][0]['relationships']['section']['data']['id'], javascript.id.to_s
|
1198
|
+
assert_equal json_response['data'][0]['attributes']['title'], 'A great new Post QWERTY'
|
1199
|
+
assert_equal json_response['data'][0]['attributes']['body'], 'AAAA'
|
1135
1200
|
assert matches_array?([{'type' => 'tags', 'id' => '3'}, {'type' => 'tags', 'id' => '4'}],
|
1136
|
-
json_response['data'][0]['
|
1201
|
+
json_response['data'][0]['relationships']['tags']['data'])
|
1137
1202
|
|
1138
|
-
assert_equal json_response['data'][1]['
|
1139
|
-
assert_equal json_response['data'][1]['
|
1140
|
-
assert_equal json_response['data'][1]['title'], 'A great new Post ASDFG'
|
1141
|
-
assert_equal json_response['data'][1]['body'], 'Not First!!!!'
|
1203
|
+
assert_equal json_response['data'][1]['relationships']['author']['data']['id'], '3'
|
1204
|
+
assert_equal json_response['data'][1]['relationships']['section']['data']['id'], javascript.id.to_s
|
1205
|
+
assert_equal json_response['data'][1]['attributes']['title'], 'A great new Post ASDFG'
|
1206
|
+
assert_equal json_response['data'][1]['attributes']['body'], 'Not First!!!!'
|
1142
1207
|
assert matches_array?([{'type' => 'tags', 'id' => '3'}, {'type' => 'tags', 'id' => '4'}],
|
1143
|
-
json_response['data'][1]['
|
1208
|
+
json_response['data'][1]['relationships']['tags']['data'])
|
1144
1209
|
end
|
1145
1210
|
|
1146
1211
|
def test_update_multiple_missing_keys
|
@@ -1153,16 +1218,20 @@ class PostsControllerTest < ActionController::TestCase
|
|
1153
1218
|
data: [
|
1154
1219
|
{
|
1155
1220
|
type: 'posts',
|
1156
|
-
|
1157
|
-
|
1221
|
+
attributes: {
|
1222
|
+
title: 'A great new Post ASDFG'
|
1223
|
+
},
|
1224
|
+
relationships: {
|
1158
1225
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1159
1226
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1160
1227
|
}
|
1161
1228
|
},
|
1162
1229
|
{
|
1163
1230
|
type: 'posts',
|
1164
|
-
|
1165
|
-
|
1231
|
+
attributes: {
|
1232
|
+
title: 'A great new Post QWERTY'
|
1233
|
+
},
|
1234
|
+
relationships: {
|
1166
1235
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1167
1236
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1168
1237
|
}
|
@@ -1184,19 +1253,23 @@ class PostsControllerTest < ActionController::TestCase
|
|
1184
1253
|
{
|
1185
1254
|
type: 'posts',
|
1186
1255
|
id: 3,
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1256
|
+
attributes: {
|
1257
|
+
title: 'A great new Post ASDFG'
|
1258
|
+
},
|
1259
|
+
relationships: {
|
1260
|
+
section: {data: {type: 'sections', id: "#{javascript.id}"}},
|
1261
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
1191
1262
|
}
|
1192
1263
|
},
|
1193
1264
|
{
|
1194
1265
|
type: 'posts',
|
1195
1266
|
id: 8,
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1267
|
+
attributes: {
|
1268
|
+
title: 'A great new Post QWERTY'
|
1269
|
+
},
|
1270
|
+
relationships: {
|
1271
|
+
section: {data: {type: 'sections', id: "#{javascript.id}"}},
|
1272
|
+
tags: {data: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]}
|
1200
1273
|
}
|
1201
1274
|
}
|
1202
1275
|
]}
|
@@ -1216,8 +1289,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
1216
1289
|
{
|
1217
1290
|
type: 'posts',
|
1218
1291
|
id: 3,
|
1219
|
-
|
1220
|
-
|
1292
|
+
attributes: {
|
1293
|
+
title: 'A great new Post QWERTY'
|
1294
|
+
},
|
1295
|
+
relationships: {
|
1221
1296
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1222
1297
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1223
1298
|
}
|
@@ -1225,8 +1300,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
1225
1300
|
{
|
1226
1301
|
type: 'posts',
|
1227
1302
|
id: 9,
|
1228
|
-
|
1229
|
-
|
1303
|
+
attributes: {
|
1304
|
+
title: 'A great new Post ASDFG'
|
1305
|
+
},
|
1306
|
+
relationships: {
|
1230
1307
|
section: {type: 'sections', id: "#{javascript.id}"},
|
1231
1308
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1232
1309
|
}
|
@@ -1245,8 +1322,10 @@ class PostsControllerTest < ActionController::TestCase
|
|
1245
1322
|
data: {
|
1246
1323
|
type: 'posts',
|
1247
1324
|
id: '3',
|
1248
|
-
|
1249
|
-
|
1325
|
+
attributes: {
|
1326
|
+
subject: 'A great new Post'
|
1327
|
+
},
|
1328
|
+
relationships: {
|
1250
1329
|
author: {type: 'people', id: '1'},
|
1251
1330
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
1252
1331
|
}
|
@@ -1265,7 +1344,9 @@ class PostsControllerTest < ActionController::TestCase
|
|
1265
1344
|
id: 3,
|
1266
1345
|
data: {
|
1267
1346
|
type: 'posts',
|
1268
|
-
|
1347
|
+
attributes: {
|
1348
|
+
subject: 'A great new Post'
|
1349
|
+
},
|
1269
1350
|
linked_objects: {
|
1270
1351
|
author: {type: 'people', id: '1'},
|
1271
1352
|
tags: [{type: 'tags', id: 3}, {type: 'tags', id: 4}]
|
@@ -1313,7 +1394,7 @@ class PostsControllerTest < ActionController::TestCase
|
|
1313
1394
|
id: '1'
|
1314
1395
|
},
|
1315
1396
|
links: {
|
1316
|
-
self: 'http://test.host/posts/1/
|
1397
|
+
self: 'http://test.host/posts/1/relationships/author',
|
1317
1398
|
related: 'http://test.host/posts/1/author'
|
1318
1399
|
}
|
1319
1400
|
}
|
@@ -1328,7 +1409,7 @@ class PostsControllerTest < ActionController::TestCase
|
|
1328
1409
|
{type: 'tags', id: '5'}
|
1329
1410
|
],
|
1330
1411
|
links: {
|
1331
|
-
self: 'http://test.host/posts/2/
|
1412
|
+
self: 'http://test.host/posts/2/relationships/tags',
|
1332
1413
|
related: 'http://test.host/posts/2/tags'
|
1333
1414
|
}
|
1334
1415
|
}
|
@@ -1347,7 +1428,7 @@ class PostsControllerTest < ActionController::TestCase
|
|
1347
1428
|
{
|
1348
1429
|
data: nil,
|
1349
1430
|
links: {
|
1350
|
-
self: 'http://test.host/posts/17/
|
1431
|
+
self: 'http://test.host/posts/17/relationships/author',
|
1351
1432
|
related: 'http://test.host/posts/17/author'
|
1352
1433
|
}
|
1353
1434
|
}
|
@@ -1356,10 +1437,10 @@ end
|
|
1356
1437
|
|
1357
1438
|
class TagsControllerTest < ActionController::TestCase
|
1358
1439
|
def test_tags_index
|
1359
|
-
get :index, {filter: {id: '6,7,8,9'}, include: 'posts
|
1440
|
+
get :index, {filter: {id: '6,7,8,9'}, include: 'posts.tags,posts.author.posts'}
|
1360
1441
|
assert_response :success
|
1361
1442
|
assert_equal 4, json_response['data'].size
|
1362
|
-
assert_equal
|
1443
|
+
assert_equal 3, json_response['included'].size
|
1363
1444
|
end
|
1364
1445
|
|
1365
1446
|
def test_tags_show_multiple
|
@@ -1369,7 +1450,7 @@ class TagsControllerTest < ActionController::TestCase
|
|
1369
1450
|
end
|
1370
1451
|
|
1371
1452
|
def test_tags_show_multiple_with_include
|
1372
|
-
get :show, {id: '6,7,8,9', include: 'posts
|
1453
|
+
get :show, {id: '6,7,8,9', include: 'posts.tags,posts.author.posts'}
|
1373
1454
|
assert_response :bad_request
|
1374
1455
|
assert_match /6,7,8,9 is not a valid value for id/, response.body
|
1375
1456
|
end
|
@@ -1396,7 +1477,7 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1396
1477
|
JSONAPI.configuration.use_text_errors = true
|
1397
1478
|
get :index, {sort: 'not_in_record'}
|
1398
1479
|
assert_response 400
|
1399
|
-
assert_equal '
|
1480
|
+
assert_equal 'INVALID_SORT_CRITERIA', json_response['errors'][0]['code']
|
1400
1481
|
JSONAPI.configuration.use_text_errors = false
|
1401
1482
|
end
|
1402
1483
|
|
@@ -1437,7 +1518,7 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1437
1518
|
get :show, {id: 1, include: 'isoCurrency,employee', 'fields' => {'expenseEntries' => 'transactionDate'}}
|
1438
1519
|
assert_response :success
|
1439
1520
|
assert json_response['data'].is_a?(Hash)
|
1440
|
-
assert json_response['data'].has_key?('transactionDate')
|
1521
|
+
assert json_response['data']['attributes'].has_key?('transactionDate')
|
1441
1522
|
assert_equal 2, json_response['included'].size
|
1442
1523
|
end
|
1443
1524
|
|
@@ -1446,7 +1527,7 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1446
1527
|
'isoCurrencies' => 'id,name'}}
|
1447
1528
|
assert_response :success
|
1448
1529
|
assert json_response['data'].is_a?(Hash)
|
1449
|
-
assert json_response['data'].has_key?('transactionDate')
|
1530
|
+
assert json_response['data']['attributes'].has_key?('transactionDate')
|
1450
1531
|
assert_equal 2, json_response['included'].size
|
1451
1532
|
end
|
1452
1533
|
|
@@ -1458,11 +1539,13 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1458
1539
|
{
|
1459
1540
|
data: {
|
1460
1541
|
type: 'expense_entries',
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1542
|
+
attributes: {
|
1543
|
+
transaction_date: '2014/04/15',
|
1544
|
+
cost: 50.58
|
1545
|
+
},
|
1546
|
+
relationships: {
|
1547
|
+
employee: {data: {type: 'people', id: '3'}},
|
1548
|
+
iso_currency: {data: {type: 'iso_currencies', id: 'USD'}}
|
1466
1549
|
}
|
1467
1550
|
},
|
1468
1551
|
include: 'iso_currency',
|
@@ -1471,9 +1554,9 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1471
1554
|
|
1472
1555
|
assert_response :created
|
1473
1556
|
assert json_response['data'].is_a?(Hash)
|
1474
|
-
assert_equal '3', json_response['data']['
|
1475
|
-
assert_equal 'USD', json_response['data']['
|
1476
|
-
assert_equal '50.58', json_response['data']['cost']
|
1557
|
+
assert_equal '3', json_response['data']['relationships']['employee']['data']['id']
|
1558
|
+
assert_equal 'USD', json_response['data']['relationships']['iso_currency']['data']['id']
|
1559
|
+
assert_equal '50.58', json_response['data']['attributes']['cost']
|
1477
1560
|
|
1478
1561
|
delete :destroy, {id: json_response['data']['id']}
|
1479
1562
|
assert_response :no_content
|
@@ -1487,11 +1570,13 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1487
1570
|
{
|
1488
1571
|
data: {
|
1489
1572
|
type: 'expense_entries',
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1573
|
+
attributes: {
|
1574
|
+
transactionDate: '2014/04/15',
|
1575
|
+
cost: 50.58
|
1576
|
+
},
|
1577
|
+
relationships: {
|
1578
|
+
employee: {data: {type: 'people', id: '3'}},
|
1579
|
+
isoCurrency: {data: {type: 'iso_currencies', id: 'USD'}}
|
1495
1580
|
}
|
1496
1581
|
},
|
1497
1582
|
include: 'isoCurrency',
|
@@ -1500,9 +1585,9 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1500
1585
|
|
1501
1586
|
assert_response :created
|
1502
1587
|
assert json_response['data'].is_a?(Hash)
|
1503
|
-
assert_equal '3', json_response['data']['
|
1504
|
-
assert_equal 'USD', json_response['data']['
|
1505
|
-
assert_equal '50.58', json_response['data']['cost']
|
1588
|
+
assert_equal '3', json_response['data']['relationships']['employee']['data']['id']
|
1589
|
+
assert_equal 'USD', json_response['data']['relationships']['isoCurrency']['data']['id']
|
1590
|
+
assert_equal '50.58', json_response['data']['attributes']['cost']
|
1506
1591
|
|
1507
1592
|
delete :destroy, {id: json_response['data']['id']}
|
1508
1593
|
assert_response :no_content
|
@@ -1516,11 +1601,13 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1516
1601
|
{
|
1517
1602
|
data: {
|
1518
1603
|
type: 'expense_entries',
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1604
|
+
attributes: {
|
1605
|
+
'transaction-date' => '2014/04/15',
|
1606
|
+
cost: 50.58
|
1607
|
+
},
|
1608
|
+
relationships: {
|
1609
|
+
employee: {data: {type: 'people', id: '3'}},
|
1610
|
+
'iso-currency' => {data: {type: 'iso_currencies', id: 'USD'}}
|
1524
1611
|
}
|
1525
1612
|
},
|
1526
1613
|
include: 'iso-currency',
|
@@ -1529,9 +1616,9 @@ class ExpenseEntriesControllerTest < ActionController::TestCase
|
|
1529
1616
|
|
1530
1617
|
assert_response :created
|
1531
1618
|
assert json_response['data'].is_a?(Hash)
|
1532
|
-
assert_equal '3', json_response['data']['
|
1533
|
-
assert_equal 'USD', json_response['data']['
|
1534
|
-
assert_equal '50.58', json_response['data']['cost']
|
1619
|
+
assert_equal '3', json_response['data']['relationships']['employee']['data']['id']
|
1620
|
+
assert_equal 'USD', json_response['data']['relationships']['iso-currency']['data']['id']
|
1621
|
+
assert_equal '50.58', json_response['data']['attributes']['cost']
|
1535
1622
|
|
1536
1623
|
delete :destroy, {id: json_response['data']['id']}
|
1537
1624
|
assert_response :no_content
|
@@ -1544,63 +1631,104 @@ class IsoCurrenciesControllerTest < ActionController::TestCase
|
|
1544
1631
|
end
|
1545
1632
|
|
1546
1633
|
def test_currencies_show
|
1547
|
-
get :show, {
|
1634
|
+
get :show, {id: 'USD'}
|
1548
1635
|
assert_response :success
|
1549
1636
|
assert json_response['data'].is_a?(Hash)
|
1550
1637
|
end
|
1551
1638
|
|
1639
|
+
def test_create_currencies_client_generated_id
|
1640
|
+
set_content_type_header!
|
1641
|
+
JSONAPI.configuration.json_key_format = :underscored_route
|
1642
|
+
|
1643
|
+
post :create,
|
1644
|
+
{
|
1645
|
+
data: {
|
1646
|
+
type: 'iso_currencies',
|
1647
|
+
id: 'BTC',
|
1648
|
+
attributes: {
|
1649
|
+
name: 'Bit Coin',
|
1650
|
+
'country_name' => 'global',
|
1651
|
+
'minor_unit' => 'satoshi'
|
1652
|
+
}
|
1653
|
+
}
|
1654
|
+
}
|
1655
|
+
|
1656
|
+
assert_response :created
|
1657
|
+
assert_equal 'BTC', json_response['data']['id']
|
1658
|
+
assert_equal 'Bit Coin', json_response['data']['attributes']['name']
|
1659
|
+
assert_equal 'global', json_response['data']['attributes']['country_name']
|
1660
|
+
assert_equal 'satoshi', json_response['data']['attributes']['minor_unit']
|
1661
|
+
|
1662
|
+
delete :destroy, {id: json_response['data']['id']}
|
1663
|
+
assert_response :no_content
|
1664
|
+
end
|
1665
|
+
|
1666
|
+
def test_currencies_primary_key_sort
|
1667
|
+
get :index, {sort: 'id'}
|
1668
|
+
assert_response :success
|
1669
|
+
assert_equal 3, json_response['data'].size
|
1670
|
+
assert_equal 'CAD', json_response['data'][0]['id']
|
1671
|
+
assert_equal 'EUR', json_response['data'][1]['id']
|
1672
|
+
assert_equal 'USD', json_response['data'][2]['id']
|
1673
|
+
end
|
1674
|
+
|
1675
|
+
def test_currencies_code_sort
|
1676
|
+
get :index, {sort: 'code'}
|
1677
|
+
assert_response :bad_request
|
1678
|
+
end
|
1679
|
+
|
1552
1680
|
def test_currencies_json_key_underscored_sort
|
1553
1681
|
JSONAPI.configuration.json_key_format = :underscored_key
|
1554
|
-
get :index, {sort: '
|
1682
|
+
get :index, {sort: 'country_name'}
|
1555
1683
|
assert_response :success
|
1556
1684
|
assert_equal 3, json_response['data'].size
|
1557
|
-
assert_equal 'Canada', json_response['data'][0]['country_name']
|
1558
|
-
assert_equal 'Euro Member Countries', json_response['data'][1]['country_name']
|
1559
|
-
assert_equal 'United States', json_response['data'][2]['country_name']
|
1685
|
+
assert_equal 'Canada', json_response['data'][0]['attributes']['country_name']
|
1686
|
+
assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country_name']
|
1687
|
+
assert_equal 'United States', json_response['data'][2]['attributes']['country_name']
|
1560
1688
|
|
1561
1689
|
# reverse sort
|
1562
1690
|
get :index, {sort: '-country_name'}
|
1563
1691
|
assert_response :success
|
1564
1692
|
assert_equal 3, json_response['data'].size
|
1565
|
-
assert_equal 'United States', json_response['data'][0]['country_name']
|
1566
|
-
assert_equal 'Euro Member Countries', json_response['data'][1]['country_name']
|
1567
|
-
assert_equal 'Canada', json_response['data'][2]['country_name']
|
1693
|
+
assert_equal 'United States', json_response['data'][0]['attributes']['country_name']
|
1694
|
+
assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country_name']
|
1695
|
+
assert_equal 'Canada', json_response['data'][2]['attributes']['country_name']
|
1568
1696
|
end
|
1569
1697
|
|
1570
1698
|
def test_currencies_json_key_dasherized_sort
|
1571
1699
|
JSONAPI.configuration.json_key_format = :dasherized_key
|
1572
|
-
get :index, {sort: '
|
1700
|
+
get :index, {sort: 'country-name'}
|
1573
1701
|
assert_response :success
|
1574
1702
|
assert_equal 3, json_response['data'].size
|
1575
|
-
assert_equal 'Canada', json_response['data'][0]['country-name']
|
1576
|
-
assert_equal 'Euro Member Countries', json_response['data'][1]['country-name']
|
1577
|
-
assert_equal 'United States', json_response['data'][2]['country-name']
|
1703
|
+
assert_equal 'Canada', json_response['data'][0]['attributes']['country-name']
|
1704
|
+
assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country-name']
|
1705
|
+
assert_equal 'United States', json_response['data'][2]['attributes']['country-name']
|
1578
1706
|
|
1579
1707
|
# reverse sort
|
1580
1708
|
get :index, {sort: '-country-name'}
|
1581
1709
|
assert_response :success
|
1582
1710
|
assert_equal 3, json_response['data'].size
|
1583
|
-
assert_equal 'United States', json_response['data'][0]['country-name']
|
1584
|
-
assert_equal 'Euro Member Countries', json_response['data'][1]['country-name']
|
1585
|
-
assert_equal 'Canada', json_response['data'][2]['country-name']
|
1711
|
+
assert_equal 'United States', json_response['data'][0]['attributes']['country-name']
|
1712
|
+
assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['country-name']
|
1713
|
+
assert_equal 'Canada', json_response['data'][2]['attributes']['country-name']
|
1586
1714
|
end
|
1587
1715
|
|
1588
1716
|
def test_currencies_json_key_custom_json_key_sort
|
1589
1717
|
JSONAPI.configuration.json_key_format = :upper_camelized_key
|
1590
|
-
get :index, {sort: '
|
1718
|
+
get :index, {sort: 'CountryName'}
|
1591
1719
|
assert_response :success
|
1592
1720
|
assert_equal 3, json_response['data'].size
|
1593
|
-
assert_equal 'Canada', json_response['data'][0]['CountryName']
|
1594
|
-
assert_equal 'Euro Member Countries', json_response['data'][1]['CountryName']
|
1595
|
-
assert_equal 'United States', json_response['data'][2]['CountryName']
|
1721
|
+
assert_equal 'Canada', json_response['data'][0]['attributes']['CountryName']
|
1722
|
+
assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['CountryName']
|
1723
|
+
assert_equal 'United States', json_response['data'][2]['attributes']['CountryName']
|
1596
1724
|
|
1597
1725
|
# reverse sort
|
1598
1726
|
get :index, {sort: '-CountryName'}
|
1599
1727
|
assert_response :success
|
1600
1728
|
assert_equal 3, json_response['data'].size
|
1601
|
-
assert_equal 'United States', json_response['data'][0]['CountryName']
|
1602
|
-
assert_equal 'Euro Member Countries', json_response['data'][1]['CountryName']
|
1603
|
-
assert_equal 'Canada', json_response['data'][2]['CountryName']
|
1729
|
+
assert_equal 'United States', json_response['data'][0]['attributes']['CountryName']
|
1730
|
+
assert_equal 'Euro Member Countries', json_response['data'][1]['attributes']['CountryName']
|
1731
|
+
assert_equal 'Canada', json_response['data'][2]['attributes']['CountryName']
|
1604
1732
|
end
|
1605
1733
|
|
1606
1734
|
def test_currencies_json_key_underscored_filter
|
@@ -1608,7 +1736,7 @@ class IsoCurrenciesControllerTest < ActionController::TestCase
|
|
1608
1736
|
get :index, {filter: {country_name: 'Canada'}}
|
1609
1737
|
assert_response :success
|
1610
1738
|
assert_equal 1, json_response['data'].size
|
1611
|
-
assert_equal 'Canada', json_response['data'][0]['country_name']
|
1739
|
+
assert_equal 'Canada', json_response['data'][0]['attributes']['country_name']
|
1612
1740
|
end
|
1613
1741
|
|
1614
1742
|
def test_currencies_json_key_camelized_key_filter
|
@@ -1616,7 +1744,7 @@ class IsoCurrenciesControllerTest < ActionController::TestCase
|
|
1616
1744
|
get :index, {filter: {'countryName' => 'Canada'}}
|
1617
1745
|
assert_response :success
|
1618
1746
|
assert_equal 1, json_response['data'].size
|
1619
|
-
assert_equal 'Canada', json_response['data'][0]['countryName']
|
1747
|
+
assert_equal 'Canada', json_response['data'][0]['attributes']['countryName']
|
1620
1748
|
end
|
1621
1749
|
|
1622
1750
|
def test_currencies_json_key_custom_json_key_filter
|
@@ -1624,7 +1752,7 @@ class IsoCurrenciesControllerTest < ActionController::TestCase
|
|
1624
1752
|
get :index, {filter: {'CountryName' => 'Canada'}}
|
1625
1753
|
assert_response :success
|
1626
1754
|
assert_equal 1, json_response['data'].size
|
1627
|
-
assert_equal 'Canada', json_response['data'][0]['CountryName']
|
1755
|
+
assert_equal 'Canada', json_response['data'][0]['attributes']['CountryName']
|
1628
1756
|
end
|
1629
1757
|
end
|
1630
1758
|
|
@@ -1639,9 +1767,11 @@ class PeopleControllerTest < ActionController::TestCase
|
|
1639
1767
|
{
|
1640
1768
|
data: {
|
1641
1769
|
type: 'people',
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1770
|
+
attributes: {
|
1771
|
+
name: 'Steve Jobs',
|
1772
|
+
email: 'sj@email.zzz',
|
1773
|
+
dateJoined: DateTime.parse('2014-1-30 4:20:00 UTC +00:00')
|
1774
|
+
}
|
1645
1775
|
}
|
1646
1776
|
}
|
1647
1777
|
|
@@ -1657,9 +1787,9 @@ class PeopleControllerTest < ActionController::TestCase
|
|
1657
1787
|
data: {
|
1658
1788
|
id: '3',
|
1659
1789
|
type: 'people',
|
1660
|
-
|
1790
|
+
relationships: {
|
1661
1791
|
'hair-cut' => {
|
1662
|
-
|
1792
|
+
data: {
|
1663
1793
|
type: 'hair-cuts',
|
1664
1794
|
id: '1'
|
1665
1795
|
}
|
@@ -1676,7 +1806,9 @@ class PeopleControllerTest < ActionController::TestCase
|
|
1676
1806
|
{
|
1677
1807
|
data: {
|
1678
1808
|
type: 'people',
|
1679
|
-
|
1809
|
+
attributes: {
|
1810
|
+
email: 'sj@email.zzz'
|
1811
|
+
}
|
1680
1812
|
}
|
1681
1813
|
}
|
1682
1814
|
|
@@ -1696,7 +1828,9 @@ class PeopleControllerTest < ActionController::TestCase
|
|
1696
1828
|
data: {
|
1697
1829
|
id: '3',
|
1698
1830
|
type: 'people',
|
1699
|
-
|
1831
|
+
attributes: {
|
1832
|
+
name: ''
|
1833
|
+
}
|
1700
1834
|
}
|
1701
1835
|
}
|
1702
1836
|
|
@@ -1723,7 +1857,7 @@ class PeopleControllerTest < ActionController::TestCase
|
|
1723
1857
|
assert_response :success
|
1724
1858
|
assert_equal json_response['data'].size, 1
|
1725
1859
|
assert_equal json_response['data'][0]['id'], '1'
|
1726
|
-
assert_equal json_response['data'][0]['name'], 'Joe Author'
|
1860
|
+
assert_equal json_response['data'][0]['attributes']['name'], 'Joe Author'
|
1727
1861
|
end
|
1728
1862
|
|
1729
1863
|
def test_get_related_resource
|
@@ -1736,31 +1870,43 @@ class PeopleControllerTest < ActionController::TestCase
|
|
1736
1870
|
data: {
|
1737
1871
|
id: '1',
|
1738
1872
|
type: 'people',
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1873
|
+
attributes: {
|
1874
|
+
name: 'Joe Author',
|
1875
|
+
email: 'joe@xyz.fake',
|
1876
|
+
"date-joined" => '2013-08-07 16:25:00 -0400'
|
1877
|
+
},
|
1742
1878
|
links: {
|
1743
|
-
self: 'http://test.host/people/1'
|
1879
|
+
self: 'http://test.host/people/1'
|
1880
|
+
},
|
1881
|
+
relationships: {
|
1744
1882
|
comments: {
|
1745
|
-
|
1746
|
-
|
1883
|
+
links: {
|
1884
|
+
self: 'http://test.host/people/1/relationships/comments',
|
1885
|
+
related: 'http://test.host/people/1/comments'
|
1886
|
+
}
|
1747
1887
|
},
|
1748
1888
|
posts: {
|
1749
|
-
|
1750
|
-
|
1889
|
+
links: {
|
1890
|
+
self: 'http://test.host/people/1/relationships/posts',
|
1891
|
+
related: 'http://test.host/people/1/posts'
|
1892
|
+
}
|
1751
1893
|
},
|
1752
1894
|
preferences: {
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1895
|
+
links: {
|
1896
|
+
self: 'http://test.host/people/1/relationships/preferences',
|
1897
|
+
related: 'http://test.host/people/1/preferences'
|
1898
|
+
},
|
1899
|
+
data: {
|
1756
1900
|
type: 'preferences',
|
1757
1901
|
id: '1'
|
1758
1902
|
}
|
1759
1903
|
},
|
1760
1904
|
"hair-cut" => {
|
1761
|
-
"
|
1762
|
-
|
1763
|
-
|
1905
|
+
"links" => {
|
1906
|
+
"self" => "http://test.host/people/1/relationships/hair_cut",
|
1907
|
+
"related" => "http://test.host/people/1/hair_cut"
|
1908
|
+
},
|
1909
|
+
"data" => nil
|
1764
1910
|
}
|
1765
1911
|
}
|
1766
1912
|
}
|
@@ -1787,8 +1933,8 @@ class Api::V5::AuthorsControllerTest < ActionController::TestCase
|
|
1787
1933
|
assert_equal 1, json_response['data'].size
|
1788
1934
|
assert_equal '1', json_response['data'][0]['id']
|
1789
1935
|
assert_equal 'authors', json_response['data'][0]['type']
|
1790
|
-
assert_equal 'Joe Author', json_response['data'][0]['name']
|
1791
|
-
assert_equal nil, json_response['data'][0]['email']
|
1936
|
+
assert_equal 'Joe Author', json_response['data'][0]['attributes']['name']
|
1937
|
+
assert_equal nil, json_response['data'][0]['attributes']['email']
|
1792
1938
|
end
|
1793
1939
|
|
1794
1940
|
def test_get_person_as_author_by_name_filter
|
@@ -1796,7 +1942,7 @@ class Api::V5::AuthorsControllerTest < ActionController::TestCase
|
|
1796
1942
|
assert_response :success
|
1797
1943
|
assert_equal 3, json_response['data'].size
|
1798
1944
|
assert_equal '1', json_response['data'][0]['id']
|
1799
|
-
assert_equal 'Joe Author', json_response['data'][0]['name']
|
1945
|
+
assert_equal 'Joe Author', json_response['data'][0]['attributes']['name']
|
1800
1946
|
end
|
1801
1947
|
end
|
1802
1948
|
|
@@ -1807,7 +1953,7 @@ class BreedsControllerTest < ActionController::TestCase
|
|
1807
1953
|
get :index
|
1808
1954
|
assert_response :success
|
1809
1955
|
assert_equal '0', json_response['data'][0]['id']
|
1810
|
-
assert_equal 'Persian', json_response['data'][0]['name']
|
1956
|
+
assert_equal 'Persian', json_response['data'][0]['attributes']['name']
|
1811
1957
|
end
|
1812
1958
|
|
1813
1959
|
def test_poro_show
|
@@ -1815,7 +1961,7 @@ class BreedsControllerTest < ActionController::TestCase
|
|
1815
1961
|
assert_response :success
|
1816
1962
|
assert json_response['data'].is_a?(Hash)
|
1817
1963
|
assert_equal '0', json_response['data']['id']
|
1818
|
-
assert_equal 'Persian', json_response['data']['name']
|
1964
|
+
assert_equal 'Persian', json_response['data']['attributes']['name']
|
1819
1965
|
end
|
1820
1966
|
|
1821
1967
|
def test_poro_show_multiple
|
@@ -1831,13 +1977,32 @@ class BreedsControllerTest < ActionController::TestCase
|
|
1831
1977
|
{
|
1832
1978
|
data: {
|
1833
1979
|
type: 'breeds',
|
1834
|
-
|
1980
|
+
attributes: {
|
1981
|
+
name: 'tabby'
|
1982
|
+
}
|
1835
1983
|
}
|
1836
1984
|
}
|
1837
1985
|
|
1838
|
-
assert_response :
|
1986
|
+
assert_response :accepted
|
1839
1987
|
assert json_response['data'].is_a?(Hash)
|
1840
|
-
assert_equal 'Tabby', json_response['data']['name']
|
1988
|
+
assert_equal 'Tabby', json_response['data']['attributes']['name']
|
1989
|
+
end
|
1990
|
+
|
1991
|
+
def test_poro_create_validation_error
|
1992
|
+
set_content_type_header!
|
1993
|
+
post :create,
|
1994
|
+
{
|
1995
|
+
data: {
|
1996
|
+
type: 'breeds',
|
1997
|
+
attributes: {
|
1998
|
+
name: ''
|
1999
|
+
}
|
2000
|
+
}
|
2001
|
+
}
|
2002
|
+
|
2003
|
+
assert_equal 1, json_response['errors'].size
|
2004
|
+
assert_equal JSONAPI::VALIDATION_ERROR, json_response['errors'][0]['code']
|
2005
|
+
assert_match /name - can't be blank/, response.body
|
1841
2006
|
end
|
1842
2007
|
|
1843
2008
|
def test_poro_create_update
|
@@ -1846,13 +2011,15 @@ class BreedsControllerTest < ActionController::TestCase
|
|
1846
2011
|
{
|
1847
2012
|
data: {
|
1848
2013
|
type: 'breeds',
|
1849
|
-
|
2014
|
+
attributes: {
|
2015
|
+
name: 'CALIC'
|
2016
|
+
}
|
1850
2017
|
}
|
1851
2018
|
}
|
1852
2019
|
|
1853
|
-
assert_response :
|
2020
|
+
assert_response :accepted
|
1854
2021
|
assert json_response['data'].is_a?(Hash)
|
1855
|
-
assert_equal 'Calic', json_response['data']['name']
|
2022
|
+
assert_equal 'Calic', json_response['data']['attributes']['name']
|
1856
2023
|
|
1857
2024
|
put :update,
|
1858
2025
|
{
|
@@ -1860,12 +2027,14 @@ class BreedsControllerTest < ActionController::TestCase
|
|
1860
2027
|
data: {
|
1861
2028
|
id: json_response['data']['id'],
|
1862
2029
|
type: 'breeds',
|
1863
|
-
|
2030
|
+
attributes: {
|
2031
|
+
name: 'calico'
|
2032
|
+
}
|
1864
2033
|
}
|
1865
2034
|
}
|
1866
2035
|
assert_response :success
|
1867
2036
|
assert json_response['data'].is_a?(Hash)
|
1868
|
-
assert_equal 'Calico', json_response['data']['name']
|
2037
|
+
assert_equal 'Calico', json_response['data']['attributes']['name']
|
1869
2038
|
end
|
1870
2039
|
|
1871
2040
|
def test_poro_delete
|
@@ -1888,17 +2057,17 @@ class Api::V1::PostsControllerTest < ActionController::TestCase
|
|
1888
2057
|
def test_show_post_namespaced
|
1889
2058
|
get :show, {id: '1'}
|
1890
2059
|
assert_response :success
|
1891
|
-
assert_equal 'http://test.host/api/v1/posts/1/
|
2060
|
+
assert_equal 'http://test.host/api/v1/posts/1/relationships/writer', json_response['data']['relationships']['writer']['links']['self']
|
1892
2061
|
end
|
1893
2062
|
|
1894
2063
|
def test_show_post_namespaced_include
|
1895
2064
|
get :show, {id: '1', include: 'writer'}
|
1896
2065
|
assert_response :success
|
1897
|
-
assert_equal '1', json_response['data']['
|
1898
|
-
assert_nil json_response['data']['
|
2066
|
+
assert_equal '1', json_response['data']['relationships']['writer']['data']['id']
|
2067
|
+
assert_nil json_response['data']['relationships']['tags']
|
1899
2068
|
assert_equal '1', json_response['included'][0]['id']
|
1900
2069
|
assert_equal 'writers', json_response['included'][0]['type']
|
1901
|
-
assert_equal 'joe@xyz.fake', json_response['included'][0]['email']
|
2070
|
+
assert_equal 'joe@xyz.fake', json_response['included'][0]['attributes']['email']
|
1902
2071
|
end
|
1903
2072
|
|
1904
2073
|
def test_index_filter_on_association_namespaced
|
@@ -1911,7 +2080,7 @@ class Api::V1::PostsControllerTest < ActionController::TestCase
|
|
1911
2080
|
get :index, {sort: '-title'}
|
1912
2081
|
|
1913
2082
|
assert_response :success
|
1914
|
-
assert_equal "Update This Later - Multiple", json_response['data'][0]['title']
|
2083
|
+
assert_equal "Update This Later - Multiple", json_response['data'][0]['attributes']['title']
|
1915
2084
|
end
|
1916
2085
|
|
1917
2086
|
def test_create_simple_namespaced
|
@@ -1920,20 +2089,22 @@ class Api::V1::PostsControllerTest < ActionController::TestCase
|
|
1920
2089
|
{
|
1921
2090
|
data: {
|
1922
2091
|
type: 'posts',
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
2092
|
+
attributes: {
|
2093
|
+
title: 'JR - now with Namespacing',
|
2094
|
+
body: 'JSONAPIResources is the greatest thing since unsliced bread now that it has namespaced resources.'
|
2095
|
+
},
|
2096
|
+
relationships: {
|
2097
|
+
writer: { data: {type: 'writers', id: '3'}}
|
1927
2098
|
}
|
1928
2099
|
}
|
1929
2100
|
}
|
1930
2101
|
|
1931
2102
|
assert_response :created
|
1932
2103
|
assert json_response['data'].is_a?(Hash)
|
1933
|
-
assert_equal '3', json_response['data']['
|
1934
|
-
assert_equal 'JR - now with Namespacing', json_response['data']['title']
|
2104
|
+
assert_equal '3', json_response['data']['relationships']['writer']['data']['id']
|
2105
|
+
assert_equal 'JR - now with Namespacing', json_response['data']['attributes']['title']
|
1935
2106
|
assert_equal 'JSONAPIResources is the greatest thing since unsliced bread now that it has namespaced resources.',
|
1936
|
-
json_response['data']['body']
|
2107
|
+
json_response['data']['attributes']['body']
|
1937
2108
|
end
|
1938
2109
|
|
1939
2110
|
end
|
@@ -1947,19 +2118,23 @@ class FactsControllerTest < ActionController::TestCase
|
|
1947
2118
|
get :show, {id: '1'}
|
1948
2119
|
assert_response :success
|
1949
2120
|
assert json_response['data'].is_a?(Hash)
|
1950
|
-
assert_equal 'Jane Author', json_response['data']['spouseName']
|
1951
|
-
assert_equal 'First man to run across Antartica.', json_response['data']['bio']
|
1952
|
-
assert_equal 23.89/45.6, json_response['data']['qualityRating']
|
1953
|
-
assert_equal '47000.56', json_response['data']['salary']
|
1954
|
-
assert_equal '2013-08-07T20:25:00Z', json_response['data']['dateTimeJoined']
|
1955
|
-
assert_equal '1965-06-30', json_response['data']['birthday']
|
1956
|
-
assert_equal '2000-01-01T20:00:00Z', json_response['data']['bedtime']
|
1957
|
-
assert_equal 'abc', json_response['data']['photo']
|
1958
|
-
assert_equal false, json_response['data']['cool']
|
2121
|
+
assert_equal 'Jane Author', json_response['data']['attributes']['spouseName']
|
2122
|
+
assert_equal 'First man to run across Antartica.', json_response['data']['attributes']['bio']
|
2123
|
+
assert_equal 23.89/45.6, json_response['data']['attributes']['qualityRating']
|
2124
|
+
assert_equal '47000.56', json_response['data']['attributes']['salary']
|
2125
|
+
assert_equal '2013-08-07T20:25:00Z', json_response['data']['attributes']['dateTimeJoined']
|
2126
|
+
assert_equal '1965-06-30', json_response['data']['attributes']['birthday']
|
2127
|
+
assert_equal '2000-01-01T20:00:00Z', json_response['data']['attributes']['bedtime']
|
2128
|
+
assert_equal 'abc', json_response['data']['attributes']['photo']
|
2129
|
+
assert_equal false, json_response['data']['attributes']['cool']
|
1959
2130
|
end
|
1960
2131
|
end
|
1961
2132
|
|
1962
2133
|
class Api::V2::BooksControllerTest < ActionController::TestCase
|
2134
|
+
def setup
|
2135
|
+
JSONAPI.configuration.json_key_format = :dasherized_key
|
2136
|
+
end
|
2137
|
+
|
1963
2138
|
def after_teardown
|
1964
2139
|
Api::V2::BookResource.paginator :offset
|
1965
2140
|
end
|
@@ -1970,7 +2145,31 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
1970
2145
|
get :index
|
1971
2146
|
assert_response :success
|
1972
2147
|
assert_equal 10, json_response['data'].size
|
1973
|
-
assert_equal 'Book 0', json_response['data'][0]['title']
|
2148
|
+
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
|
2149
|
+
end
|
2150
|
+
|
2151
|
+
def test_books_offset_pagination_no_params_includes_query_count_one_level
|
2152
|
+
Api::V2::BookResource.paginator :offset
|
2153
|
+
|
2154
|
+
query_count = count_queries do
|
2155
|
+
get :index, {include: 'book-comments'}
|
2156
|
+
end
|
2157
|
+
assert_response :success
|
2158
|
+
assert_equal 10, json_response['data'].size
|
2159
|
+
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
|
2160
|
+
assert_equal 2, query_count
|
2161
|
+
end
|
2162
|
+
|
2163
|
+
def test_books_offset_pagination_no_params_includes_query_count_two_levels
|
2164
|
+
Api::V2::BookResource.paginator :offset
|
2165
|
+
|
2166
|
+
query_count = count_queries do
|
2167
|
+
get :index, {include: 'book-comments,book-comments.author'}
|
2168
|
+
end
|
2169
|
+
assert_response :success
|
2170
|
+
assert_equal 10, json_response['data'].size
|
2171
|
+
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
|
2172
|
+
assert_equal 3, query_count
|
1974
2173
|
end
|
1975
2174
|
|
1976
2175
|
def test_books_offset_pagination
|
@@ -1979,7 +2178,7 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
1979
2178
|
get :index, {page: {offset: 50, limit: 12}}
|
1980
2179
|
assert_response :success
|
1981
2180
|
assert_equal 12, json_response['data'].size
|
1982
|
-
assert_equal 'Book 50', json_response['data'][0]['title']
|
2181
|
+
assert_equal 'Book 50', json_response['data'][0]['attributes']['title']
|
1983
2182
|
end
|
1984
2183
|
|
1985
2184
|
def test_books_offset_pagination_bad_page_param
|
@@ -2006,6 +2205,14 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
2006
2205
|
assert_match /-1 is not a valid value for limit page parameter./, json_response['errors'][0]['detail']
|
2007
2206
|
end
|
2008
2207
|
|
2208
|
+
def test_books_offset_pagination_bad_param_offset_less_than_zero
|
2209
|
+
Api::V2::BookResource.paginator :offset
|
2210
|
+
|
2211
|
+
get :index, {page: {offset: -1, limit: 20}}
|
2212
|
+
assert_response :bad_request
|
2213
|
+
assert_match /-1 is not a valid value for offset page parameter./, json_response['errors'][0]['detail']
|
2214
|
+
end
|
2215
|
+
|
2009
2216
|
def test_books_offset_pagination_invalid_page_format
|
2010
2217
|
Api::V2::BookResource.paginator :offset
|
2011
2218
|
|
@@ -2020,7 +2227,7 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
2020
2227
|
get :index
|
2021
2228
|
assert_response :success
|
2022
2229
|
assert_equal 10, json_response['data'].size
|
2023
|
-
assert_equal 'Book 0', json_response['data'][0]['title']
|
2230
|
+
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
|
2024
2231
|
end
|
2025
2232
|
|
2026
2233
|
def test_books_paged_pagination_no_page
|
@@ -2029,7 +2236,7 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
2029
2236
|
get :index, {page: {size: 12}}
|
2030
2237
|
assert_response :success
|
2031
2238
|
assert_equal 12, json_response['data'].size
|
2032
|
-
assert_equal 'Book 0', json_response['data'][0]['title']
|
2239
|
+
assert_equal 'Book 0', json_response['data'][0]['attributes']['title']
|
2033
2240
|
end
|
2034
2241
|
|
2035
2242
|
def test_books_paged_pagination
|
@@ -2038,7 +2245,7 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
2038
2245
|
get :index, {page: {number: 3, size: 12}}
|
2039
2246
|
assert_response :success
|
2040
2247
|
assert_equal 12, json_response['data'].size
|
2041
|
-
assert_equal 'Book 24', json_response['data'][0]['title']
|
2248
|
+
assert_equal 'Book 24', json_response['data'][0]['attributes']['title']
|
2042
2249
|
end
|
2043
2250
|
|
2044
2251
|
def test_books_paged_pagination_bad_page_param
|
@@ -2065,13 +2272,12 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
2065
2272
|
assert_match /-1 is not a valid value for size page parameter./, json_response['errors'][0]['detail']
|
2066
2273
|
end
|
2067
2274
|
|
2068
|
-
def
|
2275
|
+
def test_books_paged_pagination_invalid_page_format_incorrect
|
2069
2276
|
Api::V2::BookResource.paginator :paged
|
2070
2277
|
|
2071
2278
|
get :index, {page: 'qwerty'}
|
2072
|
-
assert_response :
|
2073
|
-
|
2074
|
-
assert_equal 'Book 0', json_response['data'][0]['title']
|
2279
|
+
assert_response :bad_request
|
2280
|
+
assert_match /0 is not a valid value for number page parameter./, json_response['errors'][0]['detail']
|
2075
2281
|
end
|
2076
2282
|
|
2077
2283
|
def test_books_paged_pagination_invalid_page_format_interpret_int
|
@@ -2080,6 +2286,76 @@ class Api::V2::BooksControllerTest < ActionController::TestCase
|
|
2080
2286
|
get :index, {page: 3}
|
2081
2287
|
assert_response :success
|
2082
2288
|
assert_equal 10, json_response['data'].size
|
2083
|
-
assert_equal 'Book 20', json_response['data'][0]['title']
|
2289
|
+
assert_equal 'Book 20', json_response['data'][0]['attributes']['title']
|
2290
|
+
end
|
2291
|
+
end
|
2292
|
+
|
2293
|
+
class Api::V4::BooksControllerTest < ActionController::TestCase
|
2294
|
+
def setup
|
2295
|
+
JSONAPI.configuration.json_key_format = :camelized_key
|
2296
|
+
end
|
2297
|
+
|
2298
|
+
def test_books_offset_pagination_meta
|
2299
|
+
JSONAPI.configuration.operations_processor = :counting_active_record
|
2300
|
+
Api::V4::BookResource.paginator :offset
|
2301
|
+
get :index, {page: {offset: 50, limit: 12}}
|
2302
|
+
assert_response :success
|
2303
|
+
assert_equal 12, json_response['data'].size
|
2304
|
+
assert_equal 'Book 50', json_response['data'][0]['attributes']['title']
|
2305
|
+
assert_equal 1000, json_response['meta']['totalRecords']
|
2306
|
+
JSONAPI.configuration.operations_processor = :active_record
|
2307
|
+
end
|
2308
|
+
end
|
2309
|
+
|
2310
|
+
class CategoriesControllerTest < ActionController::TestCase
|
2311
|
+
def test_index_default_filter
|
2312
|
+
get :index
|
2313
|
+
assert_response :success
|
2314
|
+
assert json_response['data'].is_a?(Array)
|
2315
|
+
assert_equal 3, json_response['data'].size
|
2316
|
+
end
|
2317
|
+
|
2318
|
+
def test_index_default_filter_override
|
2319
|
+
get :index, { filter: { status: 'inactive' } }
|
2320
|
+
assert_response :success
|
2321
|
+
assert json_response['data'].is_a?(Array)
|
2322
|
+
assert_equal 4, json_response['data'].size
|
2084
2323
|
end
|
2085
2324
|
end
|
2325
|
+
|
2326
|
+
class Api::V1::PlanetsControllerTest < ActionController::TestCase
|
2327
|
+
def test_save_model_callbacks
|
2328
|
+
set_content_type_header!
|
2329
|
+
post :create,
|
2330
|
+
{
|
2331
|
+
data: {
|
2332
|
+
type: 'planets',
|
2333
|
+
attributes: {
|
2334
|
+
name: 'Zeus',
|
2335
|
+
description: 'The largest planet in the solar system. Discovered in 2015.'
|
2336
|
+
}
|
2337
|
+
}
|
2338
|
+
}
|
2339
|
+
|
2340
|
+
assert_response :created
|
2341
|
+
assert json_response['data'].is_a?(Hash)
|
2342
|
+
assert_equal 'Zeus', json_response['data']['attributes']['name']
|
2343
|
+
end
|
2344
|
+
|
2345
|
+
def test_save_model_callbacks_fail
|
2346
|
+
set_content_type_header!
|
2347
|
+
post :create,
|
2348
|
+
{
|
2349
|
+
data: {
|
2350
|
+
type: 'planets',
|
2351
|
+
attributes: {
|
2352
|
+
name: 'Pluto',
|
2353
|
+
description: 'Yes, it is a planet.'
|
2354
|
+
}
|
2355
|
+
}
|
2356
|
+
}
|
2357
|
+
|
2358
|
+
assert_response :unprocessable_entity
|
2359
|
+
assert_match /Save failed or was cancelled/, json_response['errors'][0]['detail']
|
2360
|
+
end
|
2361
|
+
end
|