Empact-roxml 2.3.1 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|