1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00

Fix self referencing trait error (#1294)

If a new trait is defined with attributes,  check if attributes matches the name of
the trait. Raise an error if so, to avoid a recursive call to the
trait.

Co-authored-by: Daniel Colsen <daniel.j.colson@thoughtbot.com>
Co-authored-by: Paras Sanghavi <sanghaviparas@gmail.com>
This commit is contained in:
Sweta 2019-09-10 16:24:20 -07:00 committed by GitHub
parent 831dcef717
commit 5ccc564923
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 2 deletions

View file

@ -25,6 +25,9 @@ module FactoryBot
[Attribute::Association.new(name, name, {})] [Attribute::Association.new(name, name, {})]
elsif FactoryBot::Internal.sequences.registered?(name) elsif FactoryBot::Internal.sequences.registered?(name)
[Attribute::Sequence.new(name, name, @ignored)] [Attribute::Sequence.new(name, name, @ignored)]
elsif @factory.name.to_s == name.to_s
message = "Self-referencing trait '#{@name}'"
raise TraitDefinitionError, message
else else
@factory.inherit_traits([name]) @factory.inherit_traits([name])
[] []

View file

@ -2,6 +2,9 @@ module FactoryBot
# Raised when a factory is defined that attempts to instantiate itself. # Raised when a factory is defined that attempts to instantiate itself.
class AssociationDefinitionError < RuntimeError; end class AssociationDefinitionError < RuntimeError; end
# Raised when a trait is defined that references itself.
class TraitDefinitionError < RuntimeError; end
# Raised when a callback is defined that has an invalid name # Raised when a callback is defined that has an invalid name
class InvalidCallbackNameError < RuntimeError; end class InvalidCallbackNameError < RuntimeError; end

View file

@ -7,9 +7,11 @@ module FactoryBot
@name = name.to_s @name = name.to_s
@block = block @block = block
@definition = Definition.new(@name) @definition = Definition.new(@name)
proxy = FactoryBot::DefinitionProxy.new(@definition) proxy = FactoryBot::DefinitionProxy.new(@definition)
proxy.instance_eval(&@block) if block_given?
if block_given?
proxy.instance_eval(&@block)
end
end end
delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor, delegate :add_callback, :declare_attribute, :to_create, :define_trait, :constructor,

View file

@ -798,3 +798,38 @@ describe "traits used in associations" do
expect(creator.name).to eq "Joe Creator" expect(creator.name).to eq "Joe Creator"
end end
end end
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,
"Self-referencing trait 'admin'",
)
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,
"Self-referencing trait 'admin'",
)
end
end