lutaml-model 0.6.7 → 0.7.2

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 (148) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/dependent-repos-todo.json +7 -0
  3. data/.github/workflows/dependent-repos.json +17 -9
  4. data/.rubocop.yml +1 -1
  5. data/.rubocop_todo.yml +51 -65
  6. data/Gemfile +4 -1
  7. data/README.adoc +5083 -2612
  8. data/RELEASE_NOTES.adoc +346 -0
  9. data/docs/custom_adapters.adoc +144 -0
  10. data/lib/lutaml/model/attribute.rb +101 -16
  11. data/lib/lutaml/model/choice.rb +7 -0
  12. data/lib/lutaml/model/comparable_model.rb +48 -9
  13. data/lib/lutaml/model/config.rb +48 -42
  14. data/lib/lutaml/model/error/collection_count_out_of_range_error.rb +1 -1
  15. data/lib/lutaml/model/error/polymorphic_error.rb +14 -0
  16. data/lib/lutaml/model/error.rb +1 -0
  17. data/lib/lutaml/model/format_registry.rb +41 -0
  18. data/lib/lutaml/model/hash/document.rb +11 -0
  19. data/lib/lutaml/model/hash/mapping.rb +19 -0
  20. data/lib/lutaml/model/hash/mapping_rule.rb +9 -0
  21. data/lib/lutaml/model/hash/standard_adapter.rb +17 -0
  22. data/lib/lutaml/model/hash/transform.rb +8 -0
  23. data/lib/lutaml/model/hash.rb +21 -0
  24. data/lib/lutaml/model/json/document.rb +11 -0
  25. data/lib/lutaml/model/json/mapping.rb +19 -0
  26. data/lib/lutaml/model/json/mapping_rule.rb +9 -0
  27. data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
  28. data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
  29. data/lib/lutaml/model/json/transform.rb +8 -0
  30. data/lib/lutaml/model/json.rb +21 -0
  31. data/lib/lutaml/model/key_value_document.rb +27 -0
  32. data/lib/lutaml/model/{key_value_mapping.rb → mapping/key_value_mapping.rb} +64 -16
  33. data/lib/lutaml/model/{key_value_mapping_rule.rb → mapping/key_value_mapping_rule.rb} +18 -2
  34. data/lib/lutaml/model/mapping/mapping.rb +13 -0
  35. data/lib/lutaml/model/mapping/mapping_rule.rb +300 -0
  36. data/lib/lutaml/model/schema/xml_compiler.rb +15 -15
  37. data/lib/lutaml/model/sequence.rb +2 -2
  38. data/lib/lutaml/model/serialization_adapter.rb +22 -0
  39. data/lib/lutaml/model/serialize.rb +219 -444
  40. data/lib/lutaml/model/services/logger.rb +54 -0
  41. data/lib/lutaml/model/services/transformer.rb +48 -0
  42. data/lib/lutaml/model/services.rb +2 -0
  43. data/lib/lutaml/model/toml/document.rb +11 -0
  44. data/lib/lutaml/model/toml/mapping.rb +27 -0
  45. data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
  46. data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
  47. data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
  48. data/lib/lutaml/model/toml/transform.rb +8 -0
  49. data/lib/lutaml/model/toml.rb +30 -0
  50. data/lib/lutaml/model/transform/key_value_transform.rb +291 -0
  51. data/lib/lutaml/model/transform/xml_transform.rb +239 -0
  52. data/lib/lutaml/model/transform.rb +78 -0
  53. data/lib/lutaml/model/type/date.rb +1 -1
  54. data/lib/lutaml/model/type/date_time.rb +2 -2
  55. data/lib/lutaml/model/type/hash.rb +1 -1
  56. data/lib/lutaml/model/type/time.rb +2 -2
  57. data/lib/lutaml/model/type/time_without_date.rb +2 -2
  58. data/lib/lutaml/model/type/value.rb +6 -9
  59. data/lib/lutaml/model/uninitialized_class.rb +64 -0
  60. data/lib/lutaml/model/utils.rb +44 -0
  61. data/lib/lutaml/model/validation.rb +1 -0
  62. data/lib/lutaml/model/version.rb +1 -1
  63. data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
  64. data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
  65. data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
  66. data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +41 -21
  67. data/lib/lutaml/model/xml/element.rb +32 -0
  68. data/lib/lutaml/model/xml/mapping.rb +410 -0
  69. data/lib/lutaml/model/xml/mapping_rule.rb +141 -0
  70. data/lib/lutaml/model/xml/nokogiri_adapter.rb +232 -0
  71. data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
  72. data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +3 -1
  73. data/lib/lutaml/model/xml/oga_adapter.rb +171 -0
  74. data/lib/lutaml/model/xml/ox_adapter.rb +215 -0
  75. data/lib/lutaml/model/xml/transform.rb +8 -0
  76. data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
  77. data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +23 -10
  78. data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
  79. data/lib/lutaml/model/xml.rb +31 -0
  80. data/lib/lutaml/model/xml_adapter/element.rb +11 -25
  81. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
  82. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
  83. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
  84. data/lib/lutaml/model/yaml/document.rb +10 -0
  85. data/lib/lutaml/model/yaml/mapping.rb +19 -0
  86. data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
  87. data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
  88. data/lib/lutaml/model/yaml/transform.rb +8 -0
  89. data/lib/lutaml/model/yaml.rb +21 -0
  90. data/lib/lutaml/model.rb +40 -4
  91. data/lutaml-model.gemspec +0 -4
  92. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +7 -7
  93. data/spec/fixtures/person.rb +5 -5
  94. data/spec/lutaml/model/attribute_spec.rb +37 -1
  95. data/spec/lutaml/model/cdata_spec.rb +9 -9
  96. data/spec/lutaml/model/collection_spec.rb +50 -2
  97. data/spec/lutaml/model/comparable_model_spec.rb +92 -27
  98. data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
  99. data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
  100. data/spec/lutaml/model/defaults_spec.rb +1 -1
  101. data/spec/lutaml/model/enum_spec.rb +1 -1
  102. data/spec/lutaml/model/group_spec.rb +333 -20
  103. data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
  104. data/spec/lutaml/model/json_adapter_spec.rb +6 -6
  105. data/spec/lutaml/model/key_value_mapping_spec.rb +65 -3
  106. data/spec/lutaml/model/mixed_content_spec.rb +24 -24
  107. data/spec/lutaml/model/multiple_mapping_spec.rb +5 -5
  108. data/spec/lutaml/model/ordered_content_spec.rb +6 -6
  109. data/spec/lutaml/model/polymorphic_spec.rb +526 -0
  110. data/spec/lutaml/model/render_empty_spec.rb +194 -0
  111. data/spec/lutaml/model/render_nil_spec.rb +206 -22
  112. data/spec/lutaml/model/root_mappings_spec.rb +3 -3
  113. data/spec/lutaml/model/schema/xml_compiler_spec.rb +6 -6
  114. data/spec/lutaml/model/serializable_spec.rb +179 -103
  115. data/spec/lutaml/model/simple_model_spec.rb +9 -9
  116. data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
  117. data/spec/lutaml/model/toml_spec.rb +51 -0
  118. data/spec/lutaml/model/transformation_spec.rb +72 -15
  119. data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
  120. data/spec/lutaml/model/value_map_spec.rb +240 -0
  121. data/spec/lutaml/model/xml/namespace/nested_with_explicit_namespace_spec.rb +85 -0
  122. data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
  123. data/spec/lutaml/model/xml/xml_element_spec.rb +93 -0
  124. data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
  125. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
  126. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
  127. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
  128. data/spec/lutaml/model/xml_adapter_spec.rb +6 -6
  129. data/spec/lutaml/model/xml_mapping_rule_spec.rb +105 -5
  130. data/spec/lutaml/model/xml_mapping_spec.rb +70 -16
  131. data/spec/lutaml/model/xml_spec.rb +63 -0
  132. data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
  133. data/spec/sample_model_spec.rb +3 -3
  134. data/spec/spec_helper.rb +3 -3
  135. metadata +76 -59
  136. data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
  137. data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
  138. data/lib/lutaml/model/loggable.rb +0 -15
  139. data/lib/lutaml/model/mapping_rule.rb +0 -109
  140. data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
  141. data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
  142. data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
  143. data/lib/lutaml/model/toml_adapter.rb +0 -6
  144. data/lib/lutaml/model/xml_mapping.rb +0 -307
  145. data/lib/lutaml/model/xml_mapping_rule.rb +0 -122
  146. data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
  147. data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
  148. data/lib/lutaml/model/yaml_adapter.rb +0 -8
@@ -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
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "XmlElement" do
6
+ describe "#text" do
7
+ context "when only text is present" do
8
+ let(:element) { create_element("name", text: "something") }
9
+
10
+ it "returns text" do
11
+ expect(element.text).to eq("something")
12
+ end
13
+ end
14
+
15
+ context "when single text node is present" do
16
+ let(:element) do
17
+ create_element(
18
+ "name",
19
+ children: [
20
+ create_element("text", text: "John Doe"),
21
+ ],
22
+ )
23
+ end
24
+
25
+ it "returns single string" do
26
+ expect(element.text).to eq("John Doe")
27
+ end
28
+ end
29
+
30
+ context "when multiple text nodes are present" do
31
+ let(:element) do
32
+ create_element(
33
+ "name",
34
+ children: [
35
+ create_element("text", text: "John"),
36
+ create_element("text", text: "\n"),
37
+ create_element("text", text: "Doe"),
38
+ ],
39
+ )
40
+ end
41
+
42
+ it "returns all text elements array" do
43
+ expect(element.text).to eq(["John", "\n", "Doe"])
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#cdata" do
49
+ context "when only cdata is present" do
50
+ let(:element) { create_element("name", text: "something") }
51
+
52
+ it "returns cdata" do
53
+ expect(element.cdata).to eq("something")
54
+ end
55
+ end
56
+
57
+ context "when single cdata node is present" do
58
+ let(:element) do
59
+ create_element(
60
+ "name",
61
+ children: [
62
+ create_element("#cdata-section", text: "John Doe"),
63
+ ],
64
+ )
65
+ end
66
+
67
+ it "returns single string" do
68
+ expect(element.cdata).to eq("John Doe")
69
+ end
70
+ end
71
+
72
+ context "when multiple cdata nodes are present" do
73
+ let(:element) do
74
+ create_element(
75
+ "name",
76
+ children: [
77
+ create_element("#cdata-section", text: "John"),
78
+ create_element("#cdata-section", text: "\n"),
79
+ create_element("#cdata-section", text: "Doe"),
80
+ ],
81
+ )
82
+ end
83
+
84
+ it "returns all cdata elements array" do
85
+ expect(element.cdata).to eq(["John", "\n", "Doe"])
86
+ end
87
+ end
88
+ end
89
+
90
+ def create_element(name, attributes: {}, children: [], text: "")
91
+ Lutaml::Model::Xml::XmlElement.new(name, attributes, children, text)
92
+ end
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,9 +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"
5
-
6
- require_relative "../../../lib/lutaml/model/xml_mapping_rule"
3
+ require "lutaml/model/xml/ox_adapter"
4
+ require "lutaml/model/xml/oga_adapter"
7
5
 
8
6
  def content_to_xml(model, parent, doc)
9
7
  content = model.all_content.sub(/^<div>/, "").sub(/<\/div>$/, "")
@@ -14,7 +12,109 @@ def content_from_xml(model, value)
14
12
  model.all_content = "<div>#{value}</div>"
15
13
  end
16
14
 
17
- RSpec.describe Lutaml::Model::XmlMappingRule do
15
+ RSpec.describe Lutaml::Model::Xml::MappingRule do
16
+ describe "#namespaced_name" do
17
+ let(:namespaced_name) do
18
+ mapping_rule.namespaced_name
19
+ end
20
+
21
+ context "when attribute name is string 'lang'" do
22
+ let(:mapping_rule) do
23
+ described_class.new("lang", to: :lang, prefix: "xml")
24
+ end
25
+
26
+ it "returns `xml:lang`" do
27
+ expect(namespaced_name).to eq("xml:lang")
28
+ end
29
+ end
30
+
31
+ context "when attribute name is symbol ':lang'" do
32
+ let(:mapping_rule) do
33
+ described_class.new(:lang, to: :lang, prefix: "xml")
34
+ end
35
+
36
+ it "returns `xml:lang`" do
37
+ expect(namespaced_name).to eq("xml:lang")
38
+ end
39
+ end
40
+
41
+ context "when namespace is explicitly set" do
42
+ let(:mapping_rule) do
43
+ described_class.new(
44
+ "explicit_namespace",
45
+ to: :explicit_namespace,
46
+ namespace: "http://test",
47
+ namespace_set: true,
48
+ )
49
+ end
50
+
51
+ it "returns `http://test:explicit_namespace`" do
52
+ expect(namespaced_name).to eq("http://test:explicit_namespace")
53
+ end
54
+ end
55
+
56
+ context "when namespace is explicitly set to nil" do
57
+ let(:mapping_rule) do
58
+ described_class.new(
59
+ "explicit_namespace",
60
+ to: :explicit_namespace,
61
+ namespace: nil,
62
+ namespace_set: true,
63
+ default_namespace: "http://default",
64
+ )
65
+ end
66
+
67
+ it "returns name without namespace" do
68
+ expect(namespaced_name).to eq("explicit_namespace")
69
+ end
70
+ end
71
+
72
+ context "when attribute has namespace set" do
73
+ let(:mapping_rule) do
74
+ described_class.new(
75
+ "attribute",
76
+ to: :attribute,
77
+ attribute: true,
78
+ namespace: "http://test",
79
+ default_namespace: "http://default",
80
+ )
81
+ end
82
+
83
+ it "returns `http://test:attribute`" do
84
+ expect(namespaced_name).to eq("http://test:attribute")
85
+ end
86
+ end
87
+
88
+ context "when attribute has no namespace set" do
89
+ let(:mapping_rule) do
90
+ described_class.new(
91
+ "attribute",
92
+ to: :attribute,
93
+ attribute: true,
94
+ default_namespace: "http://default",
95
+ )
96
+ end
97
+
98
+ it "does not use default namespace" do
99
+ expect(namespaced_name).to eq("attribute")
100
+ end
101
+ end
102
+
103
+ context "when default_namespace is set" do
104
+ let(:mapping_rule) do
105
+ described_class.new(
106
+ "default_namespace",
107
+ to: :default_namespace,
108
+ default_namespace: "http://default",
109
+ )
110
+ end
111
+
112
+ it "returns `default_namespace:name` if not an attribute" do
113
+ expect(namespaced_name).to eq("http://default:default_namespace")
114
+ end
115
+ end
116
+ end
117
+
18
118
  context "with Xml Mapping Rule" do
19
119
  let(:orig_mapping_rule) do
20
120
  described_class.new(
@@ -1,10 +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"
5
-
6
- require_relative "../../../lib/lutaml/model/xml_mapping"
7
- require_relative "../../../lib/lutaml/model/xml_mapping_rule"
3
+ require "lutaml/model/xml/ox_adapter"
4
+ require "lutaml/model/xml/oga_adapter"
8
5
 
9
6
  # Define a sample class for testing map_content
10
7
  class Italic < Lutaml::Model::Serializable
@@ -323,7 +320,7 @@ module XmlMapping
323
320
  end
324
321
  end
325
322
 
326
- RSpec.describe Lutaml::Model::XmlMapping do
323
+ RSpec.describe Lutaml::Model::Xml::Mapping do
327
324
  shared_examples "having XML Mappings" do |adapter_class|
328
325
  around do |example|
329
326
  old_adapter = Lutaml::Model::Config.xml_adapter
@@ -334,7 +331,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
334
331
  Lutaml::Model::Config.xml_adapter = old_adapter
335
332
  end
336
333
 
337
- let(:mapping) { Lutaml::Model::XmlMapping.new }
334
+ let(:mapping) { Lutaml::Model::Xml::Mapping.new }
338
335
 
339
336
  context "with attribute having namespace" do
340
337
  input_xml = <<~XML
@@ -368,7 +365,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
368
365
  end
369
366
 
370
367
  # Skipping for OX because it does not handle namespaces
371
- 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
372
369
  let(:input_xml) do
373
370
  <<~XML
374
371
  <OverrideDefaultNamespacePrefix
@@ -445,6 +442,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
445
442
 
446
443
  it "parse and serialize model correctly" do
447
444
  parsed = XmlMapping::OwnedComment.from_xml(xml_with_attribute)
445
+
448
446
  serialized = parsed.to_xml
449
447
 
450
448
  expect(serialized).to be_equivalent_to(xml_with_attribute)
@@ -498,9 +496,9 @@ RSpec.describe Lutaml::Model::XmlMapping do
498
496
  ])
499
497
 
500
498
  {
501
- Lutaml::Model::XmlAdapter::NokogiriAdapter => nokogiri_pattern,
502
- Lutaml::Model::XmlAdapter::OxAdapter => oga_ox_pattern,
503
- 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,
504
502
  }
505
503
  end
506
504
 
@@ -510,7 +508,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
510
508
 
511
509
  def create_pattern_mapping(array)
512
510
  array.map do |type, text|
513
- Lutaml::Model::XmlAdapter::Element.new(type, text)
511
+ Lutaml::Model::Xml::Element.new(type, text)
514
512
  end
515
513
  end
516
514
 
@@ -847,7 +845,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
847
845
  end
848
846
 
849
847
  let(:expected_street) do
850
- if Lutaml::Model::Config.xml_adapter == Lutaml::Model::XmlAdapter::NokogiriAdapter
848
+ if Lutaml::Model::Config.xml_adapter == Lutaml::Model::Xml::NokogiriAdapter
851
849
  "\n <a>N</a>\n <p>adf</p>\n "
852
850
  else
853
851
  "<a>N</a><p>adf</p>"
@@ -1248,17 +1246,73 @@ RSpec.describe Lutaml::Model::XmlMapping do
1248
1246
  end
1249
1247
  end
1250
1248
  end
1249
+
1250
+ describe "validation errors" do
1251
+ let(:mapping) { Lutaml::Model::Xml::Mapping.new }
1252
+
1253
+ it "raises error when neither :to nor :with provided" do
1254
+ expect do
1255
+ mapping.map_element("test")
1256
+ end.to raise_error(
1257
+ Lutaml::Model::IncorrectMappingArgumentsError,
1258
+ ":to or :with argument is required for mapping 'test'",
1259
+ )
1260
+ end
1261
+
1262
+ it "raises error when :with is missing :to or :from keys" do
1263
+ expect do
1264
+ mapping.map_element("test", with: { to: "value" })
1265
+ end.to raise_error(
1266
+ Lutaml::Model::IncorrectMappingArgumentsError,
1267
+ ":with argument for mapping 'test' requires :to and :from keys",
1268
+ )
1269
+ end
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
+
1277
+ describe "map_attribute validations" do
1278
+ it "raises error for invalid :with argument" do
1279
+ expect do
1280
+ mapping.map_attribute("test", with: { from: "value" })
1281
+ end.to raise_error(
1282
+ Lutaml::Model::IncorrectMappingArgumentsError,
1283
+ ":with argument for mapping 'test' requires :to and :from keys",
1284
+ )
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
1292
+ end
1293
+
1294
+ describe "map_content validations" do
1295
+ it "raises error when no :to provided" do
1296
+ expect do
1297
+ mapping.map_content
1298
+ end.to raise_error(
1299
+ Lutaml::Model::IncorrectMappingArgumentsError,
1300
+ ":to or :with argument is required for mapping 'content'",
1301
+ )
1302
+ end
1303
+ end
1304
+ end
1251
1305
  end
1252
1306
 
1253
- describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
1307
+ describe Lutaml::Model::Xml::NokogiriAdapter do
1254
1308
  it_behaves_like "having XML Mappings", described_class
1255
1309
  end
1256
1310
 
1257
- describe Lutaml::Model::XmlAdapter::OxAdapter do
1311
+ describe Lutaml::Model::Xml::OxAdapter do
1258
1312
  it_behaves_like "having XML Mappings", described_class
1259
1313
  end
1260
1314
 
1261
- describe Lutaml::Model::XmlAdapter::OgaAdapter do
1315
+ describe Lutaml::Model::Xml::OgaAdapter do
1262
1316
  it_behaves_like "having XML Mappings", described_class
1263
1317
  end
1264
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("Opal") if Object.const_defined?(:Opal)
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 Opal is available" do
36
+ before do
37
+ stub_const("Opal", Module.new)
38
+ end
39
+
40
+ it "returns :opal" do
41
+ expect(described_class.detect_xml_adapter).to eq(:opal)
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("Opal", 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
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
  require_relative "fixtures/sample_model"
3
3
 
4
4
  RSpec.describe SampleModel do
5
- let(:model) { described_class.new(attributes) }
5
+ let(:model) { described_class.new(attributes, { omitted: :omitted }) }
6
6
  let(:attributes_yaml) do
7
7
  {
8
8
  "name" => "John Doe",
@@ -37,7 +37,7 @@ RSpec.describe SampleModel do
37
37
  end
38
38
 
39
39
  describe "default values" do
40
- let(:model) { described_class.new }
40
+ let(:model) { described_class.new({}, { omitted: :omitted }) }
41
41
 
42
42
  it "sets default name" do
43
43
  expect(model.name).to eq("Anonymous")
@@ -52,7 +52,7 @@ RSpec.describe SampleModel do
52
52
  end
53
53
 
54
54
  it "sets default tags" do
55
- expect(model.tags).to eq([])
55
+ expect(model.tags).to be_uninitialized
56
56
  end
57
57
 
58
58
  it "sets default preferences" do
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