Skip to content

Commit ade9a17

Browse files
committed
Migrate feature specs to system specs
System tests are natively supported by Rails and come with nice features, such as automatic screenshots in case of failures. Since a few years already, Rspec recommends system specs over feature specs.
1 parent e969d28 commit ade9a17

16 files changed

Lines changed: 89 additions & 36 deletions

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ jobs:
9595
with:
9696
token: ${{ secrets.CODECOV_TOKEN }}
9797

98+
- name: Keep screenshots from failed system specs
99+
uses: actions/upload-artifact@v4
100+
if: failure()
101+
with:
102+
name: screenshots
103+
path: ${{ github.workspace }}/tmp/screenshots
104+
if-no-files-found: ignore
105+
98106
lint:
99107
runs-on: ubuntu-latest
100108

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ group :test do
8787
gem 'capybara'
8888
gem 'database_cleaner'
8989
gem 'factory_bot_rails'
90-
gem 'headless'
9190
gem 'pundit-matchers'
9291
gem 'rails-controller-testing'
9392
gem 'rspec-collection_matchers'

Gemfile.lock

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ GEM
183183
hana (1.3.7)
184184
hashdiff (1.1.1)
185185
hashie (5.0.0)
186-
headless (2.3.1)
187186
highline (3.1.1)
188187
reline
189188
http_accept_language (2.1.1)
@@ -616,7 +615,6 @@ DEPENDENCIES
616615
devise-bootstrap-views
617616
factory_bot_rails
618617
faraday
619-
headless
620618
http_accept_language
621619
i18n-js
622620
i18n-tasks

docs/environment_variables.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ The following environment variables are specifically support in CodeHarbor and a
2323
| `BACKTRACE` | `false` | Enables more verbose log output from framework code during debugging |
2424
| `TRUSTED_IP` | ` ` in `development` | Enables `BetterErrors` for the given IP addresses during development |
2525
| `LISTEN_ADDRESS` | `127.0.0.1` in `development` | Specifies the IP address the Vagrant VM server should attach to during development |
26-
| `HEADLESS_TEST` | `false` | Enables the test environment to work without a window manager for feature tests (e.g., using Vagrant) |
26+
| `HEADLESS` | `false` | Enables the test environment to work without a window manager for feature tests (e.g., using Vagrant) |
27+
| `BROWSER` | `chrome` | Specifies the browser to be used for system tests. Supported are `chrome` or `firefox` |

spec/support/authentication.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ def sign_in_with_js_driver(user, password)
1515
end
1616

1717
RSpec.configure do |config|
18-
config.include Authentication, type: :feature
18+
config.include Authentication, type: :system
1919
end

spec/support/capybara.rb

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.configure do |config|
4+
config.before(:suite) do
5+
# Adjust the save path for screenshots. These are also uploaded as artifacts in GitHub actions.
6+
Capybara.save_path = Rails.root.join('tmp/screenshots')
7+
8+
# Clean up the save path with old assets before running the test suite.
9+
FileUtils.rm_rf(Dir.glob("#{Capybara.save_path}/*"))
10+
end
11+
12+
config.before(:each, type: :system) do
13+
# rack_test by default, for performance
14+
driven_by :rack_test
15+
end
16+
17+
config.before(:each, type: :system, js: true) do
18+
# Selenium when we need JavaScript
19+
driven_by :selenium, using: :"#{display_mode}#{browser}", &send(:"#{browser}_options")
20+
end
21+
22+
private
23+
24+
def mac_os?
25+
Gem::Platform.local.os == 'darwin'
26+
end
27+
28+
def browser
29+
return @browser if defined?(@browser)
30+
# Vagrant currently supports Firefox only.
31+
return @browser = 'firefox' if ENV.fetch('USER', nil) == 'vagrant'
32+
33+
case ENV.fetch('BROWSER', 'chrome')
34+
when /^chrom(e|ium)$/i
35+
@browser = 'chrome'
36+
when /^(firefox|iceweasel|gecko)$/i
37+
@browser = 'firefox'
38+
end
39+
end
40+
41+
def display_mode
42+
return @display_mode if defined?(@display_mode)
43+
44+
if enabled?('CI') || enabled?('HEADLESS') || ENV.fetch('USER', nil) == 'vagrant'
45+
@display_mode = 'headless_'
46+
else
47+
@display_mode = ''
48+
end
49+
end
50+
51+
def enabled?(env_key, default_value = '0')
52+
%w[0 n no off false f].exclude?(ENV.fetch(env_key, default_value).downcase)
53+
end
54+
55+
def chrome_options
56+
lambda {|driver_options|
57+
# Since Chrome 127, the browser will prompt the user to choose a search engine.
58+
driver_options.add_argument('disable-search-engine-choice-screen')
59+
# We need to sync the browser's locale with the one used by the testing framework.
60+
driver_options.add_argument("accept-lang=#{I18n.locale}")
61+
}
62+
end
63+
64+
def firefox_options
65+
lambda {|driver_options|
66+
# We need to sync the browser's locale with the one used by the testing framework.
67+
driver_options.add_preference('intl.accept_languages', I18n.locale)
68+
}
69+
end
70+
end

spec/support/database_cleaner.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
DatabaseCleaner.strategy = example.metadata[:cleaning_strategy] || :transaction
2727
end
2828

29-
config.before(:each, type: :feature) do
29+
config.before(:each, type: :system) do
3030
# :rack_test driver's Rack app under test shares database connection
3131
# with the specs, so continue to use transaction strategy for speed.
3232
unless Capybara.current_driver == :rack_test

spec/support/selenium.rb

Lines changed: 0 additions & 26 deletions
This file was deleted.

spec/support/wait_for_ajax.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ def ajax_requests_finished?
1313
end
1414

1515
RSpec.configure do |config|
16-
config.include WaitForAjax, type: :feature
16+
config.include WaitForAjax, type: :system
1717
end
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
context 'with invalid credentials' do
2727
it 'does not allow to sign in' do
2828
click_link(I18n.t('common.button.log_in')) # rubocop:disable Capybara/ClickLinkOrButtonStyle
29-
fill_in('Email', with: user.email)
30-
fill_in('Password', with: password.reverse)
29+
fill_in(:user_email, with: user.email)
30+
fill_in(:user_password, with: password.reverse)
3131
click_button(I18n.t('common.button.log_in')) # rubocop:disable Capybara/ClickLinkOrButtonStyle
3232
expect(page).to have_content(I18n.t('devise.failure.invalid', authentication_keys: 'Email'))
3333
end

0 commit comments

Comments
 (0)