2011-08-12 16:16:17 -04:00
|
|
|
describe "an instance generated by a factory with multiple traits" do
|
2011-08-09 18:00:24 -04:00
|
|
|
before do
|
2011-08-12 10:35:41 -04:00
|
|
|
define_model("User",
|
2020-06-05 15:15:18 -04:00
|
|
|
name: :string,
|
|
|
|
admin: :boolean,
|
|
|
|
gender: :string,
|
|
|
|
email: :string,
|
|
|
|
date_of_birth: :date,
|
|
|
|
great: :string)
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2011-08-09 18:00:24 -04:00
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
name { "John" }
|
2011-08-09 18:00:24 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :great do
|
2018-07-29 11:30:02 -04:00
|
|
|
great { "GREAT!!!" }
|
2011-08-12 15:05:38 -04:00
|
|
|
end
|
|
|
|
|
2019-09-30 23:53:04 -04:00
|
|
|
trait :great do
|
|
|
|
great { "EVEN GREATER!!!" }
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :admin do
|
2018-07-29 11:30:02 -04:00
|
|
|
admin { true }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :admin_trait do
|
2018-07-29 11:30:02 -04:00
|
|
|
admin { true }
|
2011-08-12 10:35:41 -04:00
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :male do
|
2020-06-05 15:15:18 -04:00
|
|
|
name { "Joe" }
|
2018-07-29 11:30:02 -04:00
|
|
|
gender { "Male" }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :female do
|
2020-06-05 15:15:18 -04:00
|
|
|
name { "Jane" }
|
2018-07-29 11:30:02 -04:00
|
|
|
gender { "Female" }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
|
|
|
|
2011-08-12 15:05:38 -04:00
|
|
|
factory :great_user do
|
|
|
|
great
|
|
|
|
end
|
|
|
|
|
2019-09-30 23:53:04 -04:00
|
|
|
factory :even_greater_user do
|
|
|
|
great
|
|
|
|
|
|
|
|
trait :great do
|
|
|
|
great { "EVEN GREATER!!!" }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-03-09 17:20:38 -05:00
|
|
|
factory :admin, traits: [:admin]
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-10 23:33:50 -04:00
|
|
|
factory :male_user do
|
|
|
|
male
|
2011-08-12 15:05:38 -04:00
|
|
|
|
|
|
|
factory :child_male_user do
|
|
|
|
date_of_birth { Date.parse("1/1/2000") }
|
|
|
|
end
|
2011-08-10 23:33:50 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2012-03-09 17:20:38 -05:00
|
|
|
factory :female, traits: [:female] do
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :admin do
|
2018-07-29 11:30:02 -04:00
|
|
|
admin { true }
|
|
|
|
name { "Judy" }
|
2011-08-10 14:11:53 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2012-03-04 14:28:09 -05:00
|
|
|
factory :female_great_user do
|
|
|
|
great
|
|
|
|
end
|
|
|
|
|
2012-03-09 17:20:38 -05:00
|
|
|
factory :female_admin_judy, traits: [:admin]
|
2011-08-10 14:11:53 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2020-06-05 15:15:18 -04:00
|
|
|
factory :female_admin, traits: [:female, :admin]
|
2012-03-09 17:20:38 -05:00
|
|
|
factory :female_after_male_admin, traits: [:male, :female, :admin]
|
|
|
|
factory :male_after_female_admin, traits: [:female, :male, :admin]
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :email do
|
2011-08-10 14:11:53 -04:00
|
|
|
email { "#{name}@example.com" }
|
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2012-03-09 17:20:38 -05:00
|
|
|
factory :user_with_email, class: User, traits: [:email] do
|
2018-07-29 11:30:02 -04:00
|
|
|
name { "Bill" }
|
2011-08-10 14:11:53 -04:00
|
|
|
end
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "the parent class" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:user) }
|
|
|
|
its(:name) { should eq "John" }
|
2011-08-09 18:00:24 -04:00
|
|
|
its(:gender) { should be_nil }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should_not be_admin }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "the child class with one trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:admin) }
|
|
|
|
its(:name) { should eq "John" }
|
2011-08-09 18:00:24 -04:00
|
|
|
its(:gender) { should be_nil }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should be_admin }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "the other child class with one trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:female) }
|
|
|
|
its(:name) { should eq "Jane" }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:gender) { should eq "Female" }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should_not be_admin }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "the child with multiple traits" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:female_admin) }
|
|
|
|
its(:name) { should eq "Jane" }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:gender) { should eq "Female" }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should be_admin }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "the child with multiple traits and overridden attributes" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:female_admin, name: "Jill", gender: nil) }
|
|
|
|
its(:name) { should eq "Jill" }
|
2011-08-09 18:00:24 -04:00
|
|
|
its(:gender) { should be_nil }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should be_admin }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "the child with multiple traits who override the same attribute" do
|
2011-08-09 18:00:24 -04:00
|
|
|
context "when the male assigns name after female" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:male_after_female_admin) }
|
|
|
|
its(:name) { should eq "Joe" }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:gender) { should eq "Male" }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should be_admin }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-09 18:00:24 -04:00
|
|
|
context "when the female assigns name after male" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:female_after_male_admin) }
|
|
|
|
its(:name) { should eq "Jane" }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:gender) { should eq "Female" }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should be_admin }
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "child class with scoped trait and inherited trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:female_admin_judy) }
|
|
|
|
its(:name) { should eq "Judy" }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:gender) { should eq "Female" }
|
2020-06-05 15:15:18 -04:00
|
|
|
it { should be_admin }
|
2011-08-10 14:11:53 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "factory using global trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:user_with_email) }
|
|
|
|
its(:name) { should eq "Bill" }
|
2018-09-27 21:35:05 -04:00
|
|
|
its(:email) { should eq "Bill@example.com" }
|
2011-08-10 14:11:53 -04:00
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "factory created with alternate syntax for specifying trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:male_user) }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:gender) { should eq "Male" }
|
2011-08-10 23:33:50 -04:00
|
|
|
|
2018-10-21 11:39:48 -04:00
|
|
|
context "where trait name and attribute are the same" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:great_user) }
|
2018-10-21 11:39:48 -04:00
|
|
|
its(:great) { should eq "GREAT!!!" }
|
|
|
|
end
|
2011-08-12 15:05:38 -04:00
|
|
|
|
2018-10-21 11:39:48 -04:00
|
|
|
context "where trait name and attribute are the same and attribute is overridden" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:great_user, great: "SORT OF!!!") }
|
2018-10-21 11:39:48 -04:00
|
|
|
its(:great) { should eq "SORT OF!!!" }
|
|
|
|
end
|
2011-08-12 15:05:38 -04:00
|
|
|
end
|
|
|
|
|
2019-09-30 23:53:04 -04:00
|
|
|
context "factory with trait defined multiple times" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:great_user) }
|
2019-09-30 23:53:04 -04:00
|
|
|
its(:great) { should eq "GREAT!!!" }
|
|
|
|
|
|
|
|
context "child factory redefining trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:even_greater_user) }
|
2019-09-30 23:53:04 -04:00
|
|
|
its(:great) { should eq "EVEN GREATER!!!" }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "child factory created where trait attributes are inherited" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:child_male_user) }
|
|
|
|
its(:gender) { should eq "Male" }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:date_of_birth) { should eq Date.parse("1/1/2000") }
|
2011-08-12 15:05:38 -04:00
|
|
|
end
|
|
|
|
|
2012-03-04 14:28:09 -05:00
|
|
|
context "child factory using grandparents' trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:female_great_user) }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:great) { should eq "GREAT!!!" }
|
2012-03-04 14:28:09 -05:00
|
|
|
end
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-10-28 17:01:27 -04:00
|
|
|
|
2018-11-25 17:41:29 -05:00
|
|
|
describe "trait indifferent access" do
|
|
|
|
context "when trait is defined as a string" do
|
|
|
|
it "can be invoked with a string" do
|
|
|
|
build_user_factory_with_admin_trait("admin")
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, "admin")
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can be invoked with a symbol" do
|
|
|
|
build_user_factory_with_admin_trait("admin")
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, :admin)
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when trait is defined as a symbol" do
|
|
|
|
it "can be invoked with a string" do
|
|
|
|
build_user_factory_with_admin_trait(:admin)
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, "admin")
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can be invoked with a symbol" do
|
|
|
|
build_user_factory_with_admin_trait(:admin)
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, :admin)
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-09-30 23:53:04 -04:00
|
|
|
context "when trait is defined as integer" do
|
|
|
|
it "can be invoked with a string" do
|
|
|
|
build_user_factory_with_admin_trait(42)
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, "42")
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can be invoked with as integer" do
|
|
|
|
build_user_factory_with_admin_trait(42)
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, 42)
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when trait is defined as struct" do
|
|
|
|
it "can be invoked with a string" do
|
|
|
|
instance = Struct.new(:a, :b).new(1, "x")
|
|
|
|
build_user_factory_with_admin_trait(instance)
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, '#<struct a=1, b="x">')
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can be invoked with a struct" do
|
|
|
|
instance = Struct.new(:a, :b).new(1, "x")
|
|
|
|
build_user_factory_with_admin_trait(instance)
|
|
|
|
|
|
|
|
user = FactoryBot.build(:user, instance)
|
|
|
|
|
|
|
|
expect(user).to be_admin
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-11-25 17:41:29 -05:00
|
|
|
def build_user_factory_with_admin_trait(trait_name)
|
|
|
|
define_model("User", admin: :boolean)
|
|
|
|
|
|
|
|
FactoryBot.define do
|
|
|
|
factory :user do
|
|
|
|
admin { false }
|
|
|
|
|
|
|
|
trait trait_name do
|
|
|
|
admin { true }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-02-22 15:53:39 -05:00
|
|
|
describe "looking up traits that don't exist" do
|
2020-07-10 11:53:20 -04:00
|
|
|
context "when passing an invalid override trait" do
|
|
|
|
it "raises a KeyError" do
|
|
|
|
define_class("User")
|
2019-02-22 15:53:39 -05:00
|
|
|
|
2020-07-10 11:53:20 -04:00
|
|
|
FactoryBot.define do
|
|
|
|
factory :user
|
|
|
|
end
|
|
|
|
|
|
|
|
expect { FactoryBot.build(:user, double("not a trait")) }
|
|
|
|
.to raise_error(KeyError)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when the factory includes an invalid default trait" do
|
|
|
|
it "raises a KeyError including the factory name" do
|
|
|
|
define_class("User")
|
|
|
|
|
|
|
|
FactoryBot.define do
|
|
|
|
factory :user do
|
|
|
|
inaccessible_trait
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :some_other_factory do
|
|
|
|
trait :inaccessible_trait
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
expect { FactoryBot.build(:user) }.to raise_error(
|
|
|
|
KeyError,
|
|
|
|
'Trait not registered: "inaccessible_trait" referenced within "user" definition'
|
|
|
|
)
|
2019-02-22 15:53:39 -05:00
|
|
|
end
|
|
|
|
|
2020-07-10 11:53:20 -04:00
|
|
|
it "maintains 'Did you mean?' suggestions at the end of the error message" do
|
|
|
|
define_class("User")
|
|
|
|
|
|
|
|
FactoryBot.define do
|
|
|
|
trait :not_quit
|
|
|
|
|
|
|
|
factory :user do
|
|
|
|
not_quite
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
expect { FactoryBot.build(:user) }.to raise_error(
|
|
|
|
KeyError,
|
|
|
|
<<~MSG.strip
|
|
|
|
Trait not registered: "not_quite" referenced within "user" definition
|
|
|
|
Did you mean? "not_quit"
|
|
|
|
MSG
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when a trait includes an invalid default trait" do
|
|
|
|
it "raises a KeyError including the factory name" do
|
|
|
|
define_class("User")
|
|
|
|
|
|
|
|
FactoryBot.define do
|
|
|
|
factory :user do
|
|
|
|
trait :admin do
|
|
|
|
inaccessible_trait
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :some_other_factory do
|
|
|
|
trait :inaccessible_trait
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
expect { FactoryBot.build(:user, :admin) }.to raise_error(
|
|
|
|
KeyError,
|
|
|
|
'Trait not registered: "inaccessible_trait" referenced within "admin" definition'
|
|
|
|
)
|
|
|
|
end
|
2019-02-22 15:53:39 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-10-28 17:01:27 -04:00
|
|
|
describe "traits with callbacks" do
|
|
|
|
before do
|
2012-03-09 17:20:38 -05:00
|
|
|
define_model("User", name: :string)
|
2011-10-28 17:01:27 -04:00
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2011-10-28 17:01:27 -04:00
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
name { "John" }
|
2011-10-28 17:01:27 -04:00
|
|
|
|
|
|
|
trait :great do
|
2013-12-14 22:33:15 -05:00
|
|
|
after(:create) { |user| user.name.upcase! }
|
2011-10-28 17:01:27 -04:00
|
|
|
end
|
|
|
|
|
2011-11-23 18:40:35 -05:00
|
|
|
trait :awesome do
|
2013-12-14 22:33:15 -05:00
|
|
|
after(:create) { |user| user.name = "awesome" }
|
2011-11-23 18:40:35 -05:00
|
|
|
end
|
|
|
|
|
2012-03-09 17:20:38 -05:00
|
|
|
factory :caps_user, traits: [:great]
|
|
|
|
factory :awesome_user, traits: [:great, :awesome]
|
2011-10-28 17:01:27 -04:00
|
|
|
|
|
|
|
factory :caps_user_implicit_trait do
|
|
|
|
great
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when the factory has a trait passed via arguments" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:caps_user) }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:name) { should eq "JOHN" }
|
2011-10-28 17:01:27 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context "when the factory has an implicit trait" do
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.create(:caps_user_implicit_trait) }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:name) { should eq "JOHN" }
|
2011-10-28 17:01:27 -04:00
|
|
|
end
|
2011-11-23 18:40:35 -05:00
|
|
|
|
|
|
|
it "executes callbacks in the order assigned" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:awesome_user).name).to eq "awesome"
|
2011-11-23 18:40:35 -05:00
|
|
|
end
|
2011-10-28 17:01:27 -04:00
|
|
|
end
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
2012-02-08 10:17:57 -05:00
|
|
|
describe "traits added via strategy" do
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
before do
|
2012-03-09 17:20:38 -05:00
|
|
|
define_model("User", name: :string, admin: :boolean)
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
name { "John" }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
|
|
|
trait :admin do
|
2018-07-29 11:30:02 -04:00
|
|
|
admin { true }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
trait :great do
|
2013-12-14 22:33:15 -05:00
|
|
|
after(:create) { |user| user.name.upcase! }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in create" do
|
2017-10-20 15:20:28 -04:00
|
|
|
subject { FactoryBot.create(:user, :admin, :great, name: "Joe") }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
2015-09-11 09:16:23 -04:00
|
|
|
its(:admin) { should be true }
|
2020-06-05 15:15:18 -04:00
|
|
|
its(:name) { should eq "JOE" }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
|
|
|
it "doesn't modify the user factory" do
|
|
|
|
subject
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:user)).not_to be_admin
|
|
|
|
expect(FactoryBot.create(:user).name).to eq "John"
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in build" do
|
2017-10-20 15:20:28 -04:00
|
|
|
subject { FactoryBot.build(:user, :admin, :great, name: "Joe") }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
2015-09-11 09:16:23 -04:00
|
|
|
its(:admin) { should be true }
|
2020-06-05 15:15:18 -04:00
|
|
|
its(:name) { should eq "Joe" }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in attributes_for" do
|
2017-10-20 15:20:28 -04:00
|
|
|
subject { FactoryBot.attributes_for(:user, :admin, :great) }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
2015-09-11 09:16:23 -04:00
|
|
|
its([:admin]) { should be true }
|
2020-06-05 15:15:18 -04:00
|
|
|
its([:name]) { should eq "John" }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in build_stubbed" do
|
2017-10-20 15:20:28 -04:00
|
|
|
subject { FactoryBot.build_stubbed(:user, :admin, :great, name: "Jack") }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
|
2015-09-11 09:16:23 -04:00
|
|
|
its(:admin) { should be true }
|
2020-06-05 15:15:18 -04:00
|
|
|
its(:name) { should eq "Jack" }
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
end
|
2012-02-07 10:13:27 -05:00
|
|
|
|
|
|
|
context "adding traits in create_list" do
|
2017-10-20 15:20:28 -04:00
|
|
|
subject { FactoryBot.create_list(:user, 2, :admin, :great, name: "Joe") }
|
2012-02-07 10:13:27 -05:00
|
|
|
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:length) { should eq 2 }
|
2012-02-07 10:13:27 -05:00
|
|
|
|
|
|
|
it "creates all the records" do
|
|
|
|
subject.each do |record|
|
2015-09-11 09:16:23 -04:00
|
|
|
expect(record.admin).to be true
|
2013-01-18 13:27:57 -05:00
|
|
|
expect(record.name).to eq "JOE"
|
2012-02-07 10:13:27 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in build_list" do
|
2017-10-20 15:20:28 -04:00
|
|
|
subject { FactoryBot.build_list(:user, 2, :admin, :great, name: "Joe") }
|
2012-02-07 10:13:27 -05:00
|
|
|
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:length) { should eq 2 }
|
2012-02-07 10:13:27 -05:00
|
|
|
|
|
|
|
it "builds all the records" do
|
|
|
|
subject.each do |record|
|
2015-09-11 09:16:23 -04:00
|
|
|
expect(record.admin).to be true
|
2013-01-18 13:27:57 -05:00
|
|
|
expect(record.name).to eq "Joe"
|
2012-02-07 10:13:27 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
Traits can be added to factories when the factory creates an instance
This allows for traits to be used with normal factories without having
to name every single factory that uses one (or many) traits.
So, instead of creating male_admin and female_admin factories:
FactoryGirl.define do
factory :user do
trait(:admin) { admin true }
trait(:male) { gender "Male" }
trait(:female) { gender "Female" }
factory :male_admin, :traits => [:male, :admin]
factory :female_admin, :traits => [:admin, :female]
end
end
FactoryGirl.create(:male_admin)
FactoryGirl.create(:female_admin)
You could just create a user with those traits assigned:
FactoryGirl.create(:user, :admin, :male)
FactoryGirl.create(:user, :admin, :female)
This can be combined with attribute overrides as expected.
FactoryGirl.create(:user, :admin, :male, :name => "John Doe")
FactoryGirl.create(:user, :admin, :female, :name => "Jane Doe")
2011-11-18 09:25:49 -05:00
|
|
|
end
|
2011-11-23 18:56:07 -05:00
|
|
|
|
|
|
|
describe "traits and dynamic attributes that are applied simultaneously" do
|
|
|
|
before do
|
2012-03-09 17:20:38 -05:00
|
|
|
define_model("User", name: :string, email: :string, combined: :string)
|
2011-11-23 18:56:07 -05:00
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2011-11-23 18:56:07 -05:00
|
|
|
trait :email do
|
|
|
|
email { "#{name}@example.com" }
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
name { "John" }
|
2011-11-23 18:56:07 -05:00
|
|
|
email
|
|
|
|
combined { "#{name} <#{email}>" }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-06-05 15:15:18 -04:00
|
|
|
subject { FactoryBot.build(:user) }
|
|
|
|
its(:name) { should eq "John" }
|
|
|
|
its(:email) { should eq "John@example.com" }
|
2013-01-18 13:27:57 -05:00
|
|
|
its(:combined) { should eq "John <John@example.com>" }
|
2011-11-23 18:56:07 -05:00
|
|
|
end
|
2012-01-16 12:29:43 -05:00
|
|
|
|
|
|
|
describe "applying inline traits" do
|
|
|
|
before do
|
|
|
|
define_model("User") do
|
|
|
|
has_many :posts
|
|
|
|
end
|
|
|
|
|
2012-03-09 17:20:38 -05:00
|
|
|
define_model("Post", user_id: :integer) do
|
2012-01-16 12:29:43 -05:00
|
|
|
belongs_to :user
|
|
|
|
end
|
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-01-16 12:29:43 -05:00
|
|
|
factory :user do
|
|
|
|
trait :with_post do
|
2018-09-27 21:35:05 -04:00
|
|
|
posts { [Post.new] }
|
2012-01-16 12:29:43 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "applies traits only to the instance generated for that call" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:user, :with_post).posts).not_to be_empty
|
|
|
|
expect(FactoryBot.create(:user).posts).to be_empty
|
|
|
|
expect(FactoryBot.create(:user, :with_post).posts).not_to be_empty
|
2012-01-16 12:29:43 -05:00
|
|
|
end
|
|
|
|
end
|
2012-01-17 23:15:41 -05:00
|
|
|
|
|
|
|
describe "inline traits overriding existing attributes" do
|
|
|
|
before do
|
2012-03-09 17:20:38 -05:00
|
|
|
define_model("User", status: :string)
|
2012-01-17 23:15:41 -05:00
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-01-17 23:15:41 -05:00
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
status { "pending" }
|
2012-01-17 23:15:41 -05:00
|
|
|
|
2018-07-29 11:30:02 -04:00
|
|
|
trait(:accepted) { status { "accepted" } }
|
|
|
|
trait(:declined) { status { "declined" } }
|
2012-01-17 23:15:41 -05:00
|
|
|
|
2012-03-09 17:20:38 -05:00
|
|
|
factory :declined_user, traits: [:declined]
|
|
|
|
factory :extended_declined_user, traits: [:declined] do
|
2018-07-29 11:30:02 -04:00
|
|
|
status { "extended_declined" }
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the default status" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:user).status).to eq "pending"
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers inline trait attributes over default attributes" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:user, :accepted).status).to eq "accepted"
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers traits on a factory over default attributes" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:declined_user).status).to eq "declined"
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers inline trait attributes over traits on a factory" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:declined_user, :accepted).status).to eq "accepted"
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers attributes on factories over attributes from non-inline traits" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:extended_declined_user).status).to eq "extended_declined"
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers inline traits over attributes on factories" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:extended_declined_user, :accepted).status).to eq "accepted"
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers overridden attributes over attributes from traits, inline traits, or attributes on factories" do
|
2018-10-21 11:39:48 -04:00
|
|
|
user = FactoryBot.build(:extended_declined_user, :accepted, status: "completely overridden")
|
|
|
|
|
|
|
|
expect(user.status).to eq "completely overridden"
|
2012-01-17 23:15:41 -05:00
|
|
|
end
|
|
|
|
end
|
2012-03-09 14:05:05 -05:00
|
|
|
|
|
|
|
describe "making sure the factory is properly compiled the first time we want to instantiate it" do
|
|
|
|
before do
|
2012-03-09 17:20:38 -05:00
|
|
|
define_model("User", role: :string, gender: :string, age: :integer)
|
2012-03-09 14:05:05 -05:00
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-03-09 14:05:05 -05:00
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
trait(:female) { gender { "female" } }
|
|
|
|
trait(:admin) { role { "admin" } }
|
2012-03-09 14:05:05 -05:00
|
|
|
|
|
|
|
factory :female_user do
|
|
|
|
female
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can honor traits on the very first call" do
|
2017-10-20 15:20:28 -04:00
|
|
|
user = FactoryBot.build(:female_user, :admin, age: 30)
|
2018-10-07 21:45:51 -04:00
|
|
|
expect(user.gender).to eq "female"
|
2013-01-18 13:27:57 -05:00
|
|
|
expect(user.age).to eq 30
|
2018-10-07 21:45:51 -04:00
|
|
|
expect(user.role).to eq "admin"
|
2012-03-09 14:05:05 -05:00
|
|
|
end
|
|
|
|
end
|
2012-05-06 16:56:37 -04:00
|
|
|
|
2012-05-11 11:43:08 -04:00
|
|
|
describe "traits with to_create" do
|
2012-05-06 16:56:37 -04:00
|
|
|
before do
|
|
|
|
define_model("User", name: :string)
|
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-05-06 16:56:37 -04:00
|
|
|
factory :user do
|
|
|
|
trait :with_to_create do
|
2013-12-14 22:33:15 -05:00
|
|
|
to_create { |instance| instance.name = "to_create" }
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
factory :sub_user do
|
2013-12-14 22:33:15 -05:00
|
|
|
to_create { |instance| instance.name = "sub" }
|
2012-05-06 16:56:37 -04:00
|
|
|
|
|
|
|
factory :child_user
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :sub_user_with_trait do
|
|
|
|
with_to_create
|
|
|
|
|
|
|
|
factory :child_user_with_trait
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :sub_user_with_trait_and_override do
|
|
|
|
with_to_create
|
2013-12-14 22:33:15 -05:00
|
|
|
to_create { |instance| instance.name = "sub with trait and override" }
|
2012-05-06 16:56:37 -04:00
|
|
|
|
|
|
|
factory :child_user_with_trait_and_override
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can apply to_create from traits" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:user, :with_to_create).name).to eq "to_create"
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "can apply to_create from the definition" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:sub_user).name).to eq "sub"
|
|
|
|
expect(FactoryBot.create(:child_user).name).to eq "sub"
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives additional traits higher priority than to_create from the definition" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:sub_user, :with_to_create).name).to eq "to_create"
|
|
|
|
expect(FactoryBot.create(:child_user, :with_to_create).name).to eq "to_create"
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives base traits normal priority" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:sub_user_with_trait).name).to eq "to_create"
|
|
|
|
expect(FactoryBot.create(:child_user_with_trait).name).to eq "to_create"
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives base traits lower priority than overrides" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.create(:sub_user_with_trait_and_override).name).to eq "sub with trait and override"
|
|
|
|
expect(FactoryBot.create(:child_user_with_trait_and_override).name).to eq "sub with trait and override"
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives additional traits higher priority than base traits and factory definition" do
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-05-06 16:56:37 -04:00
|
|
|
trait :overridden do
|
2013-12-14 22:33:15 -05:00
|
|
|
to_create { |instance| instance.name = "completely overridden" }
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-21 11:39:48 -04:00
|
|
|
sub_user = FactoryBot.create(:sub_user_with_trait_and_override, :overridden)
|
|
|
|
child_user = FactoryBot.create(:child_user_with_trait_and_override, :overridden)
|
|
|
|
expect(sub_user.name).to eq "completely overridden"
|
|
|
|
expect(child_user.name).to eq "completely overridden"
|
2012-05-06 16:56:37 -04:00
|
|
|
end
|
|
|
|
end
|
2012-05-11 11:43:08 -04:00
|
|
|
|
|
|
|
describe "traits with initialize_with" do
|
|
|
|
before do
|
|
|
|
define_class("User") do
|
|
|
|
attr_reader :name
|
|
|
|
|
|
|
|
def initialize(name)
|
|
|
|
@name = name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-05-11 11:43:08 -04:00
|
|
|
factory :user do
|
|
|
|
trait :with_initialize_with do
|
|
|
|
initialize_with { new("initialize_with") }
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :sub_user do
|
|
|
|
initialize_with { new("sub") }
|
|
|
|
|
|
|
|
factory :child_user
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :sub_user_with_trait do
|
|
|
|
with_initialize_with
|
|
|
|
|
|
|
|
factory :child_user_with_trait
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :sub_user_with_trait_and_override do
|
|
|
|
with_initialize_with
|
|
|
|
initialize_with { new("sub with trait and override") }
|
|
|
|
|
|
|
|
factory :child_user_with_trait_and_override
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "can apply initialize_with from traits" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:user, :with_initialize_with).name).to eq "initialize_with"
|
2012-05-11 11:43:08 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "can apply initialize_with from the definition" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:sub_user).name).to eq "sub"
|
|
|
|
expect(FactoryBot.build(:child_user).name).to eq "sub"
|
2012-05-11 11:43:08 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives additional traits higher priority than initialize_with from the definition" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:sub_user, :with_initialize_with).name).to eq "initialize_with"
|
|
|
|
expect(FactoryBot.build(:child_user, :with_initialize_with).name).to eq "initialize_with"
|
2012-05-11 11:43:08 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives base traits normal priority" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:sub_user_with_trait).name).to eq "initialize_with"
|
|
|
|
expect(FactoryBot.build(:child_user_with_trait).name).to eq "initialize_with"
|
2012-05-11 11:43:08 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives base traits lower priority than overrides" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:sub_user_with_trait_and_override).name).to eq "sub with trait and override"
|
|
|
|
expect(FactoryBot.build(:child_user_with_trait_and_override).name).to eq "sub with trait and override"
|
2012-05-11 11:43:08 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "gives additional traits higher priority than base traits and factory definition" do
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-05-11 11:43:08 -04:00
|
|
|
trait :overridden do
|
|
|
|
initialize_with { new("completely overridden") }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-21 11:39:48 -04:00
|
|
|
sub_user = FactoryBot.build(:sub_user_with_trait_and_override, :overridden)
|
|
|
|
child_user = FactoryBot.build(:child_user_with_trait_and_override, :overridden)
|
|
|
|
expect(sub_user.name).to eq "completely overridden"
|
|
|
|
expect(child_user.name).to eq "completely overridden"
|
2012-05-11 11:43:08 -04:00
|
|
|
end
|
|
|
|
end
|
2012-06-12 23:11:55 -04:00
|
|
|
|
|
|
|
describe "nested implicit traits" do
|
|
|
|
before do
|
|
|
|
define_class("User") do
|
|
|
|
attr_accessor :gender, :role
|
|
|
|
attr_reader :name
|
|
|
|
|
|
|
|
def initialize(name)
|
|
|
|
@name = name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
shared_examples_for "assigning data from traits" do
|
|
|
|
it "assigns the correct values" do
|
2017-10-20 15:20:28 -04:00
|
|
|
user = FactoryBot.create(:user, :female_admin)
|
2013-01-18 13:27:57 -05:00
|
|
|
expect(user.gender).to eq "FEMALE"
|
|
|
|
expect(user.role).to eq "ADMIN"
|
|
|
|
expect(user.name).to eq "Jane Doe"
|
2012-06-12 23:11:55 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "defined outside the factory" do
|
|
|
|
before do
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-06-12 23:11:55 -04:00
|
|
|
trait :female do
|
2018-07-29 11:30:02 -04:00
|
|
|
gender { "female" }
|
2013-12-14 22:33:15 -05:00
|
|
|
to_create { |instance| instance.gender = instance.gender.upcase }
|
2012-06-12 23:11:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
trait :jane_doe do
|
|
|
|
initialize_with { new("Jane Doe") }
|
|
|
|
end
|
|
|
|
|
|
|
|
trait :admin do
|
2018-07-29 11:30:02 -04:00
|
|
|
role { "admin" }
|
2013-12-14 22:33:15 -05:00
|
|
|
after(:build) { |instance| instance.role = instance.role.upcase }
|
2012-06-12 23:11:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
trait :female_admin do
|
|
|
|
female
|
|
|
|
admin
|
|
|
|
jane_doe
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :user
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like "assigning data from traits"
|
|
|
|
end
|
|
|
|
|
|
|
|
context "defined inside the factory" do
|
|
|
|
before do
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-06-12 23:11:55 -04:00
|
|
|
factory :user do
|
|
|
|
trait :female do
|
2018-07-29 11:30:02 -04:00
|
|
|
gender { "female" }
|
2013-12-14 22:33:15 -05:00
|
|
|
to_create { |instance| instance.gender = instance.gender.upcase }
|
2012-06-12 23:11:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
trait :jane_doe do
|
|
|
|
initialize_with { new("Jane Doe") }
|
|
|
|
end
|
|
|
|
|
|
|
|
trait :admin do
|
2018-07-29 11:30:02 -04:00
|
|
|
role { "admin" }
|
2013-12-14 22:33:15 -05:00
|
|
|
after(:build) { |instance| instance.role = instance.role.upcase }
|
2012-06-12 23:11:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
trait :female_admin do
|
|
|
|
female
|
|
|
|
admin
|
|
|
|
jane_doe
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like "assigning data from traits"
|
|
|
|
end
|
|
|
|
end
|
2012-06-19 22:25:46 -04:00
|
|
|
|
|
|
|
describe "implicit traits containing callbacks" do
|
|
|
|
before do
|
|
|
|
define_model("User", value: :integer)
|
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-06-19 22:25:46 -04:00
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
value { 0 }
|
2012-06-19 22:25:46 -04:00
|
|
|
|
|
|
|
trait :trait_with_callback do
|
2013-12-14 22:33:15 -05:00
|
|
|
after(:build) { |user| user.value += 1 }
|
2012-06-19 22:25:46 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
factory :user_with_trait_with_callback do
|
|
|
|
trait_with_callback
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "only runs the callback once" do
|
2017-10-20 15:20:28 -04:00
|
|
|
expect(FactoryBot.build(:user_with_trait_with_callback).value).to eq 1
|
2012-06-19 22:25:46 -04:00
|
|
|
end
|
|
|
|
end
|
2012-06-29 11:06:08 -04:00
|
|
|
|
|
|
|
describe "traits used in associations" do
|
|
|
|
before do
|
|
|
|
define_model("User", admin: :boolean, name: :string)
|
2012-08-02 10:19:17 -04:00
|
|
|
|
|
|
|
define_model("Comment", user_id: :integer) do
|
|
|
|
belongs_to :user
|
|
|
|
end
|
|
|
|
|
|
|
|
define_model("Order", creator_id: :integer) do
|
2018-10-07 21:45:51 -04:00
|
|
|
belongs_to :creator, class_name: "User"
|
2012-08-02 10:19:17 -04:00
|
|
|
end
|
|
|
|
|
2012-06-29 11:06:08 -04:00
|
|
|
define_model("Post", author_id: :integer) do
|
2018-10-07 21:45:51 -04:00
|
|
|
belongs_to :author, class_name: "User"
|
2012-06-29 11:06:08 -04:00
|
|
|
end
|
|
|
|
|
2017-10-20 15:20:28 -04:00
|
|
|
FactoryBot.define do
|
2012-06-29 11:06:08 -04:00
|
|
|
factory :user do
|
2018-07-29 11:30:02 -04:00
|
|
|
admin { false }
|
2012-06-29 11:06:08 -04:00
|
|
|
|
|
|
|
trait :admin do
|
2018-07-29 11:30:02 -04:00
|
|
|
admin { true }
|
2012-06-29 11:06:08 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :post do
|
2018-10-07 21:45:51 -04:00
|
|
|
association :author, factory: [:user, :admin], name: "John Doe"
|
2012-06-29 11:06:08 -04:00
|
|
|
end
|
2012-08-02 10:19:17 -04:00
|
|
|
|
|
|
|
factory :comment do
|
2018-10-07 21:45:51 -04:00
|
|
|
association :user, :admin, name: "Joe Slick"
|
2012-08-02 10:19:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
factory :order do
|
2018-10-07 21:45:51 -04:00
|
|
|
association :creator, :admin, factory: :user, name: "Joe Creator"
|
2012-08-02 10:19:17 -04:00
|
|
|
end
|
2012-06-29 11:06:08 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "allows assigning traits for the factory of an association" do
|
2017-10-20 15:20:28 -04:00
|
|
|
author = FactoryBot.create(:post).author
|
2013-01-18 13:27:57 -05:00
|
|
|
expect(author).to be_admin
|
2018-10-07 21:45:51 -04:00
|
|
|
expect(author.name).to eq "John Doe"
|
2012-06-29 11:06:08 -04:00
|
|
|
end
|
2012-08-02 10:19:17 -04:00
|
|
|
|
|
|
|
it "allows inline traits with the default association" do
|
2017-10-20 15:20:28 -04:00
|
|
|
user = FactoryBot.create(:comment).user
|
2013-01-18 13:27:57 -05:00
|
|
|
expect(user).to be_admin
|
2018-10-07 21:45:51 -04:00
|
|
|
expect(user.name).to eq "Joe Slick"
|
2012-08-02 10:19:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "allows inline traits with a specific factory for an association" do
|
2017-10-20 15:20:28 -04:00
|
|
|
creator = FactoryBot.create(:order).creator
|
2013-01-18 13:27:57 -05:00
|
|
|
expect(creator).to be_admin
|
2018-10-07 21:45:51 -04:00
|
|
|
expect(creator.name).to eq "Joe Creator"
|
2012-08-02 10:19:17 -04:00
|
|
|
end
|
2012-06-29 11:06:08 -04:00
|
|
|
end
|
2019-09-10 19:24:20 -04:00
|
|
|
|
|
|
|
describe "when a self-referential trait is defined" do
|
|
|
|
it "raises a TraitDefinitionError" do
|
|
|
|
define_model("User", name: :string)
|
|
|
|
FactoryBot.define do
|
|
|
|
factory :user do
|
|
|
|
trait :admin do
|
|
|
|
admin
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
expect { FactoryBot.build(:user, :admin) }.to raise_error(
|
|
|
|
FactoryBot::TraitDefinitionError,
|
2020-06-05 15:15:18 -04:00
|
|
|
"Self-referencing trait 'admin'"
|
2019-09-10 19:24:20 -04:00
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "raises a TraitDefinitionError" do
|
|
|
|
define_model("User", name: :string)
|
|
|
|
FactoryBot.define do
|
|
|
|
factory :user do
|
|
|
|
trait :admin do
|
|
|
|
admin
|
|
|
|
name { "name" }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
expect { FactoryBot.build(:user, :admin) }.to raise_error(
|
|
|
|
FactoryBot::TraitDefinitionError,
|
2020-06-05 15:15:18 -04:00
|
|
|
"Self-referencing trait 'admin'"
|
2019-09-10 19:24:20 -04:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|