require "spec_helper"
require "lutaml/model/xml_adapter/nokogiri_adapter"
require "lutaml/model/xml_adapter/ox_adapter"
require "lutaml/model/xml_adapter/oga_adapter"
require_relative "../../fixtures/sample_model"
module XmlAdapterSpec
class Mstyle < Lutaml::Model::Serializable
attribute :displaystyle, :string, default: -> { "true" }
attribute :color, :string
attribute :finish, :string, default: -> { "yes" }
xml do
root "mstyle"
map_attribute :displaystyle, to: :displaystyle, render_default: true
end
end
class Maths < Lutaml::Model::Serializable
attribute :display, :string, default: -> { "block" }
attribute :style, Mstyle, default: -> { Mstyle.new }
xml do
root "math"
map_attribute :display, to: :display
map_attribute "color", to: :color, delegate: :style
map_attribute "finish", to: :finish, delegate: :style,
render_default: true
map_element :mstyle, to: :style, render_default: true
end
end
end
RSpec.shared_examples "an XML adapter" do |adapter_class|
around do |example|
old_adapter = Lutaml::Model::Config.xml_adapter
Lutaml::Model::Config.xml_adapter = adapter_class
example.run
ensure
Lutaml::Model::Config.xml_adapter = old_adapter
end
before do
# Ensure BigDecimal is loaded because it is being used in sample model
require "bigdecimal"
end
let(:attributes) { { name: "John Doe", age: 30 } }
let(:model) { SampleModel.new(attributes) }
context "with default value" do
it "set display attribute correctly, other attributes default" do
xml = ""
parsed = XmlAdapterSpec::Maths.from_xml(xml)
expect(parsed.display).to eq("true")
expect(parsed.style.class).to eq(XmlAdapterSpec::Mstyle)
expect(parsed.style.displaystyle).to eq("true")
end
it "set style attribute correctly, other attributes default" do
xml = ""
parsed = XmlAdapterSpec::Maths.from_xml(xml)
expect(parsed.display).to eq("block")
expect(parsed.style.class).to eq(XmlAdapterSpec::Mstyle)
expect(parsed.style.displaystyle).to eq("false")
end
it "sets attributes default values" do
xml = ""
parsed = XmlAdapterSpec::Maths.from_xml(xml)
expect(parsed.display).to eq("block")
expect(parsed.style.class).to eq(XmlAdapterSpec::Mstyle)
expect(parsed.style.displaystyle).to eq("true")
end
it "delegate attributes with value" do
xml = ""
parsed = XmlAdapterSpec::Maths.from_xml(xml)
expect(parsed.style.color).to eq("blue")
expect(parsed.style.finish).to eq("no")
expect(parsed.style.displaystyle).to eq("true")
end
it "delegate attributes with one value" do
xml = ""
parsed = XmlAdapterSpec::Maths.from_xml(xml)
expect(parsed.style.color).to eq("blue")
expect(parsed.style.finish).to eq("yes")
expect(parsed.style.displaystyle).to eq("true")
end
it "delegate attributes with no value" do
xml = ""
parsed = XmlAdapterSpec::Maths.from_xml(xml)
expect(parsed.style.color).to be_nil
expect(parsed.style.finish).to eq("yes")
expect(parsed.style.displaystyle).to eq("true")
end
it "round-trips XML and add default values" do
input_xml = <<~XML
XML
output_xml = <<~XML
XML
parsed = XmlAdapterSpec::Maths.from_xml(input_xml)
expect(parsed.to_xml.strip).to be_equivalent_to(output_xml.strip)
end
end
it "serializes to XML" do
expected_xml = <<~XML
John Doe
30
XML
doc = adapter_class.parse(expected_xml)
xml = doc.to_xml
expect(xml).to be_equivalent_to(expected_xml)
end
it "serializes to XML with only content" do
expected_xml = <<~XML
Bug
XML
doc = SampleModelTag.from_xml(expected_xml)
xml = doc.to_xml
expect(xml).to be_equivalent_to(expected_xml)
end
it "deserializes from XML" do
xml = <<~XML
John Doe
30
XML
doc = adapter_class.parse(xml)
new_model = SampleModel.new(doc.root.children.to_h do |child|
[child.name.downcase.to_sym, child.text]
end)
expect(new_model.name).to eq("John Doe")
expect(new_model.age).to eq(30)
end
end
RSpec.describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
it_behaves_like "an XML adapter", described_class
end
RSpec.describe Lutaml::Model::XmlAdapter::OxAdapter do
it_behaves_like "an XML adapter", described_class
end
RSpec.describe Lutaml::Model::XmlAdapter::OgaAdapter do
it_behaves_like "an XML adapter", described_class
end