Note: This is for issues with Capybara. If you have a howto type question, please ask on the mailing list as requested in the README: http://groups.google.com/group/ruby-capybara
Capybara Version:
gem 'capybara', '~> 2.7', '>= 2.7.1'
Driver Information (and browser if relevant):
(Session info: chrome=61.0.3163.79)
(Driver info: chromedriver=2.32.498537 (cb2f855cbc7b82e20387eaf9a43f6b99b6105061),platform=Mac OS X 10.12.6 x86_64)
Chrome should operate in a headless mode.
The GUI is being displayed.
Here is my current code. Please let me know if it's a mistake on my part. I'm pretty baffled. I'm just now switching from Poltergeist, however I've done my research before creating an issue.
Capybara.register_driver(:headless_chrome) do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[no-sandbox headless disable-gpu] }
)
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: capabilities
)
end
Capybara.javascript_driver = :headless_chrome
The above code is in my test_helper.rb file and in the class Capybara::Rails::TestCase. In the system tests, the driver is set pretty much like so:
require 'test_helper'
require 'support/my_helper'
class MyFeatureTest < Capybara::Rails::TestCase
include MyHelper
feature 'MyFeatureTest' do
let(:fixture) { users(:the_user) }
before(:each) do
Capybara.current_driver = :headless_chrome
feature_sign_in(fixture)
end
describe 'when I attempt to execute my test' do
it 'should execute with chrome headless' do
execute_headless_chrome
end
end
end
private
def execute_headless_chrome
puts 'Method code here for example.'
end
end
Any help is greatly appreciated. I know this is most likely NOT a Capybara issue, but I figured this was a good place to start with the knowledge base here.
Thank you in advance.
Firstly, the gem spec doesn't tell us what version of Capybara you're actually using (only that it's 2.x and > 2.7.1). If you are using the latest Capybara try specifying :selenium_chrome_headless as your driver - https://github.com/teamcapybara/capybara/blob/master/lib/capybara.rb#L489 - and see if that works.
Beyond that, it's tough to tell, from your example, exactly what you're using for testing. You mention "system tests" but specify "feature", you appear to possibly be using RSpec but are deriving from 'Capybara::Rails::TestCase' ???
Not using RSpec. We're using the most up to date version of Capybara.
We're using Minitest. The class inheritance is to maintain one test_helper.rb file for DatabaseCleaner and switching between transactional and truncation.
Here is a list of relevant gem files in the test_helper.rb file:
require 'fileutils'
require 'rails/test_help'
require 'webmock/minitest'
require 'mocha/mini_test'
require 'time_mixin'
require 'minitest/rails/capybara'
require 'vcr_helper'
require 'minitest/ci'
require 'capybara/poltergeist'
require 'database_cleaner'
require 'selenium/webdriver'
AH - you're using the minitest_rails_capybara spec DSL - which makes minitest look like RSpec - that explains my confusion. Did using the built-in driver registration :selenium_chrome_headless, rather than your own registration, run in headless mode?
It did not. I did as follows:
Capybara.register_driver(:selenium_chrome_headless) do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w(no-sandbox headless disable-gpu) }
)
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: capabilities
)
end
Capybara.javascript_driver = :selenium_chrome_headless
I also changed the Capybara.current_driver = :selenium_chrome_headless inside the tests.
Is it because I'm running on a Mac and Macs' no longer have X window? It was my understanding Chrome no longer needed X window to run headless, but maybe I'm wrong here?
@TheJayWright No -- don't change the name you're registering -- just specify :selenium_chrome_headless wherever you're setting javascript_driver' andcurrent_driver`. Capybara already registers it, and it works fine for Capybaras headless tests. All you've done there is overwrite what Capybara registered with what we know already doesn't work.
Note: I'm not sure why you're specifying current_driver in your before, I believer the usual way of doing that with minitest_capybara_rails would be to set javascript_driver, add js: true metadata to the specific test, and call super first in your before block so the default behavior from the Capybara::Rails::TestCase class would set the driver.
It has nothing to do with being on a Mac, Chrome on a Mac doesn't use X windows - Are you sure your tests are written correctly? All the examples for the minitest_capybara_rails gems show that you don't need to derive an outer class from Capybara::Rails::TestCase when using the spec DSL (feature/describe/etc). They only do that when not using the spec DSL.
The test_helper.rb was already written this way when I started here, however I know that it's deriving correctly from the class and that shouldn't be affecting Chrome launching headless or not. Also, I was under the impression that the js: true only worked on RSpec. I'm specifying current driver because in my teardown I have it resetting to default driver which is the rake driver for the unit tests.
def after_teardown
super
Capybara.reset_sessions!
Capybara.use_default_driver
DatabaseCleaner.clean
self.use_transactional_fixtures = true
DatabaseCleaner.strategy = :transaction
end
When I changed the name as you suggested without changing the browser I registered, I received the following error:
Capybara::DriverNotFoundError: no driver called :selenium_chrome_headless was found, available drivers: :rack_test, :selenium, :poltergeist, :headless_chrome
@TheJayWright Then you're not using the latest Capybara (as claimed)
As far as the js: true - I'm basing my info on the README of the gem you claim to be using - https://github.com/blowmage/minitest-rails-capybara#specifying-drivers - which also handles calling reset_sessions! and use_default_driver in it's base class when you call super - assuming you've configured it correctly - https://github.com/blowmage/minitest-rails-capybara/blob/master/lib/minitest/rails/capybara.rb#L42
Yes, we are. We do not have Capybara version locked in our Gemfile.
gem 'minitest-rails-capybara'
gem 'capybara'
@TheJayWright If you were, it would be defined - just because you haven't locked it in your Gemfile, doesn't mean you've updated - or that some other gem you're using isn't preventing it from installing the latest. That's exactly why I asked what version you were using - and you told me "most up to date" - which is obviously not true.
Apparently you are correct as for some reason our capybara gem will not update above 2.14.4.
Could this be due to ruby/rails version?
We're using Ruby 2.3.3 and Rails 4.2 currently.
Nope -- look in your Gemfile.lock and see what is requiring that - or specify ~>2.15 in your Gemfile and see what error it raises when you try to install
Fetching gem metadata from https://rubygems.org/.......
Fetching gem metadata from https://rubygems.org/.......
Fetching gem metadata from https://rubygems.org/...
You have requested:
capybara ~> 2.15
The bundle currently has capybara locked at 2.14.4.
Try running `bundle update capybara`
If you are updating multiple gems in your Gemfile at once,
try passing them all to `bundle update`
It is minitest-capybara...
minitest-capybara (0.8.2)
capybara (~> 2.2)
minitest (~> 5.0)
rake
Actually, it's Poltergeist I believe, which I would no longer need.
I removed poltergeist, but it still doesn't want to update. The only other dependencies version locking Capybara in the Gemfile.lock file is the following:
minitest-capybara (0.8.2)
capybara (~> 2.2)
minitest-rails-capybara (2.1.2)
capybara (~> 2.7)
md5-f68d8a024efe06c87de255b86fce078f
poltergeist (1.15.0)
capybara (~> 2.1)
So it seems that taking my original example and doing the following got me a lot closer and did clean up the code.
require 'test_helper'
require 'support/my_helper'
class MyFeatureTest < Capybara::Rails::TestCase
include MyHelper
feature 'MyFeatureTest' do
let(:fixture) { users(:the_user) }
before(:each) do
feature_sign_in(fixture)
end
describe 'when I attempt to execute my test' do
it 'should execute with chrome headless', js: true do
execute_headless_chrome
end
end
end
private
def execute_headless_chrome
puts 'Method code here for example.'
end
end
Capybara::DriverNotFoundError: no driver called :selenium_chrome_headless was found, available drivers: :rack_test, :selenium, :headless_chrome
still occurs, so I need to find the dependency keeping me from upgrading Capybara and running headless.
Thanks for your help.
Do you have capybara-webkit in your Gemfile, if so remove it since it will lock you at 2.14.x. If not you need to look in your Gemfile.lock for an instance of capybara with a version like 2.14.< 2.15. Versions that look like ~> 2.7 are fine since it means 2.x where x >= 7. Another option is to specify ~> 2.15 for Capybara in your Gemfile and then do a full gems update -- that should tell you what gems are conflicting (and then you can back to your previous commit if you don't actually want all gems updated). - anyway, closing this because it doesn't seem to be a Capybara issue
Also, if I'm reading the minitest-rails-capybara gems README and code correctly your test should just be written as
require 'test_helper'
require 'support/my_helper'
feature 'MyFeatureTest' do
include MyHelper
let(:fixture) { users(:the_user) }
before(:each) do
feature_sign_in(fixture)
end
describe 'when I attempt to execute my test' do
it 'should execute with chrome headless', js: true do
execute_headless_chrome
end
end
end
private
def execute_headless_chrome
puts 'Method code here for example.'
end
I was able to update Capybara and now am running headless. We have to inherit the class because of the way our test_helper is laid out with other classes because of database_cleaner. It needs to be recoded honestly, but at the moment that's the way it's setup.
@TheJayWright feature does inherit - It's just done via the registered spec type - https://github.com/blowmage/minitest-rails-capybara/blob/master/lib/minitest/rails/capybara.rb#L23
It appears In your case you are creating a class inside a class both of which derive from Capybara::Rails::TestCase - but I guess if its working then its working.
@twalpole This may give you a better idea why we're doing it that way with the classes in test_helper.
class ActiveSupport::TestCase
include Cannable
ActiveRecord::Migration.check_pending!
fixtures :all
def setup
unless is_a?(Capybara::Rails::TestCase)
self.use_transactional_fixtures = true
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.start
end
end
def teardown
DatabaseCleaner.clean unless is_a?(Capybara::Rails::TestCase)
end
Then we have common methods we use throughout our unit tests, then we call this class to override setup and teardown for Capybara browser testing.
class Capybara::Rails::TestCase
def before_setup
# Causes loading of *ALL* fixtures before every test
# sorry if it's slow, but that's the way it has to be.
self.use_transactional_fixtures = false
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.start
super
end
Minitest::Reporters.use! [Minitest::Reporters::PrideReporter.new(slow_count: 5)]
# Capybara.register_driver :poltergeist do |app|
# options = {
# phantomjs_options: [
# '--load-images=false',
# '--ignore-ssl-errors=true'
# ]
# }
# Capybara::Poltergeist::Driver.new(app, options)
# end
#
# Capybara.javascript_driver = :poltergeist
Capybara.register_driver(:chrome) do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome)
end
Capybara.register_driver(:headless_chrome) do |app|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w(headless disable-gpu) }
)
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: caps
)
end
Capybara.javascript_driver = :headless_chrome
def after_teardown
super
Capybara.reset_sessions!
Capybara.use_default_driver
DatabaseCleaner.clean
self.use_transactional_fixtures = true
DatabaseCleaner.strategy = :transaction
end
end
@TheJayWright Yes but the line feature "MyFeatureTest" do .. becomes describe "MyFeatureTest Feature Test" do ... which due to the minitest registered spec type basically becomes 'ATestClass < Capybara::Rails::TestCase ...` so you are ending up with two nested classes each derived from Capybara::Rails::TestCase
class MyFeatureTest < Capybara::Rails::TestCase
...
class MyFeatureTestBlah < Capybara::Rails::TestCase # this is what feature 'MyFeatureTest' basically becomes
...
end
end
Maybe there is a subtlety here I'm missing but it seems like the outer class definition is extraneous - anyway if it's working go with it.
I understand what you're saying. Myself and another developer are going through test_helper today to get this cleaned up. Thank you for your help yesterday. Greatly appreciated.
I am also getting the same error
Capybara::DriverNotFoundError:
no driver called :selenium_cfhrome_headless was found, available drivers: :rack_test, :selenium, :selenium_chrome, :selenium_chrome_headless, :poltergeist, :webkit, :webkit_debug
In my Gem File
ruby '2.5.1'
gem 'rails', ~> 5.2.0
group :test do
gem 'poltergeist'
gem 'phantomjs', :require => 'phantomjs/poltergeist'
gem 'simplecov', require: false
gem 'rspec-rails', ~> 3.8
gem 'capybara', '>= 2.15', '< 4.0'
gem 'selenium-webdriver'
gem 'chromedriver-helper'
gem 'capybara-webkit'
gem 'factory_bot_rails'
gem 'faker'
gem 'database_cleaner'
end
If you find any fix for it, please share me. Thanks
@laddhadhiraj - Note the typo in your error message.
Most helpful comment
It did not. I did as follows:
I also changed the
Capybara.current_driver = :selenium_chrome_headlessinside the tests.