Skip to content

Commit

Permalink
Support file_fixture in Factory definitions
Browse files Browse the repository at this point in the history
Related to [factory_bot#1282][]

[rails/rails#45606][] has been merged and is likely to be released as
part of Rails 7.1.

With that addition, the path toward resolving [factory_bot#1282][]
becomes more clear. If factories can pass along [Pathname][] instances
to attachment attributes, Active Support will handle the rest.

Instances of `ActiveSupport::TestCase` provide a [file_fixture][] helper
to construct a `Pathname` instance based on the path defined by
`ActiveSupport::TestCase.file_fixture_path` (relative to the Rails root
directory).

[factory_bot#1282]: thoughtbot/factory_bot#1282 (comment)
[rails/rails#45606]: rails/rails#45606
[Pathname]: https://docs.ruby-lang.org/en/master/Pathname.html
[file_fixture]: https://api.rubyonrails.org/classes/ActiveSupport/Testing/FileFixtures.html#method-i-file_fixture
  • Loading branch information
seanpdoyle committed Nov 1, 2024
1 parent e62adb9 commit 33c1348
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 1 deletion.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ using an empty array:
config.factory_bot.definition_file_paths = []
```

### File Fixture Support

Factories have access to [ActiveSupport::Testing::FileFixtures#file_fixture][]
helper to read files from tests.

To disable file fixture support, set `file_fixture_support = false`:

```rb
config.factory_bot.file_fixture_support = false
```

[ActiveSupport::Testing::FileFixtures#file_fixture]: https://api.rubyonrails.org/classes/ActiveSupport/Testing/FileFixtures.html#method-i-file_fixture

### Generators

Including factory\_bot\_rails in the development group of your Gemfile
Expand Down
5 changes: 4 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "bundler/setup"
require "cucumber/rake/task"
require "rspec/core/rake_task"
require "minitest/test_task"
require "standard/rake"

Bundler::GemHelper.install_tasks name: "factory_bot_rails"
Expand All @@ -12,5 +13,7 @@ end

RSpec::Core::RakeTask.new(:spec)

Minitest::TestTask.create

desc "Run the test suite and standard"
task default: %w[spec cucumber standard]
task default: %w[test spec cucumber standard]
9 changes: 9 additions & 0 deletions lib/factory_bot_rails/file_fixture_support.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module FactoryBotRails
module FileFixtureSupport
def self.included(klass)
klass.class_attribute :file_fixture_support, instance_accessor: false

klass.delegate :file_fixture, to: "self.class.file_fixture_support"
end
end
end
18 changes: 18 additions & 0 deletions lib/factory_bot_rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
require "factory_bot_rails/generator"
require "factory_bot_rails/reloader"
require "factory_bot_rails/factory_validator"
require "factory_bot_rails/file_fixture_support"
require "rails"

module FactoryBotRails
class Railtie < Rails::Railtie
config.factory_bot = ActiveSupport::OrderedOptions.new
config.factory_bot.definition_file_paths = FactoryBot.definition_file_paths
config.factory_bot.validator = FactoryBotRails::FactoryValidator.new
config.factory_bot.file_fixture_support = true

initializer "factory_bot.set_fixture_replacement" do
Generator.new(config).run
Expand All @@ -20,6 +22,22 @@ class Railtie < Rails::Railtie
FactoryBot.definition_file_paths = definition_file_paths
end

config.after_initialize do
if config.factory_bot.file_fixture_support
FactoryBot::SyntaxRunner.include FactoryBotRails::FileFixtureSupport

ActiveSupport.on_load :active_support_test_case do
setup { FactoryBot::SyntaxRunner.file_fixture_support = self }
end

if defined?(RSpec) && RSpec.respond_to?(:configure)
RSpec.configure do |config|
config.before { FactoryBot::SyntaxRunner.file_fixture_support = self }
end
end
end
end

config.after_initialize do |app|
FactoryBot.find_definitions
Reloader.new(app).run
Expand Down
24 changes: 24 additions & 0 deletions spec/factory_bot_rails/factory_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

require "rails/all"
require "rspec/rails"

describe "factory extensions" do
include FactoryBot::Syntax::Methods

describe "#file_fixture" do
it "delegates to the test harness" do
define_model "Upload", filename: :string

FactoryBot.define do
factory :upload do
filename { file_fixture("file.txt") }
end
end

upload = build(:upload)

expect(Pathname(upload.filename)).to eq(file_fixture("file.txt"))
end
end
end
2 changes: 2 additions & 0 deletions spec/fake_app.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "rails"

module Dummy
class Application < Rails::Application
config.eager_load = false
Expand Down
Empty file added spec/fixtures/files/file.txt
Empty file.
23 changes: 23 additions & 0 deletions test/factory_bot_rails/factory_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require "test_helper"

class FactoryBotRails::FactoryTest < ActiveSupport::TestCase
include FactoryBot::Syntax::Methods

Upload = Struct.new(:filename)

self.file_fixture_path = "test/fixtures/files"

test "delegates #file_fixture to the test harness" do
FactoryBot.define do
factory :upload, class: Upload do
filename { file_fixture("file.txt") }
end
end

upload = build(:upload)

assert_equal file_fixture("file.txt"), upload.filename
end
end
Empty file added test/fixtures/files/file.txt
Empty file.
8 changes: 8 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

# Configure Rails Environment
ENV["RAILS_ENV"] = "test"

require_relative "../spec/fake_app"
require "rails/test_help"
require "factory_bot_rails"

0 comments on commit 33c1348

Please sign in to comment.