nokogiri-happymapper 0.8.1 → 0.9.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 +7 -0
- data/README.md +0 -3
- data/lib/happymapper/element.rb +2 -2
- data/lib/happymapper/supported_types.rb +3 -5
- data/lib/happymapper/version.rb +1 -1
- data/lib/happymapper.rb +44 -52
- metadata +98 -107
- data/spec/features/after_parse_callbacks_spec.rb +0 -32
- data/spec/features/attribute_default_value_spec.rb +0 -48
- data/spec/features/attributes_spec.rb +0 -35
- data/spec/features/has_many_empty_array_spec.rb +0 -44
- data/spec/features/ignay_spec.rb +0 -92
- data/spec/features/inheritance_spec.rb +0 -121
- data/spec/features/mixed_namespaces_spec.rb +0 -60
- data/spec/features/parse_with_object_to_update_spec.rb +0 -116
- data/spec/features/same_tag_different_meaning_spec.rb +0 -44
- data/spec/features/to_xml_spec.rb +0 -205
- data/spec/features/to_xml_with_namespaces_spec.rb +0 -237
- data/spec/features/wildcard_tag_name_spec.rb +0 -110
- data/spec/features/wrap_spec.rb +0 -87
- data/spec/features/xpath_spec.rb +0 -84
- data/spec/fixtures/address.xml +0 -9
- data/spec/fixtures/ambigous_items.xml +0 -22
- data/spec/fixtures/analytics.xml +0 -61
- data/spec/fixtures/analytics_profile.xml +0 -127
- data/spec/fixtures/atom.xml +0 -19
- data/spec/fixtures/commit.xml +0 -52
- data/spec/fixtures/current_weather.xml +0 -89
- data/spec/fixtures/current_weather_missing_elements.xml +0 -18
- data/spec/fixtures/default_namespace_combi.xml +0 -6
- data/spec/fixtures/dictionary.xml +0 -20
- data/spec/fixtures/family_tree.xml +0 -21
- data/spec/fixtures/inagy.xml +0 -85
- data/spec/fixtures/lastfm.xml +0 -355
- data/spec/fixtures/multiple_namespaces.xml +0 -170
- data/spec/fixtures/multiple_primitives.xml +0 -5
- data/spec/fixtures/optional_attributes.xml +0 -6
- data/spec/fixtures/pita.xml +0 -133
- data/spec/fixtures/posts.xml +0 -23
- data/spec/fixtures/product_default_namespace.xml +0 -18
- data/spec/fixtures/product_no_namespace.xml +0 -10
- data/spec/fixtures/product_single_namespace.xml +0 -10
- data/spec/fixtures/quarters.xml +0 -19
- data/spec/fixtures/radar.xml +0 -21
- data/spec/fixtures/set_config_options.xml +0 -3
- data/spec/fixtures/statuses.xml +0 -422
- data/spec/fixtures/subclass_namespace.xml +0 -50
- data/spec/fixtures/unformatted_address.xml +0 -1
- data/spec/fixtures/wrapper.xml +0 -11
- data/spec/happymapper/anonymous_mapper_spec.rb +0 -158
- data/spec/happymapper/attribute_spec.rb +0 -12
- data/spec/happymapper/item_spec.rb +0 -177
- data/spec/happymapper_spec.rb +0 -1208
- data/spec/spec_helper.rb +0 -25
@@ -1,158 +0,0 @@
|
|
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
|
@@ -1,12 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe HappyMapper::Attribute do
|
6
|
-
describe 'initialization' do
|
7
|
-
it 'accepts :default option' do
|
8
|
-
attr = described_class.new(:foo, String, default: 'foobar')
|
9
|
-
expect(attr.default).to eq('foobar')
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
@@ -1,177 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Foo
|
6
|
-
class Bar; end
|
7
|
-
end
|
8
|
-
|
9
|
-
describe HappyMapper::Item do
|
10
|
-
describe 'new instance' do
|
11
|
-
before do
|
12
|
-
@item = described_class.new(:foo, String, tag: 'foobar')
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'accepts a name' do
|
16
|
-
expect(@item.name).to eq('foo')
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'accepts a type' do
|
20
|
-
expect(@item.type).to eq(String)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'accepts :tag as an option' do
|
24
|
-
expect(@item.tag).to eq('foobar')
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'has a method_name' do
|
28
|
-
expect(@item.method_name).to eq('foo')
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#constant' do
|
33
|
-
it 'justs use type if constant' do
|
34
|
-
item = described_class.new(:foo, String)
|
35
|
-
expect(item.constant).to eq(String)
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'converts string type to constant' do
|
39
|
-
item = described_class.new(:foo, 'String')
|
40
|
-
expect(item.constant).to eq(String)
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'converts string with :: to constant' do
|
44
|
-
item = described_class.new(:foo, 'Foo::Bar')
|
45
|
-
expect(item.constant).to eq(Foo::Bar)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe '#method_name' do
|
50
|
-
it 'converts dashes to underscores' do
|
51
|
-
item = described_class.new(:'foo-bar', String, tag: 'foobar')
|
52
|
-
expect(item.method_name).to eq('foo_bar')
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe '#xpath' do
|
57
|
-
it 'defaults to tag' do
|
58
|
-
item = described_class.new(:foo, String, tag: 'foobar')
|
59
|
-
expect(item.xpath).to eq('foobar')
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'prepends with .// if options[:deep] true' do
|
63
|
-
item = described_class.new(:foo, String, tag: 'foobar', deep: true)
|
64
|
-
expect(item.xpath).to eq('.//foobar')
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'prepends namespace if namespace exists' do
|
68
|
-
item = described_class.new(:foo, String, tag: 'foobar')
|
69
|
-
item.namespace = 'v2'
|
70
|
-
expect(item.xpath).to eq('v2:foobar')
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe 'typecasting' do
|
75
|
-
it 'works with Strings' do
|
76
|
-
item = described_class.new(:foo, String)
|
77
|
-
[21, '21'].each do |a|
|
78
|
-
expect(item.typecast(a)).to eq('21')
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'with Integers' do
|
83
|
-
let(:item) { described_class.new(:foo, Integer) }
|
84
|
-
|
85
|
-
it 'works with an integer' do
|
86
|
-
expect(item.typecast(21)).to eq 21
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'works with a float' do
|
90
|
-
expect(item.typecast(21.0)).to eq 21
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'works with a string' do
|
94
|
-
expect(item.typecast('21')).to eq 21
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'works with a string with trailing characters' do
|
98
|
-
expect(item.typecast('21foo')).to eq 21
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'works with a string with zero plus trailing characters' do
|
102
|
-
expect(item.typecast('0foo')).to eq 0
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'handles a non-numeric string' do
|
106
|
-
expect(item.typecast('foo')).to be_nil
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'handles an empty string' do
|
110
|
-
expect(item.typecast('')).to be_nil
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'handles nil' do
|
114
|
-
expect(item.typecast(nil)).to be_nil
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'works with Floats' do
|
119
|
-
item = described_class.new(:foo, Float)
|
120
|
-
[21, 21.0, '21'].each do |a|
|
121
|
-
expect(item.typecast(a)).to eq 21.0
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'works with Times' do
|
126
|
-
item = described_class.new(:foo, Time)
|
127
|
-
expect(item.typecast('2000-01-01 01:01:01.123456')).to eq(Time.local(2000, 1, 1, 1, 1, 1, 123_456))
|
128
|
-
end
|
129
|
-
|
130
|
-
context 'with Date' do
|
131
|
-
let(:item) { described_class.new(:foo, Date) }
|
132
|
-
|
133
|
-
it 'works with a string' do
|
134
|
-
expect(item.typecast('2000-01-01')).to eq(Date.new(2000, 1, 1))
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'handles nil' do
|
138
|
-
expect(item.typecast(nil)).to be_nil
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'handles empty string' do
|
142
|
-
expect(item.typecast('')).to eq(nil)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
context 'with DateTime' do
|
147
|
-
let(:item) { described_class.new(:foo, DateTime) }
|
148
|
-
|
149
|
-
it 'works with a string' do
|
150
|
-
result = item.typecast('2000-01-01 13:42:37')
|
151
|
-
expect(result.to_time).to eq Time.new(2000, 1, 1, 13, 42, 37, '+00:00')
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'works with a historical date in a string' do
|
155
|
-
result = item.typecast('1616-04-23')
|
156
|
-
|
157
|
-
aggregate_failures do
|
158
|
-
expect(result.to_time).to eq Time.new(1616, 4, 23, 0, 0, 0, '+00:00')
|
159
|
-
expect(result).to be_gregorian
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'handles nil' do
|
164
|
-
expect(item.typecast(nil)).to eq(nil)
|
165
|
-
end
|
166
|
-
|
167
|
-
it 'handles empty strings' do
|
168
|
-
expect(item.typecast('')).to eq(nil)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'works with Boolean' do
|
173
|
-
item = described_class.new(:foo, HappyMapper::Boolean)
|
174
|
-
expect(item.typecast('false')).to eq(false)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|