Test suite refactor

This commit is contained in:
ccocchi 2012-04-15 18:17:49 +02:00
parent 52941e6232
commit 4e6142602f
11 changed files with 87 additions and 103 deletions

View File

@ -5,7 +5,6 @@ require 'active_support/json'
require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/class/attribute_accessors'
require 'rabl-fast-json/version' require 'rabl-fast-json/version'
require 'rabl-fast-json/helpers'
require 'rabl-fast-json/template' require 'rabl-fast-json/template'
require 'rabl-fast-json/compiler' require 'rabl-fast-json/compiler'

View File

@ -4,8 +4,6 @@ module RablFastJson
# representing data structure # representing data structure
# #
class Compiler class Compiler
include Helpers
def initialize def initialize
@glue_count = 0 @glue_count = 0
end end
@ -49,7 +47,7 @@ module RablFastJson
# #
def collection(data, options = {}) def collection(data, options = {})
object(data) object(data)
@template.root_name = options[:root] if root_given?(options) @template.root_name = options[:root] if options[:root]
end end
# #
@ -82,8 +80,8 @@ module RablFastJson
# #
def child(name_or_data, options = {}, &block) def child(name_or_data, options = {}, &block)
data, name = extract_data_and_name(name_or_data) data, name = extract_data_and_name(name_or_data)
name = options[:root] if root_given?(options) name = options[:root] if options[:root]
if partial_given?(options) if options[:partial]
template = Library.instance.get(options[:partial]) template = Library.instance.get(options[:partial])
@template[name] = template.merge!(:_data => data) @template[name] = template.merge!(:_data => data)
else else

View File

@ -1,11 +0,0 @@
module RablFastJson
module Helpers
def root_given?(options) #:nodoc:
options[:root].present?
end
def partial_given?(options) #:nodoc:
options[:partial].present?
end
end
end

View File

@ -4,8 +4,6 @@ module RablFastJson
class Library class Library
include Singleton include Singleton
attr_accessor :view_renderer
def initialize def initialize
@cached_templates = {} @cached_templates = {}
end end
@ -31,7 +29,7 @@ module RablFastJson
def get(path) def get(path)
template = @cached_templates[path] template = @cached_templates[path]
return template unless template.nil? return template if template
t = @lookup_context.find_template(path, [], false) t = @lookup_context.find_template(path, [], false)
get_compiled_template(path, t.source) get_compiled_template(path, t.source)
end end

View File

@ -74,6 +74,10 @@ module RablFastJson
collection.map { |o| render_resource(o, source) } collection.map { |o| render_resource(o, source) }
end end
#
# Allow to use partial inside of node blocks (they are evaluated at)
# rendering time.
#
def partial(template_path, options = {}) def partial(template_path, options = {})
raise "No object was given to partial" unless options[:object] raise "No object was given to partial" unless options[:object]
object = options[:object] object = options[:object]

View File

@ -18,10 +18,10 @@ class CacheTemplatesTest < ActiveSupport::TestCase
test "cached templates should not be modifiable in place" do test "cached templates should not be modifiable in place" do
ActionController::Base.stub(:perform_caching).and_return(true) ActionController::Base.stub(:perform_caching).and_return(true)
t = @library.get_compiled_template('some/path', "") @library.get_compiled_template('some/path', "")
assert_nil t.context t = @library.get_compiled_template('some/path', "attribute :id")
t.context = "foobar"
assert_nil @library.get_compiled_template('some/path', "").context assert_equal({}, t.source)
end end
test "don't cache templates cache_templates is enabled but perform_caching is not active" do test "don't cache templates cache_templates is enabled but perform_caching is not active" do

View File

@ -11,6 +11,40 @@ class CompilerTest < ActiveSupport::TestCase
assert_instance_of RablFastJson::CompiledTemplate, @compiler.compile_source("") assert_instance_of RablFastJson::CompiledTemplate, @compiler.compile_source("")
end end
test "object set data for the template" do
t = @compiler.compile_source(%{ object :@user })
assert_equal :@user, t.data
assert_equal({}, t.source)
end
test "object property can define root name" do
t = @compiler.compile_source(%{ object :@user => :author })
assert_equal :@user, t.data
assert_equal :author, t.root_name
assert_equal({}, t.source)
end
test "collection set the data for the template" do
t = @compiler.compile_source(%{ collection :@user })
assert_equal :@user, t.data
assert_equal({}, t.source)
end
test "collection property can define root name" do
t = @compiler.compile_source(%{ collection :@user => :users })
assert_equal :@user, t.data
assert_equal :users, t.root_name
assert_equal({}, t.source)
end
test "collection property can define root name via options" do
t = @compiler.compile_source(%{ collection :@user, :root => :users })
assert_equal :@user, t.data
assert_equal :users, t.root_name
end
# Compilation
test "simple attributes are compiled to hash" do test "simple attributes are compiled to hash" do
t = @compiler.compile_source(%{ attributes :id, :name }) t = @compiler.compile_source(%{ attributes :id, :name })
assert_equal({ :id => :id, :name => :name}, t.source) assert_equal({ :id => :id, :name => :name}, t.source)
@ -57,11 +91,10 @@ class CompilerTest < ActiveSupport::TestCase
end end
test "child with succint partial notation" do test "child with succint partial notation" do
@view_renderer = mock() mock_template = RablFastJson::CompiledTemplate.new
@view_renderer.stub_chain(:lookup_context, :find_template).with('users/base', [], false).and_return( mock_template.source = { :id => :id }
mock(:source => %{ attribute :id }))
RablFastJson::Library.reset_instance RablFastJson::Library.reset_instance
RablFastJson::Library.instance.view_renderer = @view_renderer RablFastJson::Library.instance.stub(:get).with('users/base').and_return(mock_template)
t = @compiler.compile_source(%{child(:user, :partial => 'users/base') }) t = @compiler.compile_source(%{child(:user, :partial => 'users/base') })
assert_equal( {:user => { :_data => :user, :id => :id } }, t.source) assert_equal( {:user => { :_data => :user, :id => :id } }, t.source)
@ -84,38 +117,6 @@ class CompilerTest < ActiveSupport::TestCase
}, t.source) }, t.source)
end end
test "object set data for the template" do
t = @compiler.compile_source(%{ object :@user })
assert_equal :@user, t.data
assert_equal({}, t.source)
end
test "object property can define root name" do
t = @compiler.compile_source(%{ object :@user => :author })
assert_equal :@user, t.data
assert_equal :author, t.root_name
assert_equal({}, t.source)
end
test "collection set the data for the template" do
t = @compiler.compile_source(%{ collection :@user })
assert_equal :@user, t.data
assert_equal({}, t.source)
end
test "collection property can define root name" do
t = @compiler.compile_source(%{ collection :@user => :users })
assert_equal :@user, t.data
assert_equal :users, t.root_name
assert_equal({}, t.source)
end
test "collection property can define root name via options" do
t = @compiler.compile_source(%{ collection :@user, :root => :users })
assert_equal :@user, t.data
assert_equal :users, t.root_name
end
test "extends use other template source as itself" do test "extends use other template source as itself" do
template = mock('template', :source => { :id => :id }) template = mock('template', :source => { :id => :id })
RablFastJson::Library.reset_instance RablFastJson::Library.reset_instance

View File

@ -21,15 +21,11 @@ class DeepNestingTest < ActiveSupport::TestCase
@user.stub(:posts).and_return([@post]) @user.stub(:posts).and_return([@post])
@user.stub(:respond_to?).with(:each).and_return(false) @user.stub(:respond_to?).with(:each).and_return(false)
@view_renderer = mock()
@view_renderer.stub_chain(:lookup_context, :find_template).with('comments/show', [], false).and_return(
mock(:source => %{ object :@comment\n attribute :content }))
@context = Context.new @context = Context.new
@context.stub(:instance_variable_get).with(:@user).and_return(@user) @context.stub(:instance_variable_get).with(:@user).and_return(@user)
@context.stub(:instance_variable_get).with(:@view_renderer).and_return(@view_renderer)
@context.stub(:instance_variable_get).with(:@virtual_path).and_return('users/show') @context.stub(:instance_variable_get).with(:@virtual_path).and_return('users/show')
@context.stub(:instance_variable_get).with(:@_assigns).and_return({}) @context.stub(:instance_variable_get).with(:@_assigns).and_return({})
@context.stub(:lookup_context).and_return(mock(:find_template => mock(:source => %{ object :@comment\n attribute :content })))
end end
test "compile and render deep nesting template" do test "compile and render deep nesting template" do

View File

@ -3,18 +3,18 @@ require 'test_helper'
class NonRestfulResponseTest < ActiveSupport::TestCase class NonRestfulResponseTest < ActiveSupport::TestCase
setup do setup do
RablFastJson::Library.reset_instance RablFastJson::Library.reset_instance
@user = User.new(1, 'foo', 'male') @user = User.new(1, 'foo', 'male')
@user.stub_chain(:posts, :count).and_return(10) @user.stub_chain(:posts, :count).and_return(10)
@user.stub(:respond_to?).with(:each).and_return(false) @user.stub(:respond_to?).with(:each).and_return(false)
@context = Context.new @context = Context.new
@context.stub(:instance_variable_get).with(:@user).and_return(@user) @context.stub(:instance_variable_get).with(:@user).and_return(@user)
@context.stub(:instance_variable_get).with(:@view_renderer).and_return(mock())
@context.stub(:instance_variable_get).with(:@virtual_path).and_return('user/show') @context.stub(:instance_variable_get).with(:@virtual_path).and_return('user/show')
@context.stub(:instance_variable_get).with(:@_assigns).and_return({'user' => @user}) @context.stub(:instance_variable_get).with(:@_assigns).and_return({'user' => @user})
@context.stub(:lookup_context)
end end
test "compile and render non restful resource" do test "compile and render non restful resource" do
source = %{ source = %{
object false object false
@ -23,13 +23,13 @@ class NonRestfulResponseTest < ActiveSupport::TestCase
attributes :id, :name attributes :id, :name
end end
} }
assert_equal(ActiveSupport::JSON.encode({ assert_equal(ActiveSupport::JSON.encode({
:post_count => 10, :post_count => 10,
:user => { :user => {
:id => 1, :id => 1,
:name => 'foo' :name => 'foo'
} }
}), RablFastJson::Library.instance.get_rendered_template(source, @context)) }), RablFastJson::Library.instance.get_rendered_template(source, @context))
end end
end end

View File

@ -1,76 +1,80 @@
require 'test_helper' require 'test_helper'
class TestCompiledTemplate < ActiveSupport::TestCase class TestJsonRenderer < ActiveSupport::TestCase
setup do setup do
@context = Context.new
@data = User.new(1, 'foobar', 'male') @data = User.new(1, 'foobar', 'male')
@data.stub(:respond_to?).with(:each).and_return(false) @data.stub(:respond_to?).with(:each).and_return(false)
@context = Context.new
@context.stub(:instance_variable_get).with(:@data).and_return(@data) @context.stub(:instance_variable_get).with(:@data).and_return(@data)
@context.stub(:instance_variable_get).with(:@_assigns).and_return({}) @context.stub(:instance_variable_get).with(:@_assigns).and_return({})
@template = RablFastJson::CompiledTemplate.new @template = RablFastJson::CompiledTemplate.new
@template.context = @context
@template.data = :@data @template.data = :@data
end end
def render_json_output def render_json_output
RablFastJson::Renderers::JSON.new(@context).render(@template) RablFastJson::Renderers::JSON.new(@context).render(@template).to_s
end end
test "render object wth empty template" do test "render object wth empty template" do
@template.source = {} @template.source = {}
assert_equal({}, @template.render) assert_equal %q({}), render_json_output
end end
test "render collection with empty template" do test "render collection with empty template" do
@context.stub(:instance_variable_get).with(:@data).and_return([@data]) @context.stub(:instance_variable_get).with(:@data).and_return([@data])
@template.source = {} @template.source = {}
assert_equal([{}], @template.render) assert_equal %q([{}]), render_json_output
end end
test "render single object attributes" do test "render single object attributes" do
@template.source = { :id => :id, :name => :name } @template.source = { :id => :id, :name => :name }
assert_equal({ :id => 1, :name => 'foobar'}, @template.render) assert_equal %q({"id":1,"name":"foobar"}), render_json_output
end end
test "render object as a child" do test "render child with object association" do
@data.stub(:address).and_return(mock(:city => 'Paris'))
@template.source = { :address => { :_data => :address, :city => :city } }
assert_equal %q({"address":{"city":"Paris"}}), render_json_output
end
test "render child with arbitrary data source" do
@template.source = { :author => { :_data => :@data, :name => :name } } @template.source = { :author => { :_data => :@data, :name => :name } }
assert_equal({ :author => { :name => 'foobar' } }, @template.render) assert_equal %q({"author":{"name":"foobar"}}), render_json_output
end end
test "render glued attributes from single object" do test "render glued attributes from single object" do
@template.source = { :_glue0 => { :_data => :@data, :name => :name } } @template.source = { :_glue0 => { :_data => :@data, :name => :name } }
assert_equal({ :name => 'foobar' }, @template.render) assert_equal %q({"name":"foobar"}), render_json_output
end end
test "render collection with attributes" do test "render collection with attributes" do
@data = [User.new(1, 'foo', 'male'), User.new(2, 'bar', 'female')] @data = [User.new(1, 'foo', 'male'), User.new(2, 'bar', 'female')]
@context.stub(:instance_variable_get).with(:@data).and_return(@data) @context.stub(:instance_variable_get).with(:@data).and_return(@data)
@template.source = { :uid => :id, :name => :name, :gender => :sex } @template.source = { :uid => :id, :name => :name, :gender => :sex }
assert_equal([ assert_equal %q([{"uid":1,"name":"foo","gender":"male"},{"uid":2,"name":"bar","gender":"female"}]), render_json_output
{ :uid => 1, :name => 'foo', :gender => 'male'},
{ :uid => 2, :name => 'bar', :gender => 'female'}
], @template.render)
end end
test "render node property" do test "render node property" do
proc = lambda { |object| object.sex } proc = lambda { |object| object.name }
@template.source = { :sex => proc } @template.source = { :name => proc }
assert_equal({ :sex => 'male' }, @template.render) assert_equal %q({"name":"foobar"}), render_json_output
end end
test "render node property with true condition" do test "render node property with true condition" do
condition = lambda { |u| true } condition = lambda { |u| true }
proc = lambda { |object| object.name } proc = lambda { |object| object.name }
@template.source = { :name => [condition, proc] } @template.source = { :name => [condition, proc] }
assert_equal({ :name => 'foobar' }, @template.render) assert_equal %q({"name":"foobar"}), render_json_output
end end
test "render node property with false condition" do test "render node property with false condition" do
condition = lambda { |u| false } condition = lambda { |u| false }
proc = lambda { |object| object.name } proc = lambda { |object| object.name }
@template.source = { :name => [condition, proc] } @template.source = { :name => [condition, proc] }
assert_equal({}, @template.render) assert_equal %q({}), render_json_output
end end
test "partial should be evaluated at rendering time" do test "partial should be evaluated at rendering time" do
@ -80,27 +84,27 @@ class TestCompiledTemplate < ActiveSupport::TestCase
# Stub Library#get # Stub Library#get
t = RablFastJson::CompiledTemplate.new t = RablFastJson::CompiledTemplate.new
t.source, t.context = { :name => :name }, @context t.source = { :name => :name }
RablFastJson::Library.reset_instance RablFastJson::Library.reset_instance
RablFastJson::Library.instance.should_receive(:get).with('users/base').and_return(t) RablFastJson::Library.instance.should_receive(:get).with('users/base').and_return(t)
@template.data = false @template.data = false
@template.source = { :user => ->(s) { partial('users/base', :object => @user) } } @template.source = { :user => ->(s) { partial('users/base', :object => @user) } }
assert_equal({ :user => { :name => 'foobar' } }, @template.render) assert_equal %q({"user":{"name":"foobar"}}), render_json_output
end end
test "partial with nil values should raise an error" do test "partial with no values should raise an error" do
@template.data = false @template.data = false
@template.source = { :user => ->(s) { partial('users/base') } } @template.source = { :user => ->(s) { partial('users/base') } }
assert_raises(RuntimeError) { @template.render } assert_raises(RuntimeError) { render_json_output }
end end
test "partial with empty values should not raise an error" do test "partial with empty values should not raise an error" do
@template.data = false @template.data = false
@template.source = { :users => ->(s) { partial('users/base', :object => []) } } @template.source = { :users => ->(s) { partial('users/base', :object => []) } }
assert_equal({ :users => [] }, @template.render) assert_equal %q({"users":[]}), render_json_output
end end
end end

View File

@ -35,16 +35,11 @@ class Context
def initialize def initialize
@_assigns = {} @_assigns = {}
@virtual_path = '/users'
end end
def set_assign(key, value) def params
@_assigns[key] = value {}
end
def get_assign(key)
@_assigns[key]
end end
end end
User = Struct.new(:id, :name, :sex) User = Struct.new(:id, :name, :sex)