Added tests.

This commit is contained in:
José Valim 2011-12-01 08:19:14 +01:00
parent c6eee6457f
commit 5a230e8e66
11 changed files with 715 additions and 25 deletions

View File

@ -1,2 +1,11 @@
#!/usr/bin/env rake
require "bundler/gem_tasks"
require "rake/testtask"
desc 'Run tests'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end

View File

@ -7,7 +7,13 @@ ActiveModel::Serialization.class_eval do
module ClassMethods #:nodoc:
def active_model_serializer
return @active_model_serializer if defined?(@active_model_serializer)
@active_model_serializer = "#{self.name}Serializer".safe_constantize
# Use safe constantize when Rails 3.2 is out
begin
@active_model_serializer = "#{self.name}Serializer".constantize
rescue NameError => e
raise unless e.message =~ /uninitialized constant$/ && e.name.to_s == "#{self.name}Serializer"
end
end
end

View File

@ -1,6 +1,7 @@
module Rails
module Generators
class SerializerGenerator < NamedBase
source_root File.expand_path("../templates", __FILE__)
check_class_collision :suffix => "Serializer"
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
@ -26,8 +27,9 @@ module Rails
def parent_class_name
if options[:parent]
options[:parent]
elsif (n = Rails::Generators.namespace) && n.const_defined?(:ApplicationSerializer)
"ApplicationSerializer"
# Only works on 3.2
# elsif (n = Rails::Generators.namespace) && n.const_defined?(:ApplicationSerializer)
# "ApplicationSerializer"
elsif Object.const_defined?(:ApplicationSerializer)
"ApplicationSerializer"
else

View File

@ -1,13 +0,0 @@
require 'rails/generators/test_unit'
module TestUnit
module Generators
class SerializerGenerator < Base
check_class_collision :suffix => "SerializerTest"
def create_test_files
template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_serializer_test.rb")
end
end
end
end

View File

@ -1,9 +0,0 @@
require 'test_helper'
<% module_namespacing do -%>
class <%= class_name %>SerializerTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
<% end -%>

67
test/generators_test.rb Normal file
View File

@ -0,0 +1,67 @@
require 'rails'
class Foo < Rails::Application
end
Rails.application.load_generators
require 'generators/serializer/serializer_generator'
class SerializerGeneratorTest < Rails::Generators::TestCase
destination File.expand_path("../tmp", __FILE__)
setup :prepare_destination
tests Rails::Generators::SerializerGenerator
arguments %w(account name:string description:text business:references)
def test_generates_a_serializer
run_generator
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < ActiveModel::Serializer/
end
def test_generates_a_namespaced_serializer
run_generator ["admin/account"]
assert_file "app/serializers/admin/account_serializer.rb", /class Admin::AccountSerializer < ActiveModel::Serializer/
end
def test_uses_application_serializer_if_one_exists
Object.const_set(:ApplicationSerializer, Class.new)
run_generator
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < ApplicationSerializer/
ensure
Object.send :remove_const, :ApplicationSerializer
end
# def test_uses_namespace_application_serializer_if_one_exists
# Object.const_set(:SerializerNamespace, Module.new)
# SerializerNamespace.const_set(:ApplicationSerializer, Class.new)
# Rails::Generators.namespace = SerializerNamespace
# run_generator
# assert_file "app/serializers/serializer_namespace/account_serializer.rb",
# /module SerializerNamespace\n class AccountSerializer < ApplicationSerializer/
# ensure
# Object.send :remove_const, :SerializerNamespace
# Rails::Generators.namespace = nil
# end
def test_uses_given_parent
Object.const_set(:ApplicationSerializer, Class.new)
run_generator ["Account", "--parent=MySerializer"]
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < MySerializer/
ensure
Object.send :remove_const, :ApplicationSerializer
end
def test_generates_attributes_and_associations
run_generator
assert_file "app/serializers/account_serializer.rb" do |serializer|
assert_match(/^ attributes :name, :description$/, serializer)
assert_match(/^ has_one :business$/, serializer)
end
end
def test_with_no_attributes_does_not_add_extra_space
run_generator ["account"]
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < ActiveModel::Serializer\nend/
end
end

172
test/serialization_test.rb Normal file
View File

@ -0,0 +1,172 @@
require 'test_helper'
require 'pathname'
class RenderJsonTest < ActionController::TestCase
class JsonRenderable
def as_json(options={})
hash = { :a => :b, :c => :d, :e => :f }
hash.except!(*options[:except]) if options[:except]
hash
end
def to_json(options = {})
super :except => [:c, :e]
end
end
class JsonSerializer
def initialize(object, scope)
@object, @scope = object, scope
end
def as_json(*)
{ :object => @object.as_json, :scope => @scope.as_json }
end
end
class JsonSerializable
def initialize(skip=false)
@skip = skip
end
def active_model_serializer
JsonSerializer unless @skip
end
def as_json(*)
{ :serializable_object => true }
end
end
class TestController < ActionController::Base
protect_from_forgery
serialization_scope :current_user
attr_reader :current_user
def self.controller_path
'test'
end
def render_json_nil
render :json => nil
end
def render_json_render_to_string
render :text => render_to_string(:json => '[]')
end
def render_json_hello_world
render :json => ActiveSupport::JSON.encode(:hello => 'world')
end
def render_json_hello_world_with_status
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :status => 401
end
def render_json_hello_world_with_callback
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
end
def render_json_with_custom_content_type
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
end
def render_symbol_json
render :json => ActiveSupport::JSON.encode(:hello => 'world')
end
def render_json_with_extra_options
render :json => JsonRenderable.new, :except => [:c, :e]
end
def render_json_without_options
render :json => JsonRenderable.new
end
def render_json_with_serializer
@current_user = Struct.new(:as_json).new(:current_user => true)
render :json => JsonSerializable.new
end
def render_json_with_serializer_api_but_without_serializer
@current_user = Struct.new(:as_json).new(:current_user => true)
render :json => JsonSerializable.new(true)
end
end
tests TestController
def setup
# enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
# a more accurate simulation of what happens in "real life".
super
@controller.logger = Logger.new(nil)
@request.host = "www.nextangle.com"
end
def test_render_json_nil
get :render_json_nil
assert_equal 'null', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_render_to_string
get :render_json_render_to_string
assert_equal '[]', @response.body
end
def test_render_json
get :render_json_hello_world
assert_equal '{"hello":"world"}', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_status
get :render_json_hello_world_with_status
assert_equal '{"hello":"world"}', @response.body
assert_equal 401, @response.status
end
def test_render_json_with_callback
get :render_json_hello_world_with_callback
assert_equal 'alert({"hello":"world"})', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_custom_content_type
get :render_json_with_custom_content_type
assert_equal '{"hello":"world"}', @response.body
assert_equal 'text/javascript', @response.content_type
end
def test_render_symbol_json
get :render_symbol_json
assert_equal '{"hello":"world"}', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_forwards_extra_options
get :render_json_with_extra_options
assert_equal '{"a":"b"}', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_calls_to_json_from_object
get :render_json_without_options
assert_equal '{"a":"b"}', @response.body
end
def test_render_json_with_serializer
get :render_json_with_serializer
assert_match '"scope":{"current_user":true}', @response.body
assert_match '"object":{"serializable_object":true}', @response.body
end
def test_render_json_with_serializer_api_but_without_serializer
get :render_json_with_serializer_api_but_without_serializer
assert_match '{"serializable_object":true}', @response.body
end
end

432
test/serializer_test.rb Normal file
View File

@ -0,0 +1,432 @@
require "test_helper"
class SerializerTest < ActiveModel::TestCase
class Model
def initialize(hash={})
@attributes = hash
end
def read_attribute_for_serialization(name)
@attributes[name]
end
def as_json(*)
{ :model => "Model" }
end
end
class User
include ActiveModel::Serialization
attr_accessor :superuser
def initialize(hash={})
@attributes = hash.merge(:first_name => "Jose", :last_name => "Valim", :password => "oh noes yugive my password")
end
def read_attribute_for_serialization(name)
@attributes[name]
end
def super_user?
@superuser
end
end
class Post < Model
attr_accessor :comments
def active_model_serializer; PostSerializer; end
end
class Comment < Model
def active_model_serializer; CommentSerializer; end
end
class UserSerializer < ActiveModel::Serializer
attributes :first_name, :last_name
def serializable_hash
attributes.merge(:ok => true).merge(scope)
end
end
class DefaultUserSerializer < ActiveModel::Serializer
attributes :first_name, :last_name
end
class MyUserSerializer < ActiveModel::Serializer
attributes :first_name, :last_name
def serializable_hash
hash = attributes
hash = hash.merge(:super_user => true) if my_user.super_user?
hash
end
end
class CommentSerializer
def initialize(comment, scope)
@comment, @scope = comment, scope
end
def serializable_hash
{ :title => @comment.read_attribute_for_serialization(:title) }
end
def as_json(*)
{ :comment => serializable_hash }
end
end
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments, :serializer => CommentSerializer
end
def test_attributes
user = User.new
user_serializer = DefaultUserSerializer.new(user, {})
hash = user_serializer.as_json
assert_equal({
:default_user => { :first_name => "Jose", :last_name => "Valim" }
}, hash)
end
def test_attributes_method
user = User.new
user_serializer = UserSerializer.new(user, {})
hash = user_serializer.as_json
assert_equal({
:user => { :first_name => "Jose", :last_name => "Valim", :ok => true }
}, hash)
end
def test_serializer_receives_scope
user = User.new
user_serializer = UserSerializer.new(user, {:scope => true})
hash = user_serializer.as_json
assert_equal({
:user => {
:first_name => "Jose",
:last_name => "Valim",
:ok => true,
:scope => true
}
}, hash)
end
def test_pretty_accessors
user = User.new
user.superuser = true
user_serializer = MyUserSerializer.new(user, nil)
hash = user_serializer.as_json
assert_equal({
:my_user => {
:first_name => "Jose", :last_name => "Valim", :super_user => true
}
}, hash)
end
def test_has_many
user = User.new
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
comments = [Comment.new(:title => "Comment1"), Comment.new(:title => "Comment2")]
post.comments = comments
post_serializer = PostSerializer.new(post, user)
assert_equal({
:post => {
:title => "New Post",
:body => "Body of new post",
:comments => [
{ :title => "Comment1" },
{ :title => "Comment2" }
]
}
}, post_serializer.as_json)
end
class Blog < Model
attr_accessor :author
end
class AuthorSerializer < ActiveModel::Serializer
attributes :first_name, :last_name
end
class BlogSerializer < ActiveModel::Serializer
has_one :author, :serializer => AuthorSerializer
end
def test_has_one
user = User.new
blog = Blog.new
blog.author = user
json = BlogSerializer.new(blog, user).as_json
assert_equal({
:blog => {
:author => {
:first_name => "Jose",
:last_name => "Valim"
}
}
}, json)
end
def test_implicit_serializer
author_serializer = Class.new(ActiveModel::Serializer) do
attributes :first_name
end
blog_serializer = Class.new(ActiveModel::Serializer) do
const_set(:AuthorSerializer, author_serializer)
has_one :author
end
user = User.new
blog = Blog.new
blog.author = user
json = blog_serializer.new(blog, user).as_json
assert_equal({
:author => {
:first_name => "Jose"
}
}, json)
end
def test_overridden_associations
author_serializer = Class.new(ActiveModel::Serializer) do
attributes :first_name
end
blog_serializer = Class.new(ActiveModel::Serializer) do
const_set(:PersonSerializer, author_serializer)
def person
object.author
end
has_one :person
end
user = User.new
blog = Blog.new
blog.author = user
json = blog_serializer.new(blog, user).as_json
assert_equal({
:person => {
:first_name => "Jose"
}
}, json)
end
def post_serializer(type)
Class.new(ActiveModel::Serializer) do
attributes :title, :body
has_many :comments, :serializer => CommentSerializer
if type != :super
define_method :serializable_hash do
post_hash = attributes
post_hash.merge!(send(type))
post_hash
end
end
end
end
def test_associations
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
comments = [Comment.new(:title => "Comment1"), Comment.new(:title => "Comment2")]
post.comments = comments
serializer = post_serializer(:associations).new(post, nil)
assert_equal({
:title => "New Post",
:body => "Body of new post",
:comments => [
{ :title => "Comment1" },
{ :title => "Comment2" }
]
}, serializer.as_json)
end
def test_association_ids
serializer = post_serializer(:association_ids)
serializer.class_eval do
def as_json(*)
{ :post => serializable_hash }.merge(associations)
end
end
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
post.comments = comments
serializer = serializer.new(post, nil)
assert_equal({
:post => {
:title => "New Post",
:body => "Body of new post",
:comments => [1, 2]
},
:comments => [
{ :title => "Comment1" },
{ :title => "Comment2" }
]
}, serializer.as_json)
end
def test_associations_with_nil_association
user = User.new
blog = Blog.new
json = BlogSerializer.new(blog, user).as_json
assert_equal({
:blog => { :author => nil }
}, json)
serializer = Class.new(BlogSerializer) do
root :blog
def serializable_hash
attributes.merge(association_ids)
end
end
json = serializer.new(blog, user).as_json
assert_equal({ :blog => { :author => nil } }, json)
end
def test_custom_root
user = User.new
blog = Blog.new
serializer = Class.new(BlogSerializer) do
root :my_blog
end
assert_equal({ :my_blog => { :author => nil } }, serializer.new(blog, user).as_json)
end
def test_false_root
user = User.new
blog = Blog.new
serializer = Class.new(BlogSerializer) do
root false
end
assert_equal({ :author => nil }, serializer.new(blog, user).as_json)
# test inherited false root
serializer = Class.new(serializer)
assert_equal({ :author => nil }, serializer.new(blog, user).as_json)
end
def test_embed_ids
serializer = post_serializer(:super)
serializer.class_eval do
root :post
embed :ids
end
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
post.comments = comments
serializer = serializer.new(post, nil)
assert_equal({
:post => {
:title => "New Post",
:body => "Body of new post",
:comments => [1, 2]
}
}, serializer.as_json)
end
def test_embed_ids_include_true
serializer = post_serializer(:super)
serializer.class_eval do
root :post
embed :ids, :include => true
end
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
post.comments = comments
serializer = serializer.new(post, nil)
assert_equal({
:post => {
:title => "New Post",
:body => "Body of new post",
:comments => [1, 2]
},
:comments => [
{ :title => "Comment1" },
{ :title => "Comment2" }
]
}, serializer.as_json)
end
def test_embed_objects
serializer = post_serializer(:super)
serializer.class_eval do
root :post
embed :objects
end
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
post.comments = comments
serializer = serializer.new(post, nil)
assert_equal({
:post => {
:title => "New Post",
:body => "Body of new post",
:comments => [
{ :title => "Comment1" },
{ :title => "Comment2" }
]
}
}, serializer.as_json)
end
def test_array_serializer
model = Model.new
user = User.new
comments = Comment.new(:title => "Comment1", :id => 1)
array = [model, user, comments]
serializer = array.active_model_serializer.new(array, {:scope => true})
assert_equal([
{ :model => "Model" },
{ :user => { :last_name=>"Valim", :ok=>true, :first_name=>"Jose", :scope => true } },
{ :comment => { :title => "Comment1" } }
], serializer.as_json)
end
end

24
test/test_helper.rb Normal file
View File

@ -0,0 +1,24 @@
require "rubygems"
require "bundler"
Bundler.setup
require "active_model_serializers"
require "active_support/json"
require "test/unit"
module TestHelper
Routes = ActionDispatch::Routing::RouteSet.new
Routes.draw do
match ':controller(/:action(/:id))'
match ':controller(/:action)'
end
ActionController::Base.send :include, Routes.url_helpers
end
ActiveSupport::TestCase.class_eval do
setup do
@routes = ::TestHelper::Routes
end
end