require 'test_helper' class XmlPublicMethodsTest < Minitest::Spec #--- # from_hash class BandRepresenter < Representable::Decorator include Representable::XML property :id property :name end let(:data) { %{1Rancid} } it { _(BandRepresenter.new(Band.new).from_xml(data)[:id, :name]).must_equal ["1", "Rancid"] } it { _(BandRepresenter.new(Band.new).parse(data)[:id, :name]).must_equal ["1", "Rancid"] } #--- # to_hash let(:band) { Band.new("1", "Rancid") } it { BandRepresenter.new(band).to_xml.must_equal_xml data } it { BandRepresenter.new(band).render.must_equal_xml data } end class XmlTest < MiniTest::Spec class Band include Representable::XML property :name attr_accessor :name def initialize(name=nil) name and self.name = name end end XML = Representable::XML Def = Representable::Definition describe "Xml module" do before do @Band = Class.new do include Representable::XML self.representation_wrap = :band property :name property :label attr_accessor :name, :label end @band = @Band.new end describe "#from_xml" do before do @band = @Band.new @xml = %{Nofx} end it "parses XML and assigns properties" do @band.from_xml(@xml) assert_equal ["Nofx", "NOFX"], [@band.name, @band.label] end end describe "#from_xml with remove_namespaces! and xmlns present" do before do @Band.remove_namespaces! @band = @Band.new @xml = %{Nofx} end it "parses with xmlns present" do @band.from_xml(@xml) assert_equal ["Nofx", "NOFX"], [@band.name, @band.label] end end describe "#from_node" do before do @band = @Band.new @xml = Nokogiri::XML(%{Nofx}).root end it "receives Nokogiri node and assigns properties" do @band.from_node(@xml) assert_equal ["Nofx", "NOFX"], [@band.name, @band.label] end end describe "#to_xml" do it "delegates to #to_node and returns string" do assert_xml_equal "Rise Against", Band.new("Rise Against").to_xml end end describe "#to_node" do it "returns Nokogiri node" do node = Band.new("Rise Against").to_node assert_kind_of Nokogiri::XML::Element, node end it "wraps with infered class name per default" do node = Band.new("Rise Against").to_node assert_xml_equal "Rise Against", node.to_s end it "respects #representation_wrap=" do klass = Class.new(Band) do include Representable property :name end klass.representation_wrap = :group assert_xml_equal "Rise Against", klass.new("Rise Against").to_node.to_s end end describe "XML::Binding#build_for" do it "returns AttributeBinding" do assert_kind_of XML::Binding::Attribute, XML::Binding.build_for(Def.new(:band, :as => "band", :attribute => true)) end it "returns Binding" do assert_kind_of XML::Binding, XML::Binding.build_for(Def.new(:band, :class => Hash)) assert_kind_of XML::Binding, XML::Binding.build_for(Def.new(:band, :as => :content)) end it "returns CollectionBinding" do assert_kind_of XML::Binding::Collection, XML::Binding.build_for(Def.new(:band, :collection => :true)) end it "returns HashBinding" do assert_kind_of XML::Binding::Hash, XML::Binding.build_for(Def.new(:band, :hash => :true)) end end describe "DCI" do module SongRepresenter include Representable::XML property :name end module AlbumRepresenter include Representable::XML property :best_song, :class => Song, :extend => SongRepresenter collection :songs, :class => Song, :as => :song, :extend => SongRepresenter end it "allows adding the representer by using #extend" do module BandRepresenter include Representable::XML property :name end civ = Object.new civ.instance_eval do def name; "CIV"; end def name=(v) @name = v end end civ.extend(BandRepresenter) assert_xml_equal "CIV", civ.to_xml end it "extends contained models when serializing" do @album = Album.new( [Song.new("I Hate My Brain"), mr=Song.new("Mr. Charisma")], mr) @album.extend(AlbumRepresenter) @album.to_xml.must_equal_xml " Mr. Charisma I Hate My Brain Mr. Charisma " end it "extends contained models when deserializing" do @album = Album.new @album.extend(AlbumRepresenter) @album.from_xml("Mr. CharismaI Hate My BrainMr. Charisma") assert_equal "Mr. Charisma", @album.best_song.name end end end end class AttributesTest < MiniTest::Spec describe ":as => rel, :attribute => true" do class Link include Representable::XML property :href, :as => "href", :attribute => true property :title, :as => "title", :attribute => true attr_accessor :href, :title end it "#from_xml creates correct accessors" do link = Link.new.from_xml(%{ }) assert_equal "http://apotomo.de", link.href assert_equal "Home, sweet home", link.title end it "#to_xml serializes correctly" do link = Link.new link.href = "http://apotomo.de/" assert_xml_equal %{}, link.to_xml end end end class CDataBand class CData < Representable::XML::Binding def serialize_node(parent, value) parent << Nokogiri::XML::CDATA.new(parent, represented.name) end end include Representable::XML property :name, :binding => lambda { |*args| CData.new(*args) }#getter: lambda { |opt| Nokogiri::XML::CDATA.new(opt[:doc], name) } attr_accessor :name def initialize(name=nil) name and self.name = name end end class TypedPropertyTest < MiniTest::Spec class Band include Representable::XML property :name attr_accessor :name def initialize(name=nil) name and self.name = name end end module AlbumRepresenter include Representable::XML property :band, :class => Band end class Album attr_accessor :band def initialize(band=nil) @band = band end end # TODO:property :group, :class => Band # :class # where to mixin DCI? describe ":class => Item" do it "#from_xml creates one Item instance" do album = Album.new.extend(AlbumRepresenter).from_xml(%{ Bad Religion }) assert_equal "Bad Religion", album.band.name end describe "#to_xml" do it "doesn't escape xml from Band#to_xml" do band = Band.new("Bad Religion") album = Album.new(band).extend(AlbumRepresenter) assert_xml_equal %{ Bad Religion }, album.to_xml end it "doesn't escape and wrap string from Band#to_node" do band = Band.new("Bad Religion") band.instance_eval do def to_node(*) "Baaaad Religion" end end assert_xml_equal %{Baaaad Religion}, Album.new(band).extend(AlbumRepresenter).to_xml end end describe "#to_xml with CDATA" do it "wraps Band name in CDATA#to_xml" do band = CDataBand.new("Bad Religion") album = Album.new(band).extend(AlbumRepresenter) assert_xml_equal %{ }, album.to_xml end end end end # TODO: add parsing tests. class XMLPropertyTest < Minitest::Spec Band = Struct.new(:name, :genre) Manager = Struct.new(:managed) #--- #- :as with scalar class BandRepresenter < Representable::Decorator include Representable::XML property :name, as: :theyCallUs property :genre, attribute: true end it { BandRepresenter.new(Band.new("Mute")).to_xml.must_equal_xml %{Mute} } class ManagerRepresenter < Representable::Decorator include Representable::XML property :managed, as: :band, decorator: BandRepresenter end #- :as with nested property it { ManagerRepresenter.new(Manager.new(Band.new("Mute", "Punkrock"))).to_xml.must_equal_xml %{Mute} } end class XMLCollectionTest < MiniTest::Spec Band = Struct.new(:name) Compilation = Struct.new(:bands) class BandRepresenter < Representable::Decorator include Representable::XML property :name end #--- #- :as, :decorator, :class describe ":class => Band, :as => :band, :collection => true" do class CompilationRepresenter < Representable::Decorator include Representable::XML collection :bands, class: Band, as: :group, decorator: BandRepresenter end describe "#from_xml" do it "pushes collection items to array" do cd = CompilationRepresenter.new(Compilation.new).from_xml(%{ Diesel Boy Cobra Skulls }) assert_equal ["Cobra Skulls", "Diesel Boy"], cd.bands.map(&:name).sort end end it "responds to #to_xml" do cd = Compilation.new([Band.new("Diesel Boy"), Band.new("Bad Religion")]) CompilationRepresenter.new(cd).to_xml.must_equal_xml %{ Diesel Boy Bad Religion } end end describe ":as" do let(:xml_doc) { Module.new do include Representable::XML collection :songs, :as => :song end } it "collects untyped items" do album = Album.new.extend(xml_doc).from_xml(%{ Two Kevins Wright and Rong Laundry Basket }) assert_equal ["Laundry Basket", "Two Kevins", "Wright and Rong"].sort, album.songs.sort end end describe ":wrap" do let(:album) { Album.new.extend(xml_doc) } let(:xml_doc) { Module.new do include Representable::XML collection :songs, :as => :song, :wrap => :songs end } describe "#from_xml" do it "finds items in wrapped collection" do album.from_xml(%{ Two Kevins Wright and Rong Laundry Basket }) assert_equal ["Laundry Basket", "Two Kevins", "Wright and Rong"].sort, album.songs.sort end end describe "#to_xml" do it "wraps items" do album.songs = ["Laundry Basket", "Two Kevins", "Wright and Rong"] assert_xml_equal %{ Laundry Basket Two Kevins Wright and Rong }, album.to_xml end end end require 'representable/xml/hash' class LonelyRepresenterTest < MiniTest::Spec # TODO: where is the XML::Hash test? module SongRepresenter include Representable::XML property :name self.representation_wrap = :song end let(:decorator) { rpr = representer; Class.new(Representable::Decorator) { include Representable::XML; include rpr } } describe "XML::Collection" do describe "with contained objects" do representer!(:module => Representable::XML::Collection) do items :class => Song, :extend => SongRepresenter self.representation_wrap= :songs end let(:songs) { [Song.new("Days Go By"), Song.new("Can't Take Them All")] } let(:xml_doc) { "Days Go ByCan't Take Them All" } it "renders array" do songs.extend(representer).to_xml.must_equal_xml xml_doc end it "renders array with decorator" do decorator.new(songs).to_xml.must_equal_xml xml_doc end it "parses array" do _([].extend(representer).from_xml(xml_doc)).must_equal songs end it "parses array with decorator" do _(decorator.new([]).from_xml(xml_doc)).must_equal songs end end end describe "XML::AttributeHash" do # TODO: move to HashTest. representer!(:module => Representable::XML::AttributeHash) do self.representation_wrap= :songs end let(:songs) { {"one" => "Graveyards", "two" => "Can't Take Them All"} } let(:xml_doc) { "" } describe "#to_xml" do it "renders hash" do songs.extend(representer).to_xml.must_equal_xml xml_doc end it "respects :exclude" do assert_xml_equal "", songs.extend(representer).to_xml(:exclude => [:one]) end it "respects :include" do assert_xml_equal "", songs.extend(representer).to_xml(:include => [:two]) end it "renders hash with decorator" do decorator.new(songs).to_xml.must_equal_xml xml_doc end end describe "#from_json" do it "returns hash" do _({}.extend(representer).from_xml(xml_doc)).must_equal songs end it "respects :exclude" do assert_equal({"two" => "Can't Take Them All"}, {}.extend(representer).from_xml(xml_doc, :exclude => [:one])) end it "respects :include" do assert_equal({"one" => "Graveyards"}, {}.extend(representer).from_xml(xml_doc, :include => [:one])) end it "parses hash with decorator" do _(decorator.new({}).from_xml(xml_doc)).must_equal songs end end end end end class XmlHashTest < MiniTest::Spec # scalar, no object describe "plain text" do representer!(module: Representable::XML) do hash :songs end let(:doc) { "The GargoyleBronx" } # to_xml it { OpenStruct.new(songs: {"first" => "The Gargoyle", "second" => "Bronx"}).extend(representer).to_xml.must_equal_xml(doc) } # FIXME: this NEVER worked! # it { OpenStruct.new.extend(representer).from_xml(doc).songs.must_equal({"first" => "The Gargoyle", "second" => "Bronx"}) } end describe "with objects" do representer!(module: Representable::XML) do hash :songs, class: OpenStruct do property :title end end let(:doc) { " The Gargoyle Bronx " } # to_xml it { OpenStruct.new(songs: {"first" => OpenStruct.new(title: "The Gargoyle"), "second" => OpenStruct.new(title: "Bronx")}).extend(representer).to_xml.must_equal_xml(doc) } # FIXME: this NEVER worked! # it { OpenStruct.new.extend(representer).from_xml(doc).songs.must_equal({"first" => "The Gargoyle", "second" => "Bronx"}) } end end