yob-roxml 3.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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,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.sought_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.parse_string(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.roxml_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.roxml_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
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'test/test_helper'
|
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
|
+
|
8
|
+
class XmlBool
|
9
|
+
include ROXML
|
10
|
+
|
11
|
+
xml_name 'xml_bool'
|
12
|
+
xml_reader :true_from_TRUE?, :to_xml => PROC_TRUE
|
13
|
+
xml_reader :false_from_FALSE?, :from => 'text_for_FALSE', :to_xml => PROC_TRUE
|
14
|
+
xml_reader :true_from_one?, :from => '@attr_for_one', :to_xml => PROC_1
|
15
|
+
xml_reader :false_from_zero?, :from => 'text_for_zero', :in => 'container', :to_xml => PROC_1
|
16
|
+
xml_reader :true_from_True?, :from => '@attr_for_True', :in => 'container', :to_xml => PROC_True
|
17
|
+
xml_reader :false_from_False?, :from => 'false_from_cdata_False', :cdata => true, :to_xml => PROC_True
|
18
|
+
xml_reader :true_from_true?, :to_xml => PROC_true
|
19
|
+
xml_reader :false_from_false?, :to_xml => PROC_true
|
20
|
+
xml_reader :missing?
|
21
|
+
end
|
22
|
+
|
23
|
+
class XmlBoolRequired
|
24
|
+
include ROXML
|
25
|
+
|
26
|
+
xml_reader :required?, :required => true
|
27
|
+
end
|
28
|
+
|
29
|
+
class XmlBoolUnexpected
|
30
|
+
include ROXML
|
31
|
+
|
32
|
+
xml_reader :unexpected?
|
33
|
+
end
|
34
|
+
|
35
|
+
class XmlBoolUnexpectedWithBlock
|
36
|
+
include ROXML
|
37
|
+
|
38
|
+
xml_reader :unexpected? do |val|
|
39
|
+
val
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
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
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
class TestXMLBool < ActiveSupport::TestCase
|
72
|
+
def test_bool_results_for_various_inputs
|
73
|
+
x = XmlBool.from_xml(BOOL_XML)
|
74
|
+
assert_equal true, x.true_from_TRUE?
|
75
|
+
assert_equal false, x.false_from_FALSE?
|
76
|
+
assert_equal true, x.true_from_one?
|
77
|
+
assert_equal false, x.false_from_zero?
|
78
|
+
assert_equal true, x.true_from_True?
|
79
|
+
assert_equal false, x.false_from_False?
|
80
|
+
assert_equal true, x.true_from_true?
|
81
|
+
assert_equal false, x.false_from_false?
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_missing_results_in_nil
|
85
|
+
x = XmlBool.from_xml(BOOL_XML)
|
86
|
+
assert_equal nil, x.missing?
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_unexpected_value_results_in_nil
|
90
|
+
x = XmlBoolUnexpected.from_xml(UNEXPECTED_VALUE_XML)
|
91
|
+
assert_equal nil, x.unexpected?
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_block_recieves_unexpected_value_rather_than_nil
|
95
|
+
x = XmlBoolUnexpectedWithBlock.from_xml(UNEXPECTED_VALUE_XML)
|
96
|
+
assert_equal "Unexpected Value", x.unexpected?
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_required_raises_on_missing
|
100
|
+
assert_nothing_raised do
|
101
|
+
XmlBoolRequired.from_xml(PRESENT)
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_raise ROXML::RequiredElementMissing do
|
105
|
+
XmlBoolRequired.from_xml(ABSENT)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_writable_references_properly_handle_punctuation
|
110
|
+
klass = Class.new do
|
111
|
+
include ROXML
|
112
|
+
xml_accessor :punctuation?
|
113
|
+
end
|
114
|
+
|
115
|
+
instance = klass.from_xml("<xml><punctuation>True</punctuation></xml>")
|
116
|
+
assert_equal true, instance.punctuation?
|
117
|
+
instance.punctuation = false
|
118
|
+
assert_equal false, instance.punctuation?
|
119
|
+
end
|
120
|
+
|
121
|
+
to_xml_test XmlBool => BOOL_XML
|
122
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'test/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, :as => [], :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, :as => [], :required => true
|
92
|
+
end
|
93
|
+
|
94
|
+
class InheritedBookCaseDefault < ParentBookCaseDefault
|
95
|
+
end
|
96
|
+
|
97
|
+
class TestXMLConvention < ActiveSupport::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
|