lutaml-model 0.3.23 → 0.3.25

Sign up to get free protection for your applications and to get access to all the features.
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