ROXML 3.0.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.
Files changed (101) hide show
  1. data/.gitignore +6 -0
  2. data/.gitmodules +3 -0
  3. data/History.txt +299 -0
  4. data/MIT-LICENSE +18 -0
  5. data/README.rdoc +161 -0
  6. data/Rakefile +95 -0
  7. data/TODO +39 -0
  8. data/VERSION +1 -0
  9. data/config/website.yml +2 -0
  10. data/examples/amazon.rb +35 -0
  11. data/examples/current_weather.rb +27 -0
  12. data/examples/dashed_elements.rb +20 -0
  13. data/examples/library.rb +40 -0
  14. data/examples/posts.rb +27 -0
  15. data/examples/rails.rb +70 -0
  16. data/examples/twitter.rb +37 -0
  17. data/examples/xml/active_record.xml +70 -0
  18. data/examples/xml/amazon.xml +133 -0
  19. data/examples/xml/current_weather.xml +89 -0
  20. data/examples/xml/dashed_elements.xml +52 -0
  21. data/examples/xml/posts.xml +23 -0
  22. data/examples/xml/twitter.xml +422 -0
  23. data/lib/roxml.rb +547 -0
  24. data/lib/roxml/definition.rb +236 -0
  25. data/lib/roxml/hash_definition.rb +25 -0
  26. data/lib/roxml/xml.rb +43 -0
  27. data/lib/roxml/xml/parsers/libxml.rb +91 -0
  28. data/lib/roxml/xml/parsers/nokogiri.rb +77 -0
  29. data/lib/roxml/xml/references.rb +297 -0
  30. data/roxml.gemspec +201 -0
  31. data/spec/definition_spec.rb +486 -0
  32. data/spec/examples/active_record_spec.rb +40 -0
  33. data/spec/examples/amazon_spec.rb +54 -0
  34. data/spec/examples/current_weather_spec.rb +37 -0
  35. data/spec/examples/dashed_elements_spec.rb +20 -0
  36. data/spec/examples/library_spec.rb +46 -0
  37. data/spec/examples/post_spec.rb +24 -0
  38. data/spec/examples/twitter_spec.rb +32 -0
  39. data/spec/roxml_spec.rb +372 -0
  40. data/spec/shared_specs.rb +15 -0
  41. data/spec/spec.opts +1 -0
  42. data/spec/spec_helper.rb +14 -0
  43. data/spec/support/libxml.rb +3 -0
  44. data/spec/support/nokogiri.rb +3 -0
  45. data/spec/xml/attributes_spec.rb +36 -0
  46. data/spec/xml/namespace_spec.rb +240 -0
  47. data/spec/xml/namespaces_spec.rb +32 -0
  48. data/spec/xml/parser_spec.rb +26 -0
  49. data/tasks/rdoc.rake +13 -0
  50. data/tasks/rspec.rake +25 -0
  51. data/tasks/test.rake +35 -0
  52. data/test/fixtures/book_malformed.xml +5 -0
  53. data/test/fixtures/book_pair.xml +8 -0
  54. data/test/fixtures/book_text_with_attribute.xml +5 -0
  55. data/test/fixtures/book_valid.xml +5 -0
  56. data/test/fixtures/book_with_authors.xml +7 -0
  57. data/test/fixtures/book_with_contributions.xml +9 -0
  58. data/test/fixtures/book_with_contributors.xml +7 -0
  59. data/test/fixtures/book_with_contributors_attrs.xml +7 -0
  60. data/test/fixtures/book_with_default_namespace.xml +9 -0
  61. data/test/fixtures/book_with_depth.xml +6 -0
  62. data/test/fixtures/book_with_octal_pages.xml +4 -0
  63. data/test/fixtures/book_with_publisher.xml +7 -0
  64. data/test/fixtures/book_with_wrapped_attr.xml +3 -0
  65. data/test/fixtures/dictionary_of_attr_name_clashes.xml +8 -0
  66. data/test/fixtures/dictionary_of_attrs.xml +6 -0
  67. data/test/fixtures/dictionary_of_guarded_names.xml +6 -0
  68. data/test/fixtures/dictionary_of_mixeds.xml +4 -0
  69. data/test/fixtures/dictionary_of_name_clashes.xml +10 -0
  70. data/test/fixtures/dictionary_of_names.xml +4 -0
  71. data/test/fixtures/dictionary_of_texts.xml +10 -0
  72. data/test/fixtures/library.xml +30 -0
  73. data/test/fixtures/library_uppercase.xml +30 -0
  74. data/test/fixtures/muffins.xml +3 -0
  75. data/test/fixtures/nameless_ageless_youth.xml +2 -0
  76. data/test/fixtures/node_with_attr_name_conflicts.xml +1 -0
  77. data/test/fixtures/node_with_name_conflicts.xml +4 -0
  78. data/test/fixtures/numerology.xml +4 -0
  79. data/test/fixtures/person.xml +1 -0
  80. data/test/fixtures/person_with_guarded_mothers.xml +13 -0
  81. data/test/fixtures/person_with_mothers.xml +10 -0
  82. data/test/mocks/dictionaries.rb +57 -0
  83. data/test/mocks/mocks.rb +279 -0
  84. data/test/support/fixtures.rb +11 -0
  85. data/test/test_helper.rb +34 -0
  86. data/test/unit/definition_test.rb +235 -0
  87. data/test/unit/deprecations_test.rb +24 -0
  88. data/test/unit/to_xml_test.rb +81 -0
  89. data/test/unit/xml_attribute_test.rb +39 -0
  90. data/test/unit/xml_block_test.rb +81 -0
  91. data/test/unit/xml_bool_test.rb +122 -0
  92. data/test/unit/xml_convention_test.rb +150 -0
  93. data/test/unit/xml_hash_test.rb +115 -0
  94. data/test/unit/xml_initialize_test.rb +49 -0
  95. data/test/unit/xml_name_test.rb +141 -0
  96. data/test/unit/xml_namespace_test.rb +31 -0
  97. data/test/unit/xml_object_test.rb +207 -0
  98. data/test/unit/xml_required_test.rb +94 -0
  99. data/test/unit/xml_text_test.rb +71 -0
  100. data/website/index.html +98 -0
  101. metadata +254 -0
@@ -0,0 +1,11 @@
1
+ def fixture(name)
2
+ File.read(fixture_path(name))
3
+ end
4
+
5
+ def xml_fixture(name)
6
+ ROXML::XML::Parser.parse_file(fixture_path(name)).root
7
+ end
8
+
9
+ def fixture_path(name)
10
+ "test/fixtures/#{name}.xml"
11
+ end
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'active_support/test_case'
3
+ require 'test/mocks/mocks'
4
+ require 'test/mocks/dictionaries'
5
+ require 'test/support/fixtures'
6
+
7
+ def to_xml_test(*names)
8
+ names = names.first if names.size == 1 && names.first.is_a?(Hash)
9
+ names.each do |name, xml_name|
10
+ xml_name ||= name
11
+
12
+ define_method "test_#{name}" do
13
+ klass = name.is_a?(Symbol) ? name.to_s.camelize.constantize : name
14
+ xml = xml_name.is_a?(Symbol) ? xml_fixture(xml_name) : xml_name
15
+
16
+ dict = klass.from_xml(xml)
17
+ xml = remove_children(xml)
18
+ assert_equal xml.to_s, dict.to_xml.to_s
19
+ end
20
+ end
21
+ end
22
+
23
+ def remove_children(xml)
24
+ xml = ROXML::XML::Parser.parse(xml).root if xml.is_a?(String)
25
+ return unless xml.respond_to? :children
26
+ xml.children.each do |child|
27
+ if child.to_s.blank?
28
+ child.remove!
29
+ else
30
+ remove_children(child)
31
+ end
32
+ end
33
+ xml
34
+ end
@@ -0,0 +1,235 @@
1
+ require 'test/test_helper'
2
+
3
+ class TestDefinition < ActiveSupport::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_empty_array_means_as_array_for_text
12
+ opts = ROXML::Definition.new(:authors, :as => [])
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, :as => [], :from => :attr)
19
+ assert opts.array?
20
+ assert_equal :attr, opts.type
21
+ end
22
+
23
+ def test_block_shorthand_in_array_means_array
24
+ opts = ROXML::Definition.new(:intarray, :as => [Integer])
25
+ assert opts.array?
26
+ assert_equal :text, opts.type
27
+ assert 1, opts.blocks.size
28
+ end
29
+
30
+ def test_required
31
+ assert !ROXML::Definition.new(:author).required?
32
+ assert ROXML::Definition.new(:author, :required => true).required?
33
+ assert !ROXML::Definition.new(:author, :required => false).required?
34
+ end
35
+
36
+ def test_required_conflicts_with_else
37
+ assert_raise ArgumentError do
38
+ ROXML::Definition.new(:author, :required => true, :else => 'Johnny')
39
+ end
40
+ assert_nothing_raised do
41
+ ROXML::Definition.new(:author, :required => false, :else => 'Johnny')
42
+ end
43
+ end
44
+
45
+ def test_hash_of_attrs
46
+ opts = ROXML::Definition.new(:attributes, :as => {:key => '@name', :value => '@value'})
47
+ assert_hash(opts, :attr => 'name', :attr => 'value')
48
+ end
49
+
50
+ def test_hash_with_attr_key_and_text_val
51
+ opts = ROXML::Definition.new(:attributes, :as => {:key => '@name',
52
+ :value => :value})
53
+ assert_hash(opts, :attr => 'name', :text => 'value')
54
+ end
55
+
56
+ def test_hash_with_string_class_for_type
57
+ opts = ROXML::Definition.new(:attributes, :as => {:key => 'name',
58
+ :value => 'value'})
59
+ assert_hash(opts, :text => 'name', :text => 'value')
60
+ end
61
+
62
+ def test_hash_with_attr_key_and_content_val
63
+ opts = ROXML::Definition.new(:attributes, :as => {:key => '@name',
64
+ :value => :content})
65
+ assert_hash(opts, :attr => 'name', :text => '.')
66
+ end
67
+
68
+ def test_hash_with_options
69
+ opts = ROXML::Definition.new(:definitions, :as => {:key => '@dt', :value => '@dd'},
70
+ :in => :definitions, :from => 'definition')
71
+ assert_hash(opts, :attr => 'dt', :attr => 'dd')
72
+ assert_equal 'definition', opts.hash.wrapper
73
+ end
74
+
75
+ def test_no_block_shorthand_means_no_block
76
+ assert ROXML::Definition.new(:count).blocks.empty?
77
+ end
78
+
79
+ def test_block_integer_shorthand
80
+ assert_equal 3, ROXML::Definition.new(:count, :as => Integer).blocks.first['3']
81
+ end
82
+
83
+ def test_block_float_shorthand
84
+ assert_equal 3.1, ROXML::Definition.new(:count, :as => Float).blocks.first['3.1']
85
+ end
86
+
87
+ def test_from_attr_is_supported
88
+ opts = ROXML::Definition.new(:count, :from => :attr)
89
+ assert_equal "count", opts.name
90
+ assert_equal :attr, opts.type
91
+ end
92
+
93
+ def test_from_at_name_is_supported
94
+ opts = ROXML::Definition.new(:count, :from => "@COUNT")
95
+ assert_equal "COUNT", opts.name
96
+ assert_equal :attr, opts.type
97
+ end
98
+
99
+ def test_multiple_shorthands_raises
100
+ assert_raise ArgumentError do
101
+ assert_deprecated do
102
+ ROXML::Definition.new(:count, :as => [Float, Integer])
103
+ end
104
+ end
105
+ end
106
+
107
+ def test_stacked_blocks
108
+ assert_equal 2, ROXML::Definition.new(:count, :as => Integer) {|val| val.to_i }.blocks.size
109
+ assert_equal 2, ROXML::Definition.new(:count, :as => Float) {|val| val.object_id }.blocks.size
110
+ end
111
+
112
+ def test_block_shorthand_supports_bool
113
+ assert_equal true, ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("1")
114
+ assert_equal [true, false, nil], ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call(["TrUe", "0", "328"])
115
+ end
116
+
117
+ def test_block_shorthand_supports_integer
118
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(" ")
119
+ assert_equal 792, ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792")
120
+ assert_raise ArgumentError do
121
+ ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call("792.13")
122
+ end
123
+ assert_equal [792, 12, 328], ROXML::Definition.new(:floatvalue, :as => Integer).blocks.first.call(["792", "12", "328"])
124
+ end
125
+
126
+ def test_block_shorthand_supports_float
127
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(" ")
128
+ assert_equal 792.13, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("792.13")
129
+ assert_equal 240.0, ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call("240")
130
+ assert_equal [792.13, 240.0, 3.14], ROXML::Definition.new(:floatvalue, :as => Float).blocks.first.call(["792.13", "240", "3.14"])
131
+ end
132
+
133
+ def test_block_shorthand_supports_time
134
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Time).blocks.first.call(" ")
135
+ assert_equal 31, ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call("12:31am").min
136
+ assert_equal [31, 0, 59], ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call(["12:31am", "3:00pm", "11:59pm"]).map(&:min)
137
+ end
138
+
139
+ def test_block_shorthand_supports_date
140
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => Date).blocks.first.call(" ")
141
+ assert_equal "1970-09-03", ROXML::Definition.new(:datevalue, :as => Date).blocks.first.call("September 3rd, 1970").to_s
142
+ 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)
143
+ end
144
+
145
+ def test_block_shorthand_supports_datetime
146
+ assert_equal nil, ROXML::Definition.new(:floatvalue, :as => DateTime).blocks.first.call(" ")
147
+ 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
148
+ 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)
149
+ end
150
+
151
+ def test_name_explicit_indicates_whether_from_option_is_present
152
+ assert_equal true, ROXML::Definition.new(:element, :from => 'somewhere').name_explicit?
153
+ assert_equal false, ROXML::Definition.new(:element).name_explicit?
154
+ end
155
+
156
+ def test_xpath_in_is_formed_properly
157
+ opts = ROXML::Definition.new(:manufacturer, :in => './')
158
+ assert_equal "manufacturer", opts.name
159
+ assert_equal "./", opts.wrapper
160
+ end
161
+
162
+ def test_cdata_is_specifiable
163
+ assert ROXML::Definition.new(:manufacturer, :cdata => true).cdata?
164
+ end
165
+
166
+ def test_as_supports_generic_roxml_types
167
+ assert_equal RoxmlObject, ROXML::Definition.new(:type, :as => RoxmlObject).type
168
+ end
169
+
170
+ def test_as_supports_generic_roxml_types_in_arrays
171
+ assert_equal RoxmlObject, ROXML::Definition.new(:types, :as => [RoxmlObject]).type
172
+ end
173
+
174
+ def test_default_works
175
+ opts = ROXML::Definition.new(:missing, :else => true)
176
+ assert_equal true, opts.to_ref(RoxmlObject.new).value_in(ROXML::XML::Parser.parse('<xml></xml>'))
177
+ end
178
+
179
+ def test_default_works_for_arrays
180
+ opts = ROXML::Definition.new(:missing, :as => [])
181
+ assert_equal [], opts.to_ref(RoxmlObject.new).value_in(ROXML::XML::Parser.parse('<xml></xml>'))
182
+ end
183
+
184
+ def test_default_works_for_recursive_objects
185
+ opts = ROXML::Definition.new(:missing, :as => RecursiveObject, :else => false)
186
+ assert_equal false, opts.to_ref(RoxmlObject.new).value_in(ROXML::XML::Parser.parse('<xml></xml>'))
187
+ end
188
+
189
+ def test_content_is_accepted_as_from
190
+ assert ROXML::Definition.new(:author, :from => :content).content?
191
+ assert ROXML::Definition.new(:author, :from => '.').content?
192
+ end
193
+
194
+ def test_content_is_a_recognized_type
195
+ opts = ROXML::Definition.new(:author, :from => :content)
196
+ assert opts.content?
197
+ assert_equal '.', opts.name
198
+ assert_equal :text, opts.type
199
+ end
200
+
201
+ def test_content_symbol_as_target_is_translated_to_string
202
+ opts = ROXML::Definition.new(:content, :from => :attr)
203
+ assert_equal 'content', opts.name
204
+ assert_equal :attr, opts.type
205
+ end
206
+
207
+ def test_attr_is_accepted_as_from
208
+ assert_equal :attr, ROXML::Definition.new(:author, :from => :attr).type
209
+ assert_equal :attr, ROXML::Definition.new(:author, :from => '@author').type
210
+ end
211
+
212
+ def test_attr_is_a_recognized_type
213
+ opts = ROXML::Definition.new(:author, :from => :attr)
214
+ assert_equal 'author', opts.name
215
+ assert_equal :attr, opts.type
216
+ end
217
+ end
218
+
219
+ class RecursiveObject
220
+ include ROXML
221
+
222
+ xml_reader :next, :as => RecursiveObject, :else => true
223
+ end
224
+
225
+ class RoxmlObject
226
+ include ROXML
227
+ end
228
+
229
+ class HashDefinitionTest < ActiveSupport::TestCase
230
+ def test_content_detected_as_from
231
+ opts = ROXML::Definition.new(:hash, :as => {:key => :content, :value => :name})
232
+ assert_equal '.', opts.hash.key.name
233
+ assert_equal :text, opts.hash.key.type
234
+ end
235
+ end
@@ -0,0 +1,24 @@
1
+ require 'test/test_helper'
2
+
3
+ class TestDeprecation < ActiveSupport::TestCase
4
+ def test_as_array_not_deprecated
5
+ assert_not_deprecated do
6
+ opts = ROXML::Definition.new(:name, :as => [])
7
+ assert_equal :text, opts.type
8
+ assert opts.array?
9
+ end
10
+ end
11
+
12
+ def test_as_hash_not_deprecated
13
+ assert_not_deprecated do
14
+ opts = ROXML::Definition.new(:name, :as => {:key => '@dt', :value => '@dd'})
15
+ assert opts.hash?
16
+ end
17
+ end
18
+
19
+ def test_as_object_with_from_xml_not_deprecated
20
+ assert_not_deprecated do
21
+ ROXML::Definition.new(:name, :as => OctalInteger)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,81 @@
1
+ require 'test/test_helper'
2
+
3
+ class TestHashToXml < ActiveSupport::TestCase
4
+ to_xml_test :dictionary_of_attrs,
5
+ :dictionary_of_mixeds,
6
+ :dictionary_of_texts,
7
+ :dictionary_of_names,
8
+ :dictionary_of_guarded_names,
9
+ :dictionary_of_name_clashes,
10
+ :dictionary_of_attr_name_clashes
11
+ end
12
+
13
+ class TestOtherToXml < ActiveSupport::TestCase
14
+ to_xml_test :book => :book_valid,
15
+ :book_with_author_text_attribute => :book_text_with_attribute,
16
+ :uppercase_library => :library_uppercase
17
+
18
+ to_xml_test :book_with_authors,
19
+ :book_with_contributors,
20
+ :book_with_contributions,
21
+ :library,
22
+ :node_with_name_conflicts,
23
+ :node_with_attr_name_conflicts
24
+
25
+ to_xml_test :person_with_mother => :person_with_mothers,
26
+ :person_with_guarded_mother => :person_with_guarded_mothers
27
+
28
+ to_xml_test :book_with_wrapped_attr
29
+ end
30
+
31
+ class TestToXmlWithDefaults < ActiveSupport::TestCase
32
+ def test_content_and_attr_defaults_are_represented_in_output
33
+ dict = Person.from_xml(fixture(:nameless_ageless_youth))
34
+
35
+ xml = '<person age="21">Unknown</person>'
36
+ assert_equal ROXML::XML::Parser.parse(xml).root.to_s, dict.to_xml.to_s
37
+ end
38
+ end
39
+
40
+ class TestToXmlWithBlocks < ActiveSupport::TestCase
41
+ def test_pagecount_serialized_properly_after_modification
42
+ b = Book.from_xml(fixture(:book_valid))
43
+ xml = xml_fixture(:book_valid)
44
+ assert_equal '357', xml.search('pagecount').first.content
45
+ assert_equal 357, b.pages
46
+
47
+ b.pages = 500
48
+ doc = ROXML::XML::Document.new()
49
+ doc.root = b.to_xml
50
+ assert_equal '500', doc.search('pagecount').first.content
51
+ end
52
+ end
53
+
54
+ class OctalInteger
55
+ def self.from_xml(val)
56
+ new(Integer(val.content))
57
+ end
58
+
59
+ def initialize(value)
60
+ @val = value
61
+ end
62
+
63
+ def ==(other)
64
+ @val == other
65
+ end
66
+
67
+ def to_xml
68
+ sprintf("%#o", @val)
69
+ end
70
+ end
71
+
72
+ class BookWithOctalPages
73
+ include ROXML
74
+
75
+ xml_accessor :pages_with_to_xml_proc, :as => Integer, :to_xml => proc {|val| sprintf("%#o", val) }, :required => true
76
+ xml_accessor :pages_with_type, :as => OctalInteger, :required => true
77
+ end
78
+
79
+ class TestToXmlWithOverriddenOutput < ActiveSupport::TestCase
80
+ to_xml_test :book_with_octal_pages
81
+ end
@@ -0,0 +1,39 @@
1
+ require 'test/test_helper'
2
+
3
+ class TestXMLAttribute < ActiveSupport::TestCase
4
+ def test_attr_from
5
+ # :attr => *
6
+ book = Book.from_xml(fixture(:book_text_with_attribute))
7
+ assert_equal '0201710897', book.isbn
8
+
9
+ # :attr, :from => *
10
+ book = BookWithAttrFrom.from_xml(fixture(:book_text_with_attribute))
11
+ assert_equal '0201710897', book.isbn
12
+ end
13
+
14
+ def test_mutable_attr
15
+ book = Book.from_xml(fixture(:book_text_with_attribute))
16
+ assert book.respond_to?(:'isbn=')
17
+ end
18
+
19
+ def test_default_initialization
20
+ person = PersonWithMotherOrMissing.from_xml(fixture(:nameless_ageless_youth))
21
+ assert_equal 21, person.age
22
+ end
23
+
24
+ def test_recursive_with_default_initialization
25
+ p = PersonWithMotherOrMissing.from_xml(fixture(:person_with_mothers))
26
+ assert_equal 21, p.mother.mother.mother.age
27
+ end
28
+
29
+ def test_no_name_clashes
30
+ n = NodeWithAttrNameConflicts.from_xml(fixture(:node_with_attr_name_conflicts))
31
+ assert_equal "Just junk... really", n.content
32
+ assert_equal "Cartwheel", n.name
33
+ end
34
+
35
+ def test_wrapped_attr_accessible
36
+ b = BookWithWrappedAttr.from_xml(fixture(:book_with_wrapped_attr))
37
+ assert_equal "0974514055", b.isbn
38
+ end
39
+ end
@@ -0,0 +1,81 @@
1
+ require 'test/test_helper'
2
+
3
+ class ArrayWithBlockShorthand
4
+ include ROXML
5
+
6
+ xml_reader :array, :as => [Integer], :from => 'number'
7
+ end
8
+
9
+ class ArrayWithBlock
10
+ include ROXML
11
+
12
+ xml_reader :array, :as => [], :from => 'number' do |arr|
13
+ arr.map(&:to_i).reverse
14
+ end
15
+ end
16
+
17
+ class TestXMLBlocks < ActiveSupport::TestCase
18
+ def test_block_is_applied
19
+ muffins = Muffins.from_xml(fixture(:muffins))
20
+
21
+ assert muffins.count > 0
22
+ assert_equal 0, muffins.count % 13
23
+ end
24
+
25
+ def test_block_is_applied_to_hash
26
+ numerology = Numerology.from_xml(fixture(:numerology))
27
+
28
+ assert !numerology.predictions.keys.empty?
29
+ assert numerology.predictions.keys.all? {|k| k.is_a? Integer }
30
+ assert numerology.predictions.values.all? {|k| k.is_a? String }
31
+ end
32
+
33
+ def test_stacked_blocks_are_applied
34
+ muffins = MuffinsWithStackedBlocks.from_xml(fixture(:muffins))
35
+
36
+ assert muffins.count > 0
37
+ assert_equal 0, muffins.count % 13
38
+ end
39
+
40
+ def test_block_shorthand_applied_properly_to_array
41
+ obj = ArrayWithBlockShorthand.from_xml(%{
42
+ <array_with_block_shorthand>
43
+ <number>1</number>
44
+ <number>2</number>
45
+ <number>3</number>
46
+ </array_with_block_shorthand>
47
+ })
48
+
49
+ assert_equal [1, 2, 3], obj.array
50
+ end
51
+
52
+ def test_block_applied_properly_to_array
53
+ obj = ArrayWithBlock.from_xml(%{
54
+ <array_with_block>
55
+ <number>1</number>
56
+ <number>2</number>
57
+ <number>3</number>
58
+ </array_with_block>
59
+ })
60
+
61
+ assert_equal [3, 2, 1], obj.array
62
+ end
63
+
64
+ def test_block_shorthand_applied_properly_to_empty_array
65
+ obj = ArrayWithBlockShorthand.from_xml(%{
66
+ <array_with_block_shorthand>
67
+ </array_with_block_shorthand>
68
+ })
69
+
70
+ assert_equal [], obj.array
71
+ end
72
+
73
+ def test_block_applied_properly_to_empty_array
74
+ obj = ArrayWithBlock.from_xml(%{
75
+ <array_with_block>
76
+ </array_with_block>
77
+ })
78
+
79
+ assert_equal [], obj.array
80
+ end
81
+ end