lutaml-model 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,21 +1,21 @@
1
1
  require "spec_helper"
2
2
  require "lutaml/model/schema"
3
3
 
4
- RSpec.describe Lutaml::Model::Schema::XsdSchema do
5
- module SchemaGeneration
6
- class Glaze < Lutaml::Model::Serializable
7
- attribute :color, Lutaml::Model::Type::String
8
- attribute :finish, Lutaml::Model::Type::String
9
- end
4
+ module SchemaGeneration
5
+ class Glaze < Lutaml::Model::Serializable
6
+ attribute :color, Lutaml::Model::Type::String
7
+ attribute :finish, Lutaml::Model::Type::String
8
+ end
10
9
 
11
- class Vase < Lutaml::Model::Serializable
12
- attribute :height, Lutaml::Model::Type::Float
13
- attribute :diameter, Lutaml::Model::Type::Float
14
- attribute :glaze, Glaze
15
- attribute :materials, Lutaml::Model::Type::String, collection: true
16
- end
10
+ class Vase < Lutaml::Model::Serializable
11
+ attribute :height, Lutaml::Model::Type::Float
12
+ attribute :diameter, Lutaml::Model::Type::Float
13
+ attribute :glaze, Glaze
14
+ attribute :materials, Lutaml::Model::Type::String, collection: true
17
15
  end
16
+ end
18
17
 
18
+ RSpec.describe Lutaml::Model::Schema::XsdSchema do
19
19
  describe ".generate" do
20
20
  it "generates an XSD schema for nested Serialize objects" do
21
21
  schema = described_class.generate(SchemaGeneration::Vase, pretty: true)
@@ -1,21 +1,21 @@
1
1
  require "spec_helper"
2
2
  require "lutaml/model/schema"
3
3
 
4
- RSpec.describe Lutaml::Model::Schema::YamlSchema do
5
- module SchemaGeneration
6
- class Glaze < Lutaml::Model::Serializable
7
- attribute :color, Lutaml::Model::Type::String
8
- attribute :finish, Lutaml::Model::Type::String
9
- end
4
+ module SchemaGeneration
5
+ class Glaze < Lutaml::Model::Serializable
6
+ attribute :color, Lutaml::Model::Type::String
7
+ attribute :finish, Lutaml::Model::Type::String
8
+ end
10
9
 
11
- class Vase < Lutaml::Model::Serializable
12
- attribute :height, Lutaml::Model::Type::Float
13
- attribute :diameter, Lutaml::Model::Type::Float
14
- attribute :glaze, Glaze
15
- attribute :materials, Lutaml::Model::Type::String, collection: true
16
- end
10
+ class Vase < Lutaml::Model::Serializable
11
+ attribute :height, Lutaml::Model::Type::Float
12
+ attribute :diameter, Lutaml::Model::Type::Float
13
+ attribute :glaze, Glaze
14
+ attribute :materials, Lutaml::Model::Type::String, collection: true
17
15
  end
16
+ end
18
17
 
18
+ RSpec.describe Lutaml::Model::Schema::YamlSchema do
19
19
  describe ".generate" do
20
20
  it "generates a YAML schema for nested Serialize objects" do
21
21
  schema = described_class.generate(SchemaGeneration::Vase)
@@ -56,45 +56,10 @@ RSpec.describe "Sequence" do
56
56
  context "with nesting sequence" do
57
57
  let(:mapper) { SequenceSpec::Ceramic }
58
58
 
59
- it "don't raise error for a valid instance, if given attribute for sequence has correct order" do
60
- xml = <<~XML
61
- <Ceramic>
62
- <tag>Nik</tag>
63
- <id>1</id>
64
- <name>Vase</name>
65
- <type>Decorative</type>
66
- <color>Blue</color>
67
- <bold>Heading</bold>
68
- <text>Header</text>
69
- <usage>Indoor</usage>
70
- <size>Medium</size>
71
- <first_name>Dale</first_name>
72
- <last_name>Steyn</last_name>
73
- <temperature>Normal</temperature>
74
- </Ceramic>
75
- XML
76
-
77
- expect { mapper.from_xml(xml) }.not_to raise_error
78
- end
79
-
80
- it "don't raise error for a valid instance with sequence range, if given attribute for sequence has correct order" do
81
- xml = <<~XML
82
- <collection>
83
- <ceramic>
84
- <tag>Nik</tag>
85
- <id>1</id>
86
- <name>Vase</name>
87
- <type>Decorative</type>
88
- <color>Blue</color>
89
- <bold>Heading</bold>
90
- <text>Header</text>
91
- <usage>Indoor</usage>
92
- <size>Medium</size>
93
- <first_name>Dale</first_name>
94
- <last_name>Steyn</last_name>
95
- <temperature>Normal</temperature>
96
- </ceramic>
97
- <ceramic>
59
+ context "when given attribute for sequence has correct order" do
60
+ let(:xml) do
61
+ <<~XML
62
+ <Ceramic>
98
63
  <tag>Nik</tag>
99
64
  <id>1</id>
100
65
  <name>Vase</name>
@@ -107,95 +72,146 @@ RSpec.describe "Sequence" do
107
72
  <first_name>Dale</first_name>
108
73
  <last_name>Steyn</last_name>
109
74
  <temperature>Normal</temperature>
110
- </ceramic>
111
- </collection>
112
- XML
75
+ </Ceramic>
76
+ XML
77
+ end
113
78
 
114
- expect do
115
- SequenceSpec::CeramicCollection.from_xml(xml)
116
- end.not_to raise_error
79
+ it "does not raise error" do
80
+ expect { mapper.from_xml(xml) }.not_to raise_error
81
+ end
117
82
  end
118
83
 
119
- it "raises error, if given attributes order is incorrect in sequence" do
120
- xml = <<~XML
121
- <Ceramic>
122
- <tag>Nik</tag>
123
- <temperature>High</temperature>
124
- <first_name>Micheal</first_name>
125
- <id>1</id>
126
- <name>Vase</name>
127
- <type>Decorative</type>
128
- <color>Blue</color>
129
- <bold>Heading</bold>
130
- <usage>Indoor</usage>
131
- <size>Medium</size>
132
- <last_name>Johnson</last_name>
133
- <text>Header</text>
134
- </Ceramic>
135
- XML
84
+ context "when given attribute for sequence collection has correct order" do
85
+ let(:xml) do
86
+ <<~XML
87
+ <collection>
88
+ <ceramic>
89
+ <tag>Nik</tag>
90
+ <id>1</id>
91
+ <name>Vase</name>
92
+ <type>Decorative</type>
93
+ <color>Blue</color>
94
+ <bold>Heading</bold>
95
+ <text>Header</text>
96
+ <usage>Indoor</usage>
97
+ <size>Medium</size>
98
+ <first_name>Dale</first_name>
99
+ <last_name>Steyn</last_name>
100
+ <temperature>Normal</temperature>
101
+ </ceramic>
102
+ <ceramic>
103
+ <tag>Nik</tag>
104
+ <id>1</id>
105
+ <name>Vase</name>
106
+ <type>Decorative</type>
107
+ <color>Blue</color>
108
+ <bold>Heading</bold>
109
+ <text>Header</text>
110
+ <usage>Indoor</usage>
111
+ <size>Medium</size>
112
+ <first_name>Dale</first_name>
113
+ <last_name>Steyn</last_name>
114
+ <temperature>Normal</temperature>
115
+ </ceramic>
116
+ </collection>
117
+ XML
118
+ end
136
119
 
137
- expect do
138
- mapper.from_xml(xml)
139
- end.to raise_error(Lutaml::Model::IncorrectSequenceError) do |error|
140
- expect(error.message).to eq("Element `usage` does not match the expected sequence order element `text`")
120
+ it "does not raise error" do
121
+ expect do
122
+ SequenceSpec::CeramicCollection.from_xml(xml)
123
+ end.not_to raise_error
141
124
  end
142
125
  end
143
126
 
144
- it "raises error with sequence range, if given attributes order is incorrect in sequence" do
145
- invalid_xml = <<~XML
146
- <collection>
147
- <ceramic>
127
+ context "when given attributes order is incorrect in sequence" do
128
+ let(:xml) do
129
+ <<~XML
130
+ <Ceramic>
131
+ <tag>Nik</tag>
132
+ <temperature>High</temperature>
133
+ <first_name>Micheal</first_name>
148
134
  <id>1</id>
149
135
  <name>Vase</name>
150
136
  <type>Decorative</type>
151
137
  <color>Blue</color>
152
138
  <bold>Heading</bold>
153
- <text>Header</text>
154
139
  <usage>Indoor</usage>
155
140
  <size>Medium</size>
156
- <first_name>Dale</first_name>
157
- <last_name>Steyn</last_name>
158
- <temperature>Normal</temperature>
159
- <tag>Nik</tag>
160
- </ceramic>
161
-
162
- <ceramic>
163
- <id>2</id>
164
- <name>Nick</name>
165
- <type>Unique</type>
166
- <color>Red</color>
167
- <bold>Name</bold>
168
- <text>Body</text>
169
- <usage>Outdoor</usage>
170
- <size>Small</size>
171
- <first_name>Smith</first_name>
172
- <last_name>Ash</last_name>
173
- <temperature>High</temperature>
174
- <tag>Adid</tag>
175
- </ceramic>
176
-
177
- <ceramic>
178
- <id>3</id>
179
- <name>Starc</name>
180
- <type>Int</type>
181
- <color>White</color>
182
- <bold>Act</bold>
183
- <text>Footer</text>
184
- <usage>Nothing</usage>
185
- <size>Large</size>
186
- <first_name>Dale</first_name>
187
- <last_name>Steyn</last_name>
188
- <temperature>Normal</temperature>
189
- <tag>Bet</tag>
190
- </ceramic>
191
- </collection>
192
- XML
141
+ <last_name>Johnson</last_name>
142
+ <text>Header</text>
143
+ </Ceramic>
144
+ XML
145
+ end
193
146
 
194
- expect do
195
- SequenceSpec::CeramicCollection.from_xml(invalid_xml).validate!
196
- end.to raise_error(Lutaml::Model::ValidationError) do |error|
197
- expect(error).to include(Lutaml::Model::CollectionCountOutOfRangeError)
198
- expect(error.error_messages).to eq(["ceramic count is 3, must be between 1 and 2"])
147
+ it "raises IncorrectSequenceError error" do
148
+ expect do
149
+ mapper.from_xml(xml)
150
+ end.to raise_error(Lutaml::Model::IncorrectSequenceError) do |error|
151
+ expect(error.message).to eq("Element `usage` does not match the expected sequence order element `text`")
152
+ end
153
+ end
154
+ end
155
+
156
+ context "when given attributes order is incorrect in sequence collection" do
157
+ let(:xml) do
158
+ <<~XML
159
+ <collection>
160
+ <ceramic>
161
+ <id>1</id>
162
+ <name>Vase</name>
163
+ <type>Decorative</type>
164
+ <color>Blue</color>
165
+ <bold>Heading</bold>
166
+ <text>Header</text>
167
+ <usage>Indoor</usage>
168
+ <size>Medium</size>
169
+ <first_name>Dale</first_name>
170
+ <last_name>Steyn</last_name>
171
+ <temperature>Normal</temperature>
172
+ <tag>Nik</tag>
173
+ </ceramic>
174
+
175
+ <ceramic>
176
+ <id>2</id>
177
+ <name>Nick</name>
178
+ <type>Unique</type>
179
+ <color>Red</color>
180
+ <bold>Name</bold>
181
+ <text>Body</text>
182
+ <usage>Outdoor</usage>
183
+ <size>Small</size>
184
+ <first_name>Smith</first_name>
185
+ <last_name>Ash</last_name>
186
+ <temperature>High</temperature>
187
+ <tag>Adid</tag>
188
+ </ceramic>
189
+
190
+ <ceramic>
191
+ <id>3</id>
192
+ <name>Starc</name>
193
+ <type>Int</type>
194
+ <color>White</color>
195
+ <bold>Act</bold>
196
+ <text>Footer</text>
197
+ <usage>Nothing</usage>
198
+ <size>Large</size>
199
+ <first_name>Dale</first_name>
200
+ <last_name>Steyn</last_name>
201
+ <temperature>Normal</temperature>
202
+ <tag>Bet</tag>
203
+ </ceramic>
204
+ </collection>
205
+ XML
206
+ end
207
+
208
+ it "raises CollectionCountOutOfRangeError error" do
209
+ expect do
210
+ SequenceSpec::CeramicCollection.from_xml(xml).validate!
211
+ end.to raise_error(Lutaml::Model::ValidationError) do |error|
212
+ expect(error).to include(Lutaml::Model::CollectionCountOutOfRangeError)
213
+ expect(error.error_messages).to eq(["ceramic count is 3, must be between 1 and 2"])
214
+ end
199
215
  end
200
216
  end
201
217
 
@@ -3,37 +3,39 @@ require "lutaml/model/toml_adapter/toml_rb_adapter"
3
3
  require "lutaml/model/toml_adapter/tomlib_adapter"
4
4
  require_relative "../../fixtures/sample_model"
5
5
 
6
- RSpec.shared_examples "a TOML adapter" do |adapter_class|
7
- let(:attributes) { { name: "John Doe", age: 30 } }
8
- let(:model) { SampleModel.new(attributes) }
9
-
10
- let(:expected_toml) do
11
- if adapter_class == Lutaml::Model::TomlAdapter::TomlRbAdapter
12
- TomlRB.dump(attributes)
13
- elsif adapter_class == Lutaml::Model::TomlAdapter::TomlibAdapter
14
- Tomlib.dump(attributes)
6
+ RSpec.describe "TomlAdapter" do
7
+ shared_examples "a TOML adapter" do |adapter_class|
8
+ let(:attributes) { { name: "John Doe", age: 30 } }
9
+ let(:model) { SampleModel.new(attributes) }
10
+
11
+ let(:expected_toml) do
12
+ if adapter_class == Lutaml::Model::TomlAdapter::TomlRbAdapter
13
+ TomlRB.dump(attributes)
14
+ elsif adapter_class == Lutaml::Model::TomlAdapter::TomlibAdapter
15
+ Tomlib.dump(attributes)
16
+ end
15
17
  end
16
- end
17
18
 
18
- it "serializes to TOML" do
19
- toml = adapter_class.new(attributes).to_toml
19
+ it "serializes to TOML" do
20
+ toml = adapter_class.new(attributes).to_toml
20
21
 
21
- expect(toml).to eq(expected_toml)
22
- end
22
+ expect(toml).to eq(expected_toml)
23
+ end
23
24
 
24
- it "deserializes from TOML" do
25
- doc = adapter_class.parse(expected_toml)
26
- new_model = SampleModel.new(doc.to_h)
25
+ it "deserializes from TOML" do
26
+ doc = adapter_class.parse(expected_toml)
27
+ new_model = SampleModel.new(doc.to_h)
27
28
 
28
- expect(new_model.name).to eq("John Doe")
29
- expect(new_model.age).to eq(30)
29
+ expect(new_model.name).to eq("John Doe")
30
+ expect(new_model.age).to eq(30)
31
+ end
30
32
  end
31
- end
32
33
 
33
- RSpec.describe Lutaml::Model::TomlAdapter::TomlRbAdapter do
34
- it_behaves_like "a TOML adapter", described_class
35
- end
34
+ describe Lutaml::Model::TomlAdapter::TomlRbAdapter do
35
+ it_behaves_like "a TOML adapter", described_class
36
+ end
36
37
 
37
- RSpec.describe Lutaml::Model::TomlAdapter::TomlibAdapter do
38
- it_behaves_like "a TOML adapter", described_class
38
+ describe Lutaml::Model::TomlAdapter::TomlibAdapter do
39
+ it_behaves_like "a TOML adapter", described_class
40
+ end
39
41
  end
@@ -1,97 +1,97 @@
1
1
  require "spec_helper"
2
2
 
3
- RSpec.describe "Value Transformations" do
4
- module TransformationSpec
5
- # Class with only attribute-level transformations
6
- class AttributeTransformPerson < Lutaml::Model::Serializable
7
- attribute :name, :string, transform: {
8
- export: ->(value) { value.to_s.upcase },
3
+ module TransformationSpec
4
+ # Class with only attribute-level transformations
5
+ class AttributeTransformPerson < Lutaml::Model::Serializable
6
+ attribute :name, :string, transform: {
7
+ export: ->(value) { value.to_s.upcase },
8
+ }
9
+ attribute :email, :string, transform: {
10
+ import: ->(value) { "#{value}@example.com" },
11
+ }
12
+ attribute :tags, :string, collection: true, transform: {
13
+ export: ->(value) { value.map(&:upcase) },
14
+ import: ->(value) { value.map { |v| "#{v}-1" } },
15
+ }
16
+ end
17
+
18
+ # Class with only mapping-level transformations
19
+ class MappingTransformPerson < Lutaml::Model::Serializable
20
+ attribute :name, :string
21
+ attribute :email, :string
22
+ attribute :tags, :string, collection: true
23
+
24
+ json do
25
+ map "fullName", to: :name, transform: {
26
+ export: ->(value) { "Dr. #{value}" },
9
27
  }
10
- attribute :email, :string, transform: {
11
- import: ->(value) { "#{value}@example.com" },
28
+ map "emailAddress", to: :email, transform: {
29
+ import: ->(value) { value.gsub("at", "@") },
12
30
  }
13
- attribute :tags, :string, collection: true, transform: {
14
- export: ->(value) { value.map(&:upcase) },
15
- import: ->(value) { value.map { |v| "#{v}-1" } },
31
+ map "labels", to: :tags, transform: {
32
+ export: ->(value) { value.join("-|-") },
33
+ import: ->(value) { value.split("|") },
16
34
  }
17
35
  end
18
36
 
19
- # Class with only mapping-level transformations
20
- class MappingTransformPerson < Lutaml::Model::Serializable
21
- attribute :name, :string
22
- attribute :email, :string
23
- attribute :tags, :string, collection: true
24
-
25
- json do
26
- map "fullName", to: :name, transform: {
27
- export: ->(value) { "Dr. #{value}" },
28
- }
29
- map "emailAddress", to: :email, transform: {
30
- import: ->(value) { value.gsub("at", "@") },
31
- }
32
- map "labels", to: :tags, transform: {
33
- export: ->(value) { value.join("-|-") },
34
- import: ->(value) { value.split("|") },
35
- }
36
- end
37
-
38
- xml do
39
- root "person"
40
- map_element "full-name", to: :name, transform: {
41
- export: ->(value) { "Dr. #{value}" },
42
- }
43
- map_element "email-address", to: :email, transform: {
44
- import: ->(value) { value.gsub("at", "@") },
45
- }
46
- map_element "labels", to: :tags, transform: {
47
- export: ->(value) { value.join("-|-") },
48
- import: ->(value) { value.split("|") },
49
- }
50
- end
51
- end
52
-
53
- # Class with both attribute and mapping transformations
54
- class CombinedTransformPerson < Lutaml::Model::Serializable
55
- attribute :name, :string, transform: {
56
- export: ->(value) { value.to_s.capitalize },
57
- import: ->(value) { value.to_s.downcase },
37
+ xml do
38
+ root "person"
39
+ map_element "full-name", to: :name, transform: {
40
+ export: ->(value) { "Dr. #{value}" },
58
41
  }
59
- attribute :email, :string, transform: {
60
- export: lambda(&:downcase),
61
- import: lambda(&:downcase),
42
+ map_element "email-address", to: :email, transform: {
43
+ import: ->(value) { value.gsub("at", "@") },
44
+ }
45
+ map_element "labels", to: :tags, transform: {
46
+ export: ->(value) { value.join("-|-") },
47
+ import: ->(value) { value.split("|") },
48
+ }
49
+ end
50
+ end
51
+
52
+ # Class with both attribute and mapping transformations
53
+ class CombinedTransformPerson < Lutaml::Model::Serializable
54
+ attribute :name, :string, transform: {
55
+ export: ->(value) { value.to_s.capitalize },
56
+ import: ->(value) { value.to_s.downcase },
57
+ }
58
+ attribute :email, :string, transform: {
59
+ export: lambda(&:downcase),
60
+ import: lambda(&:downcase),
61
+ }
62
+ attribute :tags, :string, collection: true, transform: {
63
+ export: ->(value) { value.map(&:upcase) },
64
+ import: ->(value) { value.map { |v| "#{v}-1" } },
65
+ }
66
+
67
+ json do
68
+ map "fullName", to: :name, transform: {
69
+ export: ->(value) { "Prof. #{value}" },
70
+ import: ->(value) { value.gsub("Prof. ", "") },
62
71
  }
63
- attribute :tags, :string, collection: true, transform: {
64
- export: ->(value) { value.map(&:upcase) },
65
- import: ->(value) { value.map { |v| "#{v}-1" } },
72
+ map "contactEmail", to: :email, transform: {
73
+ export: ->(value) { "contact+#{value}" },
74
+ import: ->(value) { value.gsub("contact+", "") },
66
75
  }
76
+ map "skills", to: :tags
77
+ end
67
78
 
68
- json do
69
- map "fullName", to: :name, transform: {
70
- export: ->(value) { "Prof. #{value}" },
71
- import: ->(value) { value.gsub("Prof. ", "") },
72
- }
73
- map "contactEmail", to: :email, transform: {
74
- export: ->(value) { "contact+#{value}" },
75
- import: ->(value) { value.gsub("contact+", "") },
76
- }
77
- map "skills", to: :tags
78
- end
79
-
80
- xml do
81
- root "person"
82
- map_element "full-name", to: :name, transform: {
83
- export: ->(value) { "Prof. #{value}" },
84
- import: ->(value) { value.gsub("Prof. ", "") },
85
- }
86
- map_element "contact-email", to: :email, transform: {
87
- export: ->(value) { "contact+#{value}" },
88
- import: ->(value) { value.gsub("contact+", "") },
89
- }
90
- map_element "skills", to: :tags
91
- end
79
+ xml do
80
+ root "person"
81
+ map_element "full-name", to: :name, transform: {
82
+ export: ->(value) { "Prof. #{value}" },
83
+ import: ->(value) { value.gsub("Prof. ", "") },
84
+ }
85
+ map_element "contact-email", to: :email, transform: {
86
+ export: ->(value) { "contact+#{value}" },
87
+ import: ->(value) { value.gsub("contact+", "") },
88
+ }
89
+ map_element "skills", to: :tags
92
90
  end
93
91
  end
92
+ end
94
93
 
94
+ RSpec.describe "Value Transformations" do
95
95
  describe "Attribute-only transformations" do
96
96
  let(:attribute_person) do
97
97
  TransformationSpec::AttributeTransformPerson.new(
@@ -71,14 +71,14 @@ RSpec.describe Lutaml::Model::Type::Boolean do
71
71
  end
72
72
 
73
73
  context "with key-value serialization" do
74
- let(:yaml) do
74
+ let(:attrs) do
75
75
  {
76
76
  "name" => "John Smith",
77
77
  "full_time" => true,
78
78
  "on_leave" => false,
79
79
  "remote" => nil,
80
80
  "active" => nil,
81
- }.to_yaml
81
+ }
82
82
  end
83
83
 
84
84
  let(:expected_yaml) do
@@ -91,7 +91,7 @@ RSpec.describe Lutaml::Model::Type::Boolean do
91
91
  end
92
92
 
93
93
  it "deserializes boolean values correctly" do
94
- employee = BooleanSpec::Employee.from_yaml(yaml)
94
+ employee = BooleanSpec::Employee.from_yaml(attrs.to_yaml)
95
95
 
96
96
  expect(employee.name).to eq("John Smith")
97
97
  expect(employee.full_time).to be true
@@ -101,13 +101,7 @@ RSpec.describe Lutaml::Model::Type::Boolean do
101
101
  end
102
102
 
103
103
  it "serializes boolean values correctly" do
104
- employee = BooleanSpec::Employee.new(
105
- name: "John Smith",
106
- full_time: true,
107
- on_leave: false,
108
- remote: nil,
109
- active: nil,
110
- )
104
+ employee = BooleanSpec::Employee.new(attrs)
111
105
 
112
106
  yaml_output = employee.to_yaml
113
107
  expect(yaml_output).to eq(expected_yaml)
@@ -112,10 +112,10 @@ RSpec.describe Lutaml::Model::Type do
112
112
  hide_const("BigDecimal")
113
113
  end
114
114
 
115
+ let(:serialized) { Lutaml::Model::Type::Decimal.serialize("123.45") }
116
+
115
117
  it "raises TypeNotEnabledError" do
116
- expect do
117
- Lutaml::Model::Type::Decimal.serialize("123.45")
118
- end.to raise_error(
118
+ expect { serialized }.to raise_error(
119
119
  Lutaml::Model::TypeNotEnabledError,
120
120
  /Decimal/,
121
121
  )