require File.expand_path('../../spec_helper', __FILE__) require File.expand_path('../../fixtures/class', __FILE__) ClassSpecsNumber = 12 module ClassSpecs Number = 12 end describe "A class definition" do it "creates a new class" do ClassSpecs::A.should be_kind_of(Class) ClassSpecs::A.new.should be_kind_of(ClassSpecs::A) end it "has no class variables" do ClassSpecs::A.class_variables.should == [] end it "raises TypeError if constant given as class name exists and is not a Module" do # 1.9 needs the constant defined here because of it's scoping rules ClassSpecsNumber = 12 lambda { class ClassSpecsNumber end }.should raise_error(TypeError) end # test case known to be detecting bugs (JRuby, MRI 1.9) it "raises TypeError if the constant qualifying the class is nil" do lambda { class nil::Foo end }.should raise_error(TypeError) end it "raises TypeError if any constant qualifying the class is not a Module" do lambda { class ClassSpecs::Number::MyClass end }.should raise_error(TypeError) lambda { class ClassSpecsNumber::MyClass end }.should raise_error(TypeError) end it "allows using self as the superclass if self is a class" do ClassSpecs::I::J.superclass.should == ClassSpecs::I lambda { class ShouldNotWork < self; end }.should raise_error(TypeError) end it "raises a TypeError if inheriting from a metaclass" do obj = mock("metaclass super") meta = obj.singleton_class lambda { class ClassSpecs::MetaclassSuper < meta; end }.should raise_error(TypeError) end # # I do not think this is a valid spec -- rue # it "has no class-level instance variables" do # ClassSpecs::A.instance_variables.should == [] # end it "allows the declaration of class variables in the body" do ClassSpecs.string_class_variables(ClassSpecs::B).should == ["@@cvar"] ClassSpecs::B.send(:class_variable_get, :@@cvar).should == :cvar end it "stores instance variables defined in the class body in the class object" do ClassSpecs.string_instance_variables(ClassSpecs::B).should include("@ivar") ClassSpecs::B.instance_variable_get(:@ivar).should == :ivar end it "allows the declaration of class variables in a class method" do ClassSpecs::C.class_variables.should == [] ClassSpecs::C.make_class_variable ClassSpecs.string_class_variables(ClassSpecs::C).should == ["@@cvar"] end it "allows the definition of class-level instance variables in a class method" do ClassSpecs.string_instance_variables(ClassSpecs::C).should_not include("@civ") ClassSpecs::C.make_class_instance_variable ClassSpecs.string_instance_variables(ClassSpecs::C).should include("@civ") end it "allows the declaration of class variables in an instance method" do ClassSpecs::D.class_variables.should == [] ClassSpecs::D.new.make_class_variable ClassSpecs.string_class_variables(ClassSpecs::D).should == ["@@cvar"] end it "allows the definition of instance methods" do ClassSpecs::E.new.meth.should == :meth end it "allows the definition of class methods" do ClassSpecs::E.cmeth.should == :cmeth end it "allows the definition of class methods using class << self" do ClassSpecs::E.smeth.should == :smeth end it "allows the definition of Constants" do Object.const_defined?('CONSTANT').should == false ClassSpecs::E.const_defined?('CONSTANT').should == true ClassSpecs::E::CONSTANT.should == :constant! end it "returns the value of the last statement in the body" do class ClassSpecs::Empty; end.should == nil class ClassSpecs::Twenty; 20; end.should == 20 class ClassSpecs::Plus; 10 + 20; end.should == 30 class ClassSpecs::Singleton; class << self; :singleton; end; end.should == :singleton end end describe "An outer class definition" do ruby_version_is ""..."1.9" do it "contains the inner classes" do ClassSpecs::Container.constants.should include('A', 'B') end end ruby_version_is "1.9" do it "contains the inner classes" do ClassSpecs::Container.constants.should include(:A, :B) end end end describe "A class definition extending an object (sclass)" do it "allows adding methods" do ClassSpecs::O.smeth.should == :smeth end it "raises a TypeError when trying to extend numbers" do lambda { eval <<-CODE class << 1 def xyz self end end CODE }.should raise_error(TypeError) end it "allows accessing the block of the original scope" do ClassSpecs.sclass_with_block { 123 }.should == 123 end not_compliant_on :rubinius do it "can use return to cause the enclosing method to return" do ClassSpecs.sclass_with_return.should == :inner end end end describe "Reopening a class" do it "extends the previous definitions" do c = ClassSpecs::F.new c.meth.should == :meth c.another.should == :another end it "overwrites existing methods" do ClassSpecs::G.new.override.should == :override end it "raises a TypeError when superclasses mismatch" do lambda { class ClassSpecs::A < Array; end }.should raise_error(TypeError) end it "adds new methods to subclasses" do lambda { ClassSpecs::M.m }.should raise_error(NoMethodError) class ClassSpecs::L def self.m 1 end end ClassSpecs::M.m.should == 1 end end describe "class provides hooks" do it "calls inherited when a class is created" do ClassSpecs::H.track_inherited.should == [ClassSpecs::K] end end