roxml 1.2 → 2.3.2

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.
Files changed (97) hide show
  1. data/MIT-LICENSE +18 -0
  2. data/README.rdoc +126 -0
  3. data/Rakefile +100 -0
  4. data/lib/roxml.rb +479 -485
  5. data/lib/roxml/extensions/active_support.rb +32 -0
  6. data/lib/roxml/extensions/array.rb +5 -0
  7. data/lib/roxml/extensions/array/conversions.rb +25 -0
  8. data/lib/roxml/extensions/deprecation.rb +28 -0
  9. data/lib/roxml/extensions/string.rb +21 -0
  10. data/lib/roxml/extensions/string/conversions.rb +44 -0
  11. data/lib/roxml/extensions/string/iterators.rb +12 -0
  12. data/lib/roxml/options.rb +266 -0
  13. data/lib/roxml/xml.rb +223 -0
  14. data/lib/roxml/xml/libxml.rb +63 -0
  15. data/lib/roxml/xml/rexml.rb +64 -0
  16. data/roxml.gemspec +105 -0
  17. data/test/fixtures/book_text_with_attribute.xml +1 -1
  18. data/test/fixtures/book_valid.xml +2 -2
  19. data/test/fixtures/book_with_authors.xml +7 -0
  20. data/test/fixtures/book_with_contributors_attrs.xml +7 -0
  21. data/test/fixtures/book_with_default_namespace.xml +9 -0
  22. data/test/fixtures/book_with_depth.xml +6 -0
  23. data/test/fixtures/book_with_wrapped_attr.xml +3 -0
  24. data/test/fixtures/dictionary_of_attr_name_clashes.xml +8 -0
  25. data/test/fixtures/dictionary_of_attrs.xml +6 -0
  26. data/test/fixtures/dictionary_of_guarded_names.xml +6 -0
  27. data/test/fixtures/dictionary_of_mixeds.xml +4 -0
  28. data/test/fixtures/dictionary_of_name_clashes.xml +10 -0
  29. data/test/fixtures/dictionary_of_names.xml +4 -0
  30. data/test/fixtures/dictionary_of_texts.xml +10 -0
  31. data/test/fixtures/library.xml +1 -1
  32. data/test/fixtures/library_uppercase.xml +30 -0
  33. data/test/fixtures/muffins.xml +3 -0
  34. data/test/fixtures/nameless_ageless_youth.xml +2 -0
  35. data/test/fixtures/node_with_attr_name_conflicts.xml +1 -0
  36. data/test/fixtures/node_with_name_conflicts.xml +4 -0
  37. data/test/fixtures/numerology.xml +4 -0
  38. data/test/fixtures/person_with_guarded_mothers.xml +13 -0
  39. data/test/fixtures/person_with_mothers.xml +10 -0
  40. data/test/mocks/dictionaries.rb +56 -0
  41. data/test/mocks/mocks.rb +244 -48
  42. data/test/release/dependencies_test.rb +32 -0
  43. data/test/test_helper.rb +44 -0
  44. data/test/unit/inheritance_test.rb +19 -0
  45. data/test/unit/options_test.rb +102 -0
  46. data/test/unit/roxml_test.rb +24 -0
  47. data/test/unit/string_test.rb +11 -0
  48. data/test/unit/to_xml_test.rb +52 -0
  49. data/test/unit/xml_attribute_test.rb +39 -0
  50. data/test/unit/xml_block_test.rb +81 -0
  51. data/test/unit/xml_bool_test.rb +105 -0
  52. data/test/unit/xml_construct_test.rb +77 -0
  53. data/test/unit/xml_hash_test.rb +65 -0
  54. data/test/unit/xml_initialize_test.rb +50 -0
  55. data/test/unit/xml_name_test.rb +108 -0
  56. data/test/unit/xml_namespace_test.rb +38 -0
  57. data/test/unit/xml_object_test.rb +116 -0
  58. data/test/unit/xml_required_test.rb +93 -0
  59. data/test/unit/xml_text_test.rb +68 -0
  60. metadata +138 -87
  61. data/MIT-LICENSE.txt +0 -9
  62. data/README +0 -2
  63. data/doc/classes/ROXML.html +0 -374
  64. data/doc/classes/ROXML.src/M000003.html +0 -19
  65. data/doc/classes/ROXML.src/M000004.html +0 -25
  66. data/doc/classes/ROXML.src/M000005.html +0 -22
  67. data/doc/classes/ROXML/ROXML_Class.html +0 -429
  68. data/doc/classes/ROXML/ROXML_Class.src/M000006.html +0 -27
  69. data/doc/classes/ROXML/ROXML_Class.src/M000007.html +0 -18
  70. data/doc/classes/ROXML/ROXML_Class.src/M000008.html +0 -19
  71. data/doc/classes/ROXML/ROXML_Class.src/M000009.html +0 -25
  72. data/doc/classes/ROXML/ROXML_Class.src/M000010.html +0 -24
  73. data/doc/classes/ROXML/ROXML_Class.src/M000011.html +0 -18
  74. data/doc/classes/ROXML/ROXML_Class.src/M000012.html +0 -18
  75. data/doc/classes/ROXML/XMLAttributeRef.html +0 -175
  76. data/doc/classes/ROXML/XMLAttributeRef.src/M000015.html +0 -19
  77. data/doc/classes/ROXML/XMLAttributeRef.src/M000016.html +0 -19
  78. data/doc/classes/ROXML/XMLObjectRef.html +0 -175
  79. data/doc/classes/ROXML/XMLObjectRef.src/M000013.html +0 -26
  80. data/doc/classes/ROXML/XMLObjectRef.src/M000014.html +0 -32
  81. data/doc/classes/ROXML/XMLRef.html +0 -166
  82. data/doc/classes/ROXML/XMLRef.src/M000017.html +0 -21
  83. data/doc/classes/ROXML/XMLTextRef.html +0 -198
  84. data/doc/classes/ROXML/XMLTextRef.src/M000018.html +0 -28
  85. data/doc/classes/ROXML/XMLTextRef.src/M000019.html +0 -34
  86. data/doc/classes/String.html +0 -165
  87. data/doc/classes/String.src/M000001.html +0 -23
  88. data/doc/classes/String.src/M000002.html +0 -23
  89. data/doc/created.rid +0 -1
  90. data/doc/files/lib/roxml_rb.html +0 -234
  91. data/doc/fr_class_index.html +0 -33
  92. data/doc/fr_file_index.html +0 -27
  93. data/doc/fr_method_index.html +0 -45
  94. data/doc/index.html +0 -24
  95. data/doc/rdoc-style.css +0 -208
  96. data/test/fixture_helper.rb +0 -5
  97. data/test/test_roxml.rb +0 -105
@@ -0,0 +1,65 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class TestXMLHash < Test::Unit::TestCase
4
+ def setup
5
+ @contents = {'quaquaversally' => 'adjective: (of a geological formation) sloping downward from the center in all directions.',
6
+ 'tergiversate' => 'To use evasions or ambiguities; equivocate.'}
7
+ end
8
+
9
+ def test_attrs_hash
10
+ dict = DictionaryOfAttrs.from_xml(fixture(:dictionary_of_attrs))
11
+ assert_equal Hash, dict.definitions.class
12
+ assert_equal @contents, dict.definitions
13
+ end
14
+
15
+ def test_text_hash
16
+ dict = DictionaryOfTexts.from_xml(fixture(:dictionary_of_texts))
17
+ assert_equal Hash, dict.definitions.class
18
+ assert_equal @contents, dict.definitions
19
+ end
20
+
21
+ def test_mixed_content_hash
22
+ dict = DictionaryOfMixeds.from_xml(fixture(:dictionary_of_mixeds))
23
+ assert_equal Hash, dict.definitions.class
24
+ assert_equal @contents, dict.definitions
25
+ end
26
+
27
+ def test_name_hash
28
+ dict = DictionaryOfNames.from_xml(fixture(:dictionary_of_names))
29
+ assert_equal Hash, dict.definitions.class
30
+ assert_equal @contents, dict.definitions
31
+ end
32
+
33
+ def test_guarded_name_hash
34
+ dict = DictionaryOfGuardedNames.from_xml(fixture(:dictionary_of_guarded_names))
35
+ assert_equal Hash, dict.definitions.class
36
+ assert_equal @contents, dict.definitions
37
+ end
38
+
39
+ def test_text_name_clashes
40
+ dict = DictionaryOfNameClashes.from_xml(fixture(:dictionary_of_name_clashes))
41
+ assert_equal Hash, dict.definitions.class
42
+ assert_equal @contents, dict.definitions
43
+ end
44
+
45
+ def test_attr_name_clashes
46
+ dict = DictionaryOfAttrNameClashes.from_xml(fixture(:dictionary_of_attr_name_clashes))
47
+ assert_equal Hash, dict.definitions.class
48
+ assert_equal @contents, dict.definitions
49
+ end
50
+
51
+ def test_it_should_gracefully_handle_empty_hash
52
+ dict = Class.new do
53
+ include ROXML
54
+
55
+ xml_reader :missing_hash, {:key => :name, :value => :content}, :in => 'EmptyDictionary'
56
+ end
57
+
58
+ assert_equal({}, dict.from_xml(%{
59
+ <dict>
60
+ <EmptyDictionary>
61
+ </EmptyDictionary>
62
+ </dict>
63
+ }).missing_hash)
64
+ end
65
+ end
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class BookWithXmlInitialize < BookWithDepth
4
+ attr_reader :created_at, :creator
5
+
6
+ def initialize(created_at, creator = "Unknown")
7
+ @created_at = created_at
8
+ @creator = creator
9
+ end
10
+ alias_method :xml_initialize, :initialize
11
+ end
12
+
13
+ class TestXMLInitialize < Test::Unit::TestCase
14
+ def test_xml_construct_not_in_use
15
+ assert Measurement.xml_construction_args_without_deprecation.empty?
16
+ end
17
+
18
+ def test_initialize_is_run
19
+ m = Measurement.from_xml('<measurement units="hundredths-meters">1130</measurement>')
20
+ assert_equal 11.3, m.value
21
+ assert_equal 'meters', m.units
22
+ end
23
+
24
+ def test_initialize_is_run_for_nested_type
25
+ b = BookWithDepth.from_xml(fixture(:book_with_depth))
26
+ assert_equal Measurement.new(11.3, 'meters'), b.depth
27
+ end
28
+
29
+ def test_initialize_is_run_for_nested_type_with_inheritance
30
+ b = InheritedBookWithDepth.from_xml(fixture(:book_with_depth))
31
+ assert_equal Measurement.new(11.3, 'meters'), b.depth
32
+ end
33
+
34
+ def test_initialize_fails_on_missing_required_arg
35
+ assert_raises(ArgumentError) do
36
+ b = BookWithXmlInitialize.from_xml(fixture(:book_with_depth))
37
+ end
38
+ end
39
+
40
+ def test_initialize_with_extra_args
41
+ now = Time.now
42
+ b = BookWithXmlInitialize.from_xml(fixture(:book_with_depth), now)
43
+ assert_equal now, b.created_at
44
+ assert_equal "Unknown", b.creator
45
+
46
+ b = BookWithXmlInitialize.from_xml(fixture(:book_with_depth), Time.now, "Joe Librarian")
47
+ assert now < b.created_at
48
+ assert_equal "Joe Librarian", b.creator
49
+ end
50
+ end
@@ -0,0 +1,108 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ # Parent | Child
4
+ # :from | no :from |
5
+ # -------------------|--------------
6
+ # :from | xml_name | xml_name-d
7
+ # value | value |
8
+ # -------------------|--------------
9
+ # :from | parent's |
10
+ # value | accessor | un-xml_name-d
11
+ # | name |
12
+
13
+ class Child
14
+ include ROXML
15
+ end
16
+
17
+ class NamedChild
18
+ include ROXML
19
+
20
+ xml_name :xml_name_of_child
21
+ end
22
+
23
+ class ParentOfNamedChild
24
+ include ROXML
25
+
26
+ xml_name :parent
27
+ xml_accessor :child_accessor_name, NamedChild
28
+ end
29
+
30
+ class ParentOfNamedChildWithFrom
31
+ include ROXML
32
+
33
+ xml_name :parent
34
+ xml_accessor :child_accessor_name, NamedChild, :from => 'child_from_name'
35
+ end
36
+
37
+ class ParentOfUnnamedChild
38
+ include ROXML
39
+
40
+ xml_name :parent
41
+ xml_accessor :child_accessor_name, Child
42
+ end
43
+
44
+ class ParentOfUnnamedChildWithFrom
45
+ include ROXML
46
+
47
+ xml_name :parent
48
+ xml_accessor :child_accessor_name, Child, :from => 'child_from_name'
49
+ end
50
+
51
+ class TestXMLName < Test::Unit::TestCase
52
+ def test_from_always_dominates_attribute_name_xml_name_or_not
53
+ parent = ParentOfNamedChildWithFrom.new
54
+ parent.child_accessor_name = Child.new
55
+
56
+ assert_equal "<parent><child_from_name/></parent>", parent.to_xml.to_s.gsub(/[\n ]/, '')
57
+
58
+ parent = ParentOfUnnamedChildWithFrom.new
59
+ parent.child_accessor_name = Child.new
60
+
61
+ assert_equal "<parent><child_from_name/></parent>", parent.to_xml.to_s.gsub(/[\n ]/, '')
62
+ end
63
+
64
+ def test_attribute_name_comes_from_the_xml_name_value_if_present
65
+ parent = ParentOfNamedChild.new
66
+ parent.child_accessor_name = Child.new
67
+
68
+ assert_equal "<parent><xml_name_of_child/></parent>", parent.to_xml.to_s.gsub(/[\n ]/, '')
69
+ end
70
+
71
+ def test_attribute_name_comes_from_parent_accessor_by_default
72
+ parent = ParentOfUnnamedChild.new
73
+ parent.child_accessor_name = Child.new
74
+
75
+ assert_equal "<parent><child_accessor_name/></parent>", parent.to_xml.to_s.gsub(/[\n ]/, '')
76
+ end
77
+
78
+ def test_named_books_picked_up
79
+ named = Library.from_xml(fixture(:library))
80
+ assert named.books
81
+ assert_equal :book, named.books.first.tag_name
82
+ end
83
+
84
+ def test_nameless_books_missing
85
+ nameless = LibraryWithBooksOfUnderivableName.from_xml(fixture(:library))
86
+ assert nameless.novels.empty?
87
+ end
88
+
89
+ def test_tag_name
90
+ assert_equal :dictionary, DictionaryOfTexts.tag_name
91
+
92
+ dict = DictionaryOfTexts.from_xml(fixture(:dictionary_of_texts))
93
+
94
+ assert_equal :dictionary, dict.tag_name
95
+ end
96
+
97
+ def test_tag_refs
98
+ assert_equal 'definition', DictionaryOfTexts.tag_refs.only.name
99
+ assert_equal 'word', DictionaryOfTexts.tag_refs.only.hash.key.name
100
+ assert_equal 'meaning', DictionaryOfTexts.tag_refs.only.hash.value.name
101
+
102
+ dict = DictionaryOfTexts.from_xml(fixture(:dictionary_of_texts))
103
+
104
+ assert_equal 'definition', dict.tag_refs.only.name
105
+ assert_equal 'word', dict.tag_refs.only.hash.key.name
106
+ assert_equal 'meaning', dict.tag_refs.only.hash.value.name
107
+ end
108
+ end
@@ -0,0 +1,38 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class TestXMLNamespaces < Test::Unit::TestCase
4
+ def setup
5
+ @book = BookWithContributions.from_xml(fixture(:book_with_default_namespace))
6
+ end
7
+
8
+ def test_default_namespace_doesnt_interfere_with_normal_operation
9
+ assert_equal("Programming Ruby - 2nd Edition", @book.title)
10
+ end
11
+
12
+ def test_default_namespace_is_applied_to_in_element
13
+ expected_authors = ["David Thomas","Andrew Hunt","Chad Fowler"]
14
+ assert !@book.contributions.empty?
15
+ @book.contributions.each do |contributor|
16
+ assert expected_authors.include?(contributor.name)
17
+ end
18
+ end
19
+
20
+ def test_that_rexml_follows_nameless_default_namespace
21
+ require 'rexml/document'
22
+ xml = REXML::Document.new(
23
+ '<container xmlns="http://fakenamespace.org"><node>Yeah, content</node></container>')
24
+
25
+ assert_equal "Yeah, content", xml.root.get_elements('node').first.text
26
+ end
27
+
28
+ def test_default_namespace_on_root_node_should_be_found
29
+ require 'libxml'
30
+ xml = LibXML::XML::Parser.string(
31
+ '<container xmlns="http://defaultnamespace.org"><node>Yeah, content</node><node><subnode>Another</subnode></node></container>').parse
32
+
33
+ assert_equal nil, xml.find_first('node')
34
+ assert_equal "Yeah, content", xml.find_first('ns:node', 'ns:http://defaultnamespace.org').content
35
+ assert_equal nil, xml.find_first('ns:node/subnode', 'ns:http://defaultnamespace.org')
36
+ assert_equal "Another", xml.find_first('ns:node/ns:subnode', 'ns:http://defaultnamespace.org').content
37
+ end
38
+ end
@@ -0,0 +1,116 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class TestXMLObject < Test::Unit::TestCase
4
+ # Test book with text and attribute
5
+ def test_book_author_text_attribute
6
+ book = BookWithAuthorTextAttribute.from_xml(fixture(:book_text_with_attribute))
7
+ assert_equal("primary",book.author.role)
8
+ assert_equal("David Thomas",book.author.text)
9
+ end
10
+
11
+ # Test XML object containing list of other XML objects (one-to-many)
12
+ # In this case, book with contibutions
13
+ def test_one_to_many_with_container
14
+ expected_authors = ["David Thomas","Andrew Hunt","Chad Fowler"]
15
+ book = BookWithContributions.from_xml(fixture(:book_with_contributions))
16
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
17
+ book.contributions.each do |contributor|
18
+ assert expected_authors.include?(contributor.name)
19
+ end
20
+ end
21
+
22
+ # Test XML object containing 1-n other XML objects without container (one-to-many)
23
+ # In this case, book with contibutions
24
+ def test_one_to_many_without_container
25
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler"]
26
+ book = BookWithContributors.from_xml(fixture(:book_with_contributors))
27
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
28
+ book.contributors.each do |contributor|
29
+ assert(expected_contributors.include?(contributor.name))
30
+ end
31
+ end
32
+
33
+ # when building objects that contain arrays, the second object seems to
34
+ # inherit data from the first
35
+ #
36
+ def test_one_to_many_without_container_sequence
37
+ contrib = WriteableContributor.new
38
+ contrib.name = "David Thomas"
39
+
40
+ book_one = WriteableBookWithContributors.new
41
+ book_one.isbn = "9781843549161"
42
+ book_one.title = "Anathem"
43
+ book_one.description = "A new title from Neal Stephenson"
44
+ book_one.contributors << contrib
45
+
46
+ # this book should be completely empty
47
+ book_two = WriteableBookWithContributors.new
48
+
49
+ assert_equal(nil, book_two.isbn)
50
+ assert_equal(nil, book_two.title)
51
+ assert_equal(nil, book_two.description)
52
+ assert_equal(0, book_two.contributors.size)
53
+ end
54
+
55
+ # Test XML object containing one other XML object (one-to-one)
56
+ # In this case, book with publisher
57
+ def test_one_to_one
58
+ book = BookWithPublisher.from_xml(fixture(:book_with_publisher))
59
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
60
+ assert_equal("Pragmatic Bookshelf", book.publisher.name)
61
+ end
62
+
63
+ # Test XML object containing type of self (self-reference)
64
+ def test_self_reference
65
+ book = BookPair.from_xml(fixture(:book_pair))
66
+ assert_equal("Programming Ruby - 2nd Edition", book.title)
67
+ assert_equal("Agile Web Development with Rails", book.book.title)
68
+ end
69
+
70
+ # Test three-level composition (one-to-many-to-many)
71
+ def test_one_to_many_to_many
72
+ expected_contributors = ["David Thomas","Andrew Hunt","Chad Fowler", "David Heinemeier Hansson"]
73
+ expected_books = ["Programming Ruby - 2nd Edition", "Agile Web Development with Rails"]
74
+ library = Library.from_xml(fixture(:library))
75
+ assert_equal("Ruby library", library.name)
76
+ assert !library.books.empty?
77
+ library.books.each do |book|
78
+ assert expected_books.include?(book.title)
79
+ book.contributions.each do |contributor|
80
+ assert(expected_contributors.include?(contributor.name))
81
+ end
82
+ end
83
+ end
84
+
85
+ def test_without_needed_from
86
+ assert_equal [], UppercaseLibrary.from_xml(fixture(:library)).books
87
+ assert_equal [], Library.from_xml(fixture(:library_uppercase)).books
88
+ end
89
+
90
+ def test_with_needed_from
91
+ assert Library.from_xml(fixture(:library)).books
92
+ assert UppercaseLibrary.from_xml(fixture(:library_uppercase)).books
93
+ end
94
+
95
+ def test_with_recursion
96
+ p = PersonWithMother.from_xml(fixture(:person_with_mothers))
97
+ assert_equal 'Ben Franklin', p.name
98
+ assert_equal 'Abiah Folger', p.mother.name
99
+ assert_equal 'Madeup Mother', p.mother.mother.name
100
+ assert_equal nil, p.mother.mother.mother
101
+ end
102
+
103
+ def test_with_guarded_recursion
104
+ p = PersonWithGuardedMother.from_xml(fixture(:person_with_guarded_mothers))
105
+ assert_equal 'Ben Franklin', p.name
106
+ assert_equal 'Abiah Folger', p.mother.name
107
+ assert_equal 'Madeup Mother', p.mother.mother.name
108
+ assert_equal nil, p.mother.mother.mother
109
+ end
110
+
111
+ def test_recursive_with_default_initialization
112
+ p = PersonWithMotherOrMissing.from_xml(fixture(:person_with_mothers))
113
+ assert_equal 'Unknown', p.mother.mother.mother.name
114
+ assert_equal Person, p.mother.mother.mother.class
115
+ end
116
+ end
@@ -0,0 +1,93 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class TestXMLRequired < Test::Unit::TestCase
4
+ def setup
5
+ @full_book = <<BOOK
6
+ <book ISBN="1234">
7
+ <title>This &amp; that</title>
8
+ <contributor_array>
9
+ <contributor role="Author">
10
+ <name>Johnny</name>
11
+ </contributor>
12
+ </contributor_array>
13
+ <contributor_hash>
14
+ <contributor role="Author" name="Johnny" />
15
+ </contributor_hash>
16
+ </book>
17
+ BOOK
18
+
19
+ @book_missing_attr = <<BOOK
20
+ <book>
21
+ <title>This &amp; that</title>
22
+ <contributor_array>
23
+ <contributor role="Author">
24
+ <name>Johnny</name>
25
+ </contributor>
26
+ </contributor_array>
27
+ <contributor_hash>
28
+ <contributor role="Author" name="Johnny" />
29
+ </contributor_hash>
30
+ </book>
31
+ BOOK
32
+
33
+ @book_missing_text = <<BOOK
34
+ <book ISBN="1234">
35
+ <contributor_array>
36
+ <contributor role="Author">
37
+ <name>Johnny</name>
38
+ </contributor>
39
+ </contributor_array>
40
+ <contributor_hash>
41
+ <contributor role="Author" name="Johnny" />
42
+ </contributor_hash>
43
+ </book>
44
+ BOOK
45
+
46
+ @book_missing_array = <<BOOK
47
+ <book ISBN="1234">
48
+ <title>This &amp; that</title>
49
+ <contributor_hash>
50
+ <contributor role="Author" name="Johnny" />
51
+ </contributor_hash>
52
+ </book>
53
+ BOOK
54
+
55
+ @book_missing_hash = <<BOOK
56
+ <book ISBN="1234">
57
+ <title>This &amp; that</title>
58
+ <contributor_array>
59
+ <contributor role="Author">
60
+ <name>Johnny</name>
61
+ </contributor>
62
+ </contributor_array>
63
+ </book>
64
+ BOOK
65
+ end
66
+
67
+ def test_required_passes_on_prescence
68
+ BookWithRequired.from_xml(@full_book)
69
+ end
70
+
71
+ def test_required_throws_on_attr_absence
72
+ assert_raise ROXML::RequiredElementMissing do
73
+ BookWithRequired.from_xml(@book_missing_attr)
74
  end
75
+ end
76
+
77
+ def test_required_throws_on_text_absence
78
+ assert_raise ROXML::RequiredElementMissing do
79
+ BookWithRequired.from_xml(@book_missing_text)
80
+ end
81
+ end
82
+
83
+ def test_required_throws_on_array_absence
84
+ assert_raise ROXML::RequiredElementMissing do
85
+ BookWithRequired.from_xml(@book_missing_array)
86
+ end
87
+ end
88
+
89
+ def test_required_throws_on_hash_absence
90
+ assert_raise ROXML::RequiredElementMissing do
91
+ BookWithRequired.from_xml(@book_missing_hash)
92
+ end
93
+ end
94
+ end