roxml 2.4.1 → 2.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/History.txt +21 -0
  2. data/MIT-LICENSE +1 -1
  3. data/Manifest.txt +27 -6
  4. data/Rakefile +2 -2
  5. data/TODO +35 -14
  6. data/config/website.yml +2 -0
  7. data/examples/amazon.rb +33 -0
  8. data/examples/current_weather.rb +27 -0
  9. data/examples/dashed_elements.rb +20 -0
  10. data/examples/posts.rb +27 -0
  11. data/examples/twitter.rb +37 -0
  12. data/examples/xml/amazon.xml +133 -0
  13. data/examples/xml/current_weather.xml +89 -0
  14. data/examples/xml/dashed_elements.xml +52 -0
  15. data/examples/xml/posts.xml +23 -0
  16. data/examples/xml/twitter.xml +422 -0
  17. data/lib/roxml.rb +35 -6
  18. data/lib/roxml/{options.rb → definition.rb} +60 -88
  19. data/lib/roxml/extensions.rb +3 -0
  20. data/lib/roxml/hash_definition.rb +59 -0
  21. data/lib/roxml/xml.rb +15 -272
  22. data/lib/roxml/xml/{libxml.rb → parsers/libxml.rb} +13 -5
  23. data/lib/roxml/xml/{rexml.rb → parsers/rexml.rb} +13 -4
  24. data/lib/roxml/xml/references.rb +290 -0
  25. data/roxml.gemspec +4 -4
  26. data/spec/examples/amazon_spec.rb +53 -0
  27. data/spec/examples/current_weather_spec.rb +37 -0
  28. data/spec/examples/dashed_elements_spec.rb +20 -0
  29. data/spec/examples/post_spec.rb +24 -0
  30. data/spec/examples/twitter_spec.rb +32 -0
  31. data/spec/spec.opts +1 -0
  32. data/spec/spec_helper.rb +16 -0
  33. data/tasks/rspec.rake +21 -0
  34. data/test/unit/definition_test.rb +160 -0
  35. data/test/unit/inheritance_test.rb +22 -1
  36. data/test/unit/roxml_test.rb +30 -1
  37. data/test/unit/xml_name_test.rb +29 -0
  38. data/test/unit/xml_namespace_test.rb +38 -1
  39. data/website/index.html +98 -0
  40. metadata +30 -9
  41. data/html/index.html +0 -278
  42. data/html/style.css +0 -79
  43. 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
- if default_namespace && !xpath.include?(':')
12
- find(namespaced(xpath),
13
- in_default_namespace(default_namespace.href))
14
- else
15
- find(xpath)
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
- REXML::XPath.match(self, xpath)
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(string)
42
- REXML::Document.new(string, :ignore_whitespace_nodes => :all)
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
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{roxml}
5
- s.version = "2.4.1"
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-28}
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", "html/index.html", "html/style.css", "lib/roxml.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/options.rb", "lib/roxml/xml.rb", "lib/roxml/xml/libxml.rb", "lib/roxml/xml/rexml.rb", "roxml.gemspec", "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/freeze_test.rb", "test/unit/inheritance_test.rb", "test/unit/options_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"]
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/xml_construct_test.rb", "test/unit/options_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"]
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