summaryrefslogtreecommitdiff
path: root/qa/qa/support
diff options
context:
space:
mode:
Diffstat (limited to 'qa/qa/support')
-rw-r--r--qa/qa/support/api.rb13
-rw-r--r--qa/qa/support/formatters/feature_flag_formatter.rb36
-rw-r--r--qa/qa/support/formatters/test_stats_formatter.rb1
-rw-r--r--qa/qa/support/helpers/mask_token.rb19
-rw-r--r--qa/qa/support/helpers/plan.rb5
-rw-r--r--qa/qa/support/loglinking.rb4
-rw-r--r--qa/qa/support/matchers/have_matcher.rb1
-rw-r--r--qa/qa/support/page_error_checker.rb45
-rw-r--r--qa/qa/support/wait_for_requests.rb6
9 files changed, 118 insertions, 12 deletions
diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb
index 976188e45c6..0c0a1a90ff2 100644
--- a/qa/qa/support/api.rb
+++ b/qa/qa/support/api.rb
@@ -20,9 +20,7 @@ module QA
verify_ssl: false
}
- RestClient::Request.execute(
- default_args.merge(args)
- )
+ RestClient::Request.execute(default_args.merge(args))
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
@@ -56,13 +54,16 @@ module QA
end
end
- def put(url, payload = nil)
+ def put(url, payload = nil, args = {})
with_retry_on_too_many_requests do
- RestClient::Request.execute(
+ default_args = {
method: :put,
url: url,
payload: payload,
- verify_ssl: false)
+ verify_ssl: false
+ }
+
+ RestClient::Request.execute(default_args.merge(args))
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
diff --git a/qa/qa/support/formatters/feature_flag_formatter.rb b/qa/qa/support/formatters/feature_flag_formatter.rb
new file mode 100644
index 00000000000..94c039586f9
--- /dev/null
+++ b/qa/qa/support/formatters/feature_flag_formatter.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ module Formatters
+ class FeatureFlagFormatter < ::RSpec::Core::Formatters::BaseFormatter
+ include Specs::Helpers::FeatureFlag
+
+ ::RSpec::Core::Formatters.register(
+ self,
+ :example_group_started,
+ :example_started
+ )
+
+ # Starts example group
+ # @param [RSpec::Core::Notifications::GroupNotification] example_group_notification
+ # @return [void]
+ def example_group_started(example_group_notification)
+ group = example_group_notification.group
+
+ skip_or_run_feature_flag_tests_or_contexts(group)
+ end
+
+ # Starts example
+ # @param [RSpec::Core::Notifications::ExampleNotification] example_notification
+ # @return [void]
+ def example_started(example_notification)
+ example = example_notification.example
+
+ # if skip propagated from example_group, do not reset skip metadata
+ skip_or_run_feature_flag_tests_or_contexts(example) unless example.metadata[:skip]
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/formatters/test_stats_formatter.rb b/qa/qa/support/formatters/test_stats_formatter.rb
index 16fc0a50b1b..9d19c2e8bb5 100644
--- a/qa/qa/support/formatters/test_stats_formatter.rb
+++ b/qa/qa/support/formatters/test_stats_formatter.rb
@@ -64,6 +64,7 @@ module QA
name: example.full_description,
file_path: file_path,
status: example.execution_result.status,
+ smoke: example.metadata.key?(:smoke).to_s,
reliable: example.metadata.key?(:reliable).to_s,
quarantined: quarantined(example.metadata),
retried: ((example.metadata[:retry_attempts] || 0) > 0).to_s,
diff --git a/qa/qa/support/helpers/mask_token.rb b/qa/qa/support/helpers/mask_token.rb
new file mode 100644
index 00000000000..1f8161f7173
--- /dev/null
+++ b/qa/qa/support/helpers/mask_token.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ module Helpers
+ module MaskToken
+ def use_ci_variable(name:, value:, project:)
+ Resource::CiVariable.fabricate_via_api! do |ci_variable|
+ ci_variable.project = project
+ ci_variable.key = name
+ ci_variable.value = value
+ ci_variable.protected = true
+ end
+ "$#{name}"
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/helpers/plan.rb b/qa/qa/support/helpers/plan.rb
index 298a6d3f036..b6950c6bacd 100644
--- a/qa/qa/support/helpers/plan.rb
+++ b/qa/qa/support/helpers/plan.rb
@@ -57,8 +57,9 @@ module QA
}.freeze
LICENSE_TYPE = {
- license_file: 'license file',
- cloud_license: 'cloud license'
+ legacy_license: 'legacy license',
+ online_cloud: 'online license',
+ offline_cloud: 'offline license'
}.freeze
end
end
diff --git a/qa/qa/support/loglinking.rb b/qa/qa/support/loglinking.rb
index 89519e9537c..caf381912d3 100644
--- a/qa/qa/support/loglinking.rb
+++ b/qa/qa/support/loglinking.rb
@@ -5,7 +5,7 @@ module QA
# Static address variables declared for mapping environment to logging URLs
STAGING_ADDRESS = 'https://staging.gitlab.com'
STAGING_REF_ADDRESS = 'https://staging-ref.gitlab.com'
- PRODUCTION_ADDRESS = 'https://www.gitlab.com'
+ PRODUCTION_ADDRESS = 'https://gitlab.com'
PRE_PROD_ADDRESS = 'https://pre.gitlab.com'
SENTRY_ENVIRONMENTS = {
staging: 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg',
@@ -30,7 +30,7 @@ module QA
errors = ["Correlation Id: #{correlation_id}"]
errors << "Sentry Url: #{sentry_uri}&query=correlation_id%3A%22#{correlation_id}%22" if sentry_uri
- errors << "Kibana Url: #{kibana_uri}app/discover#/?_a=(query:(language:kuery,query:'json.correlation_id%20:%20#{correlation_id}'))" if kibana_uri
+ errors << "Kibana Url: #{kibana_uri}app/discover#/?_a=(query:(language:kuery,query:'json.correlation_id%20:%20#{correlation_id}'))&_g=(time:(from:now-24h%2Fh,to:now))" if kibana_uri
errors.join("\n")
end
diff --git a/qa/qa/support/matchers/have_matcher.rb b/qa/qa/support/matchers/have_matcher.rb
index a90d2df96ae..b96566a9e5d 100644
--- a/qa/qa/support/matchers/have_matcher.rb
+++ b/qa/qa/support/matchers/have_matcher.rb
@@ -10,6 +10,7 @@ module QA
file_content
assignee
child_pipeline
+ linked_pipeline
content
design
file
diff --git a/qa/qa/support/page_error_checker.rb b/qa/qa/support/page_error_checker.rb
index ede9b49bda6..192b8c147cd 100644
--- a/qa/qa/support/page_error_checker.rb
+++ b/qa/qa/support/page_error_checker.rb
@@ -49,7 +49,7 @@ module QA
error_code = 404 if Nokogiri::HTML.parse(page.html).xpath("//img").map { |t| t[:alt] }.first.eql?('404')
# 500 error page in header surrounded by newlines, try to match
- five_hundred_test = Nokogiri::HTML.parse(page.html).xpath("//h1").map.first
+ five_hundred_test = Nokogiri::HTML.parse(page.html).xpath("//h1/text()").map.first
unless five_hundred_test.nil?
error_code = 500 if five_hundred_test.text.include?('500')
end
@@ -61,6 +61,39 @@ module QA
end
end
+ # Log request errors triggered from async api calls from the browser
+ #
+ # If any errors are found in the session, log them
+ # using QA::Runtime::Logger
+ # @param [Capybara::Session] page
+ def log_request_errors(page)
+ return if QA::Runtime::Browser.blank_page?
+
+ url = page.driver.browser.current_url
+ QA::Runtime::Logger.debug "Fetching API error cache for #{url}"
+
+ cache = page.execute_script <<~JS
+ return !(typeof(Interceptor)==="undefined") ? Interceptor.getCache() : null;
+ JS
+
+ return unless cache&.dig('errors')
+
+ grouped_errors = group_errors(cache['errors'])
+
+ errors = grouped_errors.map do |error_metadata, request_id_string|
+ "#{error_metadata} -- #{request_id_string}"
+ end
+
+ unless errors.nil? || errors.empty?
+ QA::Runtime::Logger.error "Interceptor Api Errors\n#{errors.join("\n")}"
+ end
+
+ # clear the cache after logging the errors
+ page.execute_script <<~JS
+ Interceptor && Interceptor.saveCache({});
+ JS
+ end
+
def error_report_for(logs)
logs
.map(&:message)
@@ -70,6 +103,16 @@ module QA
def logs(page)
page.driver.browser.manage.logs.get(:browser)
end
+
+ private
+
+ def group_errors(errors)
+ errors.each_with_object({}) do |error, memo|
+ url = error['url']&.split('?')&.first || 'Unknown url'
+ key = "[#{error['status']}] #{error['method']} #{url}"
+ memo[key] = "Correlation Id: #{error.dig('headers', 'x-request-id') || 'Correlation Id not found'}"
+ end
+ end
end
end
end
diff --git a/qa/qa/support/wait_for_requests.rb b/qa/qa/support/wait_for_requests.rb
index 16af4bae521..89674a1d5c6 100644
--- a/qa/qa/support/wait_for_requests.rb
+++ b/qa/qa/support/wait_for_requests.rb
@@ -16,12 +16,16 @@ module QA
Waiter.wait_until(log: false) do
finished_all_ajax_requests? && (!skip_finished_loading_check ? finished_loading?(wait: 1) : true)
end
+ QA::Support::PageErrorChecker.log_request_errors(Capybara.page) if QA::Runtime::Env.can_intercept?
rescue Repeater::WaitExceededError
raise $!, 'Page did not fully load. This could be due to an unending async request or loading icon.'
end
def finished_all_ajax_requests?
- Capybara.page.evaluate_script('window.pendingRequests || window.pendingRailsUJSRequests || 0').zero? # rubocop:disable Style/NumericPredicate
+ requests = %w[window.pendingRequests window.pendingRailsUJSRequests 0]
+ requests.unshift('(window.Interceptor && window.Interceptor.activeFetchRequests)') if Runtime::Env.can_intercept?
+ script = requests.join(' || ')
+ Capybara.page.evaluate_script(script).zero? # rubocop:disable Style/NumericPredicate
end
def finished_loading?(wait: DEFAULT_MAX_WAIT_TIME)