lutaml-model 0.6.1 → 0.6.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/dependent-repos.json +2 -1
  3. data/.rubocop_todo.yml +10 -80
  4. data/lib/lutaml/model/attribute.rb +6 -1
  5. data/lib/lutaml/model/schema/xml_compiler.rb +3 -1
  6. data/lib/lutaml/model/type/float.rb +0 -4
  7. data/lib/lutaml/model/version.rb +1 -1
  8. data/lib/lutaml/model/xml_adapter/xml_document.rb +0 -4
  9. data/lib/lutaml/model/xml_adapter/xml_element.rb +1 -3
  10. data/spec/address_spec.rb +3 -3
  11. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +3 -3
  12. data/spec/lutaml/model/collection_spec.rb +0 -16
  13. data/spec/lutaml/model/json_adapter_spec.rb +26 -24
  14. data/spec/lutaml/model/key_value_mapping_spec.rb +1 -13
  15. data/spec/lutaml/model/schema/json_schema_spec.rb +12 -12
  16. data/spec/lutaml/model/schema/relaxng_schema_spec.rb +12 -12
  17. data/spec/lutaml/model/schema/xml_compiler_spec.rb +447 -147
  18. data/spec/lutaml/model/schema/xsd_schema_spec.rb +12 -12
  19. data/spec/lutaml/model/schema/yaml_schema_spec.rb +12 -12
  20. data/spec/lutaml/model/sequence_spec.rb +129 -113
  21. data/spec/lutaml/model/toml_adapter_spec.rb +27 -25
  22. data/spec/lutaml/model/transformation_spec.rb +80 -80
  23. data/spec/lutaml/model/type/boolean_spec.rb +4 -10
  24. data/spec/lutaml/model/type/decimal_spec.rb +3 -3
  25. data/spec/lutaml/model/type/hash_spec.rb +39 -26
  26. data/spec/lutaml/model/type/integer_spec.rb +2 -2
  27. data/spec/lutaml/model/type/time_without_date_spec.rb +0 -6
  28. data/spec/lutaml/model/type_spec.rb +6 -26
  29. data/spec/lutaml/model/utils_spec.rb +25 -30
  30. data/spec/lutaml/model/validation_spec.rb +9 -6
  31. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
  32. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
  33. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +280 -281
  34. data/spec/lutaml/model/xml_adapter_spec.rb +128 -120
  35. data/spec/lutaml/model/xml_mapping_spec.rb +23 -16
  36. data/spec/person_spec.rb +6 -16
  37. metadata +2 -2
@@ -17,31 +17,44 @@ RSpec.describe Lutaml::Model::Type::Hash do
17
17
  expect(described_class.cast(mapping_hash)).to eq({ "key" => "value" })
18
18
  end
19
19
 
20
- it "filters out text keys from nested hashes" do
21
- hash = {
22
- "key1" => {
23
- "text" => "content1",
24
- "other" => "value1",
25
- },
26
- "key2" => {
27
- "text" => "content2",
28
- "other" => "value2",
29
- },
30
- }
31
- expected = {
32
- "key1" => { "other" => "value1" },
33
- "key2" => { "other" => "value2" },
34
- }
35
- expect(described_class.cast(hash)).to eq expected
36
- end
37
-
38
- it "preserves non-hash values" do
39
- input = {
40
- "string" => "value",
41
- "number" => 42,
42
- "array" => [1, 2, 3],
43
- }
44
- expect(described_class.cast(input)).to eq input
20
+ context "with nested hashes" do
21
+ let(:input) do
22
+ {
23
+ "key1" => {
24
+ "text" => "content1",
25
+ "other" => "value1",
26
+ },
27
+ "key2" => {
28
+ "text" => "content2",
29
+ "other" => "value2",
30
+ },
31
+ }
32
+ end
33
+
34
+ let(:expected_hash) do
35
+ {
36
+ "key1" => { "other" => "value1" },
37
+ "key2" => { "other" => "value2" },
38
+ }
39
+ end
40
+
41
+ it "filters out text keys from nested hashes" do
42
+ expect(described_class.cast(input)).to eq(expected_hash)
43
+ end
44
+ end
45
+
46
+ context "with non-hash values" do
47
+ let(:input) do
48
+ {
49
+ "string" => "value",
50
+ "number" => 42,
51
+ "array" => [1, 2, 3],
52
+ }
53
+ end
54
+
55
+ it "preserves non-hash values" do
56
+ expect(described_class.cast(input)).to eq input
57
+ end
45
58
  end
46
59
  end
47
60
 
@@ -56,7 +69,7 @@ RSpec.describe Lutaml::Model::Type::Hash do
56
69
  end
57
70
 
58
71
  it "converts arbitrary object responding to to_h" do
59
- obj = double(to_h: { "key" => "value" })
72
+ obj = instance_double(Hash, to_h: { "key" => "value" })
60
73
  expect(described_class.serialize(obj)).to eq({ "key" => "value" })
61
74
  end
62
75
  end
@@ -89,10 +89,10 @@ RSpec.describe Lutaml::Model::Type::Integer do
89
89
  end
90
90
 
91
91
  context "with very large integer" do
92
- let(:max_value) { ((2**((0.size * 8) - 2)) - 1) }
92
+ let(:max_value) { ((2**((0.size * 8) - 2))) }
93
93
  let(:value) { max_value.to_s }
94
94
 
95
- xit { is_expected.to eq(max_value) }
95
+ it { is_expected.to eq(max_value) }
96
96
  end
97
97
 
98
98
  context "with very small integer" do
@@ -96,12 +96,6 @@ RSpec.describe Lutaml::Model::Type::TimeWithoutDate do
96
96
  it { is_expected.to be_nil }
97
97
  end
98
98
 
99
- context "with Time object" do
100
- let(:value) { Time.new(2024, 1, 1, 13, 45, 30) }
101
-
102
- it { is_expected.to eq("13:45:30") }
103
- end
104
-
105
99
  context "with single-digit values" do
106
100
  let(:value) { Time.new(2024, 1, 1, 9, 5, 3) }
107
101
 
@@ -191,12 +191,7 @@ RSpec.describe Lutaml::Model::Type do
191
191
 
192
192
  context "when BigDecimal is not available" do
193
193
  before do
194
- Object.send(:remove_const, :BigDecimal) if defined?(BigDecimal)
195
- $LOADED_FEATURES.delete_if { |path| path.include?("bigdecimal") }
196
- end
197
-
198
- after do
199
- require "bigdecimal"
194
+ hide_const("BigDecimal") if defined?(BigDecimal)
200
195
  end
201
196
 
202
197
  let(:decimal_class) { described_class.lookup(:decimal) }
@@ -277,8 +272,8 @@ RSpec.describe Lutaml::Model::Type do
277
272
  end
278
273
 
279
274
  describe "Serialization" do
280
- it "correctly serializes to XML" do
281
- expected_xml = <<~XML
275
+ let(:xml) do
276
+ <<~XML
282
277
  <test>
283
278
  <string_symbol>test</string_symbol>
284
279
  <string_class>test</string_class>
@@ -294,28 +289,13 @@ RSpec.describe Lutaml::Model::Type do
294
289
  </hash>
295
290
  </test>
296
291
  XML
292
+ end
297
293
 
298
- expect(test_instance.to_xml).to be_equivalent_to(expected_xml)
294
+ it "correctly serializes to XML" do
295
+ expect(test_instance.to_xml).to be_equivalent_to(xml)
299
296
  end
300
297
 
301
298
  it "correctly deserializes from XML" do
302
- xml = <<~XML
303
- <test>
304
- <string_symbol>test</string_symbol>
305
- <string_class>test</string_class>
306
- <integer>123</integer>
307
- <float>123.45</float>
308
- <date>2024-01-01</date>
309
- <time>12:00:00</time>
310
- <time_without_date>10:06:15</time_without_date>
311
- <date_time>2024-01-01T12:00:00</date_time>
312
- <boolean>true</boolean>
313
- <hash>
314
- <key>value</key>
315
- </hash>
316
- </test>
317
- XML
318
-
319
299
  deserialized = TypeTestModel.from_xml(xml)
320
300
  expect(deserialized.string_symbol).to eq("test")
321
301
  expect(deserialized.string_class).to eq("test")
@@ -69,43 +69,38 @@ RSpec.describe Lutaml::Model::Utils do
69
69
  let(:duplicate_array) { utils.deep_dup(original_array) }
70
70
 
71
71
  it "creates deep duplicate of hash" do
72
- expect(original_hash).to eq(duplicate_hash)
73
- expect(original_hash.object_id).not_to eq(duplicate_hash.object_id)
74
-
75
- expect(original_hash[:one]).to eq(duplicate_hash[:one])
76
- expect(original_hash[:one].object_id).not_to eq(duplicate_hash[:one].object_id)
77
-
78
- expect(original_hash[:one][:one_one]).to eq(duplicate_hash[:one][:one_one])
79
- expect(original_hash[:one][:one_one].object_id).not_to eq(duplicate_hash[:one][:one_one].object_id)
80
-
81
- expect(original_hash[:one][:one_one][:one_one1]).to eq(duplicate_hash[:one][:one_one][:one_one1])
82
- expect(original_hash[:one][:one_one][:one_one1].object_id).not_to eq(duplicate_hash[:one][:one_one][:one_one1].object_id)
83
-
84
- # this is a symbol so the object_id will be same
85
- expect(original_hash[:one][:one_one][:one_one2]).to eq(duplicate_hash[:one][:one_one][:one_one2])
86
-
87
- expect(original_hash[:one][:one_two]).to eq(duplicate_hash[:one][:one_two])
88
- expect(original_hash[:one][:one_two].object_id).not_to eq(duplicate_hash[:one][:one_two].object_id)
72
+ expect(compare_duplicate(original_hash, duplicate_hash)).to be_truthy
89
73
  end
90
74
 
91
- it "creates deep duplicate of array" do
92
- expect(original_array).to eq(duplicate_array)
93
- expect(original_array.object_id).not_to eq(duplicate_array.object_id)
75
+ it "creates a deep duplicate of the array" do
76
+ expect(compare_duplicate(original_array, duplicate_array)).to be_truthy
77
+ end
94
78
 
95
- expect(original_array[0]).to eq(duplicate_array[0])
96
- expect(original_array[0].object_id).not_to eq(duplicate_array[0].object_id)
79
+ def compare_duplicate(original, duplicate)
80
+ return false unless original == duplicate
81
+ return false if !primitive?(original) && original.equal?(duplicate)
97
82
 
98
- expect(original_array[1][0]).to eq(duplicate_array[1][0])
99
- expect(original_array[1][0].object_id).not_to eq(duplicate_array[1][0].object_id)
83
+ case original
84
+ when Array then compare_array(original, duplicate)
85
+ when Hash then compare_hash(original, duplicate)
86
+ else true
87
+ end
88
+ end
100
89
 
101
- expect(original_array[1][1][0]).to eq(duplicate_array[1][1][0])
102
- expect(original_array[1][1][0].object_id).not_to eq(duplicate_array[1][1][0].object_id)
90
+ def compare_array(original, duplicate)
91
+ original.each_with_index.all? do |el, i|
92
+ compare_duplicate(el, duplicate[i])
93
+ end
94
+ end
103
95
 
104
- expect(original_array[1][1][1]).to eq(duplicate_array[1][1][1])
105
- expect(original_array[1][1][1].object_id).not_to eq(duplicate_array[1][1][1].object_id)
96
+ def compare_hash(original, duplicate)
97
+ original.keys.all? do |key|
98
+ compare_duplicate(original[key], duplicate[key])
99
+ end
100
+ end
106
101
 
107
- expect(original_array[1][2]).to eq(duplicate_array[1][2])
108
- expect(original_array[1][2].object_id).not_to eq(duplicate_array[1][2].object_id)
102
+ def primitive?(value)
103
+ [Symbol, NilClass, TrueClass, FalseClass].include?(value.class)
109
104
  end
110
105
  end
111
106
  end
@@ -3,12 +3,15 @@
3
3
  require "spec_helper"
4
4
 
5
5
  RSpec.describe Lutaml::Model::Validation do
6
- class ValidationTestClass < Lutaml::Model::Serializable
7
- attribute :name, :string
8
- attribute :age, :integer
9
- attribute :email, :string, values: ["test@example.com", "user@example.com"]
10
- attribute :tags, :string, collection: true
11
- attribute :role, :string, collection: 1..3
6
+ before do
7
+ stub_const("ValidationTestClass", Class.new(Lutaml::Model::Serializable) do
8
+ attribute :name, :string
9
+ attribute :age, :integer
10
+ attribute :email, :string,
11
+ values: ["test@example.com", "user@example.com"]
12
+ attribute :tags, :string, collection: true
13
+ attribute :role, :string, collection: 1..3
14
+ end)
12
15
  end
13
16
 
14
17
  let(:valid_instance) do
@@ -13,7 +13,7 @@ RSpec.describe Lutaml::Model::XmlAdapter::OgaAdapter do
13
13
 
14
14
  let(:document) { described_class.parse(xml_string) }
15
15
 
16
- context "parsing XML with namespaces" do
16
+ context "when parsing XML with namespaces" do
17
17
  let(:child) { document.root.children.first }
18
18
 
19
19
  it "parses the root element with default namespace" do
@@ -37,7 +37,7 @@ RSpec.describe Lutaml::Model::XmlAdapter::OgaAdapter do
37
37
  end
38
38
  end
39
39
 
40
- context "generating XML with namespaces" do
40
+ context "when generating XML with namespaces" do
41
41
  it "generates XML with namespaces correctly" do
42
42
  xml_output = document.root.to_xml
43
43
  parsed_output = Moxml::Adapter::Oga.parse(xml_output)
@@ -14,7 +14,7 @@ RSpec.describe Lutaml::Model::XmlAdapter::OxAdapter do
14
14
 
15
15
  let(:document) { described_class.parse(xml_string) }
16
16
 
17
- context "parsing XML with namespaces" do
17
+ context "when parsing XML with namespaces" do
18
18
  it "parses the root element with default namespace" do
19
19
  expect(document.root.name).to eq("root")
20
20
  expect(document.root.namespace.uri).to eq("http://example.com/default")
@@ -42,7 +42,7 @@ RSpec.describe Lutaml::Model::XmlAdapter::OxAdapter do
42
42
  end
43
43
  end
44
44
 
45
- context "generating XML with namespaces" do
45
+ context "when generating XML with namespaces" do
46
46
  it "generates XML with namespaces correctly" do
47
47
  xml_output = document.to_xml
48
48
  parsed_output = Ox.parse(xml_output)