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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -5
- data/README.md +85 -69
- data/lib/happymapper.rb +27 -22
- data/lib/happymapper/anonymous_mapper.rb +35 -30
- data/lib/happymapper/item.rb +1 -1
- data/lib/happymapper/supported_types.rb +2 -7
- data/lib/happymapper/version.rb +1 -1
- data/spec/features/after_parse_callbacks_spec.rb +29 -0
- data/spec/{attribute_default_value_spec.rb → features/attribute_default_value_spec.rb} +3 -3
- data/spec/{attributes_spec.rb → features/attributes_spec.rb} +6 -6
- data/spec/{has_many_empty_array_spec.rb → features/has_many_empty_array_spec.rb} +1 -1
- data/spec/{ignay_spec.rb → features/ignay_spec.rb} +10 -19
- data/spec/{inheritance_spec.rb → features/inheritance_spec.rb} +1 -1
- data/spec/{mixed_namespaces_spec.rb → features/mixed_namespaces_spec.rb} +17 -17
- data/spec/{parse_with_object_to_update_spec.rb → features/parse_with_object_to_update_spec.rb} +0 -0
- data/spec/features/same_tag_different_meaning_spec.rb +44 -0
- data/spec/{to_xml_spec.rb → features/to_xml_spec.rb} +2 -2
- data/spec/{to_xml_with_namespaces_spec.rb → features/to_xml_with_namespaces_spec.rb} +0 -0
- data/spec/{wilcard_tag_name_spec.rb → features/wildcard_tag_name_spec.rb} +5 -5
- data/spec/{wrap_spec.rb → features/wrap_spec.rb} +4 -4
- data/spec/{xpath_spec.rb → features/xpath_spec.rb} +17 -23
- data/spec/happymapper/anonymous_mapper_spec.rb +158 -0
- data/spec/happymapper/element_spec.rb +1 -1
- data/spec/happymapper/item_spec.rb +75 -45
- data/spec/happymapper_spec.rb +120 -125
- metadata +32 -28
- data/spec/happymapper_parse_spec.rb +0 -131
data/lib/happymapper/item.rb
CHANGED
@@ -28,7 +28,7 @@ module HappyMapper
|
|
28
28
|
end
|
29
29
|
|
30
30
|
#
|
31
|
-
# @param [
|
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
|
130
|
-
|
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
|
data/lib/happymapper/version.rb
CHANGED
@@ -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).
|
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
|
@@ -39,25 +39,29 @@ class CatalogNode
|
|
39
39
|
end
|
40
40
|
|
41
41
|
describe HappyMapper do
|
42
|
-
|
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 '
|
48
|
+
it 'has the attribute code' do
|
47
49
|
expect(catalog_tree.code).to eq('NLD')
|
48
50
|
end
|
49
51
|
|
50
|
-
it '
|
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
|
-
|
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 '
|
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 '
|
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 '
|
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
|
data/spec/{parse_with_object_to_update_spec.rb → features/parse_with_object_to_update_spec.rb}
RENAMED
File without changes
|
@@ -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
|
File without changes
|
@@ -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 '
|
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 '
|
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 '
|
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 '
|
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 "
|
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
|
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
|
46
|
-
expect { subject.description = 'anything' }.
|
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 =
|
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(:
|
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 '
|
54
|
-
expect(
|
53
|
+
it 'has a title' do
|
54
|
+
expect(parsed_result.title).to eq 'Test XML'
|
55
55
|
end
|
56
56
|
|
57
|
-
it '
|
58
|
-
expect(
|
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 '
|
62
|
-
expect(
|
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 '
|
66
|
-
expect(
|
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 '
|
70
|
-
expect(
|
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 '
|
76
|
-
expect(
|
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 '
|
82
|
-
expect(
|
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 '
|
88
|
-
expect(
|
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
|