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