nokogiri-happymapper 0.7.0 → 0.8.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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -5
  3. data/README.md +85 -69
  4. data/lib/happymapper.rb +27 -22
  5. data/lib/happymapper/anonymous_mapper.rb +35 -30
  6. data/lib/happymapper/item.rb +1 -1
  7. data/lib/happymapper/supported_types.rb +2 -7
  8. data/lib/happymapper/version.rb +1 -1
  9. data/spec/features/after_parse_callbacks_spec.rb +29 -0
  10. data/spec/{attribute_default_value_spec.rb → features/attribute_default_value_spec.rb} +3 -3
  11. data/spec/{attributes_spec.rb → features/attributes_spec.rb} +6 -6
  12. data/spec/{has_many_empty_array_spec.rb → features/has_many_empty_array_spec.rb} +1 -1
  13. data/spec/{ignay_spec.rb → features/ignay_spec.rb} +10 -19
  14. data/spec/{inheritance_spec.rb → features/inheritance_spec.rb} +1 -1
  15. data/spec/{mixed_namespaces_spec.rb → features/mixed_namespaces_spec.rb} +17 -17
  16. data/spec/{parse_with_object_to_update_spec.rb → features/parse_with_object_to_update_spec.rb} +0 -0
  17. data/spec/features/same_tag_different_meaning_spec.rb +44 -0
  18. data/spec/{to_xml_spec.rb → features/to_xml_spec.rb} +2 -2
  19. data/spec/{to_xml_with_namespaces_spec.rb → features/to_xml_with_namespaces_spec.rb} +0 -0
  20. data/spec/{wilcard_tag_name_spec.rb → features/wildcard_tag_name_spec.rb} +5 -5
  21. data/spec/{wrap_spec.rb → features/wrap_spec.rb} +4 -4
  22. data/spec/{xpath_spec.rb → features/xpath_spec.rb} +17 -23
  23. data/spec/happymapper/anonymous_mapper_spec.rb +158 -0
  24. data/spec/happymapper/element_spec.rb +1 -1
  25. data/spec/happymapper/item_spec.rb +75 -45
  26. data/spec/happymapper_spec.rb +120 -125
  27. metadata +32 -28
  28. data/spec/happymapper_parse_spec.rb +0 -131
@@ -28,7 +28,7 @@ module HappyMapper
28
28
  end
29
29
 
30
30
  #
31
- # @param [XMLNode] node the xml node that is being parsed
31
+ # @param [Nokogiri::XML::Element] node the xml node that is being parsed
32
32
  # @param [String] namespace the name of the namespace
33
33
  # @param [Hash] xpath_options additional xpath options
34
34
  #
@@ -126,13 +126,8 @@ module HappyMapper
126
126
 
127
127
  register_type Integer do |value|
128
128
  value_to_i = value.to_i
129
- if value_to_i == 0 && value != '0'
130
- value_to_s = value.to_s
131
- begin
132
- Integer(value_to_s =~ /^(\d+)/ ? $1 : value_to_s)
133
- rescue ArgumentError
134
- nil
135
- end
129
+ if value_to_i == 0 && !value.to_s.start_with?('0')
130
+ nil
136
131
  else
137
132
  value_to_i
138
133
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HappyMapper
4
- VERSION = '0.7.0'
4
+ VERSION = '0.8.0'
5
5
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'after_parse callbacks' do
6
+ module AfterParseSpec
7
+ class Address
8
+ include HappyMapper
9
+ element :street, String
10
+ end
11
+ end
12
+
13
+ after do
14
+ AfterParseSpec::Address.after_parse_callbacks.clear
15
+ end
16
+
17
+ it 'callbacks with the newly created object' do
18
+ from_cb = nil
19
+ called = false
20
+ cb1 = proc { |object| from_cb = object }
21
+ cb2 = proc { called = true }
22
+ AfterParseSpec::Address.after_parse(&cb1)
23
+ AfterParseSpec::Address.after_parse(&cb2)
24
+
25
+ object = AfterParseSpec::Address.parse fixture_file('address.xml')
26
+ expect(from_cb).to eq(object)
27
+ expect(called).to eq(true)
28
+ end
29
+ end
@@ -30,15 +30,15 @@ describe 'Attribute Default Value' do
30
30
  end
31
31
 
32
32
  context 'when a new, non-nil value has been set' do
33
+ let(:expected_xml) { %(<?xml version="1.0"?>\n<meal type="kosher"/>\n) }
34
+
33
35
  it 'returns the new value' do
34
36
  meal = subject.parse('<meal />')
35
37
  meal.type = 'vegan'
36
38
 
37
- expect(meal.type).to_not eq default_meal_type
39
+ expect(meal.type).not_to eq default_meal_type
38
40
  end
39
41
 
40
- let(:expected_xml) { %(<?xml version="1.0"?>\n<meal type="kosher"/>\n) }
41
-
42
42
  it 'saves the new value to the xml' do
43
43
  meal = subject.new
44
44
  meal.type = 'kosher'
@@ -3,12 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe 'Attribute Method Conversion' do
6
- let(:xml_document) do
7
- %(<document>
8
- <link data-src='http://cooking.com/roastbeef' type='recipe'>Roast Beef</link>
9
- </document>)
10
- end
11
-
12
6
  module AttributeMethodConversion
13
7
  class Document
14
8
  include HappyMapper
@@ -17,6 +11,12 @@ describe 'Attribute Method Conversion' do
17
11
  end
18
12
  end
19
13
 
14
+ let(:xml_document) do
15
+ %(<document>
16
+ <link data-src='http://cooking.com/roastbeef' type='recipe'>Roast Beef</link>
17
+ </document>)
18
+ end
19
+
20
20
  let(:document) do
21
21
  AttributeMethodConversion::Document.parse(xml_document, single: true)
22
22
  end
@@ -38,7 +38,7 @@ describe 'emptyness' do
38
38
  expect(navigator.items_with_a_different_name).to be_empty
39
39
  end
40
40
 
41
- it 'returns an empty array' do
41
+ it 'looks for items based on the element tag, not the element name' do
42
42
  expect(navigator.items).to be_empty
43
43
  end
44
44
  end
@@ -39,25 +39,29 @@ class CatalogNode
39
39
  end
40
40
 
41
41
  describe HappyMapper do
42
- it 'should not be nil' do
42
+ let(:catalog_tree) { CatalogTree.parse(fixture_file('inagy.xml'), single: true) }
43
+
44
+ it 'is not nil' do
43
45
  expect(catalog_tree).not_to be_nil
44
46
  end
45
47
 
46
- it 'should have the attribute code' do
48
+ it 'has the attribute code' do
47
49
  expect(catalog_tree.code).to eq('NLD')
48
50
  end
49
51
 
50
- it 'should have many nodes' do
52
+ it 'has many nodes' do
51
53
  expect(catalog_tree.nodes).not_to be_empty
52
54
  expect(catalog_tree.nodes.length).to eq(2)
53
55
  end
54
56
 
55
57
  context 'first node' do
56
- it 'should have a name' do
58
+ let(:first_node) { catalog_tree.nodes.first }
59
+
60
+ it 'has a name' do
57
61
  expect(first_node.name).to eq('Parent 1')
58
62
  end
59
63
 
60
- it 'should have translations' do
64
+ it 'has translations' do
61
65
  expect(first_node.translations.length).to eq(2)
62
66
 
63
67
  expect(first_node.translations.first.language).to eq('en-GB')
@@ -65,7 +69,7 @@ describe HappyMapper do
65
69
  expect(first_node.translations.last.name).to eq('Parent 1 de')
66
70
  end
67
71
 
68
- it 'should have subnodes' do
72
+ it 'has subnodes' do
69
73
  expect(first_node.nodes).to be_kind_of(Enumerable)
70
74
  expect(first_node.nodes).not_to be_empty
71
75
  expect(first_node.nodes.length).to eq(1)
@@ -74,18 +78,5 @@ describe HappyMapper do
74
78
  it 'first node - first node name' do
75
79
  expect(first_node.nodes.first.name).to eq('First')
76
80
  end
77
-
78
- def first_node
79
- @first_node = catalog_tree.nodes.first
80
- end
81
- end
82
-
83
- def catalog_tree
84
- @catalog_tree
85
- end
86
-
87
- before(:all) do
88
- xml_reference = "#{File.dirname(__FILE__)}/fixtures/inagy.xml"
89
- @catalog_tree = CatalogTree.parse(File.read(xml_reference), single: true)
90
81
  end
91
82
  end
@@ -79,7 +79,7 @@ describe 'Using inheritance to share elements and attributes' do
79
79
  end
80
80
 
81
81
  context 'when parsing xml' do
82
- it 'should be possible to deserialize XML into a Child class instance' do
82
+ it 'is possible to deserialize XML into a Child class instance' do
83
83
  expect(subject.love).to eq 99
84
84
  expect(subject.genetics.dna).to eq 'ABBA'
85
85
  expect(subject.naivety).to eq 'trusting'
@@ -3,23 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe 'A document with mixed namespaces' do
6
- #
7
- # Note that the parent element of the xml has the namespacing. The elements
8
- # contained within the xml do not share the parent element namespace so a
9
- # user of the library would likely need to clear the namespace on each of
10
- # these child elements.
11
- #
12
- let(:xml_document) do
13
- %(<prefix:address location='home' xmlns:prefix="http://www.unicornland.com/prefix"
14
- xmlns:different="http://www.trollcountry.com/different">
15
- <street>Milchstrasse</street>
16
- <street>Another Street</street>
17
- <housenumber>23</housenumber>
18
- <different:postcode>26131</different:postcode>
19
- <city>Oldenburg</city>
20
- </prefix:address>)
21
- end
22
-
23
6
  module MixedNamespaces
24
7
  class Address
25
8
  include HappyMapper
@@ -38,6 +21,23 @@ describe 'A document with mixed namespaces' do
38
21
  end
39
22
  end
40
23
 
24
+ #
25
+ # Note that the parent element of the xml has the namespacing. The elements
26
+ # contained within the xml do not share the parent element namespace so a
27
+ # user of the library would likely need to clear the namespace on each of
28
+ # these child elements.
29
+ #
30
+ let(:xml_document) do
31
+ %(<prefix:address location='home' xmlns:prefix="http://www.unicornland.com/prefix"
32
+ xmlns:different="http://www.trollcountry.com/different">
33
+ <street>Milchstrasse</street>
34
+ <street>Another Street</street>
35
+ <housenumber>23</housenumber>
36
+ <different:postcode>26131</different:postcode>
37
+ <city>Oldenburg</city>
38
+ </prefix:address>)
39
+ end
40
+
41
41
  let(:address) do
42
42
  MixedNamespaces::Address.parse(xml_document, single: true)
43
43
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'parsing the same tag differently in different contexts' do
6
+ module SameTagSpec
7
+ class Bar
8
+ include HappyMapper
9
+ has_one :baz, String
10
+ end
11
+
12
+ class Baz
13
+ include HappyMapper
14
+ has_one :qux, String
15
+ end
16
+
17
+ class Foo
18
+ include HappyMapper
19
+ has_one :bar, Bar
20
+ has_one :baz, Baz, xpath: '.'
21
+ end
22
+ end
23
+
24
+ let(:xml) do
25
+ <<~XML
26
+ <foo>
27
+ <bar>
28
+ <baz>Hello</baz>
29
+ </bar>
30
+ <baz>
31
+ <qux>Hi</qux>
32
+ </baz>
33
+ </foo>
34
+ XML
35
+ end
36
+
37
+ it 'parses both uses correctly if xpath limits recursion' do
38
+ result = SameTagSpec::Foo.parse xml
39
+ aggregate_failures do
40
+ expect(result.bar.baz).to eq 'Hello'
41
+ expect(result.baz.qux).to eq 'Hi'
42
+ end
43
+ end
44
+ end
@@ -191,11 +191,11 @@ describe 'Saving #to_xml' do
191
191
  expect(subject.xpath('country/@countryCode').text).to eq 'us'
192
192
  end
193
193
 
194
- it 'saves elements' do
194
+ it 'saves elements with a specified tag' do
195
195
  expect(subject.xpath('country/countryName').text).to eq 'USA'
196
196
  end
197
197
 
198
- it 'saves elements' do
198
+ it 'saves elements with content' do
199
199
  expect(subject.xpath('country/description').text).to eq 'A lovely country'
200
200
  end
201
201
  end
@@ -58,12 +58,12 @@ describe 'Wildcard Root Tag' do
58
58
  let(:subject) { GenericBase::Root.parse(generic_class_xml) }
59
59
  let(:xml) { Nokogiri::XML(subject.to_xml) }
60
60
 
61
- it 'should map different elements to same class' do
61
+ it 'maps different elements to same class' do
62
62
  expect(subject.blargs).not_to be_nil
63
63
  expect(subject.jellos).not_to be_nil
64
64
  end
65
65
 
66
- it 'should filter on xpath appropriately' do
66
+ it 'filters on xpath appropriately' do
67
67
  expect(subject.blargs.size).to eq(2)
68
68
  expect(subject.jellos.size).to eq(1)
69
69
  expect(subject.subjellos.size).to eq(1)
@@ -73,7 +73,7 @@ describe 'Wildcard Root Tag' do
73
73
  GenericBase::Base.new(name: name, href: href, other: other)
74
74
  end
75
75
 
76
- it 'should parse correct values onto generic class' do
76
+ it 'parses correct values onto generic class' do
77
77
  expect(subject.blargs[0]).to eq base_with('blargname1', 'http://blarg.com', nil)
78
78
  expect(subject.blargs[1]).to eq base_with('blargname2', 'http://blarg.com', nil)
79
79
  expect(subject.jellos[0]).to eq base_with('jelloname', 'http://jello.com', nil)
@@ -86,14 +86,14 @@ describe 'Wildcard Root Tag' do
86
86
  expect(xml.xpath("#{xpath}/@other").text).to eq other
87
87
  end
88
88
 
89
- it 'should #to_xml using parent element tag name' do
89
+ it '#to_xmls using parent element tag name' do
90
90
  expect(xml.xpath('/root/description').text).to eq('some description')
91
91
  validate_xpath('/root/blarg[1]', 'blargname1', 'http://blarg.com', '')
92
92
  validate_xpath('/root/blarg[2]', 'blargname2', 'http://blarg.com', '')
93
93
  validate_xpath('/root/jello[1]', 'jelloname', 'http://jello.com', '')
94
94
  end
95
95
 
96
- it "should properly respect child HappyMapper tags if tag isn't provided on the element defintion" do
96
+ it "properlies respect child HappyMapper tags if tag isn't provided on the element defintion" do
97
97
  expect(xml.xpath('root/subelement').size).to eq(1)
98
98
  end
99
99
  end
@@ -35,15 +35,15 @@ describe 'wrap which allows you to specify a wrapper element' do
35
35
  expect(subject.subclass.items.size).to eq(2)
36
36
  expect(subject.subclass.items[0]).to eq 'item1'
37
37
  expect(subject.subclass.items[1]).to eq 'item2'
38
- expect(subject.number).to eq 12345
38
+ expect(subject.number).to eq 12_345
39
39
  end
40
40
  end
41
41
 
42
42
  context 'when initialized without XML' do
43
43
  let(:subject) { Wrap::Root.new }
44
44
 
45
- it 'anonymous classes are created so nil class values does not occur' do
46
- expect { subject.description = 'anything' }.to_not raise_error
45
+ it 'creates anonymous classes so nil class values do not occur' do
46
+ expect { subject.description = 'anything' }.not_to raise_error
47
47
  end
48
48
  end
49
49
  end
@@ -54,7 +54,7 @@ describe 'wrap which allows you to specify a wrapper element' do
54
54
  root.attr1 = 'somevalue'
55
55
  root.name = 'myname'
56
56
  root.description = 'some description'
57
- root.number = 12345
57
+ root.number = 12_345
58
58
 
59
59
  subclass = Wrap::SubClass.new
60
60
  subclass.myattr = 'attrvalue'
@@ -27,7 +27,7 @@ describe 'Specifying elements and attributes with an xpath' do
27
27
  has_one :name, String
28
28
  end
29
29
 
30
- let(:subject) { Item.parse(xml_string, single: true) }
30
+ let(:parsed_result) { Item.parse(xml_string, single: true) }
31
31
 
32
32
  let(:xml_string) do
33
33
  %(
@@ -50,41 +50,35 @@ describe 'Specifying elements and attributes with an xpath' do
50
50
  )
51
51
  end
52
52
 
53
- it 'should have a title' do
54
- expect(subject.title).to eq 'Test XML'
53
+ it 'has a title' do
54
+ expect(parsed_result.title).to eq 'Test XML'
55
55
  end
56
56
 
57
- it 'should find the link href value' do
58
- expect(subject.link).to eq 'link_to_resources'
57
+ it 'finds the link href value' do
58
+ expect(parsed_result.link).to eq 'link_to_resources'
59
59
  end
60
60
 
61
- it 'should find the link href value' do
62
- expect(subject.different_link).to eq 'different_link'
61
+ it 'finds the other link href value' do
62
+ expect(parsed_result.different_link).to eq 'different_link'
63
63
  end
64
64
 
65
- it 'should find this subitem based on the xpath' do
66
- expect(subject.detail).to eq 'I want to parse this'
65
+ it 'finds this subitem based on the xpath' do
66
+ expect(parsed_result.detail).to eq 'I want to parse this'
67
67
  end
68
68
 
69
- it 'should find the subitems based on the xpath' do
70
- expect(subject.more_details_text.size).to eq(2)
71
- expect(subject.more_details_text.first).to eq 'more 1'
72
- expect(subject.more_details_text.last).to eq 'more 2'
69
+ it 'finds the subitem texts based on the xpath' do
70
+ expect(parsed_result.more_details_text).to eq ['more 1', 'more 2']
73
71
  end
74
72
 
75
- it 'should find the subitems based on the xpath' do
76
- expect(subject.more_details.size).to eq(2)
77
- expect(subject.more_details.first).to eq 'this one'
78
- expect(subject.more_details.last).to eq 'another one'
73
+ it 'finds the subitem attributes based on the xpath' do
74
+ expect(parsed_result.more_details).to eq ['this one', 'another one']
79
75
  end
80
76
 
81
- it 'should find the subitems based on the xpath' do
82
- expect(subject.more_details_alternative.size).to eq(2)
83
- expect(subject.more_details_alternative.first).to eq 'this one'
84
- expect(subject.more_details_alternative.last).to eq 'another one'
77
+ it 'finds the subitem attributes based on the xpath with a wildcard' do
78
+ expect(parsed_result.more_details_alternative).to eq ['this one', 'another one']
85
79
  end
86
80
 
87
- it 'should have a baby name' do
88
- expect(subject.baby.name).to eq 'Jumbo'
81
+ it 'has a baby name' do
82
+ expect(parsed_result.baby.name).to eq 'Jumbo'
89
83
  end
90
84
  end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe HappyMapper::AnonymousMapper do
6
+ let(:anonymous_mapper) { described_class.new }
7
+
8
+ describe '#parse' do
9
+ context 'when parsing a single root node' do
10
+ let(:parsed_result) { anonymous_mapper.parse fixture_file('address.xml') }
11
+
12
+ it 'creates the correct set of child elements on the element class' do
13
+ elements = parsed_result.class.elements
14
+ expect(elements.map(&:tag)).to eq %w(street housenumber postcode city country state)
15
+ end
16
+
17
+ it 'parses child elements' do
18
+ aggregate_failures do
19
+ expect(parsed_result.street).to eq('Milchstrasse')
20
+ expect(parsed_result.housenumber).to eq('23')
21
+ expect(parsed_result.postcode).to eq('26131')
22
+ expect(parsed_result.city).to eq('Oldenburg')
23
+ end
24
+ end
25
+
26
+ it 'does not create a content entry when the xml contents no text content' do
27
+ expect(parsed_result).not_to respond_to :content
28
+ end
29
+
30
+ it 'parses both the attributes and content when present' do
31
+ aggregate_failures do
32
+ expect(parsed_result.country.code).to eq('de')
33
+ expect(parsed_result.country.content).to eq('Germany')
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'with element names with special characters' do
39
+ let(:parsed_result) { anonymous_mapper.parse fixture_file('ambigous_items.xml') }
40
+
41
+ it 'creates accessor methods with similar names' do
42
+ expect(parsed_result.my_items.item).to be_kind_of Array
43
+ end
44
+ end
45
+
46
+ context 'with element names with camelCased elements and Capital Letters' do
47
+ let(:parsed_result) { anonymous_mapper.parse fixture_file('subclass_namespace.xml') }
48
+
49
+ it 'parses camel-cased child elements correctly' do
50
+ aggregate_failures do
51
+ expect(parsed_result.photo.publish_options.author).to eq('Stephanie')
52
+ expect(parsed_result.gallery.photo.title).to eq('photo title')
53
+ end
54
+ end
55
+
56
+ it 'parses camel-cased child properties correctly' do
57
+ expect(parsed_result.publish_options.created_day).to eq('2011-01-14')
58
+ end
59
+ end
60
+
61
+ context 'with repeated elements with camel-cased names' do
62
+ let(:xml) do
63
+ <<~XML
64
+ <foo>
65
+ <fooBar>
66
+ <baz>Hello</baz>
67
+ </fooBar>
68
+ <fooBar>
69
+ <baz>Hi</baz>
70
+ </fooBar>
71
+ </foo>
72
+ XML
73
+ end
74
+ let(:parsed_result) { anonymous_mapper.parse xml }
75
+
76
+ it 'parses the repeated elements correctly' do
77
+ expect(parsed_result.foo_bar.map(&:baz)).to eq %w(Hello Hi)
78
+ end
79
+ end
80
+
81
+ context 'with elements with camelCased attribute names' do
82
+ let(:parsed_result) { anonymous_mapper.parse '<foo barBaz="quuz"/>' }
83
+
84
+ it 'parses attributes correctly' do
85
+ expect(parsed_result.bar_baz).to eq('quuz')
86
+ end
87
+ end
88
+
89
+ context 'with several elements nested deeply' do
90
+ let(:parsed_result) { anonymous_mapper.parse fixture_file('ambigous_items.xml') }
91
+
92
+ it 'parses the entire relationship' do
93
+ expect(parsed_result.my_items.item.first.item.name).to eq('My first internal item')
94
+ end
95
+ end
96
+
97
+ context 'when parsing an that contains multiple elements with the same tag' do
98
+ let(:parsed_result) { anonymous_mapper.parse fixture_file('multiple_primitives.xml') }
99
+
100
+ it "parses the elements as it would a 'has_many'" do
101
+ aggregate_failures do
102
+ expect(parsed_result.name).to eq('value')
103
+ expect(parsed_result.image).to eq(%w(image1 image2))
104
+ end
105
+ end
106
+ end
107
+
108
+ context 'when parsing xml with multiple namespaces' do
109
+ let(:parsed_result) { anonymous_mapper.parse fixture_file('subclass_namespace.xml') }
110
+
111
+ it 'parses the elements an values correctly' do
112
+ expect(parsed_result.title).to eq('article title')
113
+ end
114
+
115
+ it 'parses attribute names correctly' do
116
+ expect(parsed_result.name).to eq 'title'
117
+ end
118
+ end
119
+
120
+ context 'when parsing an element with a nested value element with a different namespace' do
121
+ let(:xml) do
122
+ <<~XML
123
+ <a:foo xmlns:a="http://foo.org/a" xmlns:b="http://foo.org/b">
124
+ <b:bar>Hello</b:bar>
125
+ </a:foo>
126
+ XML
127
+ end
128
+ let(:result) { anonymous_mapper.parse xml }
129
+
130
+ it 'parses the value elements correctly' do
131
+ expect(result.bar).to eq 'Hello'
132
+ end
133
+ end
134
+
135
+ context 'when parsing xml that uses the same tag for string and other elements' do
136
+ let(:xml) do
137
+ <<~XML
138
+ <foo>
139
+ <bar>
140
+ <baz>Hello</baz>
141
+ </bar>
142
+ <baz>
143
+ <qux>Hi</qux>
144
+ </baz>
145
+ </foo>
146
+ XML
147
+ end
148
+ let(:result) { anonymous_mapper.parse xml }
149
+
150
+ it 'parses both occurences of the tag correctly' do
151
+ aggregate_failures do
152
+ expect(result.bar.baz).to eq 'Hello'
153
+ expect(result.baz.qux).to eq 'Hi'
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end