hypertemplate 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +29 -0
- data/README.md +134 -0
- data/lib/hypertemplate.rb +14 -0
- data/lib/hypertemplate/builder.rb +33 -0
- data/lib/hypertemplate/builder/base.rb +111 -0
- data/lib/hypertemplate/builder/json.rb +132 -0
- data/lib/hypertemplate/builder/values.rb +33 -0
- data/lib/hypertemplate/builder/xml.rb +119 -0
- data/lib/hypertemplate/errors.rb +3 -0
- data/lib/hypertemplate/hook.rb +6 -0
- data/lib/hypertemplate/hook/rails.rb +112 -0
- data/lib/hypertemplate/hook/sinatra.rb +44 -0
- data/lib/hypertemplate/hook/tilt.rb +68 -0
- data/lib/hypertemplate/recipes.rb +25 -0
- data/lib/hypertemplate/registry.rb +24 -0
- data/lib/hypertemplate/version.rb +13 -0
- data/script/console +7 -0
- data/test/hypertemplate/builder/base_test.rb +45 -0
- data/test/hypertemplate/builder/json_test.rb +506 -0
- data/test/hypertemplate/builder/values_test.rb +12 -0
- data/test/hypertemplate/builder/xml_test.rb +479 -0
- data/test/hypertemplate/helper_test.rb +116 -0
- data/test/hypertemplate/hook/rails_test.rb +77 -0
- data/test/hypertemplate/hook/sinatra_test.rb +89 -0
- data/test/hypertemplate/hook/tilt_test.rb +48 -0
- data/test/hypertemplate/recipes_test.rb +94 -0
- data/test/rails2_skel/Rakefile +16 -0
- data/test/rails2_skel/app/controllers/application_controller.rb +1 -0
- data/test/rails2_skel/app/controllers/test_controller.rb +18 -0
- data/test/rails2_skel/app/views/test/_feed_member.tokamak +9 -0
- data/test/rails2_skel/app/views/test/feed.tokamak +24 -0
- data/test/rails2_skel/app/views/test/show.hyper +31 -0
- data/test/rails2_skel/config/boot.rb +110 -0
- data/test/rails2_skel/config/environment.rb +20 -0
- data/test/rails2_skel/config/environments/development.rb +17 -0
- data/test/rails2_skel/config/environments/production.rb +28 -0
- data/test/rails2_skel/config/environments/test.rb +28 -0
- data/test/rails2_skel/config/initializers/cookie_verification_secret.rb +2 -0
- data/test/rails2_skel/config/initializers/mime_types.rb +3 -0
- data/test/rails2_skel/config/initializers/new_rails_defaults.rb +10 -0
- data/test/rails2_skel/config/initializers/session_store.rb +5 -0
- data/test/rails2_skel/config/routes.rb +43 -0
- data/test/rails2_skel/log/development.log +10190 -0
- data/test/rails2_skel/script/console +3 -0
- data/test/test_helper.rb +9 -0
- metadata +207 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# every builder comes with a default helper, with collection and member methods. See lib/hypertemplate/builder.rb
|
4
|
+
class TestDefaultHelper
|
5
|
+
extend Hypertemplate::Builder::Json.helper
|
6
|
+
end
|
7
|
+
|
8
|
+
# but here you can cheack how to pass other default options to helper methods
|
9
|
+
class DummyAtom < Hypertemplate::Builder::Base
|
10
|
+
|
11
|
+
def self.media_types
|
12
|
+
["application/atom+xml"]
|
13
|
+
end
|
14
|
+
|
15
|
+
collection_helper_default_options :atom_type => :feed
|
16
|
+
member_helper_default_options :atom_type => :entry
|
17
|
+
|
18
|
+
def initialize(obj, options = {})
|
19
|
+
#do nothing
|
20
|
+
end
|
21
|
+
|
22
|
+
def representation
|
23
|
+
"puft!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
class AtomGenerator
|
27
|
+
extend DummyAtom.helper
|
28
|
+
end
|
29
|
+
|
30
|
+
# how to complete override the helper
|
31
|
+
module MyHelper
|
32
|
+
# these examples are just to show that you can freely change the behavior
|
33
|
+
# of the helper methods, since you respect the methods signature
|
34
|
+
def collection(obj, *args, &block)
|
35
|
+
member(obj, *args, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def member(obj, *args, &block)
|
39
|
+
default_options = {:my_option => "my_value"}
|
40
|
+
default_options.merge!(args.shift)
|
41
|
+
args.unshift(default_options)
|
42
|
+
OverwrittenHelperBuilder.build(obj, *args, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
class OverwrittenHelperBuilder < Hypertemplate::Builder::Base
|
46
|
+
def self.media_types
|
47
|
+
["some/media+type"]
|
48
|
+
end
|
49
|
+
|
50
|
+
# just implement this method passing the new helper
|
51
|
+
def self.helper
|
52
|
+
MyHelper
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize(obj, options = {})
|
56
|
+
#do nothing
|
57
|
+
end
|
58
|
+
|
59
|
+
def representation
|
60
|
+
"pleft!"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
class TestOverwrittenHelper
|
64
|
+
extend OverwrittenHelperBuilder.helper
|
65
|
+
end
|
66
|
+
|
67
|
+
class Hypertemplate::Builder::HelperTest < Test::Unit::TestCase
|
68
|
+
|
69
|
+
def setup
|
70
|
+
@registry = Hypertemplate::Registry.new
|
71
|
+
@registry << DummyAtom
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_default_helper
|
75
|
+
obj = { :foo => "bar" }
|
76
|
+
a_collection = [1,2,3,4]
|
77
|
+
json = TestDefaultHelper.collection(obj) do |collection|
|
78
|
+
collection.values do |values|
|
79
|
+
values.id "an_id"
|
80
|
+
end
|
81
|
+
|
82
|
+
collection.members(:collection => a_collection) do |member, number|
|
83
|
+
member.values do |values|
|
84
|
+
values.id number
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
hash = JSON.parse(json).extend(Methodize)
|
90
|
+
|
91
|
+
assert_equal "an_id", hash.id
|
92
|
+
assert_equal 1 , hash.members.first.id
|
93
|
+
assert_equal 4 , hash.members.size
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_helper_with_options_overwritten
|
97
|
+
numbers = [1,2,3,4,5]
|
98
|
+
result = AtomGenerator.collection(numbers, :other_option => "an_option") do |collection, num, opt|
|
99
|
+
assert_equal :feed , opt[:atom_type]
|
100
|
+
assert_equal "an_option", opt[:other_option]
|
101
|
+
assert_equal [1,2,3,4,5], num
|
102
|
+
end
|
103
|
+
assert_equal "puft!", result
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_overwritten_helper
|
107
|
+
numbers = [1,2,3,4,5]
|
108
|
+
result = TestOverwrittenHelper.collection(numbers, :other_option => "an_option") do |collection, num, opt|
|
109
|
+
assert_equal "an_option", opt[:other_option]
|
110
|
+
assert_equal "my_value" , opt[:my_option]
|
111
|
+
assert_equal [1,2,3,4,5], num
|
112
|
+
end
|
113
|
+
assert_equal "pleft!", result
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require "methodize"
|
4
|
+
require "rack/conneg"
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'ruby-debug'
|
8
|
+
rescue Exception => e; end
|
9
|
+
|
10
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../rails2_skel/config/environment.rb')
|
11
|
+
|
12
|
+
# put the require below to use hypertemplate in your rails project
|
13
|
+
require "hypertemplate/hook/rails"
|
14
|
+
|
15
|
+
class Hypertemplate::Hook::RailsTest < ActionController::IntegrationTest
|
16
|
+
|
17
|
+
def test_view_generation_with_json
|
18
|
+
get '/test/show', {}, :accept => 'application/json'
|
19
|
+
|
20
|
+
json = @controller.response.body
|
21
|
+
hash = JSON.parse(json).extend(Methodize)
|
22
|
+
|
23
|
+
assert_equal "John Doe" , hash.author.first.name
|
24
|
+
assert_equal "foobar@example.com" , hash.author.last.email
|
25
|
+
assert_equal "http://example.com/json", hash.id
|
26
|
+
|
27
|
+
assert_equal "http://a.link.com/next" , hash.link.first.href
|
28
|
+
assert_equal "next" , hash.link.first.rel
|
29
|
+
assert_equal "application/json" , hash.link.last.type
|
30
|
+
|
31
|
+
assert_equal "uri:1" , hash.articles.first.id
|
32
|
+
assert_equal "a great article" , hash.articles.first.title
|
33
|
+
assert_equal "http://example.com/image/1" , hash.articles.last.link.first.href
|
34
|
+
assert_equal "image" , hash.articles.last.link.first.rel
|
35
|
+
assert_equal "application/json" , hash.articles.last.link.last.type
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_view_generation_with_xml
|
39
|
+
get '/test/show', {}, :accept => 'application/xml'
|
40
|
+
|
41
|
+
xml = @controller.response.body
|
42
|
+
xml = Nokogiri::XML::Document.parse(xml)
|
43
|
+
|
44
|
+
assert_equal "John Doe" , xml.css("root > author").first.css("name").first.text
|
45
|
+
assert_equal "foobar@example.com" , xml.css("root > author").last.css("email").first.text
|
46
|
+
|
47
|
+
assert_equal "http://a.link.com/next" , xml.css("root > link").first["href"]
|
48
|
+
assert_equal "next" , xml.css("root > link").first["rel"]
|
49
|
+
assert_equal "application/xml" , xml.css("root > link").last["type"]
|
50
|
+
|
51
|
+
assert_equal "uri:1" , xml.css("root > articles").first.css("id").first.text
|
52
|
+
assert_equal "a great article" , xml.css("root > articles").first.css("title").first.text
|
53
|
+
assert_equal "http://example.com/image/1" , xml.css("root > articles").first.css("link").first["href"]
|
54
|
+
assert_equal "image" , xml.css("root > articles").first.css("link").first["rel"]
|
55
|
+
assert_equal "application/json" , xml.css("root > articles").first.css("link").last["type"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_view_generation_with_partial
|
59
|
+
get '/test/feed', {}, :accept => 'application/xml'
|
60
|
+
|
61
|
+
xml = @controller.response.body
|
62
|
+
xml = Nokogiri::XML::Document.parse(xml)
|
63
|
+
|
64
|
+
assert_equal "John Doe" , xml.css("root > author").first.css("name").first.text
|
65
|
+
assert_equal "foobar@example.com" , xml.css("root > author").last.css("email").first.text
|
66
|
+
|
67
|
+
assert_equal "http://a.link.com/next" , xml.css("root > link").first["href"]
|
68
|
+
assert_equal "next" , xml.css("root > link").first["rel"]
|
69
|
+
assert_equal "application/xml" , xml.css("root > link").last["type"]
|
70
|
+
|
71
|
+
assert_equal "uri:1" , xml.css("root > articles").first.css("id").first.text
|
72
|
+
assert_equal "a great article" , xml.css("root > articles").first.css("title").first.text
|
73
|
+
assert_equal "http://example.com/image/1" , xml.css("root > articles").first.css("link").first["href"]
|
74
|
+
assert_equal "image" , xml.css("root > articles").first.css("link").first["rel"]
|
75
|
+
assert_equal "application/json" , xml.css("root > articles").first.css("link").last["type"]
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require "methodize"
|
4
|
+
require "sinatra"
|
5
|
+
require "rack/conneg"
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'ruby-debug'
|
9
|
+
rescue Exception => e; end
|
10
|
+
|
11
|
+
# requiring the hook for sinatra
|
12
|
+
require "hypertemplate/hook/sinatra"
|
13
|
+
|
14
|
+
# simple sinatra app declaration
|
15
|
+
set :views, File.expand_path(File.dirname(__FILE__) + '/../../rails2_skel/app/views/test')
|
16
|
+
|
17
|
+
use(Rack::Hypertemplate)
|
18
|
+
use(Rack::Conneg) do |conneg|
|
19
|
+
conneg.set :accept_all_extensions, false
|
20
|
+
conneg.set :fallback, :html
|
21
|
+
conneg.ignore('/public/')
|
22
|
+
conneg.provide([:json,:xml])
|
23
|
+
end
|
24
|
+
|
25
|
+
before do
|
26
|
+
if negotiated?
|
27
|
+
content_type negotiated_type
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
get "/" do
|
32
|
+
some_articles = [
|
33
|
+
{:id => 1, :title => "a great article", :updated => Time.now},
|
34
|
+
{:id => 2, :title => "another great article", :updated => Time.now}
|
35
|
+
]
|
36
|
+
hyper :show, {}, {:@some_articles => some_articles}
|
37
|
+
end
|
38
|
+
|
39
|
+
require "rack/test"
|
40
|
+
ENV['RACK_ENV'] = 'test'
|
41
|
+
|
42
|
+
class Hypertemplate::Hook::SinatraTest < Test::Unit::TestCase
|
43
|
+
include Rack::Test::Methods
|
44
|
+
|
45
|
+
def app
|
46
|
+
Sinatra::Application
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_hypertemplate_builder_hook_with_sinatra_rendering_json
|
50
|
+
get '/', {}, {"HTTP_ACCEPT" => "application/json"}
|
51
|
+
|
52
|
+
assert last_response.ok?
|
53
|
+
hash = JSON.parse(last_response.body).extend(Methodize)
|
54
|
+
|
55
|
+
assert_equal "John Doe" , hash.author.first.name
|
56
|
+
assert_equal "foobar@example.com" , hash.author.last.email
|
57
|
+
assert_equal "http://example.com/json", hash.id
|
58
|
+
|
59
|
+
assert_equal "http://a.link.com/next" , hash.link.first.href
|
60
|
+
assert_equal "next" , hash.link.first.rel
|
61
|
+
assert_equal "application/json" , hash.link.last.type
|
62
|
+
|
63
|
+
assert_equal "uri:1" , hash.articles.first.id
|
64
|
+
assert_equal "a great article" , hash.articles.first.title
|
65
|
+
assert_equal "http://example.com/image/1" , hash.articles.last.link.first.href
|
66
|
+
assert_equal "image" , hash.articles.last.link.first.rel
|
67
|
+
assert_equal "application/json" , hash.articles.last.link.last.type
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_hypertemplate_builder_hook_with_sinatra_rendering_xml
|
71
|
+
get '/', {}, {"HTTP_ACCEPT" => "application/xml"}
|
72
|
+
|
73
|
+
xml = Nokogiri::XML::Document.parse(last_response.body)
|
74
|
+
|
75
|
+
assert_equal "John Doe" , xml.css("root > author").first.css("name").first.text
|
76
|
+
assert_equal "foobar@example.com" , xml.css("root > author").last.css("email").first.text
|
77
|
+
|
78
|
+
assert_equal "http://a.link.com/next" , xml.css("root > link").first["href"]
|
79
|
+
assert_equal "next" , xml.css("root > link").first["rel"]
|
80
|
+
assert_equal "application/xml" , xml.css("root > link").last["type"]
|
81
|
+
|
82
|
+
assert_equal "uri:1" , xml.css("root > articles").first.css("id").first.text
|
83
|
+
assert_equal "a great article" , xml.css("root > articles").first.css("title").first.text
|
84
|
+
assert_equal "http://example.com/image/1" , xml.css("root > articles").first.css("link").first["href"]
|
85
|
+
assert_equal "image" , xml.css("root > articles").first.css("link").first["rel"]
|
86
|
+
assert_equal "application/json" , xml.css("root > articles").first.css("link").last["type"]
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require "methodize"
|
4
|
+
require "tilt"
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'ruby-debug'
|
8
|
+
rescue Exception => e; end
|
9
|
+
|
10
|
+
require "hypertemplate/hook/tilt"
|
11
|
+
|
12
|
+
class Hypertemplate::Hook::TiltTest < Test::Unit::TestCase
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@hypertemplate = Hypertemplate::Registry.new
|
16
|
+
@hypertemplate << Hypertemplate::Builder::Json
|
17
|
+
end
|
18
|
+
def hypertemplate_registry
|
19
|
+
@hypertemplate
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_hypertemplate_builder_integration_with_tilt
|
23
|
+
|
24
|
+
@some_articles = [
|
25
|
+
{:id => 1, :title => "a great article", :updated => Time.now},
|
26
|
+
{:id => 2, :title => "another great article", :updated => Time.now}
|
27
|
+
]
|
28
|
+
|
29
|
+
view = File.expand_path(File.dirname(__FILE__) + '/../../rails2_skel/app/views/test/show.hyper')
|
30
|
+
template = Hypertemplate::Hook::Tilt::HypertemplateTemplate.new(@hypertemplate, view, :media_type => "application/json")
|
31
|
+
json = template.render(self, :@some_articles => @some_articles)
|
32
|
+
hash = JSON.parse(json).extend(Methodize)
|
33
|
+
|
34
|
+
assert_equal "John Doe" , hash.author.first.name
|
35
|
+
assert_equal "foobar@example.com" , hash.author.last.email
|
36
|
+
assert_equal "http://example.com/json", hash.id
|
37
|
+
|
38
|
+
assert_equal "http://a.link.com/next" , hash.link.first.href
|
39
|
+
assert_equal "next" , hash.link.first.rel
|
40
|
+
assert_equal "application/json" , hash.link.last.type
|
41
|
+
|
42
|
+
assert_equal "uri:1" , hash.articles.first.id
|
43
|
+
assert_equal "a great article" , hash.articles.first.title
|
44
|
+
assert_equal "http://example.com/image/1" , hash.articles.last.link.first.href
|
45
|
+
assert_equal "image" , hash.articles.last.link.first.rel
|
46
|
+
assert_equal "application/json" , hash.articles.last.link.last.type
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Hypertemplate::RecipesTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@recipes = Hypertemplate::Recipes.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_add_recipe_to_hypertemplate
|
10
|
+
@recipes.add "foo" do
|
11
|
+
string = "recipes are represented as blocks"
|
12
|
+
end
|
13
|
+
@recipes.add :bar do
|
14
|
+
string = "recipes are represented as blocks"
|
15
|
+
end
|
16
|
+
|
17
|
+
assert_equal Proc, @recipes["foo"].class
|
18
|
+
assert_equal Proc, @recipes[:bar].class
|
19
|
+
assert_equal nil , @recipes["undeclared recipe"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_remove_recipe_from_hypertemplate
|
23
|
+
@recipes.add :bar do
|
24
|
+
string = "recipes are represented as blocks"
|
25
|
+
end
|
26
|
+
@recipes.remove(:bar)
|
27
|
+
|
28
|
+
assert_equal nil, @recipes[:bar]
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_list_recipe_names
|
32
|
+
@recipes.add "foo" do
|
33
|
+
string = "recipes are represented as blocks"
|
34
|
+
end
|
35
|
+
@recipes.add :bar do
|
36
|
+
string = "recipes are represented as blocks"
|
37
|
+
end
|
38
|
+
|
39
|
+
assert @recipes.list.include?(:bar)
|
40
|
+
assert @recipes.list.include?("foo")
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_builder_with_previously_declared_recipe
|
44
|
+
obj = [{ :foo => "bar" }]
|
45
|
+
|
46
|
+
@recipes.add :simple_feed do |collection|
|
47
|
+
collection.values do |values|
|
48
|
+
values.id "an_id"
|
49
|
+
end
|
50
|
+
|
51
|
+
collection.members do |member, some_foos|
|
52
|
+
member.values do |values|
|
53
|
+
values.id some_foos[:foo]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
json = Hypertemplate::Builder::Json.build(obj, :recipe => @recipes[:simple_feed])
|
59
|
+
hash = JSON.parse(json).extend(Methodize)
|
60
|
+
|
61
|
+
assert_equal "an_id", hash.id
|
62
|
+
assert_equal "bar" , hash.members.first.id
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_raise_exception_with_a_undeclared_recipe
|
66
|
+
obj = [{ :foo => "bar" }]
|
67
|
+
|
68
|
+
assert_raise Hypertemplate::BuilderError do
|
69
|
+
json = Hypertemplate::Builder::Json.build(obj, :recipe => nil)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_builder_with_recipe_option_as_a_block
|
74
|
+
obj = [{ :foo => "bar" }]
|
75
|
+
|
76
|
+
json = Hypertemplate::Builder::Json.build(obj, :recipe => Proc.new { |collection|
|
77
|
+
collection.values do |values|
|
78
|
+
values.id "an_id"
|
79
|
+
end
|
80
|
+
|
81
|
+
collection.members do |member, some_foos|
|
82
|
+
member.values do |values|
|
83
|
+
values.id some_foos[:foo]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
})
|
87
|
+
hash = JSON.parse(json).extend(Methodize)
|
88
|
+
|
89
|
+
assert_equal "an_id", hash.id
|
90
|
+
assert_equal "bar" , hash.members.first.id
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
|
2
|
+
require 'rake'
|
3
|
+
# require 'rake/testtask'
|
4
|
+
# require 'rake/rdoctask'
|
5
|
+
# require 'tasks/rails'
|
6
|
+
|
7
|
+
# extracted from 'tasks/rails' since its the only tasks we're interested in
|
8
|
+
$VERBOSE = nil
|
9
|
+
|
10
|
+
task :default => :middleware
|
11
|
+
task :environment do
|
12
|
+
$rails_rake_task = true
|
13
|
+
require(File.join(RAILS_ROOT, 'config', 'environment'))
|
14
|
+
end
|
15
|
+
|
16
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
class ApplicationController < ActionController::Base; end
|