hypertemplate 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/LICENSE +29 -0
  2. data/README.md +134 -0
  3. data/lib/hypertemplate.rb +14 -0
  4. data/lib/hypertemplate/builder.rb +33 -0
  5. data/lib/hypertemplate/builder/base.rb +111 -0
  6. data/lib/hypertemplate/builder/json.rb +132 -0
  7. data/lib/hypertemplate/builder/values.rb +33 -0
  8. data/lib/hypertemplate/builder/xml.rb +119 -0
  9. data/lib/hypertemplate/errors.rb +3 -0
  10. data/lib/hypertemplate/hook.rb +6 -0
  11. data/lib/hypertemplate/hook/rails.rb +112 -0
  12. data/lib/hypertemplate/hook/sinatra.rb +44 -0
  13. data/lib/hypertemplate/hook/tilt.rb +68 -0
  14. data/lib/hypertemplate/recipes.rb +25 -0
  15. data/lib/hypertemplate/registry.rb +24 -0
  16. data/lib/hypertemplate/version.rb +13 -0
  17. data/script/console +7 -0
  18. data/test/hypertemplate/builder/base_test.rb +45 -0
  19. data/test/hypertemplate/builder/json_test.rb +506 -0
  20. data/test/hypertemplate/builder/values_test.rb +12 -0
  21. data/test/hypertemplate/builder/xml_test.rb +479 -0
  22. data/test/hypertemplate/helper_test.rb +116 -0
  23. data/test/hypertemplate/hook/rails_test.rb +77 -0
  24. data/test/hypertemplate/hook/sinatra_test.rb +89 -0
  25. data/test/hypertemplate/hook/tilt_test.rb +48 -0
  26. data/test/hypertemplate/recipes_test.rb +94 -0
  27. data/test/rails2_skel/Rakefile +16 -0
  28. data/test/rails2_skel/app/controllers/application_controller.rb +1 -0
  29. data/test/rails2_skel/app/controllers/test_controller.rb +18 -0
  30. data/test/rails2_skel/app/views/test/_feed_member.tokamak +9 -0
  31. data/test/rails2_skel/app/views/test/feed.tokamak +24 -0
  32. data/test/rails2_skel/app/views/test/show.hyper +31 -0
  33. data/test/rails2_skel/config/boot.rb +110 -0
  34. data/test/rails2_skel/config/environment.rb +20 -0
  35. data/test/rails2_skel/config/environments/development.rb +17 -0
  36. data/test/rails2_skel/config/environments/production.rb +28 -0
  37. data/test/rails2_skel/config/environments/test.rb +28 -0
  38. data/test/rails2_skel/config/initializers/cookie_verification_secret.rb +2 -0
  39. data/test/rails2_skel/config/initializers/mime_types.rb +3 -0
  40. data/test/rails2_skel/config/initializers/new_rails_defaults.rb +10 -0
  41. data/test/rails2_skel/config/initializers/session_store.rb +5 -0
  42. data/test/rails2_skel/config/routes.rb +43 -0
  43. data/test/rails2_skel/log/development.log +10190 -0
  44. data/test/rails2_skel/script/console +3 -0
  45. data/test/test_helper.rb +9 -0
  46. 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