require 'test_helper' class InlineTest < MiniTest::Spec let (:song) { Song.new("Alive") } let (:request) { representer.prepare(OpenStruct.new(:song => song)) } { :hash => [Representable::Hash, {"song"=>{"name"=>"Alive"}}, {"song"=>{"name"=>"You've Taken Everything"}}], :json => [Representable::JSON, "{\"song\":{\"name\":\"Alive\"}}", "{\"song\":{\"name\":\"You've Taken Everything\"}}"], :xml => [Representable::XML, "\n \n Alive\n \n", "You've Taken Everything/open_struct>"], :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"], }.each do |format, cfg| mod, output, input = cfg describe "[#{format}] with :class" do representer!(:module => mod) do property :song, :class => Song do property :name end end let (:format) { format } it { render(request).must_equal_document output } it { parse(request, input).song.name.must_equal "You've Taken Everything"} end end { :hash => [Representable::Hash, {"songs"=>[{"name"=>"Alive"}]}, {"songs"=>[{"name"=>"You've Taken Everything"}]}], :json => [Representable::JSON, "{\"songs\":[{\"name\":\"Alive\"}]}", "{\"songs\":[{\"name\":\"You've Taken Everything\"}]}"], :xml => [Representable::XML, "\n \n Alive\n \n", "You've Taken Everything", { :as => :song }], :yaml => [Representable::YAML, "---\nsongs:\n- name: Alive\n", "---\nsongs:\n- name: You've Taken Everything\n"], }.each do |format, cfg| mod, output, input, collection_options = cfg collection_options ||= {} describe "[#{format}] collection with :class" do let (:request) { representer.prepare(OpenStruct.new(:songs => [song])) } representer!(:module => mod) do collection :songs, collection_options.merge(:class => Song) do property :name end end let (:format) { format } # FIXME: why do we have to define this? it { render(request).must_equal_document output } it { parse(request, input).songs.first.name.must_equal "You've Taken Everything"} end end describe "without :class" do representer! do property :song do property :name end end it { request.to_hash.must_equal({"song"=>{"name"=>"Alive"}}) } end for_formats( :hash => [Representable::Hash, {}], # :xml => [Representable::XML, "\n \n Alive\n \n", "You've Taken Everything/open_struct>"], # :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"], ) do |format, mod, input| describe "parsing [#{format}] where nested property missing" do representer!(:module => mod) do property :song do property :name end end it "doesn't change represented object" do request.send("from_#{format}", input).song.must_equal song end end end describe "inheriting from outer representer" do let (:request) { Struct.new(:song, :requester).new(song, "Josephine") } [false, true].each do |is_decorator| # test for module and decorator. representer!(:decorator => is_decorator) do property :requester property :song, :class => Song do property :name end end let (:decorator) { representer.prepare(request) } it { decorator.to_hash.must_equal({"requester"=>"Josephine", "song"=>{"name"=>"Alive"}}) } it { decorator.from_hash({"song"=>{"name"=>"You've Taken Everything"}}).song.name.must_equal "You've Taken Everything"} end end describe "object pollution" do representer!(:decorator => true) do property :song do property :name end end it "uses an inline decorator and doesn't alter represented" do representer.prepare(Struct.new(:song).new(song)).to_hash song.wont_be_kind_of Representable end end # TODO: should be in extend:/decorator: test. # FIXME: this tests :getter{represented}+:extend - represented gets extended twice and the inline decorator overrides original config. # for_formats( # :hash => [Representable::Hash, {"album" => {"artist" => {"label"=>"Epitaph"}}}], # # :xml => [Representable::XML, ""], # #:yaml => [Representable::YAML, "---\nlabel:\n label: Epitaph\n owner: Brett Gurewitz\n"] # ) do |format, mod, output, input| # module ArtistRepresenter # include Representable::JSON # property :label # end # describe ":getter with inline representer" do # let (:format) { format } # representer!(:module => mod) do # self.representation_wrap = :album # property :artist, :getter => lambda { |args| represented }, :extend => ArtistRepresenter # end # let (:album) { OpenStruct.new(:label => "Epitaph").extend(representer) } # it "renders nested Album-properties in separate section" do # render(album).must_equal_document output # end # end # end for_formats({ :hash => [Representable::Hash, {"album" => {"artist" => {"label"=>"Epitaph"}}}], # :xml => [Representable::XML, ""], #:yaml => [Representable::YAML, "---\nlabel:\n label: Epitaph\n owner: Brett Gurewitz\n"] }) do |format, mod, output, input| class ArtistDecorator < Representable::Decorator include Representable::JSON property :label end describe ":getter with :decorator" do let (:format) { format } representer!(:module => mod) do self.representation_wrap = "album" property :artist, :getter => lambda { |args| represented }, :decorator => ArtistDecorator end let (:album) { OpenStruct.new(:label => "Epitaph").extend(representer) } it "renders nested Album-properties in separate section" do render(album).must_equal_document output end end end # test helper methods within inline representer for_formats({ :hash => [Representable::Hash, {"song"=>{"name"=>"ALIVE"}}], :xml => [Representable::XML, "\n \n ALIVE\n \n"], :yaml => [Representable::YAML, "---\nsong:\n name: ALIVE\n"], }) do |format, mod, output| describe "helper method within inline representer [#{format}]" do let (:format) { format } representer!(:module => mod, :decorator => true) do self.representation_wrap = :request if format == :xml property :requester property :song do property :name, :exec_context => :decorator define_method :name do represented.name.upcase end self.representation_wrap = :song if format == :xml end end let (:request) { representer.prepare(OpenStruct.new(:song => Song.new("Alive"))) } it do render(request).must_equal_document output end end end describe "deprecate mixing :extend and inline representers" do # TODO: remove in 2.0. representer! do rpr_module = Module.new do include Representable::Hash property :title end property :song, :extend => rpr_module do property :artist end end it do OpenStruct.new(:song => OpenStruct.new(:title => "The Fever And The Sound", :artist => "Strung Out")).extend(representer). to_hash. must_equal({"song"=>{"artist"=>"Strung Out", "title"=>"The Fever And The Sound"}}) end end describe "include module in inline representers" do representer! do extension = Module.new do include Representable::Hash property :title end property :song do include extension property :artist end end it do OpenStruct.new(:song => OpenStruct.new(:title => "The Fever And The Sound", :artist => "Strung Out")).extend(representer). to_hash. must_equal({"song"=>{"artist"=>"Strung Out", "title"=>"The Fever And The Sound"}}) end end end