2011-08-09 18:00:24 -04:00
|
|
|
require "spec_helper"
|
|
|
|
|
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",
|
2011-08-12 15:05:38 -04:00
|
|
|
:name => :string,
|
|
|
|
:admin => :boolean,
|
|
|
|
:gender => :string,
|
|
|
|
:email => :string,
|
|
|
|
:date_of_birth => :date,
|
|
|
|
:great => :string)
|
2011-08-12 10:35:41 -04:00
|
|
|
|
|
|
|
FactoryGirl.define do
|
|
|
|
factory :user_without_admin_scoping, :class => User do
|
2011-08-12 16:16:17 -04:00
|
|
|
admin_trait
|
2011-08-12 10:35:41 -04:00
|
|
|
end
|
2011-08-09 18:00:24 -04:00
|
|
|
|
|
|
|
factory :user do
|
|
|
|
name "John"
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :great do
|
2011-08-12 15:05:38 -04:00
|
|
|
great "GREAT!!!"
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :admin do
|
2011-08-09 18:00:24 -04:00
|
|
|
admin true
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :admin_trait do
|
2011-08-12 10:35:41 -04:00
|
|
|
admin true
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :male do
|
2011-08-09 20:29:02 -04:00
|
|
|
name "Joe"
|
2011-08-09 18:00:24 -04:00
|
|
|
gender "Male"
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
trait :female do
|
2011-08-09 18:00:24 -04:00
|
|
|
name "Jane"
|
|
|
|
gender "Female"
|
|
|
|
end
|
|
|
|
|
2011-08-12 15:05:38 -04:00
|
|
|
factory :great_user do
|
|
|
|
great
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04: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
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
factory :female, :traits => [:female] do
|
|
|
|
trait :admin do
|
2011-08-10 14:11:53 -04:00
|
|
|
admin true
|
|
|
|
name "Judy"
|
|
|
|
end
|
2011-08-12 10:35:41 -04:00
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
factory :female_admin_judy, :traits => [: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
|
|
|
factory :female_admin, :traits => [:female, :admin]
|
|
|
|
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
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
factory :user_with_email, :class => User, :traits => [:email] do
|
2011-08-10 14:11:53 -04:00
|
|
|
name "Bill"
|
|
|
|
end
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "the parent class" do
|
|
|
|
subject { FactoryGirl.create(:user) }
|
|
|
|
its(:name) { should == "John" }
|
|
|
|
its(:gender) { should be_nil }
|
2011-08-12 10:35:41 -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
|
2011-08-09 18:00:24 -04:00
|
|
|
subject { FactoryGirl.create(:admin) }
|
|
|
|
its(:name) { should == "John" }
|
|
|
|
its(:gender) { should be_nil }
|
2011-08-12 10:35:41 -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
|
2011-08-09 18:00:24 -04:00
|
|
|
subject { FactoryGirl.create(:female) }
|
|
|
|
its(:name) { should == "Jane" }
|
|
|
|
its(:gender) { should == "Female" }
|
2011-08-12 10:35:41 -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
|
2011-08-09 18:00:24 -04:00
|
|
|
subject { FactoryGirl.create(:female_admin) }
|
|
|
|
its(:name) { should == "Jane" }
|
|
|
|
its(:gender) { should == "Female" }
|
2011-08-12 10:35:41 -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
|
2011-08-09 18:00:24 -04:00
|
|
|
subject { FactoryGirl.create(:female_admin, :name => "Jill", :gender => nil) }
|
|
|
|
its(:name) { should == "Jill" }
|
|
|
|
its(:gender) { should be_nil }
|
2011-08-12 10:35:41 -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
|
|
|
|
subject { FactoryGirl.create(:male_after_female_admin) }
|
2011-08-09 20:29:02 -04:00
|
|
|
its(:name) { should == "Joe" }
|
2011-08-09 18:00:24 -04:00
|
|
|
its(:gender) { should == "Male" }
|
2011-08-12 10:35:41 -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
|
|
|
|
subject { FactoryGirl.create(:female_after_male_admin) }
|
|
|
|
its(:name) { should == "Jane" }
|
|
|
|
its(:gender) { should == "Female" }
|
2011-08-12 10:35:41 -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
|
2011-08-12 10:35:41 -04:00
|
|
|
subject { FactoryGirl.create(:female_admin_judy) }
|
|
|
|
its(:name) { should == "Judy" }
|
2011-08-10 14:11:53 -04:00
|
|
|
its(:gender) { should == "Female" }
|
2011-08-12 10:35:41 -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
|
2011-08-12 10:35:41 -04:00
|
|
|
subject { FactoryGirl.create(:user_with_email) }
|
|
|
|
its(:name) { should == "Bill" }
|
2011-08-10 14:11:53 -04:00
|
|
|
its(:email) { should == "Bill@example.com"}
|
|
|
|
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
|
2011-08-12 10:35:41 -04:00
|
|
|
subject { FactoryGirl.create(:male_user) }
|
2011-08-10 23:33:50 -04:00
|
|
|
its(:gender) { should == "Male" }
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "factory created with alternate syntax where trait name and attribute are the same" do
|
2011-08-12 15:05:38 -04:00
|
|
|
subject { FactoryGirl.create(:great_user) }
|
|
|
|
its(:great) { should == "GREAT!!!" }
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "factory created with alternate syntax where trait name and attribute are the same and attribute is overridden" do
|
2011-08-12 15:05:38 -04:00
|
|
|
subject { FactoryGirl.create(:great_user, :great => "SORT OF!!!") }
|
|
|
|
its(:great) { should == "SORT OF!!!" }
|
|
|
|
end
|
|
|
|
|
2011-08-12 16:16:17 -04:00
|
|
|
context "child factory created where trait attributes are inherited" do
|
2011-08-12 15:05:38 -04:00
|
|
|
subject { FactoryGirl.create(:child_male_user) }
|
|
|
|
its(:gender) { should == "Male" }
|
|
|
|
its(:date_of_birth) { should == Date.parse("1/1/2000") }
|
|
|
|
end
|
|
|
|
|
2011-08-12 10:35:41 -04:00
|
|
|
context "factory outside of scope" do
|
|
|
|
subject { FactoryGirl.create(:user_without_admin_scoping) }
|
2011-10-15 01:54:01 -04:00
|
|
|
it { expect { subject }.to raise_error(ArgumentError, "Trait not registered: admin_trait") }
|
2011-08-12 10:35:41 -04:00
|
|
|
end
|
2011-08-09 18:00:24 -04:00
|
|
|
end
|
2011-10-28 17:01:27 -04:00
|
|
|
|
|
|
|
describe "traits with callbacks" do
|
|
|
|
before do
|
|
|
|
define_model("User", :name => :string)
|
|
|
|
|
|
|
|
FactoryGirl.define do
|
|
|
|
factory :user do
|
|
|
|
name "John"
|
|
|
|
|
|
|
|
trait :great do
|
|
|
|
after_create {|user| user.name.upcase! }
|
|
|
|
end
|
|
|
|
|
2011-11-23 18:40:35 -05:00
|
|
|
trait :awesome do
|
|
|
|
after_create {|user| user.name = "awesome" }
|
|
|
|
end
|
|
|
|
|
2011-10-28 17:01:27 -04:00
|
|
|
factory :caps_user, :traits => [:great]
|
2011-11-23 18:40:35 -05:00
|
|
|
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
|
|
|
|
subject { FactoryGirl.create(:caps_user) }
|
|
|
|
its(:name) { should == "JOHN" }
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when the factory has an implicit trait" do
|
|
|
|
subject { FactoryGirl.create(:caps_user_implicit_trait) }
|
2011-10-28 23:01:50 -04:00
|
|
|
its(:name) { should == "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
|
|
|
|
FactoryGirl.create(:awesome_user).name.should == "awesome"
|
|
|
|
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
|
|
|
|
|
|
|
describe "traits added via proxy" do
|
|
|
|
before do
|
|
|
|
define_model("User", :name => :string, :admin => :boolean)
|
|
|
|
|
|
|
|
FactoryGirl.define do
|
|
|
|
factory :user do
|
|
|
|
name "John"
|
|
|
|
|
|
|
|
trait :admin do
|
|
|
|
admin true
|
|
|
|
end
|
|
|
|
|
|
|
|
trait :great do
|
|
|
|
after_create {|user| user.name.upcase! }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in create" do
|
|
|
|
subject { FactoryGirl.create(:user, :admin, :great, :name => "Joe") }
|
|
|
|
|
|
|
|
its(:admin) { should be_true }
|
|
|
|
its(:name) { should == "JOE" }
|
|
|
|
|
|
|
|
it "doesn't modify the user factory" do
|
|
|
|
subject
|
|
|
|
FactoryGirl.create(:user).should_not be_admin
|
|
|
|
FactoryGirl.create(:user).name.should == "John"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in build" do
|
|
|
|
subject { FactoryGirl.build(:user, :admin, :great, :name => "Joe") }
|
|
|
|
|
|
|
|
its(:admin) { should be_true }
|
|
|
|
its(:name) { should == "Joe" }
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in attributes_for" do
|
|
|
|
subject { FactoryGirl.attributes_for(:user, :admin, :great) }
|
|
|
|
|
|
|
|
its([:admin]) { should be_true }
|
|
|
|
its([:name]) { should == "John" }
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in build_stubbed" do
|
|
|
|
subject { FactoryGirl.build_stubbed(:user, :admin, :great, :name => "Jack") }
|
|
|
|
|
|
|
|
its(:admin) { should be_true }
|
|
|
|
its(:name) { should == "Jack" }
|
|
|
|
end
|
2012-02-07 10:13:27 -05:00
|
|
|
|
|
|
|
context "adding traits in create_list" do
|
|
|
|
subject { FactoryGirl.create_list(:user, 2, :admin, :great, :name => "Joe") }
|
|
|
|
|
|
|
|
its(:length) { should == 2 }
|
|
|
|
|
|
|
|
it "creates all the records" do
|
|
|
|
subject.each do |record|
|
|
|
|
record.admin.should be_true
|
|
|
|
record.name.should == "JOE"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "adding traits in build_list" do
|
|
|
|
subject { FactoryGirl.build_list(:user, 2, :admin, :great, :name => "Joe") }
|
|
|
|
|
|
|
|
its(:length) { should == 2 }
|
|
|
|
|
|
|
|
it "builds all the records" do
|
|
|
|
subject.each do |record|
|
|
|
|
record.admin.should be_true
|
|
|
|
record.name.should == "Joe"
|
|
|
|
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
|
|
|
|
define_model("User", :name => :string, :email => :string, :combined => :string)
|
|
|
|
|
|
|
|
FactoryGirl.define do
|
|
|
|
trait :email do
|
|
|
|
email { "#{name}@example.com" }
|
|
|
|
end
|
|
|
|
|
|
|
|
factory :user do
|
|
|
|
name "John"
|
|
|
|
email
|
|
|
|
combined { "#{name} <#{email}>" }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
subject { FactoryGirl.build(:user) }
|
|
|
|
its(:name) { should == "John" }
|
|
|
|
its(:email) { should == "John@example.com" }
|
|
|
|
its(:combined) { should == "John <John@example.com>" }
|
|
|
|
end
|
2012-01-16 12:29:43 -05:00
|
|
|
|
|
|
|
describe "applying inline traits" do
|
|
|
|
before do
|
|
|
|
define_model("User") do
|
|
|
|
has_many :posts
|
|
|
|
end
|
|
|
|
|
|
|
|
define_model("Post", :user_id => :integer) do
|
|
|
|
belongs_to :user
|
|
|
|
end
|
|
|
|
|
|
|
|
FactoryGirl.define do
|
|
|
|
factory :user do
|
|
|
|
trait :with_post do
|
|
|
|
posts { [ Post.new ] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "applies traits only to the instance generated for that call" do
|
|
|
|
FactoryGirl.create(:user, :with_post).posts.should_not be_empty
|
|
|
|
FactoryGirl.create(:user).posts.should be_empty
|
|
|
|
FactoryGirl.create(:user, :with_post).posts.should_not be_empty
|
|
|
|
end
|
|
|
|
end
|
2012-01-17 23:15:41 -05:00
|
|
|
|
|
|
|
describe "inline traits overriding existing attributes" do
|
|
|
|
before do
|
|
|
|
define_model("User", :status => :string)
|
|
|
|
|
|
|
|
FactoryGirl.define do
|
|
|
|
factory :user do
|
|
|
|
status "pending"
|
|
|
|
|
|
|
|
trait(:accepted) { status "accepted" }
|
|
|
|
trait(:declined) { status "declined" }
|
|
|
|
|
|
|
|
factory :declined_user, :traits => [:declined]
|
|
|
|
factory :extended_declined_user, :traits => [:declined] do
|
|
|
|
status "extended_declined"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns the default status" do
|
|
|
|
FactoryGirl.build(:user).status.should == "pending"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers inline trait attributes over default attributes" do
|
|
|
|
FactoryGirl.build(:user, :accepted).status.should == "accepted"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers traits on a factory over default attributes" do
|
|
|
|
FactoryGirl.build(:declined_user).status.should == "declined"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers inline trait attributes over traits on a factory" do
|
|
|
|
FactoryGirl.build(:declined_user, :accepted).status.should == "accepted"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers attributes on factories over attributes from non-inline traits" do
|
|
|
|
FactoryGirl.build(:extended_declined_user).status.should == "extended_declined"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers inline traits over attributes on factories" do
|
|
|
|
FactoryGirl.build(:extended_declined_user, :accepted).status.should == "accepted"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "prefers overridden attributes over attributes from traits, inline traits, or attributes on factories" do
|
|
|
|
FactoryGirl.build(:extended_declined_user, :accepted, :status => "completely overridden").status.should == "completely overridden"
|
|
|
|
end
|
|
|
|
end
|