test/twin/twin_test.rb in disposable-0.0.9 vs test/twin/twin_test.rb in disposable-0.1.0

- old
+ new

@@ -1,69 +1,100 @@ require 'test_helper' - class TwinTest < MiniTest::Spec module Model Song = Struct.new(:id, :title, :album) - Album = Struct.new(:id, :name, :songs) + Album = Struct.new(:id, :name, :songs, :artist) + Artist = Struct.new(:id) end module Twin class Album < Disposable::Twin property :id # DISCUSS: needed for #save. property :name collection :songs, :twin => lambda { |*| Song } - - # model Model::Album + property :artist, :twin => lambda { |*| Artist } end class Song < Disposable::Twin property :id # DISCUSS: needed for #save. - property :name, :from => :title + property :title property :album, :twin => Album + end - # model Model::Song + class Artist < Disposable::Twin + property :id + + include Setup end end let (:song) { Model::Song.new(1, "Broken", nil) } describe "#initialize" do it do twin = Twin::Song.new(song) song.id = 2 # :from maps public name - twin.name.must_equal "Broken" # public: #name - twin.id.must_equal 2 + twin.title.must_equal "Broken" # public: #record_name + twin.id.must_equal 1 end - # override property with public name in constructor. + # allows passing options. it do # override twin's value... - Twin::Song.new(song, :name => "Kenny").name.must_equal "Kenny" + Twin::Song.new(song, :title => "Kenny").title.must_equal "Kenny" # .. but do not write to the model! song.title.must_equal "Broken" end end describe "setter" do let (:twin) { Twin::Song.new(song) } + let (:album) { Model::Album.new(1, "The Stories Are True") } - before do + it do twin.id = 3 - twin.name = "Lucky" + twin.title = "Lucky" + twin.album = album # this is a model, not a twin. + + # updates twin + twin.id.must_equal 3 + twin.title.must_equal "Lucky" + + # setter for nested property will twin value. + twin.album.extend(Disposable::Comparable) + assert twin.album == Twin::Album.new(album) # FIXME: why does must_equal not call #== ? + + # setter for nested collection. + + # DOES NOT update model + song.id.must_equal 1 + song.title.must_equal "Broken" end - # updates twin - it { twin.id.must_equal 3 } - it { twin.name.must_equal "Lucky" } + # setters for twin properties return the twin, not the model + # it do + # result = twin.album = album + # result.must_equal twin.album + # end + end - # DOES NOT update model - it { song.id.must_equal 1 } - it { song.title.must_equal "Broken" } + # FIXME: experimental. + describe "#to_s" do + class HitTwin < Disposable::Twin + include Setup + + property :song do + end + end + + let (:hit) { OpenStruct.new(song: song) } + it { HitTwin.new(hit).to_s.must_match "#<TwinTest::HitTwin:" } + it { HitTwin.new(hit).song.to_s.must_match "#<Twin (inline):" } end end class OverridingAccessorsTest < TwinTest @@ -78,40 +109,10 @@ it { Song.new(Model::Song.new(1, "A Tale That Wasn't Right")).title.must_equal "a tale that wasn't right" } end -class TwinDecoratorTest < MiniTest::Spec - subject { TwinTest::Twin::Song.representer_class.new(nil) } - - it { subject.twin_names.must_equal [:album] } -end - - -require 'disposable/twin/struct' -class TwinStructTest < MiniTest::Spec - class Song < Disposable::Twin - include Struct - property :number, :default => 1 # FIXME: this should be :default_if_nil so it becomes clear with a model. - option :cool? - end - - # empty hash - it { Song.new({}).number.must_equal 1 } - # model hash - it { Song.new(number: 2).number.must_equal 2 } - - # with hash and options as one hash. - it { Song.new(number: 3, cool?: true).cool?.must_equal true } - it { Song.new(number: 3, cool?: true).number.must_equal 3 } - - # with model hash and options hash separated. - it { Song.new({number: 3}, {cool?: true}).cool?.must_equal true } - it { Song.new({number: 3}, {cool?: true}).number.must_equal 3 } -end - - class TwinAsTest < MiniTest::Spec module Model Song = Struct.new(:title, :album) Album = Struct.new(:name) end @@ -131,86 +132,6 @@ # model Model::Song end end end - - -class TwinOptionTest < TwinTest - class Song < Disposable::Twin - property :id # DISCUSS: needed for #save. - property :title - - option :preview? - option :highlight? - end - - let (:song) { Model::Song.new(1, "Broken") } - let (:twin) { Song.new(song, :preview? => false) } - - - # properties are read from model. - it { twin.id.must_equal 1 } - it { twin.title.must_equal "Broken" } - - # option is not delegated to model. - it { twin.preview?.must_equal false } - # not passing option means zero. - it { twin.highlight?.must_equal nil } - - # passing both options. - it { Song.new(song, preview?: true, highlight?: false).preview?.must_equal true } -end - - -class TwinBuilderTest < MiniTest::Spec - class Twin < Disposable::Twin - property :id - property :title - option :is_released - end - - describe "without property setup" do - class Host - include Disposable::Twin::Builder - - twin Twin - - def initialize(*args) - @model = build_twin(*args) - end - - attr_reader :model - end - - subject { Host.new(TwinTest::Model::Song.new(1, "Saturday Night"), is_released: true) } - - # model is simply the twin. - it { subject.respond_to?(:title).must_equal false } - it { subject.model.id.must_equal 1 } - it { subject.model.title.must_equal "Saturday Night" } - it { subject.model.is_released.must_equal true } - end - - - describe "without property setup" do - class HostWithReaders - include Disposable::Twin::Builder - - extend Forwardable - twin(Twin) { |dfn| def_delegator :@model, dfn.name } - - def initialize(*args) - @model = build_twin(*args) - end - end - - subject { HostWithReaders.new(TwinTest::Model::Song.new(1, "Saturday Night"), is_released: true) } - - # both twin gets created and reader method defined. - it { subject.id.must_equal 1 } - it { subject.title.must_equal "Saturday Night" } - it { subject.is_released.must_equal true } - end -end - # TODO: test coercion! \ No newline at end of file