require "spec_helper" require "lutaml/model" module IncludedSpec class Base include Lutaml::Model::Serialize attribute :text, Lutaml::Model::Type::String attribute :id, Lutaml::Model::Type::String attribute :name, Lutaml::Model::Type::String xml do map_content to: :text map_attribute "id", to: :id map_element "name", to: :name end end class Implementation1 include Lutaml::Model::Serialize attribute :text, Lutaml::Model::Type::String attribute :id, Lutaml::Model::Type::String attribute :name, Lutaml::Model::Type::String attribute :age, Lutaml::Model::Type::Integer xml do root "impl_one" map_content to: :text map_attribute "id", to: :id map_element "name", to: :name map_element "age", to: :age end end class Implementation2 include Lutaml::Model::Serialize attribute :text, Lutaml::Model::Type::String attribute :id, Lutaml::Model::Type::String attribute :name, Lutaml::Model::Type::String attribute :age, Lutaml::Model::Type::Integer xml do root "impl_two" map_content to: :text map_attribute "id", to: :id map_element "name", to: :name map_element "gender", to: :age end end module ParentClass include Lutaml::Model::Serialize attribute :parent_name, Lutaml::Model::Type::String attribute :parent_id, Lutaml::Model::Type::String xml do root "parent" map_attribute "id", to: :parent_id map_element "parent_name", to: :parent_name end end module ChildClass include ParentClass attribute :child_name, Lutaml::Model::Type::String attribute :child_type, Lutaml::Model::Type::String attribute :child_text, Lutaml::Model::Type::String xml do root "child" map_attribute "type", to: :child_type map_element "child_name", to: :child_name map_content to: :child_text end end class GrandChildClass include ChildClass attribute :grandchild_name, Lutaml::Model::Type::String attribute :grandchild_version, Lutaml::Model::Type::String attribute :grandchild_text, Lutaml::Model::Type::String xml do root "grandchild" map_attribute "version", to: :grandchild_version map_element "grandchild_name", to: :grandchild_name map_content to: :grandchild_text end end end RSpec.describe "Included" do subject(:impl_object) do IncludedSpec::Implementation1.new( { text: "Some text", name: "John Doe", id: "foobar", age: 30, }, ) end let(:expected_xml) do 'John Doe30Some text' end it "uses included module attributes" do expect(impl_object.to_xml(pretty: true)).to eq(expected_xml) end context "with multiple implementing classes" do describe "Implementation1" do let(:impl1) { IncludedSpec::Implementation1 } it "has correct mappings" do expect(impl1.mappings_for(:xml).mappings.count).to eq(4) end it "has correct attributes" do expect(impl1.attributes.count).to eq(4) end it "has correct model" do expect(impl1.model).to eq(impl1) end end describe "Implementation2" do let(:impl2) { IncludedSpec::Implementation2 } it "has correct mappings" do expect(impl2.mappings_for(:xml).mappings.count).to eq(4) end it "has correct attributes" do expect(impl2.attributes.count).to eq(4) end it "has correct model" do expect(impl2.model).to eq(impl2) end end end context "with nested module inclusion" do let(:grandchild) do IncludedSpec::GrandChildClass.new( parent_name: "Parent Name", parent_id: "P123", child_name: "Child Name", child_type: "Type A", child_text: "Child Text", grandchild_name: "GrandChild Name", grandchild_version: "1.0", grandchild_text: "GrandChild Text", ) end it "inherits attributes through the chain" do expect(IncludedSpec::GrandChildClass.attributes.keys).to include( :parent_name, :parent_id, :child_name, :child_type, :child_text, :grandchild_name, :grandchild_version, :grandchild_text ) end it "maintains correct XML mappings through inheritance" do expected_xml = <<~XML Parent Name Child Name GrandChild Name GrandChild Text XML expect(grandchild.to_xml(pretty: true)).to be_equivalent_to(expected_xml) end it "preserves separate mapping configurations" do expect(IncludedSpec::ParentClass.mappings_for(:xml).root_element).to eq("parent") expect(IncludedSpec::ChildClass.mappings_for(:xml).root_element).to eq("child") expect(IncludedSpec::GrandChildClass.mappings_for(:xml).root_element).to eq("grandchild") end end end