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.
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