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.
- data/.gitignore +6 -0
- data/.gitmodules +3 -0
- data/History.txt +299 -0
- data/MIT-LICENSE +18 -0
- data/README.rdoc +161 -0
- data/Rakefile +95 -0
- data/TODO +39 -0
- data/VERSION +1 -0
- data/config/website.yml +2 -0
- data/examples/amazon.rb +35 -0
- data/examples/current_weather.rb +27 -0
- data/examples/dashed_elements.rb +20 -0
- data/examples/library.rb +40 -0
- data/examples/posts.rb +27 -0
- data/examples/rails.rb +70 -0
- data/examples/twitter.rb +37 -0
- data/examples/xml/active_record.xml +70 -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 +547 -0
- data/lib/roxml/definition.rb +236 -0
- data/lib/roxml/hash_definition.rb +25 -0
- data/lib/roxml/xml.rb +43 -0
- data/lib/roxml/xml/parsers/libxml.rb +91 -0
- data/lib/roxml/xml/parsers/nokogiri.rb +77 -0
- data/lib/roxml/xml/references.rb +297 -0
- data/roxml.gemspec +201 -0
- data/spec/definition_spec.rb +486 -0
- data/spec/examples/active_record_spec.rb +40 -0
- data/spec/examples/amazon_spec.rb +54 -0
- data/spec/examples/current_weather_spec.rb +37 -0
- data/spec/examples/dashed_elements_spec.rb +20 -0
- data/spec/examples/library_spec.rb +46 -0
- data/spec/examples/post_spec.rb +24 -0
- data/spec/examples/twitter_spec.rb +32 -0
- data/spec/roxml_spec.rb +372 -0
- data/spec/shared_specs.rb +15 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/libxml.rb +3 -0
- data/spec/support/nokogiri.rb +3 -0
- data/spec/xml/attributes_spec.rb +36 -0
- data/spec/xml/namespace_spec.rb +240 -0
- data/spec/xml/namespaces_spec.rb +32 -0
- data/spec/xml/parser_spec.rb +26 -0
- data/tasks/rdoc.rake +13 -0
- data/tasks/rspec.rake +25 -0
- data/tasks/test.rake +35 -0
- data/test/fixtures/book_malformed.xml +5 -0
- data/test/fixtures/book_pair.xml +8 -0
- data/test/fixtures/book_text_with_attribute.xml +5 -0
- data/test/fixtures/book_valid.xml +5 -0
- data/test/fixtures/book_with_authors.xml +7 -0
- data/test/fixtures/book_with_contributions.xml +9 -0
- data/test/fixtures/book_with_contributors.xml +7 -0
- data/test/fixtures/book_with_contributors_attrs.xml +7 -0
- data/test/fixtures/book_with_default_namespace.xml +9 -0
- data/test/fixtures/book_with_depth.xml +6 -0
- data/test/fixtures/book_with_octal_pages.xml +4 -0
- data/test/fixtures/book_with_publisher.xml +7 -0
- data/test/fixtures/book_with_wrapped_attr.xml +3 -0
- data/test/fixtures/dictionary_of_attr_name_clashes.xml +8 -0
- data/test/fixtures/dictionary_of_attrs.xml +6 -0
- data/test/fixtures/dictionary_of_guarded_names.xml +6 -0
- data/test/fixtures/dictionary_of_mixeds.xml +4 -0
- data/test/fixtures/dictionary_of_name_clashes.xml +10 -0
- data/test/fixtures/dictionary_of_names.xml +4 -0
- data/test/fixtures/dictionary_of_texts.xml +10 -0
- data/test/fixtures/library.xml +30 -0
- data/test/fixtures/library_uppercase.xml +30 -0
- data/test/fixtures/muffins.xml +3 -0
- data/test/fixtures/nameless_ageless_youth.xml +2 -0
- data/test/fixtures/node_with_attr_name_conflicts.xml +1 -0
- data/test/fixtures/node_with_name_conflicts.xml +4 -0
- data/test/fixtures/numerology.xml +4 -0
- data/test/fixtures/person.xml +1 -0
- data/test/fixtures/person_with_guarded_mothers.xml +13 -0
- data/test/fixtures/person_with_mothers.xml +10 -0
- data/test/mocks/dictionaries.rb +57 -0
- data/test/mocks/mocks.rb +279 -0
- data/test/support/fixtures.rb +11 -0
- data/test/test_helper.rb +34 -0
- data/test/unit/definition_test.rb +235 -0
- data/test/unit/deprecations_test.rb +24 -0
- data/test/unit/to_xml_test.rb +81 -0
- data/test/unit/xml_attribute_test.rb +39 -0
- data/test/unit/xml_block_test.rb +81 -0
- data/test/unit/xml_bool_test.rb +122 -0
- data/test/unit/xml_convention_test.rb +150 -0
- data/test/unit/xml_hash_test.rb +115 -0
- data/test/unit/xml_initialize_test.rb +49 -0
- data/test/unit/xml_name_test.rb +141 -0
- data/test/unit/xml_namespace_test.rb +31 -0
- data/test/unit/xml_object_test.rb +207 -0
- data/test/unit/xml_required_test.rb +94 -0
- data/test/unit/xml_text_test.rb +71 -0
- data/website/index.html +98 -0
- metadata +254 -0
data/test/test_helper.rb
ADDED
@@ -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
|