Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-19 06:08:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-19 06:08:33 +0300
commit2ea638391497c495798e0bab7c704af112789299 (patch)
tree55dedad2513c731b127e11622134f1791a87cfb0 /qa
parent8c80b21468c5c969644c9ea83fec7b43dba1eb3c (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'qa')
-rw-r--r--qa/Gemfile2
-rw-r--r--qa/Gemfile.lock4
-rw-r--r--qa/qa/ce/strategy.rb3
-rw-r--r--qa/qa/page/admin/applications.rb70
-rw-r--r--qa/qa/page/admin/menu.rb4
-rw-r--r--qa/qa/page/base.rb2
-rw-r--r--qa/qa/page/main/login.rb10
-rw-r--r--qa/qa/page/main/menu.rb18
-rw-r--r--qa/qa/page/profile/menu.rb4
-rw-r--r--qa/qa/page/project/issue/show.rb4
-rw-r--r--qa/qa/page/project/show.rb4
-rw-r--r--qa/qa/page/sub_menus/common.rb4
-rw-r--r--qa/qa/resource/instance_oauth_application.rb49
-rw-r--r--qa/qa/runtime/browser.rb44
-rw-r--r--qa/qa/runtime/env.rb46
-rw-r--r--qa/qa/service/docker_run/base.rb4
-rw-r--r--qa/qa/service/docker_run/gitlab.rb35
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb113
-rw-r--r--qa/qa/specs/spec_helper.rb2
-rw-r--r--qa/qa/tools/test_resources_handler.rb1
20 files changed, 392 insertions, 31 deletions
diff --git a/qa/Gemfile b/qa/Gemfile
index cd28fd0f0ae..4f138efd06c 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -18,7 +18,7 @@ gem 'faker', '~> 3.2'
gem 'knapsack', '~> 4.0'
gem 'parallel_tests', '~> 4.2'
gem 'rotp', '~> 6.2.2'
-gem 'parallel', '~> 1.22', '>= 1.22.1'
+gem 'parallel', '~> 1.23'
gem 'rainbow', '~> 3.1.1'
gem 'rspec-parameterized', '~> 1.0.0'
gem 'octokit', '~> 6.1.1'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index b646afd665d..ce37fee0ad4 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -189,7 +189,7 @@ GEM
sawyer (~> 0.9)
oj (3.13.23)
os (1.1.4)
- parallel (1.22.1)
+ parallel (1.23.0)
parallel_tests (4.2.0)
parallel
parser (3.1.3.0)
@@ -323,7 +323,7 @@ DEPENDENCIES
knapsack (~> 4.0)
nokogiri (~> 1.14, >= 1.14.3)
octokit (~> 6.1.1)
- parallel (~> 1.22, >= 1.22.1)
+ parallel (~> 1.23)
parallel_tests (~> 4.2)
pry-byebug (~> 3.10.1)
rainbow (~> 3.1.1)
diff --git a/qa/qa/ce/strategy.rb b/qa/qa/ce/strategy.rb
index 8143595a18b..2587da17739 100644
--- a/qa/qa/ce/strategy.rb
+++ b/qa/qa/ce/strategy.rb
@@ -16,6 +16,9 @@ module QA
QA::Runtime::Env.personal_access_token)
end
+ QA::Runtime::Logger.info("Browser: #{QA::Runtime::Env.browser}")
+ QA::Runtime::Logger.info("Browser version: #{QA::Runtime::Env.browser_version}")
+
# The login page could take some time to load the first time it is visited.
# We visit the login page and wait for it to properly load only once before the tests.
QA::Runtime::Logger.info("Performing sanity check for environment!")
diff --git a/qa/qa/page/admin/applications.rb b/qa/qa/page/admin/applications.rb
new file mode 100644
index 00000000000..56880a4b22c
--- /dev/null
+++ b/qa/qa/page/admin/applications.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ class Applications < Page::Base
+ view 'app/views/admin/applications/index.html.haml' do
+ element :new_application_button
+ end
+
+ view 'app/views/admin/applications/_form.html.haml' do
+ element :name_field
+ element :redirect_uri_field
+ element :trusted_checkbox
+ element :save_application_button
+ end
+
+ view 'app/views/shared/tokens/_scopes_form.html.haml' do
+ element :api_label, '#{scope}_label' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
+ end
+
+ view 'app/views/shared/doorkeeper/applications/_show.html.haml' do
+ element :application_id_field
+ element :id_of_application_field
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue' do
+ element :clipboard_button
+ end
+
+ def click_new_application_button
+ click_element :new_application_button
+ end
+
+ def fill_name(name)
+ fill_element :name_field, name
+ end
+
+ def fill_redirect_uri(redirect_uri)
+ fill_element :redirect_uri_field, redirect_uri
+ end
+
+ def set_trusted_checkbox(value)
+ check_element :trusted_checkbox, value
+ end
+
+ def set_scope(scope)
+ click_element "#{scope}_label".to_sym
+ end
+
+ def save_application
+ click_element :save_application_button
+ end
+
+ def get_secret_id
+ find_element(:clipboard_button)['data-clipboard-text']
+ end
+
+ def get_application_id
+ find_element(:application_id_field).value
+ end
+
+ # Returns the ID of the resource
+ def get_id_of_application
+ find_element(:id_of_application_field, visible: false).value
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb
index dc6fbb6c081..6ef59e118fb 100644
--- a/qa/qa/page/admin/menu.rb
+++ b/qa/qa/page/admin/menu.rb
@@ -67,6 +67,10 @@ module QA
click_element :admin_overview_groups_link
end
+ def go_to_applications
+ click_element(:sidebar_menu_link, menu_item: 'Applications')
+ end
+
private
def hover_element(element)
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 5d7ca2d60ad..616c12bd900 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -6,7 +6,7 @@ module QA
module Page
class Base
prepend Support::Page::Logging
- prepend Mobile::Page::Base if QA::Runtime::Env.remote_mobile_device_name
+ prepend Mobile::Page::Base if QA::Runtime::Env.mobile_layout?
include Capybara::DSL
include Scenario::Actable
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index 2fce357c877..59371dbed39 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -41,6 +41,7 @@ module QA
view 'app/helpers/auth_helper.rb' do
element :saml_login_button
element :github_login_button
+ element :oidc_login_button
end
view 'app/views/layouts/devise.html.haml' do
@@ -188,6 +189,11 @@ module QA
click_element :saml_login_button
end
+ def sign_in_with_oidc
+ set_initial_password_if_present
+ click_element :oidc_login_button
+ end
+
def sign_out_and_sign_in_as(user:)
Menu.perform(&:sign_out_if_signed_in)
has_sign_in_tab?
@@ -232,6 +238,10 @@ module QA
Support::WaitForRequests.wait_for_requests
+ wait_until(sleep_interval: 5, message: '502 - GitLab is taking too much time to respond') do
+ has_no_text?('GitLab is taking too much time to respond')
+ end
+
# For debugging invalid login attempts
has_notice?('Invalid login or password')
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index ad722e85cdd..a46b2057327 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -4,7 +4,9 @@ module QA
module Page
module Main
class Menu < Page::Base
- prepend Mobile::Page::Main::Menu if Runtime::Env.mobile_layout?
+ # We need to check phone_layout? instead of mobile_layout? here
+ # since tablets have the regular top navigation bar
+ prepend Mobile::Page::Main::Menu if Runtime::Env.phone_layout?
if Runtime::Env.super_sidebar_enabled?
prepend SubMenus::CreateNewMenu
@@ -15,8 +17,8 @@ module QA
# Define alternative navbar (super sidebar) which does not yet implement all the same elements
view 'app/assets/javascripts/super_sidebar/components/super_sidebar.vue' do
element :navbar, required: true # TODO: rename to sidebar once it's default implementation
- element :user_menu, required: !QA::Runtime::Env.mobile_layout?
- element :user_avatar_content, required: !QA::Runtime::Env.mobile_layout?
+ element :user_menu, required: !Runtime::Env.phone_layout?
+ element :user_avatar_content, required: !Runtime::Env.phone_layout?
end
view 'app/assets/javascripts/super_sidebar/components/user_menu.vue' do
@@ -27,12 +29,12 @@ module QA
view 'app/views/layouts/header/_default.html.haml' do
element :navbar, required: true
element :canary_badge_link
- element :user_avatar_content, required: !QA::Runtime::Env.mobile_layout?
- element :user_menu, required: !QA::Runtime::Env.mobile_layout?
+ element :user_avatar_content, required: !Runtime::Env.phone_layout?
+ element :user_menu, required: !Runtime::Env.phone_layout?
element :stop_impersonation_link
- element :issues_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
- element :merge_requests_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
- element :todos_shortcut_button, required: !QA::Runtime::Env.mobile_layout?
+ element :issues_shortcut_button, required: !Runtime::Env.phone_layout?
+ element :merge_requests_shortcut_button, required: !Runtime::Env.phone_layout?
+ element :todos_shortcut_button, required: !Runtime::Env.phone_layout?
end
view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
diff --git a/qa/qa/page/profile/menu.rb b/qa/qa/page/profile/menu.rb
index 6750a4c847c..f9493dbefcc 100644
--- a/qa/qa/page/profile/menu.rb
+++ b/qa/qa/page/profile/menu.rb
@@ -4,9 +4,7 @@ module QA
module Page
module Profile
class Menu < Page::Base
- # We need to check remote_mobile_device_name instead of mobile_layout? here
- # since tablets have the regular top navigation bar but still close the left nav
- prepend QA::Mobile::Page::SubMenus::Common if QA::Runtime::Env.remote_mobile_device_name
+ prepend QA::Mobile::Page::SubMenus::Common if QA::Runtime::Env.mobile_layout?
# TODO: integrate back once super sidebar becomes default
prepend QA::Page::Profile::SuperSidebar::Menu if QA::Runtime::Env.super_sidebar_enabled?
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 2f8ffc634ac..20dce1b3639 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -8,7 +8,9 @@ module QA
include Page::Component::Note
include Page::Component::DesignManagement
include Page::Component::Issuable::Sidebar
- prepend Mobile::Page::Project::Issue::Show if Runtime::Env.mobile_layout?
+ # We need to check phone_layout? instead of mobile_layout? here
+ # since tablets have the regular top navigation bar
+ prepend Mobile::Page::Project::Issue::Show if Runtime::Env.phone_layout?
view 'app/assets/javascripts/issuable/components/related_issuable_item.vue' do
element :remove_related_issue_button
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 8a71544fea9..a76717f4760 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -9,7 +9,9 @@ module QA
include Page::Component::Breadcrumbs
include Page::File::Shared::CommitMessage
include Page::Component::Dropdown
- prepend Mobile::Page::Project::Show if Runtime::Env.mobile_layout?
+ # We need to check phone_layout? instead of mobile_layout? here
+ # since tablets have the regular top navigation bar
+ prepend Mobile::Page::Project::Show if Runtime::Env.phone_layout?
view 'app/assets/javascripts/repository/components/preview/index.vue' do
element :blob_viewer_content
diff --git a/qa/qa/page/sub_menus/common.rb b/qa/qa/page/sub_menus/common.rb
index e04ac3be64f..bbd886706ba 100644
--- a/qa/qa/page/sub_menus/common.rb
+++ b/qa/qa/page/sub_menus/common.rb
@@ -4,9 +4,7 @@ module QA
module Page
module SubMenus
module Common
- # We need to check remote_mobile_device_name instead of mobile_layout? here
- # since tablets have the regular top navigation bar but still close the left nav
- prepend Mobile::Page::SubMenus::Common if QA::Runtime::Env.remote_mobile_device_name
+ prepend Mobile::Page::SubMenus::Common if QA::Runtime::Env.mobile_layout?
def hover_element(element)
within_sidebar do
diff --git a/qa/qa/resource/instance_oauth_application.rb b/qa/qa/resource/instance_oauth_application.rb
new file mode 100644
index 00000000000..7aa3661717b
--- /dev/null
+++ b/qa/qa/resource/instance_oauth_application.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class InstanceOauthApplication < Base
+ attr_accessor :name, :redirect_uri, :scopes, :trusted
+
+ attributes :id, :application_id, :application_secret
+
+ def initialize
+ @name = "Instance OAuth Application #{SecureRandom.hex(8)}"
+ @redirect_uri = ''
+ @scopes = []
+ @trusted = true
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def api_get_path
+ '/applications'
+ end
+
+ def api_delete_path
+ "/applications/#{id}"
+ end
+
+ def fabricate!
+ Flow::Login.sign_in_as_admin
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_applications)
+ Page::Admin::Applications.perform do |app|
+ app.click_new_application_button
+ app.fill_name(name)
+ app.fill_redirect_uri(redirect_uri)
+ app.set_trusted_checkbox(trusted)
+ scopes.each { |scope| app.set_scope(scope) }
+ app.save_application
+ self.application_id = app.get_application_id
+ self.application_secret = app.get_secret_id
+ self.id = app.get_id_of_application
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 945823fb9c0..b67db792419 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -17,6 +17,9 @@ module QA
NotRespondingError = Class.new(RuntimeError)
CAPYBARA_MAX_WAIT_TIME = Env.max_capybara_wait_time
+ DEFAULT_WINDOW_SIZE = '1480,2200'
+ PHONE_VIDEO_SIZE = '500x900'
+ TABLET_VIDEO_SIZE = '800x1100'
def self.blank_page?
['', 'about:blank', 'data:,'].include?(Capybara.current_session.driver.browser.current_url)
@@ -96,11 +99,14 @@ module QA
capabilities['goog:chromeOptions'][:args] << 'disable-dev-shm-usage' if QA::Runtime::Env.disable_dev_shm?
# Set chrome default download path
-
- capabilities['goog:chromeOptions'][:prefs] = {
- 'download.default_directory' => File.expand_path(QA::Runtime::Env.chrome_default_download_path),
- 'download.prompt_for_download' => false
- }
+ # TODO: Set for remote grid as well once Sauce Labs tests are deprecated and Options.chrome is added
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112258
+ unless QA::Runtime::Env.remote_grid
+ capabilities['goog:chromeOptions'][:prefs] = {
+ 'download.default_directory' => File.expand_path(QA::Runtime::Env.chrome_default_download_path),
+ 'download.prompt_for_download' => false
+ }
+ end
# Specify the user-agent to allow challenges to be bypassed
# See https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11938
@@ -114,7 +120,7 @@ module QA
capabilities['appium:deviceName'] = QA::Runtime::Env.remote_mobile_device_name
capabilities['appium:platformVersion'] = 'latest'
else
- capabilities['goog:chromeOptions'][:args] << 'window-size=1480,2200'
+ capabilities['goog:chromeOptions'][:args] << "window-size=#{DEFAULT_WINDOW_SIZE}"
end
# Slack tries to open an external URL handler
@@ -159,6 +165,9 @@ module QA
when :firefox
capabilities['acceptInsecureCerts'] = true if QA::Runtime::Env.accept_insecure_certs?
+
+ when :edge
+ capabilities['ms:edgeOptions'] = { args: ["--window-size=#{DEFAULT_WINDOW_SIZE}"] }
end
# Use the same profile on QA runs if CHROME_REUSE_PROFILE is true.
@@ -174,10 +183,21 @@ module QA
if QA::Runtime::Env.remote_grid
selenium_options[:browser] = :remote
selenium_options[:url] = QA::Runtime::Env.remote_grid
- capabilities[:browserVersion] = 'latest'
+ capabilities[:browserVersion] = QA::Runtime::Env.browser_version
+ end
+
+ if QA::Runtime::Env.remote_tunnel_id
capabilities['sauce:options'] = { tunnelIdentifier: QA::Runtime::Env.remote_tunnel_id }
end
+ if QA::Runtime::Env.record_video?
+ capabilities['selenoid:options'] = {
+ enableVideo: true,
+ videoScreenSize: video_screen_size,
+ videoName: "#{QA::Runtime::Env.browser}-#{QA::Runtime::Env.browser_version}-#{Time.now}.mp4"
+ }
+ end
+
Capybara::Selenium::Driver.new(
app,
**selenium_options
@@ -233,6 +253,16 @@ module QA
::File.expand_path('../../tmp/qa-profile', __dir__)
end
+ def self.video_screen_size
+ if QA::Runtime::Env.phone_layout?
+ PHONE_VIDEO_SIZE
+ elsif QA::Runtime::Env.tablet_layout?
+ TABLET_VIDEO_SIZE
+ else
+ ''
+ end
+ end
+
class Session
include Capybara::DSL
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 34e392c6263..cde36ba80c4 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -58,6 +58,22 @@ module QA
browser == :chrome && interception_enabled?
end
+ def release
+ ENV['RELEASE']
+ end
+
+ def release_registry_url
+ ENV['RELEASE_REGISTRY_URL']
+ end
+
+ def release_registry_username
+ ENV['RELEASE_REGISTRY_USERNAME']
+ end
+
+ def release_registry_password
+ ENV['RELEASE_REGISTRY_PASSWORD']
+ end
+
def ci_job_url
ENV['CI_JOB_URL']
end
@@ -187,14 +203,38 @@ module QA
ENV['QA_BROWSER'].nil? ? :chrome : ENV['QA_BROWSER'].to_sym
end
+ def browser_version
+ ENV['QA_BROWSER_VERSION'] || 'latest'
+ end
+
def remote_mobile_device_name
- ENV['QA_REMOTE_MOBILE_DEVICE_NAME']
+ ENV['QA_REMOTE_MOBILE_DEVICE_NAME']&.downcase
+ end
+
+ def layout
+ ENV['QA_LAYOUT']&.downcase || ''
+ end
+
+ def tablet_layout?
+ return true if remote_mobile_device_name && !phone_layout?
+
+ layout.include?('tablet')
+ end
+
+ def phone_layout?
+ return true if layout.include?('phone')
+
+ return false unless remote_mobile_device_name
+
+ !(remote_mobile_device_name.include?('ipad') || remote_mobile_device_name.include?('tablet'))
end
def mobile_layout?
- return false if ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].blank?
+ phone_layout? || tablet_layout? || remote_mobile_device_name
+ end
- !(ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].downcase.include?('ipad') || ENV['QA_REMOTE_MOBILE_DEVICE_NAME'].downcase.include?('tablet'))
+ def record_video?
+ enabled?(ENV['QA_RECORD_VIDEO'], default: false)
end
def user_username
diff --git a/qa/qa/service/docker_run/base.rb b/qa/qa/service/docker_run/base.rb
index bf85b640586..ce558849abd 100644
--- a/qa/qa/service/docker_run/base.rb
+++ b/qa/qa/service/docker_run/base.rb
@@ -85,6 +85,10 @@ module QA
shell "docker restart #{@name}"
end
+
+ def health
+ shell("docker inspect --format='{{json .State.Health.Status}}' #{@name}").delete('"')
+ end
end
end
end
diff --git a/qa/qa/service/docker_run/gitlab.rb b/qa/qa/service/docker_run/gitlab.rb
new file mode 100644
index 00000000000..4fbe6603d5b
--- /dev/null
+++ b/qa/qa/service/docker_run/gitlab.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module QA
+ module Service
+ module DockerRun
+ class Gitlab < Base
+ def initialize(name:, omnibus_config: '', image: '')
+ @image = image
+ @name = name
+ @omnibus_configuration = omnibus_config
+ super()
+ end
+
+ def login
+ super(Runtime::Env.release_registry_url,
+ user: Runtime::Env.release_registry_username,
+ password: Runtime::Env.release_registry_password)
+ end
+
+ def register!
+ shell <<~CMD.tr("\n", ' ')
+ docker run -d --rm
+ --network #{network}
+ --hostname #{host_name}
+ --publish 80:80
+ #{RUBY_PLATFORM.include?('arm64') ? '--platform linux/amd64' : ''}
+ --env GITLAB_OMNIBUS_CONFIG="#{@omnibus_configuration}"
+ --name #{@name}
+ #{@image}
+ CMD
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb
new file mode 100644
index 00000000000..268bd6fdbf0
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oidc_with_gitlab_as_idp_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage', :skip_live_env, requires_admin: 'creates users and instance OAuth application',
+ product_group: :authentication_and_authorization do
+ let!(:user) { Resource::User.fabricate_via_api! }
+ let(:oidc_consumer_name) { 'gitlab-oidc-consumer' }
+ let(:oidc_consumer_host) { "http://#{oidc_consumer_name}.#{Runtime::Env.running_in_ci? ? 'test' : 'bridge'}" }
+ let(:instance_oauth_app) do
+ Resource::InstanceOauthApplication.fabricate! do |application|
+ application.redirect_uri = "#{oidc_consumer_host}/users/auth/openid_connect/callback"
+ application.scopes = %w[openid profile email]
+ end
+ end
+
+ after do
+ instance_oauth_app.remove_via_api!
+ remove_gitlab_service(oidc_consumer_name)
+ end
+
+ # The host GitLab instance with address Runtime::Scenario.gitlab_address is the OIDC idP - OIDC application will be
+ # created here.
+ # GitLab instance stood up in docker with address gitlab-oidc-consumer.test (or gitlab-oidc-consumer.bridge) is
+ # the consumer - The GitLab OIDC Login button will be displayed here.
+ describe 'OIDC' do
+ it(
+ 'creates GitLab OIDC application and uses it to login',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/405137'
+ ) do
+ instance_oauth_app
+
+ Page::Main::Menu.perform(&:sign_out_if_signed_in)
+
+ app_id = instance_oauth_app.application_id
+ app_secret = instance_oauth_app.application_secret
+
+ consumer_gitlab_service = run_gitlab_service(name: oidc_consumer_name, app_id: app_id, app_secret: app_secret)
+
+ wait_for_service(consumer_gitlab_service)
+
+ page.visit oidc_consumer_host
+
+ expect(page.driver.current_url).to include(oidc_consumer_host)
+
+ Page::Main::Login.perform(&:sign_in_with_oidc)
+
+ expect(page.driver.current_url).to include(Runtime::Scenario.gitlab_address)
+
+ Flow::Login.sign_in(as: user)
+
+ expect(page.driver.current_url).to include(oidc_consumer_host)
+
+ Page::Dashboard::Welcome.perform do |welcome|
+ expect(welcome).to have_welcome_title("Welcome to GitLab")
+ end
+ end
+
+ def run_gitlab_service(name:, app_id:, app_secret:)
+ Service::DockerRun::Gitlab.new(
+ image: Runtime::Env.release,
+ name: name,
+ omnibus_config: omnibus_configuration(app_id: app_id, app_secret: app_secret)).tap do |gitlab|
+ gitlab.login
+ gitlab.pull
+ gitlab.register!
+ end
+ end
+
+ def remove_gitlab_service(name)
+ Service::DockerRun::Gitlab.new(name: name).remove!
+ end
+
+ def wait_for_service(service)
+ Support::Waiter.wait_until(max_duration: 900, sleep_interval: 5, raise_on_failure: true) do
+ service.health == "healthy"
+ end
+ end
+
+ def omnibus_configuration(app_id:, app_secret:)
+ <<~OMNIBUS
+ gitlab_rails['initial_root_password']='5iveL\!fe';
+ gitlab_rails['omniauth_enabled'] = true;
+ gitlab_rails['omniauth_allow_single_sign_on'] = true;
+ gitlab_rails['omniauth_block_auto_created_users'] = false;
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: 'openid_connect',
+ label: 'GitLab OIDC',
+ args: {
+ name: 'openid_connect',
+ scope: ['openid','profile','email'],
+ response_type: 'code',
+ issuer: '#{Runtime::Scenario.gitlab_address}',
+ discovery: false,
+ uid_field: 'preferred_username',
+ send_scope_to_token_endpoint: 'false',
+ client_options: {
+ identifier: '#{app_id}',
+ secret: '#{app_secret}',
+ redirect_uri: '#{oidc_consumer_host}/users/auth/openid_connect/callback',
+ jwks_uri: '#{Runtime::Scenario.gitlab_address}/oauth/discovery/keys',
+ userinfo_endpoint: '#{Runtime::Scenario.gitlab_address}/oauth/userinfo',
+ token_endpoint: '#{Runtime::Scenario.gitlab_address}/oauth/token',
+ authorization_endpoint: '#{Runtime::Scenario.gitlab_address}/oauth/authorize'
+ }
+ }
+ }
+ ];
+ OMNIBUS
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/spec_helper.rb b/qa/qa/specs/spec_helper.rb
index 1bf189ed6ac..aa274a4e101 100644
--- a/qa/qa/specs/spec_helper.rb
+++ b/qa/qa/specs/spec_helper.rb
@@ -33,7 +33,7 @@ RSpec.configure do |config|
QA::Runtime::Logger.info("Starting test: #{Rainbow(example.full_description).bright}")
QA::Runtime::Example.current = example
- visit(QA::Runtime::Scenario.gitlab_address) if QA::Runtime::Env.remote_mobile_device_name
+ visit(QA::Runtime::Scenario.gitlab_address) if QA::Runtime::Env.mobile_layout?
# Reset fabrication counters tracked in resource base
Thread.current[:api_fabrication] = 0
diff --git a/qa/qa/tools/test_resources_handler.rb b/qa/qa/tools/test_resources_handler.rb
index f30c1902119..7f4b8f78618 100644
--- a/qa/qa/tools/test_resources_handler.rb
+++ b/qa/qa/tools/test_resources_handler.rb
@@ -31,6 +31,7 @@ module QA
QA::Resource::CiVariable
QA::Resource::Repository::Commit
QA::Resource::Design
+ QA::Resource::InstanceOauthApplication
QA::EE::Resource::ComplianceFramework
QA::EE::Resource::GroupIteration
QA::EE::Resource::Settings::Elasticsearch