require 'assert' require 'mr/factory' require 'thread' require 'mr/fake_record' require 'mr/model' require 'mr/read_model' require 'mr/type_converter' module MR::Factory class UnitTests < Assert::Context desc "MR::Factory" setup do @type_converter = MR::TypeConverter.new end subject{ MR::Factory } should have_imeths :new should have_imeths :primary_key, :decimal, :timestamp should have_imeths :type_converter should "extend `Assert::Factory`" do assert_respond_to :integer, subject assert_respond_to :float, subject assert_respond_to :date, subject assert_respond_to :datetime, subject assert_respond_to :time, subject assert_respond_to :string, subject assert_respond_to :text, subject assert_respond_to :slug, subject assert_respond_to :hex, subject assert_respond_to :binary, subject assert_respond_to :file_name, subject assert_respond_to :dir_path, subject assert_respond_to :file_path, subject assert_respond_to :boolean, subject end should "return unique integers for an identifier using `primary_key`" do assert_equal 1, subject.primary_key('test') assert_equal 2, subject.primary_key('test') assert_equal 1, subject.primary_key('other') end should "return a random decimal using `decimal`" do assert_kind_of BigDecimal, subject.decimal end should "allow passing a maximum value using `decimal`" do decimal = subject.decimal(2) assert decimal <= 2 assert decimal >= 0 end should "return a random time object using `timestamp`" do assert_kind_of Time, subject.timestamp end should "return an instance of MR::TypeConverter using `type_converter`" do assert_instance_of MR::TypeConverter, subject.type_converter end end class NewTests < UnitTests desc "new" setup do @record_factory_built_with = nil Assert.stub(MR::Factory::RecordFactory, :new) do |*args, &block| @record_factory_built_with = args + [block] Assert.stub_send(MR::Factory::RecordFactory, :new, *args, &block) end @model_factory_built_with = nil Assert.stub(MR::Factory::ModelFactory, :new) do |*args, &block| @model_factory_built_with = args + [block] Assert.stub_send(MR::Factory::ModelFactory, :new, *args, &block) end @read_model_factory_built_with = nil Assert.stub(MR::Factory::ReadModelFactory, :new) do |*args, &block| @read_model_factory_built_with = args + [block] Assert.stub_send(MR::Factory::ReadModelFactory, :new, *args, &block) end end should "build a record factory when passed a record class" do block = proc{ Factory.string } factory = subject.new(TestFakeRecord, &block) assert_equal [TestFakeRecord, block], @record_factory_built_with assert_instance_of MR::Factory::RecordFactory, factory end should "build a model factory when passed a model class" do block = proc{ Factory.string } factory = subject.new(TestFakeModel, TestFakeRecord, &block) assert_equal [TestFakeModel, TestFakeRecord, block], @model_factory_built_with assert_instance_of MR::Factory::ModelFactory, factory end should "build a read model factory when passed a read model class" do block = proc{ Factory.string } factory = subject.new(TestReadModel, &block) assert_equal [TestReadModel, block], @read_model_factory_built_with assert_instance_of MR::Factory::ReadModelFactory, factory end should "build a read model factory when passed a read model struct class" do block = proc{ Factory.string } factory = subject.new(TestReadModelStruct, &block) assert_equal [TestReadModelStruct, block], @read_model_factory_built_with assert_instance_of MR::Factory::ReadModelFactory, factory end end class PrimaryKeyProviderTests < UnitTests desc "PrimaryKeyProvider" setup do @provider = PrimaryKeyProvider.new @started_at = @provider.current end subject{ @provider } should have_readers :mutex, :current should "store a mutex and it's current value" do assert_instance_of Mutex, subject.mutex assert_instance_of Fixnum, subject.current end should "increated the counter and return the value using `next`" do next_id = subject.next assert_equal @started_at + 1, next_id assert_equal @started_at + 1, subject.current end should "lock getting the next value using `next`" do threads = [*0..2].map do |n| Thread.new{ Thread.current['id'] = @provider.next } end primary_keys = threads.map{ |thread| thread.join; thread['id'] } assert_includes 1, primary_keys assert_includes 2, primary_keys end end class NoRecordClassErrorTests < UnitTests desc "NoRecordClassError" setup do @error_class = NoRecordClassError end subject{ @error_class } should have_imeths :for_association should "be a runtime error" do assert_true subject < RuntimeError end should "know how to be built for a record reflection" do record = TestFakeRecord.new ar_association = record.association(:user) error = subject.for_association(ar_association) exp = "can't build 'user' association on #{TestFakeRecord} -- try " \ "manually setting it or building it via a stack if you've " \ "configured default associations" assert_equal exp, error.message ar_association = record.association(:parent) error = subject.for_association(ar_association) exp = "can't build 'parent' association on #{TestFakeRecord} -- try " \ "manually setting it, building it via a stack if you've " \ "configured default associations, or setting its 'parent_type' " \ "attribute" assert_equal exp, error.message end end class TestFakeRecord include MR::FakeRecord attribute :parent_type, :string, :null => true attribute :parent_id, :integer, :null => true attribute :user_id, :integer belongs_to :parent, :polymorphic => true belongs_to :user, :class_name => 'MR::Factory::RecordFactory::TestFakeRecord' end class TestFakeModel include MR::Model record_class TestFakeRecord end class TestReadModel include MR::ReadModel end class TestReadModelStruct include MR::ReadModelStruct end end