Skip to content

Commit

Permalink
Introduce suspenders:testing generator (#1156)
Browse files Browse the repository at this point in the history
Set up projects 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

## Details

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.

```ruby
#spec/spec_helper.rb
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/,
    "googlechromelabs.github.io",
  ]
)
```

The only thing that differs from the existing `spec/rails_helper.rb` configuration is:

```ruby
config.infer_base_class_for_anonymous_controllers = false
```

```ruby
# spec/support/chromedriver.rb

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
# spec/support/shoulda_matchers.rb

Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end
```

```ruby
# spec/support/i18n.rb

RSpec.configure do |config|
  config.include ActionView::Helpers::TranslationHelper
end
```

```ruby
# spec/support/action_mailer.rb

RSpec.configure do |config|
  config.before(:each) do
    ActionMailer::Base.deliveries.clear
  end
end
```

## Notable changes

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.

[formulaic]: https://github.com/calebhearth/formulaic
  • Loading branch information
stevepolitodesign committed May 10, 2024
1 parent 95325e2 commit 762faaa
Show file tree
Hide file tree
Showing 8 changed files with 386 additions and 0 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ Configures `default_url_options` in `test` and `development`.
bin/rails g suspenders:email
```

### Testing

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

See the [CONTRIBUTING] document.
Expand Down
84 changes: 84 additions & 0 deletions lib/generators/suspenders/testing_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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
gem "rspec-rails", "~> 6.1.0"
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"
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/,
"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", 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
end
end
end
5 changes: 5 additions & 0 deletions lib/generators/templates/testing/action_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
RSpec.configure do |config|
config.before(:each) do
ActionMailer::Base.deliveries.clear
end
end
27 changes: 27 additions & 0 deletions lib/generators/templates/testing/chromedriver.rb
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions lib/generators/templates/testing/i18n.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
RSpec.configure do |config|
config.include ActionView::Helpers::TranslationHelper
end
6 changes: 6 additions & 0 deletions lib/generators/templates/testing/shoulda_matchers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
Loading

0 comments on commit 762faaa

Please sign in to comment.