mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-23 06:16:50 +00:00
One of three constituents is used to provide the CollectionSerializer's #json_key: 1) the :root option - controlled by the caller 2) the #name of the first resource serializer - the root or underscored model name 3) the underscored #name of the resources object - generally equivalent to the underscored model name of #2 Of the three, only the latter 2 are out of the callers control, and only the latter two are expected to be singular by default. Not pluralizing the root gives the caller additional flexibility in defining the desired root, whether conventionally plural, unconventionally plural (e.g. objects_received:) or singular.
436 lines
13 KiB
Ruby
436 lines
13 KiB
Ruby
require 'test_helper'
|
|
|
|
module ActionController
|
|
module Serialization
|
|
class ImplicitSerializerTest < ActionController::TestCase
|
|
include ActiveSupport::Testing::Stream
|
|
class ImplicitSerializationTestController < ActionController::Base
|
|
include SerializationTesting
|
|
def render_using_implicit_serializer
|
|
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
render json: @profile
|
|
end
|
|
|
|
def render_using_default_adapter_root
|
|
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
render json: @profile
|
|
end
|
|
|
|
def render_array_using_custom_root
|
|
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
render json: [@profile], root: 'custom_root'
|
|
end
|
|
|
|
def render_array_that_is_empty_using_custom_root
|
|
render json: [], root: 'custom_root'
|
|
end
|
|
|
|
def render_object_using_custom_root
|
|
@profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
render json: @profile, root: 'custom_root'
|
|
end
|
|
|
|
def render_array_using_implicit_serializer
|
|
array = [
|
|
Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
|
|
Profile.new(name: 'Name 2', description: 'Description 2', comments: 'Comments 2')
|
|
]
|
|
render json: array
|
|
end
|
|
|
|
def render_array_using_implicit_serializer_and_meta
|
|
@profiles = [
|
|
Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
|
|
]
|
|
render json: @profiles, meta: { total: 10 }
|
|
end
|
|
|
|
def render_object_with_cache_enabled
|
|
@comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
@author = Author.new(id: 1, name: 'Joao Moura.')
|
|
@post = Post.new(id: 1, title: 'New Post', body: 'Body', comments: [@comment], author: @author)
|
|
|
|
generate_cached_serializer(@post)
|
|
|
|
@post.title = 'ZOMG a New Post'
|
|
render json: @post
|
|
end
|
|
|
|
def render_json_object_without_serializer
|
|
render json: { error: 'Result is Invalid' }
|
|
end
|
|
|
|
def render_json_array_object_without_serializer
|
|
render json: [{ error: 'Result is Invalid' }]
|
|
end
|
|
|
|
def update_and_render_object_with_cache_enabled
|
|
@post.updated_at = Time.now
|
|
|
|
generate_cached_serializer(@post)
|
|
render json: @post
|
|
end
|
|
|
|
def render_object_expired_with_cache_enabled
|
|
comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
author = Author.new(id: 1, name: 'Joao Moura.')
|
|
post = Post.new(id: 1, title: 'New Post', body: 'Body', comments: [comment], author: author)
|
|
|
|
generate_cached_serializer(post)
|
|
|
|
post.title = 'ZOMG a New Post'
|
|
|
|
expires_in = [
|
|
PostSerializer._cache_options[:expires_in],
|
|
CommentSerializer._cache_options[:expires_in],
|
|
].max + 200
|
|
|
|
Timecop.travel(Time.zone.now + expires_in) do
|
|
render json: post
|
|
end
|
|
end
|
|
|
|
def render_changed_object_with_cache_enabled
|
|
comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
author = Author.new(id: 1, name: 'Joao Moura.')
|
|
post = Post.new(id: 1, title: 'ZOMG a New Post', body: 'Body', comments: [comment], author: author)
|
|
|
|
render json: post
|
|
end
|
|
|
|
def render_fragment_changed_object_with_only_cache_enabled
|
|
author = Author.new(id: 1, name: 'Joao Moura.')
|
|
role = Role.new(id: 42, name: 'ZOMG A ROLE', description: 'DESCRIPTION HERE', author: author)
|
|
|
|
generate_cached_serializer(role)
|
|
role.name = 'lol'
|
|
role.description = 'HUEHUEBRBR'
|
|
|
|
render json: role
|
|
end
|
|
|
|
def render_fragment_changed_object_with_except_cache_enabled
|
|
author = Author.new(id: 1, name: 'Joao Moura.')
|
|
bio = Bio.new(id: 42, content: 'ZOMG A ROLE', rating: 5, author: author)
|
|
|
|
generate_cached_serializer(bio)
|
|
bio.content = 'lol'
|
|
bio.rating = 0
|
|
|
|
render json: bio
|
|
end
|
|
|
|
def render_fragment_changed_object_with_relationship
|
|
comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
comment2 = Comment.new(id: 1, body: 'ZOMG AN UPDATED-BUT-NOT-CACHE-EXPIRED COMMENT')
|
|
like = Like.new(id: 1, likeable: comment, time: 3.days.ago)
|
|
|
|
generate_cached_serializer(like)
|
|
like.likable = comment2
|
|
like.time = Time.zone.now.to_s
|
|
|
|
render json: like
|
|
end
|
|
end
|
|
|
|
tests ImplicitSerializationTestController
|
|
|
|
# We just have Null for now, this will change
|
|
def test_render_using_implicit_serializer
|
|
get :render_using_implicit_serializer
|
|
|
|
expected = {
|
|
name: 'Name 1',
|
|
description: 'Description 1'
|
|
}
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_using_default_root
|
|
with_adapter :json_api do
|
|
get :render_using_default_adapter_root
|
|
end
|
|
expected = {
|
|
data: {
|
|
id: assigns(:profile).id.to_s,
|
|
type: 'profiles',
|
|
attributes: {
|
|
name: 'Name 1',
|
|
description: 'Description 1'
|
|
}
|
|
}
|
|
}
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_array_using_custom_root
|
|
with_adapter :json do
|
|
get :render_array_using_custom_root
|
|
end
|
|
expected = { custom_root: [{ name: 'Name 1', description: 'Description 1' }] }
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_array_that_is_empty_using_custom_root
|
|
with_adapter :json do
|
|
get :render_array_that_is_empty_using_custom_root
|
|
end
|
|
|
|
expected = { custom_root: [] }
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_object_using_custom_root
|
|
with_adapter :json do
|
|
get :render_object_using_custom_root
|
|
end
|
|
|
|
expected = { custom_root: { name: 'Name 1', description: 'Description 1' } }
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_json_object_without_serializer
|
|
get :render_json_object_without_serializer
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
expected_body = { error: 'Result is Invalid' }
|
|
assert_equal expected_body.to_json, @response.body
|
|
end
|
|
|
|
def test_render_json_array_object_without_serializer
|
|
get :render_json_array_object_without_serializer
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
expected_body = [{ error: 'Result is Invalid' }]
|
|
assert_equal expected_body.to_json, @response.body
|
|
end
|
|
|
|
def test_render_array_using_implicit_serializer
|
|
get :render_array_using_implicit_serializer
|
|
assert_equal 'application/json', @response.content_type
|
|
|
|
expected = [
|
|
{
|
|
name: 'Name 1',
|
|
description: 'Description 1'
|
|
},
|
|
{
|
|
name: 'Name 2',
|
|
description: 'Description 2'
|
|
}
|
|
]
|
|
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_array_using_implicit_serializer_and_meta
|
|
with_adapter :json_api do
|
|
get :render_array_using_implicit_serializer_and_meta
|
|
end
|
|
expected = {
|
|
data: [
|
|
{
|
|
id: assigns(:profiles).first.id.to_s,
|
|
type: 'profiles',
|
|
attributes: {
|
|
name: 'Name 1',
|
|
description: 'Description 1'
|
|
}
|
|
}
|
|
],
|
|
meta: {
|
|
total: 10
|
|
}
|
|
}
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_with_cache_enable
|
|
expected = {
|
|
id: 1,
|
|
title: 'New Post',
|
|
body: 'Body',
|
|
comments: [
|
|
{
|
|
id: 1,
|
|
body: 'ZOMG A COMMENT' }
|
|
],
|
|
blog: {
|
|
id: 999,
|
|
name: 'Custom blog'
|
|
},
|
|
author: {
|
|
id: 1,
|
|
name: 'Joao Moura.'
|
|
}
|
|
}
|
|
|
|
ActionController::Base.cache_store.clear
|
|
Timecop.freeze(Time.zone.now) do
|
|
get :render_object_with_cache_enabled
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected.to_json, @response.body
|
|
|
|
get :render_changed_object_with_cache_enabled
|
|
assert_equal expected.to_json, @response.body
|
|
end
|
|
|
|
ActionController::Base.cache_store.clear
|
|
get :render_changed_object_with_cache_enabled
|
|
assert_not_equal expected.to_json, @response.body
|
|
end
|
|
|
|
def test_render_with_cache_enable_and_expired
|
|
ActionController::Base.cache_store.clear
|
|
get :render_object_expired_with_cache_enabled
|
|
|
|
expected = {
|
|
id: 1,
|
|
title: 'ZOMG a New Post',
|
|
body: 'Body',
|
|
comments: [
|
|
{
|
|
id: 1,
|
|
body: 'ZOMG A COMMENT' }
|
|
],
|
|
blog: {
|
|
id: 999,
|
|
name: 'Custom blog'
|
|
},
|
|
author: {
|
|
id: 1,
|
|
name: 'Joao Moura.'
|
|
}
|
|
}
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
actual = @response.body
|
|
expected = expected.to_json
|
|
if ENV['APPVEYOR'] && actual != expected
|
|
skip('Cache expiration tests sometimes fail on Appveyor. FIXME :)')
|
|
else
|
|
assert_equal actual, expected
|
|
end
|
|
end
|
|
|
|
def test_render_with_fragment_only_cache_enable
|
|
ActionController::Base.cache_store.clear
|
|
get :render_fragment_changed_object_with_only_cache_enabled
|
|
response = JSON.parse(@response.body)
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal 'ZOMG A ROLE', response['name']
|
|
assert_equal 'HUEHUEBRBR', response['description']
|
|
end
|
|
|
|
def test_render_with_fragment_except_cache_enable
|
|
ActionController::Base.cache_store.clear
|
|
get :render_fragment_changed_object_with_except_cache_enabled
|
|
response = JSON.parse(@response.body)
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal 5, response['rating']
|
|
assert_equal 'lol', response['content']
|
|
end
|
|
|
|
def test_render_fragment_changed_object_with_relationship
|
|
ActionController::Base.cache_store.clear
|
|
|
|
Timecop.freeze(Time.zone.now) do
|
|
get :render_fragment_changed_object_with_relationship
|
|
response = JSON.parse(@response.body)
|
|
|
|
expected_return = {
|
|
'id' => 1,
|
|
'time' => Time.zone.now.to_s,
|
|
'likeable' => {
|
|
'id' => 1,
|
|
'body' => 'ZOMG A COMMENT'
|
|
}
|
|
}
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
assert_equal expected_return, response
|
|
end
|
|
end
|
|
|
|
def test_cache_expiration_on_update
|
|
ActionController::Base.cache_store.clear
|
|
get :render_object_with_cache_enabled
|
|
|
|
expected = {
|
|
id: 1,
|
|
title: 'ZOMG a New Post',
|
|
body: 'Body',
|
|
comments: [
|
|
{
|
|
id: 1,
|
|
body: 'ZOMG A COMMENT' }
|
|
],
|
|
blog: {
|
|
id: 999,
|
|
name: 'Custom blog'
|
|
},
|
|
author: {
|
|
id: 1,
|
|
name: 'Joao Moura.'
|
|
}
|
|
}
|
|
|
|
get :update_and_render_object_with_cache_enabled
|
|
|
|
assert_equal 'application/json', @response.content_type
|
|
actual = @response.body
|
|
expected = expected.to_json
|
|
if ENV['APPVEYOR'] && actual != expected
|
|
skip('Cache expiration tests sometimes fail on Appveyor. FIXME :)')
|
|
else
|
|
assert_equal actual, expected
|
|
end
|
|
end
|
|
|
|
def test_warn_overridding_use_adapter_as_falsy_on_controller_instance
|
|
controller = Class.new(ImplicitSerializationTestController) do
|
|
def use_adapter?
|
|
false
|
|
end
|
|
end.new
|
|
assert_match(/adapter: false/, (capture(:stderr) do
|
|
controller.get_serializer(Profile.new)
|
|
end))
|
|
end
|
|
|
|
def test_dont_warn_overridding_use_adapter_as_truthy_on_controller_instance
|
|
controller = Class.new(ImplicitSerializationTestController) do
|
|
def use_adapter?
|
|
true
|
|
end
|
|
end.new
|
|
assert_equal '', (capture(:stderr) do
|
|
controller.get_serializer(Profile.new)
|
|
end)
|
|
end
|
|
|
|
def test_render_event_is_emmited
|
|
ActiveSupport::Notifications.subscribe('render.active_model_serializers') do |name|
|
|
@name = name
|
|
end
|
|
|
|
get :render_using_implicit_serializer
|
|
|
|
assert_equal 'render.active_model_serializers', @name
|
|
end
|
|
end
|
|
end
|
|
end
|