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,12 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class Hypertemplate::Builder::ValuesTest < Test::Unit::TestCase
4
+
5
+ def test_should_not_remove_important_methods
6
+ values = Hypertemplate::Builder::Values.new(nil)
7
+ assert values.respond_to? :method_missing
8
+ assert values.respond_to? :object_id
9
+ assert values.respond_to? :respond_to?
10
+ end
11
+
12
+ end
@@ -0,0 +1,479 @@
1
+ require 'test_helper'
2
+
3
+ class Hypertemplate::Builder::XmlTest < Test::Unit::TestCase
4
+
5
+ def test_media_type_should_be_xml
6
+ assert_equal ["application/xml","text/xml"], Hypertemplate::Builder::Xml.media_types
7
+ end
8
+
9
+ def test_the_most_simple_xml
10
+ obj = [{ :foo => "bar" }]
11
+ xml = Hypertemplate::Builder::Xml.build(obj) do |collection|
12
+ collection.values do |values|
13
+ values.id "an_id"
14
+ end
15
+
16
+ collection.members do |member, some_foos|
17
+ member.values do |values|
18
+ values.id some_foos[:foo]
19
+ end
20
+ end
21
+ end
22
+
23
+ xml = Nokogiri::XML::Document.parse(xml)
24
+
25
+ assert_equal "root" , xml.root.name
26
+ assert_equal "an_id", xml.css("root id").first.text
27
+ assert_equal "bar" , xml.css("root > member > id").first.text
28
+ end
29
+
30
+ def test_root_set_on_builder
31
+ obj = [{ :foo => "bar" }, { :foo => "zue" }]
32
+ xml = Hypertemplate::Builder::Xml.build(obj, :root => "foos") do |collection|
33
+ collection.values do |values|
34
+ values.id "an_id"
35
+ end
36
+
37
+ collection.members do |member, some_foos|
38
+ member.values do |values|
39
+ values.id some_foos[:foo]
40
+ end
41
+ end
42
+ end
43
+
44
+ xml = Nokogiri::XML::Document.parse(xml)
45
+
46
+ assert_equal "foos" , xml.root.name
47
+ assert_equal "an_id", xml.css("foos id").first.text
48
+ assert_equal "bar" , xml.css("foos > member > id").first.text
49
+ end
50
+
51
+ def test_collection_set_on_members
52
+ obj = { :foo => "bar" }
53
+ a_collection = [1,2,3,4]
54
+ xml = Hypertemplate::Builder::Xml.build(obj) do |collection|
55
+ collection.values do |values|
56
+ values.id "an_id"
57
+ end
58
+
59
+ collection.members(:collection => a_collection) do |member, number|
60
+ member.values do |values|
61
+ values.id number
62
+ end
63
+ end
64
+ end
65
+
66
+ xml = Nokogiri::XML::Document.parse(xml)
67
+
68
+ assert_equal "an_id", xml.css("root id").first.text
69
+ assert_equal "1" , xml.css("root > member > id").first.text
70
+ assert_equal 4 , xml.css("root > member > id").size
71
+ end
72
+
73
+ def test_raise_exception_for_not_passing_a_collection_as_parameter_to_members
74
+ obj = 42
75
+
76
+ assert_raise Hypertemplate::BuilderError do
77
+ Hypertemplate::Builder::Xml.build(obj) do |collection, number|
78
+ collection.values do |values|
79
+ values.id number
80
+ end
81
+
82
+ collection.members do |member, item|
83
+ member.values do |values|
84
+ values.id item
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ def test_root_set_on_members
92
+ obj = [{ :foo => "bar" }, { :foo => "zue" }]
93
+ xml = Hypertemplate::Builder::Xml.build(obj) do |collection|
94
+ collection.values do |values|
95
+ values.id "an_id"
96
+ end
97
+
98
+ collection.members(:root => "foos") do |member, some_foos|
99
+ member.values do |values|
100
+ values.id some_foos[:foo]
101
+ end
102
+ end
103
+ end
104
+
105
+ xml = Nokogiri::XML::Document.parse(xml)
106
+
107
+ assert_equal "an_id", xml.css("root id").first.text
108
+ assert_equal "bar" , xml.css("root > foos > id").first.text
109
+ assert_equal 2 , xml.css("root > foos > id").size
110
+ end
111
+
112
+ def test_values_that_should_be_an_array
113
+ obj = [{ :foo => ["bar", "zoom"] }]
114
+ xml = Hypertemplate::Builder::Xml.build(obj) do |collection|
115
+ collection.values do |values|
116
+ values.id "an_id"
117
+ end
118
+
119
+ collection.members do |member, some_foos|
120
+ member.values do |values|
121
+ values.ids []
122
+ some_foos[:foo].each do |id|
123
+ values.ids id
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ xml = Nokogiri::XML::Document.parse(xml)
130
+
131
+ assert_equal "root" , xml.root.name
132
+ assert_equal "an_id", xml.css("root id").first.text
133
+ assert_equal ["bar", "zoom"], xml.css("root > member > ids").map { |id| id.text }
134
+ end
135
+
136
+ def test_nested_crazy_values
137
+ obj = [{ :foo => "bar" }, { :foo => "zue" }]
138
+ xml = Hypertemplate::Builder::Xml.build(obj) do |collection|
139
+ collection.values do |values|
140
+ values.body {
141
+ values.face {
142
+ values.eyes "blue"
143
+ values.mouth "large"
144
+ }
145
+ }
146
+ end
147
+ end
148
+
149
+ xml = Nokogiri::XML::Document.parse(xml)
150
+
151
+ assert_equal "blue" , xml.css("root > body > face > eyes").first.text
152
+ assert_equal "large", xml.css("root > body > face > mouth").first.text
153
+ end
154
+
155
+ def test_xml_attributes_on_values
156
+ obj = [{ :foo => "bar" }, { :foo => "zue" }]
157
+ xml = Hypertemplate::Builder::Xml.build(obj) do |collection|
158
+ collection.values do |values|
159
+ values.body(:type => "fat", :gender => "male") {
160
+ values.face {
161
+ values.eyes "blue"
162
+ values.mouth "large", :teeth_count => 32
163
+ }
164
+ }
165
+ end
166
+ end
167
+
168
+ xml = Nokogiri::XML::Document.parse(xml)
169
+
170
+ assert_equal "fat" , xml.css("root > body").first["type"]
171
+ assert_equal "32" , xml.css("root > body > face > mouth").first["teeth_count"]
172
+ end
173
+
174
+ def test_xml_namespaces_on_values
175
+ obj = [{ :foo => "bar" }, { :foo => "zue" }]
176
+ xml = Hypertemplate::Builder::Xml.build(obj) do |collection|
177
+ collection.values do |values|
178
+ values.body("xmlns:biology" => "http://a.biology.namespace.com") {
179
+ values["biology"].face {
180
+ values["biology"].eyes "blue"
181
+ values["biology"].mouth "large", :teeth_count => 32
182
+ }
183
+ }
184
+ end
185
+ end
186
+
187
+ xml = Nokogiri::XML::Document.parse(xml)
188
+
189
+ assert_equal "biology", xml.at_xpath(".//biology:face", {"biology" => "http://a.biology.namespace.com"}).namespace.prefix
190
+ end
191
+
192
+ def test_build_full_collection
193
+ time = Time.now
194
+ some_articles = [
195
+ {:id => 1, :title => "a great article", :updated => time},
196
+ {:id => 2, :title => "another great article", :updated => time}
197
+ ]
198
+
199
+ xml = Hypertemplate::Builder::Xml.build(some_articles) do |collection|
200
+ collection.values do |values|
201
+ values.id "http://example.com/json"
202
+ values.title "Feed"
203
+ values.updated time
204
+
205
+ values.author {
206
+ values.name "John Doe"
207
+ values.email "joedoe@example.com"
208
+ }
209
+
210
+ values.author {
211
+ values.name "Foo Bar"
212
+ values.email "foobar@example.com"
213
+ }
214
+ end
215
+
216
+ collection.link("next" , "http://a.link.com/next")
217
+ collection.link("previous", "http://a.link.com/previous")
218
+
219
+ collection.members(:root => "articles") do |member, article|
220
+ member.values do |values|
221
+ values.id "uri:#{article[:id]}"
222
+ values.title article[:title]
223
+ values.updated article[:updated]
224
+ end
225
+
226
+ member.link("image", "http://example.com/image/1")
227
+ member.link("image", "http://example.com/image/2", :type => "application/json")
228
+ end
229
+ end
230
+
231
+ xml = Nokogiri::XML::Document.parse(xml)
232
+
233
+ assert_equal "John Doe" , xml.css("root > author").first.css("name").first.text
234
+ assert_equal "foobar@example.com" , xml.css("root > author").last.css("email").first.text
235
+
236
+ assert_equal "http://a.link.com/next" , xml.css("root > link").first["href"]
237
+ assert_equal "next" , xml.css("root > link").first["rel"]
238
+ assert_equal "application/xml" , xml.css("root > link").last["type"]
239
+
240
+ assert_equal "uri:1" , xml.css("root > articles").first.css("id").first.text
241
+ assert_equal "a great article" , xml.css("root > articles").first.css("title").first.text
242
+ assert_equal "http://example.com/image/1" , xml.css("root > articles").first.css("link").first["href"]
243
+ assert_equal "image" , xml.css("root > articles").first.css("link").first["rel"]
244
+ assert_equal "application/json" , xml.css("root > articles").first.css("link").last["type"]
245
+ end
246
+
247
+ def test_build_full_member
248
+ time = Time.now
249
+ an_article = {:id => 1, :title => "a great article", :updated => time}
250
+
251
+ xml = Hypertemplate::Builder::Xml.build(an_article, :root => "article") do |member, article|
252
+ member.values do |values|
253
+ values.id "uri:#{article[:id]}"
254
+ values.title article[:title]
255
+ values.updated article[:updated]
256
+
257
+ values.domain("xmlns" => "http://a.namespace.com") {
258
+ member.link("image", "http://example.com/image/1")
259
+ member.link("image", "http://example.com/image/2", :type => "application/atom+xml")
260
+ }
261
+ end
262
+
263
+ member.link("image", "http://example.com/image/1")
264
+ member.link("image", "http://example.com/image/2", :type => "application/json")
265
+ end
266
+
267
+ xml = Nokogiri::XML::Document.parse(xml)
268
+
269
+ assert_equal "http://example.com/image/1" , xml.css("article > link").first["href"]
270
+ assert_equal "image" , xml.css("article > link").first["rel"]
271
+ assert_equal "application/json" , xml.css("article > link").last["type"]
272
+
273
+ assert_equal "http://example.com/image/1" , xml.xpath("/article/xmlns:domain/xmlns:link", {"xmlns" => "http://a.namespace.com"}).first["href"]
274
+ assert_equal "image" , xml.xpath("/article/xmlns:domain/xmlns:link", {"xmlns" => "http://a.namespace.com"}).first["rel"]
275
+ assert_equal "application/atom+xml" , xml.xpath("/article/xmlns:domain/xmlns:link", {"xmlns" => "http://a.namespace.com"}).last["type"]
276
+ end
277
+ end
278
+
279
+ class Hypertemplate::Builder::XmlLambdaTest < Test::Unit::TestCase
280
+
281
+ def xml_build_and_parse(obj = {}, options = {}, &block)
282
+ block ||= lambda {}
283
+ xml = Hypertemplate::Builder::Xml.build_dsl(obj, options, &block)
284
+ Nokogiri::XML::Document.parse(xml)
285
+ end
286
+
287
+ def test_accepts_custom_values
288
+ xml = xml_build_and_parse do
289
+ name "erich"
290
+ end
291
+
292
+ assert_equal "erich", xml.css("root name").first.text
293
+ end
294
+
295
+ def test_supports_any_attribute_by_using_the_write_method
296
+ xml = xml_build_and_parse do
297
+ write :to_s , "22"
298
+ end
299
+
300
+ assert_equal "22", xml.css("root to_s").first.text
301
+ end
302
+
303
+ def test_id_method_is_also_accepted
304
+ xml = xml_build_and_parse do
305
+ id "22"
306
+ end
307
+
308
+ assert_equal "22", xml.css("root id").first.text
309
+ end
310
+
311
+ def test_root_member_should_be_called_root
312
+ xml = xml_build_and_parse
313
+
314
+ assert_equal "root" , xml.root.name
315
+ end
316
+
317
+ def test_allows_iterating_over_a_collection
318
+ items = [{ :name => "pencil" }]
319
+ xml = xml_build_and_parse do
320
+ each(items) do |item|
321
+ name item[:name]
322
+ end
323
+ end
324
+
325
+ assert_equal "pencil" , xml.css("root > member > name").first.text
326
+ end
327
+
328
+ def test_allows_collection_custom_member_name
329
+ items = [{ :name => "pencil" }]
330
+ xml = xml_build_and_parse do
331
+ each(items, :root => "item") do |item|
332
+ name item[:name]
333
+ end
334
+ end
335
+
336
+ assert_equal "pencil" , xml.css("root > item > name").first.text
337
+ end
338
+
339
+ def test_allows_typical_usage_of_a_collection
340
+ items = [{ :name => "pencil" }, { :name => "eraser"}]
341
+ xml = xml_build_and_parse do
342
+ items {
343
+ each(items, :root => "item") do |item|
344
+ name item[:name]
345
+ end
346
+ }
347
+ end
348
+
349
+ assert_equal "pencil" , xml.css("root > items > item > name").first.text
350
+ assert_equal "eraser" , xml.css("root > items > item > name").last.text
351
+ end
352
+
353
+ def test_supports_custom_root_with_collections
354
+ items = [{ :name => "pencil" }, { :name => "eraser"}]
355
+ xml = xml_build_and_parse({}, :root => "items") do
356
+ each(items, :root => "item") do |item|
357
+ name item[:name]
358
+ end
359
+ end
360
+
361
+ assert_equal "pencil" , xml.css("items > item > name").first.text
362
+ assert_equal "eraser" , xml.css("items > item > name").last.text
363
+ end
364
+
365
+ def test_uses_outside_scope_when_passing_an_arg_to_the_builder
366
+ helper = Object.new
367
+ def helper.name
368
+ "guilherme"
369
+ end
370
+ xml = xml_build_and_parse(helper) do |s|
371
+ name s.name
372
+ end
373
+
374
+ assert_equal "guilherme", xml.css("root name").first.text
375
+ end
376
+
377
+ def test_uses_externally_declared_objects_if_accessible
378
+ obj = { :category => "esporte" }
379
+ xml = xml_build_and_parse do |s|
380
+ categoria obj[:category]
381
+ end
382
+
383
+ assert_equal "esporte", xml.css("root categoria").first.text
384
+ end
385
+
386
+ def test_accepts_nested_elements
387
+ xml = xml_build_and_parse do
388
+ body {
389
+ face {
390
+ eyes "blue"
391
+ mouth "large"
392
+ }
393
+ }
394
+ end
395
+
396
+ assert_equal "blue" , xml.css("root > body > face > eyes").first.text
397
+ assert_equal "large", xml.css("root > body > face > mouth").first.text
398
+ end
399
+
400
+ def test_accepts_xml_attributes_on_values
401
+ xml = xml_build_and_parse do
402
+ body(:type => "fat", :gender => "male") {
403
+ face {
404
+ eyes "blue"
405
+ mouth "large", :teeth_count => 32
406
+ }
407
+ }
408
+ end
409
+
410
+ assert_equal "fat" , xml.css("root > body").first["type"]
411
+ assert_equal "32" , xml.css("root > body > face > mouth").first["teeth_count"]
412
+ end
413
+
414
+ def test_accepts_xml_namespaces_on_values
415
+ obj = [{ :foo => "bar" }, { :foo => "zue" }]
416
+ xml = xml_build_and_parse(obj) do
417
+ body("xmlns:biology" => "http://a.biology.namespace.com") {
418
+ ns("biology").face {
419
+ ns("biology").eyes "blue"
420
+ ns("biology").mouth "large", :teeth_count => 32
421
+ }
422
+ }
423
+ end
424
+
425
+ assert_equal "biology", xml.at_xpath(".//biology:face", {"biology" => "http://a.biology.namespace.com"}).namespace.prefix
426
+ end
427
+
428
+ def test_an_entire_complex_case
429
+ time = Time.now
430
+ articles = [
431
+ {:id => 1, :title => "a great article", :updated => time},
432
+ {:id => 2, :title => "another great article", :updated => time}
433
+ ]
434
+
435
+ xml = xml_build_and_parse do
436
+ id "http://example.com/xml"
437
+ title "Feed"
438
+ updated time
439
+
440
+ authors {
441
+ author {
442
+ name "John Doe"
443
+ email "joedoe@example.com"
444
+ }
445
+
446
+ author {
447
+ name "Foo Bar"
448
+ email "foobar@example.com"
449
+ }
450
+ }
451
+
452
+ link("next" , "http://a.link.com/next")
453
+ link("previous", "http://a.link.com/previous")
454
+
455
+ each(articles, :root => "articles") do |article|
456
+ id "uri:#{article[:id]}"
457
+ title article[:title]
458
+ updated article[:updated]
459
+
460
+ link("image", "http://example.com/image/1")
461
+ link("image", "http://example.com/image/2", :type => "application/json")
462
+ end
463
+ end
464
+
465
+ assert_equal "John Doe" , xml.css("root > authors > author").first.css("name").first.text
466
+ assert_equal "foobar@example.com" , xml.css("root > authors > author").last.css("email").first.text
467
+
468
+ assert_equal "http://a.link.com/next" , xml.css("root > link").first["href"]
469
+ assert_equal "next" , xml.css("root > link").first["rel"]
470
+ assert_equal "application/xml" , xml.css("root > link").last["type"]
471
+
472
+ assert_equal "uri:1" , xml.css("root > articles").first.css("id").first.text
473
+ assert_equal "a great article" , xml.css("root > articles").first.css("title").first.text
474
+ assert_equal "http://example.com/image/1" , xml.css("root > articles").first.css("link").first["href"]
475
+ assert_equal "image" , xml.css("root > articles").first.css("link").first["rel"]
476
+ assert_equal "application/json" , xml.css("root > articles").first.css("link").last["type"]
477
+ end
478
+ end
479
+