Empact-roxml 2.3.1 → 2.4.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/History.txt +145 -0
- data/Manifest.txt +81 -0
- data/Rakefile +85 -95
- data/TODO +42 -0
- data/html/index.html +278 -0
- data/html/style.css +79 -0
- data/lib/roxml.rb +113 -49
- data/lib/roxml/extensions/active_support.rb +37 -12
- data/lib/roxml/extensions/array/conversions.rb +12 -2
- data/lib/roxml/extensions/deprecation.rb +4 -4
- data/lib/roxml/options.rb +39 -30
- data/lib/roxml/xml.rb +119 -55
- data/lib/roxml/xml/rexml.rb +2 -2
- data/roxml.gemspec +40 -101
- data/test/bugs/rexml_bugs.rb +15 -0
- data/test/fixtures/book_with_octal_pages.xml +4 -0
- data/test/mocks/mocks.rb +0 -4
- data/test/test_helper.rb +29 -0
- data/test/unit/array_test.rb +16 -0
- data/test/unit/freeze_test.rb +71 -0
- data/test/unit/inheritance_test.rb +26 -3
- data/test/unit/options_test.rb +20 -19
- data/test/unit/overriden_output_test.rb +33 -0
- data/test/unit/roxml_test.rb +7 -0
- data/test/unit/to_xml_test.rb +0 -25
- data/test/unit/xml_bool_test.rb +51 -45
- data/test/unit/xml_convention_test.rb +150 -0
- data/test/unit/xml_hash_test.rb +41 -0
- data/test/unit/xml_name_test.rb +29 -6
- data/test/unit/xml_object_test.rb +30 -0
- metadata +69 -32
data/test/unit/roxml_test.rb
CHANGED
data/test/unit/to_xml_test.rb
CHANGED
@@ -1,30 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
|
-
def to_xml_test(*names)
|
4
|
-
names = names.only if names.one? && names.only.is_a?(Hash)
|
5
|
-
names.each do |(name, xml_name)|
|
6
|
-
xml_name ||= name
|
7
|
-
|
8
|
-
define_method "test_#{name}" do
|
9
|
-
dict = name.to_s.camelize.constantize.from_xml(fixture(xml_name))
|
10
|
-
xml = xml_fixture(xml_name)
|
11
|
-
remove_children(xml)
|
12
|
-
assert_equal xml, dict.to_xml
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def remove_children(xml)
|
18
|
-
return unless xml.respond_to? :children
|
19
|
-
xml.children.each do |child|
|
20
|
-
if child.blank?
|
21
|
-
child.remove!
|
22
|
-
else
|
23
|
-
remove_children(child)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
3
|
class TestHashToXml < Test::Unit::TestCase
|
29
4
|
to_xml_test :dictionary_of_attrs,
|
30
5
|
:dictionary_of_mixeds,
|
data/test/unit/xml_bool_test.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
|
+
PROC_TRUE = proc {|val| val ? 'TRUE' : 'FALSE'}
|
4
|
+
PROC_True = proc {|val| val ? 'True' : 'False'}
|
5
|
+
PROC_true = proc {|val| val.to_s}
|
6
|
+
PROC_1 = proc {|val| val ? 1 : 0}
|
7
|
+
|
3
8
|
class XmlBool
|
4
9
|
include ROXML
|
5
10
|
|
6
|
-
|
7
|
-
xml_reader :
|
8
|
-
xml_reader :
|
9
|
-
xml_reader :
|
10
|
-
xml_reader :
|
11
|
-
xml_reader :
|
12
|
-
xml_reader :
|
13
|
-
xml_reader :
|
11
|
+
xml_name 'xml_bool'
|
12
|
+
xml_reader :true_from_TRUE?, :to_xml => PROC_TRUE
|
13
|
+
xml_reader :false_from_FALSE?, :text => 'text_for_FALSE', :to_xml => PROC_TRUE
|
14
|
+
xml_reader :true_from_one?, :attr => 'attr_for_one', :to_xml => PROC_1
|
15
|
+
xml_reader :false_from_zero?, :text => 'text_for_zero', :in => 'container', :to_xml => PROC_1
|
16
|
+
xml_reader :true_from_True?, :attr => 'attr_for_True', :in => 'container', :to_xml => PROC_True
|
17
|
+
xml_reader :false_from_False?, :text => 'false_from_cdata_False', :as => :cdata, :to_xml => PROC_True
|
18
|
+
xml_reader :true_from_true?, :to_xml => PROC_true
|
19
|
+
xml_reader :false_from_false?, :to_xml => PROC_true
|
14
20
|
xml_reader :missing?
|
15
21
|
end
|
16
22
|
|
@@ -34,39 +40,37 @@ class XmlBoolUnexpectedWithBlock
|
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
<unexpected>Unexpected Value</unexpected>
|
64
|
-
</xml_bool_unexpected>
|
65
|
-
}
|
66
|
-
end
|
43
|
+
BOOL_XML = %{
|
44
|
+
<xml_bool attr_for_one="1">
|
45
|
+
<true_from_TRUE>TRUE</true_from_TRUE>
|
46
|
+
<text_for_FALSE>FALSE</text_for_FALSE>
|
47
|
+
<container attr_for_True="True">
|
48
|
+
<text_for_zero>0</text_for_zero>
|
49
|
+
</container>
|
50
|
+
<false_from_cdata_False><![CDATA[False]]></false_from_cdata_False>
|
51
|
+
<true_from_true>true</true_from_true>
|
52
|
+
<false_from_false>false</false_from_false>
|
53
|
+
</xml_bool>
|
54
|
+
}
|
55
|
+
PRESENT = %{
|
56
|
+
<xml_bool_required>
|
57
|
+
<required>true</required>
|
58
|
+
</xml_bool_required>
|
59
|
+
}
|
60
|
+
ABSENT = %{
|
61
|
+
<xml_bool_required>
|
62
|
+
</xml_bool_required>
|
63
|
+
}
|
64
|
+
UNEXPECTED_VALUE_XML = %{
|
65
|
+
<xml_bool_unexpected>
|
66
|
+
<unexpected>Unexpected Value</unexpected>
|
67
|
+
</xml_bool_unexpected>
|
68
|
+
}
|
67
69
|
|
70
|
+
|
71
|
+
class TestXMLBool < Test::Unit::TestCase
|
68
72
|
def test_bool_results_for_various_inputs
|
69
|
-
x = XmlBool.from_xml(
|
73
|
+
x = XmlBool.from_xml(BOOL_XML)
|
70
74
|
assert_equal true, x.true_from_TRUE?
|
71
75
|
assert_equal false, x.false_from_FALSE?
|
72
76
|
assert_equal true, x.true_from_one?
|
@@ -78,27 +82,29 @@ class TestXMLBool < Test::Unit::TestCase
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def test_missing_results_in_nil
|
81
|
-
x = XmlBool.from_xml(
|
85
|
+
x = XmlBool.from_xml(BOOL_XML)
|
82
86
|
assert_equal nil, x.missing?
|
83
87
|
end
|
84
88
|
|
85
89
|
def test_unexpected_value_results_in_nil
|
86
|
-
x = XmlBoolUnexpected.from_xml(
|
90
|
+
x = XmlBoolUnexpected.from_xml(UNEXPECTED_VALUE_XML)
|
87
91
|
assert_equal nil, x.unexpected?
|
88
92
|
end
|
89
93
|
|
90
94
|
def test_block_recieves_unexpected_value_rather_than_nil
|
91
|
-
x = XmlBoolUnexpectedWithBlock.from_xml(
|
95
|
+
x = XmlBoolUnexpectedWithBlock.from_xml(UNEXPECTED_VALUE_XML)
|
92
96
|
assert_equal "Unexpected Value", x.unexpected?
|
93
97
|
end
|
94
98
|
|
95
99
|
def test_required_raises_on_missing
|
96
100
|
assert_nothing_raised do
|
97
|
-
XmlBoolRequired.from_xml(
|
101
|
+
XmlBoolRequired.from_xml(PRESENT)
|
98
102
|
end
|
99
103
|
|
100
|
-
|
101
|
-
XmlBoolRequired.from_xml(
|
104
|
+
assert_raise ROXML::RequiredElementMissing do
|
105
|
+
XmlBoolRequired.from_xml(ABSENT)
|
102
106
|
end
|
103
107
|
end
|
108
|
+
|
109
|
+
to_xml_test XmlBool => BOOL_XML
|
104
110
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
|
+
|
3
|
+
XML_CAMELLOWER = %{
|
4
|
+
<bookCase name="Jonas' Books">
|
5
|
+
<bookCount>12</bookCount>
|
6
|
+
<bigBooks>
|
7
|
+
<bigBook>GED</bigBook>
|
8
|
+
<bigBook>House of Leaves</bigBook>
|
9
|
+
</bigBooks>
|
10
|
+
</bookCase>
|
11
|
+
}
|
12
|
+
|
13
|
+
XML_CAMELCASE = %{
|
14
|
+
<BookCase Name="Jonas' Books">
|
15
|
+
<BookCount>12</BookCount>
|
16
|
+
<BigBooks>
|
17
|
+
<BigBook>GED</BigBook>
|
18
|
+
<BigBook>House of Leaves</BigBook>
|
19
|
+
</BigBooks>
|
20
|
+
</BookCase>
|
21
|
+
}
|
22
|
+
|
23
|
+
XML_UNDERSCORE = %{
|
24
|
+
<book_case name="Jonas' Books">
|
25
|
+
<book_count>12</book_count>
|
26
|
+
<big_books>
|
27
|
+
<big_book>GED</big_book>
|
28
|
+
<big_book>House of Leaves</big_book>
|
29
|
+
</big_books>
|
30
|
+
</book_case>
|
31
|
+
}
|
32
|
+
|
33
|
+
XML_DASHES = %{
|
34
|
+
<book-case name="Jonas' Books">
|
35
|
+
<book-count>12</book-count>
|
36
|
+
<big-books>
|
37
|
+
<big-book>GED</big-book>
|
38
|
+
<big-book>House of Leaves</big-book>
|
39
|
+
</big-books>
|
40
|
+
</book-case>
|
41
|
+
}
|
42
|
+
|
43
|
+
XML_UPCASE = %{
|
44
|
+
<BOOKCASE NAME="Jonas' Books">
|
45
|
+
<BOOKCOUNT>12</BOOKCOUNT>
|
46
|
+
<BIGBOOKS>
|
47
|
+
<BIGBOOK>GED</BIGBOOK>
|
48
|
+
<BIGBOOK>House of Leaves</BIGBOOK>
|
49
|
+
</BIGBOOKS>
|
50
|
+
</BOOKCASE>
|
51
|
+
}
|
52
|
+
|
53
|
+
class BookCase
|
54
|
+
include ROXML
|
55
|
+
|
56
|
+
xml_reader :book_count, :as => Integer, :required => true
|
57
|
+
xml_reader :big_books, [:text], :required => true
|
58
|
+
end
|
59
|
+
|
60
|
+
class BookCaseCamelCase < BookCase
|
61
|
+
xml_convention :camelcase
|
62
|
+
end
|
63
|
+
|
64
|
+
class BookCaseUnderScore < BookCase
|
65
|
+
xml_convention :underscore
|
66
|
+
end
|
67
|
+
|
68
|
+
class BookCaseDashes < BookCase
|
69
|
+
xml_convention &:dasherize
|
70
|
+
end
|
71
|
+
|
72
|
+
class BookCaseCamelLower < BookCase
|
73
|
+
xml_convention {|val| val.camelcase(:lower) }
|
74
|
+
end
|
75
|
+
|
76
|
+
class BookCaseUpCase < BookCase
|
77
|
+
xml_convention {|val| val.gsub('_', '').upcase }
|
78
|
+
end
|
79
|
+
|
80
|
+
class InheritedBookCaseCamelCase < BookCaseCamelCase
|
81
|
+
end
|
82
|
+
|
83
|
+
class InheritedBookCaseUpCase < BookCaseUpCase
|
84
|
+
end
|
85
|
+
|
86
|
+
# Same as BookCase. Needed to keep BookCase clean for other tests
|
87
|
+
class ParentBookCaseDefault
|
88
|
+
include ROXML
|
89
|
+
|
90
|
+
xml_reader :book_count, :as => Integer, :required => true
|
91
|
+
xml_reader :big_books, [:text], :required => true
|
92
|
+
end
|
93
|
+
|
94
|
+
class InheritedBookCaseDefault < ParentBookCaseDefault
|
95
|
+
end
|
96
|
+
|
97
|
+
class TestXMLConstruct < Test::Unit::TestCase
|
98
|
+
# TODO: Test convention applies to xml_name as well...
|
99
|
+
|
100
|
+
def test_default_convention_is_underscore
|
101
|
+
bc = BookCase.from_xml(XML_UNDERSCORE)
|
102
|
+
assert_has_book_case_info(bc)
|
103
|
+
end
|
104
|
+
|
105
|
+
[BookCaseUpCase, BookCaseCamelLower, BookCaseDashes, BookCaseUnderScore, BookCaseCamelCase].each do |klass|
|
106
|
+
define_method(:"test_xml_convention_#{klass.to_s.underscore}") do
|
107
|
+
data = :"XML_#{klass.to_s.sub('BookCase', '').upcase}"
|
108
|
+
assert_equal Proc, klass.roxml_naming_convention.class
|
109
|
+
|
110
|
+
bc = klass.from_xml(Object.const_get(data))
|
111
|
+
assert_has_book_case_info(bc)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_child_should_inherit_convention_if_it_doesnt_declare_one
|
116
|
+
[InheritedBookCaseUpCase, InheritedBookCaseCamelCase].each do |klass|
|
117
|
+
data = :"XML_#{klass.to_s.sub('InheritedBookCase', '').upcase}"
|
118
|
+
assert_equal Proc, klass.roxml_naming_convention.class
|
119
|
+
|
120
|
+
bc = klass.from_xml(Object.const_get(data))
|
121
|
+
assert_has_book_case_info(bc)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_child_should_inherit_convention_even_if_it_is_added_after_child_declaration
|
126
|
+
bc = InheritedBookCaseDefault.from_xml(XML_UNDERSCORE)
|
127
|
+
assert_has_book_case_info(bc)
|
128
|
+
|
129
|
+
ParentBookCaseDefault.class_eval do
|
130
|
+
xml_convention :dasherize
|
131
|
+
end
|
132
|
+
|
133
|
+
bc = InheritedBookCaseDefault.from_xml(XML_DASHES)
|
134
|
+
assert_has_book_case_info(bc)
|
135
|
+
assert_raise ROXML::RequiredElementMissing do
|
136
|
+
InheritedBookCaseDefault.from_xml(XML_UNDERSCORE)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_tag_name_should_get_convention_treatment_as_well
|
141
|
+
assert_equal "book-case-dashes", BookCaseDashes.tag_name
|
142
|
+
assert_equal "INHERITEDBOOKCASEUPCASE", InheritedBookCaseUpCase.tag_name
|
143
|
+
assert_equal "InheritedBookCaseCamelCase", InheritedBookCaseCamelCase.tag_name
|
144
|
+
end
|
145
|
+
|
146
|
+
def assert_has_book_case_info(bc)
|
147
|
+
assert_equal 12, bc.book_count
|
148
|
+
assert_equal ['GED', 'House of Leaves'], bc.big_books
|
149
|
+
end
|
150
|
+
end
|
data/test/unit/xml_hash_test.rb
CHANGED
@@ -1,11 +1,52 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
|
+
class BookWithContributorHash
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_reader :contributors, {:key => {:attr => 'role'},
|
7
|
+
:value => 'name'}
|
8
|
+
end
|
9
|
+
|
3
10
|
class TestXMLHash < Test::Unit::TestCase
|
4
11
|
def setup
|
5
12
|
@contents = {'quaquaversally' => 'adjective: (of a geological formation) sloping downward from the center in all directions.',
|
6
13
|
'tergiversate' => 'To use evasions or ambiguities; equivocate.'}
|
7
14
|
end
|
8
15
|
|
16
|
+
def test_hash_preserves_data
|
17
|
+
b = BookWithContributorHash.from_xml(%{
|
18
|
+
<book isbn="0974514055">
|
19
|
+
<contributor role="author"><name>David Thomas</name></contributor>
|
20
|
+
<contributor role="supporting author"><name>Andrew Hunt</name></contributor>
|
21
|
+
<contributor role="supporting author"><name>Chad Fowler</name></contributor>
|
22
|
+
</book>
|
23
|
+
})
|
24
|
+
assert_equal({'author' => 'David Thomas', 'supporting author' => ['Andrew Hunt', 'Chad Fowler']},
|
25
|
+
b.contributors)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_hash_with_object_key_fails
|
29
|
+
assert_raise ArgumentError do
|
30
|
+
Class.new do
|
31
|
+
include ROXML
|
32
|
+
|
33
|
+
xml_reader :object_key_to_text, {:key => BookWithContributorHash,
|
34
|
+
:value => 'text_node'}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_hash_with_object_value_fails
|
40
|
+
assert_raise ArgumentError do
|
41
|
+
Class.new do
|
42
|
+
include ROXML
|
43
|
+
|
44
|
+
xml_reader :key_to_object_value, {:key => {:attr => 'text_node'},
|
45
|
+
:value => BookWithContributorHash}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
9
50
|
def test_attrs_hash
|
10
51
|
dict = DictionaryOfAttrs.from_xml(fixture(:dictionary_of_attrs))
|
11
52
|
assert_equal Hash, dict.definitions.class
|
data/test/unit/xml_name_test.rb
CHANGED
@@ -75,6 +75,16 @@ class TestXMLName < Test::Unit::TestCase
|
|
75
75
|
assert_equal "<parent><child_accessor_name/></parent>", parent.to_xml.to_s.gsub(/[\n ]/, '')
|
76
76
|
end
|
77
77
|
|
78
|
+
def test_it_should_be_inherited
|
79
|
+
class_with_inherited_name = Class.new(ParentOfNamedChild)
|
80
|
+
assert_equal :parent, class_with_inherited_name.tag_name
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_it_should_be_inherited_over_multiple_levels
|
84
|
+
class_with_inherited_name = Class.new(Class.new(ParentOfNamedChild))
|
85
|
+
assert_equal :parent, class_with_inherited_name.tag_name
|
86
|
+
end
|
87
|
+
|
78
88
|
def test_named_books_picked_up
|
79
89
|
named = Library.from_xml(fixture(:library))
|
80
90
|
assert named.books
|
@@ -95,14 +105,27 @@ class TestXMLName < Test::Unit::TestCase
|
|
95
105
|
end
|
96
106
|
|
97
107
|
def test_tag_refs
|
98
|
-
assert_equal 'definition', DictionaryOfTexts.
|
99
|
-
assert_equal 'word', DictionaryOfTexts.
|
100
|
-
assert_equal 'meaning', DictionaryOfTexts.
|
108
|
+
assert_equal 'definition', DictionaryOfTexts.tag_refs_without_deprecation.only.name
|
109
|
+
assert_equal 'word', DictionaryOfTexts.tag_refs_without_deprecation.only.hash.key.name
|
110
|
+
assert_equal 'meaning', DictionaryOfTexts.tag_refs_without_deprecation.only.hash.value.name
|
101
111
|
|
102
112
|
dict = DictionaryOfTexts.from_xml(fixture(:dictionary_of_texts))
|
103
113
|
|
104
|
-
assert_equal 'definition', dict.
|
105
|
-
assert_equal 'word', dict.
|
106
|
-
assert_equal 'meaning', dict.
|
114
|
+
assert_equal 'definition', dict.tag_refs_without_deprecation.only.name
|
115
|
+
assert_equal 'word', dict.tag_refs_without_deprecation.only.hash.key.name
|
116
|
+
assert_equal 'meaning', dict.tag_refs_without_deprecation.only.hash.value.name
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_roxml_attrs
|
120
|
+
assert_equal 'definition', DictionaryOfTexts.roxml_attrs.only.name
|
121
|
+
assert_equal 'word', DictionaryOfTexts.roxml_attrs.only.hash.key.name
|
122
|
+
assert_equal 'meaning', DictionaryOfTexts.roxml_attrs.only.hash.value.name
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_xml_name_query_is_deprecated
|
126
|
+
# This query should go when the XML_NAME_WARNING stuff goes
|
127
|
+
assert_deprecated do
|
128
|
+
NamedChild.xml_name?
|
129
|
+
end
|
107
130
|
end
|
108
131
|
end
|
@@ -1,5 +1,21 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
2
2
|
|
3
|
+
class EmptyCart
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_reader :id
|
7
|
+
|
8
|
+
def empty?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class CartHolder
|
14
|
+
include ROXML
|
15
|
+
|
16
|
+
xml_reader :cart, EmptyCart, :required => true
|
17
|
+
end
|
18
|
+
|
3
19
|
class TestXMLObject < Test::Unit::TestCase
|
4
20
|
# Test book with text and attribute
|
5
21
|
def test_book_author_text_attribute
|
@@ -113,4 +129,18 @@ class TestXMLObject < Test::Unit::TestCase
|
|
113
129
|
assert_equal 'Unknown', p.mother.mother.mother.name
|
114
130
|
assert_equal Person, p.mother.mother.mother.class
|
115
131
|
end
|
132
|
+
|
133
|
+
def test_defining_empty_on_object_doesnt_cause_it_to_be_seen_as_absent
|
134
|
+
# absent means defaulting, failing required
|
135
|
+
|
136
|
+
holder = CartHolder.from_xml(%{
|
137
|
+
<cartholder>
|
138
|
+
<cart>
|
139
|
+
<id>111111</id>
|
140
|
+
</cart>
|
141
|
+
</cartholder>
|
142
|
+
})
|
143
|
+
|
144
|
+
assert_equal "111111", holder.cart.id
|
145
|
+
end
|
116
146
|
end
|