Commit 7108952d authored by Sanad Liaquat's avatar Sanad Liaquat

Merge branch 'qa-remote-grid' into 'master'

Allow QA to run in remote grid environments

Closes #55051

See merge request gitlab-org/gitlab-ce!23708
parents b7b7d014 7f780046
......@@ -40,34 +40,38 @@ module QA
return if Capybara.drivers.include?(:chrome)
Capybara.register_driver :chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
# This enables access to logs with `page.driver.manage.get_log(:browser)`
loggingPrefs: {
browser: "ALL",
client: "ALL",
driver: "ALL",
server: "ALL"
}
)
Capybara.register_driver QA::Runtime::Env.browser do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.send(QA::Runtime::Env.browser,
# This enables access to logs with `page.driver.manage.get_log(:browser)`
loggingPrefs: {
browser: "ALL",
client: "ALL",
driver: "ALL",
server: "ALL"
})
if QA::Runtime::Env.accept_insecure_certs?
capabilities['acceptInsecureCerts'] = true
end
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument("window-size=1240,1680")
# QA::Runtime::Env.browser.capitalize will work for every driver type except PhantomJS.
# We will have no use to use PhantomJS so this shouldn't be a problem.
options = Selenium::WebDriver.const_get(QA::Runtime::Env.browser.capitalize)::Options.new
if QA::Runtime::Env.browser == :chrome
options.add_argument("window-size=1240,1680")
# Chrome won't work properly in a Docker container in sandbox mode
options.add_argument("no-sandbox")
# Chrome won't work properly in a Docker container in sandbox mode
options.add_argument("no-sandbox")
# Run headless by default unless CHROME_HEADLESS is false
if QA::Runtime::Env.chrome_headless?
options.add_argument("headless")
# Run headless by default unless CHROME_HEADLESS is false
if QA::Runtime::Env.chrome_headless?
options.add_argument("headless")
# Chrome documentation says this flag is needed for now
# https://developers.google.com/web/updates/2017/04/headless-chrome#cli
options.add_argument("disable-gpu")
# Chrome documentation says this flag is needed for now
# https://developers.google.com/web/updates/2017/04/headless-chrome#cli
options.add_argument("disable-gpu")
end
end
# Use the same profile on QA runs if CHROME_REUSE_PROFILE is true.
......@@ -80,12 +84,18 @@ module QA
# Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab-ee/issues/4252
options.add_argument("disable-dev-shm-usage") if QA::Runtime::Env.running_in_ci?
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
selenium_options = {
browser: QA::Runtime::Env.browser,
clear_local_storage: true,
desired_capabilities: capabilities,
options: options
}
selenium_options[:url] = QA::Runtime::Env.remote_grid if QA::Runtime::Env.remote_grid
Capybara::Selenium::Driver.new(
app,
selenium_options
)
end
......@@ -93,7 +103,7 @@ module QA
Capybara::Screenshot.prune_strategy = :keep_last_run
# From https://github.com/mattheworiordan/capybara-screenshot/issues/84#issuecomment-41219326
Capybara::Screenshot.register_driver(:chrome) do |driver, path|
Capybara::Screenshot.register_driver(QA::Runtime::Env.browser) do |driver, path|
driver.browser.save_screenshot(path)
end
......@@ -102,8 +112,8 @@ module QA
end
Capybara.configure do |config|
config.default_driver = :chrome
config.javascript_driver = :chrome
config.default_driver = QA::Runtime::Env.browser
config.javascript_driver = QA::Runtime::Env.browser
config.default_max_wait_time = 10
# https://github.com/mattheworiordan/capybara-screenshot/issues/164
config.save_path = ::File.expand_path('../../tmp', __dir__)
......
......@@ -56,6 +56,34 @@ module QA
@personal_access_token ||= ENV['PERSONAL_ACCESS_TOKEN']
end
def remote_grid
# if username specified, password/auth token is required
# can be
# - "http://user:pass@somehost.com/wd/hub"
# - "https://user:pass@somehost.com:443/wd/hub"
# - "http://localhost:4444/wd/hub"
return unless ENV['QA_REMOTE_GRID']
"#{remote_grid_protocol}://#{remote_grid_credentials}#{ENV['QA_REMOTE_GRID']}/wd/hub"
end
def remote_grid_username
ENV['QA_REMOTE_GRID_USERNAME']
end
def remote_grid_access_key
ENV['QA_REMOTE_GRID_ACCESS_KEY']
end
def remote_grid_protocol
ENV['QA_REMOTE_GRID_PROTOCOL'] || 'http'
end
def browser
ENV['QA_BROWSER'].nil? ? :chrome : ENV['QA_BROWSER'].to_sym
end
def user_username
ENV['GITLAB_USERNAME']
end
......@@ -158,6 +186,16 @@ module QA
private
def remote_grid_credentials
if remote_grid_username
raise ArgumentError, %Q(Please provide an access key for user "#{remote_grid_username}") unless remote_grid_access_key
return "#{remote_grid_username}:#{remote_grid_access_key}@"
end
''
end
def enabled?(value, default: true)
return default if value.nil?
......
......@@ -207,4 +207,63 @@ describe QA::Runtime::Env do
expect { described_class.can_test? :foo }.to raise_error(ArgumentError, 'Unknown feature "foo"')
end
end
describe 'remote grid credentials' do
it 'is blank if username is empty' do
stub_env('QA_REMOTE_GRID_USERNAME', nil)
expect(described_class.send(:remote_grid_credentials)).to eq('')
end
it 'throws ArgumentError if GRID_ACCESS_KEY is not specified with USERNAME' do
stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
expect { described_class.send(:remote_grid_credentials) }.to raise_error(ArgumentError, 'Please provide an access key for user "foo"')
end
it 'returns a user:key@ combination when all args are satiated' do
stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
stub_env('QA_REMOTE_GRID_ACCESS_KEY', 'bar')
expect(described_class.send(:remote_grid_credentials)).to eq('foo:bar@')
end
end
describe '.remote_grid_protocol' do
it 'defaults protocol to http' do
stub_env('QA_REMOTE_GRID_PROTOCOL', nil)
expect(described_class.remote_grid_protocol).to eq('http')
end
end
describe '.remote_grid' do
it 'is falsey if QA_REMOTE_GRID is not set' do
expect(described_class.remote_grid).to be_falsey
end
it 'accepts https protocol' do
stub_env('QA_REMOTE_GRID', 'localhost:4444')
stub_env('QA_REMOTE_GRID_PROTOCOL', 'https')
expect(described_class.remote_grid).to eq('https://localhost:4444/wd/hub')
end
context 'with credentials' do
it 'has a grid of http://user:key@grid/wd/hub' do
stub_env('QA_REMOTE_GRID_USERNAME', 'foo')
stub_env('QA_REMOTE_GRID_ACCESS_KEY', 'bar')
stub_env('QA_REMOTE_GRID', 'localhost:4444')
expect(described_class.remote_grid).to eq('http://foo:bar@localhost:4444/wd/hub')
end
end
context 'without credentials' do
it 'has a grid of http://grid/wd/hub' do
stub_env('QA_REMOTE_GRID', 'localhost:4444')
expect(described_class.remote_grid).to eq('http://localhost:4444/wd/hub')
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment