From e093a1b7a04214f0a8f887eba279464e4ef213e5 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 --- 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 +++++++ 8 files changed, 84 insertions(+) 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/lib/factory_bot_rails/file_fixture_support.rb b/lib/factory_bot_rails/file_fixture_support.rb new file mode 100644 index 00000000..6fa5dd7b --- /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 + + klass.delegate :file_fixture, to: :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..243fea14 --- /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 { self.file_fixture("file.txt") } + end + end + + upload = build(:upload) + + expect(upload.filename).to eq(file_fixture("file.txt").to_s) + 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..03c485f7 --- /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 { self.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"