Support rails generator testing in Rspec
This goes into spec/support/generator_specs_support.rb:
module GeneratorSpecsSupport
extend ActiveSupport::Concern
included do
gen_name = @metadata[:description]
gen_name_snake = gen_name.underscore
require 'fileutils'
require 'rails/generators'
require "generators/#{gen_name_snake.chomp('_generator')}/#{gen_name_snake}"
require 'active_support/testing/stream'
require 'rails/generators/testing/behaviour'
include FileUtils
include ActiveSupport::Testing::Stream
around(:each) do |example|
current_path = File.expand_path(Dir.pwd)
Dir.mktmpdir do |path|
@destination_root = path
@generator_class = gen_name.constantize
@default_arguments = []
example.run
remove_instance_variable('@destination_root')
remove_instance_variable('@generator_class')
remove_instance_variable('@default_arguments')
end
cd current_path
end
end
attr_reader :destination_root, :generator_class, :default_arguments
def generated_path(path) = Pathname("#{destination_root}/#{path}")
# Borrowed from railties/lib/rails/generators/testing/behaviour.rb
def run_generator(args = default_arguments, config = {})
capture(:stdout) do
args += ["--skip-bundle"] unless args.include?("--no-skip-bundle") || args.include?("--dev")
args |= ["--skip-bootsnap"] unless args.include?("--no-skip-bootsnap")
generator_class.start(args, config.reverse_merge(destination_root: destination_root))
end
end
end
In spec/rails_helper.rb add the following:
# Near top requires:
require Rails.root.join('spec/support/generator_specs_support')
# In config block:
config.include(GeneratorSpecsSupport, type: :generator)
Specs should go into spec/generator/my_generator_spec.rb
.
Here’s an example spec:
require 'rails_helper'
# `'AdrGenerator'` must be the actual class name of the generator.
RSpec.describe 'AdrGenerator' do
it "inserts correct name and date" do
today = Date.current
expect { run_generator ["sample_adr"] }.to_not raise_error
md_file = generated_path "doc/adr/#{today.strftime("%Y-%m")}-sample-adr.md"
expect(md_file).to exist
md_contents = md_file.read
expect(md_contents).to include("# Sample Adr")
expect(md_contents).to include("* **Last Updated:** #{today}")
end
end
Code snippets in this post are covered by 0BSD License.