lutaml-model 0.7.1 → 0.7.3

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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +49 -48
  4. data/Gemfile +4 -1
  5. data/README.adoc +791 -143
  6. data/RELEASE_NOTES.adoc +346 -0
  7. data/docs/custom_adapters.adoc +144 -0
  8. data/lib/lutaml/model/attribute.rb +17 -11
  9. data/lib/lutaml/model/config.rb +48 -42
  10. data/lib/lutaml/model/error/polymorphic_error.rb +7 -2
  11. data/lib/lutaml/model/format_registry.rb +41 -0
  12. data/lib/lutaml/model/hash/document.rb +11 -0
  13. data/lib/lutaml/model/hash/mapping.rb +19 -0
  14. data/lib/lutaml/model/hash/mapping_rule.rb +9 -0
  15. data/lib/lutaml/model/hash/standard_adapter.rb +17 -0
  16. data/lib/lutaml/model/hash/transform.rb +8 -0
  17. data/lib/lutaml/model/hash.rb +21 -0
  18. data/lib/lutaml/model/json/document.rb +11 -0
  19. data/lib/lutaml/model/json/mapping.rb +19 -0
  20. data/lib/lutaml/model/json/mapping_rule.rb +9 -0
  21. data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
  22. data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
  23. data/lib/lutaml/model/json/transform.rb +8 -0
  24. data/lib/lutaml/model/json.rb +21 -0
  25. data/lib/lutaml/model/key_value_document.rb +27 -0
  26. data/lib/lutaml/model/mapping/key_value_mapping.rb +8 -4
  27. data/lib/lutaml/model/mapping/mapping.rb +13 -0
  28. data/lib/lutaml/model/mapping/mapping_rule.rb +7 -6
  29. data/lib/lutaml/model/serialization_adapter.rb +22 -0
  30. data/lib/lutaml/model/serialize.rb +146 -521
  31. data/lib/lutaml/model/services/logger.rb +54 -0
  32. data/lib/lutaml/model/services/transformer.rb +48 -0
  33. data/lib/lutaml/model/services.rb +2 -0
  34. data/lib/lutaml/model/toml/document.rb +11 -0
  35. data/lib/lutaml/model/toml/mapping.rb +27 -0
  36. data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
  37. data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
  38. data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
  39. data/lib/lutaml/model/toml/transform.rb +8 -0
  40. data/lib/lutaml/model/toml.rb +30 -0
  41. data/lib/lutaml/model/transform/key_value_transform.rb +291 -0
  42. data/lib/lutaml/model/transform/xml_transform.rb +239 -0
  43. data/lib/lutaml/model/transform.rb +78 -0
  44. data/lib/lutaml/model/type/value.rb +6 -9
  45. data/lib/lutaml/model/uninitialized_class.rb +1 -1
  46. data/lib/lutaml/model/utils.rb +30 -0
  47. data/lib/lutaml/model/version.rb +1 -1
  48. data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
  49. data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
  50. data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
  51. data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +6 -7
  52. data/lib/lutaml/model/xml/element.rb +32 -0
  53. data/lib/lutaml/model/xml/mapping.rb +410 -0
  54. data/lib/lutaml/model/xml/mapping_rule.rb +141 -0
  55. data/lib/lutaml/model/xml/nokogiri_adapter.rb +232 -0
  56. data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
  57. data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +3 -1
  58. data/lib/lutaml/model/xml/oga_adapter.rb +171 -0
  59. data/lib/lutaml/model/xml/ox_adapter.rb +215 -0
  60. data/lib/lutaml/model/xml/transform.rb +8 -0
  61. data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
  62. data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +6 -3
  63. data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
  64. data/lib/lutaml/model/xml.rb +31 -0
  65. data/lib/lutaml/model/xml_adapter/element.rb +11 -25
  66. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
  67. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
  68. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
  69. data/lib/lutaml/model/yaml/document.rb +10 -0
  70. data/lib/lutaml/model/yaml/mapping.rb +19 -0
  71. data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
  72. data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
  73. data/lib/lutaml/model/yaml/transform.rb +8 -0
  74. data/lib/lutaml/model/yaml.rb +21 -0
  75. data/lib/lutaml/model.rb +39 -4
  76. data/lutaml-model.gemspec +0 -4
  77. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +4 -4
  78. data/spec/lutaml/model/cdata_spec.rb +7 -7
  79. data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
  80. data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
  81. data/spec/lutaml/model/group_spec.rb +18 -7
  82. data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
  83. data/spec/lutaml/model/json_adapter_spec.rb +6 -6
  84. data/spec/lutaml/model/key_value_mapping_spec.rb +25 -1
  85. data/spec/lutaml/model/mixed_content_spec.rb +24 -24
  86. data/spec/lutaml/model/multiple_mapping_spec.rb +5 -5
  87. data/spec/lutaml/model/ordered_content_spec.rb +6 -6
  88. data/spec/lutaml/model/polymorphic_spec.rb +178 -0
  89. data/spec/lutaml/model/root_mappings_spec.rb +3 -3
  90. data/spec/lutaml/model/schema/xml_compiler_spec.rb +6 -6
  91. data/spec/lutaml/model/serializable_spec.rb +179 -103
  92. data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
  93. data/spec/lutaml/model/toml_spec.rb +51 -0
  94. data/spec/lutaml/model/transformation_spec.rb +72 -15
  95. data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
  96. data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
  97. data/spec/lutaml/model/xml/xml_element_spec.rb +1 -1
  98. data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
  99. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
  100. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
  101. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
  102. data/spec/lutaml/model/xml_adapter_spec.rb +6 -6
  103. data/spec/lutaml/model/xml_mapping_rule_spec.rb +3 -3
  104. data/spec/lutaml/model/xml_mapping_spec.rb +26 -14
  105. data/spec/lutaml/model/xml_spec.rb +63 -0
  106. data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
  107. data/spec/spec_helper.rb +3 -3
  108. metadata +64 -59
  109. data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
  110. data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
  111. data/lib/lutaml/model/loggable.rb +0 -15
  112. data/lib/lutaml/model/mapping/json_mapping.rb +0 -17
  113. data/lib/lutaml/model/mapping/toml_mapping.rb +0 -25
  114. data/lib/lutaml/model/mapping/xml_mapping.rb +0 -389
  115. data/lib/lutaml/model/mapping/xml_mapping_rule.rb +0 -139
  116. data/lib/lutaml/model/mapping/yaml_mapping.rb +0 -17
  117. data/lib/lutaml/model/mapping.rb +0 -14
  118. data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
  119. data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
  120. data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
  121. data/lib/lutaml/model/toml_adapter.rb +0 -6
  122. data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
  123. data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
  124. data/lib/lutaml/model/yaml_adapter.rb +0 -8
@@ -56,7 +56,7 @@ module TransformationSpec
56
56
  import: ->(value) { value.to_s.downcase },
57
57
  }
58
58
  attribute :email, :string, transform: {
59
- export: lambda(&:downcase),
59
+ export: lambda(&:upcase),
60
60
  import: lambda(&:downcase),
61
61
  }
62
62
  attribute :tags, :string, collection: true, transform: {
@@ -82,13 +82,36 @@ module TransformationSpec
82
82
  export: ->(value) { "Prof. #{value}" },
83
83
  import: ->(value) { value.gsub("Prof. ", "") },
84
84
  }
85
- map_element "contact-email", to: :email, transform: {
85
+ map_attribute "contact-email", to: :email, transform: {
86
86
  export: ->(value) { "contact+#{value}" },
87
87
  import: ->(value) { value.gsub("contact+", "") },
88
88
  }
89
89
  map_element "skills", to: :tags
90
90
  end
91
91
  end
92
+
93
+ class RoundTripTransformations < Lutaml::Model::Serializable
94
+ attribute :number, :string, transform: {
95
+ import: ->(value) { (value.to_f + 1).to_s },
96
+ export: ->(value) { (value.to_f - 1).to_s },
97
+ }
98
+
99
+ json do
100
+ map "number", to: :number, transform: {
101
+ import: ->(value) { ((value.to_f * 10) + 1).to_s },
102
+ export: ->(value) { ((value.to_f - 1) / 10.0).to_s },
103
+ }
104
+ end
105
+
106
+ xml do
107
+ root "RoundTripTransformations"
108
+
109
+ map_element "number", to: :number, transform: {
110
+ import: ->(value) { ((value.to_f * 10) + 1).to_s },
111
+ export: ->(value) { ((value.to_f - 1) / 10.0).to_s },
112
+ }
113
+ end
114
+ end
92
115
  end
93
116
 
94
117
  RSpec.describe "Value Transformations" do
@@ -147,6 +170,18 @@ RSpec.describe "Value Transformations" do
147
170
  )
148
171
  end
149
172
 
173
+ let(:json) do
174
+ {
175
+ "fullName" => "Dr. bob",
176
+ "emailAddress" => "bobattest.com",
177
+ "labels" => "senior|lead",
178
+ }.to_json
179
+ end
180
+
181
+ let(:parsed) do
182
+ TransformationSpec::MappingTransformPerson.from_json(json)
183
+ end
184
+
150
185
  let(:expected_xml) do
151
186
  <<~XML
152
187
  <person>
@@ -165,16 +200,15 @@ RSpec.describe "Value Transformations" do
165
200
  expect(parsed["labels"]).to eq("developer-|-architect")
166
201
  end
167
202
 
168
- it "applies mapping transformations during JSON deserialization" do
169
- json = {
170
- "fullName" => "Dr. bob",
171
- "emailAddress" => "bobattest.com",
172
- "labels" => "senior|lead",
173
- }.to_json
174
-
175
- parsed = TransformationSpec::MappingTransformPerson.from_json(json)
203
+ it "correctly deserialize name from JSON" do
176
204
  expect(parsed.name).to eq("Dr. bob")
205
+ end
206
+
207
+ it "correctly deserialize email from JSON" do
177
208
  expect(parsed.email).to eq("bob@test.com")
209
+ end
210
+
211
+ it "correctly deserialize tags from JSON" do
178
212
  expect(parsed.tags).to eq(["senior", "lead"])
179
213
  end
180
214
 
@@ -195,9 +229,8 @@ RSpec.describe "Value Transformations" do
195
229
 
196
230
  let(:expected_xml) do
197
231
  <<~XML
198
- <person>
199
- <full-name>Prof. carol</full-name>
200
- <contact-email>contact+CAROL@TEST.COM</contact-email>
232
+ <person contact-email="contact+CAROL@TEST.COM">
233
+ <full-name>Prof. Carol</full-name>
201
234
  <skills>MANAGER-1</skills>
202
235
  <skills>AGILE-1</skills>
203
236
  </person>
@@ -208,7 +241,7 @@ RSpec.describe "Value Transformations" do
208
241
  json = combined_person.to_json
209
242
  parsed = JSON.parse(json)
210
243
 
211
- expect(parsed["fullName"]).to eq("Prof. carol")
244
+ expect(parsed["fullName"]).to eq("Prof. Carol")
212
245
  expect(parsed["contactEmail"]).to eq("contact+CAROL@TEST.COM")
213
246
  end
214
247
 
@@ -217,7 +250,7 @@ RSpec.describe "Value Transformations" do
217
250
  json = combined_person.to_json
218
251
  parsed_json = TransformationSpec::CombinedTransformPerson.from_json(json)
219
252
  expect(parsed_json.name).to eq("carol")
220
- expect(parsed_json.email).to eq("CAROL@TEST.COM")
253
+ expect(parsed_json.email).to eq("carol@test.com")
221
254
  expect(parsed_json.tags).to eq(["MANAGER-1", "AGILE-1"])
222
255
  end
223
256
 
@@ -227,4 +260,28 @@ RSpec.describe "Value Transformations" do
227
260
  expect(parsed_xml.to_xml).to be_equivalent_to(expected_xml)
228
261
  end
229
262
  end
263
+
264
+ describe "Custom Transformations all mappings applied" do
265
+ let(:xml) do
266
+ <<~XML
267
+ <RoundTripTransformations>
268
+ <number>10.0</number>
269
+ </RoundTripTransformations>
270
+ XML
271
+ end
272
+
273
+ let(:json) do
274
+ { number: "10.0" }.to_json
275
+ end
276
+
277
+ it "correctly round trips XML" do
278
+ parsed = TransformationSpec::RoundTripTransformations.from_xml(xml)
279
+ expect(parsed.to_xml).to be_equivalent_to(xml)
280
+ end
281
+
282
+ it "correctly round trips JSON" do
283
+ parsed = TransformationSpec::RoundTripTransformations.from_json(json)
284
+ expect(parsed.to_json).to be_equivalent_to(json)
285
+ end
286
+ end
230
287
  end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Lutaml::Model::UninitializedClass do
4
+ subject(:uninitialized) { described_class.instance }
5
+
6
+ describe "#to_s" do
7
+ it "returns self" do
8
+ expect(uninitialized.to_s).to eq(uninitialized)
9
+ end
10
+ end
11
+
12
+ describe "#inspect" do
13
+ it "returns 'uninitialized'" do
14
+ expect(uninitialized.inspect).to eq("uninitialized")
15
+ end
16
+ end
17
+
18
+ describe "#uninitialized?" do
19
+ it "returns true" do
20
+ expect(uninitialized.uninitialized?).to be true
21
+ end
22
+ end
23
+
24
+ describe "#match?" do
25
+ it "returns false for any argument" do
26
+ expect(uninitialized).not_to match /pattern/
27
+ expect(uninitialized).not_to match "string"
28
+ expect(uninitialized).not_to match nil
29
+ end
30
+ end
31
+
32
+ describe "#include?" do
33
+ it "returns false for any argument" do
34
+ expect(uninitialized).not_to include "substring"
35
+ expect(uninitialized).not_to include nil
36
+ end
37
+ end
38
+
39
+ describe "#gsub" do
40
+ it "returns self regardless of arguments" do
41
+ expect(uninitialized.gsub("pattern", "replacement")).to eq(uninitialized)
42
+ expect(uninitialized.gsub("pattern", "replacement")).to eq(uninitialized)
43
+ end
44
+ end
45
+
46
+ describe "#to_yaml" do
47
+ it "returns nil" do
48
+ expect(uninitialized.to_yaml).to be_nil
49
+ end
50
+ end
51
+
52
+ describe "#to_f" do
53
+ it "returns self" do
54
+ expect(uninitialized.to_f).to eq(uninitialized)
55
+ end
56
+ end
57
+
58
+ describe "#size" do
59
+ it "returns 0" do
60
+ expect(uninitialized.size).to eq(0)
61
+ end
62
+ end
63
+
64
+ describe "#encoding" do
65
+ it "returns the default string encoding" do
66
+ expect(uninitialized.encoding).to eq("".encoding)
67
+ end
68
+ end
69
+
70
+ describe "method_missing" do
71
+ context "when method ends with '?'" do
72
+ it "returns false" do
73
+ expect(uninitialized).not_to be_empty
74
+ expect(uninitialized).not_to be_nil
75
+ expect(uninitialized).not_to be_blank
76
+ end
77
+ end
78
+
79
+ context "when method doesn't end with '?'" do
80
+ it "raises NoMethodError" do
81
+ expect { uninitialized.unknown_method }.to raise_error(NoMethodError)
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "#respond_to_missing?" do
87
+ it "returns true for methods ending with ?" do
88
+ expect(uninitialized.respond_to?(:empty?)).to be true
89
+ expect(uninitialized.respond_to?(:nil?)).to be true
90
+ end
91
+
92
+ it "returns false for methods not ending with ?" do
93
+ expect(uninitialized.respond_to?(:unknown_method)).to be false
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+
3
+ module NamespaceSpec
4
+ class NestedChild < Lutaml::Model::Serializable
5
+ attribute :name, :string
6
+
7
+ xml do
8
+ root "NestedChild"
9
+
10
+ map_element :name, to: :name
11
+ end
12
+ end
13
+
14
+ class Child < Lutaml::Model::Serializable
15
+ attribute :nested_child, NestedChild
16
+
17
+ xml do
18
+ root "NestedChild"
19
+
20
+ map_element :NestedChild, to: :nested_child
21
+ end
22
+ end
23
+
24
+ class Parent < Lutaml::Model::Serializable
25
+ attribute :child, Child
26
+
27
+ xml do
28
+ root "Parent"
29
+ namespace "https://abc.com"
30
+
31
+ map_element :Child, to: :child
32
+ end
33
+ end
34
+ end
35
+
36
+ RSpec.describe "NamespaceSpec" do
37
+ let(:parsed) { NamespaceSpec::Parent.from_xml(xml) }
38
+ let(:xml) do
39
+ <<~XML
40
+ <Parent xmlns="https://abc.com">
41
+ <Child>
42
+ <NestedChild>
43
+ <name>Rogger moore</name>
44
+ </NestedChild>
45
+ </Child>
46
+ </Parent>
47
+ XML
48
+ end
49
+
50
+ it "parses nested child using root namespace" do
51
+ expect(parsed.child.nested_child.name).to eq("Rogger moore")
52
+ end
53
+
54
+ it "round-trips xml" do
55
+ expect(parsed.to_xml).to be_equivalent_to(xml)
56
+ end
57
+ end
@@ -88,6 +88,6 @@ RSpec.describe "XmlElement" do
88
88
  end
89
89
 
90
90
  def create_element(name, attributes: {}, children: [], text: "")
91
- Lutaml::Model::XmlAdapter::XmlElement.new(name, attributes, children, text)
91
+ Lutaml::Model::Xml::XmlElement.new(name, attributes, children, text)
92
92
  end
93
93
  end
@@ -1,8 +1,8 @@
1
1
  require "spec_helper"
2
2
  require "nokogiri"
3
- require_relative "../../../../lib/lutaml/model/xml_adapter/nokogiri_adapter"
3
+ require_relative "../../../../lib/lutaml/model/xml/nokogiri_adapter"
4
4
 
5
- RSpec.describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
5
+ RSpec.describe Lutaml::Model::Xml::NokogiriAdapter do
6
6
  let(:xml_string) do
7
7
  <<-XML
8
8
  <root xmlns="http://example.com/default" xmlns:prefix="http://example.com/prefixed">
@@ -1,8 +1,8 @@
1
1
  require "spec_helper"
2
2
  require "oga"
3
- require_relative "../../../../lib/lutaml/model/xml_adapter/oga_adapter"
3
+ require_relative "../../../../lib/lutaml/model/xml/oga_adapter"
4
4
 
5
- RSpec.describe Lutaml::Model::XmlAdapter::OgaAdapter do
5
+ RSpec.describe Lutaml::Model::Xml::OgaAdapter do
6
6
  let(:xml_string) do
7
7
  <<~XML
8
8
  <root xmlns="http://example.com/default" xmlns:prefix="http://example.com/prefixed">
@@ -1,8 +1,8 @@
1
1
  require "spec_helper"
2
2
  require "ox"
3
- require_relative "../../../../lib/lutaml/model/xml_adapter/ox_adapter"
3
+ require_relative "../../../../lib/lutaml/model/xml/ox_adapter"
4
4
 
5
- RSpec.describe Lutaml::Model::XmlAdapter::OxAdapter do
5
+ RSpec.describe Lutaml::Model::Xml::OxAdapter do
6
6
  let(:xml_string) do
7
7
  <<-XML
8
8
  <root xmlns="http://example.com/default" xmlns:prefix="http://example.com/prefixed">
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
- require "lutaml/model/xml_adapter/nokogiri_adapter"
3
- require "lutaml/model/xml_adapter/ox_adapter"
4
- require "lutaml/model/xml_adapter/oga_adapter"
2
+ require "lutaml/model/xml/nokogiri_adapter"
3
+ require "lutaml/model/xml/ox_adapter"
4
+ require "lutaml/model/xml/oga_adapter"
5
5
  require "lutaml/model"
6
6
 
7
7
  RSpec.describe "XmlNamespace" do
@@ -354,15 +354,15 @@ RSpec.describe "XmlNamespace" do
354
354
  end
355
355
  end
356
356
 
357
- describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
357
+ describe Lutaml::Model::Xml::NokogiriAdapter do
358
358
  it_behaves_like "an XML namespace parser", described_class
359
359
  end
360
360
 
361
- describe Lutaml::Model::XmlAdapter::OxAdapter do
361
+ describe Lutaml::Model::Xml::OxAdapter do
362
362
  it_behaves_like "an XML namespace parser", described_class
363
363
  end
364
364
 
365
- describe Lutaml::Model::XmlAdapter::OgaAdapter do
365
+ describe Lutaml::Model::Xml::OgaAdapter do
366
366
  it_behaves_like "an XML namespace parser", described_class
367
367
  end
368
368
  end
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
- require "lutaml/model/xml_adapter/nokogiri_adapter"
3
- require "lutaml/model/xml_adapter/ox_adapter"
4
- require "lutaml/model/xml_adapter/oga_adapter"
2
+ require "lutaml/model/xml/nokogiri_adapter"
3
+ require "lutaml/model/xml/ox_adapter"
4
+ require "lutaml/model/xml/oga_adapter"
5
5
  require_relative "../../fixtures/sample_model"
6
6
 
7
7
  module XmlAdapterSpec
@@ -172,15 +172,15 @@ RSpec.describe "XmlAdapter" do
172
172
  end
173
173
  end
174
174
 
175
- describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
175
+ describe Lutaml::Model::Xml::NokogiriAdapter do
176
176
  it_behaves_like "an XML adapter", described_class
177
177
  end
178
178
 
179
- describe Lutaml::Model::XmlAdapter::OxAdapter do
179
+ describe Lutaml::Model::Xml::OxAdapter do
180
180
  it_behaves_like "an XML adapter", described_class
181
181
  end
182
182
 
183
- describe Lutaml::Model::XmlAdapter::OgaAdapter do
183
+ describe Lutaml::Model::Xml::OgaAdapter do
184
184
  it_behaves_like "an XML adapter", described_class
185
185
  end
186
186
  end
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
- require "lutaml/model/xml_adapter/ox_adapter"
4
- require "lutaml/model/xml_adapter/oga_adapter"
3
+ require "lutaml/model/xml/ox_adapter"
4
+ require "lutaml/model/xml/oga_adapter"
5
5
 
6
6
  def content_to_xml(model, parent, doc)
7
7
  content = model.all_content.sub(/^<div>/, "").sub(/<\/div>$/, "")
@@ -12,7 +12,7 @@ def content_from_xml(model, value)
12
12
  model.all_content = "<div>#{value}</div>"
13
13
  end
14
14
 
15
- RSpec.describe Lutaml::Model::XmlMappingRule do
15
+ RSpec.describe Lutaml::Model::Xml::MappingRule do
16
16
  describe "#namespaced_name" do
17
17
  let(:namespaced_name) do
18
18
  mapping_rule.namespaced_name
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
- require "lutaml/model/xml_adapter/ox_adapter"
4
- require "lutaml/model/xml_adapter/oga_adapter"
3
+ require "lutaml/model/xml/ox_adapter"
4
+ require "lutaml/model/xml/oga_adapter"
5
5
 
6
6
  # Define a sample class for testing map_content
7
7
  class Italic < Lutaml::Model::Serializable
@@ -320,7 +320,7 @@ module XmlMapping
320
320
  end
321
321
  end
322
322
 
323
- RSpec.describe Lutaml::Model::XmlMapping do
323
+ RSpec.describe Lutaml::Model::Xml::Mapping do
324
324
  shared_examples "having XML Mappings" do |adapter_class|
325
325
  around do |example|
326
326
  old_adapter = Lutaml::Model::Config.xml_adapter
@@ -331,7 +331,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
331
331
  Lutaml::Model::Config.xml_adapter = old_adapter
332
332
  end
333
333
 
334
- let(:mapping) { Lutaml::Model::XmlMapping.new }
334
+ let(:mapping) { Lutaml::Model::Xml::Mapping.new }
335
335
 
336
336
  context "with attribute having namespace" do
337
337
  input_xml = <<~XML
@@ -365,7 +365,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
365
365
  end
366
366
 
367
367
  # Skipping for OX because it does not handle namespaces
368
- context "when overriding child namespace prefix", skip: adapter_class == Lutaml::Model::XmlAdapter::OxAdapter do
368
+ context "when overriding child namespace prefix", skip: adapter_class == Lutaml::Model::Xml::OxAdapter do
369
369
  let(:input_xml) do
370
370
  <<~XML
371
371
  <OverrideDefaultNamespacePrefix
@@ -496,9 +496,9 @@ RSpec.describe Lutaml::Model::XmlMapping do
496
496
  ])
497
497
 
498
498
  {
499
- Lutaml::Model::XmlAdapter::NokogiriAdapter => nokogiri_pattern,
500
- Lutaml::Model::XmlAdapter::OxAdapter => oga_ox_pattern,
501
- Lutaml::Model::XmlAdapter::OgaAdapter => oga_ox_pattern,
499
+ Lutaml::Model::Xml::NokogiriAdapter => nokogiri_pattern,
500
+ Lutaml::Model::Xml::OxAdapter => oga_ox_pattern,
501
+ Lutaml::Model::Xml::OgaAdapter => oga_ox_pattern,
502
502
  }
503
503
  end
504
504
 
@@ -508,7 +508,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
508
508
 
509
509
  def create_pattern_mapping(array)
510
510
  array.map do |type, text|
511
- Lutaml::Model::XmlAdapter::Element.new(type, text)
511
+ Lutaml::Model::Xml::Element.new(type, text)
512
512
  end
513
513
  end
514
514
 
@@ -845,7 +845,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
845
845
  end
846
846
 
847
847
  let(:expected_street) do
848
- if Lutaml::Model::Config.xml_adapter == Lutaml::Model::XmlAdapter::NokogiriAdapter
848
+ if Lutaml::Model::Config.xml_adapter == Lutaml::Model::Xml::NokogiriAdapter
849
849
  "\n <a>N</a>\n <p>adf</p>\n "
850
850
  else
851
851
  "<a>N</a><p>adf</p>"
@@ -1248,7 +1248,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
1248
1248
  end
1249
1249
 
1250
1250
  describe "validation errors" do
1251
- let(:mapping) { Lutaml::Model::XmlMapping.new }
1251
+ let(:mapping) { Lutaml::Model::Xml::Mapping.new }
1252
1252
 
1253
1253
  it "raises error when neither :to nor :with provided" do
1254
1254
  expect do
@@ -1268,6 +1268,12 @@ RSpec.describe Lutaml::Model::XmlMapping do
1268
1268
  )
1269
1269
  end
1270
1270
 
1271
+ it "does not raise error when :to is provided" do
1272
+ expect do
1273
+ mapping.map_element("test", to: :test, with: { from: "value" })
1274
+ end.not_to raise_error
1275
+ end
1276
+
1271
1277
  describe "map_attribute validations" do
1272
1278
  it "raises error for invalid :with argument" do
1273
1279
  expect do
@@ -1277,6 +1283,12 @@ RSpec.describe Lutaml::Model::XmlMapping do
1277
1283
  ":with argument for mapping 'test' requires :to and :from keys",
1278
1284
  )
1279
1285
  end
1286
+
1287
+ it "does not raise error if to is provided" do
1288
+ expect do
1289
+ mapping.map_attribute("test", to: :test, with: { from: "value" })
1290
+ end.not_to raise_error
1291
+ end
1280
1292
  end
1281
1293
 
1282
1294
  describe "map_content validations" do
@@ -1292,15 +1304,15 @@ RSpec.describe Lutaml::Model::XmlMapping do
1292
1304
  end
1293
1305
  end
1294
1306
 
1295
- describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
1307
+ describe Lutaml::Model::Xml::NokogiriAdapter do
1296
1308
  it_behaves_like "having XML Mappings", described_class
1297
1309
  end
1298
1310
 
1299
- describe Lutaml::Model::XmlAdapter::OxAdapter do
1311
+ describe Lutaml::Model::Xml::OxAdapter do
1300
1312
  it_behaves_like "having XML Mappings", described_class
1301
1313
  end
1302
1314
 
1303
- describe Lutaml::Model::XmlAdapter::OgaAdapter do
1315
+ describe Lutaml::Model::Xml::OgaAdapter do
1304
1316
  it_behaves_like "having XML Mappings", described_class
1305
1317
  end
1306
1318
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "lutaml/model/xml"
5
+
6
+ RSpec.describe Lutaml::Model::Xml do
7
+ describe ".detect_xml_adapter" do
8
+ before do
9
+ # Hide any existing constants first
10
+ hide_const("Nokogiri") if Object.const_defined?(:Nokogiri)
11
+ hide_const("Ox") if Object.const_defined?(:Ox)
12
+ hide_const("Oga") if Object.const_defined?(:Oga)
13
+ end
14
+
15
+ context "when Nokogiri is available" do
16
+ before do
17
+ stub_const("Nokogiri", Module.new)
18
+ end
19
+
20
+ it "returns :nokogiri" do
21
+ expect(described_class.detect_xml_adapter).to eq(:nokogiri)
22
+ end
23
+ end
24
+
25
+ context "when Ox is available" do
26
+ before do
27
+ stub_const("Ox", Module.new)
28
+ end
29
+
30
+ it "returns :ox" do
31
+ expect(described_class.detect_xml_adapter).to eq(:ox)
32
+ end
33
+ end
34
+
35
+ context "when Oga is available" do
36
+ before do
37
+ stub_const("Oga", Module.new)
38
+ end
39
+
40
+ it "returns :oga" do
41
+ expect(described_class.detect_xml_adapter).to eq(:oga)
42
+ end
43
+ end
44
+
45
+ context "when no adapters are available" do
46
+ it "returns nil" do
47
+ expect(described_class.detect_xml_adapter).to be_nil
48
+ end
49
+ end
50
+
51
+ context "when multiple adapters are available" do
52
+ before do
53
+ stub_const("Nokogiri", Module.new)
54
+ stub_const("Ox", Module.new)
55
+ stub_const("Oga", Module.new)
56
+ end
57
+
58
+ it "prefers Nokogiri" do
59
+ expect(described_class.detect_xml_adapter).to eq(:nokogiri)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,5 +1,4 @@
1
1
  require "spec_helper"
2
- require "lutaml/model/yaml_adapter"
3
2
  require_relative "../../fixtures/sample_model"
4
3
 
5
4
  RSpec.shared_examples "a YAML adapter" do |adapter_class|
@@ -7,7 +6,7 @@ RSpec.shared_examples "a YAML adapter" do |adapter_class|
7
6
  let(:model) { SampleModel.new(attributes) }
8
7
 
9
8
  let(:expected_yaml) do
10
- if adapter_class == Lutaml::Model::YamlAdapter::StandardYamlAdapter
9
+ if adapter_class == Lutaml::Model::Yaml::StandardAdapter
11
10
  attributes.to_yaml
12
11
  end
13
12
  end
@@ -20,11 +19,10 @@ RSpec.shared_examples "a YAML adapter" do |adapter_class|
20
19
 
21
20
  it "deserializes from YAML" do
22
21
  new_model = adapter_class.parse(expected_yaml)
23
- expect(new_model["name"]).to eq("John Doe")
24
- expect(new_model["age"]).to eq(30)
22
+ expect(new_model).to eq(attributes)
25
23
  end
26
24
  end
27
25
 
28
- RSpec.describe Lutaml::Model::YamlAdapter::StandardYamlAdapter do
26
+ RSpec.describe Lutaml::Model::Yaml::StandardAdapter do
29
27
  it_behaves_like "a YAML adapter", described_class
30
28
  end
data/spec/spec_helper.rb CHANGED
@@ -22,9 +22,9 @@ end
22
22
 
23
23
  # configuration example
24
24
  require_relative "../lib/lutaml/model"
25
- require_relative "../lib/lutaml/model/xml_adapter/nokogiri_adapter"
26
- require_relative "../lib/lutaml/model/xml_adapter/ox_adapter"
27
- require_relative "../lib/lutaml/model/toml_adapter/toml_rb_adapter"
25
+ # require_relative "../lib/lutaml/model/xml/nokogiri_adapter"
26
+ # require_relative "../lib/lutaml/model/xml/ox_adapter"
27
+ # require_relative "../lib/lutaml/model/toml_adapter/toml_rb_adapter"
28
28
 
29
29
  Lutaml::Model::Config.configure do |config|
30
30
  config.xml_adapter_type = :nokogiri