require File.dirname(__FILE__) + '/../spec_helper' require 'database_cleaner/active_record/transaction' require 'database_cleaner/data_mapper/transaction' require 'database_cleaner/mongo_mapper/truncation' require 'database_cleaner/mongoid/truncation' require 'database_cleaner/couch_potato/truncation' module DatabaseCleaner describe Base do describe "autodetect" do #Cache all ORMs, we'll need them later but not now. before(:all) do Temp_AR = ::ActiveRecord if defined?(::ActiveRecord) and not defined?(Temp_AR) Temp_DM = ::DataMapper if defined?(::DataMapper) and not defined?(Temp_DM) Temp_MM = ::MongoMapper if defined?(::MongoMapper) and not defined?(Temp_MM) Temp_MO = ::Mongoid if defined?(::Mongoid) and not defined?(Temp_MO) Temp_CP = ::CouchPotato if defined?(::CouchPotato) and not defined?(Temp_CP) Temp_SQ = ::Sequel if defined?(::Sequel) and not defined?(Temp_SQ) end #Remove all ORM mocks and restore from cache after(:all) do Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord) Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper) Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper) Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid) Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato) Object.send(:remove_const, 'Sequel') if defined?(::Sequel) # Restore ORMs ::ActiveRecord = Temp_AR if defined? Temp_AR ::DataMapper = Temp_DM if defined? Temp_DM ::MongoMapper = Temp_MM if defined? Temp_MM ::Mongoid = Temp_MO if defined? Temp_MO ::CouchPotato = Temp_CP if defined? Temp_CP end #reset the orm mocks before(:each) do Object.send(:remove_const, 'ActiveRecord') if defined?(::ActiveRecord) Object.send(:remove_const, 'DataMapper') if defined?(::DataMapper) Object.send(:remove_const, 'MongoMapper') if defined?(::MongoMapper) Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid) Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato) Object.send(:remove_const, 'Sequel') if defined?(::Sequel) end let(:cleaner) { DatabaseCleaner::Base.new :autodetect } it "should raise an error when no ORM is detected" do running { cleaner }.should raise_error(DatabaseCleaner::NoORMDetected) end it "should detect ActiveRecord first" do Object.const_set('ActiveRecord','Actively mocking records.') Object.const_set('DataMapper', 'Mapping data mocks') Object.const_set('MongoMapper', 'Mapping mock mongos') Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') cleaner.orm.should == :active_record cleaner.should be_auto_detected end it "should detect DataMapper second" do Object.const_set('DataMapper', 'Mapping data mocks') Object.const_set('MongoMapper', 'Mapping mock mongos') Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') cleaner.orm.should == :data_mapper cleaner.should be_auto_detected end it "should detect MongoMapper third" do Object.const_set('MongoMapper', 'Mapping mock mongos') Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') cleaner.orm.should == :mongo_mapper cleaner.should be_auto_detected end it "should detect Mongoid fourth" do Object.const_set('Mongoid', 'Mongoid mock') Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') cleaner.orm.should == :mongoid cleaner.should be_auto_detected end it "should detect CouchPotato fifth" do Object.const_set('CouchPotato', 'Couching mock potatos') Object.const_set('Sequel', 'Sequel mock') cleaner.orm.should == :couch_potato cleaner.should be_auto_detected end it "should detect Sequel last" do Object.const_set('Sequel', 'Sequel mock') cleaner.orm.should == :sequel cleaner.should be_auto_detected end end describe "orm_module" do it "should ask ::DatabaseCleaner what the module is for its orm" do orm = mock("orm") mockule = mock("module") cleaner = ::DatabaseCleaner::Base.new cleaner.should_receive(:orm).and_return(orm) ::DatabaseCleaner.should_receive(:orm_module).with(orm).and_return(mockule) cleaner.send(:orm_module).should == mockule end end describe "comparison" do it "should be equal if orm, connection and strategy are the same" do strategy = mock("strategy") one = DatabaseCleaner::Base.new(:active_record,:connection => :default) one.strategy = strategy two = DatabaseCleaner::Base.new(:active_record,:connection => :default) two.strategy = strategy one.should == two two.should == one end end describe "initialization" do context "db specified" do subject { ::DatabaseCleaner::Base.new(:active_record,:connection => :my_db) } it "should store db from :connection in params hash" do subject.db.should == :my_db end end describe "orm" do it "should store orm" do cleaner = ::DatabaseCleaner::Base.new :a_orm cleaner.orm.should == :a_orm end it "converts string to symbols" do cleaner = ::DatabaseCleaner::Base.new "mongoid" cleaner.orm.should == :mongoid end it "is autodetected if orm is not provided" do cleaner = ::DatabaseCleaner::Base.new cleaner.should be_auto_detected end it "is autodetected if you specify :autodetect" do cleaner = ::DatabaseCleaner::Base.new "autodetect" cleaner.should be_auto_detected end it "should default to autodetect upon initalisation" do subject.should be_auto_detected end end end describe "db" do it "should default to :default" do subject.db.should == :default end it "should return any stored db value" do subject.stub(:strategy_db=) subject.db = :test_db subject.db.should == :test_db end it "should pass db to any specified strategy" do subject.should_receive(:strategy_db=).with(:a_new_db) subject.db = :a_new_db end end describe "strategy_db=" do let(:strategy) { mock("strategy") } before(:each) do subject.strategy = strategy end it "should check that strategy supports db specification" do strategy.should_receive(:respond_to?).with(:db=).and_return(true) strategy.stub(:db=) subject.strategy_db = :a_db end context "when strategy supports db specification" do before(:each) { strategy.stub(:respond_to?).with(:db=).and_return true } it "should pass db to the strategy" do strategy.should_receive(:db=).with(:a_db) subject.strategy_db = :a_db end end context "when strategy doesn't supports db specification" do before(:each) { strategy.stub(:respond_to?).with(:db=).and_return false } it "should check to see if db is :default" do db = mock("default") db.should_receive(:==).with(:default).and_return(true) subject.strategy_db = db end it "should raise an argument error when db isn't default" do db = mock("a db") expect{ subject.strategy_db = db }.to raise_error ArgumentError end end end describe "clean_with" do let (:strategy) { mock("strategy",:clean => true) } before(:each) { subject.stub(:create_strategy).with(anything).and_return(strategy) } it "should pass all arguments to create_strategy" do subject.should_receive(:create_strategy).with(:lorum, :dollar, :amet, :ipsum => "random").and_return(strategy) subject.clean_with :lorum, :dollar, :amet, { :ipsum => "random" } end it "should invoke clean on the created strategy" do strategy.should_receive(:clean) subject.clean_with :strategy end it "should return the strategy" do subject.clean_with( :strategy ).should == strategy end end describe "clean_with!" do let (:strategy) { mock("strategy",:clean => true) } before(:each) { subject.stub(:create_strategy).with(anything).and_return(strategy) } it "should pass all arguments to create_strategy" do subject.should_receive(:create_strategy).with(:lorum, :dollar, :amet, :ipsum => "random").and_return(strategy) subject.clean_with! :lorum, :dollar, :amet, { :ipsum => "random" } end it "should invoke clean on the created strategy" do strategy.should_receive(:clean) subject.clean_with! :strategy end it "should return the strategy" do subject.clean_with!( :strategy ).should == strategy end end describe "create_strategy" do let(:klass) { mock("klass",:new => mock("instance")) } before :each do subject.stub(:orm_strategy).and_return(klass) end it "should pass the first argument to orm_strategy" do subject.should_receive(:orm_strategy).with(:strategy).and_return(Object) subject.create_strategy :strategy end it "should pass the remainding argument to orm_strategy.new" do klass.should_receive(:new).with(:params => {:lorum => "ipsum"}) subject.create_strategy :strategy, {:params => {:lorum => "ipsum"}} end it "should return the resulting strategy" do subject.create_strategy( :strategy ).should == klass.new end end describe "strategy=" do let(:mock_strategy) { mock("strategy") } it "should proxy symbolised strategies to create_strategy" do subject.should_receive(:create_strategy).with(:symbol) subject.strategy = :symbol end it "should proxy params with symbolised strategies" do subject.should_receive(:create_strategy).with(:symbol,:param => "one") subject.strategy= :symbol, {:param => "one"} end it "should accept strategy objects" do expect{ subject.strategy = mock_strategy }.to_not raise_error end it "should raise argument error when params given with strategy Object" do expect{ subject.strategy = mock("object"), {:param => "one"} }.to raise_error ArgumentError end it "should attempt to set strategy db" do subject.stub(:db).and_return(:my_db) subject.should_receive(:strategy_db=).with(:my_db) subject.strategy = mock_strategy end it "should return the stored strategy" do result = subject.strategy = mock_strategy result.should == mock_strategy end end describe "strategy" do subject { ::DatabaseCleaner::Base.new :a_orm } it "returns a null strategy when strategy no set and undetectable" do subject.instance_values["@strategy"] = nil subject.strategy.should == DatabaseCleaner::NullStrategy end it "returns the set strategy" do strategum = mock("strategy") subject.strategy = strategum subject.strategy.should == strategum end end describe "orm=" do it "should stored the desired orm" do subject.orm.should_not == :desired_orm subject.orm = :desired_orm subject.orm.should == :desired_orm end end describe "orm" do let(:mock_orm) { mock("orm") } it "should return orm if orm set" do subject.instance_variable_set "@orm", mock_orm subject.orm.should == mock_orm end context "orm isn't set" do before(:each) { subject.instance_variable_set "@orm", nil } it "should run autodetect if orm isn't set" do subject.should_receive(:autodetect) subject.orm end it "should return the result of autodetect if orm isn't set" do subject.stub(:autodetect).and_return(mock_orm) subject.orm.should == mock_orm end end end describe "proxy methods" do let (:strategy) { mock("strategy") } before(:each) do subject.stub(:strategy).and_return(strategy) end describe "start" do it "should proxy start to the strategy" do strategy.should_receive(:start) subject.start end end describe "clean" do it "should proxy clean to the strategy" do strategy.should_receive(:clean) subject.clean end end describe "clean!" do it "should proxy clean! to the strategy clean" do strategy.should_receive(:clean) subject.clean! end end end describe "auto_detected?" do it "should return true unless @autodetected is nil" do subject.instance_variable_set("@autodetected","not nil") subject.auto_detected?.should be_true end it "should return false if @autodetect is nil" do subject.instance_variable_set("@autodetected",nil) subject.auto_detected?.should be_false end end describe "orm_strategy" do let (:klass) { mock("klass") } before(:each) do subject.stub(:orm_module).and_return(klass) end context "in response to a LoadError" do before(:each) { subject.should_receive(:require).with(anything).and_raise(LoadError) } it "should catch LoadErrors" do expect { subject.send(:orm_strategy,:a_strategy) }.to_not raise_error LoadError end it "should raise UnknownStrategySpecified" do expect { subject.send(:orm_strategy,:a_strategy) }.to raise_error UnknownStrategySpecified end it "should ask orm_module if it will list available_strategies" do klass.should_receive(:respond_to?).with(:available_strategies) subject.stub(:orm_module).and_return(klass) expect { subject.send(:orm_strategy,:a_strategy) }.to raise_error UnknownStrategySpecified end it "should use available_strategies (for the error message) if its available" do klass.stub(:respond_to?).with(:available_strategies).and_return(true) klass.should_receive(:available_strategies).and_return([]) subject.stub(:orm_module).and_return(klass) expect { subject.send(:orm_strategy,:a_strategy) }.to raise_error UnknownStrategySpecified end end it "should return the constant of the Strategy class requested" do strategy_klass = mock("strategy klass") subject.stub(:require).with(anything).and_return(true) klass.should_receive(:const_get).with("Cunningplan").and_return(strategy_klass) subject.send(:orm_strategy, :cunningplan).should == strategy_klass end end describe 'set_default_orm_strategy' do it 'sets strategy to :transaction for ActiveRecord' do cleaner = DatabaseCleaner::Base.new(:active_record) cleaner.strategy.should be_instance_of DatabaseCleaner::ActiveRecord::Transaction end it 'sets strategy to :transaction for DataMapper' do cleaner = DatabaseCleaner::Base.new(:data_mapper) cleaner.strategy.should be_instance_of DatabaseCleaner::DataMapper::Transaction end it 'sets strategy to :truncation for MongoMapper' do cleaner = DatabaseCleaner::Base.new(:mongo_mapper) cleaner.strategy.should be_instance_of DatabaseCleaner::MongoMapper::Truncation end it 'sets strategy to :truncation for Mongoid' do cleaner = DatabaseCleaner::Base.new(:mongoid) cleaner.strategy.should be_instance_of DatabaseCleaner::Mongoid::Truncation end it 'sets strategy to :truncation for CouchPotato' do cleaner = DatabaseCleaner::Base.new(:couch_potato) cleaner.strategy.should be_instance_of DatabaseCleaner::CouchPotato::Truncation end end end end