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-01-31 06:08:13 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-01-31 06:08:13 +0300
commit25805c16335ed6466f0e475417e3005cd09848c2 (patch)
tree59e83dff33c409d33b6cfac4c1bfd8e310eadb78 /qa
parent13ddda5208f9175e822af6d05a32600bc9cad091 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'qa')
-rw-r--r--qa/lib/slack.rb9
-rw-r--r--qa/lib/slack/mixins/browser.rb11
-rw-r--r--qa/lib/slack/mixins/gitlab_app.rb52
-rw-r--r--qa/lib/slack/page/chat.rb68
-rw-r--r--qa/lib/slack/page/login.rb40
-rw-r--r--qa/lib/slack/page/oauth.rb9
-rw-r--r--qa/qa/flow/integrations/slack.rb54
-rw-r--r--qa/qa/page/profile/chat_names/new.rb13
-rw-r--r--qa/qa/page/project/settings/integrations.rb5
-rw-r--r--qa/qa/runtime/browser.rb49
-rw-r--r--qa/qa/runtime/env.rb21
11 files changed, 326 insertions, 5 deletions
diff --git a/qa/lib/slack.rb b/qa/lib/slack.rb
new file mode 100644
index 00000000000..95e81b700f5
--- /dev/null
+++ b/qa/lib/slack.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'chemlab/library'
+
+module Slack
+ include Chemlab::Library
+
+ self.base_url = 'https://slack.com'
+end
diff --git a/qa/lib/slack/mixins/browser.rb b/qa/lib/slack/mixins/browser.rb
new file mode 100644
index 00000000000..853ff2c7130
--- /dev/null
+++ b/qa/lib/slack/mixins/browser.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Slack
+ module Mixins
+ module Browser
+ def browser
+ ::Chemlab.configuration.browser.session.engine
+ end
+ end
+ end
+end
diff --git a/qa/lib/slack/mixins/gitlab_app.rb b/qa/lib/slack/mixins/gitlab_app.rb
new file mode 100644
index 00000000000..66b456ef824
--- /dev/null
+++ b/qa/lib/slack/mixins/gitlab_app.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Slack
+ module Mixins
+ module GitlabApp
+ # @param [QA::Resource::Project] project
+ # @param [String] channel
+ # @param [String] title
+ # @param [String] description
+ def create_issue(project, channel:, title:, description:)
+ lines = [
+ "/staging-gitlab #{project.path_with_namespace} issue new #{title}",
+ description
+ ]
+
+ send_message_to_channel(lines, channel: channel)
+ end
+
+ # @param [QA::Resource::Project] project
+ # @param [QA::Resource::Project] target
+ # @param [String] id
+ # @param [String] channel
+ def move_issue(project, target, id:, channel:)
+ line = "/staging-gitlab #{project.path_with_namespace} issue move #{id} to #{target.path_with_namespace}"
+ send_message_to_channel([line], channel: channel)
+ end
+
+ # @param [QA::Resource::Project] project
+ # @param [String] id
+ # @param [String] channel
+ def show_issue(project, id:, channel:)
+ send_message_to_channel(["/staging-gitlab #{project.path_with_namespace} issue show #{id}"], channel: channel)
+ end
+
+ # @param [QA::Resource::Project] project
+ # @param [String] id
+ # @param [String] channel
+ def close_issue(project, id:, channel:)
+ send_message_to_channel(["/staging-gitlab #{project.path_with_namespace} issue close #{id}"], channel: channel)
+ end
+
+ # @param [QA::Resource::Project] project
+ # @param [String] channel
+ # @param [String] id
+ # @param [String] comment
+ def comment_on_issue(project, channel:, id:, comment:)
+ command = "/staging-gitlab #{project.path_with_namespace} issue comment #{id}"
+ send_message_to_channel([command, comment], channel: channel)
+ end
+ end
+ end
+end
diff --git a/qa/lib/slack/page/chat.rb b/qa/lib/slack/page/chat.rb
new file mode 100644
index 00000000000..5f8553fc425
--- /dev/null
+++ b/qa/lib/slack/page/chat.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Slack
+ module Page
+ class Chat < Chemlab::Page
+ include Mixins::Browser
+ include Mixins::GitlabApp
+
+ div :message_field, data_qa: 'message_input'
+ button :connect_gitlab_button, visible_text: /Connect your GitLab account/
+ button :skip_download_slack_button, data_qa: 'continue_in_browser'
+
+ def skip_download_screen
+ wait_for_text('download the Slack app')
+
+ skip_download_slack_button_element.click if skip_download_slack_button_element.exists?
+ end
+
+ # @param [Array<String>] lines - messages to send
+ # @param [String] channel to send message to
+ def send_message_to_channel(lines, channel:)
+ go_to_channel(channel)
+
+ message_field_element.focus
+ message_field_element.click
+
+ while line = lines.shift
+ browser.send_keys(line)
+ wait_for_text(line)
+
+ browser.send_keys([:shift, :enter]) unless lines.empty?
+ end
+
+ browser.send_keys(:enter)
+ end
+
+ def wait_for_text(line)
+ QA::Support::Waiter.wait_until(max_duration: 3, raise_on_failure: false) do
+ browser.text.include?(line)
+ end
+ end
+
+ def go_to_channel(channel)
+ menu_item = messages.find do |div|
+ div.text == channel
+ end
+ menu_item.click
+ end
+
+ def click_connect_account_link
+ divs = messages(visible_text: /connect your GitLab account/i)
+ el = divs.last.a(href: /staging-ref/)
+ el.scroll.to(:top)
+ el.click
+ end
+
+ def messages(**opts)
+ browser.divs(data_qa: 'virtual-list-item', **opts)
+ end
+
+ def gitlab_app_home
+ browser.divs(data_qa: 'channel_item_container').find do |el|
+ el.text == 'GitLab'
+ end
+ end
+ end
+ end
+end
diff --git a/qa/lib/slack/page/login.rb b/qa/lib/slack/page/login.rb
new file mode 100644
index 00000000000..a11b0d27fd0
--- /dev/null
+++ b/qa/lib/slack/page/login.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Slack
+ module Page
+ class Login < Chemlab::Page
+ path '/workspace-signin'
+
+ text_field :workspace_field, data_qa: 'signin_domain_input'
+ button :continue_button, data_qa: 'submit_team_domain_button'
+
+ link :sign_in_with_password_link, data_qa: 'sign_in_password_link'
+
+ text_field :email_address_field, data_qa: 'login_email'
+ text_field :password_field, data_qa: 'login_password', type: 'password'
+ button :sign_in_button, data_qa: 'signin_button'
+
+ def sign_in
+ navigate_to_workspace
+
+ # sign into with password if needed
+ sign_in_with_password_link_element.click if sign_in_with_password_link_element.exists?
+
+ finish_sign_in
+ end
+
+ def navigate_to_workspace
+ self.workspace_field = ::QA::Runtime::Env.slack_workspace
+ continue_button
+ end
+
+ def finish_sign_in
+ return unless email_address_field_element.exists?
+
+ self.email_address_field = ::QA::Runtime::Env.slack_email
+ self.password_field = ::QA::Runtime::Env.slack_password
+ sign_in_button
+ end
+ end
+ end
+end
diff --git a/qa/lib/slack/page/oauth.rb b/qa/lib/slack/page/oauth.rb
new file mode 100644
index 00000000000..700d19f0c4c
--- /dev/null
+++ b/qa/lib/slack/page/oauth.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Slack
+ module Page
+ class Oauth < Chemlab::Page
+ button :submit_oauth, data_qa: 'oauth_submit_button'
+ end
+ end
+end
diff --git a/qa/qa/flow/integrations/slack.rb b/qa/qa/flow/integrations/slack.rb
new file mode 100644
index 00000000000..8f18ccaa791
--- /dev/null
+++ b/qa/qa/flow/integrations/slack.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module QA
+ module Flow
+ module Integrations
+ module Slack
+ extend self
+
+ # Need to sign in for this method
+ # @param [QA::Resource::Project]
+ def start_slack_install(project)
+ project.visit!
+
+ Page::Project::Menu.perform do |project_menu_page|
+ project_menu_page.click_project
+ project_menu_page.go_to_integrations_settings
+ end
+
+ Page::Project::Settings::Integrations.perform(&:click_slack_application_link)
+
+ EE::Page::Project::Settings::Services::Slack.perform(&:start_slack_install)
+ ::Slack::Page::Oauth.perform(&:submit_oauth)
+ end
+
+ # @param [QA::Resource::Project] project
+ # @option [String | Nil] channel
+ # @return [Boolean] is this account already authorized?
+ def start_gitlab_connect(project, channel: nil)
+ ::Slack::Page::Chat.perform do |chat_page|
+ # sometimes Slack will present a blocking page
+ # for downloading the app instead of using a browser
+ chat_page.skip_download_screen
+
+ lines = ["/staging-gitlab #{project.path_with_namespace} issue show 1"]
+ chat_page.send_message_to_channel(lines, channel: channel)
+
+ # The only way to know if we are authorized is to send a slash command to the channel.
+ # If the account / chat_name is already authorized, the Slack app will try to look up the issue
+ # and return a 404 because it doesn't exist
+ QA::Support::Waiter.wait_until(max_duration: 4, raise_on_failure: false) do
+ chat_page.messages.last.text =~ /connect your GitLab account|404 not found!/i
+ end
+
+ break(true) if chat_page.messages.last.text =~ /404 not found!/i
+
+ chat_page.click_connect_account_link
+
+ false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/profile/chat_names/new.rb b/qa/qa/page/profile/chat_names/new.rb
new file mode 100644
index 00000000000..351d36b87d5
--- /dev/null
+++ b/qa/qa/page/profile/chat_names/new.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Profile
+ module ChatNames
+ class New < Chemlab::Page
+ button :authorize, value: /Authorize/i
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/integrations.rb b/qa/qa/page/project/settings/integrations.rb
index 58b3badbb22..c97593312d1 100644
--- a/qa/qa/page/project/settings/integrations.rb
+++ b/qa/qa/page/project/settings/integrations.rb
@@ -10,6 +10,7 @@ module QA
element :prometheus_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :jira_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :pipelines_email_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
+ element :gitlab_slack_application_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
end
def click_on_prometheus_integration
@@ -27,6 +28,10 @@ module QA
def click_jenkins_ci_link
click_element :jenkins_link
end
+
+ def click_slack_application_link
+ click_element :gitlab_slack_application_link
+ end
end
end
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index faf2023f7c2..f01657c8deb 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -104,7 +104,7 @@ module QA
# Specify the user-agent to allow challenges to be bypassed
# See https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11938
- if QA::Runtime::Env.user_agent
+ unless QA::Runtime::Env.user_agent.blank?
capabilities['goog:chromeOptions'][:args] << "user-agent=#{QA::Runtime::Env.user_agent}"
end
@@ -117,6 +117,38 @@ module QA
capabilities['goog:chromeOptions'][:args] << 'window-size=1480,2200'
end
+ # Slack tries to open an external URL handler
+ # The test needs to default the handler to always open Slack
+ # to prevent a blocking popup.
+ if QA::Runtime::Env.slack_workspace
+ slack_default_preference = {
+ 'protocol_handler' => {
+ 'allowed_origin_protocol_pairs' => {
+ "https://#{QA::Runtime::Env.slack_workspace}.slack.com" => {
+ 'slack' => true
+ }
+ }
+ }
+ }
+
+ default_profile = File.join("#{chrome_profile_location}/Default")
+ FileUtils.mkdir_p(default_profile) unless Dir.exist?(default_profile)
+ preferences = slack_default_preference
+
+ # mutate the preferences if it exists
+ # else write a new file
+ if File.exist?("#{default_profile}/Preferences")
+ begin
+ preferences = JSON.parse(File.read("#{default_profile}/Preferences"))
+ preferences.deep_merge!(slack_default_preference)
+ rescue JSON::ParserError => _
+ end
+ end
+
+ File.write("#{default_profile}/Preferences", preferences.to_json)
+ append_chrome_profile_to_capabilities(capabilities)
+ end
+
when :safari
if QA::Runtime::Env.remote_mobile_device_name
capabilities['platformName'] = 'iOS'
@@ -131,10 +163,7 @@ module QA
# Use the same profile on QA runs if CHROME_REUSE_PROFILE is true.
# Useful to speed up local QA.
- if QA::Runtime::Env.reuse_chrome_profile?
- qa_profile_dir = ::File.expand_path('../../tmp/qa-profile', __dir__)
- capabilities['goog:chromeOptions'][:args] << "user-data-dir=#{qa_profile_dir}"
- end
+ append_chrome_profile_to_capabilities(capabilities) if QA::Runtime::Env.reuse_chrome_profile?
selenium_options = {
browser: QA::Runtime::Env.browser,
@@ -193,6 +222,16 @@ module QA
end
# rubocop: enable Metrics/AbcSize
+ def self.append_chrome_profile_to_capabilities(capabilities)
+ return if capabilities['goog:chromeOptions'][:args].include?(chrome_profile_location)
+
+ capabilities['goog:chromeOptions'][:args] << "user-data-dir=#{chrome_profile_location}"
+ end
+
+ def self.chrome_profile_location
+ ::File.expand_path('../../tmp/qa-profile', __dir__)
+ end
+
class Session
include Capybara::DSL
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index e952c0337f2..b53c2320537 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -293,6 +293,18 @@ module QA
ENV['JIRA_HOSTNAME']
end
+ def slack_workspace
+ ENV['QA_SLACK_WORKSPACE']
+ end
+
+ def slack_email
+ ENV['QA_SLACK_EMAIL']
+ end
+
+ def slack_password
+ ENV['QA_SLACK_PASSWORD']
+ end
+
def jenkins_admin_username
ENV.fetch('QA_JENKINS_USER', 'administrator')
end
@@ -502,6 +514,15 @@ module QA
ENV['DEFAULT_CHROME_DOWNLOAD_PATH'] || Dir.tmpdir
end
+ def require_slack_env!
+ missing_env = %i[slack_workspace slack_email slack_password].select do |method|
+ ::QA::Runtime::Env.public_send(method).nil?
+ end
+ return unless missing_env.any?
+
+ raise "Missing Slack env: #{missing_env.map(&:upcase).join(', ')}"
+ end
+
private
def remote_grid_credentials