hypertemplate 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|