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,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
+