I'm trying to setup my Rails application with Docker. I'm having difficulties with the system tests that I'm trying to run in the Docker container.
I've setup a Selenium container which tries to open a website on http://0.0.0.0:3005 but cannot connect. I want Capybara to connect to a remote server by changing the IP address on which it needs to connect but it's not succeeding.
Here's my Docker compose file:
# docker-compose.yml
version: '3'
services:
postgres:
image: postgres:10.3-alpine
volumes:
- ./tmp/db:/var/lib/postgresql/data
redis:
image: redis:4.0.5-alpine
command: redis-server
hostname: redis
volumes:
- ./tmp/redis:/var/lib/redis/data
app:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
hostname: bumblebee-web
depends_on:
- postgres
- redis
ports:
- 3000:3000
volumes:
- .:/app
environment:
- RAILS_LOG_TO_STDOUT=true
tty: true
sidekiq:
depends_on:
- postgres
- redis
build: .
command: bundle exec sidekiq -C config/sidekiq.yml
volumes:
- .:/app
# Test containers
test:
build: .
env_file:
- .env.test
ports:
- 3005:3005 # Capybara listens here
links:
- postgres
- selenium
volumes:
- .:/app
command: bin/spring server
environment:
TEST_APP_HOST: test
TEST_APP_PORT: 3005
SELENIUM_HOST: selenium
RAILS_ENV: test
DOCKER: 'true'
networks:
default:
aliases:
- test
selenium:
image: selenium/standalone-chrome-debug
ports:
- 4444:4444
- 5900:5900
logging:
driver: none
This is my RSpec Rails helper configuration
# rails_helper.rb
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!
config.include Devise::Test::ControllerHelpers, type: :controller
config.before(:each, type: :system, js: true) do
if YAML.safe_load(ENV["DOCKER"])
driven_by :selenium_remote
host! "http://#{Capybara.server_host}:#{Capybara.server_port}"
else
driven_by :headless_chrome
end
end
end
if YAML.safe_load(ENV["DOCKER"])
selenium_url = "http://selenium:4444/wd/hub"
Capybara.register_driver :selenium_remote do |app|
Capybara::Selenium::Driver.new(
app,
url: selenium_url,
browser: :remote,
desired_capabilities: :chrome
)
end
Capybara.run_server = false
Capybara.server_host = ENV['TEST_APP_HOST']
Capybara.server_port = ENV['TEST_APP_PORT']
Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}"
else
Capybara.register_driver(:headless_chrome) do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[headless disable-gpu window-size=1920,1080] }
)
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: capabilities,
)
end
Capybara.javascript_driver = :headless_chrome
end
I've connect with VNC to the selenium Docker container and made a screenshot of the page that it's opening. I've attached the screenshot.
I've tried getting the IP address of the test container and entering it manualy but nothing seems to help.
To be sure I have given everything that I use to run the test here is the command that I'm using:
docker-compose run test bin/rspec spec/feature/compositions/composition_multi_delete_spec.rb
And the test RSpec file:
# spec/feature/compositions/composition_multi_delete_spec.rb
require 'rails_helper'
include Warden::Test::Helpers
feature "Multi delete of compositions" do
let(:group) { FactoryBot.create :private_group }
let(:user) { FactoryBot.create :user }
let(:composition) { FactoryBot.create :composition, :filled, user: user, group: group }
before do
composition
login_as user, scope: :user
end
scenario "is expected to work and remove the composition", type: :system, js: true do
composition
visit compositions_path
click_on "Edit compositions"
find("#composition-#{composition.id}").click
click_on "Delete items"
page.driver.browser.switch_to.alert.accept
expect(page).to_not have_content composition.name
visit compositions_path
expect(page).to_not have_content composition.name
end
scenario "is expected to preserve the search scope after delete", type: :system, js: true do
visit compositions_path scope: "all"
click_on "Edit compositions"
find("#composition-#{composition.id}").click
click_on "Delete items"
page.driver.browser.switch_to.alert.accept
# because of DB deadlock issue added sleep
sleep 0.2
expect(page).to have_current_path '/compositions?scope=all'
end
end
Any help or advice is welcome!
