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