Capybara throwing error "undefined method `needs_server?' for :selenium_headless_in_container:Symbol"
nathanhamilton opened this issue · comments
Error Summary
I have a Docker container where I am trying to run Capybara using Selenium and when I run the tests, it throws the following error:
NoMethodError:
undefined method `needs_server?' for :selenium_headless_in_container:Symbol
# /usr/local/rvm/gems/ruby-3.2.2/gems/capybara-3.40.0/lib/capybara/session.rb:92:in `initialize'
# /usr/local/rvm/gems/ruby-3.2.2/gems/capybara-3.40.0/lib/capybara.rb:422:in `new'
# /usr/local/rvm/gems/ruby-3.2.2/gems/capybara-3.40.0/lib/capybara.rb:422:in `block in session_pool'
# /usr/local/rvm/gems/ruby-3.2.2/gems/capybara-3.40.0/lib/capybara.rb:317:in `current_session'
# /usr/local/rvm/gems/ruby-3.2.2/gems/capybara-3.40.0/lib/capybara/dsl.rb:46:in `page'
# /usr/local/rvm/gems/ruby-3.2.2/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `visit'
# ./spec/system/degree_management_spec.rb:104:in `block (2 levels) in <main>'
Current System Specs
Here are the current specs of what I'm running:
Ruby Version: 3.2.2
Rails Version: 6.1.7.7
Puma Version: 6.4.2
capybara Version: 3.40.0
capybara-lockstep version: 2.2.0
selenium-webdriver version: 4.17.0
Selenium Docker Image: selenium/standalone-chrome:120.0.6099.224-chromedriver-120.0.6099.109-grid-4.17.0-20240123
Local System Setup
Here is the configuration I have:
spec/support/capybara.rb
require_relative './ip'
Capybara.register_driver :selenium_headless_in_container do |app|
options = Selenium::WebDriver::Options.chrome
options.add_argument('--headless=new')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--window-size=1400,1400')
options.add_argument('--ignore-certificate-errors')
desired_capabilities = Selenium::WebDriver::Remote::Capabilities.new
desired_capabilities.browser_name = 'chrome'
desired_capabilities.accept_insecure_certs = true
url = 'http://selenium-chrome:4444/wd/hub'
Selenium::WebDriver.logger.level = :debug # Use this if you need to debug the selenium driver
Capybara::Selenium::Driver.new(
app,
browser: :remote,
options: options,
caps: desired_capabilities,
url: url
)
Capybara.javascript_driver = :selenium_headless_in_container
end
spec/rails_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'capybara/rspec'
require 'rspec/rails'
require 'selenium-webdriver'
require 'support/capybara'
require 'factory_bot'
require 'spec_helper'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
FactoryBot::SyntaxRunner.class_eval do
include ActionDispatch::TestProcess
include ActiveSupport::Testing::FileFixtures
end
RSpec.configure do |config|
config.include ActionDispatch::TestProcess
config.include Capybara::DSL
config.mock_with :rspec
config.use_transactional_fixtures = false
config.infer_base_class_for_anonymous_controllers = false
config.order = 'random'
config.include FactoryBot::Syntax::Methods
config.raise_errors_for_deprecations!
config.filter_run focus: true
config.run_all_when_everything_filtered = true
config.file_fixture_path = File.expand_path('./fixtures', __dir__)
config.before(:each, type: :system) do
driven_by :rack_test
end
config.before(:each, type: :system, js: true) do
Capybara.default_max_wait_time = 300
Capybara.server_host = '0.0.0.0'
Capybara.server_port = 4000
Capybara.app_host = "http://test:4000"
driven_by :selenium_headless_in_container
end
end
def test_element(name)
find test_selector(name)
end
def test_selector(name)
"[data-test=\"#{name}\"]"
end
def clear_input(selector)
first("#{selector} svg").click
end
build/docker-compose.yml
version: '3.5'
services:
test:
stdin_open: true
tty: true
build:
context: ../.
args:
environment: 'test'
dockerfile: build/ubuntu.Dockerfile
target: build-test
command: bin/bundle exec bin/rspec --format documentation
depends_on:
- postgres
- selenium
- selenium-chrome
env_file:
- ../.env
environment:
DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL: 'true'
DATABASE_HOST: postgres
DATABASE_URL: postgres://root:@postgres:5432/app_test
EXECJS_RUNTIME: Node
RAILS_ENV: test
restart: "no"
networks:
dev_testing_net:
ipv4_address: 172.20.1.208
internal:
extra_hosts:
- rabbitmq:172.20.1.2
- passport-test.lumerit.com:172.20.1.3
- dashboard.test:172.20.1.4
- app.test:172.20.1.208
- selenium:172.20.1.178
- selenium_chrome:172.20.1.220
volumes:
- ..:/app:cached
- '../certs/app.crt:/certs/app.crt:ro'
- '../certs/app.key:/certs/app.key:ro'
ports:
- "4000:4000"
"selenium-chrome":
image: selenium/standalone-chrome:120.0.6099.224-chromedriver-120.0.6099.109-grid-4.17.0-20240123
container_name: selenium-chrome
networks:
dev_testing_net:
ipv4_address: 172.20.1.220
internal:
volumes:
- /dev/shm:/dev/shm
ports:
- "4444:4444"
selenium:
build:
context: ../.
dockerfile: build/selenium.Dockerfile
container_name: selenium
volumes:
- /dev/shm:/dev/shm
- '../.ca-certificates/certificate.crt:/usr/local/share/ca-certificates/certificate.crt'
networks:
dev_testing_net:
ipv4_address: 172.20.1.178
internal:
# ports:
# - "4444:4444"
postgres:
image: postgres:9.6
environment:
POSTGRES_DB: 'app_test'
POSTGRES_USER: 'root'
POSTGRES_HOST_AUTH_METHOD: trust
networks:
internal:
networks:
internal:
dev_testing_net:
external: true
name: dev_testing
Steps to reproduce
This is the command that I am running to execute the javascript tests using capybara
docker-compose run --rm --service-ports --use-aliases -e RAILS_ENV=test test /bin/bash -l -c "sleep 1 && bundle exec rails db:migrate && bundle exec rspec --tag js --fail-fast --format documentation"
However, when the tests are being executed, I get the above error. From my perspective, everything has been setup as Capybara has noted in the documentation, but It seems Capybara isn't recognizing the driver.
Turns out I had the config Capybara.javascript_driver = :selenium_headless_in_container
inside the Capybara.register_driver
block. Once outside, it executed successfully.