test/twin/twin_test.rb in disposable-0.0.6 vs test/twin/twin_test.rb in disposable-0.0.7

- old
+ new

@@ -7,73 +7,63 @@ Album = Struct.new(:id, :name, :songs) end module Twin - class Song < Disposable::Twin - end - class Album < Disposable::Twin property :id # DISCUSS: needed for #save. property :name collection :songs, :twin => lambda { |*| Song } - model Model::Album + # model Model::Album end class Song < Disposable::Twin property :id # DISCUSS: needed for #save. - property :title + property :name, :as => :title property :album, :twin => Album - model Model::Song + # model Model::Song end end + let (:song) { Model::Song.new(1, "Broken", nil) } - describe "::new" do # TODO: this creates a new model! - let(:album) { Twin::Album.new } - let (:song) { Twin::Song.new } + describe "#initialize" do + it do + twin = Twin::Song.new(song) + song.id = 2 + # :as maps public name + twin.name.must_equal "Broken" # public: #name + twin.id.must_equal 2 + end - it { album.name.must_equal nil } - it { album.songs.must_equal nil } - it { song.title.must_equal nil } - it { song.album.must_equal nil } - end + # override property with public name in constructor. + it do + # override twin's value... + Twin::Song.new(song, :name => "Kenny").name.must_equal "Kenny" - - describe "::new with arguments" do - let (:talking) { Twin::Song.new("title" => "Talking") } - let (:album) { Twin::Album.new(:name => "30 Years", :songs => [talking]) } - subject { Twin::Song.new("title" => "Broken", "album" => album) } - - it { subject.title.must_equal "Broken" } - it { subject.album.must_equal album } - it { subject.album.name.must_equal "30 Years" } - it { album.songs.must_equal [talking] } + # .. but do not write to the model! + song.title.must_equal "Broken" + end end + describe "setter" do + let (:twin) { Twin::Song.new(song) } - describe "::new with :symbols" do - subject { Twin::Song.new(:title => "Broken") } + before do + twin.id = 3 + twin.name = "Lucky" + end - it { subject.title.must_equal "Broken" } - it { subject.album.must_equal nil } - end + # updates twin + it { twin.id.must_equal 3 } + it { twin.name.must_equal "Lucky" } - - # DISCUSS: make ::from private. - describe "::from" do - let (:song) { Model::Song.new(1, "Broken", album) } - let (:album) { Model::Album.new(2, "The Process Of Belief", [Model::Song.new(3, "Dr. Stein")]) } - - subject {Twin::Song.from(song) } - - it { subject.title.must_equal "Broken" } - it { subject.album.must_be_kind_of Twin::Album } - it { subject.album.name.must_equal album.name } - it { subject.album.songs.first.title.must_equal "Dr. Stein" } # TODO: more tests on collections and object identity (if we need that). + # DOES NOT update model + it { song.id.must_equal 1 } + it { song.title.must_equal "Broken" } end end class OverridingAccessorsTest < TwinTest @@ -84,27 +74,44 @@ def title super.downcase end end - it { Song.from(Model::Song.new(1, "A Tale That Wasn't Right")).title.must_equal "a tale that wasn't right" } + 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 -# from is as close to from_hash as possible -# there should be #to in a perfect API, nothing else. +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 -# should #new create empty associated models? + # 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 @@ -112,72 +119,46 @@ module Twin class Album < Disposable::Twin property :record_name, :as => :name - model Model::Album + # model Model::Album end class Song < Disposable::Twin property :name, :as => :title property :record, :twin => Album, :as => :album - model Model::Song + # model Model::Song end end - - let (:record) { Twin::Album.new(:record_name => "Veni Vidi Vicous") } - subject { Twin::Song.new(:name => "Outsmarted", :record => record) } - - - describe "::new" do # TODO: this creates a new model! - # the Twin exposes the as: API. - it { subject.name.must_equal "Outsmarted" } - it { subject.record.must_equal record } - end - - # DISCUSS: should we test saving without AR? is that worth the hustle? - # describe "#save" do - # before { subject.send(:model).instance_eval do - # def update_attributes(*) - - # end - # end - # subject.save - # } - - - - # # before { subject.save } - - # it { subject.name } - # end end -require 'disposable/twin/option' class TwinOptionTest < TwinTest class Song < Disposable::Twin - include Option - 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) } - describe "::from" do - let (:song) { Model::Song.new(1, "Broken") } - let (:twin) { Song.from(song, :preview? => false) } - it { twin.id.must_equal 1 } - it { twin.title.must_equal "Broken" } - it { twin.preview?.must_equal false } + # properties are read from model. + it { twin.id.must_equal 1 } + it { twin.title.must_equal "Broken" } - it { Song.from(song, :preview? => true, :highlight => false).preview?.must_equal true } - end + # 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 # TODO: test coercion! \ No newline at end of file