spec/moosex_spec.rb in moosex-0.0.9 vs spec/moosex_spec.rb in moosex-0.0.10

- old
+ new

@@ -1,755 +1,16 @@ require 'moosex' -class Point +class A include MooseX - - has x: { - is: :rw, # read-write (mandatory) - isa: Integer, # should be Integer - default: 0, # default value is 0 (constant) - } - - has y: { - is: :rw, - isa: Integer, - default: lambda { 0 }, # you should specify a lambda - } - - def clear - self.x= 0 # to run with type-check you must - self.y= 0 # use the setter instad @x= - end -end - -describe "Point" do - describe "should has an intelligent constructor" do - it "without arguments, should initialize with default values" do - p = Point.new - p.x.should be_zero - p.y.should be_zero - end - - it "should initialize only y" do - p = Point.new( x: 5 ) - p.x.should == 5 - p.y.should be_zero - end - - it "should initialize x and y" do - p = Point.new( x: 5, y: 4) - p.x.should == 5 - p.y.should == 4 - end - end - - describe "should create a getter and a setter" do - it "for x" do - p = Point.new - p.x= 5 - p.x.should == 5 - end - - it "for x, with type check" do - p = Point.new - expect { - p.x = "lol" - }.to raise_error('isa check for "x" failed: is not instance of Integer!') - end - - it "for x, with type check" do - expect { - Point.new(x: "lol") - }.to raise_error('isa check for "x" failed: is not instance of Integer!') - end - - it "clear should clean attributes" do - p = Point.new( x: 5, y: 4) - p.clear - p.x.should be_zero - p.y.should be_zero - end - end end -class Foo - include MooseX - - has bar: { - is: :rwp, # read-write-private (private setter) - required: true, # you should require in the constructor - } - - has my_other_bar: { - is: :rw, - init_arg: :bar2 - } -end - -describe "Foo" do - it "should require bar if necessary" do - expect { - Foo.new - }.to raise_error("attr \"bar\" is required") +describe "MooseX" do + it "should contains has method" do + A.methods.include?(:has).should be_true end - it "should require bar if necessary" do - foo = Foo.new( bar: 123 ) - foo.bar.should == 123 - end - - it "should not be possible update bar (setter private)" do - foo = Foo.new( bar: 123 ) - expect { - foo.bar = 1024 - }.to raise_error(NoMethodError) - end - - it "should be possible initialize my_other_bar by bar2" do - foo = Foo.new( bar: 1, bar2: 555) - foo.my_other_bar.should == 555 - end -end - -class Baz - include MooseX - - has bam: { - is: :ro, # read-only, you should specify in new only - isa: lambda do |bam| # you should add your own validator - raise 'bam should be less than 100' if bam > 100 - end, - required: true, - } - - has boom: { - is: :rw, - predicate: true, # add has_boom? method, ask if the attribute is unset - clearer: true, # add reset_boom! method, unset the attribute - } -end - -describe "Baz" do - it "should require bam if necessary" do - baz = Baz.new( bam: 99 ) - baz.bam.should == 99 - end - - it "should not be possible update baz (read only)" do - baz = Baz.new( bam: 99 ) - expect { - baz.bam = 1024 - }.to raise_error(NoMethodError) - end - - it "should run the lambda isa" do - expect { - Baz.new( bam: 199 ) - }.to raise_error(/bam should be less than 100/) - end - - it "rw acessor should has nil value, supports predicate" do - baz = Baz.new( bam: 99 ) - - baz.has_boom?.should be_false - baz.boom.should be_nil - baz.boom= 0 - baz.has_boom?.should be_true - baz.boom.should be_zero - end - - it "rw acessor should has nil value, supports clearer" do - baz = Baz.new( bam: 99, boom: 0 ) - - baz.has_boom?.should be_true - baz.boom.should be_zero - - baz.reset_boom! - - baz.has_boom?.should be_false - baz.boom.should be_nil - end - - it "should be possible call the clearer twice" do - baz = Baz.new( bam: 99, boom: 0 ) - - baz.reset_boom! - baz.reset_boom! - - baz.has_boom?.should be_false - baz.boom.should be_nil - end -end - -class Lol - include MooseX - - has [:a, :b], { # define attributes a and b - is: :ro, # with same set of properties - default: 0, - } - - has c: { # alternative syntax to be - is: :ro, # more similar to Moo/Moose - default: 1, - predicate: :can_haz_c?, # custom predicate - clearer: "desintegrate_c", # force coerce to symbol - } - - has [:d, :e] => { - is: "ro", # can coerce from strings - default: 2, - required: true, - } -end - -describe "Lol" do - it "Lol should has five arguments" do - lol = Lol.new(a: 5, d: -1) - lol.a.should == 5 - lol.b.should be_zero - lol.c.should == 1 - lol.d.should == -1 - lol.e.should == 2 - end - - it "Lol should support custom predicate and clearer" do - lol = Lol.new(a: 5, d: -1) - - lol.can_haz_c?.should be_true - lol.desintegrate_c - lol.can_haz_c?.should be_false - end -end - -class ProxyToTarget - include MooseX - - has target: { - is: :ro, - default: lambda { Target.new }, # default, new instace of Target - handles: { # handles is for delegation, - my_method_x: :method_x, # inject methods with new names - my_method_y: :method_y, # old => obj.target.method_x - }, # now => obj.my_method_x - } -end - -module TargetModule - def method_x; 1024; end # works with simple methods - def method_y(a,b,c); a + b + c; end # or methods with arguments -end - -class Target - include TargetModule -end - -describe "ProxyToTarget" do - it "should delegate method_x to the target" do - p = ProxyToTarget.new - - p.target.method_x.should == 1024 - p.my_method_x.should == 1024 - end - - it "should delegate method_y to the target" do - p = ProxyToTarget.new - - p.target.method_y(1,2,3).should == 6 - p.my_method_y(1,2,3).should == 6 - end -end - -class ProxyToTargetUsingArrayOfMethods - include MooseX - - has targetz: { - is: :ro, - default: lambda { Target.new }, - handles: [ - :method_x, :method_y # will inject all methods with same name - ] - } -end - -describe "ProxyToTargetUsingArrayOfMethods" do - it "should delegate method_x to the target" do - p = ProxyToTargetUsingArrayOfMethods.new - - p.targetz.method_x.should == 1024 - p.method_x.should == 1024 - end - - it "should delegate method_y to the target" do - p = ProxyToTargetUsingArrayOfMethods.new - - p.targetz.method_y(1,2,3).should == 6 - p.method_y(1,2,3).should == 6 - end -end - -class ProxyToTargetUsingSingleMethod - include MooseX - - has target: { - is: :ro, - default: lambda { Target.new }, - handles: "method_x" # coerce to an array of symbols - } -end - -describe "ProxyToTargetUsingSingleMethod" do - it "should delegate method_x to the target" do - p = ProxyToTargetUsingSingleMethod.new - - p.target.method_x.should == 1024 - p.method_x.should == 1024 - end -end - -class ProxyToTargetUsingModule - include MooseX - - has target: { - is: :ro, - default: lambda { Target.new }, - handles: TargetModule # will import all methods from module - } -end - -describe "ProxyToTargetUsingModule" do - it "should delegate method_x to the target" do - p = ProxyToTargetUsingModule.new - - p.target.method_x.should == 1024 - p.method_x.should == 1024 - end - - it "should delegate method_y to the target" do - p = ProxyToTargetUsingModule.new - - p.target.method_y(1,2,3).should == 6 - p.method_y(1,2,3).should == 6 - end -end - -class ProxyToTargetUsingClass - include MooseX - - has target: { - is: :ro, - default: lambda { Target.new }, - handles: Target # will use only public methods on Target class - } # exclude methods from superclass -end - -describe "ProxyToTargetUsingClass" do - it "should delegate method_x to the target" do - p = ProxyToTargetUsingClass.new - - p.target.method_x.should == 1024 - p.method_x.should == 1024 - end - - it "should delegate method_y to the target" do - p = ProxyToTargetUsingClass.new - - p.target.method_y(1,2,3).should == 6 - p.method_y(1,2,3).should == 6 - end -end - -class Point3D < Point - - has x: { # override original attr! - is: :rw, - isa: Integer, - default: 1, - } - - has z: { - is: :rw, # read-write (mandatory) - isa: Integer, # should be Integer - default: 0, # default value is 0 (constant) - } - - has color: { - is: :rw, # you should specify the reader/writter - reader: :what_is_the_color_of_this_point, - writter: :set_the_color_of_this_point, - default: :red, - } - - def clear - self.x= 0 # to run with type-check you must - self.y= 0 # use the setter instad @x= - self.z= 0 - end -end - -describe "Point3D" do - describe "should has an intelligent constructor" do - it "without arguments, should initialize with default values" do - p = Point3D.new - p.x.should == 1 - p.y.should be_zero - p.z.should be_zero - p.what_is_the_color_of_this_point.should == :red - end - - it "should initialize only y" do - p = Point3D.new( x: 5 ) - p.x.should == 5 - p.y.should be_zero - p.z.should be_zero - p.what_is_the_color_of_this_point.should == :red - end - - it "should initialize x and y" do - p = Point3D.new( x: 5, y: 4, z: 8, color: :yellow) - p.x.should == 5 - p.y.should == 4 - p.z.should == 8 - p.what_is_the_color_of_this_point.should == :yellow - end - end - - describe "should create a getter and a setter" do - it "for z" do - p = Point3D.new - p.z= 5 - p.z.should == 5 - end - - it "for z, with type check" do - p = Point3D.new - expect { - p.z = "lol" - }.to raise_error('isa check for "z" failed: is not instance of Integer!') - end - - it "for z, with type check" do - expect { - Point3D.new(z: "lol") - }.to raise_error('isa check for "z" failed: is not instance of Integer!') - end - - it "clear should clean attributes" do - p = Point3D.new( x: 5, y: 4, z: 9) - p.clear - p.x.should be_zero - p.y.should be_zero - p.z.should be_zero - end - end - - describe "should create the accessors names with custom names" do - it "should get/set" do - p = Point3D.new - p.what_is_the_color_of_this_point.should == :red - p.set_the_color_of_this_point(:black) - p.what_is_the_color_of_this_point.should == :black - end - end -end - -class LazyFox - include MooseX - - has something: { - is: :lazy - } - - has other_thing: { - is: :rw, - lazy: true, - predicate: true, - clearer: true, - builder: :my_build_other_thing, - } - - has lazy_attr_who_accepts_lambda: { - is: :lazy, - builder: lambda{ |object| object.something } - } - - has lazy_with_default: { - is: :lazy, - default: 10, - clearer: true, - builder: lambda {|o| 1 }, - } - - has last_lazy_attr: { - is: :rw, - lazy: true, - } - - def build_something - 1024 - end - - private - def my_build_other_thing - 128 - end -end - -describe "LazyFox" do - it "lazy attr should be act as a normal read only attr" do - l = LazyFox.new(something: 0) - l.something.should == 0 - end - - it "lazy attr should be read-only" do - l = LazyFox.new - expect{ - l.something= 1 - }.to raise_error(NoMethodError) - end - - it "lazy: true but is :rw should act as a defered default value" do - l = LazyFox.new - l.other_thing.should == 128 - l.other_thing = 9 - l.other_thing.should == 9 - end - - it "lazy: true should not exists until necessary" do - l = LazyFox.new - l.has_other_thing?.should be_false - - l.other_thing.should == 128 - - l.has_other_thing?.should be_true - end - - it "lazy: true :rw should build again" do - l = LazyFox.new - l.other_thing.should == 128 - - l.has_other_thing?.should be_true - - l.reset_other_thing! - - l.has_other_thing?.should be_false - - l.other_thing.should == 128 - - l.has_other_thing?.should be_true - end - - it "lazy attr should call build if necessary" do - l = LazyFox.new - l.something.should == 1024 - l.other_thing.should == 128 - end - - it "lazy attr should accept lambda" do - l = LazyFox.new - l.lazy_attr_who_accepts_lambda.should == 1024 - end - - it "lazy attr should accept lambda (2)" do - l = LazyFox.new(something: 2) - l.lazy_attr_who_accepts_lambda.should == 2 - end - - it "lazy_with_default should be initialize with default value" do - l = LazyFox.new - l.lazy_with_default.should == 10 - l.reset_lazy_with_default! - l.lazy_with_default.should == 1 - end - - it "last_lazy_attr will raise error without a builder" do - l = LazyFox.new - expect { - l.last_lazy_attr - }.to raise_error(NoMethodError) - end - - it "last_lazy_attr will not raise error with a builder" do - l = LazyFox.new - def l.build_last_lazy_attr - 0 - end - l.last_lazy_attr.should be_zero - end -end - -class CoerceTest - include MooseX - - has attribute_ro: { - is: :ro, - isa: Integer, - coerce: lambda {|value| value.to_i }, - } - - has attribute_rw: { - is: :rw, - isa: Integer, - coerce: lambda {|value| value.to_i }, - } - - has attribute_lazy: { - is: :lazy, - isa: Integer, - coerce: lambda {|value| value.to_i }, - builder: lambda{|object| "2048" }, - } - - def trigger_attr(new_value) - puts "change value of attribute to #{new_value}" - end -end - -describe "CoerceTest" do - it "should coerce the argument using to_i on constructor" do - ct = CoerceTest.new(attribute_ro: "12") - ct.attribute_ro.should == 12 - end - - it "should coerce the argument using to_i on constructor" do - ct = CoerceTest.new(attribute_rw: "12") - ct.attribute_rw.should == 12 - end - - it "should coerce in the setter" do - ct = CoerceTest.new - ct.attribute_rw= "128" - ct.attribute_rw.should == 128 - end - - it "should coerce from builder" do - ct = CoerceTest.new - ct.attribute_lazy.should == 2048 - end -end - -class TriggerTest - include MooseX - - has logger: { - is: :ro - } - - has attr_with_trigger: { - is: :rw, - trigger: :my_method, - } - - has attr_with_trigger_ro: { - is: :ro, - trigger: :my_method, - } - - has attr_with_default: { - is: :rw, - trigger: lambda do |object, new_value| - object.logger.log "will update attr_with_trigger with new value #{new_value}" - end, - default: 1, - } - - has attr_lazy_trigger: { - is: :lazy, - trigger: :my_method, - builder: lambda{ |x| 1}, - } - - def my_method(new_value) - logger.log "will update attr_with_trigger with new value #{new_value}" - end -end - -describe "TriggerTest" do - it "should call trigger on constructor" do - log = double - log.should_receive(:log) - t = TriggerTest.new(attr_with_trigger: 1, logger: log) - - end - - it "should call trigger on constructor (ro)" do - log = double - log.should_receive(:log) - t = TriggerTest.new(attr_with_trigger_ro: 1, logger: log) - - end - - it "should NOT call trigger on constructor (with default)" do - log = double - log.should_not_receive(:log) - t = TriggerTest.new(logger: log) - end - - it "should NOT call trigger on constructor (with default)" do - log = double - log.should_receive(:log) - t = TriggerTest.new(logger: log) - - t.attr_with_default = 1 - end - - it "should call trigger on setter" do - log = double - log.should_receive(:log) - t = TriggerTest.new(logger: log) - - t.attr_with_trigger = 1 - end - - it "should call trigger on setter" do - log = double - log.should_receive(:log) - t = TriggerTest.new(logger: log) - - t.attr_lazy_trigger.should == 1 - end -end - -class BuildArgsExample - include MooseX - - has [:x, :y], { - is: :rw, - required: true, - } - - def BUILDARGS(args) - args[:x] = 1024 - args[:y] = - args[:y] - args - end -end - -describe "BuildArgsExample" do - it "should create the object" do - ex = BuildArgsExample.new(x: 10, y: -2) - ex.x.should == 1024 - ex.y.should == 2 - end -end - -class BuildExample - include MooseX - - has [:x, :y], { - is: :rw, - required: true, - } - def BUILD - if self.x == self.y - raise "invalid: you should use x != y" - end - end -end - -describe "BuildExample" do - it "should raise exception on build" do - expect { - BuildExample.new(x: 0, y: 0) - }.to raise_error(/invalid: you should use x != y/) + it "should be possible create one single instance" do + a = A.new + a.is_a?(A).should be_true end end \ No newline at end of file