1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00
thoughtbot--factory_bot/spec/acceptance/associations_spec.rb
Daniel Colson 9879060289
Improve documentation for collection associations (#1420)
* Improve documentation for collection associations

This commit makes `Evaluator#association` and `Evaluator#instance`
officially part of the public API of factory\_bot. Folks were already
using these methods, and all of the examples here were inspired by
examples in the various issues mentioned below.

This commit also adds and updates some tests to match the examples in
the documentation, to ensure that these examples will continue to work
as expected.

Closes #1268 by adding documentation for both `Evaluator#association`
and `Evaluator#instance`. The documentation on interconnected
associations is also relevant to #1063, #1255, and #1309.

Closes #1304 by providing multiple alternative approaches to creating
collection associations, and adding a note about reloading the record in
the callback example. This had also come up back in #549.

Closes #458 by offering `Evaluator#association` as a more flexible way
to build collection associations. This has come up many times over the
years in many different forms, including #426, #487, #640, #1022, #1150,
and #1360.
2020-07-09 12:26:23 -04:00

145 lines
4 KiB
Ruby

describe "associations" do
context "when accidentally using an implicit delcaration for the factory" do
it "raises an error" do
define_class("Post")
FactoryBot.define do
factory :post do
author factory: user
end
end
expect { FactoryBot.build(:post) }.to raise_error(
ArgumentError,
"Association 'author' received an invalid factory argument.\n" \
"Did you mean? 'factory: :user'\n"
)
end
end
context "when accidentally using an implicit delcaration as an override" do
it "raises an error" do
define_class("Post")
FactoryBot.define do
factory :post do
author factory: :user, invalid_attribute: implicit_trait
end
end
expect { FactoryBot.build(:post) }.to raise_error(
ArgumentError,
"Association 'author' received an invalid attribute override.\n" \
"Did you mean? 'invalid_attribute: :implicit_trait'\n"
)
end
end
context "when building interrelated associations" do
it "assigns the instance passed as an association attribute" do
define_class("Supplier") do
attr_accessor :account
end
define_class("Account") do
attr_accessor :supplier
end
FactoryBot.define do
factory :supplier
factory :account do
supplier { association(:supplier, account: instance) }
end
end
account = FactoryBot.build(:account)
expect(account.supplier.account).to eq(account)
end
it "connects records with interdependent relationships" do
define_model("Student", school_id: :integer) do
belongs_to :school
has_one :profile
end
define_model("Profile", school_id: :integer, student_id: :integer) do
belongs_to :school
belongs_to :student
end
define_model("School") do
has_many :students
has_many :profiles
end
FactoryBot.define do
factory :student do
school
profile { association :profile, student: instance, school: school }
end
factory :profile do
school
student { association :student, profile: instance, school: school }
end
factory :school
end
student = FactoryBot.create(:student)
expect(student.profile.school).to eq(student.school)
expect(student.profile.student).to eq(student)
expect(student.school.students.map(&:id)).to eq([student.id])
expect(student.school.profiles.map(&:id)).to eq([student.profile.id])
profile = FactoryBot.create(:profile)
expect(profile.student.school).to eq(profile.school)
expect(profile.student.profile).to eq(profile)
expect(profile.school.profiles.map(&:id)).to eq([profile.id])
expect(profile.school.students.map(&:id)).to eq([profile.student.id])
end
end
context "when building collection associations" do
it "builds the association according to the given strategy" do
define_model("Photo", listing_id: :integer) do
belongs_to :listing
attr_accessor :name
end
define_model("Listing") do
has_many :photos
end
FactoryBot.define do
factory :photo
factory :listing do
photos { [association(:photo)] }
end
end
created_listing = FactoryBot.create(:listing)
expect(created_listing.photos.first).to be_a Photo
expect(created_listing.photos.first).to be_persisted
built_listing = FactoryBot.build(:listing)
expect(built_listing.photos.first).to be_a Photo
expect(built_listing.photos.first).not_to be_persisted
stubbed_listing = FactoryBot.build_stubbed(:listing)
expect(stubbed_listing.photos.first).to be_a Photo
expect(stubbed_listing.photos.first).to be_persisted
expect { stubbed_listing.photos.first.save! }.to raise_error(
"stubbed models are not allowed to access the database - Photo#save!()"
)
end
end
end