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
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require example('dashed_elements')
3
+
4
+ describe GitHub::Commit do
5
+ before do
6
+ @commit = GitHub::Commit.from_xml(xml_for('dashed_elements'))
7
+ end
8
+
9
+ it "should extract committed date" do
10
+ @commit.committed_date.should be_an_instance_of(Date)
11
+ end
12
+
13
+ it "should extract url" do
14
+ @commit.url.should_not be_empty
15
+ end
16
+
17
+ it "should extract id" do
18
+ @commit.id.should_not be_empty
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require example('posts')
3
+
4
+ describe Post do
5
+ before do
6
+ @posts = Posts.from_xml(xml_for('posts')).posts
7
+ end
8
+
9
+ it "should extract description" do
10
+ @posts.each {|post| post.description.should_not be_empty }
11
+ end
12
+
13
+ it "should extract href" do
14
+ @posts.each {|post| post.href.should_not be_empty }
15
+ end
16
+
17
+ it "should extract extended" do
18
+ @posts.each {|post| post.extended.should_not be_empty }
19
+ end
20
+
21
+ it "should extract time" do
22
+ @posts.each {|post| post.time.should be_an_instance_of(DateTime) }
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require example('twitter')
3
+
4
+ describe Statuses do
5
+ describe Status do
6
+ before do
7
+ @statuses = Statuses.from_xml(xml_for('twitter')).statuses
8
+ end
9
+
10
+ it "should extract text" do
11
+ @statuses.each {|status| status.text.should_not be_empty }
12
+ end
13
+
14
+ it "should extract source" do
15
+ @statuses.each {|status| status.source.should_not be_empty }
16
+ end
17
+
18
+ describe User do
19
+ before do
20
+ @users = @statuses.map(&:user)
21
+ end
22
+
23
+ it "should extract name" do
24
+ @users.each {|user| user.name.should == "John Nunemaker" }
25
+ end
26
+
27
+ it "should extract screen_name" do
28
+ @users.each {|user| user.screen_name.should == "jnunemaker" }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,16 @@
1
+ require 'pathname'
2
+
3
+ module ROXML
4
+ SILENCE_XML_NAME_WARNING = true
5
+ end
6
+
7
+ DIR = Pathname.new(__FILE__).dirname
8
+ require DIR.join('../lib/roxml').expand_path
9
+
10
+ def example(name)
11
+ DIR.join("../examples/#{name}.rb").expand_path
12
+ end
13
+
14
+ def xml_for(name)
15
+ DIR.join("../examples/xml/#{name}.xml").expand_path
16
+ end
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
@@ -0,0 +1,160 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class TestDefinition < Test::Unit::TestCase
4
+ def assert_hash(opts, kvp)
5
+ assert opts.hash?
6
+ assert !opts.array?
7
+ assert_equal kvp, {opts.hash.key.type => opts.hash.key.name,
8
+ opts.hash.value.type => opts.hash.value.name}
9
+ end
10
+
11
+ def test_text_in_array_means_as_array_for_text
12
+ opts = ROXML::Definition.new(:authors, [:text])
13
+ assert opts.array?
14
+ assert_equal :text, opts.type
15
+ end
16
+
17
+ def test_attr_in_array_means_as_array_for_attr
18
+ opts = ROXML::Definition.new(:authors, [:attr])
19
+ assert opts.array?
20
+ assert_equal :attr, opts.type
21
+ end
22
+
23
+ def test_object_in_array_means_as_array_for_object
24
+ opts = ROXML::Definition.new(:authors, [Hash])
25
+ assert opts.array?
26
+ assert_equal Hash, opts.type
27
+ end
28
+
29
+ def test_content_is_a_recognized_type
30
+ assert ROXML::Definition.new(:author, :content).content?
31
+ end
32
+
33
+ def test_required
34
+ assert !ROXML::Definition.new(:author, :content).required?
35
+ assert ROXML::Definition.new(:author, :content, :required => true).required?
36
+ assert !ROXML::Definition.new(:author, :content, :required => false).required?
37
+ end
38
+
39
+ def test_required_conflicts_with_else
40
+ assert_raise ArgumentError do
41
+ ROXML::Definition.new(:author, :content, :required => true, :else => 'Johnny')
42
+ end
43
+ assert_nothing_raised do
44
+ ROXML::Definition.new(:author, :content, :required => false, :else => 'Johnny')
45
+ end
46
+ end
47
+
48
+ def test_hash_of_attrs
49
+ opts = ROXML::Definition.new(:attributes, {:attrs => [:name, :value]})
50
+ assert_hash(opts, :attr => 'name', :attr => 'value')
51
+ end
52
+
53
+ def test_hash_with_attr_key_and_text_val
54
+ opts = ROXML::Definition.new(:attributes, {:key => {:attr => :name},
55
+ :value => :value})
56
+ assert_hash(opts, :attr => 'name', :text => 'value')
57
+ end
58
+
59
+ def test_hash_with_string_class_for_type
60
+ opts = ROXML::Definition.new(:attributes, {:key => {String => 'name'},
61
+ :value => {String => 'value'}})
62
+ assert_hash(opts, :text => 'name', :text => 'value')
63
+ end
64
+
65
+ def test_hash_with_attr_key_and_content_val
66
+ opts = ROXML::Definition.new(:attributes, {:key => {:attr => :name},
67
+ :value => :content})
68
+ assert_hash(opts, :attr => 'name', :content => '')
69
+ end
70
+
71
+ def test_hash_with_options
72
+ opts = ROXML::Definition.new(:definitions, {:attrs => [:dt, :dd]},
73
+ :in => :definitions)
74
+ assert_hash(opts, :attr => 'dt', :attr => 'dd')
75
+ end
76
+
77
+ def test_no_block_shorthand_means_no_block
78
+ assert ROXML::Definition.new(:count).blocks.empty?
79
+ assert ROXML::Definition.new(:count, :as => :intager).blocks.empty?
80
+ assert ROXML::Definition.new(:count, :as => :foat).blocks.empty?
81
+ end
82
+
83
+ def test_block_integer_shorthand
84
+ assert_equal 3, ROXML::Definition.new(:count, :as => Integer).blocks.first['3']
85
+ end
86
+
87
+ def test_block_float_shorthand
88
+ assert_equal 3.1, ROXML::Definition.new(:count, :as => Float).blocks.first['3.1']
89
+ end
90
+
91
+ def test_multiple_shorthands_raises
92
+ assert_raise ArgumentError do
93
+ ROXML::Definition.new(:count, :as => [Float, Integer])
94
+ end
95
+ end
96
+
97
+ def test_stacked_blocks
98
+ assert_equal 2, ROXML::Definition.new(:count, :as => Integer) {|val| val.to_i }.blocks.size
99
+ assert_equal 2, ROXML::Definition.new(:count, :as => Float) {|val| val.object_id }.blocks.size
100
+ end
101
+
102
+ def test_symbol_shorthands_are_deprecated
103
+ assert_deprecated do
104
+ ROXML::Definition.new(:junk, :as => :integer)
105
+ end
106
+ assert_deprecated do
107
+ ROXML::Definition.new(:junk, :as => :float)
108
+ end
109
+ end
110
+
111
+ def test_block_shorthand_supports_bool
112
+ assert_equal true, ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("1")
113
+ assert_equal [true, false, nil], ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call(["TrUe", "0", "328"])
114
+ end
115
+
116
+ def test_block_shorthand_supports_integer
117
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(" ")
118
+ assert_equal 792, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792")
119
+ assert_raise ArgumentError do
120
+ ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792.13")
121
+ end
122
+ assert_equal [792, 12, 328], ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(["792", "12", "328"])
123
+ end
124
+
125
+ def test_block_shorthand_supports_float
126
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(" ")
127
+ assert_equal 792.13, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("792.13")
128
+ assert_equal 240.0, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("240")
129
+ assert_equal [792.13, 240.0, 3.14], ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(["792.13", "240", "3.14"])
130
+ end
131
+
132
+ def test_block_shorthand_supports_time
133
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Time).blocks.first.call(" ")
134
+ assert_equal 31, ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call("12:31am").min
135
+ assert_equal [31, 0, 59], ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call(["12:31am", "3:00pm", "11:59pm"]).map(&:min)
136
+ end
137
+
138
+ def test_block_shorthand_supports_date
139
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Date).blocks.first.call(" ")
140
+ assert_equal "1970-09-03", ROXML::Definition.new(:datevalue, :as => Date).blocks.first.call("September 3rd, 1970").to_s
141
+ assert_equal ["1970-09-03", "1776-07-04"], ROXML::Definition.new(:datevalue, :as => Date).blocks.first.call(["September 3rd, 1970", "1776-07-04"]).map(&:to_s)
142
+ end
143
+
144
+ def test_block_shorthand_supports_datetime
145
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => DateTime).blocks.first.call(" ")
146
+ assert_equal "1970-09-03T12:05:00+00:00", ROXML::Definition.new(:datevalue, :as => DateTime).blocks.first.call("12:05pm, September 3rd, 1970").to_s
147
+ assert_equal ["1970-09-03T12:05:00+00:00", "1700-05-22T15:00:00+00:00"], ROXML::Definition.new(:datevalue, :as => DateTime).blocks.first.call(["12:05pm, September 3rd, 1970", "3:00pm, May 22, 1700"]).map(&:to_s)
148
+ end
149
+
150
+ def test_name_explicit_indicates_whether_from_option_is_present
151
+ assert_equal true, ROXML::Definition.new(:element, :from => 'somewhere').name_explicit?
152
+ assert_equal false, ROXML::Definition.new(:element).name_explicit?
153
+ end
154
+
155
+ def test_xpath_in_is_formed_properly
156
+ opts = ROXML::Definition.new(:manufacturer, :in => './')
157
+ assert_equal "manufacturer", opts.name
158
+ assert_equal "./", opts.wrapper
159
+ end
160
+ end
@@ -1,5 +1,17 @@
1
1
  require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
2
 
3
+ class ParentWithNamespace
4
+ include ROXML
5
+ xml_namespace 'parent_namespace'
6
+ end
7
+
8
+ class ChildWithInheritedNamespace < ParentWithNamespace
9
+ end
10
+
11
+ class ChildWithOwnNamespace < ParentWithNamespace
12
+ xml_namespace 'child_namespace'
13
+ end
14
+
3
15
  class InheritedBookWithDepth < Book
4
16
  xml_reader :depth, Measurement
5
17
  end
@@ -13,6 +25,7 @@ class TestInheritance < Test::Unit::TestCase
13
25
  <author>David Thomas, Andrew Hunt, Dave Thomas</author>
14
26
  <depth units="hundredths-meters">1130</depth>
15
27
  <publisher>Pragmattic Programmers</publisher>
28
+ <pagecount>500</pagecount>
16
29
  </book>
17
30
  }
18
31
 
@@ -24,7 +37,7 @@ class TestInheritance < Test::Unit::TestCase
24
37
  assert_equal 'The PickAxe', @b.title
25
38
  assert_equal 'Probably the best Ruby book out there', @b.description
26
39
  assert_equal 'David Thomas, Andrew Hunt, Dave Thomas', @b.author
27
- assert_equal 0, @b.pages
40
+ assert_equal 500, @b.pages
28
41
  end
29
42
 
30
43
  def test_it_should_include_its_own_attributes
@@ -39,4 +52,12 @@ class TestInheritance < Test::Unit::TestCase
39
52
  book = InheritedBookWithDepth.from_xml(@book_xml)
40
53
  assert_equal "Pragmattic Programmers", book.publisher
41
54
  end
55
+
56
+ def test_it_should_inherit_namespace
57
+ assert_equal 'parent_namespace', ChildWithInheritedNamespace.roxml_namespace
58
+ end
59
+
60
+ def test_inherited_namespace_should_be_overridable
61
+ assert_equal 'child_namespace', ChildWithOwnNamespace.roxml_namespace
62
+ end
42
63
  end
@@ -25,7 +25,36 @@ class TestROXML < Test::Unit::TestCase
25
25
  def test_tag_refs_is_deprecated
26
26
  assert_deprecated do
27
27
  Class.new do
28
- include ROXML
29
28
  end.tag_refs
29
+ include ROXML
30
+ end.tag_refs
31
+ end
32
+ end
33
+
34
+ def test_from_xml_should_support_pathnames
35
+ book = BookWithContributors.from_xml(Pathname.new(fixture_path(:book_with_contributors)))
36
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
37
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
38
+ book.contributors.each do |contributor|
39
+ assert(expected_contributors.include?(contributor.name))
40
+ end
41
+ end
42
+
43
+ def test_from_xml_should_support_uris
44
+ uri = URI.parse("file://#{File.expand_path(File.expand_path(fixture_path(:book_with_contributors)))}")
45
+ book = BookWithContributors.from_xml(uri)
46
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
47
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
48
+ book.contributors.each do |contributor|
49
+ assert(expected_contributors.include?(contributor.name))
50
+ end
51
+ end
52
+
53
+ def test_from_xml_should_support_files
54
+ book = BookWithContributors.from_xml(File.new(fixture_path(:book_with_contributors)))
55
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
56
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
57
+ book.contributors.each do |contributor|
58
+ assert(expected_contributors.include?(contributor.name))
30
59
  end
31
60
  end
32
61
  end
@@ -128,4 +128,33 @@ class TestXMLName < Test::Unit::TestCase
128
128
  NamedChild.xml_name?
129
129
  end
130
130
  end
131
+
132
+ def test_xml_name_should_not_be_conventionalized_if_explicitly_set
133
+ reference = ROXML::XMLTextRef.new(ROXML::Definition.new(:name, :from => 'georss:name'), WrapModule::InstanceStandin.new)
134
+ assert_equal "georss:name", reference.name
135
+ end
136
+
137
+ def test_xml_name_not_screwed_up_by_xml_convention
138
+ reference = ROXML::XMLTextRef.new(ROXML::Definition.new(:name, :in => './'), WrapModule::InstanceStandin.new)
139
+ assert_equal "name value", reference.value_in(ROXML::XML::Parser.parse(%(
140
+ <Wrapper>
141
+ <MoreStuff>
142
+ <DeepWrapper>
143
+ <Name>name value</Name>
144
+ </DeepWrapper>
145
+ </MoreStuff>
146
+ </Wrapper>
147
+ )).root)
148
+ end
149
+ end
150
+
151
+ module WrapModule
152
+ class BaseClass
153
+ include ROXML
154
+ xml_convention :camelcase
155
+ end
156
+
157
+ class InstanceStandin < BaseClass
158
+ xml_reader :name, :in => './'
159
+ end
131
160
  end
@@ -1,6 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
2
 
3
- class TestXMLNamespaces < Test::Unit::TestCase
3
+ class TestDefaultXMLNamespaces < Test::Unit::TestCase
4
4
  def setup
5
5
  @book = BookWithContributions.from_xml(fixture(:book_with_default_namespace))
6
6
  end
@@ -35,4 +35,41 @@ class TestXMLNamespaces < Test::Unit::TestCase
35
35
  assert_equal nil, xml.find_first('ns:node/subnode', 'ns:http://defaultnamespace.org')
36
36
  assert_equal "Another", xml.find_first('ns:node/ns:subnode', 'ns:http://defaultnamespace.org').content
37
37
  end
38
+ end
39
+
40
+ class NamespaceyObject
41
+ include ROXML
42
+ xml_namespace :aws
43
+
44
+ xml_reader :default_namespace
45
+ xml_reader :different_namespace, :from => 'different:namespace'
46
+ xml_reader :no_namespace, :from => 'no_namespace'
47
+ end
48
+
49
+ class TestXMLNamespaceDeclarations < Test::Unit::TestCase
50
+ def setup
51
+ @instance = NamespaceyObject.from_xml(%{
52
+ <aws:book xmlns:aws="http://www.aws.com/aws" xmlns:different="http://www.aws.com/different">
53
+ <aws:default_namespace>default_value</aws:default_namespace>
54
+ <different:namespace>different_value</different:namespace>
55
+ <no_namespace>no_value</no_namespace>
56
+ </aws:book>
57
+ })
58
+ end
59
+
60
+ def test_namespace_is_accessible
61
+ assert_equal "aws", @instance.class.roxml_namespace
62
+ end
63
+
64
+ def test_namespace_declaration_should_be_followed_on_attributes
65
+ assert_equal "default_value", @instance.default_namespace
66
+ end
67
+
68
+ def test_namespace_declaration_can_be_overriden_for_different_namespace_elements
69
+ assert_equal "different_value", @instance.different_namespace
70
+ end
71
+
72
+ def test_namespace_declaration_can_be_overriden_for_no_namespace_elements
73
+ assert_equal "no_value", @instance.no_namespace
74
+ end
38
75
  end