lutaml-model 0.7.3 → 0.7.5
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.
- checksums.yaml +4 -4
- data/.envrc +1 -0
- data/.github/workflows/release.yml +3 -0
- data/.gitignore +6 -1
- data/.irbrc +1 -0
- data/.pryrc +1 -0
- data/.rubocop_todo.yml +25 -52
- data/README.adoc +2177 -192
- data/docs/custom_registers.adoc +228 -0
- data/docs/schema_generation.adoc +898 -0
- data/docs/schema_import.adoc +364 -0
- data/flake.lock +114 -0
- data/flake.nix +103 -0
- data/lib/lutaml/model/attribute.rb +230 -94
- data/lib/lutaml/model/choice.rb +30 -0
- data/lib/lutaml/model/collection.rb +194 -0
- data/lib/lutaml/model/comparable_model.rb +3 -3
- data/lib/lutaml/model/config.rb +26 -3
- data/lib/lutaml/model/constants.rb +2 -0
- data/lib/lutaml/model/error/element_count_out_of_range_error.rb +29 -0
- data/lib/lutaml/model/error/invalid_attribute_name_error.rb +15 -0
- data/lib/lutaml/model/error/invalid_attribute_options_error.rb +16 -0
- data/lib/lutaml/model/error/invalid_choice_range_error.rb +3 -5
- data/lib/lutaml/model/error/register/not_registrable_class_error.rb +11 -0
- data/lib/lutaml/model/error/type/invalid_value_error.rb +5 -3
- data/lib/lutaml/model/error/type/max_bound_error.rb +20 -0
- data/lib/lutaml/model/error/type/max_length_error.rb +20 -0
- data/lib/lutaml/model/error/type/min_bound_error.rb +20 -0
- data/lib/lutaml/model/error/type/min_length_error.rb +20 -0
- data/lib/lutaml/model/error/type/pattern_not_matched_error.rb +18 -0
- data/lib/lutaml/model/error/validation_failed_error.rb +9 -0
- data/lib/lutaml/model/error.rb +10 -0
- data/lib/lutaml/model/errors.rb +36 -0
- data/lib/lutaml/model/format_registry.rb +5 -2
- data/lib/lutaml/model/global_register.rb +41 -0
- data/lib/lutaml/model/{hash.rb → hash_adapter.rb} +5 -5
- data/lib/lutaml/model/jsonl/document.rb +14 -0
- data/lib/lutaml/model/jsonl/mapping.rb +19 -0
- data/lib/lutaml/model/jsonl/mapping_rule.rb +9 -0
- data/lib/lutaml/model/jsonl/standard_adapter.rb +33 -0
- data/lib/lutaml/model/jsonl/transform.rb +19 -0
- data/lib/lutaml/model/jsonl.rb +21 -0
- data/lib/lutaml/model/key_value_document.rb +3 -2
- data/lib/lutaml/model/mapping/key_value_mapping.rb +64 -4
- data/lib/lutaml/model/mapping/key_value_mapping_rule.rb +4 -0
- data/lib/lutaml/model/mapping/mapping_rule.rb +8 -3
- data/lib/lutaml/model/register.rb +105 -0
- data/lib/lutaml/model/registrable.rb +6 -0
- data/lib/lutaml/model/schema/base_schema.rb +64 -0
- data/lib/lutaml/model/schema/decorators/attribute.rb +114 -0
- data/lib/lutaml/model/schema/decorators/choices.rb +31 -0
- data/lib/lutaml/model/schema/decorators/class_definition.rb +85 -0
- data/lib/lutaml/model/schema/decorators/definition_collection.rb +97 -0
- data/lib/lutaml/model/schema/generator/definition.rb +53 -0
- data/lib/lutaml/model/schema/generator/definitions_collection.rb +81 -0
- data/lib/lutaml/model/schema/generator/properties_collection.rb +63 -0
- data/lib/lutaml/model/schema/generator/property.rb +110 -0
- data/lib/lutaml/model/schema/generator/ref.rb +24 -0
- data/lib/lutaml/model/schema/helpers/template_helper.rb +49 -0
- data/lib/lutaml/model/schema/json_schema.rb +42 -49
- data/lib/lutaml/model/schema/relaxng_schema.rb +14 -10
- data/lib/lutaml/model/schema/renderer.rb +36 -0
- data/lib/lutaml/model/schema/shared_methods.rb +24 -0
- data/lib/lutaml/model/schema/templates/model.erb +9 -0
- data/lib/lutaml/model/schema/xml_compiler/attribute.rb +85 -0
- data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +45 -0
- data/lib/lutaml/model/schema/xml_compiler/choice.rb +65 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +27 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +34 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +136 -0
- data/lib/lutaml/model/schema/xml_compiler/element.rb +104 -0
- data/lib/lutaml/model/schema/xml_compiler/group.rb +97 -0
- data/lib/lutaml/model/schema/xml_compiler/restriction.rb +101 -0
- data/lib/lutaml/model/schema/xml_compiler/sequence.rb +50 -0
- data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +36 -0
- data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +189 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +231 -587
- data/lib/lutaml/model/schema/xsd_schema.rb +12 -8
- data/lib/lutaml/model/schema/yaml_schema.rb +41 -35
- data/lib/lutaml/model/schema.rb +1 -0
- data/lib/lutaml/model/sequence.rb +60 -30
- data/lib/lutaml/model/serialize.rb +175 -53
- data/lib/lutaml/model/services/base.rb +11 -0
- data/lib/lutaml/model/services/logger.rb +2 -2
- data/lib/lutaml/model/services/rule_value_extractor.rb +92 -0
- data/lib/lutaml/model/services/type/validator/number.rb +25 -0
- data/lib/lutaml/model/services/type/validator/string.rb +52 -0
- data/lib/lutaml/model/services/type/validator.rb +43 -0
- data/lib/lutaml/model/services/validator.rb +145 -0
- data/lib/lutaml/model/services.rb +3 -0
- data/lib/lutaml/model/transform/key_value_transform.rb +60 -50
- data/lib/lutaml/model/transform/xml_transform.rb +46 -57
- data/lib/lutaml/model/transform.rb +22 -8
- data/lib/lutaml/model/type/boolean.rb +1 -1
- data/lib/lutaml/model/type/date.rb +1 -1
- data/lib/lutaml/model/type/date_time.rb +1 -1
- data/lib/lutaml/model/type/decimal.rb +11 -9
- data/lib/lutaml/model/type/float.rb +2 -1
- data/lib/lutaml/model/type/integer.rb +24 -21
- data/lib/lutaml/model/type/string.rb +4 -2
- data/lib/lutaml/model/type/time.rb +1 -1
- data/lib/lutaml/model/type/time_without_date.rb +1 -1
- data/lib/lutaml/model/type/value.rb +5 -1
- data/lib/lutaml/model/type.rb +5 -2
- data/lib/lutaml/model/utils.rb +30 -8
- data/lib/lutaml/model/validation.rb +6 -4
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml/document.rb +37 -19
- data/lib/lutaml/model/xml/mapping.rb +74 -13
- data/lib/lutaml/model/xml/mapping_rule.rb +10 -2
- data/lib/lutaml/model/xml/nokogiri_adapter.rb +5 -3
- data/lib/lutaml/model/xml/oga/element.rb +4 -1
- data/lib/lutaml/model/xml/oga_adapter.rb +4 -3
- data/lib/lutaml/model/xml/ox_adapter.rb +20 -6
- data/lib/lutaml/model/xml/xml_element.rb +3 -28
- data/lib/lutaml/model/xml_adapter/element.rb +1 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +1 -1
- data/lib/lutaml/model/yamls/document.rb +14 -0
- data/lib/lutaml/model/yamls/mapping.rb +19 -0
- data/lib/lutaml/model/yamls/mapping_rule.rb +9 -0
- data/lib/lutaml/model/yamls/standard_adapter.rb +34 -0
- data/lib/lutaml/model/yamls/transform.rb +19 -0
- data/lib/lutaml/model/yamls.rb +21 -0
- data/lib/lutaml/model.rb +7 -31
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +4 -5
- data/spec/fixtures/xml/advanced_test_schema.xsd +134 -0
- data/spec/fixtures/xml/examples/nested_categories.xml +55 -0
- data/spec/fixtures/xml/examples/valid_catalog.xml +43 -0
- data/spec/fixtures/xml/product_catalog.xsd +151 -0
- data/spec/fixtures/xml/specifications_schema.xsd +38 -0
- data/spec/lutaml/model/attribute_collection_spec.rb +101 -0
- data/spec/lutaml/model/attribute_spec.rb +41 -44
- data/spec/lutaml/model/choice_spec.rb +44 -0
- data/spec/lutaml/model/custom_collection_spec.rb +830 -0
- data/spec/lutaml/model/custom_model_spec.rb +15 -3
- data/spec/lutaml/model/defaults_spec.rb +5 -1
- data/spec/lutaml/model/global_register_spec.rb +108 -0
- data/spec/lutaml/model/group_spec.rb +9 -3
- data/spec/lutaml/model/jsonl/standard_adapter_spec.rb +91 -0
- data/spec/lutaml/model/jsonl_spec.rb +229 -0
- data/spec/lutaml/model/multiple_mapping_spec.rb +1 -1
- data/spec/lutaml/model/register/key_value_spec.rb +275 -0
- data/spec/lutaml/model/register/xml_spec.rb +187 -0
- data/spec/lutaml/model/register_spec.rb +147 -0
- data/spec/lutaml/model/rule_value_extractor_spec.rb +162 -0
- data/spec/lutaml/model/schema/generator/definitions_collection_spec.rb +120 -0
- data/spec/lutaml/model/schema/json_schema_spec.rb +412 -51
- data/spec/lutaml/model/schema/json_schema_to_models_spec.rb +383 -0
- data/spec/lutaml/model/schema/xml_compiler/attribute_group_spec.rb +65 -0
- data/spec/lutaml/model/schema/xml_compiler/attribute_spec.rb +63 -0
- data/spec/lutaml/model/schema/xml_compiler/choice_spec.rb +71 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_content_restriction_spec.rb +55 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_content_spec.rb +37 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_type_spec.rb +173 -0
- data/spec/lutaml/model/schema/xml_compiler/element_spec.rb +63 -0
- data/spec/lutaml/model/schema/xml_compiler/group_spec.rb +86 -0
- data/spec/lutaml/model/schema/xml_compiler/restriction_spec.rb +76 -0
- data/spec/lutaml/model/schema/xml_compiler/sequence_spec.rb +59 -0
- data/spec/lutaml/model/schema/xml_compiler/simple_content_spec.rb +55 -0
- data/spec/lutaml/model/schema/xml_compiler/simple_type_spec.rb +181 -0
- data/spec/lutaml/model/schema/xml_compiler_spec.rb +503 -1804
- data/spec/lutaml/model/schema/yaml_schema_spec.rb +249 -26
- data/spec/lutaml/model/sequence_spec.rb +36 -0
- data/spec/lutaml/model/serializable_spec.rb +31 -0
- data/spec/lutaml/model/type_spec.rb +8 -4
- data/spec/lutaml/model/utils_spec.rb +3 -3
- data/spec/lutaml/model/xml/derived_attributes_spec.rb +1 -1
- data/spec/lutaml/model/xml/xml_element_spec.rb +7 -1
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
- data/spec/lutaml/model/xml_adapter_spec.rb +24 -0
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +11 -4
- data/spec/lutaml/model/xml_mapping_spec.rb +1 -1
- data/spec/lutaml/model/yamls/standard_adapter_spec.rb +183 -0
- data/spec/lutaml/model/yamls_spec.rb +294 -0
- data/spec/spec_helper.rb +1 -0
- metadata +105 -9
- data/lib/lutaml/model/schema/templates/simple_type.rb +0 -247
- /data/lib/lutaml/model/{hash → hash_adapter}/document.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/mapping.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/mapping_rule.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/standard_adapter.rb +0 -0
- /data/lib/lutaml/model/{hash → hash_adapter}/transform.rb +0 -0
@@ -0,0 +1,173 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Lutaml::Model::Schema::XmlCompiler::ComplexType do
|
4
|
+
let(:complex_type) { described_class.new }
|
5
|
+
let(:dummy_class) do
|
6
|
+
Class.new do
|
7
|
+
def to_attributes(indent); end
|
8
|
+
def to_xml_mapping(indent); end
|
9
|
+
def required_files; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
let(:simple_content_class) do
|
13
|
+
Class.new do
|
14
|
+
def base_class; end
|
15
|
+
def to_attributes(indent); end
|
16
|
+
def to_xml_mapping(indent); end
|
17
|
+
def required_files; end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#initialize" do
|
22
|
+
it "sets default base_class and empty instances" do
|
23
|
+
expect(complex_type.base_class).to eq(described_class::SERIALIZABLE_BASE_CLASS)
|
24
|
+
expect(complex_type.instances).to eq([])
|
25
|
+
end
|
26
|
+
|
27
|
+
it "allows custom base_class" do
|
28
|
+
ct = described_class.new(base_class: "CustomBase")
|
29
|
+
expect(ct.base_class).to eq("CustomBase")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "attribute accessors" do
|
34
|
+
it "allows reading and writing id, name, mixed, simple_content" do
|
35
|
+
complex_type.id = "id"
|
36
|
+
complex_type.name = "Name"
|
37
|
+
complex_type.mixed = true
|
38
|
+
complex_type.simple_content = instance_double(simple_content_class)
|
39
|
+
expect(complex_type.id).to eq("id")
|
40
|
+
expect(complex_type.name).to eq("Name")
|
41
|
+
expect(complex_type.mixed).to be true
|
42
|
+
expect(complex_type.simple_content).to be_a(RSpec::Mocks::InstanceVerifyingDouble)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#<<" do
|
47
|
+
it "adds instances to the list" do
|
48
|
+
instance = instance_double(dummy_class)
|
49
|
+
expect { complex_type << instance }.to change { complex_type.instances.size }.by(1)
|
50
|
+
expect(complex_type.instances).to include(instance)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "ignores nil instances" do
|
54
|
+
expect { complex_type << nil }.not_to(change { complex_type.instances.size })
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#simple_content?" do
|
59
|
+
it "returns false if simple_content is nil or blank" do
|
60
|
+
expect(complex_type.simple_content?).to be false
|
61
|
+
complex_type.simple_content = nil
|
62
|
+
expect(complex_type.simple_content?).to be false
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns true if simple_content is present" do
|
66
|
+
complex_type.simple_content = instance_double(simple_content_class)
|
67
|
+
expect(complex_type.simple_content?).to be true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#to_class" do
|
72
|
+
it "renders a class with no instances or simple_content" do
|
73
|
+
complex_type.name = "TestClass"
|
74
|
+
code = complex_type.to_class
|
75
|
+
expect(code).to include("class TestClass < Lutaml::Model::Serializable")
|
76
|
+
expect(code).to include("def self.register_class_with_id")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "renders a class with instances" do
|
80
|
+
instance = instance_double(dummy_class, to_attributes: " attribute :foo, :string\n", to_xml_mapping: " map_element 'foo', to: :foo\n", required_files: [])
|
81
|
+
complex_type.name = "TestClass"
|
82
|
+
complex_type << instance
|
83
|
+
code = complex_type.to_class
|
84
|
+
expect(code).to include("attribute :foo, :string")
|
85
|
+
expect(code).to include("map_element 'foo', to: :foo")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "renders a class with simple_content" do
|
89
|
+
simple_content = instance_double(simple_content_class, base_class: "string", to_attributes: " attribute :content, :string\n", to_xml_mapping: " map_content to: :content\n", required_files: ["require 'simple_content'"])
|
90
|
+
complex_type.name = "TestClass"
|
91
|
+
complex_type.simple_content = simple_content
|
92
|
+
code = complex_type.to_class
|
93
|
+
expect(code).to include("attribute :content, :string")
|
94
|
+
expect(code).to include("map_content to: :content")
|
95
|
+
expect(code).to include("require 'simple_content'")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "renders a class with mixed content" do
|
99
|
+
complex_type.name = "TestClass"
|
100
|
+
complex_type.mixed = true
|
101
|
+
code = complex_type.to_class
|
102
|
+
expect(code).to include(", mixed: true")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "renders a class with namespace and prefix options" do
|
106
|
+
complex_type.name = "TestClass"
|
107
|
+
code = complex_type.to_class(options: { namespace: "http://example.com", prefix: "ex", indent: 2 })
|
108
|
+
expect(code).to include("namespace \"http://example.com\"", "\"ex\"")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#required_files" do
|
113
|
+
it "returns require lutaml/model for default base_class" do
|
114
|
+
expect(complex_type.required_files).to include("require \"lutaml/model\"")
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns require_relative for custom base_class" do
|
118
|
+
ct = described_class.new(base_class: "foo:BarBase")
|
119
|
+
expect(ct.required_files).to include("require_relative \"bar_base\"")
|
120
|
+
end
|
121
|
+
|
122
|
+
it "includes required_files from instances and simple_content" do
|
123
|
+
instance = instance_double(dummy_class, required_files: ["require 'foo'"])
|
124
|
+
simple_content = instance_double(simple_content_class, required_files: ["require 'bar'"])
|
125
|
+
complex_type << instance
|
126
|
+
complex_type.simple_content = simple_content
|
127
|
+
expect(complex_type.required_files).to include("require 'foo'")
|
128
|
+
expect(complex_type.required_files).to include("require 'bar'")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "private methods" do
|
133
|
+
it "base_class_name returns correct value" do
|
134
|
+
expect(complex_type.send(:base_class_name)).to eq("Lutaml::Model::Serializable")
|
135
|
+
ct = described_class.new(base_class: "foo:BarBase")
|
136
|
+
expect(ct.send(:base_class_name)).to eq("BarBase")
|
137
|
+
end
|
138
|
+
|
139
|
+
it "base_class_require returns correct require line" do
|
140
|
+
expect(complex_type.send(:base_class_require)).to eq("require \"lutaml/model\"")
|
141
|
+
ct = described_class.new(base_class: "foo:BarBase")
|
142
|
+
expect(ct.send(:base_class_require)).to eq("require_relative \"bar_base\"")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "last_of_split returns last part after colon" do
|
146
|
+
expect(complex_type.send(:last_of_split, "foo:BarBase")).to eq("BarBase")
|
147
|
+
expect(complex_type.send(:last_of_split, "BarBase")).to eq("BarBase")
|
148
|
+
expect(complex_type.send(:last_of_split, nil)).to be_nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "edge cases" do
|
153
|
+
it "handles no instances or simple_content" do
|
154
|
+
complex_type.name = "TestClass"
|
155
|
+
expect { complex_type.to_class }.not_to raise_error
|
156
|
+
end
|
157
|
+
|
158
|
+
it "handles unusual base_class values" do
|
159
|
+
ct = described_class.new(base_class: nil)
|
160
|
+
ct.name = "TestClass"
|
161
|
+
expect { ct.to_class }.not_to raise_error
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "integration" do
|
166
|
+
it "generates valid Ruby code for a complex type" do
|
167
|
+
complex_type.name = "TestClass"
|
168
|
+
code = complex_type.to_class
|
169
|
+
expect(code).to include("class TestClass < Lutaml::Model::Serializable")
|
170
|
+
expect(code).to include("def self.register_class_with_id")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Lutaml::Model::Schema::XmlCompiler::Element do
|
4
|
+
let(:element) { described_class.new(name: "foo", ref: "bar:Ref") }
|
5
|
+
|
6
|
+
describe "#initialize" do
|
7
|
+
it "sets name and ref" do
|
8
|
+
e = described_class.new(name: "foo", ref: "bar")
|
9
|
+
expect(e.name).to eq("foo")
|
10
|
+
expect(e.ref).to eq("bar")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#to_attributes" do
|
15
|
+
it "returns attribute line if not skippable and resolved_type present" do
|
16
|
+
allow(element).to receive_messages(resolved_name: "foo", resolved_type: "string", skippable?: false)
|
17
|
+
expect(element.to_attributes(" ")).to include("attribute :foo, :string")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns nil if skippable" do
|
21
|
+
allow(element).to receive(:skippable?).and_return(true)
|
22
|
+
expect(element.to_attributes(" ")).to be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#to_xml_mapping" do
|
27
|
+
it "returns map_element line if not skippable and resolved_type present" do
|
28
|
+
allow(element).to receive_messages(resolved_name: "foo", resolved_type: "string", skippable?: false)
|
29
|
+
expect(element.to_xml_mapping(" ")).to include("map_element :foo, to: :foo")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns nil if skippable" do
|
33
|
+
allow(element).to receive(:skippable?).and_return(true)
|
34
|
+
expect(element.to_xml_mapping(" ")).to be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#required_files" do
|
39
|
+
it "returns require 'bigdecimal' for decimal type" do
|
40
|
+
allow(element).to receive_messages(resolved_name: "foo", resolved_type: "decimal", skippable?: false)
|
41
|
+
expect(element.required_files).to eq("require \"bigdecimal\"")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns require_relative for non-skippable type" do
|
45
|
+
allow(Lutaml::Model::Schema::XmlCompiler::SimpleType).to receive(:skippable?).and_return(false)
|
46
|
+
allow(element).to receive_messages(resolved_name: "foo", resolved_type: "foo")
|
47
|
+
expect(element.required_files).to eq("require_relative \"foo\"")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns nil for skippable type" do
|
51
|
+
allow(element).to receive(:skippable?).and_return(true)
|
52
|
+
expect(element.required_files).to be_nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "private methods" do
|
57
|
+
it "last_of_split returns last part after colon" do
|
58
|
+
expect(element.send(:last_of_split, "foo:Bar")).to eq("Bar")
|
59
|
+
expect(element.send(:last_of_split, "Bar")).to eq("Bar")
|
60
|
+
expect(element.send(:last_of_split, nil)).to be_nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Lutaml::Model::Schema::XmlCompiler::Group do
|
4
|
+
let(:group) { described_class.new("GroupName", nil) }
|
5
|
+
let(:dummy_class) do
|
6
|
+
Class.new do
|
7
|
+
def to_attributes(indent); end
|
8
|
+
def to_xml_mapping(indent); end
|
9
|
+
def required_files; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it "sets name and ref" do
|
15
|
+
g = described_class.new("foo", "bar")
|
16
|
+
expect(g.name).to eq("foo")
|
17
|
+
expect(g.ref).to eq("bar")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#to_xml_mapping" do
|
22
|
+
it "returns import_model_mappings if ref is present" do
|
23
|
+
group.ref = "foo:Bar"
|
24
|
+
group.name = nil
|
25
|
+
expect(group.to_xml_mapping(" ")).to include("import_model_mappings :bar")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "delegates to instance if ref is not present" do
|
29
|
+
instance = instance_double(dummy_class, to_xml_mapping: " map_element :foo, to: :foo\n")
|
30
|
+
group.instance = instance
|
31
|
+
group.ref = nil
|
32
|
+
expect(group.to_xml_mapping(" ")).to include("map_element :foo, to: :foo")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#to_class" do
|
37
|
+
it "renders the group template" do
|
38
|
+
group.name = "GroupName"
|
39
|
+
group.instance = instance_double(dummy_class, to_attributes: " attribute :foo, :string\n", to_xml_mapping: " map_element :foo, to: :foo\n", required_files: [])
|
40
|
+
expect(group.to_class).to include("class GroupName")
|
41
|
+
expect(group.to_class).to include("attribute :foo, :string")
|
42
|
+
expect(group.to_class).to include("map_element :foo, to: :foo")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#required_files" do
|
47
|
+
it "returns require_relative if name is blank and ref is present" do
|
48
|
+
group.name = nil
|
49
|
+
group.ref = "foo:Bar"
|
50
|
+
expect(group.required_files).to include("require_relative \"bar\"")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "delegates to instance if name is present" do
|
54
|
+
instance = instance_double(dummy_class, required_files: "require 'foo'")
|
55
|
+
group.instance = instance
|
56
|
+
group.name = "GroupName"
|
57
|
+
group.ref = nil
|
58
|
+
expect(group.required_files).to eq("require 'foo'")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#to_attributes" do
|
63
|
+
it "returns import_model_attributes if ref is present" do
|
64
|
+
group.ref = "foo:Bar"
|
65
|
+
group.name = nil
|
66
|
+
expect(group.to_attributes(" ")).to include("import_model_attributes :bar")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "delegates to instance if ref is not present" do
|
70
|
+
instance = instance_double(dummy_class, to_attributes: " attribute :foo, :string\n")
|
71
|
+
group.instance = instance
|
72
|
+
group.ref = nil
|
73
|
+
expect(group.to_attributes(" ")).to include("attribute :foo, :string")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#base_name" do
|
78
|
+
it "returns last part of name or ref" do
|
79
|
+
group.name = "foo:Bar"
|
80
|
+
expect(group.base_name).to eq("Bar")
|
81
|
+
group.name = nil
|
82
|
+
group.ref = "foo:Baz"
|
83
|
+
expect(group.base_name).to eq("Baz")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Lutaml::Model::Schema::XmlCompiler::Restriction do
|
4
|
+
let(:restriction) { described_class.new }
|
5
|
+
|
6
|
+
describe "attribute accessors" do
|
7
|
+
it "allows reading and writing all attributes" do
|
8
|
+
restriction.min_inclusive = 1
|
9
|
+
restriction.max_inclusive = 10
|
10
|
+
restriction.min_exclusive = 2
|
11
|
+
restriction.max_exclusive = 9
|
12
|
+
restriction.enumerations = ["A", "B"]
|
13
|
+
restriction.max_length = 5
|
14
|
+
restriction.min_length = 1
|
15
|
+
restriction.base_class = "foo:Bar"
|
16
|
+
restriction.pattern = /abc/
|
17
|
+
restriction.length = 3
|
18
|
+
restriction.transform = "value.upcase"
|
19
|
+
expect(restriction.min_inclusive).to eq(1)
|
20
|
+
expect(restriction.max_inclusive).to eq(10)
|
21
|
+
expect(restriction.enumerations).to eq(["A", "B"])
|
22
|
+
expect(restriction.pattern).to eq(/abc/)
|
23
|
+
expect(restriction.transform).to eq("value.upcase")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#to_method_body" do
|
28
|
+
it "returns method body for all present attributes" do
|
29
|
+
restriction.enumerations = ["A", "B"]
|
30
|
+
restriction.min_inclusive = 1
|
31
|
+
restriction.max_inclusive = 10
|
32
|
+
restriction.pattern = /abc/
|
33
|
+
restriction.transform = "value.upcase"
|
34
|
+
body = restriction.to_method_body(" ")
|
35
|
+
expect(body).to include("options[:values]")
|
36
|
+
expect(body).to include("options[:min]")
|
37
|
+
expect(body).to include("options[:max]")
|
38
|
+
expect(body).to include("options[:pattern]")
|
39
|
+
expect(body).to include("value = value.upcase")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns empty string if no attributes are set" do
|
43
|
+
expect(restriction.to_method_body(" ")).to eq("")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#required_files" do
|
48
|
+
it "returns require 'bigdecimal' for decimal base_class" do
|
49
|
+
restriction.base_class = "decimal"
|
50
|
+
expect(restriction.required_files).to eq("require \"bigdecimal\"")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns require_relative for non-skippable base_class" do
|
54
|
+
restriction.base_class = "foo:Base"
|
55
|
+
expect(restriction.required_files).to eq("require_relative \"base\"")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns nil for skippable base_class" do
|
59
|
+
restriction.base_class = "string"
|
60
|
+
expect(restriction.required_files).to be_nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "private methods" do
|
65
|
+
it "base_class_name returns last part as symbol" do
|
66
|
+
restriction.base_class = "foo:Bar"
|
67
|
+
expect(restriction.send(:base_class_name)).to eq(:Bar)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "casted_enumerations returns super calls for each enumeration" do
|
71
|
+
restriction.enumerations = ["A", "B"]
|
72
|
+
expect(restriction.send(:casted_enumerations)).to include("super(\"A\")")
|
73
|
+
expect(restriction.send(:casted_enumerations)).to include("super(\"B\")")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Lutaml::Model::Schema::XmlCompiler::Sequence do
|
4
|
+
let(:sequence) { described_class.new }
|
5
|
+
let(:dummy_class) do
|
6
|
+
Class.new do
|
7
|
+
def to_attributes(indent); end
|
8
|
+
def to_xml_mapping(indent); end
|
9
|
+
def required_files; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it "starts with empty instances" do
|
15
|
+
expect(sequence.instances).to eq([])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#<<" do
|
20
|
+
it "adds instances to the list" do
|
21
|
+
instance = instance_double(dummy_class, to_attributes: " attribute :foo, :string\n", to_xml_mapping: " map_element :foo, to: :foo\n", required_files: "require 'foo'")
|
22
|
+
expect { sequence << instance }.to change { sequence.instances.size }.by(1)
|
23
|
+
expect(sequence.instances).to include(instance)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "ignores nil instances" do
|
27
|
+
expect { sequence << nil }.not_to(change { sequence.instances.size })
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#to_attributes" do
|
32
|
+
it "returns joined attributes from instances" do
|
33
|
+
instance = instance_double(dummy_class, to_attributes: " attribute :foo, :string\n")
|
34
|
+
sequence << instance
|
35
|
+
expect(sequence.to_attributes(" ")).to include("attribute :foo, :string")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#to_xml_mapping" do
|
40
|
+
it "returns empty string if no content" do
|
41
|
+
expect(sequence.to_xml_mapping(" ")).to eq("")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns xml mapping block if content exists" do
|
45
|
+
instance = instance_double(dummy_class, to_xml_mapping: " map_element :foo, to: :foo\n")
|
46
|
+
sequence << instance
|
47
|
+
expect(sequence.to_xml_mapping(" ")).to include("sequence do")
|
48
|
+
expect(sequence.to_xml_mapping(" ")).to include("map_element :foo, to: :foo")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#required_files" do
|
53
|
+
it "collects required_files from all instances" do
|
54
|
+
instance = instance_double(dummy_class, required_files: "require 'foo'")
|
55
|
+
sequence << instance
|
56
|
+
expect(sequence.required_files).to include("require 'foo'")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Lutaml::Model::Schema::XmlCompiler::SimpleContent do
|
4
|
+
let(:simple_content) { described_class.new }
|
5
|
+
let(:dummy_class) do
|
6
|
+
Class.new do
|
7
|
+
def to_attributes(indent); end
|
8
|
+
def to_xml_mapping(indent); end
|
9
|
+
def required_files; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it "starts with empty instances and nil base_class" do
|
15
|
+
expect(simple_content.instances).to eq([])
|
16
|
+
expect(simple_content.base_class).to be_nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#<<" do
|
21
|
+
it "adds instances to the list" do
|
22
|
+
instance = instance_double(dummy_class, to_attributes: "attr", to_xml_mapping: "xml", required_files: "files")
|
23
|
+
expect { simple_content << instance }.to change { simple_content.instances.size }.by(1)
|
24
|
+
expect(simple_content.instances).to include(instance)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "ignores nil instances" do
|
28
|
+
expect { simple_content << nil }.not_to(change { simple_content.instances.size })
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#to_attributes" do
|
33
|
+
it "returns joined attributes from instances" do
|
34
|
+
instance = instance_double(dummy_class, to_attributes: "attr")
|
35
|
+
simple_content << instance
|
36
|
+
expect(simple_content.to_attributes(" ")).to include("attr")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#to_xml_mapping" do
|
41
|
+
it "returns joined xml mappings from instances" do
|
42
|
+
instance = instance_double(dummy_class, to_xml_mapping: "xml")
|
43
|
+
simple_content << instance
|
44
|
+
expect(simple_content.to_xml_mapping(" ")).to include("xml")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#required_files" do
|
49
|
+
it "collects required_files from all instances" do
|
50
|
+
instance = instance_double(dummy_class, required_files: "files")
|
51
|
+
simple_content << instance
|
52
|
+
expect(simple_content.required_files).to include("files")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|