summaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-20 12:52:10 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-20 12:52:10 +0000
commitdba864470fbcbb6bdd5b94eb510acdce62c962d8 (patch)
treee8ead0b84e7b814f5891d2c8cd3db2d6b635fb64 /qa
parentb7d29500f28ff59c8898cdf889a40d3da908f162 (diff)
downloadgitlab-ce-dba864470fbcbb6bdd5b94eb510acdce62c962d8.tar.gz
Add latest changes from gitlab-org/gitlab@12-8-stable-ee
Diffstat (limited to 'qa')
-rw-r--r--qa/Gemfile.lock2
-rw-r--r--qa/README.md10
-rw-r--r--qa/qa.rb12
-rw-r--r--qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml337
-rw-r--r--qa/qa/flow/saml.rb72
-rw-r--r--qa/qa/flow/user.rb26
-rw-r--r--qa/qa/page/base.rb12
-rw-r--r--qa/qa/page/component/ci_badge_link.rb23
-rw-r--r--qa/qa/page/component/select2.rb4
-rw-r--r--qa/qa/page/dashboard/snippet/new.rb10
-rw-r--r--qa/qa/page/group/menu.rb13
-rw-r--r--qa/qa/page/group/sub_menus/common.rb21
-rw-r--r--qa/qa/page/layout/performance_bar.rb4
-rw-r--r--qa/qa/page/merge_request/show.rb4
-rw-r--r--qa/qa/page/project/issue/show.rb2
-rw-r--r--qa/qa/page/project/job/show.rb10
-rw-r--r--qa/qa/page/project/new.rb3
-rw-r--r--qa/qa/page/project/operations/metrics.rb49
-rw-r--r--qa/qa/page/project/pipeline/index.rb22
-rw-r--r--qa/qa/page/project/pipeline/show.rb4
-rw-r--r--qa/qa/page/project/settings/ci_variables.rb8
-rw-r--r--qa/qa/page/project/settings/protected_branches.rb1
-rw-r--r--qa/qa/page/project/show.rb35
-rw-r--r--qa/qa/page/project/sub_menus/common.rb18
-rw-r--r--qa/qa/page/project/sub_menus/operations.rb9
-rw-r--r--qa/qa/page/sub_menus/common.rb50
-rw-r--r--qa/qa/resource/api_fabricator.rb12
-rw-r--r--qa/qa/resource/events/base.rb2
-rw-r--r--qa/qa/resource/fork.rb52
-rw-r--r--qa/qa/resource/group.rb1
-rw-r--r--qa/qa/resource/members.rb4
-rw-r--r--qa/qa/resource/merge_request_from_fork.rb2
-rw-r--r--qa/qa/resource/project.rb33
-rw-r--r--qa/qa/resource/project_milestone.rb33
-rw-r--r--qa/qa/resource/sandbox.rb4
-rw-r--r--qa/qa/resource/user.rb13
-rw-r--r--qa/qa/runtime/browser.rb33
-rw-r--r--qa/qa/runtime/env.rb4
-rw-r--r--qa/qa/runtime/feature.rb14
-rw-r--r--qa/qa/runtime/release.rb10
-rw-r--r--qa/qa/runtime/search.rb19
-rw-r--r--qa/qa/scenario/template.rb5
-rw-r--r--qa/qa/scenario/test/instance.rb5
-rw-r--r--qa/qa/scenario/test/sanity/selectors.rb5
-rw-r--r--qa/qa/service/docker_run/saml_idp.rb69
-rw-r--r--qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb (renamed from qa/qa/specs/features/browser_ui/2_plan/issue/close_issue_spec.rb)26
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb53
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb38
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb59
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb121
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb24
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb111
-rw-r--r--qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb6
-rw-r--r--qa/qa/support/page/logging.rb7
-rw-r--r--qa/qa/support/repeater.rb4
-rw-r--r--qa/qa/support/retrier.rb2
-rw-r--r--qa/qa/support/wait_for_requests.rb2
-rw-r--r--qa/qa/support/waiter.rb25
-rw-r--r--qa/qa/tools/delete_subgroups.rb30
-rw-r--r--qa/qa/vendor/jenkins/page/job.rb23
-rw-r--r--qa/spec/page/logging_spec.rb18
-rw-r--r--qa/spec/resource/api_fabricator_spec.rb2
-rw-r--r--qa/spec/scenario/test/integration/github_spec.rb2
-rw-r--r--qa/spec/scenario/test/integration/instance_saml_spec.rb2
-rw-r--r--qa/spec/scenario/test/integration/kubernetes_spec.rb2
-rw-r--r--qa/spec/scenario/test/integration/ldap_spec.rb6
-rw-r--r--qa/spec/scenario/test/integration/mattermost_spec.rb2
-rw-r--r--qa/spec/scenario/test/integration/oauth_spec.rb2
-rw-r--r--qa/spec/scenario/test/integration/object_storage_spec.rb2
-rw-r--r--qa/spec/specs/runner_spec.rb2
-rw-r--r--qa/spec/support/repeater_spec.rb30
-rw-r--r--qa/spec/support/retrier_spec.rb12
-rw-r--r--qa/spec/support/shared_examples/scenario_shared_examples.rb6
-rw-r--r--qa/spec/support/waiter_spec.rb9
91 files changed, 1327 insertions, 459 deletions
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 6d48a9449a5..cd73e1b6539 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -94,7 +94,7 @@ GEM
rspec-core (>= 2, < 4, != 2.12.0)
ruby-debug-ide (0.7.0)
rake (>= 0.8.1)
- rubyzip (1.2.2)
+ rubyzip (1.3.0)
selenium-webdriver (3.142.6)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
diff --git a/qa/README.md b/qa/README.md
index 1bfa83cadf1..cdc84da1c5e 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -67,6 +67,16 @@ bundle exec bin/qa Test::Instance::All http://localhost:3000
Note: If you want to run tests requiring SSH against GDK, you
will need to [modify your GDK setup](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md).
+#### Running EE tests
+
+When running EE tests you'll need to have a license available. GitLab engineers can [request a license](https://about.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee).
+
+Once you have the license file you can export it as an environment variable and then the framework can use it. If you do so it will be installed automatically.
+
+```
+export EE_LICENSE=$(cat /path/to/gitlab_license)
+```
+
### Writing tests
- [Writing tests from scratch tutorial](../doc/development/testing_guide/end_to_end/quick_start_guide.md)
diff --git a/qa/qa.rb b/qa/qa.rb
index a0ce6caa3a9..fb0c06e33aa 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-$: << File.expand_path(File.dirname(__FILE__))
+$: << File.expand_path(__dir__)
Encoding.default_external = 'UTF-8'
@@ -16,6 +16,8 @@ module QA
module Flow
autoload :Login, 'qa/flow/login'
autoload :Project, 'qa/flow/project'
+ autoload :Saml, 'qa/flow/saml'
+ autoload :User, 'qa/flow/user'
end
##
@@ -157,6 +159,10 @@ module QA
autoload :Validator, 'qa/page/validator'
autoload :Validatable, 'qa/page/validatable'
+ module SubMenus
+ autoload :Common, 'qa/page/sub_menus/common'
+ end
+
module Main
autoload :Login, 'qa/page/main/login'
autoload :Menu, 'qa/page/main/menu'
@@ -289,6 +295,8 @@ module QA
autoload :AddExisting, 'qa/page/project/operations/kubernetes/add_existing'
autoload :Show, 'qa/page/project/operations/kubernetes/show'
end
+
+ autoload :Metrics, 'qa/page/project/operations/metrics'
end
module Wiki
@@ -429,6 +437,7 @@ module QA
autoload :NodeJs, 'qa/service/docker_run/node_js'
autoload :GitlabRunner, 'qa/service/docker_run/gitlab_runner'
autoload :MailHog, 'qa/service/docker_run/mail_hog'
+ autoload :SamlIdp, 'qa/service/docker_run/saml_idp'
end
end
@@ -464,6 +473,7 @@ module QA
autoload :Configure, 'qa/vendor/jenkins/page/configure'
autoload :NewCredentials, 'qa/vendor/jenkins/page/new_credentials'
autoload :NewJob, 'qa/vendor/jenkins/page/new_job'
+ autoload :Job, 'qa/vendor/jenkins/page/job'
autoload :ConfigureJob, 'qa/vendor/jenkins/page/configure_job'
end
end
diff --git a/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml b/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml
new file mode 100644
index 00000000000..a65ae5aa1d9
--- /dev/null
+++ b/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml
@@ -0,0 +1,337 @@
+# This is stripped down version of the .gitlab-ci.yml found
+# here: https://gitlab.com/joshlambert/autodevops-deploy.
+#
+# It performs only the deploy stage.
+
+image: alpine:latest
+
+variables:
+ # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
+ AUTO_DEVOPS_DOMAIN: my-fake-domain.com
+
+ POSTGRES_USER: user
+ POSTGRES_PASSWORD: testing-password
+ POSTGRES_ENABLED: 'false'
+ POSTGRES_DB: $CI_ENVIRONMENT_SLUG
+
+ KUBERNETES_VERSION: 1.11.6
+ HELM_VERSION: 2.12.2
+
+ DOCKER_DRIVER: overlay2
+
+stages:
+ - production
+
+# This job continuously deploys to production on every push to `master`.
+
+production:
+ stage: production
+ script:
+ - check_kube_domain
+ - install_dependencies
+ - download_chart
+ - ensure_namespace
+ - initialize_tiller
+ - create_secret
+ - deploy
+ - persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ artifacts:
+ paths: [environment_url.txt]
+ only:
+ refs:
+ - master
+ kubernetes: active
+
+# ---------------------------------------------------------------------------
+
+.auto_devops: &auto_devops |
+ # Auto DevOps variables and functions
+ [[ "$TRACE" ]] && set -x
+ auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB}
+ export DATABASE_URL=${DATABASE_URL-$auto_database_url}
+ export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ export CI_APPLICATION_TAG=$CI_COMMIT_SHA
+ export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
+ export TILLER_NAMESPACE=$KUBE_NAMESPACE
+ # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
+ export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+
+
+ function get_replicas() {
+ track="${1:-stable}"
+ percentage="${2:-100}"
+
+ env_track=$( echo $track | tr -s '[:lower:]' '[:upper:]' )
+ env_slug=$( echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]' )
+
+ if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
+ # for stable track get number of replicas from `PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_slug}_REPLICAS
+ if [[ -z "$new_replicas" ]]; then
+ new_replicas=$REPLICAS
+ fi
+ else
+ # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
+ if [[ -z "$new_replicas" ]]; then
+ eval new_replicas=\${env_track}_REPLICAS
+ fi
+ fi
+
+ replicas="${new_replicas:-1}"
+ replicas="$(($replicas * $percentage / 100))"
+
+ # always return at least one replicas
+ if [[ $replicas -gt 0 ]]; then
+ echo "$replicas"
+ else
+ echo 1
+ fi
+ }
+
+
+ # Extracts variables prefixed with K8S_SECRET_
+ # and creates a Kubernetes secret.
+ #
+ # e.g. If we have the following environment variables:
+ # K8S_SECRET_A=value1
+ # K8S_SECRET_B=multi\ word\ value
+ #
+ # Then we will create a secret with the following key-value pairs:
+ # data:
+ # A: dmFsdWUxCg==
+ # B: bXVsdGkgd29yZCB2YWx1ZQo=
+ function create_application_secret() {
+ track="${1-stable}"
+ export APPLICATION_SECRET_NAME=$(application_secret_name "$track")
+
+ env | sed -n "s/^K8S_SECRET_\(.*\)$/\1/p" > k8s_prefixed_variables
+
+ kubectl create secret \
+ -n "$KUBE_NAMESPACE" generic "$APPLICATION_SECRET_NAME" \
+ --from-env-file k8s_prefixed_variables -o yaml --dry-run |
+ kubectl replace -n "$KUBE_NAMESPACE" --force -f -
+
+ export APPLICATION_SECRET_CHECKSUM=$(cat k8s_prefixed_variables | sha256sum | cut -d ' ' -f 1)
+
+ rm k8s_prefixed_variables
+ }
+
+ function deploy_name() {
+ name="$CI_ENVIRONMENT_SLUG"
+ track="${1-stable}"
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ echo $name
+ }
+
+ function application_secret_name() {
+ track="${1-stable}"
+ name=$(deploy_name "$track")
+
+ echo "${name}-secret"
+ }
+
+
+ function deploy() {
+ track="${1-stable}"
+ percentage="${2:-100}"
+ name=$(deploy_name "$track")
+
+ replicas="1"
+ service_enabled="true"
+ postgres_enabled="$POSTGRES_ENABLED"
+
+ # if track is different than stable,
+ # re-use all attached resources
+ if [[ "$track" != "stable" ]]; then
+ service_enabled="false"
+ postgres_enabled="false"
+ fi
+
+ replicas=$(get_replicas "$track" "$percentage")
+
+ if [[ "$CI_PROJECT_VISIBILITY" != "public" ]]; then
+ secret_name='gitlab-registry'
+ else
+ secret_name=''
+ fi
+
+ create_application_secret "$track"
+
+ env_slug=$(echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]')
+ eval env_ADDITIONAL_HOSTS=\$${env_slug}_ADDITIONAL_HOSTS
+ if [ -n "$env_ADDITIONAL_HOSTS" ]; then
+ additional_hosts="{$env_ADDITIONAL_HOSTS}"
+ elif [ -n "$ADDITIONAL_HOSTS" ]; then
+ additional_hosts="{$ADDITIONAL_HOSTS}"
+ fi
+
+ if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
+ echo "Deploying first release with database initialization..."
+ helm upgrade --install \
+ --wait \
+ --set service.enabled="$service_enabled" \
+ --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
+ --set image.repository="registry.gitlab.com/joshlambert/ruby-gke/master" \
+ --set image.tag="63492726c2264a0277141d6a6573c3d22ecd7de3" \
+ --set image.pullPolicy=IfNotPresent \
+ --set image.secrets[0].name="$secret_name" \
+ --set application.track="$track" \
+ --set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
+ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.url="$CI_ENVIRONMENT_URL" \
+ --set service.additionalHosts="$additional_hosts" \
+ --set replicaCount="$replicas" \
+ --set postgresql.enabled="$postgres_enabled" \
+ --set postgresql.nameOverride="postgres" \
+ --set postgresql.postgresUser="$POSTGRES_USER" \
+ --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
+ --set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set application.initializeCommand="$DB_INITIALIZE" \
+ --set gitlab.app="$CI_PROJECT_PATH_SLUG" \
+ --set gitlab.env="$CI_ENVIRONMENT_SLUG" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+
+ echo "Deploying second release..."
+ helm upgrade --reuse-values \
+ --wait \
+ --set application.initializeCommand="" \
+ --set application.migrateCommand="$DB_MIGRATE" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ else
+ echo "Deploying new release..."
+ helm upgrade --install \
+ --wait \
+ --set service.enabled="$service_enabled" \
+ --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
+ --set image.repository="registry.gitlab.com/joshlambert/ruby-gke/master" \
+ --set image.tag="63492726c2264a0277141d6a6573c3d22ecd7de3" \
+ --set image.pullPolicy=IfNotPresent \
+ --set image.secrets[0].name="$secret_name" \
+ --set application.track="$track" \
+ --set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
+ --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.url="$CI_ENVIRONMENT_URL" \
+ --set service.additionalHosts="$additional_hosts" \
+ --set replicaCount="$replicas" \
+ --set postgresql.enabled="$postgres_enabled" \
+ --set postgresql.nameOverride="postgres" \
+ --set postgresql.postgresUser="$POSTGRES_USER" \
+ --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
+ --set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set application.migrateCommand="$DB_MIGRATE" \
+ --set gitlab.app="$CI_PROJECT_PATH_SLUG" \
+ --set gitlab.env="$CI_ENVIRONMENT_SLUG" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ fi
+
+ kubectl rollout status -n "$KUBE_NAMESPACE" -w "deployment/$name"
+ }
+
+
+ function install_dependencies() {
+ apk add -U openssl curl tar gzip bash ca-certificates git
+ wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
+ wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk
+ apk add glibc-2.23-r3.apk
+ rm glibc-2.23-r3.apk
+
+ curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx
+ mv linux-amd64/helm /usr/bin/
+ mv linux-amd64/tiller /usr/bin/
+ helm version --client
+ tiller -version
+
+ curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
+ chmod +x /usr/bin/kubectl
+ kubectl version --client
+ }
+
+ function download_chart() {
+ if [[ ! -d chart ]]; then
+ auto_chart=${AUTO_DEVOPS_CHART:-gitlab/auto-deploy-app}
+ auto_chart_name=$(basename $auto_chart)
+ auto_chart_name=${auto_chart_name%.tgz}
+ else
+ auto_chart="chart"
+ auto_chart_name="chart"
+ fi
+
+ helm init --client-only
+ helm repo add gitlab https://charts.gitlab.io
+ if [[ ! -d "$auto_chart" ]]; then
+ helm fetch ${auto_chart} --untar
+ fi
+ if [ "$auto_chart_name" != "chart" ]; then
+ mv ${auto_chart_name} chart
+ fi
+
+ helm dependency update chart/
+ helm dependency build chart/
+ }
+
+ function ensure_namespace() {
+ kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
+ }
+
+ function check_kube_domain() {
+ if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then
+ echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
+ echo "You can do it in Auto DevOps project settings or defining a secret variable at group or project level"
+ echo "You can also manually add it in .gitlab-ci.yml"
+ false
+ else
+ true
+ fi
+ }
+
+ function initialize_tiller() {
+ echo "Checking Tiller..."
+
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr > /dev/null 2>&1 &
+ echo "Tiller is listening on ${HELM_HOST}"
+
+ if ! helm version --debug; then
+ echo "Failed to init Tiller."
+ return 1
+ fi
+ echo ""
+ }
+
+ function create_secret() {
+ echo "Create secret..."
+ if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
+ return
+ fi
+
+ kubectl create secret -n "$KUBE_NAMESPACE" \
+ docker-registry gitlab-registry \
+ --docker-server="$CI_REGISTRY" \
+ --docker-username="$CI_REGISTRY_USER" \
+ --docker-password="$CI_REGISTRY_PASSWORD" \
+ --docker-email="$GITLAB_USER_EMAIL" \
+ -o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
+ }
+
+ function persist_environment_url() {
+ echo $CI_ENVIRONMENT_URL > environment_url.txt
+ }
+
+before_script:
+ - *auto_devops
diff --git a/qa/qa/flow/saml.rb b/qa/qa/flow/saml.rb
new file mode 100644
index 00000000000..676be2beb01
--- /dev/null
+++ b/qa/qa/flow/saml.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module QA
+ module Flow
+ module Saml
+ module_function
+
+ def page
+ Capybara.current_session
+ end
+
+ def logout_from_idp(saml_idp_service)
+ Runtime::Logger.debug("Logging out of IDP by visiting \"#{saml_idp_service.idp_sign_out_url}\"")
+
+ Support::Waiter.wait_until(sleep_interval: 1, reload_page: page) do
+ page.visit saml_idp_service.idp_sign_out_url
+ page.has_content?("You have been logged out.")
+ end
+ end
+
+ def enable_saml_sso(group, saml_idp_service)
+ page.visit Runtime::Scenario.gitlab_address
+
+ Page::Main::Login.perform(&:sign_in_using_credentials) unless Page::Main::Menu.perform(&:signed_in?)
+
+ visit_saml_sso_settings(group)
+
+ Support::Retrier.retry_on_exception do
+ EE::Page::Group::Settings::SamlSSO.perform do |saml_sso|
+ saml_sso.set_id_provider_sso_url(saml_idp_service.idp_sso_url)
+ saml_sso.set_cert_fingerprint(saml_idp_service.idp_certificate_fingerprint)
+ saml_sso.click_save_changes
+
+ saml_sso.user_login_url_link_text
+ end
+ end
+ end
+
+ def visit_saml_sso_settings(group, direct: false)
+ if direct
+ url = "#{group.web_url}/-/saml"
+ Runtime::Logger.debug("Visiting url \"#{url}\" directly")
+ page.visit url
+ else
+ group.visit!
+
+ Page::Group::Menu.perform(&:go_to_saml_sso_group_settings)
+ end
+ # The toggle buttons take a moment to switch to the correct status.
+ # I am not sure of a better, less complex way to wait for them to reflect their actual status.
+ sleep 2
+ end
+
+ def run_saml_idp_service(group_name)
+ service = Service::DockerRun::SamlIdp.new(Runtime::Scenario.gitlab_address, group_name).tap do |runner|
+ runner.pull
+ runner.register!
+ end
+
+ service
+ end
+
+ def remove_saml_idp_service(saml_idp_service)
+ saml_idp_service.remove!
+ end
+
+ def login_to_idp_if_required(username, password)
+ Vendor::SAMLIdp::Page::Login.perform { |login_page| login_page.login_if_required(username, password) }
+ end
+ end
+ end
+end
diff --git a/qa/qa/flow/user.rb b/qa/qa/flow/user.rb
new file mode 100644
index 00000000000..acc77cb9830
--- /dev/null
+++ b/qa/qa/flow/user.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ module Flow
+ module User
+ module_function
+
+ def page
+ Capybara.current_session
+ end
+
+ def confirm_user(username)
+ Flow::Login.while_signed_in_as_admin do
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_users_overview)
+ Page::Admin::Overview::Users::Index.perform do |index|
+ index.search_user(username)
+ index.click_user(username)
+ end
+
+ Page::Admin::Overview::Users::Show.perform(&:confirm_user)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index a4c44f78ad4..22b0021ea77 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -26,13 +26,13 @@ module QA
wait_for_requests
end
- def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: false)
+ def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: true)
Support::Waiter.wait_until(max_duration: max_duration, sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do
yield || (reload && refresh && false)
end
end
- def retry_until(max_attempts: 3, reload: false, sleep_interval: 0, raise_on_failure: false)
+ def retry_until(max_attempts: 3, reload: false, sleep_interval: 0, raise_on_failure: true)
Support::Retrier.retry_until(max_attempts: max_attempts, reload_page: (reload && self), sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do
yield
end
@@ -177,7 +177,7 @@ module QA
# The number of selectors should be able to be reduced after
# migration to the new spinner is complete.
# https://gitlab.com/groups/gitlab-org/-/epics/956
- has_no_css?('.gl-spinner, .fa-spinner, .spinner', wait: Capybara.default_max_wait_time)
+ has_no_css?('.gl-spinner, .fa-spinner, .spinner', wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
end
def finished_loading_block?
@@ -255,12 +255,6 @@ module QA
click_link text
end
- def click_body
- wait_for_requests
-
- find('body').click
- end
-
def visit_link_in_element(name)
visit find_element(name)['href']
end
diff --git a/qa/qa/page/component/ci_badge_link.rb b/qa/qa/page/component/ci_badge_link.rb
index d3e44fd867d..ef9bfa560ce 100644
--- a/qa/qa/page/component/ci_badge_link.rb
+++ b/qa/qa/page/component/ci_badge_link.rb
@@ -5,7 +5,22 @@ module QA
module Component
module CiBadgeLink
COMPLETED_STATUSES = %w[passed failed canceled blocked skipped manual].freeze # excludes created, pending, running
- PASSED_STATUS = 'passed'.freeze
+ INCOMPLETE_STATUSES = %w[pending created running].freeze
+
+ # e.g. def passed?(timeout: nil); status_badge == 'passed'; end
+ COMPLETED_STATUSES.map do |status|
+ define_method "#{status}?" do |timeout: nil|
+ timeout ? completed?(timeout: timeout) : completed?
+ status_badge == status
+ end
+ end
+
+ # e.g. def pending?; status_badge == 'pending'; end
+ INCOMPLETE_STATUSES.map do |status|
+ define_method "#{status}?" do
+ status_badge == status
+ end
+ end
def self.included(base)
base.view 'app/assets/javascripts/vue_shared/components/ci_badge_link.vue' do
@@ -17,12 +32,6 @@ module QA
find_element(:status_badge).text
end
- def successful?(timeout: 60)
- raise "Timed out waiting for the status to be a valid completed state" unless completed?(timeout: timeout)
-
- status_badge == PASSED_STATUS
- end
-
private
def completed?(timeout: 60)
diff --git a/qa/qa/page/component/select2.rb b/qa/qa/page/component/select2.rb
index 1dd718a1d88..e667fad1dd3 100644
--- a/qa/qa/page/component/select2.rb
+++ b/qa/qa/page/component/select2.rb
@@ -34,6 +34,10 @@ module QA
has_css?('.select2-active', wait: 1)
has_no_css?('.select2-active', wait: 30)
end
+
+ def dropdown_open?
+ has_css?('.select2-input')
+ end
end
end
end
diff --git a/qa/qa/page/dashboard/snippet/new.rb b/qa/qa/page/dashboard/snippet/new.rb
index 4a8e65e20af..df4c2902b31 100644
--- a/qa/qa/page/dashboard/snippet/new.rb
+++ b/qa/qa/page/dashboard/snippet/new.rb
@@ -10,17 +10,25 @@ module QA
end
view 'app/views/shared/snippets/_form.html.haml' do
+ element :description_field
+ element :description_placeholder
element :snippet_title
element :snippet_file_name
element :create_snippet_button
end
+ view 'app/views/projects/_zen.html.haml' do
+ # This 'element' is here only to ensure the changes in the view source aren't mistakenly changed
+ element :_, "qa_selector = local_assigns.fetch(:qa_selector, '')" # rubocop:disable QA/ElementWithPattern
+ end
+
def fill_title(title)
fill_element :snippet_title, title
end
def fill_description(description)
- fill_element :issuable_form_description, description
+ click_element :description_placeholder
+ fill_element :description_field, description
end
def set_visibility(visibility)
diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb
index 2b3b872aff4..230511ce6f6 100644
--- a/qa/qa/page/group/menu.rb
+++ b/qa/qa/page/group/menu.rb
@@ -13,15 +13,22 @@ module QA
element :contribution_analytics_link
end
+ view 'app/views/layouts/nav/sidebar/_analytics_links.html.haml' do
+ element :analytics_link
+ element :analytics_sidebar_submenu
+ end
+
def click_group_members_item
within_sidebar do
click_element(:group_members_item)
end
end
- def click_group_analytics_item
- within_sidebar do
- click_element(:contribution_analytics_link)
+ def click_contribution_analytics_item
+ hover_element(:analytics_link) do
+ within_submenu(:analytics_sidebar_submenu) do
+ click_element(:contribution_analytics_link)
+ end
end
end
diff --git a/qa/qa/page/group/sub_menus/common.rb b/qa/qa/page/group/sub_menus/common.rb
index a378db80e4b..96efc8da98d 100644
--- a/qa/qa/page/group/sub_menus/common.rb
+++ b/qa/qa/page/group/sub_menus/common.rb
@@ -5,6 +5,8 @@ module QA
module Group
module SubMenus
module Common
+ include QA::Page::SubMenus::Common
+
def self.included(base)
base.class_eval do
view 'app/views/layouts/nav/sidebar/_group.html.haml' do
@@ -13,23 +15,10 @@ module QA
end
end
- def hover_element(element)
- within_sidebar do
- find_element(element).hover
- yield
- end
- end
+ private
- def within_sidebar
- within_element(:group_sidebar) do
- yield
- end
- end
-
- def within_submenu(element)
- within_element(element) do
- yield
- end
+ def sidebar_element
+ :group_sidebar
end
end
end
diff --git a/qa/qa/page/layout/performance_bar.rb b/qa/qa/page/layout/performance_bar.rb
index 4e144e67f12..c593783a730 100644
--- a/qa/qa/page/layout/performance_bar.rb
+++ b/qa/qa/page/layout/performance_bar.rb
@@ -21,9 +21,9 @@ module QA
has_element?(:performance_bar)
end
- def has_detailed_metrics?(count)
+ def has_detailed_metrics?(minimum_count)
retry_until(sleep_interval: 1) do
- all_elements(:detailed_metric_content, count: count).all? do |metric|
+ all_elements(:detailed_metric_content, minimum: minimum_count).all? do |metric|
metric.has_text?(%r{\d+})
end
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index ad5b3c97cb9..b69990bae9c 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -55,7 +55,7 @@ module QA
element :diffs_tab
end
- view 'app/assets/javascripts/diffs/components/diff_line_gutter_content.vue' do
+ view 'app/assets/javascripts/diffs/components/diff_table_cell.vue' do
element :diff_comment
end
@@ -155,6 +155,8 @@ module QA
def merge!
click_element :merge_button if ready_to_merge?
+ finished_loading?
+
raise "Merge did not appear to be successful" unless merged?
end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index a1e1bb4bc98..a56083ea25c 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -124,7 +124,7 @@ module QA
end
end
- click_body
+ click_element(:edit_link_labels)
labels.each do |label|
has_element?(:labels_block, text: label)
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 07dea3449f1..26db2f20c1b 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -13,11 +13,15 @@ module QA::Page
element :pipeline_path
end
+ view 'app/assets/javascripts/jobs/components/sidebar.vue' do
+ element :retry_button
+ end
+
def successful?(timeout: 60)
raise "Timed out waiting for the build trace to load" unless loaded?
raise "Timed out waiting for the status to be a valid completed state" unless completed?(timeout: timeout)
- status_badge == PASSED_STATUS
+ passed?
end
# Reminder: You may wish to wait for a particular job status before checking output
@@ -33,6 +37,10 @@ module QA::Page
result
end
+ def retry!
+ click_element :retry_button
+ end
+
private
def loaded?(wait: 60)
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index d0e8011d82d..97214e22820 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -32,8 +32,7 @@ module QA
def choose_namespace(namespace)
retry_on_exception do
- click_body
- click_element :project_namespace_select
+ click_element :project_namespace_select unless dropdown_open?
search_and_select(namespace)
end
end
diff --git a/qa/qa/page/project/operations/metrics.rb b/qa/qa/page/project/operations/metrics.rb
new file mode 100644
index 00000000000..418cc925186
--- /dev/null
+++ b/qa/qa/page/project/operations/metrics.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Operations
+ class Metrics < Page::Base
+ EXPECTED_TITLE = 'Memory Usage (Total)'
+ LOADING_MESSAGE = 'Waiting for performance data'
+
+ view 'app/assets/javascripts/monitoring/components/dashboard.vue' do
+ element :prometheus_graphs
+ end
+
+ view 'app/assets/javascripts/monitoring/components/charts/time_series.vue' do
+ element :prometheus_graph_widgets
+ end
+
+ view 'app/assets/javascripts/monitoring/components/panel_type.vue' do
+ element :prometheus_widgets_dropdown
+ element :alert_widget_menu_item
+ end
+
+ def wait_for_metrics
+ wait_for_data
+ return if has_metrics?
+
+ wait_until(max_duration: 180) do
+ wait_for_data
+ has_metrics?
+ end
+ end
+
+ def wait_for_data
+ wait_until(reload: false) { !has_text?(LOADING_MESSAGE) } if has_text?(LOADING_MESSAGE)
+ end
+
+ def has_metrics?
+ within_element :prometheus_graphs do
+ has_text?(EXPECTED_TITLE)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+QA::Page::Project::Operations::Metrics.prepend_if_ee('QA::EE::Page::Project::Operations::Metrics')
diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb
index 684ad4a59d5..f018e4bf018 100644
--- a/qa/qa/page/project/pipeline/index.rb
+++ b/qa/qa/page/project/pipeline/index.rb
@@ -9,6 +9,7 @@ module QA::Page
view 'app/assets/javascripts/pipelines/components/pipelines_table_row.vue' do
element :pipeline_commit_status
+ element :pipeline_retry_button
end
def click_on_latest_pipeline
@@ -18,10 +19,25 @@ module QA::Page
end
def wait_for_latest_pipeline_success
+ wait_for_latest_pipeline_status { has_text?('passed') }
+ end
+
+ def wait_for_latest_pipeline_completion
+ wait_for_latest_pipeline_status { has_text?('passed') || has_text?('failed') }
+ end
+
+ def wait_for_latest_pipeline_status
wait_until(reload: false, max_duration: 300) do
- within_element_by_index(:pipeline_commit_status, 0) do
- has_text?('passed')
- end
+ within_element_by_index(:pipeline_commit_status, 0) { yield }
+ end
+ end
+
+ def wait_for_latest_pipeline_success_or_retry
+ wait_for_latest_pipeline_completion
+
+ if has_text?('failed')
+ click_element :pipeline_retry_button
+ wait_for_latest_pipeline_success
end
end
end
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index 45fffbf6000..1003b828a32 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -30,9 +30,9 @@ module QA::Page
element :pipeline_badges
end
- def running?
+ def running?(wait: 0)
within('.ci-header-container') do
- page.has_content?('running')
+ page.has_content?('running', wait: wait)
end
end
diff --git a/qa/qa/page/project/settings/ci_variables.rb b/qa/qa/page/project/settings/ci_variables.rb
index 64a182e5b3a..2bb285d6086 100644
--- a/qa/qa/page/project/settings/ci_variables.rb
+++ b/qa/qa/page/project/settings/ci_variables.rb
@@ -52,6 +52,14 @@ module QA
end
end
+ def remove_variable(location: :first)
+ within('.ci-variable-row-body', match: location) do
+ find('button.ci-variable-row-remove-button').click
+ end
+
+ save_variables
+ end
+
private
def toggle_masked(masked_node, masked)
diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb
index f718311fbf2..9d302acb058 100644
--- a/qa/qa/page/project/settings/protected_branches.rb
+++ b/qa/qa/page/project/settings/protected_branches.rb
@@ -47,6 +47,7 @@ module QA
def protect_branch
click_element(:protect_button, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
+ wait_for_requests
end
private
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index c619bd6d6a3..61047c42fcc 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -7,6 +7,14 @@ module QA
include Page::Component::ClonePanel
include Page::Project::SubMenus::Settings
+ view 'app/assets/javascripts/repository/components/table/row.vue' do
+ element :file_name_link
+ end
+
+ view 'app/assets/javascripts/repository/components/table/index.vue' do
+ element :file_tree_table
+ end
+
view 'app/views/layouts/header/_new_dropdown.haml' do
element :new_menu_toggle
element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern
@@ -17,7 +25,8 @@ module QA
end
view 'app/views/projects/_home_panel.html.haml' do
- element :project_name
+ element :forked_from_link
+ element :project_name_content
end
view 'app/views/projects/_files.html.haml' do
@@ -37,10 +46,6 @@ module QA
element :quick_actions
end
- view 'app/views/projects/tree/_tree_content.html.haml' do
- element :file_tree
- end
-
view 'app/views/projects/tree/_tree_header.html.haml' do
element :add_to_tree
element :new_file_option
@@ -79,14 +84,18 @@ module QA
click_on 'Fork'
end
+ def forked_from?(parent_project_name)
+ has_element?(:forked_from_link, text: parent_project_name)
+ end
+
def click_file(filename)
- within_element(:file_tree) do
+ within_element(:file_tree_table) do
click_on filename
end
end
def click_commit(commit_msg)
- within_element(:file_tree) do
+ within_element(:file_tree_table) do
click_on commit_msg
end
end
@@ -96,6 +105,16 @@ module QA
click_link 'New issue'
end
+ def has_file?(name)
+ within_element(:file_tree_table) do
+ has_element?(:file_name_link, text: name)
+ end
+ end
+
+ def has_name?(name)
+ has_element?(:project_name_content, text: name)
+ end
+
def last_commit_content
find_element(:commit_content).text
end
@@ -113,7 +132,7 @@ module QA
end
def project_name
- find('.qa-project-name').text
+ find_element(:project_name_content).text
end
def switch_to_branch(branch_name)
diff --git a/qa/qa/page/project/sub_menus/common.rb b/qa/qa/page/project/sub_menus/common.rb
index 3c9e8085748..da759398cff 100644
--- a/qa/qa/page/project/sub_menus/common.rb
+++ b/qa/qa/page/project/sub_menus/common.rb
@@ -5,20 +5,12 @@ module QA
module Project
module SubMenus
module Common
- def within_sidebar
- within('.sidebar-top-level-items') do
- yield
- end
- end
+ include QA::Page::SubMenus::Common
+
+ private
- def within_submenu
- if has_css?('.fly-out-list')
- within('.fly-out-list') do
- yield
- end
- else
- yield
- end
+ def sidebar_element
+ :project_sidebar
end
end
end
diff --git a/qa/qa/page/project/sub_menus/operations.rb b/qa/qa/page/project/sub_menus/operations.rb
index d266cb21417..bcbc1dc16d3 100644
--- a/qa/qa/page/project/sub_menus/operations.rb
+++ b/qa/qa/page/project/sub_menus/operations.rb
@@ -12,6 +12,7 @@ module QA
view 'app/views/layouts/nav/sidebar/_project.html.haml' do
element :link_operations
element :operations_environments_link
+ element :operations_metrics_link
end
end
end
@@ -24,6 +25,14 @@ module QA
end
end
+ def go_to_operations_metrics
+ hover_operations do
+ within_submenu do
+ click_element(:operations_metrics_link)
+ end
+ end
+ end
+
def go_to_operations_kubernetes
hover_operations do
within_submenu do
diff --git a/qa/qa/page/sub_menus/common.rb b/qa/qa/page/sub_menus/common.rb
new file mode 100644
index 00000000000..0eb1b100bd7
--- /dev/null
+++ b/qa/qa/page/sub_menus/common.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module SubMenus
+ module Common
+ def hover_element(element)
+ within_sidebar do
+ find_element(element).hover
+ yield
+ end
+ end
+
+ def within_sidebar
+ within_element(sidebar_element) do
+ yield
+ end
+ end
+
+ def within_submenu(element = nil)
+ if element
+ within_element(element) do
+ yield
+ end
+ else
+ within_submenu_without_element do
+ yield
+ end
+ end
+ end
+
+ private
+
+ def within_submenu_without_element
+ if has_css?('.fly-out-list')
+ within('.fly-out-list') do
+ yield
+ end
+ else
+ yield
+ end
+ end
+
+ def sidebar_element
+ raise NotImplementedError
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
index e6057433b55..cac58c599ea 100644
--- a/qa/qa/resource/api_fabricator.rb
+++ b/qa/qa/resource/api_fabricator.rb
@@ -8,10 +8,12 @@ module QA
module ApiFabricator
include Capybara::DSL
- ResourceNotFoundError = Class.new(RuntimeError)
ResourceFabricationFailedError = Class.new(RuntimeError)
- ResourceURLMissingError = Class.new(RuntimeError)
ResourceNotDeletedError = Class.new(RuntimeError)
+ ResourceNotFoundError = Class.new(RuntimeError)
+ ResourceQueryError = Class.new(RuntimeError)
+ ResourceUpdateFailedError = Class.new(RuntimeError)
+ ResourceURLMissingError = Class.new(RuntimeError)
attr_reader :api_resource, :api_response
attr_writer :api_client
@@ -31,6 +33,12 @@ module QA
resource_web_url(api_post)
end
+ def reload!
+ api_get
+
+ self
+ end
+
def remove_via_api!
api_delete
end
diff --git a/qa/qa/resource/events/base.rb b/qa/qa/resource/events/base.rb
index f98a54a6f57..91ec0e59e37 100644
--- a/qa/qa/resource/events/base.rb
+++ b/qa/qa/resource/events/base.rb
@@ -3,7 +3,7 @@
module QA
module Resource
module Events
- MAX_WAIT = 10
+ MAX_WAIT = 60
RAISE_ON_FAILURE = true
EventNotFoundError = Class.new(RuntimeError)
diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb
index 73f1b0b9695..854dd92e89c 100644
--- a/qa/qa/resource/fork.rb
+++ b/qa/qa/resource/fork.rb
@@ -3,19 +3,24 @@
module QA
module Resource
class Fork < Base
+ attribute :name do
+ upstream.name
+ end
+
attribute :project do
- Resource::Project.fabricate! do |resource|
- resource.name = upstream.project.name
- resource.path_with_namespace = "#{user.name}/#{upstream.project.name}"
+ Resource::Project.fabricate_via_api! do |resource|
+ resource.add_name_uuid = false
+ resource.name = name
+ resource.path_with_namespace = "#{user.username}/#{name}"
end
end
attribute :upstream do
- Repository::ProjectPush.fabricate!
+ Repository::ProjectPush.fabricate!.project
end
attribute :user do
- User.fabricate! do |resource|
+ User.fabricate_via_api! do |resource|
if Runtime::Env.forker?
resource.username = Runtime::Env.forker_username
resource.password = Runtime::Env.forker_password
@@ -33,7 +38,7 @@ module QA
login.sign_in_using_credentials(user: user)
end
- upstream.project.visit!
+ upstream.visit!
Page::Project::Show.perform(&:fork_project)
@@ -47,6 +52,41 @@ module QA
populate(:project)
end
+
+ def fabricate_via_api!
+ populate(:upstream, :user)
+
+ Runtime::Logger.debug("Forking project #{upstream.name} to namespace #{user.username}...")
+ super
+ wait_until_forked
+
+ populate(:project)
+ end
+
+ def api_get_path
+ "/projects/#{CGI.escape(path_with_namespace)}"
+ end
+
+ def api_post_path
+ "/projects/#{upstream.id}/fork"
+ end
+
+ def api_post_body
+ {
+ namespace: user.username,
+ name: name,
+ path: name
+ }
+ end
+
+ def wait_until_forked
+ Runtime::Logger.debug("Waiting for the fork process to complete...")
+ forked = wait_until do
+ project.import_status == "finished"
+ end
+
+ raise "Timed out while waiting for the fork process to complete." unless forked
+ end
end
end
end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index 0824512d238..a30bb8cbc77 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -16,6 +16,7 @@ module QA
attribute :id
attribute :name
+ attribute :runners_token
def initialize
@path = Runtime::Namespace.name
diff --git a/qa/qa/resource/members.rb b/qa/qa/resource/members.rb
index c738a91a77f..38a620a5427 100644
--- a/qa/qa/resource/members.rb
+++ b/qa/qa/resource/members.rb
@@ -11,6 +11,10 @@ module QA
post Runtime::API::Request.new(api_client, api_members_path).url, { user_id: user.id, access_level: access_level }
end
+ def remove_member(user)
+ delete Runtime::API::Request.new(api_client, "#{api_members_path}/#{user.id}").url
+ end
+
def list_members
JSON.parse(get(Runtime::API::Request.new(api_client, api_members_path).url).body)
end
diff --git a/qa/qa/resource/merge_request_from_fork.rb b/qa/qa/resource/merge_request_from_fork.rb
index 9cb4e6a49ca..d9c86b3b527 100644
--- a/qa/qa/resource/merge_request_from_fork.rb
+++ b/qa/qa/resource/merge_request_from_fork.rb
@@ -8,7 +8,7 @@ module QA
attr_accessor :fork_branch
attribute :fork do
- Fork.fabricate!
+ Fork.fabricate_via_browser_ui!
end
attribute :push do
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index f2ca0e0b8fd..62e55e18e9b 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -94,6 +94,10 @@ module QA
"#{api_get_path}/runners"
end
+ def api_put_path
+ "/projects/#{id}"
+ end
+
def api_post_path
'/projects'
end
@@ -115,6 +119,35 @@ module QA
post_body
end
+ def change_repository_storage(new_storage)
+ put_body = { repository_storage: new_storage }
+ response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body
+
+ unless response.code == HTTP_STATUS_OK
+ raise ResourceUpdateFailedError, "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`."
+ end
+
+ wait_until do
+ reload!
+
+ api_response[:repository_storage] == new_storage
+ end
+ end
+
+ def import_status
+ response = get Runtime::API::Request.new(api_client, "/projects/#{id}/import").url
+
+ unless response.code == HTTP_STATUS_OK
+ raise ResourceQueryError, "Could not get import status. Request returned (#{response.code}): `#{response}`."
+ end
+
+ result = parse_body(response)
+
+ Runtime::Logger.error("Import failed: #{result[:import_error]}") if result[:import_status] == "failed"
+
+ result[:import_status]
+ end
+
def runners(tag_list: nil)
response = get Runtime::API::Request.new(api_client, "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}").url
parse_body(response)
diff --git a/qa/qa/resource/project_milestone.rb b/qa/qa/resource/project_milestone.rb
index 11aad4ae65f..4d6b37937b4 100644
--- a/qa/qa/resource/project_milestone.rb
+++ b/qa/qa/resource/project_milestone.rb
@@ -3,33 +3,17 @@
module QA
module Resource
class ProjectMilestone < Base
- attr_reader :title
- attr_accessor :description
+ attribute :id
+ attribute :title
attribute :project do
- Project.fabricate!
- end
-
- def title=(title)
- @title = "#{title}-#{SecureRandom.hex(4)}"
- @description = 'A milestone'
- end
-
- def fabricate!
- project.visit!
-
- Page::Project::Menu.perform do |menu|
- menu.click_issues
- menu.click_milestones
+ Project.fabricate_via_api! do |resource|
+ resource.name = 'project-with-milestone'
end
+ end
- Page::Project::Milestone::Index.perform(&:click_new_milestone)
-
- Page::Project::Milestone::New.perform do |milestone_new|
- milestone_new.set_title(@title)
- milestone_new.set_description(@description)
- milestone_new.click_milestone_create_button
- end
+ def initialize
+ @title = "project-milestone-#{SecureRandom.hex(4)}"
end
def api_get_path
@@ -42,8 +26,7 @@ module QA
def api_post_body
{
- description: @description,
- title: @title
+ title: title
}
end
end
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
index 54c13071cef..7b427af6b74 100644
--- a/qa/qa/resource/sandbox.rb
+++ b/qa/qa/resource/sandbox.rb
@@ -63,6 +63,10 @@ module QA
'/groups'
end
+ def api_delete_path
+ "/groups/#{id}"
+ end
+
def api_post_body
{
path: path,
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index 9544a3e80b3..e6dbe3faa61 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -35,14 +35,17 @@ module QA
end
def email
- @email ||= "#{username}@example.com"
+ @email ||= begin
+ api_email = api_resource&.dig(:email)
+ api_email && !api_email.empty? ? api_email : "#{username}@example.com"
+ end
end
def public_email
@public_email ||= begin
api_public_email = api_resource&.dig(:public_email)
- api_public_email && api_public_email != '' ? api_public_email : Runtime::User.default_email
+ api_public_email && !api_public_email.empty? ? api_public_email : Runtime::User.default_email
end
end
@@ -87,6 +90,8 @@ module QA
end
def api_get_path
+ return "/user" if fetching_own_data?
+
"/users/#{fetch_id(username)}"
end
@@ -136,6 +141,10 @@ module QA
users.first[:id]
end
+
+ def fetching_own_data?
+ user&.username == username || Runtime::User.username == username
+ end
end
end
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 340f6dc0356..69ba90702be 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -15,10 +15,6 @@ module QA
CAPYBARA_MAX_WAIT_TIME = 10
- class << self
- attr_accessor :rspec_configured, :capybara_configured
- end
-
def initialize
self.class.configure!
end
@@ -49,40 +45,11 @@ module QA
end
def self.configure!
- configure_rspec!
- configure_capybara!
- end
-
- def self.configure_rspec!
- # We don't want to enter this infinite loop:
- # Runtime::Release.perform_before_hooks -> `QA::Runtime::Browser.visit` -> configure! -> configure_rspec! -> Runtime::Release.perform_before_hooks
- # So we make sure this method is called only once.
- return if self.rspec_configured
-
- browser = self
-
RSpec.configure do |config|
config.define_derived_metadata(file_path: %r{/qa/specs/features/}) do |metadata|
metadata[:type] = :feature
end
-
- config.before do
- unless browser.rspec_configured
- browser.rspec_configured = true
-
- ##
- # Perform before hooks, which are different for CE and EE
- #
- Runtime::Release.perform_before_hooks
- end
- end
end
- end
-
- def self.configure_capybara!
- return if self.capybara_configured
-
- self.capybara_configured = true
Capybara.server_port = 9887 + ENV['TEST_ENV_NUMBER'].to_i
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 6514e41e279..1c947b0329f 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -22,6 +22,10 @@ module QA
SUPPORTED_FEATURES
end
+ def additional_repository_storage
+ ENV['QA_ADDITIONAL_REPOSITORY_STORAGE']
+ end
+
def admin_password
ENV['GITLAB_ADMIN_PASSWORD']
end
diff --git a/qa/qa/runtime/feature.rb b/qa/qa/runtime/feature.rb
index 25fc02a887e..5e948b5b850 100644
--- a/qa/qa/runtime/feature.rb
+++ b/qa/qa/runtime/feature.rb
@@ -38,6 +38,8 @@ module QA
end
raise SetFeatureError, "#{key} was not enabled!" unless is_enabled
+
+ QA::Runtime::Logger.info("Successfully enabled and verified feature flag: #{key}")
end
end
@@ -46,6 +48,12 @@ module QA
feature && feature["state"] == "on"
end
+ def get_features
+ request = Runtime::API::Request.new(api_client, "/features")
+ response = get(request.url)
+ response.body
+ end
+
private
def api_client
@@ -74,12 +82,6 @@ module QA
raise SetFeatureError, "Setting feature flag #{key} to #{value} failed with `#{response}`."
end
end
-
- def get_features
- request = Runtime::API::Request.new(api_client, "/features")
- response = get(request.url)
- response.body
- end
end
end
end
diff --git a/qa/qa/runtime/release.rb b/qa/qa/runtime/release.rb
index 18a6736afcf..1cd0c62563b 100644
--- a/qa/qa/runtime/release.rb
+++ b/qa/qa/runtime/release.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+require 'capybara/rspec'
+require 'capybara-screenshot/rspec'
+
module QA
module Runtime
##
@@ -24,6 +27,13 @@ module QA
def self.method_missing(name, *args)
self.new.strategy.public_send(name, *args)
+ rescue
+ saved = Capybara::Screenshot.screenshot_and_save_page
+
+ QA::Runtime::Logger.error("Screenshot: #{saved[:image]}") if saved&.key?(:image)
+ QA::Runtime::Logger.error("HTML capture: #{saved[:html]}") if saved&.key?(:html)
+
+ raise
end
end
end
diff --git a/qa/qa/runtime/search.rb b/qa/qa/runtime/search.rb
index 74402301098..29a71b2815c 100644
--- a/qa/qa/runtime/search.rb
+++ b/qa/qa/runtime/search.rb
@@ -35,6 +35,8 @@ module QA
)
end
+ verify_search_engine_ok(search_term)
+
find_commit(commit, "commit*#{search_term}")
find_project(project, "to-search*#{search_term}")
end
@@ -74,9 +76,7 @@ module QA
end
def search(scope, term)
- QA::Runtime::Logger.debug("Search scope '#{scope}' for '#{term}'...")
- request = Runtime::API::Request.new(api_client, "/search?scope=#{scope}&search=#{term}")
- response = get(request.url)
+ response = get_response(scope, term)
unless response.code == singleton_class::HTTP_STATUS_OK
msg = "Search attempt failed. Request returned (#{response.code}): `#{response}`."
@@ -87,6 +87,19 @@ module QA
parse_body(response)
end
+ def get_response(scope, term)
+ QA::Runtime::Logger.debug("Search scope '#{scope}' for '#{term}'...")
+ request = Runtime::API::Request.new(api_client, "/search?scope=#{scope}&search=#{term}")
+ get(request.url)
+ end
+
+ def verify_search_engine_ok(search_term)
+ response = get_response('commits', search_term)
+ if response.code.to_s =~ /5[0-9][0-9]/
+ raise ElasticSearchServerError, "elasticsearch attempt returned code #{response.code}. Check that search was conducted on the appropriate url and port."
+ end
+ end
+
def api_client
@api_client ||= Runtime::API::Client.new(:gitlab)
end
diff --git a/qa/qa/scenario/template.rb b/qa/qa/scenario/template.rb
index 97373f7a059..74d4c8f8757 100644
--- a/qa/qa/scenario/template.rb
+++ b/qa/qa/scenario/template.rb
@@ -23,6 +23,11 @@ module QA
def perform(options, *args)
extract_address(:gitlab_address, options, args)
+ ##
+ # Perform before hooks, which are different for CE and EE
+ #
+ Runtime::Release.perform_before_hooks
+
Runtime::Feature.enable(options[:enable_feature]) if options.key?(:enable_feature)
Specs::Runner.perform do |specs|
diff --git a/qa/qa/scenario/test/instance.rb b/qa/qa/scenario/test/instance.rb
index 79dad7f4619..b4098619e4e 100644
--- a/qa/qa/scenario/test/instance.rb
+++ b/qa/qa/scenario/test/instance.rb
@@ -20,6 +20,11 @@ module QA
def self.do_perform(address, *rspec_options)
Runtime::Scenario.define(:gitlab_address, address)
+ ##
+ # Perform before hooks, which are different for CE and EE
+ #
+ Runtime::Release.perform_before_hooks
+
Specs::Runner.perform do |specs|
specs.tty = true
specs.options = rspec_options if rspec_options.any?
diff --git a/qa/qa/scenario/test/sanity/selectors.rb b/qa/qa/scenario/test/sanity/selectors.rb
index 99497cbe0ad..b2c90ab2e2a 100644
--- a/qa/qa/scenario/test/sanity/selectors.rb
+++ b/qa/qa/scenario/test/sanity/selectors.rb
@@ -34,8 +34,9 @@ module QA
Please update the code in `qa/` directory to make it match
current changes in this merge request.
- For more help see documentation in `qa/page/README.md` file or
- ask for help on #quality channel on Slack (GitLab Team only).
+ For more help see documentation in
+ https://docs.gitlab.com/ee/development/testing_guide/end_to_end/page_objects.html
+ or ask for help on #quality channel on Slack (GitLab Team only).
If you are not a Team Member, and you still need help to
contribute, please open an issue in GitLab QA issue tracker.
diff --git a/qa/qa/service/docker_run/saml_idp.rb b/qa/qa/service/docker_run/saml_idp.rb
new file mode 100644
index 00000000000..a0638bbcc2e
--- /dev/null
+++ b/qa/qa/service/docker_run/saml_idp.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module QA
+ module Service
+ module DockerRun
+ class SamlIdp < Base
+ def initialize(gitlab_host, group)
+ @image = 'jamedjo/test-saml-idp'
+ @name = 'saml-idp-server'
+ @gitlab_host = gitlab_host
+ @group = group
+ super()
+ end
+
+ def idp_base_url
+ "https://#{host_name}:8443/simplesaml"
+ end
+
+ def idp_sso_url
+ "#{idp_base_url}/saml2/idp/SSOService.php"
+ end
+
+ def idp_sign_out_url
+ "#{idp_base_url}/module.php/core/authenticate.php?as=example-userpass&logout"
+ end
+
+ def idp_signed_out_url
+ "#{idp_base_url}/logout.php"
+ end
+
+ def idp_metadata_url
+ "#{idp_base_url}/saml2/idp/metadata.php"
+ end
+
+ def idp_issuer
+ idp_metadata_url
+ end
+
+ def idp_certificate_fingerprint
+ QA::Runtime::Env.simple_saml_fingerprint || '119b9e027959cdb7c662cfd075d9e2ef384e445f'
+ end
+
+ def host_name
+ return 'localhost' unless QA::Runtime::Env.running_in_ci?
+
+ super
+ end
+
+ def register!
+ command = <<~CMD.tr("\n", ' ')
+ docker run -d --rm
+ --network #{network}
+ --hostname #{host_name}
+ --name #{@name}
+ --env SIMPLESAMLPHP_SP_ENTITY_ID=#{@gitlab_host}/groups/#{@group}
+ --env SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=#{@gitlab_host}/groups/#{@group}/-/saml/callback
+ --publish 8080:8080
+ --publish 8443:8443
+ #{@image}
+ CMD
+
+ command.gsub!("--network #{network} ", '') unless QA::Runtime::Env.running_in_ci?
+
+ shell command
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/close_issue_spec.rb b/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
index 2543c0091fb..f14fcc5afce 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/close_issue_spec.rb
+++ b/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
@@ -2,35 +2,34 @@
module QA
context 'Plan' do
- describe 'Close issue' do
+ include Support::Api
+
+ describe 'Issue' do
let(:issue) do
Resource::Issue.fabricate_via_api!
end
let(:issue_id) { issue.api_response[:iid] }
- before do
- Flow::Login.sign_in
+ let(:api_client) { Runtime::API::Client.new(:gitlab) }
+ before do
# Initial commit should be pushed because
# the very first commit to the project doesn't close the issue
# https://gitlab.com/gitlab-org/gitlab-foss/issues/38965
push_commit('Initial commit')
end
- it 'user closes an issue by pushing commit' do
+ it 'closes via pushing a commit' do
push_commit("Closes ##{issue_id}", false)
- issue.visit!
-
- Page::Project::Issue::Show.perform do |show|
- reopen_issue_button_visible = show.wait_until(reload: true) do
- show.has_element?(:reopen_issue_button, wait: 1.0)
- end
- expect(reopen_issue_button_visible).to be_truthy
+ Support::Retrier.retry_until(max_duration: 10, sleep_interval: 1) do
+ issue_closed?
end
end
+ private
+
def push_commit(commit_message, new_branch = true)
Resource::Repository::ProjectPush.fabricate! do |push|
push.commit_message = commit_message
@@ -39,6 +38,11 @@ module QA
push.project = issue.project
end
end
+
+ def issue_closed?
+ response = get Runtime::API::Request.new(api_client, "/projects/#{issue.project.id}/issues/#{issue_id}").url
+ parse_body(response)[:state] == 'closed'
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
index 70303a30153..dea85f68be2 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
module QA
- context 'Manage', :orchestrated, :oauth, quarantine: 'https://gitlab.com/gitlab-org/gitlab/issues/196517' do
+ # This test is skipped instead of quarantine because continuously running
+ # this test may cause the user to hit GitHub's rate limits thus blocking the user.
+ # Related issue: https://gitlab.com/gitlab-org/gitlab/issues/196517
+ context 'Manage', :orchestrated, :oauth, :skip do
describe 'OAuth login' do
it 'User logs in to GitLab with GitHub OAuth' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
index 9a273e9cd1c..e30afbf8ae0 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
@@ -8,10 +8,9 @@ module QA
user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
- project = Resource::Project.fabricate_via_api! do |resource|
- resource.name = 'add-member-project'
- end
- project.visit!
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'add-member-project'
+ end.visit!
Page::Project::Menu.perform(&:go_to_members_settings)
Page::Project::Settings::Members.perform do |members|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
index 14eaf770f10..409d67d51b1 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module QA
- # https://gitlab.com/gitlab-org/gitlab/issues/26952
- # BUG_IN_CODE
- context 'Manage', :github, :quarantine do
+ context 'Manage', :github, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/26952', type: :bug } do
describe 'Project import from GitHub' do
let(:imported_project) do
Resource::ProjectImportedFromGithub.fabricate! do |project|
diff --git a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
index eecf485a518..5f7a6981f23 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
@@ -8,8 +8,8 @@ module QA
end
let(:project) do
- Resource::Project.fabricate_via_api! do |resource|
- resource.name = 'email-notification-test'
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'email-notification-test'
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
index aa88937504e..57d2c02a27b 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
module QA
- context 'Plan' do
+ context 'Plan', :reliable do
describe 'check xss occurence in @mentions in issues', :requires_admin do
- it 'user mentions a user in comment' do
+ it 'mentions a user in a comment' do
QA::Runtime::Env.personal_access_token = QA::Runtime::Env.admin_personal_access_token
unless QA::Runtime::Env.personal_access_token
@@ -21,8 +21,8 @@ module QA
Flow::Login.sign_in
- project = Resource::Project.fabricate_via_api! do |resource|
- resource.name = 'xss-test-for-mentions-project'
+ project = Resource::Project.fabricate_via_api! do |project|
+ project.name = 'xss-test-for-mentions-project'
end
Flow::Project.add_member(project: project, username: user.username)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
index e505c0991a6..33d2c7026b3 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Plan' do
+ context 'Plan', :reliable do
describe 'collapse comments in issue discussions' do
let(:my_first_reply) { 'My first reply' }
@@ -17,7 +17,7 @@ module QA
end
end
- it 'user collapses and expands reply for comments in an issue' do
+ it 'collapses and expands reply for comments in an issue' do
Page::Project::Issue::Show.perform do |show|
one_reply = "1 reply"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
index 6c37e3ecbb9..4667eb6c587 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Plan' do
+ context 'Plan', :reliable do
describe 'Issue comments' do
before do
Flow::Login.sign_in
@@ -9,7 +9,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'user comments on an issue and edits the comment' do
+ it 'comments on an issue and edits the comment' do
Page::Project::Issue::Show.perform do |show|
first_version_of_comment = 'First version of the comment'
second_version_of_comment = 'Second version of the comment'
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index 3b231b9930e..7b4418191a3 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -7,7 +7,7 @@ module QA
Flow::Login.sign_in
end
- it 'user creates an issue' do
+ it 'creates an issue', :reliable do
issue = Resource::Issue.fabricate_via_browser_ui!
Page::Project::Menu.perform(&:click_issues)
@@ -27,7 +27,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'user comments on an issue with an attachment' do
+ it 'comments on an issue with an attachment' do
Page::Project::Issue::Show.perform do |show|
show.comment('See attached banana for scale', attachment: file_to_attach)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
index 4156ba54785..b7687f785a8 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Plan' do
+ context 'Plan', :reliable do
describe 'filter issue comments activities' do
before do
Flow::Login.sign_in
@@ -9,7 +9,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'user filters comments and activities in an issue' do
+ it 'filters comments and activities in an issue' do
Page::Project::Issue::Show.perform do |show|
my_own_comment = "My own comment"
made_the_issue_confidential = "made the issue confidential"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
index 9a1d13cf677..9b46a066c8e 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Plan' do
+ context 'Plan', :reliable do
describe 'issue suggestions' do
let(:issue_title) { 'Issue Lists are awesome' }
@@ -13,7 +13,7 @@ module QA
end.project.visit!
end
- it 'user sees issue suggestions when creating a new issue' do
+ it 'shows issue suggestions when creating a new issue' do
Page::Project::Show.perform(&:go_to_new_issue)
Page::Project::Issue::New.perform do |new_page|
new_page.add_title("issue")
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
index a0647df4097..3e575517ecb 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
module QA
- context 'Plan', :smoke do
+ context 'Plan', :smoke, :reliable do
describe 'mention' do
before do
Flow::Login.sign_in
@user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
- project = Resource::Project.fabricate_via_api! do |resource|
- resource.name = 'project-to-test-mention'
- resource.visibility = 'private'
+ project = Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-to-test-mention'
+ project.visibility = 'private'
end
project.add_member(@user)
@@ -20,7 +20,7 @@ module QA
end.visit!
end
- it 'user mentions another user in an issue' do
+ it 'mentions another user in an issue' do
Page::Project::Issue::Show.perform do |show|
at_username = "@#{@user.username}"
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index eaa1a2a0da8..4a9901f2a84 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -14,7 +14,7 @@ module QA
@merge_request_description = '... to find them, to bring them all, and in the darkness bind them'
end
- it 'creates a basic merge request', :smoke do
+ it 'creates a basic merge request' do
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
merge_request.project = @project
merge_request.title = @merge_request_title
@@ -32,7 +32,6 @@ module QA
milestone = Resource::ProjectMilestone.fabricate_via_api! do |milestone|
milestone.project = @project
- milestone.title = 'milestone'
end
label = Resource::Label.fabricate_via_api! do |label|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
index 370bf30f3a4..7d4e6b7efbc 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
@@ -6,7 +6,7 @@ module QA
it 'user forks a project, submits a merge request and maintainer merges it' do
Flow::Login.sign_in
- merge_request = Resource::MergeRequestFromFork.fabricate! do |merge_request|
+ merge_request = Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request|
merge_request.fork_branch = 'feature-branch'
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index e4c79bf75b5..6ebe3e0b620 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
module QA
- # Failure issue: https://gitlab.com/gitlab-org/gitlab/issues/36817
- # BUG_IN_CODE
- context 'Create', :quarantine do
+ context 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/36817', type: :bug } do
describe 'Merge request rebasing' do
it 'user rebases source branch of merge request' do
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
new file mode 100644
index 00000000000..13fe8918f97
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'Gitaly repository storage', :orchestrated, :repository_storage, :requires_admin, quarantine: { type: :new } do
+ let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
+ let(:parent_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'parent-project'
+ project.initialize_with_readme = true
+ end
+ end
+ let(:fork_project) do
+ Resource::Fork.fabricate_via_api! do |fork|
+ fork.user = user
+ fork.upstream = parent_project
+ end.project
+ end
+
+ before do
+ parent_project.add_member(user)
+ end
+
+ it 'creates a 2nd fork after moving the parent project' do
+ Flow::Login.sign_in(as: user)
+
+ fork_project.visit!
+
+ parent_project.change_repository_storage(QA::Runtime::Env.additional_repository_storage)
+
+ second_fork_project = Resource::Fork.fabricate_via_api! do |fork|
+ fork.name = "second-fork"
+ fork.user = user
+ fork.upstream = parent_project
+ end.project
+
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = second_fork_project
+ push.file_name = 'new_file'
+ push.file_content = '# This is a new file'
+ push.commit_message = 'Add new file'
+ push.new_branch = false
+ end.project.visit!
+
+ Page::Project::Show.perform do |show|
+ expect(show).to have_file('new_file')
+ expect(show).to have_name(second_fork_project.name)
+ expect(show).to be_forked_from(parent_project.name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
index 1f156dfe6d5..ff0f212c289 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
@@ -2,9 +2,7 @@
module QA
# Git protocol v2 is temporarily disabled
- # https://gitlab.com/gitlab-org/gitlab/issues/27828
- # BUG_IN_CODE
- context 'Create', :quarantine do
+ context 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/27828', type: :bug } do
describe 'Push over HTTP using Git protocol version 2', :requires_git_protocol_v2 do
it 'user pushes to the repository' do
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
index 55c70656462..0e8b8203c34 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
@@ -2,9 +2,7 @@
module QA
# Git protocol v2 is temporarily disabled
- # https://gitlab.com/gitlab-org/gitlab/issues/27828
- # BUG_IN_CODE
- context 'Create', :quarantine do
+ context 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/27828', type: :bug } do
describe 'Push over SSH using Git protocol version 2', :requires_git_protocol_v2 do
# Note: If you run this test against GDK make sure you've enabled sshd and
# enabled setting the Git protocol by adding `AcceptEnv GIT_PROTOCOL` to
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
index 70b571a316a..7c9db5ee496 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Create', quarantine: 'https://gitlab.com/gitlab-org/gitlab/issues/196034' do
+ context 'Create' do
describe 'Web IDE file templates' do
include Runtime::Fixtures
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb
deleted file mode 100644
index c813484347e..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- context 'Verify' do
- describe 'CI variable support' do
- it 'user adds a CI variable', :smoke do
- Flow::Login.sign_in
-
- project = Resource::Project.fabricate_via_api! do |project|
- project.name = 'project-with-ci-variables'
- project.description = 'project with CI variables'
- end
-
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = project
- resource.key = 'VARIABLE_KEY'
- resource.value = 'some_CI_variable'
- resource.masked = false
- end
-
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_ci_cd_settings)
-
- Page::Project::Settings::CICD.perform do |settings|
- settings.expand_ci_variables do |page|
- expect(page).to have_field(with: 'VARIABLE_KEY')
- expect(page).not_to have_field(with: 'some_CI_variable')
-
- page.reveal_variables
-
- expect(page).to have_field(with: 'some_CI_variable')
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
new file mode 100644
index 00000000000..9dad5ad8fb5
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Verify' do
+ describe 'Add or Remove CI variable via UI', :smoke do
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-ci-variables'
+ project.description = 'project with CI variables'
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ add_ci_variable
+ open_ci_cd_settings
+ end
+
+ it 'user adds a CI variable' do
+ Page::Project::Settings::CICD.perform do |settings|
+ settings.expand_ci_variables do |page|
+ expect(page).to have_field(with: 'VARIABLE_KEY')
+ expect(page).not_to have_field(with: 'some_CI_variable')
+
+ page.reveal_variables
+
+ expect(page).to have_field(with: 'some_CI_variable')
+ end
+ end
+ end
+
+ it 'user removes a CI variable' do
+ Page::Project::Settings::CICD.perform do |settings|
+ settings.expand_ci_variables do |page|
+ page.remove_variable
+
+ expect(page).not_to have_field(with: 'VARIABLE_KEY')
+ end
+ end
+ end
+
+ private
+
+ def add_ci_variable
+ Resource::CiVariable.fabricate_via_browser_ui! do |ci_variable|
+ ci_variable.project = project
+ ci_variable.key = 'VARIABLE_KEY'
+ ci_variable.value = 'some_CI_variable'
+ ci_variable.masked = false
+ end
+ end
+
+ def open_ci_cd_settings
+ project.visit!
+ Page::Project::Menu.perform(&:go_to_ci_cd_settings)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index d4853a7bcf3..05adcc718e8 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -1,82 +1,87 @@
# frozen_string_literal: true
module QA
- context 'Verify', :orchestrated, :docker do
+ context 'Verify', :docker do
describe 'Pipeline creation and processing' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
+ let(:max_wait) { 30 }
- after do
- Service::DockerRun::GitlabRunner.new(executor).remove!
- end
-
- it 'users creates a pipeline which gets processed' do
- Flow::Login.sign_in
-
- project = Resource::Project.fabricate! do |project|
- project.name = 'project-with-pipelines'
- project.description = 'Project with CI/CD Pipelines.'
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-pipeline'
end
+ end
+ before do
Resource::Runner.fabricate! do |runner|
runner.project = project
runner.name = executor
- runner.tags = %w[qa test]
+ runner.tags = [executor]
end
+ end
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.file_name = '.gitlab-ci.yml'
- push.commit_message = 'Add .gitlab-ci.yml'
- push.file_content = <<~EOF
- test-success:
- tags:
- - qa
- - test
- script: echo 'OK'
-
- test-failure:
- tags:
- - qa
- - test
- script:
- - echo 'FAILURE'
- - exit 1
-
- test-tags:
- tags:
- - qa
- - docker
- script: echo 'NOOP'
+ after do
+ Service::DockerRun::GitlabRunner.new(executor).remove!
+ end
- test-artifacts:
- tags:
- - qa
- - test
- script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt
- artifacts:
- paths:
- - my-artifacts/
- EOF
- end.project.visit!
+ it 'users creates a pipeline which gets processed', :smoke do
+ Flow::Login.sign_in
- expect(page).to have_content('Add .gitlab-ci.yml')
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ test-success:
+ tags:
+ - #{executor}
+ script: echo 'OK'
- Page::Project::Menu.perform(&:click_ci_cd_pipelines)
+ test-failure:
+ tags:
+ - #{executor}
+ script:
+ - echo 'FAILURE'
+ - exit 1
- expect(page).to have_content('All 1')
- expect(page).to have_content('Add .gitlab-ci.yml')
+ test-tags:
+ tags:
+ - invalid
+ script: echo 'NOOP'
- puts 'Waiting for the runner to process the pipeline'
- sleep 15 # Runner should process all jobs within 15 seconds.
+ test-artifacts:
+ tags:
+ - #{executor}
+ script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt
+ artifacts:
+ paths:
+ - my-artifacts/
+ YAML
+ }
+ ]
+ )
+ end.project.visit!
+ Page::Project::Menu.perform(&:click_ci_cd_pipelines)
Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
- Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).to be_running
- expect(pipeline).to have_build('test-success', status: :success)
- expect(pipeline).to have_build('test-failure', status: :failed)
- expect(pipeline).to have_build('test-tags', status: :pending)
- expect(pipeline).to have_build('test-artifacts', status: :success)
+ {
+ 'test-success': :passed,
+ 'test-failure': :failed,
+ 'test-tags': :pending,
+ 'test-artifacts': :passed
+ }.each do |job, status|
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job(job)
+ end
+
+ Page::Project::Job::Show.perform do |show|
+ expect(show).to public_send("be_#{status}")
+ show.click_element(:pipeline_path, Page::Project::Pipeline::Show)
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
index 0ca49bd080b..581e6b8299e 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
@@ -3,15 +3,15 @@
require 'digest/sha1'
module QA
- context 'Release', :docker, quarantine: 'https://gitlab.com/gitlab-org/gitlab/issues/196047' do
+ context 'Release', :docker do
describe 'Git clone using a deploy key' do
before do
Flow::Login.sign_in
@runner_name = "qa-runner-#{Time.now.to_i}"
- @project = Resource::Project.fabricate_via_api! do |resource|
- resource.name = 'deploy-key-clone-project'
+ @project = Resource::Project.fabricate_via_api! do |project|
+ project.name = 'deploy-key-clone-project'
end
@repository_location = @project.repository_ssh_location
@@ -46,12 +46,7 @@ module QA
deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}"
- Resource::CiVariable.fabricate_via_browser_ui! do |resource|
- resource.project = @project
- resource.key = deploy_key_name
- resource.value = key.private_key
- resource.masked = false
- end
+ make_ci_variable(deploy_key_name, key)
gitlab_ci = <<~YAML
cat-config:
@@ -90,6 +85,17 @@ module QA
expect(job.output).to include(sha1sum)
end
end
+
+ private
+
+ def make_ci_variable(key_name, key)
+ Resource::CiVariable.fabricate_via_api! do |resource|
+ resource.project = @project
+ resource.key = key_name
+ resource.value = key.private_key
+ resource.masked = false
+ end
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 54014ff7067..0a52b01af03 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -4,94 +4,49 @@ require 'pathname'
module QA
context 'Configure' do
- def disable_optional_jobs(project)
- # Disable code_quality check in Auto DevOps pipeline as it takes
- # too long and times out the test
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = project
- resource.key = 'CODE_QUALITY_DISABLED'
- resource.value = '1'
- resource.masked = false
- end
-
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = project
- resource.key = 'LICENSE_MANAGEMENT_DISABLED'
- resource.value = '1'
- resource.masked = false
- end
-
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = project
- resource.key = 'SAST_DISABLED'
- resource.value = '1'
- resource.masked = false
- end
-
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = project
- resource.key = 'DEPENDENCY_SCANNING_DISABLED'
- resource.value = '1'
- resource.masked = false
- end
-
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = project
- resource.key = 'CONTAINER_SCANNING_DISABLED'
- resource.value = '1'
- resource.masked = false
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = Runtime::Env.auto_devops_project_name || 'autodevops-project'
+ project.auto_devops_enabled = true
end
+ end
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = project
- resource.key = 'DAST_DISABLED'
- resource.value = '1'
- resource.masked = false
- end
+ before do
+ disable_optional_jobs(project)
end
- # Failure issue: https://gitlab.com/gitlab-org/gitlab/issues/118481
- describe 'Auto DevOps support', :orchestrated, :kubernetes, :quarantine do
+ describe 'Auto DevOps support', :orchestrated, :kubernetes do
context 'when rbac is enabled' do
- before(:all) do
- @cluster = Service::KubernetesCluster.new.create!
- end
+ let(:cluster) { Service::KubernetesCluster.new.create! }
- after(:all) do
- @cluster&.remove!
+ after do
+ cluster&.remove!
end
it 'runs auto devops' do
Flow::Login.sign_in
- @project = Resource::Project.fabricate! do |p|
- p.name = Runtime::Env.auto_devops_project_name || 'project-with-autodevops'
- p.description = 'Project with Auto DevOps'
- end
-
- disable_optional_jobs(@project)
-
# Set an application secret CI variable (prefixed with K8S_SECRET_)
Resource::CiVariable.fabricate! do |resource|
- resource.project = @project
+ resource.project = project
resource.key = 'K8S_SECRET_OPTIONAL_MESSAGE'
resource.value = 'you_can_see_this_variable'
resource.masked = false
end
# Connect K8s cluster
- Resource::KubernetesCluster.fabricate! do |cluster|
- cluster.project = @project
- cluster.cluster = @cluster
- cluster.install_helm_tiller = true
- cluster.install_ingress = true
- cluster.install_prometheus = true
- cluster.install_runner = true
+ Resource::KubernetesCluster.fabricate! do |k8s_cluster|
+ k8s_cluster.project = project
+ k8s_cluster.cluster = cluster
+ k8s_cluster.install_helm_tiller = true
+ k8s_cluster.install_ingress = true
+ k8s_cluster.install_prometheus = true
+ k8s_cluster.install_runner = true
end
# Create Auto DevOps compatible repo
Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = @project
+ push.project = project
push.directory = Pathname
.new(__dir__)
.join('../../../../../fixtures/auto_devops_rack')
@@ -146,20 +101,15 @@ module QA
before do
Flow::Login.sign_in
- @project = Resource::Project.fabricate_via_browser_ui! do |p|
- p.name = "project-with-autodevops-#{SecureRandom.hex(8)}"
- p.description = 'Project with AutoDevOps'
- end
+ project.visit!
Page::Project::Menu.perform(&:go_to_ci_cd_settings)
Page::Project::Settings::CICD.perform(&:expand_auto_devops)
Page::Project::Settings::AutoDevops.perform(&:enable_autodevops)
- @project.visit!
-
# Create AutoDevOps repo
Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = @project
+ push.project = project
push.directory = Pathname
.new(__dir__)
.join('../../../../../fixtures/auto_devops_rack')
@@ -176,5 +126,22 @@ module QA
end
end
end
+
+ private
+
+ def disable_optional_jobs(project)
+ %w[
+ CODE_QUALITY_DISABLED LICENSE_MANAGEMENT_DISABLED
+ SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
+ CONTAINER_SCANNING_DISABLED
+ ].each do |key|
+ Resource::CiVariable.fabricate_via_api! do |resource|
+ resource.project = project
+ resource.key = key
+ resource.value = '1'
+ resource.masked = false
+ end
+ end
+ end
end
end
diff --git a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
index 4a5bb077e69..c6d5fba919b 100644
--- a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
+++ b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
@@ -4,8 +4,8 @@ module QA
context 'Non-devops' do
describe 'Performance bar display', :requires_admin do
context 'when logged in as an admin user' do
- # 4 metrics: pg, gitaly, redis, total
- let(:metrics_count) { 4 }
+ # performance metrics: pg, gitaly, redis, rugged (feature flagged), total (not always provided)
+ let(:minimum_metrics_count) { 3 }
before do
Flow::Login.sign_in_as_admin
@@ -28,7 +28,7 @@ module QA
Page::Layout::PerformanceBar.perform do |bar_component|
expect(bar_component).to have_performance_bar
- expect(bar_component).to have_detailed_metrics(metrics_count)
+ expect(bar_component).to have_detailed_metrics(minimum_metrics_count)
expect(bar_component).to have_request_for('realtime_changes') # Always requested on issue pages
end
end
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index f59795e17c3..281e1b85cc3 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -16,13 +16,6 @@ module QA
super
end
- def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: false)
- log("next wait uses reload: #{reload}")
- # Logging of wait start/end/duration is handled by QA::Support::Waiter
-
- super
- end
-
def scroll_to(selector, text: nil)
msg = "scrolling to :#{selector}"
msg += " with text: #{text}" if text
diff --git a/qa/qa/support/repeater.rb b/qa/qa/support/repeater.rb
index 53d72f2f410..14771243beb 100644
--- a/qa/qa/support/repeater.rb
+++ b/qa/qa/support/repeater.rb
@@ -10,13 +10,13 @@ module QA
RetriesExceededError = Class.new(RuntimeError)
WaitExceededError = Class.new(RuntimeError)
- def repeat_until(max_attempts: nil, max_duration: nil, reload_page: nil, sleep_interval: 0, raise_on_failure: true, retry_on_exception: false)
+ def repeat_until(max_attempts: nil, max_duration: nil, reload_page: nil, sleep_interval: 0, raise_on_failure: true, retry_on_exception: false, log: true)
attempts = 0
start = Time.now
begin
while remaining_attempts?(attempts, max_attempts) && remaining_time?(start, max_duration)
- QA::Runtime::Logger.debug("Attempt number #{attempts + 1}") if max_attempts
+ QA::Runtime::Logger.debug("Attempt number #{attempts + 1}") if max_attempts && log
result = yield
return result if result
diff --git a/qa/qa/support/retrier.rb b/qa/qa/support/retrier.rb
index 7b548e95453..f28534e7c11 100644
--- a/qa/qa/support/retrier.rb
+++ b/qa/qa/support/retrier.rb
@@ -34,7 +34,7 @@ module QA
result
end
- def retry_until(max_attempts: nil, max_duration: nil, reload_page: nil, sleep_interval: 0, raise_on_failure: false, retry_on_exception: false)
+ def retry_until(max_attempts: nil, max_duration: nil, reload_page: nil, sleep_interval: 0, raise_on_failure: true, retry_on_exception: false)
# For backwards-compatibility
max_attempts = 3 if max_attempts.nil? && max_duration.nil?
diff --git a/qa/qa/support/wait_for_requests.rb b/qa/qa/support/wait_for_requests.rb
index 5d5ba70a0c2..c58882a11ea 100644
--- a/qa/qa/support/wait_for_requests.rb
+++ b/qa/qa/support/wait_for_requests.rb
@@ -6,7 +6,7 @@ module QA
module_function
def wait_for_requests
- Waiter.wait_until do
+ Waiter.wait_until(log: false) do
finished_all_ajax_requests? && finished_all_axios_requests?
end
end
diff --git a/qa/qa/support/waiter.rb b/qa/qa/support/waiter.rb
index fe63c930c7c..9ccc0d9484f 100644
--- a/qa/qa/support/waiter.rb
+++ b/qa/qa/support/waiter.rb
@@ -7,15 +7,17 @@ module QA
module_function
- def wait_until(max_duration: singleton_class::DEFAULT_MAX_WAIT_TIME, reload_page: nil, sleep_interval: 0.1, raise_on_failure: false, retry_on_exception: false)
- QA::Runtime::Logger.debug(
- <<~MSG.tr("\n", ' ')
- with wait_until: max_duration: #{max_duration};
- reload_page: #{reload_page};
- sleep_interval: #{sleep_interval};
- raise_on_failure: #{raise_on_failure}
- MSG
- )
+ def wait_until(max_duration: singleton_class::DEFAULT_MAX_WAIT_TIME, reload_page: nil, sleep_interval: 0.1, raise_on_failure: true, retry_on_exception: false, log: true)
+ if log
+ QA::Runtime::Logger.debug(
+ <<~MSG.tr("\n", ' ')
+ with wait_until: max_duration: #{max_duration};
+ reload_page: #{reload_page};
+ sleep_interval: #{sleep_interval};
+ raise_on_failure: #{raise_on_failure}
+ MSG
+ )
+ end
result = nil
self.repeat_until(
@@ -23,11 +25,12 @@ module QA
reload_page: reload_page,
sleep_interval: sleep_interval,
raise_on_failure: raise_on_failure,
- retry_on_exception: retry_on_exception
+ retry_on_exception: retry_on_exception,
+ log: log
) do
result = yield
end
- QA::Runtime::Logger.debug("ended wait_until")
+ QA::Runtime::Logger.debug("ended wait_until") if log
result
end
diff --git a/qa/qa/tools/delete_subgroups.rb b/qa/qa/tools/delete_subgroups.rb
index 3f752adbe6f..a05ec735632 100644
--- a/qa/qa/tools/delete_subgroups.rb
+++ b/qa/qa/tools/delete_subgroups.rb
@@ -26,30 +26,19 @@ module QA
group_id = fetch_group_id
sub_groups_head_response = head Runtime::API::Request.new(@api_client, "/groups/#{group_id}/subgroups", per_page: "100").url
- total_sub_groups = sub_groups_head_response.headers[:x_total]
total_sub_group_pages = sub_groups_head_response.headers[:x_total_pages]
- STDOUT.puts "total_sub_groups: #{total_sub_groups}"
- STDOUT.puts "total_sub_group_pages: #{total_sub_group_pages}"
+ sub_group_ids = fetch_subgroup_ids(group_id, total_sub_group_pages)
+ STDOUT.puts "Number of Sub Groups not already marked for deletion: #{sub_group_ids.length}"
- total_sub_group_pages.to_i.times do |page_no|
- # Fetch all subgroups for the top level group
- sub_groups_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_id}/subgroups", per_page: "100").url
-
- sub_group_ids = JSON.parse(sub_groups_response.body).map { |subgroup| subgroup["id"] }
-
- if sub_group_ids.any?
- STDOUT.puts "\n==== Current Page: #{page_no + 1} ====\n"
-
- delete_subgroups(sub_group_ids)
- end
- end
+ delete_subgroups(sub_group_ids) unless sub_group_ids.empty?
STDOUT.puts "\nDone"
end
private
def delete_subgroups(sub_group_ids)
+ STDOUT.puts "Deleting #{sub_group_ids.length} subgroups..."
sub_group_ids.each do |subgroup_id|
delete_response = delete Runtime::API::Request.new(@api_client, "/groups/#{subgroup_id}").url
dot_or_f = delete_response.code == 202 ? "\e[32m.\e[0m" : "\e[31mF\e[0m"
@@ -61,6 +50,17 @@ module QA
group_search_response = get Runtime::API::Request.new(@api_client, "/groups", search: ENV['GROUP_NAME_OR_PATH'] || 'gitlab-qa-sandbox-group').url
JSON.parse(group_search_response.body).first["id"]
end
+
+ def fetch_subgroup_ids(group_id, group_pages)
+ sub_groups_ids = []
+
+ group_pages.to_i.times do |page_no|
+ sub_groups_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_id}/subgroups", page: (page_no + 1).to_s, per_page: "100").url
+ sub_groups_ids.concat(JSON.parse(sub_groups_response.body).reject { |subgroup| !subgroup["marked_for_deletion_on"].nil? }.map { |subgroup| subgroup["id"] })
+ end
+
+ sub_groups_ids.uniq
+ end
end
end
end
diff --git a/qa/qa/vendor/jenkins/page/job.rb b/qa/qa/vendor/jenkins/page/job.rb
new file mode 100644
index 00000000000..498ce6041b8
--- /dev/null
+++ b/qa/qa/vendor/jenkins/page/job.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'capybara/dsl'
+
+module QA
+ module Vendor
+ module Jenkins
+ module Page
+ class Job < Page::Base
+ attr_accessor :job_name
+
+ def path
+ "/job/#{@job_name}"
+ end
+
+ def has_successful_build?
+ page.has_text?("Last successful build")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
index a6b61e9b1ee..f2ce9fb2cf8 100644
--- a/qa/spec/page/logging_spec.rb
+++ b/qa/spec/page/logging_spec.rb
@@ -27,24 +27,6 @@ describe QA::Support::Page::Logging do
.to output(%r{refreshing http://current-url}).to_stdout_from_any_process
end
- it 'logs wait' do
- expect { subject.wait_until(max_duration: 0) {} }
- .to output(/next wait uses reload: true/).to_stdout_from_any_process
- expect { subject.wait_until(max_duration: 0) {} }
- .to output(/with wait_until/).to_stdout_from_any_process
- expect { subject.wait_until(max_duration: 0) {} }
- .to output(/ended wait_until$/).to_stdout_from_any_process
- end
-
- it 'logs wait with reload false' do
- expect { subject.wait_until(max_duration: 0, reload: false) {} }
- .to output(/next wait uses reload: false/).to_stdout_from_any_process
- expect { subject.wait_until(max_duration: 0, reload: false) {} }
- .to output(/with wait_until/).to_stdout_from_any_process
- expect { subject.wait_until(max_duration: 0, reload: false) {} }
- .to output(/ended wait_until$/).to_stdout_from_any_process
- end
-
it 'logs scroll_to' do
expect { subject.scroll_to(:element) }
.to output(/scrolling to :element/).to_stdout_from_any_process
diff --git a/qa/spec/resource/api_fabricator_spec.rb b/qa/spec/resource/api_fabricator_spec.rb
index a5ed4422f6e..eb2bdd1be64 100644
--- a/qa/spec/resource/api_fabricator_spec.rb
+++ b/qa/spec/resource/api_fabricator_spec.rb
@@ -120,7 +120,7 @@ describe QA::Resource::ApiFabricator do
end
end
- context '#transform_api_resource' do
+ describe '#transform_api_resource' do
let(:resource) do
Class.new do
def self.name
diff --git a/qa/spec/scenario/test/integration/github_spec.rb b/qa/spec/scenario/test/integration/github_spec.rb
index 6112ba7c694..b2d577bd552 100644
--- a/qa/spec/scenario/test/integration/github_spec.rb
+++ b/qa/spec/scenario/test/integration/github_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Scenario::Test::Integration::Github do
- context '#perform' do
+ describe '#perform' do
let(:env) { spy('Runtime::Env') }
before do
diff --git a/qa/spec/scenario/test/integration/instance_saml_spec.rb b/qa/spec/scenario/test/integration/instance_saml_spec.rb
index cb8a6a630cc..15f15b2e643 100644
--- a/qa/spec/scenario/test/integration/instance_saml_spec.rb
+++ b/qa/spec/scenario/test/integration/instance_saml_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Scenario::Test::Integration::InstanceSAML do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:instance_saml] }
end
diff --git a/qa/spec/scenario/test/integration/kubernetes_spec.rb b/qa/spec/scenario/test/integration/kubernetes_spec.rb
index cb43994b229..51ee7b9acff 100644
--- a/qa/spec/scenario/test/integration/kubernetes_spec.rb
+++ b/qa/spec/scenario/test/integration/kubernetes_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Scenario::Test::Integration::Kubernetes do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:kubernetes] }
end
diff --git a/qa/spec/scenario/test/integration/ldap_spec.rb b/qa/spec/scenario/test/integration/ldap_spec.rb
index 86747cd8eb7..c493cde6c7a 100644
--- a/qa/spec/scenario/test/integration/ldap_spec.rb
+++ b/qa/spec/scenario/test/integration/ldap_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Scenario::Test::Integration::LDAPNoTLS do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:ldap_no_tls] }
end
@@ -9,7 +9,7 @@ describe QA::Scenario::Test::Integration::LDAPNoTLS do
end
describe QA::Scenario::Test::Integration::LDAPNoServer do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:ldap_no_server] }
end
@@ -17,7 +17,7 @@ describe QA::Scenario::Test::Integration::LDAPNoServer do
end
describe QA::Scenario::Test::Integration::LDAPTLS do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:ldap_tls] }
end
diff --git a/qa/spec/scenario/test/integration/mattermost_spec.rb b/qa/spec/scenario/test/integration/mattermost_spec.rb
index 4e75e72f4d2..4452e890ebe 100644
--- a/qa/spec/scenario/test/integration/mattermost_spec.rb
+++ b/qa/spec/scenario/test/integration/mattermost_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Scenario::Test::Integration::Mattermost do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:args) { %w[gitlab_address mattermost_address] }
let(:args) do
diff --git a/qa/spec/scenario/test/integration/oauth_spec.rb b/qa/spec/scenario/test/integration/oauth_spec.rb
index c1c320be576..ab7ea905a29 100644
--- a/qa/spec/scenario/test/integration/oauth_spec.rb
+++ b/qa/spec/scenario/test/integration/oauth_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Scenario::Test::Integration::OAuth do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:oauth] }
end
diff --git a/qa/spec/scenario/test/integration/object_storage_spec.rb b/qa/spec/scenario/test/integration/object_storage_spec.rb
index 2b7188223e0..8b4367bee32 100644
--- a/qa/spec/scenario/test/integration/object_storage_spec.rb
+++ b/qa/spec/scenario/test/integration/object_storage_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
describe QA::Scenario::Test::Integration::ObjectStorage do
- context '#perform' do
+ describe '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:object_storage] }
end
diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb
index 3d98f03a982..1a3efe0b46c 100644
--- a/qa/spec/specs/runner_spec.rb
+++ b/qa/spec/specs/runner_spec.rb
@@ -11,7 +11,7 @@ describe QA::Specs::Runner do
end
end
- context '#perform' do
+ describe '#perform' do
before do
allow(QA::Runtime::Browser).to receive(:configure!)
end
diff --git a/qa/spec/support/repeater_spec.rb b/qa/spec/support/repeater_spec.rb
index 20dca6608f6..b5d5058ef49 100644
--- a/qa/spec/support/repeater_spec.rb
+++ b/qa/spec/support/repeater_spec.rb
@@ -381,5 +381,35 @@ describe QA::Support::Repeater do
end
end
end
+
+ it 'logs attempts' do
+ attempted = false
+
+ expect do
+ subject.repeat_until(max_attempts: 1) do
+ unless attempted
+ attempted = true
+ break false
+ end
+
+ true
+ end
+ end.to output(/Attempt number/).to_stdout_from_any_process
+ end
+
+ it 'allows logging to be silenced' do
+ attempted = false
+
+ expect do
+ subject.repeat_until(max_attempts: 1, log: false) do
+ unless attempted
+ attempted = true
+ break false
+ end
+
+ true
+ end
+ end.not_to output.to_stdout_from_any_process
+ end
end
end
diff --git a/qa/spec/support/retrier_spec.rb b/qa/spec/support/retrier_spec.rb
index fbe66a680f9..ef1d53e6b65 100644
--- a/qa/spec/support/retrier_spec.rb
+++ b/qa/spec/support/retrier_spec.rb
@@ -14,12 +14,12 @@ describe QA::Support::Retrier do
context 'when the condition is true' do
it 'logs max attempts (3 by default)' do
expect { subject.retry_until { true } }
- .to output(/with retry_until: max_attempts: 3; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process
+ .to output(/with retry_until: max_attempts: 3; reload_page: ; sleep_interval: 0; raise_on_failure: true; retry_on_exception: false/).to_stdout_from_any_process
end
it 'logs max duration' do
expect { subject.retry_until(max_duration: 1) { true } }
- .to output(/with retry_until: max_duration: 1; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process
+ .to output(/with retry_until: max_duration: 1; reload_page: ; sleep_interval: 0; raise_on_failure: true; retry_on_exception: false/).to_stdout_from_any_process
end
it 'logs the end' do
@@ -30,12 +30,12 @@ describe QA::Support::Retrier do
context 'when the condition is false' do
it 'logs the start' do
- expect { subject.retry_until(max_duration: 0) { false } }
+ expect { subject.retry_until(max_duration: 0, raise_on_failure: false) { false } }
.to output(/with retry_until: max_duration: 0; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process
end
it 'logs the end' do
- expect { subject.retry_until(max_duration: 0) { false } }
+ expect { subject.retry_until(max_duration: 0, raise_on_failure: false) { false } }
.to output(/ended retry_until$/).to_stdout_from_any_process
end
end
@@ -54,8 +54,8 @@ describe QA::Support::Retrier do
subject.retry_until
end
- it 'sets raise_on_failure to false by default' do
- expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: false))
+ it 'sets raise_on_failure to true by default' do
+ expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: true))
subject.retry_until
end
diff --git a/qa/spec/support/shared_examples/scenario_shared_examples.rb b/qa/spec/support/shared_examples/scenario_shared_examples.rb
index 17469ea470c..6e20adbd4ad 100644
--- a/qa/spec/support/shared_examples/scenario_shared_examples.rb
+++ b/qa/spec/support/shared_examples/scenario_shared_examples.rb
@@ -31,6 +31,12 @@ shared_examples 'a QA scenario class' do
expect(attributes).to have_received(:define).with(:gitlab_address, 'http://gitlab_address').at_least(:once)
end
+ it 'performs before hooks only once' do
+ subject.perform(args)
+
+ expect(release).to have_received(:perform_before_hooks).once
+ end
+
it 'sets tags on runner' do
subject.perform(args)
diff --git a/qa/spec/support/waiter_spec.rb b/qa/spec/support/waiter_spec.rb
index 06e404c862a..35f1e01289a 100644
--- a/qa/spec/support/waiter_spec.rb
+++ b/qa/spec/support/waiter_spec.rb
@@ -34,6 +34,11 @@ describe QA::Support::Waiter do
end
end
+ it 'allows logs to be silenced' do
+ expect { subject.wait_until(max_duration: 0, raise_on_failure: false, log: false) { false } }
+ .not_to output.to_stdout_from_any_process
+ end
+
it 'sets max_duration to 60 by default' do
expect(subject).to receive(:repeat_until).with(hash_including(max_duration: 60))
@@ -46,8 +51,8 @@ describe QA::Support::Waiter do
subject.wait_until
end
- it 'sets raise_on_failure to false by default' do
- expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: false))
+ it 'sets raise_on_failure to true by default' do
+ expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: true))
subject.wait_until
end