roxml 2.4.1 → 2.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +21 -0
- data/MIT-LICENSE +1 -1
- data/Manifest.txt +27 -6
- data/Rakefile +2 -2
- data/TODO +35 -14
- data/config/website.yml +2 -0
- data/examples/amazon.rb +33 -0
- data/examples/current_weather.rb +27 -0
- data/examples/dashed_elements.rb +20 -0
- data/examples/posts.rb +27 -0
- data/examples/twitter.rb +37 -0
- data/examples/xml/amazon.xml +133 -0
- data/examples/xml/current_weather.xml +89 -0
- data/examples/xml/dashed_elements.xml +52 -0
- data/examples/xml/posts.xml +23 -0
- data/examples/xml/twitter.xml +422 -0
- data/lib/roxml.rb +35 -6
- data/lib/roxml/{options.rb → definition.rb} +60 -88
- data/lib/roxml/extensions.rb +3 -0
- data/lib/roxml/hash_definition.rb +59 -0
- data/lib/roxml/xml.rb +15 -272
- data/lib/roxml/xml/{libxml.rb → parsers/libxml.rb} +13 -5
- data/lib/roxml/xml/{rexml.rb → parsers/rexml.rb} +13 -4
- data/lib/roxml/xml/references.rb +290 -0
- data/roxml.gemspec +4 -4
- data/spec/examples/amazon_spec.rb +53 -0
- data/spec/examples/current_weather_spec.rb +37 -0
- data/spec/examples/dashed_elements_spec.rb +20 -0
- data/spec/examples/post_spec.rb +24 -0
- data/spec/examples/twitter_spec.rb +32 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/rspec.rake +21 -0
- data/test/unit/definition_test.rb +160 -0
- data/test/unit/inheritance_test.rb +22 -1
- data/test/unit/roxml_test.rb +30 -1
- data/test/unit/xml_name_test.rb +29 -0
- data/test/unit/xml_namespace_test.rb +38 -1
- data/website/index.html +98 -0
- metadata +30 -9
- data/html/index.html +0 -278
- data/html/style.css +0 -79
- data/test/unit/options_test.rb +0 -103
@@ -8,11 +8,15 @@ module ROXML
|
|
8
8
|
|
9
9
|
module NamespacedSearch
|
10
10
|
def search(xpath)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
begin
|
12
|
+
if default_namespace && !xpath.include?(':')
|
13
|
+
find(namespaced(xpath),
|
14
|
+
in_default_namespace(default_namespace.href))
|
15
|
+
else
|
16
|
+
find(xpath)
|
17
|
+
end
|
18
|
+
rescue Exception => ex
|
19
|
+
raise ex, xpath
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
@@ -57,6 +61,10 @@ module ROXML
|
|
57
61
|
def parse_file(path)
|
58
62
|
file(path).parse
|
59
63
|
end
|
64
|
+
|
65
|
+
def parse_io(stream)
|
66
|
+
io(stream).parse
|
67
|
+
end
|
60
68
|
end
|
61
69
|
end
|
62
70
|
end
|
@@ -20,7 +20,11 @@ module ROXML
|
|
20
20
|
alias_attribute :content, :text
|
21
21
|
|
22
22
|
def search(xpath)
|
23
|
-
|
23
|
+
begin
|
24
|
+
REXML::XPath.match(self, xpath)
|
25
|
+
rescue Exception => ex
|
26
|
+
raise ex, xpath
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
def child_add(element)
|
@@ -38,14 +42,19 @@ module ROXML
|
|
38
42
|
|
39
43
|
class Parser
|
40
44
|
class << self
|
41
|
-
def parse(
|
42
|
-
REXML::Document.new(
|
45
|
+
def parse(source)
|
46
|
+
REXML::Document.new(source, :ignore_whitespace_nodes => :all)
|
43
47
|
end
|
44
48
|
|
45
|
-
def parse_file(path)
|
49
|
+
def parse_file(path) #:nodoc:
|
50
|
+
path = path.sub('file:', '') if path.starts_with?('file:')
|
46
51
|
parse(open(path))
|
47
52
|
end
|
48
53
|
|
54
|
+
def parse_io(path) #:nodoc:
|
55
|
+
parse(path)
|
56
|
+
end
|
57
|
+
|
49
58
|
def register_error_handler(&block)
|
50
59
|
end
|
51
60
|
end
|
@@ -0,0 +1,290 @@
|
|
1
|
+
module ROXML
|
2
|
+
class RequiredElementMissing < Exception # :nodoc:
|
3
|
+
end
|
4
|
+
|
5
|
+
#
|
6
|
+
# Internal base class that represents an XML - Class binding.
|
7
|
+
#
|
8
|
+
class XMLRef # :nodoc:
|
9
|
+
delegate :required?, :array?, :blocks, :accessor, :variable_name, :default, :to => :opts
|
10
|
+
|
11
|
+
def initialize(opts, instance)
|
12
|
+
@opts = opts
|
13
|
+
@instance = instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_xml
|
17
|
+
val = @instance.__send__(accessor)
|
18
|
+
opts.to_xml.respond_to?(:call) ? opts.to_xml.call(val) : val
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_xml(xml, value)
|
22
|
+
returning wrap(xml) do |xml|
|
23
|
+
write_xml(xml, value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
opts.name_explicit? ? opts.name : conventionize(opts.name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def xpath_name
|
32
|
+
if !opts.name_explicit? && namespace = @instance.class.roxml_namespace
|
33
|
+
"#{namespace}:#{name}"
|
34
|
+
else
|
35
|
+
name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def default
|
40
|
+
@default ||= @opts.default || (@opts.array? ? Array.new : nil)
|
41
|
+
@default.duplicable? ? @default.dup : @default
|
42
|
+
end
|
43
|
+
|
44
|
+
def value_in(xml)
|
45
|
+
value = fetch_value(xml)
|
46
|
+
freeze(apply_blocks(value))
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
attr_reader :opts
|
51
|
+
|
52
|
+
def conventionize(what)
|
53
|
+
if !what.blank? && @instance.try(:class).try(:roxml_naming_convention).respond_to?(:call)
|
54
|
+
require 'uri'
|
55
|
+
URI.unescape(@instance.class.roxml_naming_convention.call(URI.escape(what, /\/|::/)))
|
56
|
+
else
|
57
|
+
what
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def wrapper
|
62
|
+
conventionize(opts.wrapper)
|
63
|
+
end
|
64
|
+
|
65
|
+
def apply_blocks(val)
|
66
|
+
begin
|
67
|
+
blocks.apply_to(val)
|
68
|
+
rescue Exception => ex
|
69
|
+
raise ex, "#{accessor}: #{ex.message}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def freeze(val)
|
74
|
+
if opts.freeze?
|
75
|
+
val.each(&:freeze) if val.is_a?(Enumerable)
|
76
|
+
val.freeze
|
77
|
+
else
|
78
|
+
val
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def xpath
|
83
|
+
wrapper ? "#{wrapper}/#{xpath_name}" : xpath_name.to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
def auto_xpath
|
87
|
+
"#{conventionize(opts.name.pluralize)}/#{xpath_name}" if array?
|
88
|
+
end
|
89
|
+
|
90
|
+
def wrap(xml)
|
91
|
+
return xml if !wrapper || xml.name == wrapper
|
92
|
+
if child = xml.children.find {|c| c.name == wrapper }
|
93
|
+
return child
|
94
|
+
end
|
95
|
+
xml.child_add(XML::Node.new_element(wrapper))
|
96
|
+
end
|
97
|
+
|
98
|
+
def nodes_in(xml)
|
99
|
+
vals = xml.search(xpath)
|
100
|
+
|
101
|
+
if (opts.hash? || opts.array?) && vals.empty? && !wrapper && auto_xpath
|
102
|
+
vals = xml.search(auto_xpath)
|
103
|
+
@auto_vals = !vals.empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
if vals.empty?
|
107
|
+
raise RequiredElementMissing, "#{name} from #{xml} for #{accessor}" if required?
|
108
|
+
default
|
109
|
+
else
|
110
|
+
yield(vals)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Interal class representing an XML attribute binding
|
116
|
+
#
|
117
|
+
# In context:
|
118
|
+
# <element attribute="XMLAttributeRef">
|
119
|
+
# XMLTextRef
|
120
|
+
# </element>
|
121
|
+
class XMLAttributeRef < XMLRef # :nodoc:
|
122
|
+
private
|
123
|
+
# Updates the attribute in the given XML block to
|
124
|
+
# the value provided.
|
125
|
+
def write_xml(xml, value)
|
126
|
+
xml.attributes[name] = value.to_s.to_utf
|
127
|
+
end
|
128
|
+
|
129
|
+
def fetch_value(xml)
|
130
|
+
nodes_in(xml) do |nodes|
|
131
|
+
nodes.first.value
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def xpath_name
|
136
|
+
"@#{name}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Interal class representing XML content text binding
|
141
|
+
#
|
142
|
+
# In context:
|
143
|
+
# <element attribute="XMLAttributeRef">
|
144
|
+
# XMLTextRef
|
145
|
+
# </element>
|
146
|
+
class XMLTextRef < XMLRef # :nodoc:
|
147
|
+
delegate :cdata?, :content?, :name?, :to => :opts
|
148
|
+
|
149
|
+
private
|
150
|
+
# Updates the text in the given _xml_ block to
|
151
|
+
# the _value_ provided.
|
152
|
+
def write_xml(xml, value)
|
153
|
+
if content?
|
154
|
+
add(xml, value)
|
155
|
+
elsif name?
|
156
|
+
xml.name = value
|
157
|
+
elsif array?
|
158
|
+
value.each do |v|
|
159
|
+
add(xml.child_add(XML::Node.new_element(name)), v)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
add(xml.child_add(XML::Node.new_element(name)), value)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def fetch_value(xml)
|
167
|
+
if content? || name?
|
168
|
+
value =
|
169
|
+
if content?
|
170
|
+
xml.content.to_s.strip
|
171
|
+
elsif name?
|
172
|
+
xml.name
|
173
|
+
end
|
174
|
+
|
175
|
+
if value.empty?
|
176
|
+
raise RequiredElementMissing, "#{name} from #{xml} for #{accessor}" if required?
|
177
|
+
default
|
178
|
+
else
|
179
|
+
value
|
180
|
+
end
|
181
|
+
else
|
182
|
+
nodes_in(xml) do |nodes|
|
183
|
+
if array?
|
184
|
+
nodes.collect do |e|
|
185
|
+
e.content.strip.to_latin
|
186
|
+
end
|
187
|
+
else
|
188
|
+
nodes.first.content
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def add(dest, value)
|
195
|
+
if cdata?
|
196
|
+
dest.child_add(XML::Node.new_cdata(value.to_s.to_utf))
|
197
|
+
else
|
198
|
+
dest.content = value.to_s.to_utf
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
class XMLHashRef < XMLTextRef # :nodoc:
|
204
|
+
delegate :hash, :to => :opts
|
205
|
+
|
206
|
+
def initialize(opts, inst)
|
207
|
+
super(opts, inst)
|
208
|
+
@key = opts.hash.key.to_ref(inst)
|
209
|
+
@value = opts.hash.value.to_ref(inst)
|
210
|
+
end
|
211
|
+
|
212
|
+
private
|
213
|
+
# Updates the composed XML object in the given XML block to
|
214
|
+
# the value provided.
|
215
|
+
def write_xml(xml, value)
|
216
|
+
value.each_pair do |k, v|
|
217
|
+
node = xml.child_add(XML::Node.new_element(hash.wrapper))
|
218
|
+
@key.update_xml(node, k)
|
219
|
+
@value.update_xml(node, v)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def fetch_value(xml)
|
224
|
+
nodes_in(xml) do |nodes|
|
225
|
+
nodes.collect do |e|
|
226
|
+
[@key.value_in(e), @value.value_in(e)]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def apply_blocks(vals)
|
232
|
+
unless blocks.empty?
|
233
|
+
vals.collect! do |kvp|
|
234
|
+
super(kvp)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
vals.to_hash if vals
|
238
|
+
end
|
239
|
+
|
240
|
+
def freeze(vals)
|
241
|
+
if opts.freeze?
|
242
|
+
vals.each_pair{|k, v| k.freeze; v.freeze }
|
243
|
+
vals.freeze
|
244
|
+
else
|
245
|
+
vals
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
class XMLObjectRef < XMLTextRef # :nodoc:
|
251
|
+
delegate :type, :to => :opts
|
252
|
+
|
253
|
+
private
|
254
|
+
# Updates the composed XML object in the given XML block to
|
255
|
+
# the value provided.
|
256
|
+
def write_xml(xml, value)
|
257
|
+
if array?
|
258
|
+
value.each do |v|
|
259
|
+
xml.child_add(v.to_xml(name))
|
260
|
+
end
|
261
|
+
elsif value.is_a?(ROXML)
|
262
|
+
xml.child_add(value.to_xml(name))
|
263
|
+
else
|
264
|
+
node = XML::Node.new_element(name)
|
265
|
+
node.content = value.to_xml
|
266
|
+
xml.child_add(node)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def fetch_value(xml)
|
271
|
+
nodes_in(xml) do |nodes|
|
272
|
+
unless array?
|
273
|
+
instantiate(nodes.first)
|
274
|
+
else
|
275
|
+
nodes.collect do |e|
|
276
|
+
instantiate(e)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def instantiate(elem)
|
283
|
+
if type.respond_to? :from_xml
|
284
|
+
type.from_xml(elem)
|
285
|
+
else
|
286
|
+
type.new(elem)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
data/roxml.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{roxml}
|
5
|
-
s.version = "2.4.
|
5
|
+
s.version = "2.4.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Ben Woosley", "Zak Mandhro", "Anders Engstrom", "Russ Olsen"]
|
9
|
-
s.date = %q{2009-01-
|
9
|
+
s.date = %q{2009-01-31}
|
10
10
|
s.description = %q{ROXML is a Ruby library designed to make it easier for Ruby developers to work with XML. Using simple annotations, it enables Ruby classes to be mapped to XML. ROXML takes care of the marshalling and unmarshalling of mapped attributes so that developers can focus on building first-class Ruby classes. As a result, ROXML simplifies the development of RESTful applications, Web Services, and XML-RPC.}
|
11
11
|
s.email = %q{ben.woosley@gmail.com}
|
12
12
|
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
|
13
|
-
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "TODO", "
|
13
|
+
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "TODO", "config/website.yml", "examples/amazon.rb", "examples/current_weather.rb", "examples/dashed_elements.rb", "examples/posts.rb", "examples/twitter.rb", "examples/xml/amazon.xml", "examples/xml/current_weather.xml", "examples/xml/dashed_elements.xml", "examples/xml/posts.xml", "examples/xml/twitter.xml", "lib/roxml.rb", "lib/roxml/definition.rb", "lib/roxml/extensions.rb", "lib/roxml/extensions/active_support.rb", "lib/roxml/extensions/array.rb", "lib/roxml/extensions/array/conversions.rb", "lib/roxml/extensions/deprecation.rb", "lib/roxml/extensions/string.rb", "lib/roxml/extensions/string/conversions.rb", "lib/roxml/extensions/string/iterators.rb", "lib/roxml/hash_definition.rb", "lib/roxml/xml.rb", "lib/roxml/xml/parsers/libxml.rb", "lib/roxml/xml/parsers/rexml.rb", "lib/roxml/xml/references.rb", "roxml.gemspec", "spec/examples/amazon_spec.rb", "spec/examples/current_weather_spec.rb", "spec/examples/dashed_elements_spec.rb", "spec/examples/post_spec.rb", "spec/examples/twitter_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/rspec.rake", "tasks/test.rake", "test/bugs/rexml_bugs.rb", "test/fixtures/book_malformed.xml", "test/fixtures/book_pair.xml", "test/fixtures/book_text_with_attribute.xml", "test/fixtures/book_valid.xml", "test/fixtures/book_with_authors.xml", "test/fixtures/book_with_contributions.xml", "test/fixtures/book_with_contributors.xml", "test/fixtures/book_with_contributors_attrs.xml", "test/fixtures/book_with_default_namespace.xml", "test/fixtures/book_with_depth.xml", "test/fixtures/book_with_octal_pages.xml", "test/fixtures/book_with_publisher.xml", "test/fixtures/book_with_wrapped_attr.xml", "test/fixtures/dictionary_of_attr_name_clashes.xml", "test/fixtures/dictionary_of_attrs.xml", "test/fixtures/dictionary_of_guarded_names.xml", "test/fixtures/dictionary_of_mixeds.xml", "test/fixtures/dictionary_of_name_clashes.xml", "test/fixtures/dictionary_of_names.xml", "test/fixtures/dictionary_of_texts.xml", "test/fixtures/library.xml", "test/fixtures/library_uppercase.xml", "test/fixtures/muffins.xml", "test/fixtures/nameless_ageless_youth.xml", "test/fixtures/node_with_attr_name_conflicts.xml", "test/fixtures/node_with_name_conflicts.xml", "test/fixtures/numerology.xml", "test/fixtures/person.xml", "test/fixtures/person_with_guarded_mothers.xml", "test/fixtures/person_with_mothers.xml", "test/mocks/dictionaries.rb", "test/mocks/mocks.rb", "test/release/dependencies_test.rb", "test/test_helper.rb", "test/unit/array_test.rb", "test/unit/definition_test.rb", "test/unit/freeze_test.rb", "test/unit/inheritance_test.rb", "test/unit/overriden_output_test.rb", "test/unit/roxml_test.rb", "test/unit/string_test.rb", "test/unit/to_xml_test.rb", "test/unit/xml_attribute_test.rb", "test/unit/xml_block_test.rb", "test/unit/xml_bool_test.rb", "test/unit/xml_construct_test.rb", "test/unit/xml_convention_test.rb", "test/unit/xml_hash_test.rb", "test/unit/xml_initialize_test.rb", "test/unit/xml_name_test.rb", "test/unit/xml_namespace_test.rb", "test/unit/xml_object_test.rb", "test/unit/xml_required_test.rb", "test/unit/xml_text_test.rb", "vendor/override_rake_task/README", "vendor/override_rake_task/init.rb", "vendor/override_rake_task/install.rb", "vendor/override_rake_task/lib/override_rake_task.rb", "website/index.html"]
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.homepage = %q{http://roxml.rubyforge.org}
|
16
16
|
s.rdoc_options = ["--main", "README.rdoc"]
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.rubyforge_project = %q{roxml}
|
19
19
|
s.rubygems_version = %q{1.3.1.xported}
|
20
20
|
s.summary = %q{Ruby Object to XML mapping library}
|
21
|
-
s.test_files = ["test/unit/freeze_test.rb", "test/unit/array_test.rb", "test/unit/xml_convention_test.rb", "test/unit/xml_object_test.rb", "test/unit/xml_required_test.rb", "test/unit/xml_bool_test.rb", "test/unit/roxml_test.rb", "test/unit/xml_name_test.rb", "test/unit/
|
21
|
+
s.test_files = ["test/unit/freeze_test.rb", "test/unit/array_test.rb", "test/unit/xml_convention_test.rb", "test/unit/xml_object_test.rb", "test/unit/xml_required_test.rb", "test/unit/xml_bool_test.rb", "test/unit/roxml_test.rb", "test/unit/xml_name_test.rb", "test/unit/definition_test.rb", "test/unit/xml_construct_test.rb", "test/unit/string_test.rb", "test/unit/xml_namespace_test.rb", "test/unit/xml_text_test.rb", "test/unit/overriden_output_test.rb", "test/unit/xml_block_test.rb", "test/unit/xml_attribute_test.rb", "test/unit/inheritance_test.rb", "test/unit/xml_initialize_test.rb", "test/unit/xml_hash_test.rb", "test/unit/to_xml_test.rb"]
|
22
22
|
|
23
23
|
if s.respond_to? :specification_version then
|
24
24
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require example('amazon')
|
3
|
+
|
4
|
+
describe PITA::ItemSearchResponse do
|
5
|
+
before do
|
6
|
+
@response = PITA::ItemSearchResponse.from_xml(xml_for('amazon'))
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#total_results" do
|
10
|
+
it "should be parsed as a number" do
|
11
|
+
@response.total_results.should > 0
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#total_pages" do
|
16
|
+
it "should be parsed as a number" do
|
17
|
+
@response.total_pages.should > 0
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#items" do
|
22
|
+
it "should return a collection of items" do
|
23
|
+
@response.items.should be_an_instance_of(Array)
|
24
|
+
@response.items.each {|item| item.should be_an_instance_of(PITA::Item) }
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have the some number less than or equal to #total_results" do
|
28
|
+
@response.items.size.should > 0
|
29
|
+
@response.items.size.should <= @response.total_results
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe PITA::Item do
|
35
|
+
before do
|
36
|
+
@items = PITA::ItemSearchResponse.from_xml(xml_for('amazon')).items
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should extract asin" do
|
40
|
+
@items.each {|item| item.asin.should be_an_instance_of(String) }
|
41
|
+
@items.each {|item| item.asin.should_not be_empty }
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should extract detail_page_url" do
|
45
|
+
@items.each {|item| item.detail_page_url.should be_an_instance_of(String) }
|
46
|
+
@items.each {|item| item.detail_page_url.should_not be_empty }
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should extract manufacturer" do
|
50
|
+
@items.each {|item| item.manufacturer.should be_an_instance_of(String) }
|
51
|
+
@items.each {|item| item.manufacturer.should_not be_empty }
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require example('current_weather')
|
3
|
+
|
4
|
+
describe Weather do
|
5
|
+
before do
|
6
|
+
@weather = Weather.from_xml(xml_for('current_weather'))
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should extract observations" do
|
10
|
+
@weather.observation.should be_an_instance_of(WeatherObservation)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe WeatherObservation do
|
15
|
+
before do
|
16
|
+
@observation = Weather.from_xml(xml_for('current_weather')).observation
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should extract temperature" do
|
20
|
+
@observation.temperature.should > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should extract feels_like" do
|
24
|
+
@observation.feels_like.should > 0
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#current_condition" do
|
28
|
+
it "should extract current_condition" do
|
29
|
+
@observation.current_condition.should_not be_empty
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should extract icon attribute" do
|
33
|
+
pending "need to think options through for HappyMapper-style :attributes extensions"
|
34
|
+
@observation.current_condition.icon.should_not be_empty
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|