yob-roxml 3.1.6
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 +7 -0
- data/.gitmodules +3 -0
- data/History.txt +354 -0
- data/LICENSE +20 -0
- data/README.rdoc +195 -0
- data/Rakefile +117 -0
- data/TODO +37 -0
- data/VERSION +1 -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 +556 -0
- data/lib/roxml/definition.rb +238 -0
- data/lib/roxml/hash_definition.rb +25 -0
- data/lib/roxml/xml.rb +40 -0
- data/lib/roxml/xml/parsers/libxml.rb +85 -0
- data/lib/roxml/xml/parsers/nokogiri.rb +82 -0
- data/lib/roxml/xml/references.rb +322 -0
- data/roxml.gemspec +206 -0
- data/spec/definition_spec.rb +494 -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/array_spec.rb +36 -0
- data/spec/xml/attributes_spec.rb +71 -0
- data/spec/xml/encoding_spec.rb +52 -0
- data/spec/xml/namespace_spec.rb +270 -0
- data/spec/xml/namespaces_spec.rb +67 -0
- data/spec/xml/object_spec.rb +82 -0
- data/spec/xml/parser_spec.rb +21 -0
- data/spec/xml/text_spec.rb +71 -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/load_test.rb +6 -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 +205 -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 +300 -0
@@ -0,0 +1 @@
|
|
1
|
+
<node content="Just junk... really" name="Cartwheel" />
|
@@ -0,0 +1 @@
|
|
1
|
+
<person>Ben Franklin</person>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<person>
|
2
|
+
<name>Ben "Benji" Franklin</name>
|
3
|
+
<mother>
|
4
|
+
<person>
|
5
|
+
<name>Abiah 'Abby' Folger</name>
|
6
|
+
<mother>
|
7
|
+
<person>
|
8
|
+
<name>Madeup Mother < the third ></name>
|
9
|
+
</person>
|
10
|
+
</mother>
|
11
|
+
</person>
|
12
|
+
</mother>
|
13
|
+
</person>
|
data/test/load_test.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'lib/roxml'
|
2
|
+
|
3
|
+
class DictionaryOfAttrs
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_name :dictionary
|
7
|
+
xml_reader :definitions, :as => {:key => '@dt',
|
8
|
+
:value => '@dd'}, :in => :definitions
|
9
|
+
end
|
10
|
+
|
11
|
+
class DictionaryOfTexts
|
12
|
+
include ROXML
|
13
|
+
|
14
|
+
xml_name :dictionary
|
15
|
+
xml_reader :definitions, :as => {:key => :word,
|
16
|
+
:value => :meaning}
|
17
|
+
end
|
18
|
+
|
19
|
+
class DictionaryOfMixeds
|
20
|
+
include ROXML
|
21
|
+
|
22
|
+
xml_name :dictionary
|
23
|
+
xml_reader :definitions, :as => {:key => '@word',
|
24
|
+
:value => :content}
|
25
|
+
end
|
26
|
+
|
27
|
+
class DictionaryOfNames
|
28
|
+
include ROXML
|
29
|
+
|
30
|
+
xml_name :dictionary
|
31
|
+
xml_reader :definitions, :as => {:key => :name,
|
32
|
+
:value => :content}
|
33
|
+
end
|
34
|
+
|
35
|
+
class DictionaryOfGuardedNames
|
36
|
+
include ROXML
|
37
|
+
|
38
|
+
xml_name :dictionary
|
39
|
+
xml_reader :definitions, :as => {:key => :name,
|
40
|
+
:value => :content}, :in => :definitions
|
41
|
+
end
|
42
|
+
|
43
|
+
class DictionaryOfNameClashes
|
44
|
+
include ROXML
|
45
|
+
|
46
|
+
xml_name :dictionary
|
47
|
+
xml_reader :definitions, :as => {:key => 'name',
|
48
|
+
:value => 'content'}, :from => :definition
|
49
|
+
end
|
50
|
+
|
51
|
+
class DictionaryOfAttrNameClashes
|
52
|
+
include ROXML
|
53
|
+
|
54
|
+
xml_name :dictionary
|
55
|
+
xml_reader :definitions, :as => {:key => '@name',
|
56
|
+
:value => 'content'}, :from => :definition
|
57
|
+
end
|
data/test/mocks/mocks.rb
ADDED
@@ -0,0 +1,279 @@
|
|
1
|
+
require "lib/roxml"
|
2
|
+
|
3
|
+
class Muffins
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_reader(:count, :from => 'bakers_dozens') {|val| val.to_i * 13 }
|
7
|
+
end
|
8
|
+
|
9
|
+
class MuffinsWithStackedBlocks
|
10
|
+
include ROXML
|
11
|
+
|
12
|
+
xml_reader(:count, :from => 'bakers_dozens', :as => Integer) {|val| val * 13 }
|
13
|
+
end
|
14
|
+
|
15
|
+
class Numerology
|
16
|
+
include ROXML
|
17
|
+
|
18
|
+
xml_reader :predictions, :as => {:key => '@number', :value => '@meaning'} do |k, v|
|
19
|
+
[Integer(k), v]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Contributor
|
24
|
+
include ROXML
|
25
|
+
|
26
|
+
xml_reader :role, :from => :attr
|
27
|
+
xml_reader :name
|
28
|
+
end
|
29
|
+
|
30
|
+
class WriteableContributor
|
31
|
+
include ROXML
|
32
|
+
|
33
|
+
xml_accessor :role, :from => :attr
|
34
|
+
xml_accessor :name
|
35
|
+
end
|
36
|
+
|
37
|
+
class Book
|
38
|
+
include ROXML
|
39
|
+
|
40
|
+
xml_accessor :isbn, :from => '@ISBN'
|
41
|
+
xml_reader :title
|
42
|
+
xml_reader :description, :cdata => true
|
43
|
+
xml_reader :author
|
44
|
+
xml_accessor :pages, :from => 'pagecount', :as => Integer
|
45
|
+
end
|
46
|
+
|
47
|
+
class BookWithRequired
|
48
|
+
include ROXML
|
49
|
+
|
50
|
+
xml_accessor :isbn, :from => '@ISBN', :required => true
|
51
|
+
xml_reader :title, :required => true
|
52
|
+
xml_reader :contributors, :as => [Contributor], :in => 'contributor_array', :required => true
|
53
|
+
xml_reader :contributor_hash, :as => {:key => '@role', :value => '@name'},
|
54
|
+
:from => 'contributor', :in => 'contributor_hash', :required => true
|
55
|
+
end
|
56
|
+
|
57
|
+
class BookWithAttrFrom
|
58
|
+
include ROXML
|
59
|
+
|
60
|
+
xml_accessor :isbn, :from => '@ISBN'
|
61
|
+
end
|
62
|
+
|
63
|
+
class BookWithWrappedAttr
|
64
|
+
include ROXML
|
65
|
+
|
66
|
+
xml_name :book
|
67
|
+
xml_accessor :isbn, :from => '@ISBN', :in => 'ids'
|
68
|
+
end
|
69
|
+
|
70
|
+
class Measurement
|
71
|
+
include ROXML
|
72
|
+
|
73
|
+
xml_reader :units, :from => :attr
|
74
|
+
xml_reader :value, :from => :content, :as => Float
|
75
|
+
|
76
|
+
def initialize(value = 0, units = 'pixels')
|
77
|
+
@value = Float(value)
|
78
|
+
@units = units.to_s
|
79
|
+
normalize_hundredths
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_s
|
83
|
+
"#{value} #{units}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def ==(other)
|
87
|
+
other.units == @units && other.value == @value
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def after_parse
|
92
|
+
normalize_hundredths
|
93
|
+
end
|
94
|
+
|
95
|
+
def normalize_hundredths
|
96
|
+
if @units.starts_with? 'hundredths-'
|
97
|
+
@value /= 100
|
98
|
+
@units = @units.split('hundredths-')[1]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class BookWithDepth
|
104
|
+
include ROXML
|
105
|
+
|
106
|
+
xml_reader :isbn, :from => '@ISBN'
|
107
|
+
xml_reader :title
|
108
|
+
xml_reader :description, :cdata => true
|
109
|
+
xml_reader :author
|
110
|
+
xml_reader :depth, :as => Measurement
|
111
|
+
end
|
112
|
+
|
113
|
+
class Author
|
114
|
+
include ROXML
|
115
|
+
|
116
|
+
xml_reader :role, :from => :attr
|
117
|
+
xml_reader :text, :from => :content
|
118
|
+
end
|
119
|
+
|
120
|
+
class BookWithAuthors
|
121
|
+
include ROXML
|
122
|
+
|
123
|
+
xml_name :book
|
124
|
+
xml_reader :isbn, :from => '@ISBN'
|
125
|
+
xml_reader :title
|
126
|
+
xml_reader :description, :cdata => true
|
127
|
+
xml_reader :authors, :as => []
|
128
|
+
end
|
129
|
+
|
130
|
+
class BookWithAuthorTextAttribute
|
131
|
+
include ROXML
|
132
|
+
|
133
|
+
xml_name :book
|
134
|
+
xml_reader :isbn, :from => '@ISBN'
|
135
|
+
xml_reader :title
|
136
|
+
xml_reader :description, :cdata => true
|
137
|
+
xml_reader :author, :as => Author
|
138
|
+
end
|
139
|
+
|
140
|
+
class BookWithContributions
|
141
|
+
include ROXML
|
142
|
+
|
143
|
+
xml_name :book
|
144
|
+
xml_reader :isbn, :from => :attr
|
145
|
+
xml_reader :title
|
146
|
+
xml_reader :description
|
147
|
+
xml_reader :contributions, :as => [Contributor], :from => 'contributor', :in => "contributions"
|
148
|
+
end
|
149
|
+
|
150
|
+
class BookWithContributors
|
151
|
+
include ROXML
|
152
|
+
|
153
|
+
xml_name :book
|
154
|
+
xml_reader :isbn, :from => :attr
|
155
|
+
xml_reader :title
|
156
|
+
xml_reader :description
|
157
|
+
xml_reader :contributors, :as => [Contributor]
|
158
|
+
end
|
159
|
+
|
160
|
+
class WriteableBookWithContributors
|
161
|
+
include ROXML
|
162
|
+
|
163
|
+
xml_name :book
|
164
|
+
xml_accessor :isbn, :from => :attr
|
165
|
+
xml_accessor :title
|
166
|
+
xml_accessor :description
|
167
|
+
xml_accessor :contributors, :as => [Contributor]
|
168
|
+
end
|
169
|
+
|
170
|
+
class NamelessBook
|
171
|
+
include ROXML
|
172
|
+
|
173
|
+
xml_reader :isbn, :from => :attr
|
174
|
+
xml_reader :title
|
175
|
+
xml_reader :description
|
176
|
+
xml_reader :contributors, :as => [Contributor]
|
177
|
+
end
|
178
|
+
|
179
|
+
class Publisher
|
180
|
+
include ROXML
|
181
|
+
|
182
|
+
xml_reader :name
|
183
|
+
end
|
184
|
+
|
185
|
+
class BookWithPublisher
|
186
|
+
include ROXML
|
187
|
+
|
188
|
+
xml_reader :book
|
189
|
+
xml_reader :isbn, :from => :attr
|
190
|
+
xml_reader :title
|
191
|
+
xml_reader :description
|
192
|
+
xml_reader :publisher, :as => Publisher
|
193
|
+
end
|
194
|
+
|
195
|
+
class BookPair
|
196
|
+
include ROXML
|
197
|
+
|
198
|
+
xml_reader :isbn, :from => :attr
|
199
|
+
xml_reader :title
|
200
|
+
xml_reader :description
|
201
|
+
xml_reader :author
|
202
|
+
xml_reader :book, :as => Book
|
203
|
+
end
|
204
|
+
|
205
|
+
class Library
|
206
|
+
include ROXML
|
207
|
+
|
208
|
+
xml_reader :name
|
209
|
+
xml_reader :books, :as => [BookWithContributions]
|
210
|
+
end
|
211
|
+
|
212
|
+
class UppercaseLibrary
|
213
|
+
include ROXML
|
214
|
+
|
215
|
+
xml_name :library
|
216
|
+
xml_reader :name, :from => 'NAME'
|
217
|
+
xml_reader :books, :as => [BookWithContributions], :from => 'BOOK'
|
218
|
+
end
|
219
|
+
|
220
|
+
class LibraryWithBooksOfUnderivableName
|
221
|
+
include ROXML
|
222
|
+
|
223
|
+
xml_accessor :name
|
224
|
+
xml_reader :novels, :as => [NamelessBook]
|
225
|
+
end
|
226
|
+
|
227
|
+
class NodeWithNameConflicts
|
228
|
+
include ROXML
|
229
|
+
|
230
|
+
xml_name :node
|
231
|
+
xml_reader :content
|
232
|
+
xml_reader :name
|
233
|
+
end
|
234
|
+
|
235
|
+
class NodeWithAttrNameConflicts
|
236
|
+
include ROXML
|
237
|
+
|
238
|
+
xml_name :node
|
239
|
+
xml_reader :content, :from => '@content'
|
240
|
+
xml_reader :name, :from => '@name'
|
241
|
+
end
|
242
|
+
|
243
|
+
class Person
|
244
|
+
include ROXML
|
245
|
+
|
246
|
+
xml_accessor :age, :from => :attr, :else => 21
|
247
|
+
xml_accessor :name, :from => :content, :else => 'Unknown'
|
248
|
+
|
249
|
+
def self.blank
|
250
|
+
new.tap do |instance|
|
251
|
+
instance.age = 21
|
252
|
+
instance.name = 'Unknown'
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
class PersonWithMother
|
258
|
+
include ROXML
|
259
|
+
|
260
|
+
xml_name :person
|
261
|
+
xml_reader :name
|
262
|
+
xml_reader :mother, :as => PersonWithMother, :from => 'mother'
|
263
|
+
end
|
264
|
+
|
265
|
+
class PersonWithGuardedMother
|
266
|
+
include ROXML
|
267
|
+
|
268
|
+
xml_name :person
|
269
|
+
xml_reader :name
|
270
|
+
xml_reader :mother, :as => PersonWithGuardedMother, :from => :person, :in => :mother
|
271
|
+
end
|
272
|
+
|
273
|
+
class PersonWithMotherOrMissing
|
274
|
+
include ROXML
|
275
|
+
|
276
|
+
xml_reader :age, :from => :attr, :else => 21
|
277
|
+
xml_reader :name, :else => 'Anonymous'
|
278
|
+
xml_reader :mother,:as => PersonWithMotherOrMissing, :else => Person.blank
|
279
|
+
end
|
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.parse_string(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
|
+
defined?(Nokogiri) ? child.remove : 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.sought_type => opts.hash.key.name,
|
8
|
+
opts.hash.value.sought_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.sought_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.sought_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.sought_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.sought_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.sought_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).sought_type
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_as_supports_generic_roxml_types_in_arrays
|
171
|
+
assert_equal RoxmlObject, ROXML::Definition.new(:types, :as => [RoxmlObject]).sought_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.parse_string('<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.parse_string('<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.parse_string('<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.sought_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.sought_type
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_attr_is_accepted_as_from
|
208
|
+
assert_equal :attr, ROXML::Definition.new(:author, :from => :attr).sought_type
|
209
|
+
assert_equal :attr, ROXML::Definition.new(:author, :from => '@author').sought_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.sought_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.sought_type
|
234
|
+
end
|
235
|
+
end
|