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/lint_spec.rb
Daniel Colson 1d6170af2b Add option for verbose linting
This has come up a few times, and I can see why it might be helpful to
have access to full backtraces when debugging a factory error uncovered
by `FactoryBot.lint`. But since most of the time I don't want the extra
noise from the backtrace, I added this as a verbose option.

The default message is still:

```
The following factories are invalid:
* user - undefined method `save!' for #<User:0x00007ff0cbc89100>
* admin - undefined method `save!' for #<User:0x00007ff0cbc73e40>
```

And with the verbose option (usually with more lines of backtrace):

```
The following factories are invalid:
* user - undefined method `save!' for #<User:0x00007ff0cbc89100>
  /Users/.../thoughtbot/factory_bot/lib/factory_bot/evaluation.rb:18:in `create'
  /Users/.../factory_bot/lib/factory_bot/strategy/create.rb:12:in `block in result'

* admin - undefined method `save!' for #<User:0x00007ff0cbc73e40>
  /Users/.../thoughtbot/factory_bot/lib/factory_bot/evaluation.rb:18:in `create'
  /Users/.../factory_bot/lib/factory_bot/strategy/create.rb:12:in `block in result'
```

I moved the linting option defaults out of the FactoryBot.lint method
and into keyword argument defaults in Linter#initialize. This seems a
bit cleaner, and now we will get an error if we pass an option we don't
understand (before 6e511597 we had a test that passed in a bogus
option)

Closes #710
Closes #1124

I am opening a new PR since the original PR is years old and it seemed
unkind to request changes after so long. Instead I will list the authors
as co-authors.

Co-authored-by: Jack Kinsella <jack.kinsella@gmail.com>
Co-authored-by: Jasper Woudenberg <mail@jasperwoudenberg.com>
2018-11-27 12:04:38 -05:00

200 lines
4.5 KiB
Ruby

describe "FactoryBot.lint" do
it "raises when a factory is invalid" do
define_model "User", name: :string do
validates :name, presence: true
end
define_model "AlwaysValid"
FactoryBot.define do
factory :user do
factory :admin_user
end
factory :always_valid
end
error_message = <<~ERROR_MESSAGE.strip
The following factories are invalid:
* user - Validation failed: Name can't be blank (ActiveRecord::RecordInvalid)
* admin_user - Validation failed: Name can't be blank (ActiveRecord::RecordInvalid)
ERROR_MESSAGE
expect do
FactoryBot.lint
end.to raise_error FactoryBot::InvalidFactoryError, error_message
end
it "does not raise when all factories are valid" do
define_model "User", name: :string do
validates :name, presence: true
end
FactoryBot.define do
factory :user do
name { "assigned" }
end
end
expect { FactoryBot.lint }.not_to raise_error
end
it "allows for selective linting" do
define_model "InvalidThing", name: :string do
validates :name, presence: true
end
define_model "ValidThing", name: :string
FactoryBot.define do
factory :valid_thing
factory :invalid_thing
end
expect do
only_valid_factories = FactoryBot.factories.reject do |factory|
factory.name =~ /invalid/
end
FactoryBot.lint only_valid_factories
end.not_to raise_error
end
describe "trait validation" do
context "enabled" do
it "raises if a trait produces an invalid object" do
define_model "User", name: :string do
validates :name, presence: true
end
FactoryBot.define do
factory :user do
name { "Yep" }
trait :unnamed do
name { nil }
end
end
end
error_message = <<~ERROR_MESSAGE.strip
The following factories are invalid:
* user+unnamed - Validation failed: Name can't be blank (ActiveRecord::RecordInvalid)
ERROR_MESSAGE
expect do
FactoryBot.lint traits: true
end.to raise_error FactoryBot::InvalidFactoryError, error_message
end
it "does not raise if a trait produces a valid object" do
define_model "User", name: :string do
validates :name, presence: true
end
FactoryBot.define do
factory :user do
name { "Yep" }
trait :renamed do
name { "Yessir" }
end
end
end
expect do
FactoryBot.lint traits: true
end.not_to raise_error
end
end
context "disabled" do
it "does not raises if a trait produces an invalid object" do
define_model "User", name: :string do
validates :name, presence: true
end
FactoryBot.define do
factory :user do
name { "Yep" }
trait :unnamed do
name { nil }
end
end
end
expect do
FactoryBot.lint traits: false
FactoryBot.lint
end.not_to raise_error
end
end
end
describe "factory strategy for linting" do
it "uses the requested strategy" do
define_class "User" do
attr_accessor :name
def save!
raise "expected :build strategy, #save! shouldn't be invoked"
end
end
FactoryBot.define do
factory :user do
name { "Barbara" }
end
end
expect do
FactoryBot.lint strategy: :build
end.not_to raise_error
end
it "uses the requested strategy during trait validation" do
define_class "User" do
attr_accessor :name
def save!
raise "expected :build strategy, #save! shouldn't be invoked"
end
end
FactoryBot.define do
factory :user do
name { "Barbara" }
trait :male do
name { "Bob" }
end
end
end
expect do
FactoryBot.lint traits: true, strategy: :build
end.not_to raise_error
end
end
describe "verbose linting" do
it "prints the backtrace for each factory error" do
define_class("InvalidThing") do
def save!
raise "invalid"
end
end
FactoryBot.define do
factory :invalid_thing
end
expect do
FactoryBot.lint(verbose: true)
end.to raise_error(
FactoryBot::InvalidFactoryError,
%r{#{__FILE__}:\d*:in `save!'},
)
end
end
end