From 33c134815ae45acda852a9552fe473b3a35198df Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Mon, 25 Sep 2023 11:24:10 -0400 Subject: [PATCH] Support `file_fixture` in Factory definitions 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]: https://github.com/thoughtbot/factory_bot/issues/1282#issuecomment-1733796049 [rails/rails#45606]: https://github.com/rails/rails/pull/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 --- README.md | 13 ++++++++++ Rakefile | 5 +++- lib/factory_bot_rails/file_fixture_support.rb | 9 +++++++ lib/factory_bot_rails/railtie.rb | 18 ++++++++++++++ spec/factory_bot_rails/factory_spec.rb | 24 +++++++++++++++++++ spec/fake_app.rb | 2 ++ spec/fixtures/files/file.txt | 0 test/factory_bot_rails/factory_test.rb | 23 ++++++++++++++++++ test/fixtures/files/file.txt | 0 test/test_helper.rb | 8 +++++++ 10 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 lib/factory_bot_rails/file_fixture_support.rb create mode 100644 spec/factory_bot_rails/factory_spec.rb create mode 100644 spec/fixtures/files/file.txt create mode 100644 test/factory_bot_rails/factory_test.rb create mode 100644 test/fixtures/files/file.txt create mode 100644 test/test_helper.rb diff --git a/README.md b/README.md index 6aef3130..a1191086 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/Rakefile b/Rakefile index 1b8ba844..3a1c7029 100644 --- a/Rakefile +++ b/Rakefile @@ -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" @@ -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] diff --git a/lib/factory_bot_rails/file_fixture_support.rb b/lib/factory_bot_rails/file_fixture_support.rb new file mode 100644 index 00000000..ef2044a9 --- /dev/null +++ b/lib/factory_bot_rails/file_fixture_support.rb @@ -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 diff --git a/lib/factory_bot_rails/railtie.rb b/lib/factory_bot_rails/railtie.rb index 0e7dfdb8..2b122370 100644 --- a/lib/factory_bot_rails/railtie.rb +++ b/lib/factory_bot_rails/railtie.rb @@ -4,6 +4,7 @@ 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 @@ -11,6 +12,7 @@ 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 @@ -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 diff --git a/spec/factory_bot_rails/factory_spec.rb b/spec/factory_bot_rails/factory_spec.rb new file mode 100644 index 00000000..009b390c --- /dev/null +++ b/spec/factory_bot_rails/factory_spec.rb @@ -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 diff --git a/spec/fake_app.rb b/spec/fake_app.rb index 958850a1..1336bb6b 100644 --- a/spec/fake_app.rb +++ b/spec/fake_app.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "rails" + module Dummy class Application < Rails::Application config.eager_load = false diff --git a/spec/fixtures/files/file.txt b/spec/fixtures/files/file.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/factory_bot_rails/factory_test.rb b/test/factory_bot_rails/factory_test.rb new file mode 100644 index 00000000..ad375685 --- /dev/null +++ b/test/factory_bot_rails/factory_test.rb @@ -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 diff --git a/test/fixtures/files/file.txt b/test/fixtures/files/file.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 00000000..60a0e537 --- /dev/null +++ b/test/test_helper.rb @@ -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"