Testing a generator in a Rails engine can result in unwanted modifications of files in the test/dummy
directory.
# lib/generators/my_engine/install_generator.rb
module MyEngine
module Generators
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path("templates", __dir__)
def create_users_table
generate "migration", "create_users_table email:string:index password_digest:string"
end
def add_routes
route "root to: 'home#index'"
end
end
end
end
What's Going On Here?
- This class creates a new
rails g my_engine:install
command. When it is called a migration will be added todb/migrate/
andconfig/routes.rb
will be updated.- This will happen even when the test suite is run and will affect the
test/dummy
directory resulting in unwanted changes.
# test/lib/generators/my_engine/install_generator_test.rb
require "test_helper"
require "generators/my_engine/install_generator"
class MyEngine::InstallGeneratorTest < Rails::Generators::TestCase
tests ::MyEngine::Generators::InstallGenerator
destination Rails.root
setup :prepare_destination
teardown :restore_destination
test "creates migration for users table" do
run_generator
assert_migration "db/migrate/create_users_table.rb"
end
test "should add routes" do
run_generator
assert_file "config/routes.rb" do |file|
assert_match(/root to: 'home#index'/, file)
end
end
private
def backup_file(path)
copy_file Rails.root.join(path), Rails.root.join("#{path}.bak")
end
def prepare_destination
backup_file("config/routes.rb")
end
def remove_if_exists(path)
full_path = Rails.root.join(path)
FileUtils.rm_rf(full_path)
end
def restore_destination
remove_if_exists("db/migrate")
restore_file("config/routes.rb")
end
def restore_file(path)
File.delete(Rails.root.join(path))
copy_file Rails.root.join("#{path}.bak"), Rails.root.join(path)
File.delete(Rails.root.join("#{path}.bak"))
end
end
What's Going On Here?
- We set the destination to the
Rails.root
. That way when run_generator is called the changes happen in the dummy app located intest/dummy
.- We override the existing prepare_destination instance method with our own. This will be called before each test block is run, and serves to keep the
test/dummy
directory in a clean state. We callrestore_destination
to be called after each test is run via theteardown
callback. This will restore any modified files and remove any generated files.
References