From ed625b78c9f67342221cd809caaeabdf28cd2438 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 12 Jan 2024 05:45:48 -0500 Subject: [PATCH 01/12] Introduce `suspenders:testing` generator Generate `spec/rails_helper.rb` and `spec/spec_helper.rb` via `rails g rspec:intall` in an effort to not drift from what RSpec recommends out of the box. The only thing that differs from the existing `spec/rails_helper.rb` configuration is: ```ruby config.infer_base_class_for_anonymous_controllers = false ``` Note that we still keep `config.fixture_path = "#{::Rails.root}/spec/fixtures"`, in the generated `spec/rails_helper.rb` file even though we favor FactoriesBotRails. This is because we can still use fixtures for things like file uploads. Modify `spec/spec_helper.rb` by including the following: ```ruby config.example_status_persistence_file_path = "tmp/rspec_examples.txt config.order = :random WebMock.disable_net_connect!( allow_localhost: true, allow: "chromedriver.storage.googleapis.com" ) ``` Introduce dependency on [webmock][], and configure RSpec and Minitest to use it. Calling `generate "rspec:install"` seemed to invoked the generator twice (at least in the test), so we rely on `rails_command "generate rspec:install" Additionally, this commit removes the [formulaic][] dependency. A follow-up commit could explore creating a separate one-off generator for this, but for now, we're aiming for the leanest build possible. [webmock]: https://github.com/bblimke/webmock [formulaic]: https://github.com/calebhearth/formulaic --- NEWS.md | 1 + README.md | 4 + .../suspenders/testing_generator.rb | 112 +++++ .../templates/testing/action_mailer.rb | 5 + .../templates/testing/chromedriver.rb | 27 ++ lib/generators/templates/testing/i18n.rb | 3 + .../suspenders/testing_generator_test.rb | 418 ++++++++++++++++++ 7 files changed, 570 insertions(+) create mode 100644 lib/generators/suspenders/testing_generator.rb create mode 100644 lib/generators/templates/testing/action_mailer.rb create mode 100644 lib/generators/templates/testing/chromedriver.rb create mode 100644 lib/generators/templates/testing/i18n.rb create mode 100644 test/generators/suspenders/testing_generator_test.rb diff --git a/NEWS.md b/NEWS.md index 1a31f1e23..31563045d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,7 @@ Unreleased * Introduce `suspenders:tasks` generator * Introduce `suspenders:db:migrate` task * Introduce `suspenders:email` generator +* Introduce `suspenders:testing` generator 20230113.0 (January, 13, 2023) diff --git a/README.md b/README.md index 0f1a43568..76fd0d14b 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,10 @@ Configures `default_url_options` in `test` and `development`. bin/rails g suspenders:email ``` +### Testing + +TODO + ## Contributing See the [CONTRIBUTING] document. diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb new file mode 100644 index 000000000..f4a8e23fd --- /dev/null +++ b/lib/generators/suspenders/testing_generator.rb @@ -0,0 +1,112 @@ +module Suspenders + module Generators + class TestingGenerator < Rails::Generators::Base + FRAMEWORK_OPTIONS = %w[minitest rspec].freeze + + source_root File.expand_path("../../templates/testing", __FILE__) + class_option :framework, enum: FRAMEWORK_OPTIONS, default: "minitest" + + def add_gems + if options[:framework] == "rspec" + gem_group :development, :test do + gem "rspec-rails", "~> 6.1.0" + end + + gem_group :test do + gem "shoulda-matchers", "~> 6.0" + gem "webdrivers" + gem "webmock" + end + else + gem_group :test do + gem "webmock" + end + end + + Bundler.with_unbundled_env { run "bundle install" } + end + + def run_rspec_installation_script + if options[:framework] == "rspec" + rails_command "generate rspec:install" + end + end + + def modify_rails_helper + if options[:framework] == "rspec" + insert_into_file "spec/rails_helper.rb", + " config.infer_base_class_for_anonymous_controllers = false\n", + after: "RSpec.configure do |config|\n" + end + end + + def modify_spec_helper + if options[:framework] == "rspec" + persistence_file_path = " config.example_status_persistence_file_path = \"tmp/rspec_examples.txt\"\n" + order = " config.order = :random\n\n" + webmock_config = <<~RUBY + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + insert_into_file "spec/spec_helper.rb", + persistence_file_path + order, + after: "RSpec.configure do |config|\n" + + insert_into_file "spec/spec_helper.rb", webmock_config + end + end + + def modify_test_helper + if options[:framework] == "minitest" + webmock_config = <<~RUBY + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + insert_into_file "test/test_helper.rb", webmock_config + + insert_into_file "test/test_helper.rb", "\s\s\s\sinclude ActionView::Helpers::TranslationHelper\n\s\s\s\sinclude ActionMailer::TestCase::ClearTestDeliveries\n\n", + after: "class TestCase\n" + end + end + + def create_system_spec_dir + if options[:framework] == "rspec" + empty_directory "spec/system" + create_file "spec/system/.gitkeep" + end + end + + def configure_chromedriver + if options[:framework] == "rspec" + copy_file "chromedriver.rb", "spec/support/chromedriver.rb" + end + end + + def configure_i18n_helper + if options[:framework] == "rspec" + copy_file "i18n.rb", "spec/support/i18n.rb" + end + end + + def configure_action_mailer_helpers + # https://guides.rubyonrails.org/testing.html#the-basic-test-case + # + # The ActionMailer::Base.deliveries array is only reset automatically in + # ActionMailer::TestCase and ActionDispatch::IntegrationTest tests. If + # you want to have a clean slate outside these test cases, you can reset + # it manually with: ActionMailer::Base.deliveries.clear + if options[:framework] == "rspec" + copy_file "action_mailer.rb", "spec/support/action_mailer.rb" + end + end + end + end +end diff --git a/lib/generators/templates/testing/action_mailer.rb b/lib/generators/templates/testing/action_mailer.rb new file mode 100644 index 000000000..b9563a3bc --- /dev/null +++ b/lib/generators/templates/testing/action_mailer.rb @@ -0,0 +1,5 @@ +RSpec.configure do |config| + config.before(:each) do + ActionMailer::Base.deliveries.clear + end +end diff --git a/lib/generators/templates/testing/chromedriver.rb b/lib/generators/templates/testing/chromedriver.rb new file mode 100644 index 000000000..4091d1531 --- /dev/null +++ b/lib/generators/templates/testing/chromedriver.rb @@ -0,0 +1,27 @@ +require "selenium/webdriver" + +Capybara.register_driver :chrome do |app| + Capybara::Selenium::Driver.new(app, browser: :chrome) +end + +Capybara.register_driver :headless_chrome do |app| + options = ::Selenium::WebDriver::Chrome::Options.new + options.headless! + options.add_argument "--window-size=1680,1050" + + Capybara::Selenium::Driver.new app, + browser: :chrome, + options: options +end + +Capybara.javascript_driver = :headless_chrome + +RSpec.configure do |config| + config.before(:each, type: :system) do + driven_by :rack_test + end + + config.before(:each, type: :system, js: true) do + driven_by Capybara.javascript_driver + end +end diff --git a/lib/generators/templates/testing/i18n.rb b/lib/generators/templates/testing/i18n.rb new file mode 100644 index 000000000..0c61ce662 --- /dev/null +++ b/lib/generators/templates/testing/i18n.rb @@ -0,0 +1,3 @@ +RSpec.configure do |config| + config.include ActionView::Helpers::TranslationHelper +end diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb new file mode 100644 index 000000000..4d8aaa7f7 --- /dev/null +++ b/test/generators/suspenders/testing_generator_test.rb @@ -0,0 +1,418 @@ +require "test_helper" +require "generators/suspenders/testing_generator" + +module Suspenders + module Generators + class TestingGenerator::ClassOptionTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::TestingGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "has a framework option" do + option = generator_class.class_options[:framework] + + assert_equal :string, option.type + assert_not option.required + assert_equal %w[minitest rspec], option.enum + assert_equal "minitest", option.default + end + + test "raises if framework option is unsupported" do + output = capture(:stderr) { run_generator %w[--framework=unknown] } + + assert_match(/Expected '--framework' to be one of/, output) + end + + private + + def prepare_destination + touch "Gemfile" + end + + def restore_destination + remove_file_if_exists "Gemfile" + end + end + end +end + +module Suspenders + module Generators + class TestingGenerator::MiniTestTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::TestingGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "adds gems to Gemfile" do + expected = <<~RUBY + group :test do + gem "webmock" + end + RUBY + + run_generator %w[--framework=minitest] + + assert_file app_root("Gemfile") do |file| + assert_match(expected, file) + end + end + + test "installs gems with Bundler" do + output = run_generator %w[--framework=minitest] + + assert_match(/bundle install/, output) + end + + test "does not run RSpec installation script" do + output = run_generator %w[--framework=minitest] + + assert_no_match(/generate rspec:install/, output) + end + + test "does not configure Chromedriver" do + run_generator %w[--framework=minitest] + + assert_no_file app_root("spec/support/chromedriver.rb") + end + + test "does not create system spec directory" do + run_generator %w[--framework=minitest] + + assert_no_file app_root("spec/system/.gitkeep") + end + + test "configures test helper" do + expected = <<~RUBY + ENV["RAILS_ENV"] ||= "test" + require_relative "../config/environment" + require "rails/test_help" + + module ActiveSupport + class TestCase + include ActionView::Helpers::TranslationHelper + include ActionMailer::TestCase::ClearTestDeliveries + + end + end + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + output = run_generator %w[--framework=minitest] + + assert_file app_root("test/test_helper.rb") do |file| + assert_equal expected, file + end + end + + test "configures Action Mailer" do + end + + test "removes spec directory" do + end + + def prepare_destination + touch "Gemfile" + mkdir "test" + touch "test/test_helper.rb", content: test_helper + end + + def restore_destination + remove_file_if_exists "Gemfile" + remove_dir_if_exists "test" + end + + def test_helper + <<~RUBY + ENV["RAILS_ENV"] ||= "test" + require_relative "../config/environment" + require "rails/test_help" + + module ActiveSupport + class TestCase + end + end + RUBY + end + end + end +end + +module Suspenders + module Generators + class TestingGenerator::RSpecTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::TestingGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "adds gems to Gemfile" do + expected = <<~RUBY + group :development, :test do + gem "rspec-rails", "~> 6.1.0" + end + + group :test do + gem "shoulda-matchers", "~> 6.0" + gem "webdrivers" + gem "webmock" + end + RUBY + + run_generator %w[--framework=rspec] + + assert_file app_root("Gemfile") do |file| + assert_match(expected, file) + end + end + + test "installs gems with Bundler" do + output = run_generator %w[--framework=rspec] + + assert_match(/bundle install/, output) + end + + test "runs RSpec installation script" do + output = run_generator %w[--framework=rspec] + + assert_match(/generate rspec:install/, output) + end + + test "configures rails_helper" do + touch "spec/rails_helper.rb", content: rails_helper + + run_generator %w[--framework=rspec] + + assert_file "spec/rails_helper.rb" do |file| + assert_match(/RSpec\.configure do \|config\|\s{3}config\.infer_base_class_for_anonymous_controllers\s*=\s*false/m, + file) + end + end + + test "configures spec_helper" do + touch "spec/spec_helper.rb", content: spec_helper + expected = <<~RUBY + RSpec.configure do |config| + config.example_status_persistence_file_path = \"tmp/rspec_examples.txt\" + config.order = :random + + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + config.shared_context_metadata_behavior = :apply_to_host_groups + end + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + run_generator %w[--framework=rspec] + + assert_file app_root("spec/spec_helper.rb") do |file| + assert_equal expected, file + end + end + + test "configures Chromedriver" do + expected = <<~RUBY + require "selenium/webdriver" + + Capybara.register_driver :chrome do |app| + Capybara::Selenium::Driver.new(app, browser: :chrome) + end + + Capybara.register_driver :headless_chrome do |app| + options = ::Selenium::WebDriver::Chrome::Options.new + options.headless! + options.add_argument "--window-size=1680,1050" + + Capybara::Selenium::Driver.new app, + browser: :chrome, + options: options + end + + Capybara.javascript_driver = :headless_chrome + + RSpec.configure do |config| + config.before(:each, type: :system) do + driven_by :rack_test + end + + config.before(:each, type: :system, js: true) do + driven_by Capybara.javascript_driver + end + end + RUBY + + run_generator %w[--framework=rspec] + + assert_file app_root("spec/support/chromedriver.rb") do |file| + assert_equal expected, file + end + end + + test "creates system spec directory"do + run_generator %w[--framework=rspec] + + assert_file app_root("spec/system/.gitkeep") + end + + test "configures Should Matchers" do + skip + end + + test "configures i18n" do + expected = <<~RUBY + RSpec.configure do |config| + config.include ActionView::Helpers::TranslationHelper + end + RUBY + + run_generator %w[--framework=rspec] + + assert_file app_root("spec/support/i18n.rb") do |file| + assert_equal expected, file + end + end + + test "configures Action Mailer" do + expected = <<~RUBY + RSpec.configure do |config| + config.before(:each) do + ActionMailer::Base.deliveries.clear + end + end + RUBY + + run_generator %w[--framework=rspec] + + assert_file app_root("spec/support/action_mailer.rb") do |file| + assert_equal expected, file + end + end + + test "removes test directory" do + skip + end + + private + + def prepare_destination + touch "Gemfile" + mkdir "spec" + touch "spec/rails_helper.rb" + touch "spec/spec_helper.rb" + end + + def restore_destination + remove_file_if_exists "Gemfile" + remove_dir_if_exists "spec" + end + + def rails_helper + # Generated from rails g rspec:install + <<~RUBY + # This file is copied to spec/ when you run 'rails generate rspec:install' + require 'spec_helper' + ENV['RAILS_ENV'] ||= 'test' + require_relative '../config/environment' + # Prevent database truncation if the environment is production + abort("The Rails environment is running in production mode!") if Rails.env.production? + require 'rspec/rails' + # Add additional requires below this line. Rails is not loaded until this point! + + # Requires supporting ruby files with custom matchers and macros, etc, in + # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are + # run as spec files by default. This means that files in spec/support that end + # in _spec.rb will both be required and run as specs, causing the specs to be + # run twice. It is recommended that you do not name files matching this glob to + # end with _spec.rb. You can configure this pattern with the --pattern + # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. + # + # The following line is provided for convenience purposes. It has the downside + # of increasing the boot-up time by auto-requiring all files in the support + # directory. Alternatively, in the individual `*_spec.rb` files, manually + # require only the support files necessary. + # + # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } + + # Checks for pending migrations and applies them before tests are run. + # If you are not using ActiveRecord, you can remove these lines. + begin + ActiveRecord::Migration.maintain_test_schema! + rescue ActiveRecord::PendingMigrationError => e + abort e.to_s.strip + end + RSpec.configure do |config| + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # You can uncomment this line to turn off ActiveRecord support entirely. + # config.use_active_record = false + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, type: :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://rspec.info/features/6-0/rspec-rails + config.infer_spec_type_from_file_location! + + # Filter lines from Rails gems in backtraces. + config.filter_rails_from_backtrace! + # arbitrary gems may also be filtered via: + # config.filter_gems_from_backtrace("gem name") + end + Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file } + RUBY + end + + def spec_helper + # Generated from rails g rspec:install + # Comments removed + <<~RUBY + RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + config.shared_context_metadata_behavior = :apply_to_host_groups + end + RUBY + end + + end + end +end From 974237227b3fedf1e3a208e9824c51fb30ec812b Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Thu, 25 Jan 2024 15:59:16 -0500 Subject: [PATCH 02/12] Introduce `suspenders:testing:minitest` and `suspenders:testing:rspec` --- README.md | 4 + .../suspenders/testing/minitest_generator.rb | 38 ++ .../suspenders/testing/rspec_generator.rb | 84 ++++ .../suspenders/testing_generator.rb | 112 ----- .../testing/{ => rspec}/action_mailer.rb | 0 .../testing/{ => rspec}/chromedriver.rb | 0 .../templates/testing/{ => rspec}/i18n.rb | 0 .../testing/rspec/shoulda_matchers.rb | 6 + .../suspenders/rake_generator_test.rb | 2 +- .../testing/minitest_generator_test.rb | 100 +++++ .../testing/rspec_generator_test.rb | 250 +++++++++++ .../suspenders/testing_generator_test.rb | 418 ------------------ 12 files changed, 483 insertions(+), 531 deletions(-) create mode 100644 lib/generators/suspenders/testing/minitest_generator.rb create mode 100644 lib/generators/suspenders/testing/rspec_generator.rb delete mode 100644 lib/generators/suspenders/testing_generator.rb rename lib/generators/templates/testing/{ => rspec}/action_mailer.rb (100%) rename lib/generators/templates/testing/{ => rspec}/chromedriver.rb (100%) rename lib/generators/templates/testing/{ => rspec}/i18n.rb (100%) create mode 100644 lib/generators/templates/testing/rspec/shoulda_matchers.rb create mode 100644 test/generators/suspenders/testing/minitest_generator_test.rb create mode 100644 test/generators/suspenders/testing/rspec_generator_test.rb delete mode 100644 test/generators/suspenders/testing_generator_test.rb diff --git a/README.md b/README.md index 76fd0d14b..36391eb9d 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,10 @@ bin/rails g suspenders:email ### Testing +#### Minitest + +#### RSpec + TODO ## Contributing diff --git a/lib/generators/suspenders/testing/minitest_generator.rb b/lib/generators/suspenders/testing/minitest_generator.rb new file mode 100644 index 000000000..4e7d215b6 --- /dev/null +++ b/lib/generators/suspenders/testing/minitest_generator.rb @@ -0,0 +1,38 @@ +module Suspenders + module Generators + module Testing + class MinitestGenerator < Rails::Generators::Base + def add_gems + gem_group :test do + gem "webmock" + end + + Bundler.with_unbundled_env { run "bundle install" } + end + + def modify_test_helper + webmock_config = <<~RUBY + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + insert_into_file "test/test_helper.rb", webmock_config + + insert_into_file "test/test_helper.rb", + "\s\s\s\sinclude ActionView::Helpers::TranslationHelper\n" \ + "\s\s\s\sinclude ActionMailer::TestCase::ClearTestDeliveries\n\n", + after: "class TestCase\n" + end + + def remove_spec_directory + path = Rails.root.join("spec") + + FileUtils.rm_r path if File.exist? path + end + end + end + end +end diff --git a/lib/generators/suspenders/testing/rspec_generator.rb b/lib/generators/suspenders/testing/rspec_generator.rb new file mode 100644 index 000000000..77d3d3be6 --- /dev/null +++ b/lib/generators/suspenders/testing/rspec_generator.rb @@ -0,0 +1,84 @@ +module Suspenders + module Generators + module Testing + class RSpecGenerator < Rails::Generators::Base + source_root File.expand_path("../../../templates/testing/rspec", __FILE__) + + def add_gems + gem_group :development, :test do + gem "rspec-rails", "~> 6.1.0" + end + + gem_group :test do + gem "shoulda-matchers", "~> 6.0" + gem "webdrivers" + gem "webmock" + end + + Bundler.with_unbundled_env { run "bundle install" } + end + + def run_rspec_installation_script + rails_command "generate rspec:install" + end + + def modify_rails_helper + insert_into_file "spec/rails_helper.rb", + "\s\sconfig.infer_base_class_for_anonymous_controllers = false\n", + after: "RSpec.configure do |config|\n" + end + + def modify_spec_helper + persistence_file_path = "\s\sconfig.example_status_persistence_file_path = \"tmp/rspec_examples.txt\"\n" + order = "\s\sconfig.order = :random\n\n" + webmock_config = <<~RUBY + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + insert_into_file "spec/spec_helper.rb", + persistence_file_path + order, + after: "RSpec.configure do |config|\n" + + insert_into_file "spec/spec_helper.rb", webmock_config + end + + def create_system_spec_dir + empty_directory "spec/system" + create_file "spec/system/.gitkeep" + end + + def configure_chromedriver + copy_file "chromedriver.rb", "spec/support/chromedriver.rb" + end + + def configure_i18n_helper + copy_file "i18n.rb", "spec/support/i18n.rb" + end + + def configure_shoulda_matchers + copy_file "shoulda_matchers.rb", "spec/support/shoulda_matchers.rb" + end + + def configure_action_mailer_helpers + # https://guides.rubyonrails.org/testing.html#the-basic-test-case + # + # The ActionMailer::Base.deliveries array is only reset automatically in + # ActionMailer::TestCase and ActionDispatch::IntegrationTest tests. If + # you want to have a clean slate outside these test cases, you can reset + # it manually with: ActionMailer::Base.deliveries.clear + copy_file "action_mailer.rb", "spec/support/action_mailer.rb" + end + + def remove_test_directory + path = Rails.root.join("test") + + FileUtils.rm_r path if File.exist? path + end + end + end + end +end diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb deleted file mode 100644 index f4a8e23fd..000000000 --- a/lib/generators/suspenders/testing_generator.rb +++ /dev/null @@ -1,112 +0,0 @@ -module Suspenders - module Generators - class TestingGenerator < Rails::Generators::Base - FRAMEWORK_OPTIONS = %w[minitest rspec].freeze - - source_root File.expand_path("../../templates/testing", __FILE__) - class_option :framework, enum: FRAMEWORK_OPTIONS, default: "minitest" - - def add_gems - if options[:framework] == "rspec" - gem_group :development, :test do - gem "rspec-rails", "~> 6.1.0" - end - - gem_group :test do - gem "shoulda-matchers", "~> 6.0" - gem "webdrivers" - gem "webmock" - end - else - gem_group :test do - gem "webmock" - end - end - - Bundler.with_unbundled_env { run "bundle install" } - end - - def run_rspec_installation_script - if options[:framework] == "rspec" - rails_command "generate rspec:install" - end - end - - def modify_rails_helper - if options[:framework] == "rspec" - insert_into_file "spec/rails_helper.rb", - " config.infer_base_class_for_anonymous_controllers = false\n", - after: "RSpec.configure do |config|\n" - end - end - - def modify_spec_helper - if options[:framework] == "rspec" - persistence_file_path = " config.example_status_persistence_file_path = \"tmp/rspec_examples.txt\"\n" - order = " config.order = :random\n\n" - webmock_config = <<~RUBY - - WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" - ) - RUBY - - insert_into_file "spec/spec_helper.rb", - persistence_file_path + order, - after: "RSpec.configure do |config|\n" - - insert_into_file "spec/spec_helper.rb", webmock_config - end - end - - def modify_test_helper - if options[:framework] == "minitest" - webmock_config = <<~RUBY - - WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" - ) - RUBY - - insert_into_file "test/test_helper.rb", webmock_config - - insert_into_file "test/test_helper.rb", "\s\s\s\sinclude ActionView::Helpers::TranslationHelper\n\s\s\s\sinclude ActionMailer::TestCase::ClearTestDeliveries\n\n", - after: "class TestCase\n" - end - end - - def create_system_spec_dir - if options[:framework] == "rspec" - empty_directory "spec/system" - create_file "spec/system/.gitkeep" - end - end - - def configure_chromedriver - if options[:framework] == "rspec" - copy_file "chromedriver.rb", "spec/support/chromedriver.rb" - end - end - - def configure_i18n_helper - if options[:framework] == "rspec" - copy_file "i18n.rb", "spec/support/i18n.rb" - end - end - - def configure_action_mailer_helpers - # https://guides.rubyonrails.org/testing.html#the-basic-test-case - # - # The ActionMailer::Base.deliveries array is only reset automatically in - # ActionMailer::TestCase and ActionDispatch::IntegrationTest tests. If - # you want to have a clean slate outside these test cases, you can reset - # it manually with: ActionMailer::Base.deliveries.clear - if options[:framework] == "rspec" - copy_file "action_mailer.rb", "spec/support/action_mailer.rb" - end - end - end - end -end diff --git a/lib/generators/templates/testing/action_mailer.rb b/lib/generators/templates/testing/rspec/action_mailer.rb similarity index 100% rename from lib/generators/templates/testing/action_mailer.rb rename to lib/generators/templates/testing/rspec/action_mailer.rb diff --git a/lib/generators/templates/testing/chromedriver.rb b/lib/generators/templates/testing/rspec/chromedriver.rb similarity index 100% rename from lib/generators/templates/testing/chromedriver.rb rename to lib/generators/templates/testing/rspec/chromedriver.rb diff --git a/lib/generators/templates/testing/i18n.rb b/lib/generators/templates/testing/rspec/i18n.rb similarity index 100% rename from lib/generators/templates/testing/i18n.rb rename to lib/generators/templates/testing/rspec/i18n.rb diff --git a/lib/generators/templates/testing/rspec/shoulda_matchers.rb b/lib/generators/templates/testing/rspec/shoulda_matchers.rb new file mode 100644 index 000000000..7d045f359 --- /dev/null +++ b/lib/generators/templates/testing/rspec/shoulda_matchers.rb @@ -0,0 +1,6 @@ +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :rails + end +end diff --git a/test/generators/suspenders/rake_generator_test.rb b/test/generators/suspenders/rake_generator_test.rb index a4c8153eb..18a8ff43a 100644 --- a/test/generators/suspenders/rake_generator_test.rb +++ b/test/generators/suspenders/rake_generator_test.rb @@ -15,7 +15,7 @@ class RakeGeneratorTest < Rails::Generators::TestCase run_generator assert_file app_root("Rakefile") do |file| - assert_match /task default: "suspenders:rake"/, file + assert_match(/task default: "suspenders:rake"/, file) end end diff --git a/test/generators/suspenders/testing/minitest_generator_test.rb b/test/generators/suspenders/testing/minitest_generator_test.rb new file mode 100644 index 000000000..adf9772f2 --- /dev/null +++ b/test/generators/suspenders/testing/minitest_generator_test.rb @@ -0,0 +1,100 @@ +require "test_helper" +require "generators/suspenders/testing/minitest_generator" + +module Suspenders + module Generators + module Testing + class MinitestGeneratorTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::Testing::MinitestGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "adds gems to Gemfile" do + expected = <<~RUBY + group :test do + gem "webmock" + end + RUBY + + run_generator + + assert_file app_root("Gemfile") do |file| + assert_match(expected, file) + end + end + + test "installs gems with Bundler" do + output = run_generator + + assert_match(/bundle install/, output) + end + + test "configures test helper" do + expected = <<~RUBY + ENV["RAILS_ENV"] ||= "test" + require_relative "../config/environment" + require "rails/test_help" + + module ActiveSupport + class TestCase + include ActionView::Helpers::TranslationHelper + include ActionMailer::TestCase::ClearTestDeliveries + + end + end + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + run_generator + + assert_file app_root("test/test_helper.rb") do |file| + assert_equal expected, file + end + end + + test "removes spec directory" do + mkdir "spec" + + run_generator + + assert_no_directory app_root("spec") + end + + test "has a custom description" do + skip + end + + def prepare_destination + touch "Gemfile" + mkdir "test" + touch "test/test_helper.rb", content: test_helper + end + + def restore_destination + remove_file_if_exists "Gemfile" + remove_dir_if_exists "test" + end + + def test_helper + <<~RUBY + ENV["RAILS_ENV"] ||= "test" + require_relative "../config/environment" + require "rails/test_help" + + module ActiveSupport + class TestCase + end + end + RUBY + end + end + end + end +end diff --git a/test/generators/suspenders/testing/rspec_generator_test.rb b/test/generators/suspenders/testing/rspec_generator_test.rb new file mode 100644 index 000000000..2ba2e86b1 --- /dev/null +++ b/test/generators/suspenders/testing/rspec_generator_test.rb @@ -0,0 +1,250 @@ +require "test_helper" +require "generators/suspenders/testing/rspec_generator" + +module Suspenders + module Generators + module Testing + class RSpecGeneratorTest < Rails::Generators::TestCase + include Suspenders::TestHelpers + + tests Suspenders::Generators::Testing::RSpecGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination + + test "adds gems to Gemfile" do + expected = <<~RUBY + group :development, :test do + gem "rspec-rails", "~> 6.1.0" + end + + group :test do + gem "shoulda-matchers", "~> 6.0" + gem "webdrivers" + gem "webmock" + end + RUBY + + run_generator + + assert_file app_root("Gemfile") do |file| + assert_match(expected, file) + end + end + + test "installs gems with Bundler" do + output = run_generator + + assert_match(/bundle install/, output) + end + + test "runs RSpec installation script" do + output = run_generator + + assert_match(/generate rspec:install/, output) + end + + test "configures rails_helper" do + touch "spec/rails_helper.rb", content: rails_helper + + run_generator + + assert_file "spec/rails_helper.rb" do |file| + assert_match(/RSpec\.configure do \|config\|\s{3}config\.infer_base_class_for_anonymous_controllers\s*=\s*false/m, + file) + end + end + + test "configures spec_helper" do + touch "spec/spec_helper.rb", content: spec_helper + expected = <<~RUBY + RSpec.configure do |config| + config.example_status_persistence_file_path = "tmp/rspec_examples.txt" + config.order = :random + + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + config.shared_context_metadata_behavior = :apply_to_host_groups + end + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + run_generator + + assert_file app_root("spec/spec_helper.rb") do |file| + assert_equal expected, file + end + end + + test "configures Chromedriver" do + expected = <<~RUBY + require "selenium/webdriver" + + Capybara.register_driver :chrome do |app| + Capybara::Selenium::Driver.new(app, browser: :chrome) + end + + Capybara.register_driver :headless_chrome do |app| + options = ::Selenium::WebDriver::Chrome::Options.new + options.headless! + options.add_argument "--window-size=1680,1050" + + Capybara::Selenium::Driver.new app, + browser: :chrome, + options: options + end + + Capybara.javascript_driver = :headless_chrome + + RSpec.configure do |config| + config.before(:each, type: :system) do + driven_by :rack_test + end + + config.before(:each, type: :system, js: true) do + driven_by Capybara.javascript_driver + end + end + RUBY + + run_generator + + assert_file app_root("spec/support/chromedriver.rb") do |file| + assert_equal expected, file + end + end + + test "creates system spec directory" do + run_generator + + assert_file app_root("spec/system/.gitkeep") + end + + test "configures Should Matchers" do + expected = <<~RUBY + Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :rails + end + end + RUBY + + run_generator + + assert_file app_root("spec/support/shoulda_matchers.rb") do |file| + assert_equal expected, file + end + end + + test "configures i18n" do + expected = <<~RUBY + RSpec.configure do |config| + config.include ActionView::Helpers::TranslationHelper + end + RUBY + + run_generator + + assert_file app_root("spec/support/i18n.rb") do |file| + assert_equal expected, file + end + end + + test "configures Action Mailer" do + expected = <<~RUBY + RSpec.configure do |config| + config.before(:each) do + ActionMailer::Base.deliveries.clear + end + end + RUBY + + run_generator + + assert_file app_root("spec/support/action_mailer.rb") do |file| + assert_equal expected, file + end + end + + test "removes test directory" do + mkdir "test" + + run_generator + + assert_no_directory app_root("test") + end + + test "has custom description" do + skip + end + + private + + def prepare_destination + touch "Gemfile" + mkdir "spec" + touch "spec/rails_helper.rb" + touch "spec/spec_helper.rb" + end + + def restore_destination + remove_file_if_exists "Gemfile" + remove_dir_if_exists "spec" + end + + def rails_helper + # Generated from rails g rspec:install + # Comments removed + <<~RUBY + require 'spec_helper' + ENV['RAILS_ENV'] ||= 'test' + require_relative '../config/environment' + + abort("The Rails environment is running in production mode!") if Rails.env.production? + require 'rspec/rails' + + begin + ActiveRecord::Migration.maintain_test_schema! + rescue ActiveRecord::PendingMigrationError => e + abort e.to_s.strip + end + RSpec.configure do |config| + config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.use_transactional_fixtures = true + config.infer_spec_type_from_file_location! + config.filter_rails_from_backtrace! + end + Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file } + RUBY + end + + def spec_helper + # Generated from rails g rspec:install + # Comments removed + <<~RUBY + RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + config.shared_context_metadata_behavior = :apply_to_host_groups + end + RUBY + end + end + end + end +end diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb deleted file mode 100644 index 4d8aaa7f7..000000000 --- a/test/generators/suspenders/testing_generator_test.rb +++ /dev/null @@ -1,418 +0,0 @@ -require "test_helper" -require "generators/suspenders/testing_generator" - -module Suspenders - module Generators - class TestingGenerator::ClassOptionTest < Rails::Generators::TestCase - include Suspenders::TestHelpers - - tests Suspenders::Generators::TestingGenerator - destination Rails.root - setup :prepare_destination - teardown :restore_destination - - test "has a framework option" do - option = generator_class.class_options[:framework] - - assert_equal :string, option.type - assert_not option.required - assert_equal %w[minitest rspec], option.enum - assert_equal "minitest", option.default - end - - test "raises if framework option is unsupported" do - output = capture(:stderr) { run_generator %w[--framework=unknown] } - - assert_match(/Expected '--framework' to be one of/, output) - end - - private - - def prepare_destination - touch "Gemfile" - end - - def restore_destination - remove_file_if_exists "Gemfile" - end - end - end -end - -module Suspenders - module Generators - class TestingGenerator::MiniTestTest < Rails::Generators::TestCase - include Suspenders::TestHelpers - - tests Suspenders::Generators::TestingGenerator - destination Rails.root - setup :prepare_destination - teardown :restore_destination - - test "adds gems to Gemfile" do - expected = <<~RUBY - group :test do - gem "webmock" - end - RUBY - - run_generator %w[--framework=minitest] - - assert_file app_root("Gemfile") do |file| - assert_match(expected, file) - end - end - - test "installs gems with Bundler" do - output = run_generator %w[--framework=minitest] - - assert_match(/bundle install/, output) - end - - test "does not run RSpec installation script" do - output = run_generator %w[--framework=minitest] - - assert_no_match(/generate rspec:install/, output) - end - - test "does not configure Chromedriver" do - run_generator %w[--framework=minitest] - - assert_no_file app_root("spec/support/chromedriver.rb") - end - - test "does not create system spec directory" do - run_generator %w[--framework=minitest] - - assert_no_file app_root("spec/system/.gitkeep") - end - - test "configures test helper" do - expected = <<~RUBY - ENV["RAILS_ENV"] ||= "test" - require_relative "../config/environment" - require "rails/test_help" - - module ActiveSupport - class TestCase - include ActionView::Helpers::TranslationHelper - include ActionMailer::TestCase::ClearTestDeliveries - - end - end - - WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" - ) - RUBY - - output = run_generator %w[--framework=minitest] - - assert_file app_root("test/test_helper.rb") do |file| - assert_equal expected, file - end - end - - test "configures Action Mailer" do - end - - test "removes spec directory" do - end - - def prepare_destination - touch "Gemfile" - mkdir "test" - touch "test/test_helper.rb", content: test_helper - end - - def restore_destination - remove_file_if_exists "Gemfile" - remove_dir_if_exists "test" - end - - def test_helper - <<~RUBY - ENV["RAILS_ENV"] ||= "test" - require_relative "../config/environment" - require "rails/test_help" - - module ActiveSupport - class TestCase - end - end - RUBY - end - end - end -end - -module Suspenders - module Generators - class TestingGenerator::RSpecTest < Rails::Generators::TestCase - include Suspenders::TestHelpers - - tests Suspenders::Generators::TestingGenerator - destination Rails.root - setup :prepare_destination - teardown :restore_destination - - test "adds gems to Gemfile" do - expected = <<~RUBY - group :development, :test do - gem "rspec-rails", "~> 6.1.0" - end - - group :test do - gem "shoulda-matchers", "~> 6.0" - gem "webdrivers" - gem "webmock" - end - RUBY - - run_generator %w[--framework=rspec] - - assert_file app_root("Gemfile") do |file| - assert_match(expected, file) - end - end - - test "installs gems with Bundler" do - output = run_generator %w[--framework=rspec] - - assert_match(/bundle install/, output) - end - - test "runs RSpec installation script" do - output = run_generator %w[--framework=rspec] - - assert_match(/generate rspec:install/, output) - end - - test "configures rails_helper" do - touch "spec/rails_helper.rb", content: rails_helper - - run_generator %w[--framework=rspec] - - assert_file "spec/rails_helper.rb" do |file| - assert_match(/RSpec\.configure do \|config\|\s{3}config\.infer_base_class_for_anonymous_controllers\s*=\s*false/m, - file) - end - end - - test "configures spec_helper" do - touch "spec/spec_helper.rb", content: spec_helper - expected = <<~RUBY - RSpec.configure do |config| - config.example_status_persistence_file_path = \"tmp/rspec_examples.txt\" - config.order = :random - - config.expect_with :rspec do |expectations| - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - config.mock_with :rspec do |mocks| - mocks.verify_partial_doubles = true - end - config.shared_context_metadata_behavior = :apply_to_host_groups - end - - WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" - ) - RUBY - - run_generator %w[--framework=rspec] - - assert_file app_root("spec/spec_helper.rb") do |file| - assert_equal expected, file - end - end - - test "configures Chromedriver" do - expected = <<~RUBY - require "selenium/webdriver" - - Capybara.register_driver :chrome do |app| - Capybara::Selenium::Driver.new(app, browser: :chrome) - end - - Capybara.register_driver :headless_chrome do |app| - options = ::Selenium::WebDriver::Chrome::Options.new - options.headless! - options.add_argument "--window-size=1680,1050" - - Capybara::Selenium::Driver.new app, - browser: :chrome, - options: options - end - - Capybara.javascript_driver = :headless_chrome - - RSpec.configure do |config| - config.before(:each, type: :system) do - driven_by :rack_test - end - - config.before(:each, type: :system, js: true) do - driven_by Capybara.javascript_driver - end - end - RUBY - - run_generator %w[--framework=rspec] - - assert_file app_root("spec/support/chromedriver.rb") do |file| - assert_equal expected, file - end - end - - test "creates system spec directory"do - run_generator %w[--framework=rspec] - - assert_file app_root("spec/system/.gitkeep") - end - - test "configures Should Matchers" do - skip - end - - test "configures i18n" do - expected = <<~RUBY - RSpec.configure do |config| - config.include ActionView::Helpers::TranslationHelper - end - RUBY - - run_generator %w[--framework=rspec] - - assert_file app_root("spec/support/i18n.rb") do |file| - assert_equal expected, file - end - end - - test "configures Action Mailer" do - expected = <<~RUBY - RSpec.configure do |config| - config.before(:each) do - ActionMailer::Base.deliveries.clear - end - end - RUBY - - run_generator %w[--framework=rspec] - - assert_file app_root("spec/support/action_mailer.rb") do |file| - assert_equal expected, file - end - end - - test "removes test directory" do - skip - end - - private - - def prepare_destination - touch "Gemfile" - mkdir "spec" - touch "spec/rails_helper.rb" - touch "spec/spec_helper.rb" - end - - def restore_destination - remove_file_if_exists "Gemfile" - remove_dir_if_exists "spec" - end - - def rails_helper - # Generated from rails g rspec:install - <<~RUBY - # This file is copied to spec/ when you run 'rails generate rspec:install' - require 'spec_helper' - ENV['RAILS_ENV'] ||= 'test' - require_relative '../config/environment' - # Prevent database truncation if the environment is production - abort("The Rails environment is running in production mode!") if Rails.env.production? - require 'rspec/rails' - # Add additional requires below this line. Rails is not loaded until this point! - - # Requires supporting ruby files with custom matchers and macros, etc, in - # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are - # run as spec files by default. This means that files in spec/support that end - # in _spec.rb will both be required and run as specs, causing the specs to be - # run twice. It is recommended that you do not name files matching this glob to - # end with _spec.rb. You can configure this pattern with the --pattern - # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. - # - # The following line is provided for convenience purposes. It has the downside - # of increasing the boot-up time by auto-requiring all files in the support - # directory. Alternatively, in the individual `*_spec.rb` files, manually - # require only the support files necessary. - # - # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } - - # Checks for pending migrations and applies them before tests are run. - # If you are not using ActiveRecord, you can remove these lines. - begin - ActiveRecord::Migration.maintain_test_schema! - rescue ActiveRecord::PendingMigrationError => e - abort e.to_s.strip - end - RSpec.configure do |config| - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = true - - # You can uncomment this line to turn off ActiveRecord support entirely. - # config.use_active_record = false - - # RSpec Rails can automatically mix in different behaviours to your tests - # based on their file location, for example enabling you to call `get` and - # `post` in specs under `spec/controllers`. - # - # You can disable this behaviour by removing the line below, and instead - # explicitly tag your specs with their type, e.g.: - # - # RSpec.describe UsersController, type: :controller do - # # ... - # end - # - # The different available types are documented in the features, such as in - # https://rspec.info/features/6-0/rspec-rails - config.infer_spec_type_from_file_location! - - # Filter lines from Rails gems in backtraces. - config.filter_rails_from_backtrace! - # arbitrary gems may also be filtered via: - # config.filter_gems_from_backtrace("gem name") - end - Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file } - RUBY - end - - def spec_helper - # Generated from rails g rspec:install - # Comments removed - <<~RUBY - RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - config.mock_with :rspec do |mocks| - mocks.verify_partial_doubles = true - end - config.shared_context_metadata_behavior = :apply_to_host_groups - end - RUBY - end - - end - end -end From 379c63a61f9f00d09bc6909d7b18daf13dcd1d59 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Thu, 7 Mar 2024 19:25:38 -0500 Subject: [PATCH 03/12] Drop support for Minitest For now, drop support for Minitest to maintain existing behavior and continue forward momentum. A follow-up, long-term goal could be to explore how we can improve and extend Minitest and/or the Rails [test cases][] to better match RSpec. [test cases]: https://guides.rubyonrails.org/testing.html#a-brief-note-about-test-cases --- README.md | 4 - .../suspenders/testing/minitest_generator.rb | 38 ---- .../suspenders/testing/rspec_generator.rb | 84 -------- .../suspenders/testing_generator.rb | 82 +++++++ .../testing/{rspec => }/action_mailer.rb | 0 .../testing/{rspec => }/chromedriver.rb | 0 .../templates/testing/{rspec => }/i18n.rb | 0 .../testing/{rspec => }/shoulda_matchers.rb | 0 .../testing/minitest_generator_test.rb | 100 --------- ...ator_test.rb => testing_generator_test.rb} | 200 +++++++++--------- 10 files changed, 181 insertions(+), 327 deletions(-) delete mode 100644 lib/generators/suspenders/testing/minitest_generator.rb delete mode 100644 lib/generators/suspenders/testing/rspec_generator.rb create mode 100644 lib/generators/suspenders/testing_generator.rb rename lib/generators/templates/testing/{rspec => }/action_mailer.rb (100%) rename lib/generators/templates/testing/{rspec => }/chromedriver.rb (100%) rename lib/generators/templates/testing/{rspec => }/i18n.rb (100%) rename lib/generators/templates/testing/{rspec => }/shoulda_matchers.rb (100%) delete mode 100644 test/generators/suspenders/testing/minitest_generator_test.rb rename test/generators/suspenders/{testing/rspec_generator_test.rb => testing_generator_test.rb} (52%) diff --git a/README.md b/README.md index 36391eb9d..76fd0d14b 100644 --- a/README.md +++ b/README.md @@ -175,10 +175,6 @@ bin/rails g suspenders:email ### Testing -#### Minitest - -#### RSpec - TODO ## Contributing diff --git a/lib/generators/suspenders/testing/minitest_generator.rb b/lib/generators/suspenders/testing/minitest_generator.rb deleted file mode 100644 index 4e7d215b6..000000000 --- a/lib/generators/suspenders/testing/minitest_generator.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Suspenders - module Generators - module Testing - class MinitestGenerator < Rails::Generators::Base - def add_gems - gem_group :test do - gem "webmock" - end - - Bundler.with_unbundled_env { run "bundle install" } - end - - def modify_test_helper - webmock_config = <<~RUBY - - WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" - ) - RUBY - - insert_into_file "test/test_helper.rb", webmock_config - - insert_into_file "test/test_helper.rb", - "\s\s\s\sinclude ActionView::Helpers::TranslationHelper\n" \ - "\s\s\s\sinclude ActionMailer::TestCase::ClearTestDeliveries\n\n", - after: "class TestCase\n" - end - - def remove_spec_directory - path = Rails.root.join("spec") - - FileUtils.rm_r path if File.exist? path - end - end - end - end -end diff --git a/lib/generators/suspenders/testing/rspec_generator.rb b/lib/generators/suspenders/testing/rspec_generator.rb deleted file mode 100644 index 77d3d3be6..000000000 --- a/lib/generators/suspenders/testing/rspec_generator.rb +++ /dev/null @@ -1,84 +0,0 @@ -module Suspenders - module Generators - module Testing - class RSpecGenerator < Rails::Generators::Base - source_root File.expand_path("../../../templates/testing/rspec", __FILE__) - - def add_gems - gem_group :development, :test do - gem "rspec-rails", "~> 6.1.0" - end - - gem_group :test do - gem "shoulda-matchers", "~> 6.0" - gem "webdrivers" - gem "webmock" - end - - Bundler.with_unbundled_env { run "bundle install" } - end - - def run_rspec_installation_script - rails_command "generate rspec:install" - end - - def modify_rails_helper - insert_into_file "spec/rails_helper.rb", - "\s\sconfig.infer_base_class_for_anonymous_controllers = false\n", - after: "RSpec.configure do |config|\n" - end - - def modify_spec_helper - persistence_file_path = "\s\sconfig.example_status_persistence_file_path = \"tmp/rspec_examples.txt\"\n" - order = "\s\sconfig.order = :random\n\n" - webmock_config = <<~RUBY - - WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" - ) - RUBY - - insert_into_file "spec/spec_helper.rb", - persistence_file_path + order, - after: "RSpec.configure do |config|\n" - - insert_into_file "spec/spec_helper.rb", webmock_config - end - - def create_system_spec_dir - empty_directory "spec/system" - create_file "spec/system/.gitkeep" - end - - def configure_chromedriver - copy_file "chromedriver.rb", "spec/support/chromedriver.rb" - end - - def configure_i18n_helper - copy_file "i18n.rb", "spec/support/i18n.rb" - end - - def configure_shoulda_matchers - copy_file "shoulda_matchers.rb", "spec/support/shoulda_matchers.rb" - end - - def configure_action_mailer_helpers - # https://guides.rubyonrails.org/testing.html#the-basic-test-case - # - # The ActionMailer::Base.deliveries array is only reset automatically in - # ActionMailer::TestCase and ActionDispatch::IntegrationTest tests. If - # you want to have a clean slate outside these test cases, you can reset - # it manually with: ActionMailer::Base.deliveries.clear - copy_file "action_mailer.rb", "spec/support/action_mailer.rb" - end - - def remove_test_directory - path = Rails.root.join("test") - - FileUtils.rm_r path if File.exist? path - end - end - end - end -end diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb new file mode 100644 index 000000000..4364f1b37 --- /dev/null +++ b/lib/generators/suspenders/testing_generator.rb @@ -0,0 +1,82 @@ +module Suspenders + module Generators + class TestingGenerator < Rails::Generators::Base + source_root File.expand_path("../../templates/testing", __FILE__) + + def add_gems + gem_group :development, :test do + gem "rspec-rails", "~> 6.1.0" + end + + gem_group :test do + gem "shoulda-matchers", "~> 6.0" + gem "webdrivers" + gem "webmock" + end + + Bundler.with_unbundled_env { run "bundle install" } + end + + def run_rspec_installation_script + rails_command "generate rspec:install" + end + + def modify_rails_helper + insert_into_file "spec/rails_helper.rb", + "\s\sconfig.infer_base_class_for_anonymous_controllers = false\n", + after: "RSpec.configure do |config|\n" + end + + def modify_spec_helper + persistence_file_path = "\s\sconfig.example_status_persistence_file_path = \"tmp/rspec_examples.txt\"\n" + order = "\s\sconfig.order = :random\n\n" + webmock_config = <<~RUBY + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: "chromedriver.storage.googleapis.com" + ) + RUBY + + insert_into_file "spec/spec_helper.rb", + persistence_file_path + order, + after: "RSpec.configure do |config|\n" + + insert_into_file "spec/spec_helper.rb", webmock_config + end + + def create_system_spec_dir + empty_directory "spec/system" + create_file "spec/system/.gitkeep" + end + + def configure_chromedriver + copy_file "chromedriver.rb", "spec/support/chromedriver.rb" + end + + def configure_i18n_helper + copy_file "i18n.rb", "spec/support/i18n.rb" + end + + def configure_shoulda_matchers + copy_file "shoulda_matchers.rb", "spec/support/shoulda_matchers.rb" + end + + def configure_action_mailer_helpers + # https://guides.rubyonrails.org/testing.html#the-basic-test-case + # + # The ActionMailer::Base.deliveries array is only reset automatically in + # ActionMailer::TestCase and ActionDispatch::IntegrationTest tests. If + # you want to have a clean slate outside these test cases, you can reset + # it manually with: ActionMailer::Base.deliveries.clear + copy_file "action_mailer.rb", "spec/support/action_mailer.rb" + end + + def remove_test_directory + path = Rails.root.join("test") + + FileUtils.rm_r path if File.exist? path + end + end + end +end diff --git a/lib/generators/templates/testing/rspec/action_mailer.rb b/lib/generators/templates/testing/action_mailer.rb similarity index 100% rename from lib/generators/templates/testing/rspec/action_mailer.rb rename to lib/generators/templates/testing/action_mailer.rb diff --git a/lib/generators/templates/testing/rspec/chromedriver.rb b/lib/generators/templates/testing/chromedriver.rb similarity index 100% rename from lib/generators/templates/testing/rspec/chromedriver.rb rename to lib/generators/templates/testing/chromedriver.rb diff --git a/lib/generators/templates/testing/rspec/i18n.rb b/lib/generators/templates/testing/i18n.rb similarity index 100% rename from lib/generators/templates/testing/rspec/i18n.rb rename to lib/generators/templates/testing/i18n.rb diff --git a/lib/generators/templates/testing/rspec/shoulda_matchers.rb b/lib/generators/templates/testing/shoulda_matchers.rb similarity index 100% rename from lib/generators/templates/testing/rspec/shoulda_matchers.rb rename to lib/generators/templates/testing/shoulda_matchers.rb diff --git a/test/generators/suspenders/testing/minitest_generator_test.rb b/test/generators/suspenders/testing/minitest_generator_test.rb deleted file mode 100644 index adf9772f2..000000000 --- a/test/generators/suspenders/testing/minitest_generator_test.rb +++ /dev/null @@ -1,100 +0,0 @@ -require "test_helper" -require "generators/suspenders/testing/minitest_generator" - -module Suspenders - module Generators - module Testing - class MinitestGeneratorTest < Rails::Generators::TestCase - include Suspenders::TestHelpers - - tests Suspenders::Generators::Testing::MinitestGenerator - destination Rails.root - setup :prepare_destination - teardown :restore_destination - - test "adds gems to Gemfile" do - expected = <<~RUBY - group :test do - gem "webmock" - end - RUBY - - run_generator - - assert_file app_root("Gemfile") do |file| - assert_match(expected, file) - end - end - - test "installs gems with Bundler" do - output = run_generator - - assert_match(/bundle install/, output) - end - - test "configures test helper" do - expected = <<~RUBY - ENV["RAILS_ENV"] ||= "test" - require_relative "../config/environment" - require "rails/test_help" - - module ActiveSupport - class TestCase - include ActionView::Helpers::TranslationHelper - include ActionMailer::TestCase::ClearTestDeliveries - - end - end - - WebMock.disable_net_connect!( - allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" - ) - RUBY - - run_generator - - assert_file app_root("test/test_helper.rb") do |file| - assert_equal expected, file - end - end - - test "removes spec directory" do - mkdir "spec" - - run_generator - - assert_no_directory app_root("spec") - end - - test "has a custom description" do - skip - end - - def prepare_destination - touch "Gemfile" - mkdir "test" - touch "test/test_helper.rb", content: test_helper - end - - def restore_destination - remove_file_if_exists "Gemfile" - remove_dir_if_exists "test" - end - - def test_helper - <<~RUBY - ENV["RAILS_ENV"] ||= "test" - require_relative "../config/environment" - require "rails/test_help" - - module ActiveSupport - class TestCase - end - end - RUBY - end - end - end - end -end diff --git a/test/generators/suspenders/testing/rspec_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb similarity index 52% rename from test/generators/suspenders/testing/rspec_generator_test.rb rename to test/generators/suspenders/testing_generator_test.rb index 2ba2e86b1..a073a2ae8 100644 --- a/test/generators/suspenders/testing/rspec_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -1,19 +1,18 @@ require "test_helper" -require "generators/suspenders/testing/rspec_generator" +require "generators/suspenders/testing_generator" module Suspenders module Generators - module Testing - class RSpecGeneratorTest < Rails::Generators::TestCase - include Suspenders::TestHelpers + class TestingGeneratorTest < Rails::Generators::TestCase + include Suspenders::TestHelpers - tests Suspenders::Generators::Testing::RSpecGenerator - destination Rails.root - setup :prepare_destination - teardown :restore_destination + tests Suspenders::Generators::TestingGenerator + destination Rails.root + setup :prepare_destination + teardown :restore_destination - test "adds gems to Gemfile" do - expected = <<~RUBY + test "adds gems to Gemfile" do + expected = <<~RUBY group :development, :test do gem "rspec-rails", "~> 6.1.0" end @@ -23,41 +22,41 @@ class RSpecGeneratorTest < Rails::Generators::TestCase gem "webdrivers" gem "webmock" end - RUBY + RUBY - run_generator + run_generator - assert_file app_root("Gemfile") do |file| - assert_match(expected, file) - end + assert_file app_root("Gemfile") do |file| + assert_match(expected, file) end + end - test "installs gems with Bundler" do - output = run_generator + test "installs gems with Bundler" do + output = run_generator - assert_match(/bundle install/, output) - end + assert_match(/bundle install/, output) + end - test "runs RSpec installation script" do - output = run_generator + test "runs RSpec installation script" do + output = run_generator - assert_match(/generate rspec:install/, output) - end + assert_match(/generate rspec:install/, output) + end - test "configures rails_helper" do - touch "spec/rails_helper.rb", content: rails_helper + test "configures rails_helper" do + touch "spec/rails_helper.rb", content: rails_helper - run_generator + run_generator - assert_file "spec/rails_helper.rb" do |file| - assert_match(/RSpec\.configure do \|config\|\s{3}config\.infer_base_class_for_anonymous_controllers\s*=\s*false/m, - file) - end + assert_file "spec/rails_helper.rb" do |file| + assert_match(/RSpec\.configure do \|config\|\s{3}config\.infer_base_class_for_anonymous_controllers\s*=\s*false/m, + file) end + end - test "configures spec_helper" do - touch "spec/spec_helper.rb", content: spec_helper - expected = <<~RUBY + test "configures spec_helper" do + touch "spec/spec_helper.rb", content: spec_helper + expected = <<~RUBY RSpec.configure do |config| config.example_status_persistence_file_path = "tmp/rspec_examples.txt" config.order = :random @@ -76,17 +75,17 @@ class RSpecGeneratorTest < Rails::Generators::TestCase allow_localhost: true, allow: "chromedriver.storage.googleapis.com" ) - RUBY + RUBY - run_generator + run_generator - assert_file app_root("spec/spec_helper.rb") do |file| - assert_equal expected, file - end + assert_file app_root("spec/spec_helper.rb") do |file| + assert_equal expected, file end + end - test "configures Chromedriver" do - expected = <<~RUBY + test "configures Chromedriver" do + expected = <<~RUBY require "selenium/webdriver" Capybara.register_driver :chrome do |app| @@ -114,98 +113,98 @@ class RSpecGeneratorTest < Rails::Generators::TestCase driven_by Capybara.javascript_driver end end - RUBY + RUBY - run_generator + run_generator - assert_file app_root("spec/support/chromedriver.rb") do |file| - assert_equal expected, file - end + assert_file app_root("spec/support/chromedriver.rb") do |file| + assert_equal expected, file end + end - test "creates system spec directory" do - run_generator + test "creates system spec directory" do + run_generator - assert_file app_root("spec/system/.gitkeep") - end + assert_file app_root("spec/system/.gitkeep") + end - test "configures Should Matchers" do - expected = <<~RUBY + test "configures Should Matchers" do + expected = <<~RUBY Shoulda::Matchers.configure do |config| config.integrate do |with| with.test_framework :rspec with.library :rails end end - RUBY + RUBY - run_generator + run_generator - assert_file app_root("spec/support/shoulda_matchers.rb") do |file| - assert_equal expected, file - end + assert_file app_root("spec/support/shoulda_matchers.rb") do |file| + assert_equal expected, file end + end - test "configures i18n" do - expected = <<~RUBY + test "configures i18n" do + expected = <<~RUBY RSpec.configure do |config| config.include ActionView::Helpers::TranslationHelper end - RUBY + RUBY - run_generator + run_generator - assert_file app_root("spec/support/i18n.rb") do |file| - assert_equal expected, file - end + assert_file app_root("spec/support/i18n.rb") do |file| + assert_equal expected, file end + end - test "configures Action Mailer" do - expected = <<~RUBY + test "configures Action Mailer" do + expected = <<~RUBY RSpec.configure do |config| config.before(:each) do ActionMailer::Base.deliveries.clear end end - RUBY + RUBY - run_generator + run_generator - assert_file app_root("spec/support/action_mailer.rb") do |file| - assert_equal expected, file - end + assert_file app_root("spec/support/action_mailer.rb") do |file| + assert_equal expected, file end + end - test "removes test directory" do - mkdir "test" + test "removes test directory" do + mkdir "test" - run_generator + run_generator - assert_no_directory app_root("test") - end + assert_no_directory app_root("test") + end - test "has custom description" do - skip - end + test "has custom description" do + skip + end - private + private - def prepare_destination - touch "Gemfile" - mkdir "spec" - touch "spec/rails_helper.rb" - touch "spec/spec_helper.rb" - end + def prepare_destination + touch "Gemfile" + mkdir "spec" + touch "spec/rails_helper.rb" + touch "spec/spec_helper.rb" + end - def restore_destination - remove_file_if_exists "Gemfile" - remove_dir_if_exists "spec" - end + def restore_destination + remove_file_if_exists "Gemfile" + remove_dir_if_exists "spec" + end - def rails_helper - # Generated from rails g rspec:install - # Comments removed - <<~RUBY + def rails_helper + # Generated from rails g rspec:install + # Comments removed + <<~RUBY require 'spec_helper' ENV['RAILS_ENV'] ||= 'test' require_relative '../config/environment' @@ -225,13 +224,13 @@ def rails_helper config.filter_rails_from_backtrace! end Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file } - RUBY - end + RUBY + end - def spec_helper - # Generated from rails g rspec:install - # Comments removed - <<~RUBY + def spec_helper + # Generated from rails g rspec:install + # Comments removed + <<~RUBY RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true @@ -242,8 +241,7 @@ def spec_helper end config.shared_context_metadata_behavior = :apply_to_host_groups end - RUBY - end + RUBY end end end From 0f2505e29896e39a68d2d4efe9e668801ffe01cf Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Thu, 7 Mar 2024 19:33:44 -0500 Subject: [PATCH 04/12] Keep `test` directory Deleting a directory feels like an overstep. That should be up to the consumer. --- lib/generators/suspenders/testing_generator.rb | 6 ------ test/generators/suspenders/testing_generator_test.rb | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb index 4364f1b37..0ff5af433 100644 --- a/lib/generators/suspenders/testing_generator.rb +++ b/lib/generators/suspenders/testing_generator.rb @@ -71,12 +71,6 @@ def configure_action_mailer_helpers # it manually with: ActionMailer::Base.deliveries.clear copy_file "action_mailer.rb", "spec/support/action_mailer.rb" end - - def remove_test_directory - path = Rails.root.join("test") - - FileUtils.rm_r path if File.exist? path - end end end end diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index a073a2ae8..03da74cb5 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -180,7 +180,7 @@ class TestingGeneratorTest < Rails::Generators::TestCase run_generator - assert_no_directory app_root("test") + assert_directory app_root("test") end test "has custom description" do From 9cb77654ec8392a2131b7bfa1ad31c34eca747ee Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Thu, 7 Mar 2024 19:42:52 -0500 Subject: [PATCH 05/12] Require webmock in spec_helper --- lib/generators/suspenders/testing_generator.rb | 1 + test/generators/suspenders/testing_generator_test.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb index 0ff5af433..ba4dd4557 100644 --- a/lib/generators/suspenders/testing_generator.rb +++ b/lib/generators/suspenders/testing_generator.rb @@ -42,6 +42,7 @@ def modify_spec_helper persistence_file_path + order, after: "RSpec.configure do |config|\n" + insert_into_file "spec/spec_helper.rb", "require \"webmock\/rspec\"\n\n", before: "RSpec.configure do |config|" insert_into_file "spec/spec_helper.rb", webmock_config end diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index 03da74cb5..3cb738f6d 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -57,6 +57,8 @@ class TestingGeneratorTest < Rails::Generators::TestCase test "configures spec_helper" do touch "spec/spec_helper.rb", content: spec_helper expected = <<~RUBY + require "webmock/rspec" + RSpec.configure do |config| config.example_status_persistence_file_path = "tmp/rspec_examples.txt" config.order = :random From 1ad8e3e788dd604f22f7d74c59f782bc96d045ab Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Thu, 7 Mar 2024 19:45:50 -0500 Subject: [PATCH 06/12] Install action_dispatch-testing-integration-capybara --- lib/generators/suspenders/testing_generator.rb | 3 +++ test/generators/suspenders/testing_generator_test.rb | 1 + 2 files changed, 4 insertions(+) diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb index ba4dd4557..684c14e57 100644 --- a/lib/generators/suspenders/testing_generator.rb +++ b/lib/generators/suspenders/testing_generator.rb @@ -9,6 +9,9 @@ def add_gems end gem_group :test do + gem "action_dispatch-testing-integration-capybara", + github: "thoughtbot/action_dispatch-testing-integration-capybara", tag: "v0.1.0", + require: "action_dispatch/testing/integration/capybara/rspec" gem "shoulda-matchers", "~> 6.0" gem "webdrivers" gem "webmock" diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index 3cb738f6d..f7ff83114 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -18,6 +18,7 @@ class TestingGeneratorTest < Rails::Generators::TestCase end group :test do + gem "action_dispatch-testing-integration-capybara", github: "thoughtbot/action_dispatch-testing-integration-capybara", tag: "v0.1.0", require: "action_dispatch/testing/integration/capybara/rspec" gem "shoulda-matchers", "~> 6.0" gem "webdrivers" gem "webmock" From 336eeb9edf7034aef69a8229f011e3808c19f6d1 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 8 Mar 2024 08:42:44 -0500 Subject: [PATCH 07/12] Allow additional Chrome hosts I found I needed to add these additional hosts when testing on a fresh Rails app. --- lib/generators/suspenders/testing_generator.rb | 5 ++++- test/generators/suspenders/testing_generator_test.rb | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb index 684c14e57..82e70a12f 100644 --- a/lib/generators/suspenders/testing_generator.rb +++ b/lib/generators/suspenders/testing_generator.rb @@ -37,7 +37,10 @@ def modify_spec_helper WebMock.disable_net_connect!( allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" + allow: [ + /(chromedriver|storage)\.googleapis\.com/, + "googlechromelabs.github.io", + ] ) RUBY diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index f7ff83114..ec80c7573 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -76,7 +76,10 @@ class TestingGeneratorTest < Rails::Generators::TestCase WebMock.disable_net_connect!( allow_localhost: true, - allow: "chromedriver.storage.googleapis.com" + allow: [ + /(chromedriver|storage)\.googleapis\.com/, + "googlechromelabs.github.io", + ] ) RUBY From a4c9d36b54ea8d102bfc271c397a2b96d9a25ea5 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 8 Mar 2024 09:25:03 -0500 Subject: [PATCH 08/12] Fix linting violations --- .../suspenders/testing_generator.rb | 16 +- .../suspenders/testing_generator_test.rb | 180 +++++++++--------- 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb index 82e70a12f..dbf67d404 100644 --- a/lib/generators/suspenders/testing_generator.rb +++ b/lib/generators/suspenders/testing_generator.rb @@ -35,20 +35,20 @@ def modify_spec_helper order = "\s\sconfig.order = :random\n\n" webmock_config = <<~RUBY - WebMock.disable_net_connect!( - allow_localhost: true, - allow: [ - /(chromedriver|storage)\.googleapis\.com/, - "googlechromelabs.github.io", - ] - ) + WebMock.disable_net_connect!( + allow_localhost: true, + allow: [ + /(chromedriver|storage).googleapis.com/, + "googlechromelabs.github.io", + ] + ) RUBY insert_into_file "spec/spec_helper.rb", persistence_file_path + order, after: "RSpec.configure do |config|\n" - insert_into_file "spec/spec_helper.rb", "require \"webmock\/rspec\"\n\n", before: "RSpec.configure do |config|" + insert_into_file "spec/spec_helper.rb", "require \"webmock/rspec\"\n\n", before: "RSpec.configure do |config|" insert_into_file "spec/spec_helper.rb", webmock_config end diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index ec80c7573..6be532f4f 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -13,16 +13,16 @@ class TestingGeneratorTest < Rails::Generators::TestCase test "adds gems to Gemfile" do expected = <<~RUBY - group :development, :test do - gem "rspec-rails", "~> 6.1.0" - end - - group :test do - gem "action_dispatch-testing-integration-capybara", github: "thoughtbot/action_dispatch-testing-integration-capybara", tag: "v0.1.0", require: "action_dispatch/testing/integration/capybara/rspec" - gem "shoulda-matchers", "~> 6.0" - gem "webdrivers" - gem "webmock" - end + group :development, :test do + gem "rspec-rails", "~> 6.1.0" + end + + group :test do + gem "action_dispatch-testing-integration-capybara", github: "thoughtbot/action_dispatch-testing-integration-capybara", tag: "v0.1.0", require: "action_dispatch/testing/integration/capybara/rspec" + gem "shoulda-matchers", "~> 6.0" + gem "webdrivers" + gem "webmock" + end RUBY run_generator @@ -51,36 +51,36 @@ class TestingGeneratorTest < Rails::Generators::TestCase assert_file "spec/rails_helper.rb" do |file| assert_match(/RSpec\.configure do \|config\|\s{3}config\.infer_base_class_for_anonymous_controllers\s*=\s*false/m, - file) + file) end end test "configures spec_helper" do touch "spec/spec_helper.rb", content: spec_helper expected = <<~RUBY - require "webmock/rspec" - - RSpec.configure do |config| - config.example_status_persistence_file_path = "tmp/rspec_examples.txt" - config.order = :random + require "webmock/rspec" - config.expect_with :rspec do |expectations| - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end + RSpec.configure do |config| + config.example_status_persistence_file_path = "tmp/rspec_examples.txt" + config.order = :random - config.mock_with :rspec do |mocks| - mocks.verify_partial_doubles = true - end - config.shared_context_metadata_behavior = :apply_to_host_groups + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true end - WebMock.disable_net_connect!( - allow_localhost: true, - allow: [ - /(chromedriver|storage)\.googleapis\.com/, - "googlechromelabs.github.io", - ] - ) + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + config.shared_context_metadata_behavior = :apply_to_host_groups + end + + WebMock.disable_net_connect!( + allow_localhost: true, + allow: [ + /(chromedriver|storage).googleapis.com/, + "googlechromelabs.github.io", + ] + ) RUBY run_generator @@ -92,33 +92,33 @@ class TestingGeneratorTest < Rails::Generators::TestCase test "configures Chromedriver" do expected = <<~RUBY - require "selenium/webdriver" + require "selenium/webdriver" - Capybara.register_driver :chrome do |app| - Capybara::Selenium::Driver.new(app, browser: :chrome) - end + Capybara.register_driver :chrome do |app| + Capybara::Selenium::Driver.new(app, browser: :chrome) + end - Capybara.register_driver :headless_chrome do |app| - options = ::Selenium::WebDriver::Chrome::Options.new - options.headless! - options.add_argument "--window-size=1680,1050" + Capybara.register_driver :headless_chrome do |app| + options = ::Selenium::WebDriver::Chrome::Options.new + options.headless! + options.add_argument "--window-size=1680,1050" - Capybara::Selenium::Driver.new app, - browser: :chrome, - options: options - end + Capybara::Selenium::Driver.new app, + browser: :chrome, + options: options + end - Capybara.javascript_driver = :headless_chrome + Capybara.javascript_driver = :headless_chrome - RSpec.configure do |config| - config.before(:each, type: :system) do - driven_by :rack_test - end + RSpec.configure do |config| + config.before(:each, type: :system) do + driven_by :rack_test + end - config.before(:each, type: :system, js: true) do - driven_by Capybara.javascript_driver - end + config.before(:each, type: :system, js: true) do + driven_by Capybara.javascript_driver end + end RUBY run_generator @@ -136,12 +136,12 @@ class TestingGeneratorTest < Rails::Generators::TestCase test "configures Should Matchers" do expected = <<~RUBY - Shoulda::Matchers.configure do |config| - config.integrate do |with| - with.test_framework :rspec - with.library :rails - end + Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :rails end + end RUBY run_generator @@ -153,9 +153,9 @@ class TestingGeneratorTest < Rails::Generators::TestCase test "configures i18n" do expected = <<~RUBY - RSpec.configure do |config| - config.include ActionView::Helpers::TranslationHelper - end + RSpec.configure do |config| + config.include ActionView::Helpers::TranslationHelper + end RUBY run_generator @@ -167,11 +167,11 @@ class TestingGeneratorTest < Rails::Generators::TestCase test "configures Action Mailer" do expected = <<~RUBY - RSpec.configure do |config| - config.before(:each) do - ActionMailer::Base.deliveries.clear - end + RSpec.configure do |config| + config.before(:each) do + ActionMailer::Base.deliveries.clear end + end RUBY run_generator @@ -211,25 +211,25 @@ def rails_helper # Generated from rails g rspec:install # Comments removed <<~RUBY - require 'spec_helper' - ENV['RAILS_ENV'] ||= 'test' - require_relative '../config/environment' - - abort("The Rails environment is running in production mode!") if Rails.env.production? - require 'rspec/rails' - - begin - ActiveRecord::Migration.maintain_test_schema! - rescue ActiveRecord::PendingMigrationError => e - abort e.to_s.strip - end - RSpec.configure do |config| - config.fixture_path = "#{::Rails.root}/spec/fixtures" - config.use_transactional_fixtures = true - config.infer_spec_type_from_file_location! - config.filter_rails_from_backtrace! - end - Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file } + require 'spec_helper' + ENV['RAILS_ENV'] ||= 'test' + require_relative '../config/environment' + + abort("The Rails environment is running in production mode!") if Rails.env.production? + require 'rspec/rails' + + begin + ActiveRecord::Migration.maintain_test_schema! + rescue ActiveRecord::PendingMigrationError => e + abort e.to_s.strip + end + RSpec.configure do |config| + config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.use_transactional_fixtures = true + config.infer_spec_type_from_file_location! + config.filter_rails_from_backtrace! + end + Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file } RUBY end @@ -237,16 +237,16 @@ def spec_helper # Generated from rails g rspec:install # Comments removed <<~RUBY - RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - config.mock_with :rspec do |mocks| - mocks.verify_partial_doubles = true - end - config.shared_context_metadata_behavior = :apply_to_host_groups + RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true end + config.shared_context_metadata_behavior = :apply_to_host_groups + end RUBY end end From 820c87aa379793ab88ed810575f83a01d0e5d4d2 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 8 Mar 2024 09:26:10 -0500 Subject: [PATCH 09/12] Remove obsolete test --- test/generators/suspenders/testing_generator_test.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index 6be532f4f..9419ca637 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -181,14 +181,6 @@ class TestingGeneratorTest < Rails::Generators::TestCase end end - test "removes test directory" do - mkdir "test" - - run_generator - - assert_directory app_root("test") - end - test "has custom description" do skip end From 1675ea13a529e906a57b93c4a561b4e0fa2a87f2 Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 8 Mar 2024 09:34:34 -0500 Subject: [PATCH 10/12] Update README and description --- README.md | 12 +++++++++++- lib/generators/suspenders/testing_generator.rb | 1 + test/generators/suspenders/testing_generator_test.rb | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 76fd0d14b..adf6305e9 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,17 @@ bin/rails g suspenders:email ### Testing -TODO +Set up the project for an in-depth test-driven development workflow. + +Installs and configures [rspec-rails][], +[action_dispatch-testing-integration-capybara][], [shoulda-matchers][], +[webdrivers][] and [webmock][]. + +[rspec-rails]: https://github.com/rspec/rspec-rails +[action_dispatch-testing-integration-capybara]: https://github.com/thoughtbot/action_dispatch-testing-integration-capybara +[shoulda-matchers]: https://github.com/thoughtbot/shoulda-matchers +[webdrivers]: https://github.com/titusfortner/webdrivers +[webmock]: https://github.com/bblimke/webmock ## Contributing diff --git a/lib/generators/suspenders/testing_generator.rb b/lib/generators/suspenders/testing_generator.rb index dbf67d404..73d7e909b 100644 --- a/lib/generators/suspenders/testing_generator.rb +++ b/lib/generators/suspenders/testing_generator.rb @@ -2,6 +2,7 @@ module Suspenders module Generators class TestingGenerator < Rails::Generators::Base source_root File.expand_path("../../templates/testing", __FILE__) + desc "Set up the project for an in-depth test-driven development workflow." def add_gems gem_group :development, :test do diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index 9419ca637..133e6184a 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -182,7 +182,7 @@ class TestingGeneratorTest < Rails::Generators::TestCase end test "has custom description" do - skip + assert_no_match /Description/, generator_class.desc end private From b468f329d382c6b32c1de4dd88afe17e2aa6113b Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 8 Mar 2024 09:37:13 -0500 Subject: [PATCH 11/12] Fix linting violation --- test/generators/suspenders/testing_generator_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/generators/suspenders/testing_generator_test.rb b/test/generators/suspenders/testing_generator_test.rb index 133e6184a..ff901cd7e 100644 --- a/test/generators/suspenders/testing_generator_test.rb +++ b/test/generators/suspenders/testing_generator_test.rb @@ -182,7 +182,7 @@ class TestingGeneratorTest < Rails::Generators::TestCase end test "has custom description" do - assert_no_match /Description/, generator_class.desc + assert_no_match(/Description/, generator_class.desc) end private From 2b7c5c7c25e71a5a2bac6e8fdc37b3ce81b2161f Mon Sep 17 00:00:00 2001 From: Steve Polito Date: Fri, 8 Mar 2024 09:38:42 -0500 Subject: [PATCH 12/12] Restore file --- test/generators/suspenders/rake_generator_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/generators/suspenders/rake_generator_test.rb b/test/generators/suspenders/rake_generator_test.rb index 18a8ff43a..a4c8153eb 100644 --- a/test/generators/suspenders/rake_generator_test.rb +++ b/test/generators/suspenders/rake_generator_test.rb @@ -15,7 +15,7 @@ class RakeGeneratorTest < Rails::Generators::TestCase run_generator assert_file app_root("Rakefile") do |file| - assert_match(/task default: "suspenders:rake"/, file) + assert_match /task default: "suspenders:rake"/, file end end