lutaml-model 0.3.29 → 0.4.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/.github/workflows/dependent-repos.json +15 -0
- data/.github/workflows/dependent-tests.yml +14 -0
- data/.rubocop_todo.yml +15 -7
- data/README.adoc +6 -0
- data/lib/lutaml/model/attribute.rb +6 -2
- data/lib/lutaml/model/json_adapter/json_document.rb +1 -1
- data/lib/lutaml/model/json_adapter/multi_json_adapter.rb +1 -1
- data/lib/lutaml/model/json_adapter/standard_json_adapter.rb +1 -1
- data/lib/lutaml/model/serialize.rb +133 -33
- data/lib/lutaml/model/toml_adapter/toml_document.rb +1 -1
- data/lib/lutaml/model/toml_adapter/toml_rb_adapter.rb +1 -1
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +1 -1
- data/lib/lutaml/model/type/time.rb +4 -4
- data/lib/lutaml/model/utils.rb +1 -1
- data/lib/lutaml/model/validation.rb +6 -2
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +10 -0
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +5 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +5 -3
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +25 -10
- data/lib/lutaml/model/xml_adapter/xml_document.rb +12 -24
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +1 -1
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +1 -1
- data/spec/fixtures/xml/latin_encoding.xml +5 -0
- data/spec/fixtures/xml/shift_jis.xml +4 -0
- data/spec/lutaml/model/custom_serialization_spec.rb +16 -0
- data/spec/lutaml/model/defaults_spec.rb +74 -0
- data/spec/lutaml/model/enum_spec.rb +131 -0
- data/spec/lutaml/model/mixed_content_spec.rb +190 -7
- data/spec/lutaml/model/render_nil_spec.rb +0 -2
- data/spec/lutaml/model/serializable_spec.rb +2 -2
- data/spec/lutaml/model/xml_mapping_spec.rb +679 -543
- metadata +7 -2
@@ -6,23 +6,28 @@ module Lutaml
|
|
6
6
|
module Model
|
7
7
|
module XmlAdapter
|
8
8
|
class OxAdapter < XmlDocument
|
9
|
-
def self.parse(xml)
|
9
|
+
def self.parse(xml, options = {})
|
10
|
+
Ox.default_options = Ox.default_options.merge(encoding: options[:encoding] || "UTF-8")
|
11
|
+
|
10
12
|
parsed = Ox.parse(xml)
|
11
13
|
root = OxElement.new(parsed)
|
12
|
-
new(root)
|
14
|
+
new(root, Ox.default_options[:encoding])
|
13
15
|
end
|
14
16
|
|
15
17
|
def to_xml(options = {})
|
16
|
-
builder = Builder::Ox.build
|
17
18
|
builder_options = { version: options[:version] }
|
18
19
|
|
19
|
-
if options.key?(:encoding)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
builder_options[:encoding] = if options.key?(:encoding)
|
21
|
+
options[:encoding]
|
22
|
+
elsif options.key?(:parse_encoding)
|
23
|
+
options[:parse_encoding]
|
24
|
+
else
|
25
|
+
"UTF-8"
|
26
|
+
end
|
27
|
+
|
28
|
+
builder = Builder::Ox.build
|
29
|
+
builder.xml.instruct(:xml, encoding: options[:parse_encoding])
|
24
30
|
|
25
|
-
builder.xml.instruct(:xml, builder_options)
|
26
31
|
if @root.is_a?(Lutaml::Model::XmlAdapter::OxElement)
|
27
32
|
@root.build_xml(builder)
|
28
33
|
elsif ordered?(@root, options)
|
@@ -34,7 +39,12 @@ module Lutaml
|
|
34
39
|
end
|
35
40
|
|
36
41
|
xml_data = builder.xml.to_s
|
37
|
-
|
42
|
+
if builder_options[:encoding] && xml_data.valid_encoding?
|
43
|
+
xml_data = xml_data.encode(builder_options[:encoding])
|
44
|
+
end
|
45
|
+
|
46
|
+
stripped_data = xml_data.lines.drop(1).join
|
47
|
+
options[:declaration] ? declaration(options) + stripped_data : stripped_data
|
38
48
|
end
|
39
49
|
|
40
50
|
private
|
@@ -145,6 +155,11 @@ module Lutaml
|
|
145
155
|
build_xml.xml.to_s
|
146
156
|
end
|
147
157
|
|
158
|
+
def inner_xml
|
159
|
+
# Ox builder by default, adds a newline at the end, so `chomp` is used
|
160
|
+
children.map { |child| child.to_xml.chomp }.join
|
161
|
+
end
|
162
|
+
|
148
163
|
def build_xml(builder = nil)
|
149
164
|
builder ||= Builder::Ox.build
|
150
165
|
attrs = build_attributes(self)
|
@@ -7,13 +7,14 @@ module Lutaml
|
|
7
7
|
module Model
|
8
8
|
module XmlAdapter
|
9
9
|
class XmlDocument
|
10
|
-
attr_reader :root
|
10
|
+
attr_reader :root, :encoding
|
11
11
|
|
12
|
-
def initialize(root)
|
12
|
+
def initialize(root, encoding = nil)
|
13
13
|
@root = root
|
14
|
+
@encoding = encoding
|
14
15
|
end
|
15
16
|
|
16
|
-
def self.parse(xml)
|
17
|
+
def self.parse(xml, _options = {})
|
17
18
|
raise NotImplementedError, "Subclasses must implement `parse`."
|
18
19
|
end
|
19
20
|
|
@@ -150,6 +151,8 @@ module Lutaml
|
|
150
151
|
value,
|
151
152
|
options.merge({ rule: rule, attribute: attribute }),
|
152
153
|
)
|
154
|
+
elsif rule.raw_mapping?
|
155
|
+
xml.add_xml_fragment(xml, value)
|
153
156
|
elsif rule.prefix_set?
|
154
157
|
xml.create_and_add_element(rule.name, prefix: prefix) do
|
155
158
|
add_value(xml, value, attribute, cdata: rule.cdata)
|
@@ -186,10 +189,6 @@ module Lutaml
|
|
186
189
|
attributes = build_attributes(element,
|
187
190
|
xml_mapping, options).merge(attributes)&.compact
|
188
191
|
|
189
|
-
if element.respond_to?(:schema_location) && element.schema_location
|
190
|
-
attributes.merge!(element.schema_location.to_xml_attributes)
|
191
|
-
end
|
192
|
-
|
193
192
|
prefix = if options.key?(:namespace_prefix)
|
194
193
|
options[:namespace_prefix]
|
195
194
|
elsif xml_mapping.namespace_prefix
|
@@ -210,7 +209,8 @@ module Lutaml
|
|
210
209
|
xml)
|
211
210
|
end
|
212
211
|
|
213
|
-
xml_mapping.elements
|
212
|
+
mappings = xml_mapping.elements + [xml_mapping.raw_mapping].compact
|
213
|
+
mappings.each do |element_rule|
|
214
214
|
attribute_def = attribute_definition_for(element, element_rule,
|
215
215
|
mapper_class: mapper_class)
|
216
216
|
|
@@ -234,20 +234,9 @@ module Lutaml
|
|
234
234
|
|
235
235
|
process_content_mapping(element, xml_mapping.content_mapping,
|
236
236
|
prefixed_xml)
|
237
|
-
|
238
|
-
process_raw_mapping(element, xml_mapping.raw_mapping, prefixed_xml)
|
239
237
|
end
|
240
238
|
end
|
241
239
|
|
242
|
-
def process_raw_mapping(element, rule, xml)
|
243
|
-
return unless rule
|
244
|
-
|
245
|
-
value = attribute_value_for(element, rule)
|
246
|
-
return unless render_element?(rule, element, value)
|
247
|
-
|
248
|
-
xml.add_text(xml, value, cdata: rule.cdata)
|
249
|
-
end
|
250
|
-
|
251
240
|
def process_content_mapping(element, content_rule, xml)
|
252
241
|
return unless content_rule
|
253
242
|
|
@@ -343,7 +332,7 @@ module Lutaml
|
|
343
332
|
{}
|
344
333
|
end
|
345
334
|
|
346
|
-
if element.respond_to?(:schema_location) && element.schema_location
|
335
|
+
if element.respond_to?(:schema_location) && element.schema_location && !options[:except]&.include?(:schema_location)
|
347
336
|
attrs.merge!(element.schema_location.to_xml_attributes)
|
348
337
|
end
|
349
338
|
|
@@ -355,10 +344,9 @@ module Lutaml
|
|
355
344
|
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
356
345
|
end
|
357
346
|
|
358
|
-
|
359
|
-
|
360
|
-
hash[mapping_rule.prefixed_name] =
|
361
|
-
mapping_rule.to_value_for(element)
|
347
|
+
value = mapping_rule.to_value_for(element)
|
348
|
+
if render_element?(mapping_rule, element, value)
|
349
|
+
hash[mapping_rule.prefixed_name] = value ? value.to_s : value
|
362
350
|
end
|
363
351
|
end
|
364
352
|
|
@@ -138,6 +138,22 @@ RSpec.describe CustomSerialization do
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
+
context "with partial JSON input" do
|
142
|
+
it "deserializes from JSON with missing attributes" do
|
143
|
+
json = {
|
144
|
+
name: "JSON Masterpiece: Vase",
|
145
|
+
color: "BLUE",
|
146
|
+
}.to_json
|
147
|
+
|
148
|
+
ceramic = described_class.from_json(json)
|
149
|
+
|
150
|
+
expect(ceramic.full_name).to eq("Vase")
|
151
|
+
expect(ceramic.color).to eq("blue")
|
152
|
+
expect(ceramic.size).to be_nil
|
153
|
+
expect(ceramic.description).to be_nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
141
157
|
context "with XML serialization" do
|
142
158
|
it "serializes to XML with custom methods" do
|
143
159
|
expected_xml = <<~XML
|
@@ -105,6 +105,29 @@ module DefaultsSpec
|
|
105
105
|
map "opacity", to: :opacity, render_default: false
|
106
106
|
end
|
107
107
|
end
|
108
|
+
|
109
|
+
# Class for testing render_default: true with custom model
|
110
|
+
class Lang
|
111
|
+
attr_accessor :lang, :content
|
112
|
+
end
|
113
|
+
|
114
|
+
class CustomModelWithDefaultValue < Lutaml::Model::Serializable
|
115
|
+
model Lang
|
116
|
+
|
117
|
+
attribute :lang, :string, default: -> { "en" }
|
118
|
+
attribute :content, :string, default: -> { "default value not render when render_default is false" }
|
119
|
+
|
120
|
+
xml do
|
121
|
+
root "CustomModelWithDefaultValue"
|
122
|
+
map_attribute "lang", to: :lang, render_default: true
|
123
|
+
map_content to: :content, render_default: false
|
124
|
+
end
|
125
|
+
|
126
|
+
key_value do
|
127
|
+
map "lang", to: :lang, render_default: true
|
128
|
+
map "content", to: :content, render_default: false
|
129
|
+
end
|
130
|
+
end
|
108
131
|
end
|
109
132
|
|
110
133
|
RSpec.describe DefaultsSpec::Glaze do
|
@@ -125,6 +148,13 @@ RSpec.describe DefaultsSpec::Glaze do
|
|
125
148
|
expect(default_model.manufacturer).to eq("example@glazes.com")
|
126
149
|
expect(default_model.type).to eq("stoneware")
|
127
150
|
end
|
151
|
+
|
152
|
+
it "contains the default value in instance" do
|
153
|
+
instance = DefaultsSpec::CustomModelWithDefaultValue.new
|
154
|
+
|
155
|
+
expect(instance.content).to eq("default value not render when render_default is false")
|
156
|
+
expect(instance.lang).to eq("en")
|
157
|
+
end
|
128
158
|
end
|
129
159
|
|
130
160
|
describe "Default value rendering behavior" do
|
@@ -155,6 +185,15 @@ RSpec.describe DefaultsSpec::Glaze do
|
|
155
185
|
expect(xml).to include("<Opacity>Opaque</Opacity>")
|
156
186
|
expect(xml).to include("<FiringTime>60</FiringTime>")
|
157
187
|
end
|
188
|
+
|
189
|
+
it "serializes when render_default is true with custom model" do
|
190
|
+
parsed = DefaultsSpec::CustomModelWithDefaultValue.from_xml "<CustomModelWithDefaultValue>English</CustomModelWithDefaultValue>"
|
191
|
+
expect(parsed.lang).to eq("en")
|
192
|
+
expect(parsed.content).to eq("English")
|
193
|
+
|
194
|
+
serialized = DefaultsSpec::CustomModelWithDefaultValue.to_xml(parsed)
|
195
|
+
expect(serialized).to eq("<CustomModelWithDefaultValue lang=\"en\">English</CustomModelWithDefaultValue>")
|
196
|
+
end
|
158
197
|
end
|
159
198
|
|
160
199
|
context "when value is not default" do
|
@@ -200,6 +239,15 @@ RSpec.describe DefaultsSpec::Glaze do
|
|
200
239
|
expect(json["opacity"]).to eq("Opaque")
|
201
240
|
expect(json["firingTime"]).to eq(60)
|
202
241
|
end
|
242
|
+
|
243
|
+
it "serializes when render_default is true with custom model" do
|
244
|
+
parsed = DefaultsSpec::CustomModelWithDefaultValue.from_json('{"content": "content"}')
|
245
|
+
expect(parsed.lang).to eq("en")
|
246
|
+
expect(parsed.content).to eq("content")
|
247
|
+
|
248
|
+
serialized = DefaultsSpec::CustomModelWithDefaultValue.to_json(parsed)
|
249
|
+
expect(serialized).to eq('{"lang":"en","content":"content"}')
|
250
|
+
end
|
203
251
|
end
|
204
252
|
|
205
253
|
context "when value is not default" do
|
@@ -217,5 +265,31 @@ RSpec.describe DefaultsSpec::Glaze do
|
|
217
265
|
end
|
218
266
|
end
|
219
267
|
end
|
268
|
+
|
269
|
+
context "with YAML serialization" do
|
270
|
+
context "when value is default" do
|
271
|
+
it "serializes when render_default is true with custom model" do
|
272
|
+
parsed = DefaultsSpec::CustomModelWithDefaultValue.from_yaml("---\ncontent: content")
|
273
|
+
expect(parsed.lang).to eq("en")
|
274
|
+
expect(parsed.content).to eq("content")
|
275
|
+
|
276
|
+
serialized = DefaultsSpec::CustomModelWithDefaultValue.to_yaml(parsed)
|
277
|
+
expect(serialized).to eq("---\nlang: en\ncontent: content\n")
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "with TOML serialization" do
|
283
|
+
context "when value is default" do
|
284
|
+
it "serializes when render_default is true with custom model" do
|
285
|
+
parsed = DefaultsSpec::CustomModelWithDefaultValue.from_toml("content = 'content'")
|
286
|
+
expect(parsed.lang).to eq("en")
|
287
|
+
expect(parsed.content).to eq("content")
|
288
|
+
|
289
|
+
serialized = DefaultsSpec::CustomModelWithDefaultValue.to_toml(parsed)
|
290
|
+
expect(serialized).to eq("content = \"content\"\nlang = \"en\"\n")
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
220
294
|
end
|
221
295
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "lutaml/model"
|
3
|
+
|
4
|
+
module EnumSpec
|
5
|
+
class WithEnum < Lutaml::Model::Serializable
|
6
|
+
attribute :without_enum, :string
|
7
|
+
attribute :single_value, :string, values: %w[user admin super_admin]
|
8
|
+
attribute :multi_value, :string, values: %w[singular dual plural], collection: true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec.describe "Enum" do
|
13
|
+
let(:single_value_attr) do
|
14
|
+
EnumSpec::WithEnum.attributes[:single_value]
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:multi_value_attr) do
|
18
|
+
EnumSpec::WithEnum.attributes[:multi_value]
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:without_enum_attr) do
|
22
|
+
EnumSpec::WithEnum.attributes[:without_enum]
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:object) do
|
26
|
+
EnumSpec::WithEnum.new
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when values are provided for an attribute" do
|
30
|
+
it "is marked as enum for single_value" do
|
31
|
+
expect(single_value_attr.enum?).to be(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "is marked as enum for multi_value" do
|
35
|
+
expect(multi_value_attr.enum?).to be(true)
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with enum convinience methods" do
|
39
|
+
describe "#single_value" do
|
40
|
+
it "returns single value" do
|
41
|
+
expect { object.single_value = "user" }
|
42
|
+
.to change(object, :single_value)
|
43
|
+
.from(nil)
|
44
|
+
.to("user")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#multi_value" do
|
49
|
+
it "returns single value in array" do
|
50
|
+
expect { object.multi_value = "dual" }
|
51
|
+
.to change(object, :multi_value)
|
52
|
+
.from([])
|
53
|
+
.to(["dual"])
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns multiple value in array" do
|
57
|
+
expect { object.multi_value = %w[dual plural] }
|
58
|
+
.to change(object, :multi_value)
|
59
|
+
.from([])
|
60
|
+
.to(%w[dual plural])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
EnumSpec::WithEnum.enums.each_value do |enum_attr|
|
65
|
+
enum_attr.enum_values.each do |value|
|
66
|
+
describe "##{value}=" do
|
67
|
+
it "sets the #{value} if true" do
|
68
|
+
expect { object.public_send(:"#{value}=", true) }
|
69
|
+
.to change { object.public_send(:"#{value}?") }
|
70
|
+
.from(false)
|
71
|
+
.to(true)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "unsets the #{value} if false" do
|
75
|
+
object.public_send(:"#{value}=", true)
|
76
|
+
|
77
|
+
expect { object.public_send(:"#{value}=", false) }
|
78
|
+
.to change(object, "#{value}?")
|
79
|
+
.from(true)
|
80
|
+
.to(false)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "##{value}!" do
|
85
|
+
it "method #{value}? should be present" do
|
86
|
+
expect(object.respond_to?(:"#{value}!")).to be(true)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "sets #{value} to true for enum" do
|
90
|
+
expect { object.public_send(:"#{value}!") }
|
91
|
+
.to change(object, "#{value}?")
|
92
|
+
.from(false)
|
93
|
+
.to(true)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "##{value}?" do
|
98
|
+
it "method #{value}? should be present" do
|
99
|
+
expect(object.respond_to?(:"#{value}?")).to be(true)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "is false if role is not #{value}" do
|
103
|
+
expect(object.public_send(:"#{value}?")).to be(false)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "is true if role is set to #{value}" do
|
107
|
+
expect { object.public_send(:"#{value}=", value) }
|
108
|
+
.to change(object, "#{value}?")
|
109
|
+
.from(false)
|
110
|
+
.to(true)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it "adds a method named #{value}=" do
|
115
|
+
expect(object.respond_to?(:"#{value}?")).to be(true)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "adds a method named #{value}!" do
|
119
|
+
expect(object.respond_to?(:"#{value}!")).to be(true)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when values are not provided for an attribute" do
|
127
|
+
it "is not marked as enum" do
|
128
|
+
expect(without_enum_attr.enum?).to be(false)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -72,6 +72,28 @@ module MixedContentSpec
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
+
class Latin < Lutaml::Model::Serializable
|
76
|
+
attribute :the, :string
|
77
|
+
attribute :from, :string
|
78
|
+
attribute :heading, :string
|
79
|
+
|
80
|
+
xml do
|
81
|
+
root "note"
|
82
|
+
map_element "to", to: :the
|
83
|
+
map_element "from", to: :from
|
84
|
+
map_element "heading", to: :heading
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Shift < Lutaml::Model::Serializable
|
89
|
+
attribute :field, :string, collection: true
|
90
|
+
|
91
|
+
xml do
|
92
|
+
root "root"
|
93
|
+
map_element "FieldName", to: :field
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
75
97
|
class SpecialCharContentWithMixedTrue < Lutaml::Model::Serializable
|
76
98
|
attribute :content, :string
|
77
99
|
|
@@ -651,24 +673,185 @@ RSpec.describe "MixedContent" do
|
|
651
673
|
|
652
674
|
context "when encoding: nil xml" do
|
653
675
|
let(:expected_encoding_nil_nokogiri_xml) { "∑computer security∏ type of ​ operation specified µ by an access right" }
|
654
|
-
let(:expected_encoding_nil_ox_xml) { "
|
676
|
+
let(:expected_encoding_nil_ox_xml) { "∑computer security∏ type of operation specified µ by an access right" }
|
655
677
|
|
656
678
|
it "serializes special char mixed content correctly with encoding: nil to get hexcode" do
|
657
679
|
parsed = MixedContentSpec::HexCode.from_xml(xml)
|
658
680
|
serialized = parsed.to_xml(encoding: nil)
|
659
681
|
|
660
|
-
if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
end
|
682
|
+
expected_output = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
683
|
+
expected_encoding_nil_ox_xml
|
684
|
+
else
|
685
|
+
expected_encoding_nil_nokogiri_xml
|
686
|
+
end
|
666
687
|
|
667
688
|
expect(serialized.strip).to include(expected_output)
|
668
689
|
end
|
669
690
|
end
|
670
691
|
end
|
671
692
|
end
|
693
|
+
|
694
|
+
context "when use encoding in parsing" do
|
695
|
+
context "when use SHIFT-JIS encoding" do
|
696
|
+
let(:fixture) { File.read(fixture_path("xml/shift_jis.xml"), encoding: "Shift_JIS") }
|
697
|
+
|
698
|
+
describe ".from_xml" do
|
699
|
+
it "verifies the encoding of file read" do
|
700
|
+
expect(fixture.encoding.to_s).to eq("Shift_JIS")
|
701
|
+
end
|
702
|
+
|
703
|
+
it "deserializes SHIFT encoded content correctly with explicit encoding option" do
|
704
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture, encoding: "Shift_JIS")
|
705
|
+
|
706
|
+
expected_content = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
707
|
+
"\x8E\xE8\x8F\x91\x82\xAB\x89p\x8E\x9A\x82P".force_encoding("Shift_JIS")
|
708
|
+
else
|
709
|
+
"手書き英字1"
|
710
|
+
end
|
711
|
+
|
712
|
+
expect(parsed.field).to include(expected_content)
|
713
|
+
end
|
714
|
+
|
715
|
+
it "deserializes SHIFT encoded content incorrectly without explicit encoding option" do
|
716
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture)
|
717
|
+
|
718
|
+
expected_content = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
719
|
+
"\x8E\xE8\x8F\x91\x82\xAB\x89p\x8E\x9A\x82P".force_encoding("UTF-8")
|
720
|
+
else
|
721
|
+
"�菑���p���P"
|
722
|
+
end
|
723
|
+
|
724
|
+
expect(parsed.field).to include(expected_content)
|
725
|
+
end
|
726
|
+
end
|
727
|
+
|
728
|
+
describe ".to_xml" do
|
729
|
+
it "serializes SHIFT-JIS encoding content correctly reading from file" do
|
730
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture, encoding: "Shift_JIS")
|
731
|
+
serialized = parsed.to_xml
|
732
|
+
|
733
|
+
expect(serialized.strip).to eq(fixture.strip)
|
734
|
+
end
|
735
|
+
|
736
|
+
it "serializes SHIFT encoded content correctly with explicit encoding option both in parsing and deserializing" do
|
737
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture, encoding: "Shift_JIS")
|
738
|
+
serialized = parsed.to_xml(encoding: "UTF-8")
|
739
|
+
|
740
|
+
expected_xml = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
741
|
+
"\x8E\xE8\x8F\x91\x82\xAB\x89p\x8E\x9A\x82P".force_encoding("Shift_JIS")
|
742
|
+
else
|
743
|
+
"手書き英字1"
|
744
|
+
end
|
745
|
+
|
746
|
+
expect(parsed.field).to include(expected_xml)
|
747
|
+
expect(parsed.encoding).to eq("Shift_JIS")
|
748
|
+
|
749
|
+
expect(serialized).to include("手書き英字1")
|
750
|
+
expect(serialized.encoding.to_s).to eq("UTF-8")
|
751
|
+
end
|
752
|
+
|
753
|
+
it "serializes SHIFT encoded content correctly with explicit encoding option" do
|
754
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture, encoding: "Shift_JIS")
|
755
|
+
serialized = parsed.to_xml(encoding: "Shift_JIS")
|
756
|
+
|
757
|
+
expected_xml = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
758
|
+
"\x8E\xE8\x8F\x91\x82\xAB\x89p\x8E\x9A\x82P".force_encoding("Shift_JIS")
|
759
|
+
else
|
760
|
+
"手書き英字1"
|
761
|
+
end
|
762
|
+
|
763
|
+
expect(parsed.field).to include(expected_xml)
|
764
|
+
expect(parsed.encoding).to eq("Shift_JIS")
|
765
|
+
|
766
|
+
expect(serialized).to include("\x8E\xE8\x8F\x91\x82\xAB\x89p\x8E\x9A\x82P".force_encoding("Shift_JIS"))
|
767
|
+
expect(serialized.encoding.to_s).to eq("Shift_JIS")
|
768
|
+
end
|
769
|
+
|
770
|
+
it "serializes SHIFT encoded content correctly with declaration: true" do
|
771
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture, encoding: "Shift_JIS")
|
772
|
+
serialized = parsed.to_xml(declaration: true, encoding: "Shift_JIS")
|
773
|
+
|
774
|
+
expected_xml = "<?xml version=\"1.0\" encoding=\"Shift_JIS\"?>\n<root>\n <FieldName>\x8E\xE8\x8F\x91\x82\xAB\x89p\x8E\x9A\x82P</FieldName>\n <FieldName>123456</FieldName>\n</root>"
|
775
|
+
|
776
|
+
expect(serialized).to be_equivalent_to(expected_xml)
|
777
|
+
expect(serialized.encoding.to_s).to eq("Shift_JIS")
|
778
|
+
end
|
779
|
+
|
780
|
+
it "serializes SHIFT-JIS content incorrectly bcz no encoding provided during parsing" do
|
781
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture)
|
782
|
+
serialized = parsed.to_xml(encoding: "Shift_JIS")
|
783
|
+
|
784
|
+
expected_content = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
785
|
+
"<root>\n <FieldName>\x8E菑\x82\xAB\x89p\x8E\x9A\x82P</FieldName>\n <FieldName>123456</FieldName>\n</root>\n"
|
786
|
+
else
|
787
|
+
"<root>\n <FieldName>�菑���p���P</FieldName>\n <FieldName>123456</FieldName>\n</root>"
|
788
|
+
end
|
789
|
+
|
790
|
+
expect(serialized).to eq(expected_content)
|
791
|
+
end
|
792
|
+
|
793
|
+
it "serializes SHIFT-JIS encoding content correctly reading from string" do
|
794
|
+
xml = "<root><FieldName>手書き英字1</FieldName><FieldName>123456</FieldName></root>".encode("Shift_JIS")
|
795
|
+
parsed = MixedContentSpec::Shift.from_xml(xml, encoding: "Shift_JIS")
|
796
|
+
serialized = parsed.to_xml(encoding: "Shift_JIS")
|
797
|
+
|
798
|
+
expect(serialized).to be_equivalent_to(xml)
|
799
|
+
end
|
800
|
+
|
801
|
+
it "serializes SHIFT-JIS encoding content correctly" do
|
802
|
+
parsed = MixedContentSpec::Shift.from_xml(fixture, encoding: "Shift_JIS")
|
803
|
+
serialized = parsed.to_xml(encoding: "Shift_JIS")
|
804
|
+
|
805
|
+
expect(serialized).to be_equivalent_to(fixture)
|
806
|
+
end
|
807
|
+
end
|
808
|
+
end
|
809
|
+
|
810
|
+
context "when use LATIN (ISO-8859-1) encoding" do
|
811
|
+
let(:fixture) { File.read(fixture_path("xml/latin_encoding.xml"), encoding: "ISO-8859-1") }
|
812
|
+
|
813
|
+
describe ".from_xml" do
|
814
|
+
it "verifies the encoding of file read" do
|
815
|
+
expect(fixture.encoding.to_s).to eq("ISO-8859-1")
|
816
|
+
end
|
817
|
+
|
818
|
+
it "deserializes latin encoded content correctly" do
|
819
|
+
parsed = MixedContentSpec::Latin.from_xml(fixture, encoding: "ISO-8859-1")
|
820
|
+
|
821
|
+
expected_content = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
822
|
+
["M\xFCller".force_encoding("ISO-8859-1"), "Jos\xE9".force_encoding("ISO-8859-1")]
|
823
|
+
else
|
824
|
+
["Müller", "José"]
|
825
|
+
end
|
826
|
+
|
827
|
+
expect(parsed.from).to eq(expected_content[0])
|
828
|
+
expect(parsed.the).to eq(expected_content[1])
|
829
|
+
end
|
830
|
+
|
831
|
+
it "deserializes latin encoded content incorrectly" do
|
832
|
+
parsed = MixedContentSpec::Latin.from_xml(fixture)
|
833
|
+
|
834
|
+
expected_content = if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
|
835
|
+
["M\xFCller", "Jos\xE9"]
|
836
|
+
else
|
837
|
+
["M�ller", "Jos�"]
|
838
|
+
end
|
839
|
+
|
840
|
+
expect(parsed.from).to eq(expected_content[0])
|
841
|
+
expect(parsed.the).to eq(expected_content[1])
|
842
|
+
end
|
843
|
+
end
|
844
|
+
|
845
|
+
describe ".to_xml" do
|
846
|
+
it "serializes latin encoded content correctly" do
|
847
|
+
parsed = MixedContentSpec::Latin.from_xml(fixture, encoding: "ISO-8859-1")
|
848
|
+
serialized = parsed.to_xml
|
849
|
+
|
850
|
+
expect(serialized.strip).to eq("<note>\n <to>Jos\xE9</to>\n <from>M\xFCller</from>\n <heading>Reminder</heading>\n</note>".force_encoding("ISO-8859-1"))
|
851
|
+
end
|
852
|
+
end
|
853
|
+
end
|
854
|
+
end
|
672
855
|
end
|
673
856
|
|
674
857
|
describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
|
@@ -68,7 +68,6 @@ RSpec.describe RenderNil do
|
|
68
68
|
name: nil,
|
69
69
|
clay_type: nil,
|
70
70
|
glaze: nil,
|
71
|
-
dimensions: [],
|
72
71
|
}.to_json
|
73
72
|
|
74
73
|
expect(model.to_json).to eq(expected_json)
|
@@ -113,7 +112,6 @@ RSpec.describe RenderNil do
|
|
113
112
|
---
|
114
113
|
name:
|
115
114
|
glaze:
|
116
|
-
dimensions: []
|
117
115
|
YAML
|
118
116
|
|
119
117
|
generated_yaml = model.to_yaml.strip
|