lutaml-model 0.3.23 → 0.3.25

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +35 -16
  3. data/README.adoc +274 -28
  4. data/lib/lutaml/model/attribute.rb +18 -8
  5. data/lib/lutaml/model/error/type_error.rb +9 -0
  6. data/lib/lutaml/model/error/unknown_type_error.rb +9 -0
  7. data/lib/lutaml/model/error/validation_error.rb +0 -1
  8. data/lib/lutaml/model/error.rb +2 -0
  9. data/lib/lutaml/model/serialize.rb +7 -2
  10. data/lib/lutaml/model/type/boolean.rb +38 -0
  11. data/lib/lutaml/model/type/date.rb +35 -0
  12. data/lib/lutaml/model/type/date_time.rb +32 -4
  13. data/lib/lutaml/model/type/decimal.rb +42 -0
  14. data/lib/lutaml/model/type/float.rb +37 -0
  15. data/lib/lutaml/model/type/hash.rb +62 -0
  16. data/lib/lutaml/model/type/integer.rb +41 -0
  17. data/lib/lutaml/model/type/string.rb +49 -0
  18. data/lib/lutaml/model/type/time.rb +49 -0
  19. data/lib/lutaml/model/type/time_without_date.rb +37 -5
  20. data/lib/lutaml/model/type/value.rb +52 -0
  21. data/lib/lutaml/model/type.rb +50 -114
  22. data/lib/lutaml/model/version.rb +1 -1
  23. data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +5 -2
  24. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +2 -1
  25. data/lib/lutaml/model/xml_adapter/xml_document.rb +0 -2
  26. data/lutaml-model.gemspec +1 -1
  27. data/spec/address_spec.rb +170 -0
  28. data/spec/fixtures/address.rb +33 -0
  29. data/spec/fixtures/person.rb +73 -0
  30. data/spec/fixtures/sample_model.rb +40 -0
  31. data/spec/fixtures/vase.rb +38 -0
  32. data/spec/fixtures/xml/special_char.xml +13 -0
  33. data/spec/lutaml/model/attribute_spec.rb +112 -0
  34. data/spec/lutaml/model/collection_spec.rb +299 -0
  35. data/spec/lutaml/model/comparable_model_spec.rb +106 -0
  36. data/spec/lutaml/model/custom_model_spec.rb +410 -0
  37. data/spec/lutaml/model/custom_serialization_spec.rb +170 -0
  38. data/spec/lutaml/model/defaults_spec.rb +221 -0
  39. data/spec/lutaml/model/delegation_spec.rb +340 -0
  40. data/spec/lutaml/model/inheritance_spec.rb +92 -0
  41. data/spec/lutaml/model/json_adapter_spec.rb +37 -0
  42. data/spec/lutaml/model/key_value_mapping_spec.rb +86 -0
  43. data/spec/lutaml/model/map_content_spec.rb +118 -0
  44. data/spec/lutaml/model/mixed_content_spec.rb +625 -0
  45. data/spec/lutaml/model/namespace_spec.rb +57 -0
  46. data/spec/lutaml/model/ordered_content_spec.rb +83 -0
  47. data/spec/lutaml/model/render_nil_spec.rb +138 -0
  48. data/spec/lutaml/model/schema/json_schema_spec.rb +79 -0
  49. data/spec/lutaml/model/schema/relaxng_schema_spec.rb +60 -0
  50. data/spec/lutaml/model/schema/xsd_schema_spec.rb +55 -0
  51. data/spec/lutaml/model/schema/yaml_schema_spec.rb +47 -0
  52. data/spec/lutaml/model/serializable_spec.rb +297 -0
  53. data/spec/lutaml/model/serializable_validation_spec.rb +85 -0
  54. data/spec/lutaml/model/simple_model_spec.rb +314 -0
  55. data/spec/lutaml/model/toml_adapter_spec.rb +39 -0
  56. data/spec/lutaml/model/type/boolean_spec.rb +54 -0
  57. data/spec/lutaml/model/type/date_spec.rb +118 -0
  58. data/spec/lutaml/model/type/date_time_spec.rb +127 -0
  59. data/spec/lutaml/model/type/decimal_spec.rb +125 -0
  60. data/spec/lutaml/model/type/float_spec.rb +191 -0
  61. data/spec/lutaml/model/type/hash_spec.rb +63 -0
  62. data/spec/lutaml/model/type/integer_spec.rb +145 -0
  63. data/spec/lutaml/model/type/string_spec.rb +150 -0
  64. data/spec/lutaml/model/type/time_spec.rb +142 -0
  65. data/spec/lutaml/model/type/time_without_date_spec.rb +125 -0
  66. data/spec/lutaml/model/type_spec.rb +276 -0
  67. data/spec/lutaml/model/utils_spec.rb +79 -0
  68. data/spec/lutaml/model/validation_spec.rb +83 -0
  69. data/spec/lutaml/model/with_child_mapping_spec.rb +174 -0
  70. data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +56 -0
  71. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +56 -0
  72. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +61 -0
  73. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +251 -0
  74. data/spec/lutaml/model/xml_adapter_spec.rb +178 -0
  75. data/spec/lutaml/model/xml_mapping_spec.rb +863 -0
  76. data/spec/lutaml/model/yaml_adapter_spec.rb +30 -0
  77. data/spec/lutaml/model_spec.rb +1 -0
  78. data/spec/person_spec.rb +161 -0
  79. data/spec/spec_helper.rb +33 -0
  80. metadata +66 -2
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.3.23"
5
+ VERSION = "0.3.25"
6
6
  end
7
7
  end
@@ -39,6 +39,8 @@ module Lutaml
39
39
  )
40
40
  add_namespace_prefix(prefix)
41
41
 
42
+ element_name = "#{element_name}_" if respond_to?(element_name)
43
+
42
44
  if block_given?
43
45
  public_send(element_name, attributes) do
44
46
  xml.parent.namespace = nil if prefix.nil? && !prefix_unset
@@ -54,7 +56,8 @@ module Lutaml
54
56
  element = element.xml.parent
55
57
  end
56
58
 
57
- element << text.to_s
59
+ text_node = ::Nokogiri::XML::Text.new(text.to_s, element)
60
+ element.add_child(text_node)
58
61
  end
59
62
 
60
63
  def add_namespace_prefix(prefix)
@@ -64,7 +67,7 @@ module Lutaml
64
67
  end
65
68
 
66
69
  def method_missing(method_name, *args, &block)
67
- if block
70
+ if block_given?
68
71
  xml.public_send(method_name, *args, &block)
69
72
  else
70
73
  xml.public_send(method_name, *args)
@@ -14,6 +14,7 @@ module Lutaml
14
14
 
15
15
  def to_xml(options = {})
16
16
  builder = Builder::Ox.build
17
+ builder.xml.instruct(:xml, encoding: options[:encoding] || "UTF-8", version: options[:version])
17
18
 
18
19
  if @root.is_a?(Lutaml::Model::XmlAdapter::OxElement)
19
20
  @root.build_xml(builder)
@@ -26,7 +27,7 @@ module Lutaml
26
27
  end
27
28
 
28
29
  xml_data = builder.xml.to_s
29
- options[:declaration] ? declaration(options) + xml_data : xml_data
30
+ options[:declaration] ? xml_data : xml_data.sub(/\A<\?xml[^>]*\?>\n?/, "")
30
31
  end
31
32
 
32
33
  private
@@ -84,8 +84,6 @@ module Lutaml
84
84
 
85
85
  value = if child.text?
86
86
  child.text
87
- elsif attr&.raw?
88
- child.children.map(&:to_xml).join
89
87
  else
90
88
  parse_element(child, attr&.type || klass, format)
91
89
  end
data/lutaml-model.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  # RubyGem that have been added into git.
26
26
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
27
  `git ls-files -z`.split("\x0").reject do |f|
28
- f.match(%r{^(test|spec|features)/})
28
+ f.match(%r{^(test|features)/})
29
29
  end
30
30
  end
31
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -0,0 +1,170 @@
1
+ require "spec_helper"
2
+ require_relative "fixtures/address"
3
+ require_relative "fixtures/person"
4
+
5
+ RSpec.describe Address do
6
+ let(:person1) do
7
+ {
8
+ first_name: "Tom",
9
+ last_name: "Warren",
10
+ age: 40,
11
+ height: 5.8,
12
+ birthdate: Date.new(1980, 2, 15),
13
+ last_login: "1980-02-15T10:00:00Z",
14
+ wakeup_time: "07:30:00",
15
+ active: true,
16
+ }
17
+ end
18
+ let(:person2) do
19
+ {
20
+ first_name: "Jack",
21
+ last_name: "Warren",
22
+ age: 35,
23
+ height: 5.9,
24
+ birthdate: Date.new(1985, 5, 20),
25
+ last_login: "1985-05-20T09:00:00Z",
26
+ wakeup_time: "06:45:00",
27
+ active: false,
28
+ }
29
+ end
30
+ let(:attributes) do
31
+ {
32
+ country: "USA",
33
+ post_code: "01001",
34
+ person: [person1, person2],
35
+ }
36
+ end
37
+ let(:address) { described_class.new(attributes) }
38
+
39
+ it "serializes to JSON with a collection of persons" do
40
+ expected_json = {
41
+ country: "USA",
42
+ postCode: "01001",
43
+ person: [
44
+ {
45
+ firstName: "Tom",
46
+ lastName: "Warren",
47
+ age: 40,
48
+ height: 5.8,
49
+ birthdate: "1980-02-15",
50
+ lastLogin: "1980-02-15T10:00:00+00:00",
51
+ wakeupTime: "07:30:00",
52
+ active: true,
53
+ },
54
+ {
55
+ firstName: "Jack",
56
+ lastName: "Warren",
57
+ age: 35,
58
+ height: 5.9,
59
+ birthdate: "1985-05-20",
60
+ lastLogin: "1985-05-20T09:00:00+00:00",
61
+ wakeupTime: "06:45:00",
62
+ active: false,
63
+ },
64
+ ],
65
+ }.to_json
66
+
67
+ expect(address.to_json).to eq(expected_json)
68
+ end
69
+
70
+ it "deserializes from JSON with a collection of persons" do
71
+ json = {
72
+ country: "USA",
73
+ postCode: "01001",
74
+ person: [
75
+ {
76
+ firstName: "Tom",
77
+ lastName: "Warren",
78
+ age: 40,
79
+ height: 5.8,
80
+ birthdate: "1980-02-15",
81
+ lastLogin: "1980-02-15T10:00:00Z",
82
+ wakeupTime: "07:30:00",
83
+ active: true,
84
+ },
85
+ {
86
+ firstName: "Jack",
87
+ lastName: "Warren",
88
+ age: 35,
89
+ height: 5.9,
90
+ birthdate: "1985-05-20",
91
+ lastLogin: "1985-05-20T09:00:00Z",
92
+ wakeupTime: "06:45:00",
93
+ active: false,
94
+ },
95
+ ],
96
+ }.to_json
97
+
98
+ address_from_json = described_class.from_json(json)
99
+ expect(address_from_json.country).to eq("USA")
100
+ expect(address_from_json.post_code).to eq("01001")
101
+ expect(address_from_json.person.first.first_name).to eq("Tom")
102
+ expect(address_from_json.person.last.first_name).to eq("Jack")
103
+ end
104
+
105
+ it "serializes to XML with a collection of persons" do
106
+ expected_xml = <<~XML
107
+ <Address xmlns:p="http://example.com/person" xmlns:nsp1="http://example.com/nsp1">
108
+ <Country>USA</Country>
109
+ <PostCode>01001</PostCode>
110
+ <p:Person>
111
+ <nsp1:FirstName>Tom</nsp1:FirstName>
112
+ <nsp1:LastName>Warren</nsp1:LastName>
113
+ <p:Age>40</p:Age>
114
+ <p:Height>5.8</p:Height>
115
+ <p:Birthdate>1980-02-15</p:Birthdate>
116
+ <p:LastLogin>1980-02-15T10:00:00+00:00</p:LastLogin>
117
+ <p:WakeupTime>07:30:00</p:WakeupTime>
118
+ <p:Active>true</p:Active>
119
+ </p:Person>
120
+ <p:Person>
121
+ <nsp1:FirstName>Jack</nsp1:FirstName>
122
+ <nsp1:LastName>Warren</nsp1:LastName>
123
+ <p:Age>35</p:Age>
124
+ <p:Height>5.9</p:Height>
125
+ <p:Birthdate>1985-05-20</p:Birthdate>
126
+ <p:LastLogin>1985-05-20T09:00:00+00:00</p:LastLogin>
127
+ <p:WakeupTime>06:45:00</p:WakeupTime>
128
+ <p:Active>false</p:Active>
129
+ </p:Person>
130
+ </Address>
131
+ XML
132
+
133
+ expect(address.to_xml).to be_equivalent_to(expected_xml)
134
+ end
135
+
136
+ it "deserializes from XML with a collection of persons" do
137
+ xml = <<~XML
138
+ <Address xmlns:p="http://example.com/person" xmlns:nsp1="http://example.com/nsp1">
139
+ <Country>USA</Country>
140
+ <PostCode>01001</PostCode>
141
+ <Person>
142
+ <nsp1:FirstName>Tom</nsp1:FirstName>
143
+ <nsp1:LastName>Warren</nsp1:LastName>
144
+ <Age>40</Age>
145
+ <Height>5.8</Height>
146
+ <Birthdate>1980-02-15</Birthdate>
147
+ <LastLogin>1980-02-15T10:00:00Z</LastLogin>
148
+ <WakeupTime>07:30:00</WakeupTime>
149
+ <Active>true</Active>
150
+ </Person>
151
+ <Person>
152
+ <nsp1:FirstName>Jack</nsp1:FirstName>
153
+ <nsp1:LastName>Warren</nsp1:LastName>
154
+ <Age>35</Age>
155
+ <Height>5.9</Height>
156
+ <Birthdate>1985-05-20</Birthdate>
157
+ <LastLogin>1985-05-20T09:00:00Z</LastLogin>
158
+ <WakeupTime>06:45:00</WakeupTime>
159
+ <Active>false</Active>
160
+ </Person>
161
+ </Address>
162
+ XML
163
+
164
+ address_from_xml = described_class.from_xml(xml)
165
+ expect(address_from_xml.country).to eq("USA")
166
+ expect(address_from_xml.post_code).to eq("01001")
167
+ expect(address_from_xml.person.first.first_name).to eq("Tom")
168
+ expect(address_from_xml.person.last.first_name).to eq("Jack")
169
+ end
170
+ end
@@ -0,0 +1,33 @@
1
+ require "lutaml/model"
2
+ require_relative "person"
3
+
4
+ class Address < Lutaml::Model::Serializable
5
+ attribute :country, Lutaml::Model::Type::String
6
+ attribute :post_code, Lutaml::Model::Type::String
7
+ attribute :person, Person, collection: true
8
+
9
+ json do
10
+ map "country", to: :country
11
+ map "postCode", to: :post_code
12
+ map "person", to: :person
13
+ end
14
+
15
+ xml do
16
+ root "Address"
17
+ map_element "Country", to: :country
18
+ map_element "PostCode", to: :post_code
19
+ map_element "Person", to: :person
20
+ end
21
+
22
+ yaml do
23
+ map "country", to: :country
24
+ map "postCode", to: :post_code
25
+ map "person", to: :person
26
+ end
27
+
28
+ toml do
29
+ map "country", to: :country
30
+ map "post_code", to: :post_code
31
+ map "person", to: :person
32
+ end
33
+ end
@@ -0,0 +1,73 @@
1
+ require "lutaml/model"
2
+
3
+ class Person < Lutaml::Model::Serializable
4
+ attribute :first_name, Lutaml::Model::Type::String
5
+ attribute :last_name, Lutaml::Model::Type::String
6
+ attribute :age, Lutaml::Model::Type::Integer
7
+ attribute :height, Lutaml::Model::Type::Float
8
+ attribute :birthdate, Lutaml::Model::Type::Date
9
+ attribute :last_login, Lutaml::Model::Type::DateTime
10
+ attribute :wakeup_time, Lutaml::Model::Type::TimeWithoutDate
11
+ attribute :active, Lutaml::Model::Type::Boolean
12
+
13
+ xml do
14
+ root "Person"
15
+ namespace "http://example.com/person", "p"
16
+
17
+ map_element "FirstName",
18
+ to: :first_name,
19
+ namespace: "http://example.com/nsp1",
20
+ prefix: "nsp1"
21
+ map_element "LastName",
22
+ to: :last_name,
23
+ namespace: "http://example.com/nsp1",
24
+ prefix: "nsp1"
25
+ map_element "Age", to: :age
26
+ map_element "Height", to: :height
27
+ map_element "Birthdate", to: :birthdate
28
+ map_element "LastLogin", to: :last_login
29
+ map_element "WakeupTime", to: :wakeup_time
30
+ map_element "Active", to: :active
31
+ end
32
+
33
+ json do
34
+ map "firstName", to: :first_name
35
+ map "lastName", to: :last_name
36
+ map "age", to: :age
37
+ map "height", to: :height
38
+ map "birthdate", to: :birthdate
39
+ map "lastLogin", to: :last_login
40
+ map "wakeupTime", to: :wakeup_time
41
+ map "active", to: :active
42
+ end
43
+
44
+ yaml do
45
+ map "firstName", to: :first_name
46
+ map "lastName", with: { to: :yaml_from_last_name, from: :yaml_to_last_name }
47
+ map "age", to: :age
48
+ map "height", to: :height
49
+ map "birthdate", to: :birthdate
50
+ map "lastLogin", to: :last_login
51
+ map "wakeupTime", to: :wakeup_time
52
+ map "active", to: :active
53
+ end
54
+
55
+ toml do
56
+ map "first_name", to: :first_name
57
+ map "last_name", to: :last_name
58
+ map "age", to: :age
59
+ map "height", to: :height
60
+ map "birthdate", to: :birthdate
61
+ map "last_login", to: :last_login
62
+ map "wakeup_time", to: :wakeup_time
63
+ map "active", to: :active
64
+ end
65
+
66
+ def yaml_from_last_name(model, doc)
67
+ doc["lastName"] = model.last_name
68
+ end
69
+
70
+ def yaml_to_last_name(model, value)
71
+ model.last_name = value
72
+ end
73
+ end
@@ -0,0 +1,40 @@
1
+ require "lutaml/model"
2
+
3
+ class SampleModelTag < Lutaml::Model::Serializable
4
+ attribute :text, :string, default: -> { "" }
5
+
6
+ xml do
7
+ root "Tag"
8
+ map_content to: :text
9
+ end
10
+ end
11
+
12
+ class SampleModel < Lutaml::Model::Serializable
13
+ attribute :name, :string, default: -> { "Anonymous" }
14
+ attribute :age, :integer, default: -> { 18 }
15
+ attribute :balance, :decimal, default: -> { BigDecimal("0.0") }
16
+ attribute :tags, SampleModelTag, collection: true
17
+ attribute :preferences, :hash, default: -> { { notifications: true } }
18
+ attribute :status, :string, default: -> { "active" }
19
+ attribute :large_number, :integer, default: -> { 0 }
20
+ attribute :email, :string, default: -> { "example@example.com" }
21
+ attribute :role, :string, values: %w[user admin guest], default: -> { "user" }
22
+
23
+ xml do
24
+ root "SampleModel"
25
+ map_element "Name", to: :name
26
+ map_element "Age", to: :age
27
+ map_element "Balance", to: :balance
28
+ map_element "Tags", to: :tags
29
+ map_element "Preferences", to: :preferences
30
+ map_element "Status", to: :status
31
+ map_element "LargeNumber", to: :large_number
32
+ map_element "Email", to: :email
33
+ map_element "Role", to: :role
34
+ end
35
+
36
+ yaml do
37
+ map "name", to: :name
38
+ map "age", to: :age
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ require "lutaml/model"
2
+
3
+ class Vase < Lutaml::Model::Serializable
4
+ attribute :height, Lutaml::Model::Type::Float
5
+ attribute :diameter, Lutaml::Model::Type::Float
6
+ attribute :material, Lutaml::Model::Type::String
7
+ attribute :manufacturer, Lutaml::Model::Type::String
8
+
9
+ json do
10
+ map "height", to: :height
11
+ map "diameter", to: :diameter
12
+ map "material", to: :material
13
+ map "manufacturer", to: :manufacturer
14
+ end
15
+
16
+ yaml do
17
+ map "height", to: :height
18
+ map "diameter", to: :diameter
19
+ map "material", to: :material
20
+ map "manufacturer", to: :manufacturer
21
+ end
22
+
23
+ toml do
24
+ map "height", to: :height
25
+ map "diameter", to: :diameter
26
+ map "material", to: :material
27
+ map "manufacturer", to: :manufacturer
28
+ end
29
+
30
+ xml do
31
+ root "vase"
32
+ namespace "https://example.com/vase/1.0"
33
+ map_element "height", to: :height
34
+ map_element "diameter", to: :diameter
35
+ map_element "material", to: :material
36
+ map_attribute "manufacturer", to: :manufacturer
37
+ end
38
+ end
@@ -0,0 +1,13 @@
1
+ <article>
2
+ <back>
3
+ <ref-list>
4
+ <ref>
5
+ <element-citation>
6
+ <source>Continuity of care: report of a scoping exercise for
7
+ the national co-ordinating centre for NHS Service Delivery and
8
+ Organisation R&#x0026;D (NCCSDO), Summer 2000</source>
9
+ </element-citation>
10
+ </ref>
11
+ </ref-list>
12
+ </back>
13
+ </article>
@@ -0,0 +1,112 @@
1
+ require "spec_helper"
2
+ require "lutaml/model"
3
+ require "pathname"
4
+
5
+ RSpec.describe Lutaml::Model::Attribute do
6
+ subject(:name_attr) do
7
+ described_class.new("name", :string)
8
+ end
9
+
10
+ let(:test_record_class) do
11
+ Class.new(Lutaml::Model::Serializable) do
12
+ attribute :age, :integer
13
+ attribute :image, :string
14
+ end
15
+ end
16
+
17
+ before do
18
+ stub_const("TestRecord", test_record_class)
19
+ end
20
+
21
+ it "cast to integer when assigning age" do
22
+ obj = TestRecord.new
23
+
24
+ expect { obj.age = "20" }.to change { obj.age }.from(nil).to(20)
25
+ end
26
+
27
+ it "cast to string when assigning image file" do
28
+ obj = TestRecord.new
29
+
30
+ expect { obj.image = Pathname.new("avatar.png") }
31
+ .to change { obj.image }
32
+ .from(nil)
33
+ .to("avatar.png")
34
+ end
35
+
36
+ describe "#validate_type!" do
37
+ let(:validate_type) { name_attr.method(:validate_type!) }
38
+
39
+ it "return true if type is a class" do
40
+ expect(validate_type.call(TestRecord)).to be(true)
41
+ end
42
+
43
+ it "return true if type is a valid symbol" do
44
+ expect(validate_type.call(:string)).to be(true)
45
+ end
46
+
47
+ it "return true if type is a valid string" do
48
+ expect(validate_type.call("String")).to be(true)
49
+ end
50
+
51
+ it "raise exception if type is invalid symbol" do
52
+ expect do
53
+ validate_type.call(:foo)
54
+ end.to raise_error(StandardError, "Unknown Lutaml::Model::Type: foo")
55
+ end
56
+
57
+ it "raise exception if type is invalid string" do
58
+ expect do
59
+ validate_type.call("foo")
60
+ end.to raise_error(StandardError, "Unknown Lutaml::Model::Type: foo")
61
+ end
62
+ end
63
+
64
+ describe "#cast_type!" do
65
+ it "cast :string to Lutaml::Model::Type::String" do
66
+ expect(name_attr.cast_type!(:string)).to eq(Lutaml::Model::Type::String)
67
+ end
68
+
69
+ it "cast :integer to Lutaml::Model::Type::Integer" do
70
+ expect(name_attr.cast_type!(:integer)).to eq(Lutaml::Model::Type::Integer)
71
+ end
72
+
73
+ it "raises ArgumentError on unknown type" do
74
+ expect { name_attr.cast_type!(:foobar) }
75
+ .to raise_error(ArgumentError, "Unknown Lutaml::Model::Type: foobar")
76
+ end
77
+ end
78
+
79
+ describe "#default?" do
80
+ context "when default is not set" do
81
+ let(:attribute) { described_class.new("name", :string) }
82
+
83
+ it { expect(attribute.default).to be_nil }
84
+ end
85
+
86
+ context "when default is set as a proc" do
87
+ it "returns the value" do
88
+ attribute = described_class.new("name", :string, default: -> { "John" })
89
+ expect(attribute.default).to eq("John")
90
+ end
91
+
92
+ it "returns the value casted to correct type" do
93
+ file = Pathname.new("avatar.png")
94
+ attribute = described_class.new("image", :string, default: -> { file })
95
+
96
+ expect(attribute.default).to eq("avatar.png")
97
+ end
98
+ end
99
+
100
+ context "when default is set as value" do
101
+ it "returns the value" do
102
+ attribute = described_class.new("name", :string, default: "John Doe")
103
+ expect(attribute.default).to eq("John Doe")
104
+ end
105
+
106
+ it "returns the value casted to correct type" do
107
+ attribute = described_class.new("age", :integer, default: "24")
108
+ expect(attribute.default).to eq(24)
109
+ end
110
+ end
111
+ end
112
+ end