diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-07-19 17:16:28 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-07-19 17:16:28 +0300 |
commit | e4384360a16dd9a19d4d2d25d0ef1f2b862ed2a6 (patch) | |
tree | 2fcdfa7dcdb9db8f5208b2562f4b4e803d671243 /qa | |
parent | ffda4e7bcac36987f936b4ba515995a6698698f0 (diff) |
Add latest changes from gitlab-org/gitlab@16-2-stable-eev16.2.0-rc42
Diffstat (limited to 'qa')
123 files changed, 932 insertions, 1084 deletions
diff --git a/qa/Dockerfile b/qa/Dockerfile index bd9cd166701..213ec3450cb 100644 --- a/qa/Dockerfile +++ b/qa/Dockerfile @@ -40,6 +40,8 @@ WORKDIR /home/gitlab/qa # Install qa dependencies or fetch from cache if unchanged # COPY ./qa/Gemfile* /home/gitlab/qa/ +COPY ./vendor/gems/ /home/gitlab/vendor/gems/ +COPY ./gems/ /home/gitlab/gems/ RUN bundle config set --local without development \ && bundle install --retry=3 @@ -47,7 +49,6 @@ COPY ./config/initializers/0_inject_enterprise_edition_module.rb /home/gitlab/co COPY ./config/feature_flags /home/gitlab/config/feature_flags COPY ./config/bundler_setup.rb /home/gitlab/config/ COPY ./lib/gitlab_edition.rb /home/gitlab/lib/ -COPY ./lib/gitlab/utils.rb /home/gitlab/lib/gitlab/ COPY ./INSTALLATION_TYPE ./VERSION /home/gitlab/ COPY ./qa /home/gitlab/qa diff --git a/qa/Gemfile b/qa/Gemfile index a06914ca7de..e9616f29731 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -2,9 +2,10 @@ source 'https://rubygems.org' -gem 'gitlab-qa', '~> 11', '>= 11.2.0', require: 'gitlab/qa' -gem 'gitlab_quality-test_tooling', '~> 0.8.1', require: false -gem 'activesupport', '~> 6.1.7.2' # This should stay in sync with the root's Gemfile +gem 'gitlab-qa', '~> 12', '>= 12.1.0', require: 'gitlab/qa' +gem 'gitlab_quality-test_tooling', '~> 0.8.3', require: false +gem 'gitlab-utils', path: '../gems/gitlab-utils' +gem 'activesupport', '~> 7.0.5.1' # This should stay in sync with the root's Gemfile gem 'allure-rspec', '~> 2.20.0' gem 'capybara', '~> 3.39.2' gem 'capybara-screenshot', '~> 1.0.26' @@ -39,7 +40,7 @@ gem 'chemlab', '~> 0.10' gem 'chemlab-library-www-gitlab-com', '~> 0.1', '>= 0.1.1' # dependencies for jenkins client -gem 'nokogiri', '~> 1.15', '>= 1.15.2' +gem 'nokogiri', '~> 1.15', '>= 1.15.3' gem 'deprecation_toolkit', '~> 2.0.3', require: false diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index e4e89e7e2e1..521f101ee4d 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -1,12 +1,27 @@ +PATH + remote: ../gems/gitlab-utils + specs: + gitlab-utils (0.1.0) + actionview (>= 6.1.7.2) + activesupport (>= 6.1.7.2) + addressable (~> 2.8) + nokogiri (~> 1.15.2) + rake (~> 13.0) + GEM remote: https://rubygems.org/ specs: - activesupport (6.1.7.2) + actionview (7.0.5.1) + activesupport (= 7.0.5.1) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activesupport (7.0.5.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - zeitwerk (~> 2.3) addressable (2.8.1) public_suffix (>= 2.0.2, < 6.0) airborne (0.3.7) @@ -55,6 +70,7 @@ GEM confiner (0.4.0) gitlab (>= 4.17) zeitwerk (>= 2.5, < 3) + crass (1.0.6) debug_inspector (1.1.0) declarative (0.0.20) deprecation_toolkit (2.0.3) @@ -62,6 +78,7 @@ GEM diff-lcs (1.3) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) + erubi (1.12.0) excon (0.92.4) faker (3.2.0) i18n (>= 1.8.11, < 2) @@ -102,8 +119,8 @@ GEM gitlab (4.19.0) httparty (~> 0.20) terminal-table (>= 1.5.1) - gitlab-qa (11.2.0) - activesupport (~> 6.1) + gitlab-qa (12.1.0) + activesupport (>= 6.1, < 7.1) gitlab (~> 4.19) http (~> 5.0) nokogiri (~> 1.10) @@ -111,7 +128,7 @@ GEM rainbow (>= 3, < 4) table_print (= 1.5.7) zeitwerk (>= 2, < 3) - gitlab_quality-test_tooling (0.8.1) + gitlab_quality-test_tooling (0.8.3) activesupport (>= 6.1, < 7.1) gitlab (~> 4.19) http (~> 5.0) @@ -176,6 +193,9 @@ GEM llhttp-ffi (0.4.0) ffi-compiler (~> 1.0) rake (~> 13.0) + loofah (2.21.3) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) macaddr (1.7.2) systemu (~> 2.6.5) matrix (0.4.2) @@ -186,11 +206,11 @@ GEM mime-types-data (3.2023.0218.1) mini_mime (1.1.0) mini_portile2 (2.8.2) - minitest (5.18.0) + minitest (5.18.1) multi_json (1.15.0) multi_xml (0.6.0) netrc (0.11.0) - nokogiri (1.15.2) + nokogiri (1.15.3) mini_portile2 (~> 2.8.2) racc (~> 1.4) octokit (6.1.1) @@ -214,10 +234,15 @@ GEM byebug (~> 11.0) pry (>= 0.13, < 0.15) public_suffix (5.0.1) - racc (1.6.2) + racc (1.7.1) rack (2.2.3.1) rack-test (1.1.0) rack (>= 1.0, < 3) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.5.0) + loofah (~> 2.19, >= 2.19.1) rainbow (3.1.1) rake (13.0.6) regexp_parser (2.1.1) @@ -310,7 +335,7 @@ PLATFORMS ruby DEPENDENCIES - activesupport (~> 6.1.7.2) + activesupport (~> 7.0.5.1) airborne (~> 0.3.7) allure-rspec (~> 2.20.0) capybara (~> 3.39.2) @@ -323,11 +348,12 @@ DEPENDENCIES faraday-retry (~> 2.2) fog-core (= 2.1.0) fog-google (~> 1.19) - gitlab-qa (~> 11, >= 11.2.0) - gitlab_quality-test_tooling (~> 0.8.1) + gitlab-qa (~> 12, >= 12.1.0) + gitlab-utils! + gitlab_quality-test_tooling (~> 0.8.3) influxdb-client (~> 2.9) knapsack (~> 4.0) - nokogiri (~> 1.15, >= 1.15.2) + nokogiri (~> 1.15, >= 1.15.3) octokit (~> 6.1.1) parallel (~> 1.23) parallel_tests (~> 4.2, >= 4.2.1) @@ -348,4 +374,4 @@ DEPENDENCIES zeitwerk (~> 2.6, >= 2.6.8) BUNDLED WITH - 2.4.14 + 2.4.15 diff --git a/qa/gdk/Dockerfile.gdk b/qa/gdk/Dockerfile.gdk index cf9cea69056..51e058a7088 100644 --- a/qa/gdk/Dockerfile.gdk +++ b/qa/gdk/Dockerfile.gdk @@ -88,17 +88,11 @@ RUN set -eux; \ rm -rf ${GEM_HOME}/cache \ && go clean -cache -# Build metrics-exporter -# -COPY --chown=gdk:gdk GITLAB_METRICS_EXPORTER_VERSION ./gitlab/ -RUN set -eux; \ - make gitlab-metrics-exporter-setup; \ - go clean -cache - # Install gitlab gem dependencies # COPY --chown=gdk:gdk Gemfile Gemfile.lock ./gitlab/ -COPY --chown=gdk:gdk vendor/gems ./gitlab/vendor/gems +COPY --chown=gdk:gdk vendor/gems/ ./gitlab/vendor/gems/ +COPY --chown=gdk:gdk gems/ ./gitlab/gems/ RUN make .gitlab-bundle && rm -rf ${GEM_HOME}/cache # Install gitlab npm dependencies @@ -2,8 +2,9 @@ Encoding.default_external = 'UTF-8' +require 'gitlab/utils/all' + require_relative '../lib/gitlab_edition' -require_relative '../lib/gitlab/utils' require_relative '../config/initializers/0_inject_enterprise_edition_module' require_relative 'lib/gitlab' diff --git a/qa/qa/fixtures/package_managers/maven/gradle/build.gradle.erb b/qa/qa/fixtures/package_managers/maven/gradle/build.gradle.erb new file mode 100644 index 00000000000..77e5398bf13 --- /dev/null +++ b/qa/qa/fixtures/package_managers/maven/gradle/build.gradle.erb @@ -0,0 +1,51 @@ +plugins { + id 'java' + id 'maven-publish' + id 'application' +} + +repositories { + maven { + url "<%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/maven" + name "GitLab" + credentials(HttpHeaderCredentials) { + name = '<%= maven_header_name %>' + value = project.property('Token') + } + authentication { + header(HttpHeaderAuthentication) + } + } +} + +dependencies { + implementation group: '<%= group_id %>', name: '<%= artifact_id %>', version: '<%= package_version %>' + testImplementation 'junit:junit:4.12' +} + +publishing { + publications { + mavenJava(MavenPublication) { + groupId '<%= group_id %>' + artifactId '<%= artifact_id %>' + version '<%= package_version %>' + from components.java + } + } + repositories { + maven { + url "<%= gitlab_address_with_port %>/api/v4/projects/<%= project.id %>/packages/maven" + credentials(HttpHeaderCredentials) { + name = '<%= maven_header_name %>' + value = project.property('Token') + } + authentication { + header(HttpHeaderAuthentication) + } + } + } +} + +application { + mainClassName = 'gradle_maven_app.App' +} diff --git a/qa/qa/fixtures/package_managers/maven/gradle/build_install.gradle.erb b/qa/qa/fixtures/package_managers/maven/gradle/build_install.gradle.erb deleted file mode 100644 index 31543d30e88..00000000000 --- a/qa/qa/fixtures/package_managers/maven/gradle/build_install.gradle.erb +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - id 'java' - id 'application' -} - -repositories { - maven { - url "<%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven" - name "GitLab" - credentials(HttpHeaderCredentials) { - name = '<%= maven_header_name %>' - value = <%= token %> - } - authentication { - header(HttpHeaderAuthentication) - } - } -} - -dependencies { - implementation group: '<%= group_id %>', name: '<%= artifact_id %>', version: '<%= package_version %>' - testImplementation 'junit:junit:4.12' -} - -application { - mainClassName = 'gradle_maven_app.App' -}
\ No newline at end of file diff --git a/qa/qa/fixtures/package_managers/maven/gradle/build_upload.gradle.erb b/qa/qa/fixtures/package_managers/maven/gradle/build_upload.gradle.erb deleted file mode 100644 index c14e63e11df..00000000000 --- a/qa/qa/fixtures/package_managers/maven/gradle/build_upload.gradle.erb +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - id 'java' - id 'maven-publish' -} - -publishing { - publications { - library(MavenPublication) { - groupId '<%= group_id %>' - artifactId '<%= artifact_id %>' - version '<%= package_version %>' - from components.java - } - } - repositories { - maven { - url "<%= gitlab_address_with_port %>/api/v4/projects/<%= package_project.id %>/packages/maven" - credentials(HttpHeaderCredentials) { - name = "Private-Token" - value = "<%= personal_access_token %>" - } - authentication { - header(HttpHeaderAuthentication) - } - } - } -}
\ No newline at end of file diff --git a/qa/qa/fixtures/package_managers/maven/gradle/gradle_install_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/gradle/gradle_install_package.yaml.erb deleted file mode 100644 index 49873f124cc..00000000000 --- a/qa/qa/fixtures/package_managers/maven/gradle/gradle_install_package.yaml.erb +++ /dev/null @@ -1,8 +0,0 @@ - build: - image: gradle:6.5-jdk11 - script: - - 'gradle build' - only: - - "<%= client_project.default_branch %>" - tags: - - "runner-for-<%= client_project.group.name %>"
\ No newline at end of file diff --git a/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_install_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_install_package.yaml.erb new file mode 100644 index 00000000000..35f4dba6130 --- /dev/null +++ b/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_install_package.yaml.erb @@ -0,0 +1,23 @@ +stages: + - publish + - install + +publish: + stage: publish + image: gradle:6.5-jdk11 + script: + - 'gradle -PToken=<%= token %> publish' + only: + - "<%= project.default_branch %>" + tags: + - "runner-for-<%= project.name %>" + +install: + stage: install + image: gradle:6.5-jdk11 + script: + - 'gradle -PToken=<%= token %> build' + only: + - "<%= project.default_branch %>" + tags: + - "runner-for-<%= project.name %>" diff --git a/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_package.yaml.erb b/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_package.yaml.erb deleted file mode 100644 index 3f3c7dce03c..00000000000 --- a/qa/qa/fixtures/package_managers/maven/gradle/gradle_upload_package.yaml.erb +++ /dev/null @@ -1,8 +0,0 @@ -deploy: - image: gradle:6.5-jdk11 - script: - - 'gradle publish' - only: - - "<%= package_project.default_branch %>" - tags: - - "runner-for-<%= package_project.group.name %>"
\ No newline at end of file diff --git a/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/gitlab_ci.yaml.erb b/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/gitlab_ci.yaml.erb deleted file mode 100644 index 394c6689eef..00000000000 --- a/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/gitlab_ci.yaml.erb +++ /dev/null @@ -1,8 +0,0 @@ -install: - image: maven:3.6-jdk-11 - script: - - "mvn install -U -s settings.xml" - only: - - "<%= imported_project.default_branch %>" - tags: - - "runner-for-<%= imported_project.group.name %>"
\ No newline at end of file diff --git a/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/settings.xml.erb deleted file mode 100644 index 4bcd63b3c6d..00000000000 --- a/qa/qa/fixtures/package_managers/maven/group/consumer/request_forwarding/settings.xml.erb +++ /dev/null @@ -1,23 +0,0 @@ -<settings> - <servers> - <server> - <id>central-proxy</id> - <configuration> - <httpHeaders> - <property> - <name>Private-Token</name> - <value><%= personal_access_token %></value> - </property> - </httpHeaders> - </configuration> - </server> - </servers> - <mirrors> - <mirror> - <id>central-proxy</id> - <name>GitLab proxy of central repo</name> - <url><%= gitlab_address_with_port %>/api/v4/groups/<%= imported_project.group.id %>/-/packages/maven</url> - <mirrorOf>central</mirrorOf> - </mirror> - </mirrors> -</settings>
\ No newline at end of file diff --git a/qa/qa/fixtures/package_managers/maven/project/request_forwarding/gitlab_ci.yaml.erb b/qa/qa/fixtures/package_managers/maven/project/request_forwarding/gitlab_ci.yaml.erb deleted file mode 100644 index a41bdc4d650..00000000000 --- a/qa/qa/fixtures/package_managers/maven/project/request_forwarding/gitlab_ci.yaml.erb +++ /dev/null @@ -1,8 +0,0 @@ -install: - image: maven:3.6-jdk-11 - script: - - 'mvn install -U -s settings.xml' - only: - - "<%= imported_project.default_branch %>" - tags: - - "runner-for-<%= imported_project.name %>"
\ No newline at end of file diff --git a/qa/qa/fixtures/package_managers/maven/project/request_forwarding/settings.xml.erb b/qa/qa/fixtures/package_managers/maven/project/request_forwarding/settings.xml.erb deleted file mode 100644 index caf1fc9b761..00000000000 --- a/qa/qa/fixtures/package_managers/maven/project/request_forwarding/settings.xml.erb +++ /dev/null @@ -1,23 +0,0 @@ -<settings> - <servers> - <server> - <id>central-proxy</id> - <configuration> - <httpHeaders> - <property> - <name>Private-Token</name> - <value><%= personal_access_token %></value> - </property> - </httpHeaders> - </configuration> - </server> - </servers> - <mirrors> - <mirror> - <id>central-proxy</id> - <name>GitLab proxy of central repo</name> - <url><%= gitlab_address_with_port %>/api/v4/projects/<%= imported_project.id %>/packages/maven</url> - <mirrorOf>central</mirrorOf> - </mirror> - </mirrors> -</settings> diff --git a/qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb b/qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb index 87c01fb5477..3cd1b1e630f 100644 --- a/qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb +++ b/qa/qa/fixtures/package_managers/pypi/pypi_upload_install_package.yaml.erb @@ -14,6 +14,6 @@ run: install: stage: install script: - - "pip install <%= package.name %> --no-deps --index-url <%= uri.scheme %>://<%= personal_access_token %>:<%= personal_access_token %>@<%= gitlab_host_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host <%= gitlab_host_with_port %>" + - "pip install <%= package.name %> --no-deps --index-url <%= uri.scheme %>://${PERSONAL_ACCESS_TOKEN}:${PERSONAL_ACCESS_TOKEN}@<%= gitlab_host_with_port %>/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host <%= gitlab_host_with_port %>" tags: - runner-for-<%= project.name %> diff --git a/qa/qa/flow/alert_settings.rb b/qa/qa/flow/alert_settings.rb index f5ee4f94065..7bda1585b39 100644 --- a/qa/qa/flow/alert_settings.rb +++ b/qa/qa/flow/alert_settings.rb @@ -27,7 +27,6 @@ module QA alert.add_new_integration alert.select_prometheus alert.activate_integration - alert.fill_in_prometheus_url alert.save_and_create_alert end end diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index 35c5262e767..0e8a1c68bc5 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -144,7 +144,7 @@ module QA end def init_repository - run_git("git init") + run_git("git init --initial-branch=#{default_branch}") end def pull(repository = nil, branch = nil) diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 6c01fa9f344..92b4fd39759 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -4,6 +4,11 @@ require 'capybara/dsl' module QA module Page + # Page base class + # + # @!method self.perform + # Perform action on the page + # @yieldparam [self] instance of page object class Base # Generic matcher for common css selectors like: # - class name '.someclass' @@ -518,6 +523,12 @@ module QA "Could not find the expected element as #{element_when_flag_enabled} or #{element_when_flag_disabled}." \ "The relevant feature flag is #{feature_flag}" end + + def wait_for_gitlab_to_respond + wait_until(sleep_interval: 5, message: '502 - GitLab is taking too much time to respond') do + Capybara.page.has_no_text?('GitLab is taking too much time to respond') + end + end end end end diff --git a/qa/qa/page/component/confirm_modal.rb b/qa/qa/page/component/confirm_modal.rb index 4d1cf30c392..f72ca4f068e 100644 --- a/qa/qa/page/component/confirm_modal.rb +++ b/qa/qa/page/component/confirm_modal.rb @@ -11,6 +11,7 @@ module QA base.view 'app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue' do element :confirm_ok_button + element :confirmation_modal end base.view 'app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue' do @@ -37,6 +38,20 @@ module QA def click_confirmation_ok_button click_element(:confirm_ok_button) end + + # Click the confirmation button if the confirmation modal is present + # Can be used when the modal may not always appear in a test. For example, if the modal is behind a feature flag + # + # @return [void] + def click_confirmation_ok_button_if_present + # In the case of changing access levels[1], the modal appears while there's a request in process, so we need + # to skip the loading check otherwise it will time out. + # + # [1]: https://gitlab.com/gitlab-org/gitlab/-/blob/4a99af809b86047ce3c8985e6582748bbd23fc84/qa/qa/page/component/members/members_table.rb#L54 + return unless has_element?(:confirmation_modal, skip_finished_loading_check: true) + + click_element(:confirm_ok_button, skip_finished_loading_check: true) + end end end end diff --git a/qa/qa/page/component/design_management.rb b/qa/qa/page/component/design_management.rb index 71c24b6cac8..4caa5169c5f 100644 --- a/qa/qa/page/component/design_management.rb +++ b/qa/qa/page/component/design_management.rb @@ -78,7 +78,7 @@ module QA end def update_design(filename) - filepath = ::File.join(Runtime::Path.fixtures_path, 'designs', 'update', filename) + filepath = Runtime::Path.fixture('designs', 'update', filename) add_design(filepath) end diff --git a/qa/qa/page/component/dropdown.rb b/qa/qa/page/component/dropdown.rb index 767cd40daa2..5f60a789900 100644 --- a/qa/qa/page/component/dropdown.rb +++ b/qa/qa/page/component/dropdown.rb @@ -33,12 +33,13 @@ module QA def clear_current_selection_if_present expand_select_list unless dropdown_open? + Support::WaitForRequests.wait_for_requests - if has_css?('button[data-testid="listbox-reset-button"]') + if has_css?('button[data-testid="listbox-reset-button"]', wait: 0) find('button[data-testid="listbox-reset-button"]').click - elsif dropdown_open? - expand_select_list end + + expand_select_list if dropdown_open? end def search_item(item_text) diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb index 06a3c6a8845..15155fd9f44 100644 --- a/qa/qa/page/component/issuable/sidebar.rb +++ b/qa/qa/page/component/issuable/sidebar.rb @@ -31,7 +31,7 @@ module QA end base.view 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue' do - element :labels_dropdown_content + element :labels_select_dropdown_contents end base.view 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_value.vue' do @@ -137,7 +137,7 @@ module QA click_element(:edit_button) labels.each do |label| - within_element(:labels_dropdown_content) do + within_element(:labels_select_dropdown_contents) do fill_element(:dropdown_input_field, label) click_button(text: label) end diff --git a/qa/qa/page/component/members/invite_members_modal.rb b/qa/qa/page/component/members/invite_members_modal.rb index 0220bb1e4fc..ae51213b3e2 100644 --- a/qa/qa/page/component/members/invite_members_modal.rb +++ b/qa/qa/page/component/members/invite_members_modal.rb @@ -6,6 +6,7 @@ module QA module Members module InviteMembersModal extend QA::Page::PageConcern + include QA::Page::Component::Dropdown def self.included(base) super @@ -16,11 +17,6 @@ module QA element :invite_members_modal_content end - base.view 'app/assets/javascripts/invite_members/components/group_select.vue' do - element :group_select_dropdown_search_field - element :group_select_dropdown_item - end - base.view 'app/assets/javascripts/invite_members/components/members_token_select.vue' do element :members_token_select_input end @@ -61,11 +57,9 @@ module QA within_element(:invite_members_modal_content) do click_button 'Select a group' - Support::Waiter.wait_until { has_element?(:group_select_dropdown_item) } - - fill_element :group_select_dropdown_search_field, group_name Support::WaitForRequests.wait_for_requests - click_button group_name + + search_and_select(group_name) set_access_level(access_level) end diff --git a/qa/qa/page/component/members/members_table.rb b/qa/qa/page/component/members/members_table.rb index 46010a0f9ab..15b0f230341 100644 --- a/qa/qa/page/component/members/members_table.rb +++ b/qa/qa/page/component/members/members_table.rb @@ -14,6 +14,7 @@ module QA include MembersFilter include RemoveMemberModal include RemoveGroupModal + include ConfirmModal end base.view 'app/assets/javascripts/members/components/table/members_table.vue' do @@ -53,6 +54,8 @@ module QA click_element :access_level_dropdown click_element :access_level_link, text: access_level end + + click_confirmation_ok_button_if_present end def remove_member(username) diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb index 84cc481945f..638c46f228f 100644 --- a/qa/qa/page/component/note.rb +++ b/qa/qa/page/component/note.rb @@ -73,11 +73,13 @@ module QA end def collapse_replies + close_rich_text_promo_popover_if_present click_element :collapse_replies_button end # Attachment option should be an absolute path def comment(text, attachment: nil, filter: :all_activities) + close_rich_text_promo_popover_if_present method("select_#{filter}_filter").call fill_element :comment_field, "#{text}\n" @@ -148,7 +150,8 @@ module QA def start_discussion(text) fill_element :comment_field, text - within_element(:comment_button) { click_button(class: 'dropdown-toggle-split') } + close_rich_text_promo_popover_if_present + within_element(:comment_button) { click_button(class: 'gl-new-dropdown-toggle') } click_element :discussion_menu_item click_element :comment_button diff --git a/qa/qa/page/component/rich_text_popover.rb b/qa/qa/page/component/rich_text_popover.rb new file mode 100644 index 00000000000..6a187dcedc5 --- /dev/null +++ b/qa/qa/page/component/rich_text_popover.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module QA + module Page + module Component + module RichTextPopover + extend QA::Page::PageConcern + + def self.included(base) + super + + base.view 'app/assets/javascripts/vue_shared/components/markdown/editor_mode_switcher.vue' do + element :rich_text_promo_popover + end + + base.view 'app/views/shared/_broadcast_message.html.haml' do + element :close_button + end + end + + def close_rich_text_promo_popover_if_present + return unless has_element?(:rich_text_promo_popover, wait: 0) + + within_element(:rich_text_promo_popover) do + click_element(:close_button) + end + end + end + end + end +end diff --git a/qa/qa/page/file/form.rb b/qa/qa/page/file/form.rb index d0113d66dec..06b75f42e4d 100644 --- a/qa/qa/page/file/form.rb +++ b/qa/qa/page/file/form.rb @@ -46,7 +46,7 @@ module QA when 'LICENSE' click_element :license_dropdown else - raise %Q(Unsupported template_type "#{template_type}". Please confirm that it is a valid option.) + raise %(Unsupported template_type "#{template_type}". Please confirm that it is a valid option.) end filter_and_select template end diff --git a/qa/qa/page/group/bulk_import.rb b/qa/qa/page/group/bulk_import.rb index 90bc7a66dcc..f57b76b11a9 100644 --- a/qa/qa/page/group/bulk_import.rb +++ b/qa/qa/page/group/bulk_import.rb @@ -8,6 +8,7 @@ module QA element :import_table element :import_item element :import_status_indicator + element :filter_groups end view "app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue" do @@ -22,6 +23,12 @@ module QA element :import_group_button end + def filter_group(source_group_name) + find('input[data-testid="filter-groups"]').set(source_group_name).send_keys(:return) + + finished_loading? + end + # Import source group in to target group # # @param [String] source_group_name @@ -30,6 +37,8 @@ module QA def import_group(source_group_name, target_group_name) finished_loading? + filter_group(source_group_name) + within_element(:import_item, source_group: source_group_name) do click_element(:target_namespace_selector_dropdown) click_element(:target_group_dropdown_item, group_name: target_group_name) diff --git a/qa/qa/page/group/sub_menus/common.rb b/qa/qa/page/group/sub_menus/common.rb index 3cbca3db359..6369306da3f 100644 --- a/qa/qa/page/group/sub_menus/common.rb +++ b/qa/qa/page/group/sub_menus/common.rb @@ -13,7 +13,7 @@ module QA base.class_eval do view 'app/views/shared/nav/_sidebar.html.haml' do - element :group_sidebar, 'qa_selector: sidebar_qa_selector(sidebar.container)' # rubocop:disable QA/ElementWithPattern + element :group_sidebar, 'testid: sidebar_qa_selector(sidebar.container)' # rubocop:disable QA/ElementWithPattern end end end diff --git a/qa/qa/page/issuable/new.rb b/qa/qa/page/issuable/new.rb index b74dc705888..0a8be750752 100644 --- a/qa/qa/page/issuable/new.rb +++ b/qa/qa/page/issuable/new.rb @@ -4,6 +4,8 @@ module QA module Page module Issuable class New < Page::Base + include Page::Component::RichTextPopover + view 'app/views/shared/issuable/form/_title.html.haml' do element :issuable_form_title_field end @@ -20,6 +22,10 @@ module QA element :issuable_label_dropdown end + view 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue' do + element :labels_select_dropdown_contents + end + view 'app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml' do element :assign_to_me_link end @@ -44,6 +50,7 @@ module QA end def choose_template(template_name) + close_rich_text_promo_popover_if_present click_element :template_dropdown within_element(:template_dropdown) do click_on template_name @@ -53,7 +60,7 @@ module QA def select_label(label) click_element :issuable_label_dropdown - click_link label.title + click_on(label.title, match: :prefer_exact) click_element :issuable_label_dropdown # So that the dropdown goes away(click away action) end diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index 3a836210dea..8812c792554 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -43,6 +43,7 @@ module QA element :github_login_button element :oidc_login_button element :gitlab_oauth_login_button + element :facebook_login_button end view 'app/views/layouts/devise.html.haml' do @@ -102,6 +103,12 @@ module QA click_element :sign_in_button end + if Runtime::Env.super_sidebar_enabled? + Page::Main::Menu.perform(&:enable_new_navigation) + else + Page::Main::Menu.perform(&:disable_new_navigation) + end + Page::Main::Menu.perform(&:signed_in?) end @@ -128,8 +135,8 @@ module QA '/users/sign_in' end - def has_sign_in_tab? - has_element?(:sign_in_tab) + def has_sign_in_tab?(wait: Capybara.default_max_wait_time) + has_element?(:sign_in_tab, wait: wait) end def has_ldap_tab? @@ -186,6 +193,11 @@ module QA click_element :github_login_button end + def sign_in_with_facebook + set_initial_password_if_present + click_element :facebook_login_button + end + def sign_in_with_saml set_initial_password_if_present click_element :saml_login_button @@ -203,7 +215,6 @@ module QA def sign_out_and_sign_in_as(user:) Menu.perform(&:sign_out_if_signed_in) - has_sign_in_tab? sign_in_using_credentials(user: user) end @@ -225,7 +236,7 @@ module QA def sign_in_using_gitlab_credentials(user:, skip_page_validation: false) wait_if_retry_later - switch_to_sign_in_tab if has_sign_in_tab? + switch_to_sign_in_tab if has_sign_in_tab?(wait: 0) switch_to_standard_tab if has_standard_tab? fill_in_credential(user) @@ -258,7 +269,11 @@ module QA wait_for_gitlab_to_respond - Page::Main::Menu.perform(&:enable_new_navigation) if Runtime::Env.super_sidebar_enabled? + if Runtime::Env.super_sidebar_enabled? + Page::Main::Menu.perform(&:enable_new_navigation) + else + Page::Main::Menu.perform(&:disable_new_navigation) + end wait_for_gitlab_to_respond diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb index 7e0337035e3..29c4360f814 100644 --- a/qa/qa/page/main/menu.rb +++ b/qa/qa/page/main/menu.rb @@ -20,7 +20,7 @@ module QA end view 'app/assets/javascripts/super_sidebar/components/user_menu.vue' do - element :user_menu, required: !Runtime::Env.phone_layout? + element :user_dropdown, required: !Runtime::Env.phone_layout? element :user_avatar_content, required: !Runtime::Env.phone_layout? element :sign_out_link element :edit_profile_link @@ -31,8 +31,11 @@ module QA end view 'app/assets/javascripts/super_sidebar/components/user_bar.vue' do - element :global_search_button - element :stop_impersonation_link + element :super_sidebar_search_button + element :stop_impersonation_btn + element :issues_shortcut_button, required: !Runtime::Env.phone_layout? + element :merge_requests_shortcut_button, required: !Runtime::Env.phone_layout? + element :todos_shortcut_button, required: !Runtime::Env.phone_layout? end view 'app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue' do @@ -43,8 +46,8 @@ module QA element :navbar, required: true element :canary_badge_link element :user_avatar_content, required: !Runtime::Env.phone_layout? - element :user_menu, required: !Runtime::Env.phone_layout? - element :stop_impersonation_link + element :user_dropdown, required: !Runtime::Env.phone_layout? + element :stop_impersonation_btn element :issues_shortcut_button, required: !Runtime::Env.phone_layout? element :merge_requests_shortcut_button, required: !Runtime::Env.phone_layout? element :todos_shortcut_button, required: !Runtime::Env.phone_layout? @@ -62,7 +65,7 @@ module QA end view 'app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue' do - element :menu_subview_container + element :menu_subview end view 'lib/gitlab/nav/top_nav_menu_item.rb' do @@ -240,7 +243,7 @@ module QA end def search_for(term) - click_element(Runtime::Env.super_sidebar_enabled? ? :global_search_button : :search_box) + click_element(Runtime::Env.super_sidebar_enabled? ? :super_sidebar_search_button : :search_box) fill_element(:global_search_input, "#{term}\n") end @@ -262,7 +265,7 @@ module QA end def click_stop_impersonation_link - click_element(:stop_impersonation_link) + click_element(:stop_impersonation_btn) end # To verify whether the user has been directed to a canary web node @@ -278,11 +281,23 @@ module QA def enable_new_navigation Runtime::Logger.info("Enabling super sidebar!") return Runtime::Logger.info("User is not signed in, skipping") unless has_element?(:navbar, wait: 2) + return Runtime::Logger.info("Super sidebar is already enabled") if has_css?('[data-testid="super-sidebar"]') within_user_menu { click_element(:new_navigation_toggle) } end + def disable_new_navigation + Runtime::Logger.info("Disabling super sidebar!") + return Runtime::Logger.info("User is not signed in, skipping") unless has_element?(:navbar, wait: 2) + + unless has_css?('[data-testid="super-sidebar"]') + return Runtime::Logger.info("Super sidebar is already disabled") + end + + within_user_menu { click_element(:new_navigation_toggle) } + end + private def within_top_menu(&block) @@ -293,20 +308,20 @@ module QA within_top_menu do click_element :user_avatar_content unless has_element?(:user_profile_link, wait: 1) - within_element(:user_menu, &block) + within_element(:user_dropdown, &block) end end def within_groups_menu(&block) go_to_menu_dropdown_option(:groups_dropdown) - within_element(:menu_subview_container, &block) + within_element(:menu_subview, &block) end def within_projects_menu(&block) go_to_menu_dropdown_option(:projects_dropdown) - within_element(:menu_subview_container, &block) + within_element(:menu_subview, &block) end def click_admin_area diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index e0ec5d50bc5..71c2aa2d0b3 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -6,6 +6,7 @@ module QA class Show < Page::Base include Page::Component::Note include Page::Component::Issuable::Sidebar + include Page::Component::RichTextPopover view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do element :review_preview_dropdown @@ -285,6 +286,7 @@ module QA end def merge! + close_rich_text_promo_popover_if_present try_to_merge! finished_loading? @@ -331,13 +333,15 @@ module QA # # @param [Boolean] transient_test true if the current test is a transient test (default: false) def wait_until_ready_to_merge(transient_test: false) - wait_until do - has_element?(:merge_button) + wait_until(message: "Waiting for ready to merge", sleep_interval: 1) do + # changes in mr are rendered async, because of that mr can sometimes show no changes and there will be no + # merge button, in such case we must retry loop otherwise find_element will raise ElementNotFound error + next false unless has_element?(:merge_button, wait: 1) break true unless find_element(:merge_button).disabled? # If the widget shows "Merge blocked: new changes were just added" we can refresh the page and check again - next false if has_element?(:head_mismatch_content) + next false if has_element?(:head_mismatch_content, wait: 1) # Stop waiting if we're in a transient test. By this point we're in an unexpected state and should let the # test fail so we can investigate. If we're not in a transient test we keep trying until we reach timeout. @@ -364,6 +368,7 @@ module QA end def merge_immediately! + close_rich_text_promo_popover_if_present retry_until(reload: true, sleep_interval: 1, max_attempts: 12) do if has_element?(:merge_moment_dropdown) click_element(:merge_moment_dropdown, skip_finished_loading_check: true) @@ -377,6 +382,7 @@ module QA end def try_to_merge! + close_rich_text_promo_popover_if_present # Revisit after merge page re-architect is done https://gitlab.com/gitlab-org/gitlab/-/issues/300042 # To remove page refresh logic if possible wait_until_ready_to_merge diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb index af328f876f7..bbe0f91abf6 100644 --- a/qa/qa/page/project/branches/show.rb +++ b/qa/qa/page/project/branches/show.rb @@ -14,7 +14,6 @@ module QA end view 'app/views/projects/branches/_branch.html.haml' do - element :badge_content element :branch_container element :branch_link end @@ -23,13 +22,6 @@ module QA element :all_branches_container end - view 'app/assets/javascripts/branches/components/delete_merged_branches.vue' do - element :delete_merged_branches_dropdown_button - element :delete_merged_branches_button - element :delete_merged_branches_input - element :delete_merged_branches_confirmation_button - end - def delete_branch(branch_name) within_element(:branch_container, name: branch_name) do click_element(:delete_branch_button) @@ -47,20 +39,6 @@ module QA end end end - - def has_branch_with_badge?(branch_name, badge) - within_element(:branch_container, name: branch_name) do - has_element?(:badge_content, text: badge) - end - end - - def delete_merged_branches(branches_length) - click_element(:delete_merged_branches_dropdown_button) - click_element(:delete_merged_branches_button) - fill_element(:delete_merged_branches_input, branches_length) - click_element(:delete_merged_branches_confirmation_button) - finished_loading? - end end end end diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb index c2f334c930a..c95375dbbb9 100644 --- a/qa/qa/page/project/issue/show.rb +++ b/qa/qa/page/project/issue/show.rb @@ -9,6 +9,7 @@ module QA include Page::Component::DesignManagement include Page::Component::Issuable::Sidebar include Page::Component::Issuable::Common + include Page::Component::RichTextPopover # We need to check phone_layout? instead of mobile_layout? here # since tablets have the regular top navigation bar prepend Mobile::Page::Project::Issue::Show if Runtime::Env.phone_layout? diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb index 41c61aaecc8..c955b4d933d 100644 --- a/qa/qa/page/project/pipeline/show.rb +++ b/qa/qa/page/project/pipeline/show.rb @@ -7,19 +7,8 @@ module QA class Show < QA::Page::Base include Component::CiBadgeLink - # TODO: remove element with FF pipeline_details_header_vue removal - view 'app/assets/javascripts/vue_shared/components/header_ci_component.vue' do - element :pipeline_header - end - - # TODO: make this a requirement at page render - `required: true` - # together with FF pipeline_details_header_vue removal view 'app/assets/javascripts/pipelines/components/pipeline_details_header.vue' do - element :pipeline_details_header - end - - view 'app/views/projects/pipelines/_info.html.haml' do - element :merge_request_badge_tag + element :pipeline_details_header, required: true end view 'app/assets/javascripts/pipelines/components/graph/graph_component.vue' do @@ -63,20 +52,11 @@ module QA end def running?(wait: 0) - # TODO: remove condition check together with FF pipeline_details_header_vue removal - # issue: https://gitlab.com/gitlab-org/gitlab/-/issues/411442 - - element = has_element?(:pipeline_details_header) ? :pipeline_details_header : :pipeline_header - - within_element(element) do + within_element(:pipeline_details_header) do page.has_content?('running', wait: wait) end end - def has_merge_request_badge_tag? - has_element?(:merge_request_badge_tag) - end - def has_build?(name, status: :success, wait: nil) if status within_element(:job_item_container, text: name) do diff --git a/qa/qa/page/project/settings/alerts.rb b/qa/qa/page/project/settings/alerts.rb index 3ff4ef20bde..2646e271bd2 100644 --- a/qa/qa/page/project/settings/alerts.rb +++ b/qa/qa/page/project/settings/alerts.rb @@ -25,7 +25,6 @@ module QA element :save_and_create_alert_button element :test_payload_field element :send_test_alert_button - element :prometheus_url_field end def go_to_alert_settings @@ -73,19 +72,12 @@ module QA def select_prometheus click_element(:integration_type_dropdown) find("option[value='PROMETHEUS']").click - - # Click outside of the list to close it - click_element(:prometheus_url_field) end def enter_integration_name(name) fill_element(:integration_name_field, name) end - def fill_in_prometheus_url(url = Runtime::Scenario.gitlab_address) - fill_element(:prometheus_url_field, url) - end - def activate_integration within_element(:active_toggle_container) do find('.gl-toggle').click diff --git a/qa/qa/page/project/snippet/new.rb b/qa/qa/page/project/snippet/new.rb index 47200ba5fda..4a13e597e15 100644 --- a/qa/qa/page/project/snippet/new.rb +++ b/qa/qa/page/project/snippet/new.rb @@ -20,7 +20,7 @@ module QA # webdriver to miss the hit so we wait for the svg to load before # clicking the button. within_element(:svg_content) do - has_element?(:js_lazy_loaded) + has_element?(:js_lazy_loaded_content) end click_element(:create_first_snippet_link) end diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb index 8432edff046..19802f846d8 100644 --- a/qa/qa/page/project/web_ide/edit.rb +++ b/qa/qa/page/project/web_ide/edit.rb @@ -178,7 +178,7 @@ module QA within_element(:template_list_content) do click_on file_name rescue Capybara::ElementNotFound - raise ElementNotFound, %Q(Couldn't find file template named "#{file_name}". Please confirm that it is a valid option.) + raise ElementNotFound, %(Couldn't find file template named "#{file_name}". Please confirm that it is a valid option.) end # Wait for the modal to fade out too @@ -192,7 +192,7 @@ module QA begin click_on template rescue Capybara::ElementNotFound - raise ElementNotFound, %Q(Couldn't find template "#{template}" for #{file_name}. Please confirm that it exists in the list of templates.) + raise ElementNotFound, %(Couldn't find template "#{template}" for #{file_name}. Please confirm that it exists in the list of templates.) end end end diff --git a/qa/qa/page/user/show.rb b/qa/qa/page/user/show.rb index f14ddea3e8b..1cfaca2fc57 100644 --- a/qa/qa/page/user/show.rb +++ b/qa/qa/page/user/show.rb @@ -5,10 +5,13 @@ module QA module User class Show < Page::Base view 'app/views/users/show.html.haml' do - element :follow_user_link element :following_tab end + view 'app/views/users/_follow_user.html.haml' do + element :follow_user_link + end + view 'app/views/shared/users/_user.html.haml' do element :user_link end diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb index e12a8f97d95..459670add36 100644 --- a/qa/qa/resource/base.rb +++ b/qa/qa/resource/base.rb @@ -17,7 +17,8 @@ module QA class << self # Initialize new instance of class without fabrication # - # @param [Proc] prepare_block + # @yieldparam [self] instance of page object + # @return [self] def init(&prepare_block) new.tap(&prepare_block) end diff --git a/qa/qa/resource/design.rb b/qa/qa/resource/design.rb index 127e7ae61e3..68d8e43ad3d 100644 --- a/qa/qa/resource/design.rb +++ b/qa/qa/resource/design.rb @@ -111,7 +111,7 @@ module QA private def filepath - ::File.join(Runtime::Path.fixtures_path, 'designs', filename) + Runtime::Path.fixture('designs', filename) end end end diff --git a/qa/qa/resource/events/project.rb b/qa/qa/resource/events/project.rb index c1bd921c3cf..693fdd6168f 100644 --- a/qa/qa/resource/events/project.rb +++ b/qa/qa/resource/events/project.rb @@ -7,21 +7,21 @@ module QA include Events::Base def push_events(commit_message) - QA::Runtime::Logger.info(%Q[#{self.class.name} - wait for and fetch push events"]) + QA::Runtime::Logger.info(%[#{self.class.name} - wait for and fetch push events"]) fetch_events do events(action: 'pushed').select { |event| event.dig(:push_data, :commit_title) == commit_message } end end def wait_for_merge(title) - QA::Runtime::Logger.info(%Q[#{self.class.name} - wait_for_merge with title "#{title}"]) + QA::Runtime::Logger.info(%[#{self.class.name} - wait_for_merge with title "#{title}"]) wait_for_event do events(action: 'accepted', target_type: 'merge_request').any? { |event| event[:target_title] == title } end end def wait_for_push(commit_message) - QA::Runtime::Logger.info(%Q[#{self.class.name} - wait_for_push with commit message "#{commit_message}"]) + QA::Runtime::Logger.info(%[#{self.class.name} - wait_for_push with commit message "#{commit_message}"]) wait_for_event do events(action: 'pushed').any? { |event| event.dig(:push_data, :commit_title) == commit_message } end @@ -32,7 +32,7 @@ module QA end def wait_for_push_new_branch(branch_name = self.default_branch) - QA::Runtime::Logger.info(%Q[#{self.class.name} - wait_for_push_new_branch with branch_name "#{branch_name}"]) + QA::Runtime::Logger.info(%[#{self.class.name} - wait_for_push_new_branch with branch_name "#{branch_name}"]) wait_for_event do events(action: 'pushed').any? { |event| event.dig(:push_data, :ref) == branch_name } end diff --git a/qa/qa/resource/import_project.rb b/qa/qa/resource/import_project.rb index a490905cbd6..1709a9eb989 100644 --- a/qa/qa/resource/import_project.rb +++ b/qa/qa/resource/import_project.rb @@ -7,7 +7,7 @@ module QA def initialize @name = "ImportedProject-#{SecureRandom.hex(8)}" - @file_path = ::File.join(Runtime::Path.fixtures_path, 'export.tar.gz') + @file_path = Runtime::Path.fixture('export.tar.gz') end def fabricate! diff --git a/qa/qa/resource/issuable.rb b/qa/qa/resource/issuable.rb index 5aee27b46d4..508f412711a 100644 --- a/qa/qa/resource/issuable.rb +++ b/qa/qa/resource/issuable.rb @@ -5,7 +5,7 @@ module QA class Issuable < Base using Rainbow - # Commentes (notes) path + # Comments (notes) path # # @return [String] def api_comments_path diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb index a5d5795b0de..a39e04c61a3 100644 --- a/qa/qa/resource/issue.rb +++ b/qa/qa/resource/issue.rb @@ -69,6 +69,13 @@ module QA "#{api_get_path}/related_merge_requests" end + # Close issue + # + # @return [void] + def close + api_put_to(api_put_path, state_event: "close") + end + def set_issue_assignees(assignee_ids:) put_body = { assignee_ids: assignee_ids } response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb index 0d1a0bb2cd4..93e8c4f3be6 100644 --- a/qa/qa/resource/merge_request.rb +++ b/qa/qa/resource/merge_request.rb @@ -45,7 +45,7 @@ module QA resource.project = project resource.api_client = api_client resource.commit_message = 'This is a test commit' - resource.add_files([{ 'file_path': "file-#{SecureRandom.hex(8)}.txt", 'content': 'MR init' }]) + resource.add_files([{ file_path: "file-#{SecureRandom.hex(8)}.txt", content: 'MR init' }]) resource.branch = target_branch resource.start_branch = project.default_branch if target_branch != project.default_branch @@ -60,7 +60,7 @@ module QA resource.branch = source_branch resource.start_branch = target_branch - files = [{ 'file_path': file_name, 'content': file_content }] + files = [{ file_path: file_name, content: file_content }] update_existing_file ? resource.update_files(files) : resource.add_files(files) end end @@ -139,7 +139,8 @@ module QA source_branch: source_branch, target_branch: target_branch, title: title, - reviewer_ids: reviewer_ids + reviewer_ids: reviewer_ids, + labels: labels.join(",") } end diff --git a/qa/qa/resource/personal_access_token_cache.rb b/qa/qa/resource/personal_access_token_cache.rb index 0874618201a..078df8e6779 100644 --- a/qa/qa/resource/personal_access_token_cache.rb +++ b/qa/qa/resource/personal_access_token_cache.rb @@ -9,9 +9,9 @@ module QA token = @personal_access_tokens[username] log_message = if token - %Q[Retrieved cached token for username: #{username}, last six chars of token:#{token[-6..]}] + %[Retrieved cached token for username: #{username}, last six chars of token:#{token[-6..]}] else - %Q[No cached token found for username: #{username}] + %[No cached token found for username: #{username}] end QA::Runtime::Logger.info(log_message) @@ -20,7 +20,7 @@ module QA end def self.set_token_for_username(username, token) - QA::Runtime::Logger.info(%Q[Caching token for username: #{username}, last six chars of token:#{token[-6..]}]) + QA::Runtime::Logger.info(%[Caching token for username: #{username}, last six chars of token:#{token[-6..]}]) @personal_access_tokens[username] = token end end diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb index ed8074b1440..855e1edf3ef 100644 --- a/qa/qa/resource/project_imported_from_github.rb +++ b/qa/qa/resource/project_imported_from_github.rb @@ -3,7 +3,11 @@ module QA module Resource class ProjectImportedFromGithub < Resource::Project - attr_accessor :issue_events_import, :full_notes_import, :attachments_import, :allow_partial_import + attr_accessor :issue_events_import, + :full_notes_import, + :attachments_import, + :allow_partial_import, + :additional_access_tokens attribute :github_repo_id do github_client.repository(github_repository_path).id @@ -58,13 +62,14 @@ module QA new_name: name, target_namespace: @personal_namespace || group.full_path, personal_access_token: github_personal_access_token, + additional_access_tokens: additional_access_tokens, ci_cd_only: false, optional_stages: { single_endpoint_issue_events_import: issue_events_import, single_endpoint_notes_import: full_notes_import, attachments_import: attachments_import } - } + }.compact end def transform_api_resource(api_resource) diff --git a/qa/qa/resource/repository/branch.rb b/qa/qa/resource/repository/branch.rb new file mode 100644 index 00000000000..9e6132b8387 --- /dev/null +++ b/qa/qa/resource/repository/branch.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module QA + module Resource + module Repository + class Branch < Base + attr_accessor :name, :ref + + attribute :project do + Project.fabricate_via_api! do |resource| + resource.name = 'branch-project' + resource.initialize_with_readme = true + end + end + + def initialize + @name = 'test' + @ref = Runtime::Env.default_branch + end + + def fabricate! + raise NotImplementedError + end + + def fabricate_via_api! + resource_web_url(api_get) + rescue ResourceNotFoundError + super + end + + def api_get_path + "/projects/#{project.id}/repository/branches/#{name}" + end + + def api_delete_path + api_get_path + end + + def api_post_path + "/projects/#{project.id}/repository/branches" + end + + def api_post_body + { + branch: name, + ref: ref + } + end + end + end + end +end diff --git a/qa/qa/runtime/application_settings.rb b/qa/qa/runtime/application_settings.rb index 4cbce0972b6..0c88716a01c 100644 --- a/qa/qa/runtime/application_settings.rb +++ b/qa/qa/runtime/application_settings.rb @@ -26,6 +26,15 @@ module QA raise("Couldn't set application settings #{application_settings.inspect}, code: '#{r.code}', body: #{body}") end + # Get a single application setting + # + # @param setting [Symbol] the name of the setting to get + # @param api_client [Runtime::API::Client] the API client representing the admin user who will get the setting + # @return [String] + def get_application_setting(setting, api_client: admin_api_client) + get_application_settings(api_client: api_client).fetch(setting) + end + def get_application_settings(api_client: admin_api_client) parse_body(get(Runtime::API::Request.new(api_client, APPLICATION_SETTINGS_PATH).url)) end diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index 54f9db65afb..517cb00df41 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -253,6 +253,10 @@ module QA enabled?(ENV['USE_SELENOID'], default: false) end + def save_all_videos? + enabled?(ENV['QA_SAVE_ALL_VIDEOS'], default: false) + end + def require_video_variables! docs_link = 'https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/running_against_remote_grid.md#testing-with-selenoid' use_selenoid? || (raise ArgumentError, "USE_SELENOID is required! See docs: #{docs_link}") @@ -282,6 +286,14 @@ module QA ENV['QA_GITHUB_PASSWORD'] end + def facebook_username + ENV['QA_FACEBOOK_USERNAME'] + end + + def facebook_password + ENV['QA_FACEBOOK_PASSWORD'] + end + def forker? !!(forker_username && forker_password) end @@ -444,6 +456,10 @@ module QA ENV['QA_GITHUB_ACCESS_TOKEN'].to_s.strip end + def github_additional_access_tokens + ENV['QA_ADDITIONAL_GITHUB_ACCESS_TOKENS'] + end + def require_github_access_token! return unless github_access_token.empty? @@ -558,6 +574,10 @@ module QA ENV.fetch('QA_CONTAINER_REGISTRY_HOST', 'registry.gitlab.com') end + def runner_container_image + ENV.fetch('QA_RUNNER_CONTAINER_IMAGE', 'gitlab-runner:alpine') + end + # ENV variables for authenticating against a private container registry # These need to be set if using the # Service::DockerRun::Mixins::ThirdPartyDocker module @@ -622,6 +642,10 @@ module QA ENV['QA_1P_GITHUB_UUID'] end + def gdk_url + ENV['GDK_URL'] + end + private def remote_grid_credentials diff --git a/qa/qa/runtime/fixtures.rb b/qa/qa/runtime/fixtures.rb index 201cf7f0fcb..4319f142bba 100644 --- a/qa/qa/runtime/fixtures.rb +++ b/qa/qa/runtime/fixtures.rb @@ -35,7 +35,7 @@ module QA end def read_fixture(fixture_path, file_name) - File.read(File.join(Runtime::Path.fixtures_path, fixture_path, file_name)) + File.read(Runtime::Path.fixture(fixture_path, file_name)) end private diff --git a/qa/qa/runtime/gpg.rb b/qa/qa/runtime/gpg.rb index 3314b14cd68..fb2a63ba2e3 100644 --- a/qa/qa/runtime/gpg.rb +++ b/qa/qa/runtime/gpg.rb @@ -14,7 +14,7 @@ module QA def key return @key if defined?(@key) - shell("gpg --import #{File.join(Path.fixtures_path, 'gpg', 'admin.asc')}") + shell("gpg --import #{Path.fixture('gpg', 'admin.asc')}") @key = shell("gpg --armor --export #{key_id}") end end diff --git a/qa/qa/runtime/path.rb b/qa/qa/runtime/path.rb index fd451f2df19..ae1b26ca84a 100644 --- a/qa/qa/runtime/path.rb +++ b/qa/qa/runtime/path.rb @@ -3,14 +3,18 @@ module QA module Runtime module Path - extend self + class << self + def qa_root + ::File.expand_path('../../', __dir__) + end - def qa_root - ::File.expand_path('../../', __dir__) - end + def fixtures_path + ::File.expand_path('../fixtures', __dir__) + end - def fixtures_path - ::File.expand_path('../fixtures', __dir__) + def fixture(*args) + ::File.join(fixtures_path, *args) + end end end end diff --git a/qa/qa/scenario/test/instance/airgapped.rb b/qa/qa/scenario/test/instance/airgapped.rb index 556741ec040..1d4d57b342e 100644 --- a/qa/qa/scenario/test/instance/airgapped.rb +++ b/qa/qa/scenario/test/instance/airgapped.rb @@ -8,7 +8,7 @@ module QA include Bootable include SharedAttributes def perform(address, *rspec_options) - Runtime::Scenario.define(:runner_network, 'airgapped') + Runtime::Scenario.define(:network, 'airgapped') super end diff --git a/qa/qa/scenario/test/instance/blocking.rb b/qa/qa/scenario/test/instance/blocking.rb new file mode 100644 index 00000000000..26bd71e04e8 --- /dev/null +++ b/qa/qa/scenario/test/instance/blocking.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module QA + module Scenario + module Test + module Instance + class Blocking < All + tags :reliable, + *Specs::Runner::DEFAULT_SKIPPED_TAGS.map { |tag| :"~#{tag}" } + end + end + end + end +end diff --git a/qa/qa/scenario/test/instance/non_blocking.rb b/qa/qa/scenario/test/instance/non_blocking.rb new file mode 100644 index 00000000000..602fa60b646 --- /dev/null +++ b/qa/qa/scenario/test/instance/non_blocking.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module QA + module Scenario + module Test + module Instance + class NonBlocking < All + tags :"~reliable", + :"~smoke", + *Specs::Runner::DEFAULT_SKIPPED_TAGS.map { |tag| :"~#{tag}" } + end + end + end + end +end diff --git a/qa/qa/scenario/test/integration/oauth.rb b/qa/qa/scenario/test/integration/oauth.rb new file mode 100644 index 00000000000..912156fbc29 --- /dev/null +++ b/qa/qa/scenario/test/integration/oauth.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module QA + module Scenario + module Test + module Integration + class OAuth < Test::Instance::All + tags :oauth + end + end + end + end +end diff --git a/qa/qa/service/docker_run/base.rb b/qa/qa/service/docker_run/base.rb index 1a25aeb4c19..d6b50db7fa9 100644 --- a/qa/qa/service/docker_run/base.rb +++ b/qa/qa/service/docker_run/base.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'socket' + module QA module Service module DockerRun @@ -11,8 +13,7 @@ module QA end def initialize - @network = Runtime::Scenario.attributes[:network] || 'test' - @runner_network = Runtime::Scenario.attributes[:runner_network] || @network + @network = gdk_network || Runtime::Scenario.attributes[:network] || 'test' end # Authenticate against a container registry @@ -42,10 +43,6 @@ module QA network_exists?(@network) ? @network : 'bridge' end - def runner_network - network_exists?(@runner_network) ? @runner_network : network - end - def inspect_network(name) shell("docker network inspect #{name}", fail_on_exception: false, return_exit_status: true) end @@ -90,6 +87,33 @@ module QA def health shell("docker inspect --format='{{json .State.Health.Status}}' #{@name}").delete('"') end + + # The network to use when testing against GDK in docker + # + # @return [String] + def gdk_network + return unless Runtime::Env.gdk_url + + 'host' + end + + # The IP address of the docker host when testing against GDK in docker + # + # @return [String] + def gdk_host_ip + return unless Runtime::Env.gdk_url + + Addrinfo.tcp(URI(Runtime::Env.gdk_url).host, nil).ip_address + end + + # Returns the IP address of the docker host + # + # @return [String] + def host_ip + docker_host = shell("docker context inspect --format='{{json .Endpoints.docker.Host}}'").delete('"') + ip = Addrinfo.tcp(URI(docker_host).host, nil).ip_address + ip == '0.0.0.0' ? '127.0.0.1' : ip + end end end end diff --git a/qa/qa/service/docker_run/gitlab_runner.rb b/qa/qa/service/docker_run/gitlab_runner.rb index 078a3048cad..b0bb999e5d6 100644 --- a/qa/qa/service/docker_run/gitlab_runner.rb +++ b/qa/qa/service/docker_run/gitlab_runner.rb @@ -16,7 +16,7 @@ module QA MSG def initialize(name) - @image = "#{QA::Runtime::Env.container_registry_host}/gitlab-org/gitlab-runner:alpine" + @image = "#{QA::Runtime::Env.container_registry_host}/gitlab-org/#{QA::Runtime::Env.runner_container_image}" @name = name || "qa-runner-#{SecureRandom.hex(4)}" @run_untagged = true @executor = :shell @@ -40,9 +40,10 @@ module QA raise("Missing runner token value!") unless token cmd = <<~CMD.tr("\n", ' ') - docker run -d --rm --network #{runner_network} --name #{@name} + docker run -d --rm --network #{network} --name #{@name} #{'-v /var/run/docker.sock:/var/run/docker.sock' if @executor == :docker} --privileged + #{"--add-host gdk.test:#{gdk_host_ip}" if gdk_network} #{@image} #{add_gitlab_tls_cert if @address.include? 'https'} && docker exec --detach #{@name} sh -c "#{register_command}" CMD @@ -51,7 +52,7 @@ module QA wait_until_running_and_configured # Prove airgappedness - shell("docker exec #{@name} sh -c '#{prove_airgap}'") if runner_network == 'airgapped' + shell("docker exec #{@name} sh -c '#{prove_airgap}'") if network == 'airgapped' end def tags=(tags) diff --git a/qa/qa/service/docker_run/ldap.rb b/qa/qa/service/docker_run/ldap.rb index a6982bddf28..ea0f774b8d9 100644 --- a/qa/qa/service/docker_run/ldap.rb +++ b/qa/qa/service/docker_run/ldap.rb @@ -28,7 +28,7 @@ module QA if volume_exists?(volume_name) volume_name else - ::File.join(Runtime::Path.fixtures_path, 'ldap', volume_name) + Runtime::Path.fixture('ldap', volume_name) end end diff --git a/qa/qa/service/docker_run/smocker.rb b/qa/qa/service/docker_run/smocker.rb index b48f8aa84e3..59f32e29b44 100644 --- a/qa/qa/service/docker_run/smocker.rb +++ b/qa/qa/service/docker_run/smocker.rb @@ -38,10 +38,14 @@ module QA @api = nil end + def self.logs + @container&.logs + end + attr_reader :public_port, :admin_port def host_name - return '127.0.0.1' unless QA::Runtime::Env.running_in_ci? || QA::Runtime::Env.qa_hostname + return host_ip unless QA::Runtime::Env.running_in_ci? || QA::Runtime::Env.qa_hostname "#{@name}.#{@network_cache}" end diff --git a/qa/qa/service/docker_run/video.rb b/qa/qa/service/docker_run/video.rb index c75280b1282..601e342b6ba 100644 --- a/qa/qa/service/docker_run/video.rb +++ b/qa/qa/service/docker_run/video.rb @@ -29,6 +29,7 @@ module QA if @recorder_container_name.present? && @browser_container_hostname configure_rspec + configure_rspec_allure if QA::Runtime::Env.generate_allure_report? QA::Runtime::Logger.info("Test failure video recording setup complete!") else @@ -69,17 +70,60 @@ module QA QA::Runtime::Logger.warn("Video deletion error: #{e}") end + def record?(example) + example.metadata[:file_path].include?("/browser_ui/") + end + + def save?(example) + example.exception || QA::Runtime::Env.save_all_videos? + end + + def retrieve_video(example) + return unless record?(example) && example.exception + + # We need to wait until the video is finished processing by checking the size + QA::Support::Waiter.wait_until(max_duration: 30, sleep_interval: 1) do + size = + shell("docker exec #{@recorder_container_name} sh -c 'stat -c %s /data/#{@current_recording_name}.mp4'") + size.to_i > 1024 + end + + shell("docker cp #{@recorder_container_name}:/data/#{@current_recording_name}.mp4 tmp/") + + "#{shell('pwd')}/tmp/#{@current_recording_name}.mp4" + rescue StandardError => e + QA::Runtime::Logger.warn("Video retrieval error: #{e}") + end + private def configure_rspec RSpec.configure do |config| config.prepend_before do |example| - QA::Service::DockerRun::Video.start_recording(example) + QA::Service::DockerRun::Video.start_recording(example) if QA::Service::DockerRun::Video.record?(example) + end + + config.prepend_after do |example| + if QA::Service::DockerRun::Video.record?(example) + QA::Service::DockerRun::Video.stop_recording + QA::Service::DockerRun::Video.delete_video unless QA::Service::DockerRun::Video.save?(example) + end end + end + end + def configure_rspec_allure + RSpec.configure do |config| config.append_after do |example| - QA::Service::DockerRun::Video.stop_recording - QA::Service::DockerRun::Video.delete_video unless example.exception + video_path = QA::Service::DockerRun::Video.retrieve_video(example) + if video_path + Allure.add_attachment( + name: 'video', + source: File.open(video_path), + type: 'video/mp4', + test_case: true + ) + end end end end diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb index 684b18a97a7..56627e51b76 100644 --- a/qa/qa/service/praefect_manager.rb +++ b/qa/qa/service/praefect_manager.rb @@ -198,56 +198,6 @@ module QA destination_storage[:type] == :praefect ? verify_storage_move_to_praefect(repo_path, destination_storage[:name]) : verify_storage_move_to_gitaly(repo_path, destination_storage[:name]) end - def praefect_dataloss_information(project_id) - dataloss_info = [] - cmd = "docker exec #{@praefect} praefect -config /var/opt/gitlab/praefect/config.toml dataloss --partially-unavailable=true" - shell(cmd) { |line| dataloss_info << line.strip } - - # Expected will have a record for each repository in the storage, in the following format - # @hashed/bc/52/bc52dd634277c4a34a2d6210994a9a5e2ab6d33bb4a3a8963410e00ca6c15a02.git: - # Primary: gitaly1 - # In-Sync Storages: - # gitaly1, assigned host - # gitaly3, assigned host - # Outdated Storages: - # gitaly2 is behind by 1 change or less, assigned host - # - # Alternatively, if all repositories are in sync, a concise message is returned - # Virtual storage: default - # All repositories are fully available on all assigned storages! - - # extract the relevant project under test info if it is identified - start_index = dataloss_info.index { |line| line.include?("#{Digest::SHA256.hexdigest(project_id.to_s)}.git") } - unless start_index.nil? - dataloss_info = dataloss_info[start_index, 7] - end - - dataloss_info&.each { |info| QA::Runtime::Logger.debug(info) } - dataloss_info - end - - def wait_for_project_synced_across_all_storages(project_id) - Support::Retrier.retry_until(max_duration: 60) do - praefect_dataloss_information(project_id).include?('All repositories are fully available on all assigned storages!') - end - end - - def accept_dataloss_for_project(project_id, authoritative_storage) - repository_hash = "#{Digest::SHA256.hexdigest(project_id.to_s)}" - repository = "@hashed/#{repository_hash[0, 2]}/#{repository_hash[2, 2]}/#{repository_hash}.git" - - cmd = %{ - docker exec #{@praefect} \ - praefect \ - -config /var/opt/gitlab/praefect/config.toml \ - accept-dataloss \ - --virtual-storage=default \ - --repository=#{repository} \ - --authoritative-storage=#{authoritative_storage} - } - shell(cmd) - end - def wait_for_health_check_all_nodes gitaly_nodes.each { |node| wait_for_gitaly_health_check(node) } end @@ -310,27 +260,6 @@ module QA Support::Waiter.wait_until(sleep_interval: 1) { replication_queue_incomplete_count == 0 && replicated?(project_id) } end - def wait_for_replication_to_node(project_id, node) - Support::Waiter.wait_until(sleep_interval: 1) do - result = [] - shell sql_to_docker_exec_cmd(%{ - select * from replication_queue - where state = 'ready' - and job ->> 'change' = 'update' - and job ->> 'target_node_storage' = '#{node}' - and job ->> 'relative_path' = '#{Digest::SHA256.hexdigest(project_id.to_s)}.git'; - }) do |line| - result << line.strip - QA::Runtime::Logger.debug(line.strip) - end - # The result should look like this when all items are replicated - # id | state | created_at | updated_at | attempt | lock_id | job | meta - # ----+-------+------------+------------+---------+---------+-----+------ - # (0 rows) - result[2] == '(0 rows)' - end - end - def replication_pending? result = [] shell sql_to_docker_exec_cmd( @@ -357,58 +286,6 @@ module QA result.size >= 5 end - def list_untracked_repositories - untracked_repositories = [] - shell "docker exec #{@praefect} bash -c 'gitlab-ctl praefect list-untracked-repositories'" do |line| - # Results look like this - # The following repositories were found on disk, but missing from the tracking database: - # {"relative_path":"@hashed/aa/bb.git","storage":"gitaly1","virtual_storage":"default"} - # {"relative_path":"@hashed/bb/cc.git","storage":"gitaly3","virtual_storage":"default"} - - QA::Runtime::Logger.debug(line.chomp) - untracked_repositories.append(JSON.parse(line)) - rescue JSON::ParserError - # Ignore lines that can't be parsed as JSON - end - - QA::Runtime::Logger.debug("list_untracked_repositories --- #{untracked_repositories}") - untracked_repositories - end - - def track_repository_in_praefect(relative_path, storage, virtual_storage) - cmd = "gitlab-ctl praefect track-repository --repository-relative-path #{relative_path} --authoritative-storage #{storage} --virtual-storage-name #{virtual_storage}" - shell "docker exec #{@praefect} bash -c '#{cmd}'" - end - - def remove_tracked_praefect_repository(relative_path, virtual_storage) - cmd = "gitlab-ctl praefect remove-repository --repository-relative-path #{relative_path} --virtual-storage-name #{virtual_storage} --apply" - shell "docker exec #{@praefect} bash -c '#{cmd}'" - end - - # set_replication_factor assigns or unassigns random storage nodes as necessary to reach the desired replication factor for a repository - def set_replication_factor(relative_path, virtual_storage, factor) - cmd = "/opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -repository #{relative_path} -virtual-storage #{virtual_storage} -replication-factor #{factor}" - shell "docker exec #{@praefect} bash -c '#{cmd}'" - end - - # get_replication_storages retrieves a list of currently assigned storages for a repository - def get_replication_storages(relative_path, virtual_storage) - storage_repositories = [] - query = "SELECT storage FROM repository_assignments WHERE relative_path='#{relative_path}' AND virtual_storage='#{virtual_storage}';" - shell(sql_to_docker_exec_cmd(query)) { |line| storage_repositories << line.strip } - # Returned data from query will be in format - # storage - # -------- - # gitaly1 - # gitaly3 - # gitaly2 - # (3 rows) - # - - # remove 2 header rows and last 2 rows from query response (including blank line) - storage_repositories[2..-3] - end - def modify_repo_access_time(node, repo_path, update_time) repo = "/var/opt/gitlab/git-data/repositories/#{repo_path}" shell(%{ @@ -416,65 +293,6 @@ module QA }) end - def add_repo_to_disk(node, repo_path) - cmd = "GIT_DIR=. git init --initial-branch=main /var/opt/gitlab/git-data/repositories/#{repo_path}" - shell "docker exec --user git #{node} bash -c '#{cmd}'" - modify_repo_access_time(node, repo_path, "24 hours ago") - end - - def remove_repo_from_disk(repo_path) - cmd = "rm -rf /var/opt/gitlab/git-data/repositories/#{repo_path}" - shell "docker exec #{@primary_node} bash -c '#{cmd}'" - shell "docker exec #{@secondary_node} bash -c '#{cmd}'" - shell "docker exec #{@tertiary_node} bash -c '#{cmd}'" - end - - def remove_repository_from_praefect_database(relative_path) - shell sql_to_docker_exec_cmd("delete from repositories where relative_path = '#{relative_path}';") - shell sql_to_docker_exec_cmd("delete from storage_repositories where relative_path = '#{relative_path}';") - end - - def praefect_database_tracks_repo?(relative_path) - storage_repositories = [] - shell sql_to_docker_exec_cmd("SELECT count(*) FROM storage_repositories where relative_path='#{relative_path}';") do |line| - storage_repositories << line - end - QA::Runtime::Logger.debug("storage_repositories count is ---#{storage_repositories}") - - repositories = [] - shell sql_to_docker_exec_cmd("SELECT count(*) FROM repositories where relative_path='#{relative_path}';") do |line| - repositories << line - end - QA::Runtime::Logger.debug("repositories count is ---#{repositories}") - - (storage_repositories[2].to_i >= 1) && (repositories[2].to_i >= 1) - end - - def repository_replicated_to_disk?(node, relative_path) - Support::Waiter.wait_until(max_duration: 300, sleep_interval: 1, raise_on_failure: false) do - result = [] - shell sql_to_docker_exec_cmd("SELECT count(*) FROM storage_repositories where relative_path='#{relative_path}';") do |line| - result << line - end - QA::Runtime::Logger.debug("result is ---#{result}") - result[2].to_i == 3 - end - - repository_exists_on_node_disk?(node, relative_path) - end - - def repository_exists_on_node_disk?(node, relative_path) - # If the dir does not exist it has a non zero exit code leading to a error being raised - # Instead we echo a test line if the dir does not exist, which has a zero exit code, with no output - bash_command = "test -d /var/opt/gitlab/git-data/repositories/#{relative_path} || echo -n 'DIR_DOES_NOT_EXIST'" - result = [] - shell "docker exec #{node} bash -c '#{bash_command}'" do |line| - result << line - end - QA::Runtime::Logger.debug("result is ---#{result}") - result.exclude?("DIR_DOES_NOT_EXIST") - end - private def dataloss_command diff --git a/qa/qa/specs/features/api/12_systems/gitaly/praefect_dataloss_spec.rb b/qa/qa/specs/features/api/12_systems/gitaly/praefect_dataloss_spec.rb deleted file mode 100644 index 7b9164c1fc9..00000000000 --- a/qa/qa/specs/features/api/12_systems/gitaly/praefect_dataloss_spec.rb +++ /dev/null @@ -1,114 +0,0 @@ -# frozen_string_literal: true - -module QA - RSpec.describe 'Systems' do - describe 'Praefect dataloss commands', :orchestrated, :gitaly_cluster, product_group: :gitaly do - let(:praefect_manager) { Service::PraefectManager.new } - - let(:project) do - Resource::Project.fabricate! do |project| - project.name = 'gitaly_cluster-dataloss-project' - project.initialize_with_readme = true - end - end - - before do - praefect_manager.start_all_nodes - end - - it 'confirms that changes are synced across all storages', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/352691' do - expect { praefect_manager.praefect_dataloss_information(project.id) } - .to(eventually_include('All repositories are fully available on all assigned storages!') - .within(max_duration: 60)) - end - - it 'identifies how many changes are not in sync across storages', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/352692' do - # Ensure our test repository is replicated and in a consistent state prior to test - praefect_manager.wait_for_project_synced_across_all_storages(project.id) - - # testing for gitaly2 'out of sync' - praefect_manager.stop_node(praefect_manager.secondary_node) - - number_of_changes = 3 - 1.upto(number_of_changes) do |i| - Resource::Repository::Commit.fabricate_via_api! do |commit| - commit.project = project - commit.branch = "newbranch-#{SecureRandom.hex(8)}" - commit.start_branch = project.default_branch - commit.commit_message = 'Add new file' - commit.add_files( - [{ - file_path: "new_file-#{SecureRandom.hex(8)}.txt", content: 'new file' - }] - ) - end - end - - # testing for gitaly3 'in sync' but marked unhealthy - praefect_manager.stop_node(praefect_manager.tertiary_node) - - project_data_loss = praefect_manager.praefect_dataloss_information(project.id) - aggregate_failures "validate dataloss identified" do - expect(project_data_loss).to include('gitaly1, assigned host') - expect(project_data_loss) - .to include("gitaly2 is behind by #{number_of_changes} changes or less, assigned host, unhealthy") - expect(project_data_loss).to include('gitaly3, assigned host, unhealthy') - end - end - - it 'allows admin resolve scenario where data cannot be recovered', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/352708' do - # Ensure everything is in sync before begining test - praefect_manager.wait_for_project_synced_across_all_storages(project.id) - - Resource::Repository::Commit.fabricate_via_api! do |commit| - commit.project = project - commit.commit_message = 'accept-dataloss-1' - commit.add_files( - [{ - file_path: "new_file-#{SecureRandom.hex(8)}.txt", content: 'Add a commit to gitaly1,gitaly2,gitaly3' - }] - ) - end - - praefect_manager.wait_for_replication_to_node(project.id, praefect_manager.primary_node) - praefect_manager.stop_node(praefect_manager.primary_node) - Resource::Repository::Commit.fabricate_via_api! do |commit| - commit.project = project - commit.commit_message = 'accept-dataloss-2' - commit.add_files( - [{ - file_path: "new_file-#{SecureRandom.hex(8)}.txt", content: 'Add a commit to gitaly2,gitaly3' - }] - ) - end - - praefect_manager.wait_for_replication_to_node(project.id, praefect_manager.secondary_node) - praefect_manager.stop_node(praefect_manager.secondary_node) - Resource::Repository::Commit.fabricate_via_api! do |commit| - commit.project = project - commit.commit_message = 'accept-dataloss-3' - commit.add_files([ - { file_path: "new_file-#{SecureRandom.hex(8)}.txt", content: 'Add a commit to gitaly3' } - ]) - end - - # Confirms that they want to accept dataloss, using gitaly2 as authoritative storage to use as a base - praefect_manager.accept_dataloss_for_project(project.id, praefect_manager.secondary_node) - - # Restart nodes, and allow replication to apply dataloss changes - praefect_manager.start_all_nodes - praefect_manager.wait_for_project_synced_across_all_storages(project.id) - - # Validate that gitaly2 was accepted as the authorative storage - aggregate_failures "validate correct set of commits available" do - expect(project.commits.map { |commit| commit[:message].chomp }).to include('accept-dataloss-1') - expect(project.commits.map { |commit| commit[:message].chomp }).to include('accept-dataloss-2') - expect(project.commits.map { |commit| commit[:message].chomp }).not_to include('accept-dataloss-3') - end - end - end - end -end diff --git a/qa/qa/specs/features/api/12_systems/gitaly/praefect_repo_sync_spec.rb b/qa/qa/specs/features/api/12_systems/gitaly/praefect_repo_sync_spec.rb deleted file mode 100644 index 4f916300ee3..00000000000 --- a/qa/qa/specs/features/api/12_systems/gitaly/praefect_repo_sync_spec.rb +++ /dev/null @@ -1,96 +0,0 @@ -# frozen_string_literal: true - -module QA - RSpec.describe 'Systems' do - describe 'Praefect repository commands', :orchestrated, :gitaly_cluster, product_group: :gitaly do - let(:praefect_manager) { Service::PraefectManager.new } - - let(:repo1) do - { "relative_path" => "@hashed/repo1.git", "storage" => "gitaly1", "virtual_storage" => "default" } - end - - let(:repo2) do - { "relative_path" => "@hashed/path/to/repo2.git", "storage" => "gitaly3", "virtual_storage" => "default" } - end - - before do - praefect_manager.start_all_nodes - praefect_manager.add_repo_to_disk(praefect_manager.primary_node, repo1["relative_path"]) - praefect_manager.add_repo_to_disk(praefect_manager.tertiary_node, repo2["relative_path"]) - end - - after do - praefect_manager.remove_repo_from_disk(repo1["relative_path"]) - praefect_manager.remove_repo_from_disk(repo2["relative_path"]) - praefect_manager.remove_repository_from_praefect_database(repo1["relative_path"]) - praefect_manager.remove_repository_from_praefect_database(repo2["relative_path"]) - end - - it 'allows admin to manage difference between praefect database and disk state', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347606' do - # Some repos are on disk that praefect is not aware of - untracked_repositories = praefect_manager.list_untracked_repositories - expect(untracked_repositories).to include(repo1) - expect(untracked_repositories).to include(repo2) - - # admin manually adds the first repo to the praefect database - praefect_manager - .track_repository_in_praefect(repo1["relative_path"], repo1["storage"], repo1["virtual_storage"]) - untracked_repositories = praefect_manager.list_untracked_repositories - expect(untracked_repositories).not_to include(repo1) - expect(untracked_repositories).to include(repo2) - expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.primary_node, repo1["relative_path"])) - .to be true - expect(praefect_manager.praefect_database_tracks_repo?(repo1["relative_path"])).to be true - - # admin manually adds the second repo to the praefect database - praefect_manager - .track_repository_in_praefect(repo2["relative_path"], repo2["storage"], repo2["virtual_storage"]) - untracked_repositories = praefect_manager.list_untracked_repositories - expect(untracked_repositories).not_to include(repo2) - expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.tertiary_node, repo2["relative_path"])) - .to be true - expect(praefect_manager.praefect_database_tracks_repo?(repo2["relative_path"])).to be true - - # admin ensures replication to other nodes occurs - expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.secondary_node, repo1["relative_path"])) - .to be true - expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.tertiary_node, repo1["relative_path"])) - .to be true - expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.primary_node, repo2["relative_path"])) - .to be true - expect(praefect_manager.repository_replicated_to_disk?(praefect_manager.secondary_node, repo2["relative_path"])) - .to be true - - # admin chooses to remove the first repo completely from praefect and disk - praefect_manager.remove_tracked_praefect_repository(repo1["relative_path"], repo1["virtual_storage"]) - expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.primary_node, repo1["relative_path"])) - .to be false - expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager - .secondary_node, repo1["relative_path"])).to be false - expect(praefect_manager.repository_exists_on_node_disk?(praefect_manager.tertiary_node, repo1["relative_path"])) - .to be false - expect(praefect_manager.praefect_database_tracks_repo?(repo1["relative_path"])).to be false - - untracked_repositories = praefect_manager.list_untracked_repositories - expect(untracked_repositories).not_to include(repo1) - end - - it 'allows admin to control the number of replicas of data', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347566' do - praefect_manager - .track_repository_in_praefect(repo1['relative_path'], repo1['storage'], repo1['virtual_storage']) - - praefect_manager.set_replication_factor(repo1['relative_path'], repo1['virtual_storage'], 2) - replication_storages = praefect_manager - .get_replication_storages(repo1['relative_path'], repo1['virtual_storage']) - expect(replication_storages).to have_attributes(size: 2) - - praefect_manager.set_replication_factor(repo1['relative_path'], repo1['virtual_storage'], 3) - replication_storages = praefect_manager - .get_replication_storages(repo1['relative_path'], repo1['virtual_storage']) - expect(replication_storages).to eq(%w[gitaly1 gitaly2 gitaly3]) - end - end - end -end diff --git a/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb index b81cb70eb18..e9a9f838436 100644 --- a/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb +++ b/qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb @@ -196,6 +196,7 @@ module QA project.add_name_uuid = false project.name = 'imported-project' project.github_personal_access_token = Runtime::Env.github_access_token + project.additional_access_tokens = Runtime::Env.github_additional_access_tokens project.github_repository_path = github_repo project.personal_namespace = user.username project.api_client = Runtime::API::Client.new(user: user) @@ -204,6 +205,10 @@ module QA end end + before do + QA::Support::Helpers::ImportSource.enable('github') + end + after do |example| next unless defined?(@import_time) diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb index ac8399b391d..99f8fb5107e 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb @@ -65,6 +65,10 @@ module QA let(:mrs) { fetch_mrs(imported_project, api_client) } let(:issues) { fetch_issues(imported_project, api_client) } + before do + QA::Support::Helpers::ImportSource.enable(%w[gitlab_project]) + end + # rubocop:disable RSpec/InstanceVariable after do |example| next unless defined?(@import_time) diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb index 7d785630a57..307d0493b2a 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_mr_spec.rb @@ -70,7 +70,11 @@ module QA context 'with merge request' do it( 'successfully imports merge request', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348478' + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348478', + quarantine: { + type: :bug, + issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/414859" + } ) do expect_project_import_finished_successfully expect(imported_mrs.count).to eq(1) diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb index 0c94d6e64d5..7cbccf9be44 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb @@ -24,7 +24,7 @@ module QA group.api_client = admin_api_client group.sandbox = source_sandbox group.path = "source-group-for-import-#{SecureRandom.hex(4)}" - group.avatar = File.new(File.join(Runtime::Path.fixtures_path, 'designs', 'tanuki.jpg'), 'r') + group.avatar = File.new(Runtime::Path.fixture('designs', 'tanuki.jpg'), 'r') end end diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb index 2443887c3d4..fcf15b66c11 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_release_spec.rb @@ -34,10 +34,10 @@ module QA commit_path: release[:commit_path].split("/-/").last, tag_path: release[:tag_path].split("/-/").last, assets: release[:assets].merge({ - sources: release.dig(:assets, :sources).map do |source| - source.merge({ url: source[:url].split("/-/").last }) - end - }), + sources: release.dig(:assets, :sources).map do |source| + source.merge({ url: source[:url].split("/-/").last }) + end + }), milestones: release[:milestones].map do |milestone| milestone.except(:id, :project_id).merge({ web_url: milestone[:web_url].split("/-/").last }) end, diff --git a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb index 86fc154c1cf..d3b702a658c 100644 --- a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb +++ b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Manage', :requires_admin, :skip_live_env, except: { job: 'review-qa-*' } do + RSpec.describe 'Manage', :requires_admin, :skip_live_env, except: { job: %w[review-qa-* gdk-qa-*] } do describe 'rate limits', :reliable, product_group: :import_and_integrate do let(:rate_limited_user) { Resource::User.fabricate_via_api! } let(:api_client) { Runtime::API::Client.new(:gitlab, user: rate_limited_user) } diff --git a/qa/qa/specs/features/api/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/api/3_create/repository/add_list_delete_branches_spec.rb new file mode 100644 index 00000000000..f69a8a4dfa5 --- /dev/null +++ b/qa/qa/specs/features/api/3_create/repository/add_list_delete_branches_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'project-qa-test' + project.description = 'project for qa test' + end + end + + describe 'Create, Retrieve and Delete branches via API', :requires_admin, product_group: :source_code do + created_branch = 'create-branch' + deleted_branch = 'delete-branch' + filename = 'file.txt' + default_branch_commit_message = "Add #{filename}" + + before do + Git::Repository.perform do |repository| + repository.uri = project.repository_http_location.uri + repository.use_default_credentials + repository.try_add_credentials_to_netrc + + repository.act do + init_repository + configure_identity('GitLab QA', 'root@gitlab.com') + + commit_file(filename, 'Test file content', default_branch_commit_message) + push_changes + + checkout(deleted_branch, new_branch: true) + push_changes(deleted_branch) + end + end + project.wait_for_push default_branch_commit_message + end + + it( + 'creates, retrieves and deletes branches', + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347740' + ) do + # Create branch + Resource::Repository::Branch.fabricate_via_api! do |branch| + branch.name = created_branch + branch.project = project + end + + # Retrieve branch + delete_branch = Resource::Repository::Branch.fabricate_via_api! do |branch| + branch.name = deleted_branch + branch.project = project + end + + # Delete branch + delete_branch.remove_via_api! + + # Clone repository, verify branches and commits + Git::Repository.perform do |repository| + repository.uri = project.repository_http_location.uri + repository.use_default_credentials + repository.try_add_credentials_to_netrc + + repository.clone + + branches = repository.remote_branches + expect(branches).to include(created_branch) + expect(branches).not_to include(deleted_branch) + + expect(repository.commits.first).to include(default_branch_commit_message) + + repository.checkout(created_branch) + expect(repository.commits.first).to include(default_branch_commit_message) + end + end + end + end +end diff --git a/qa/qa/specs/features/api/5_package/container_registry/saas/container_registry_spec.rb b/qa/qa/specs/features/api/5_package/container_registry/saas/container_registry_spec.rb index d5073863dff..23d8585d07a 100644 --- a/qa/qa/specs/features/api/5_package/container_registry/saas/container_registry_spec.rb +++ b/qa/qa/specs/features/api/5_package/container_registry/saas/container_registry_spec.rb @@ -19,17 +19,17 @@ module QA end end - let!(:project_access_token) do - QA::Resource::ProjectAccessToken.fabricate_via_api! do |pat| - pat.project = project + let!(:runner) do + Resource::ProjectRunner.fabricate! do |runner| + runner.project = project + runner.name = "runner-for-#{project.name}" + runner.tags = ["runner-for-#{project.name}"] end end - let(:registry) do - Resource::RegistryRepository.init do |repository| - repository.name = project.path_with_namespace - repository.project = project - repository.tag_name = 'master' + let!(:project_access_token) do + QA::Resource::ProjectAccessToken.fabricate_via_api! do |pat| + pat.project = project end end @@ -61,6 +61,8 @@ module QA - docker build -t $IMAGE_TAG . - docker push $IMAGE_TAG - docker pull $IMAGE_TAG + tags: + - "runner-for-#{project.name}" test: image: dwdraju/alpine-curl-jq:latest @@ -74,9 +76,15 @@ module QA - if [ $status_code -ne 200 ]; then exit 1; fi; - 'status_code=$(curl --head --output /dev/null --write-out "%{http_code}\n" --header "PRIVATE-TOKEN: #{masked_token}" "https://${CI_SERVER_HOST}/api/v4/projects/#{project.id}/registry/repositories/$id/tags/master")' - if [ $status_code -ne 404 ]; then exit 1; fi; + tags: + - "runner-for-#{project.name}" YAML end + after do + runner.remove_via_api! + end + it 'pushes, pulls image to the registry and deletes tag', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348001' do Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2, message: "Commit push") do diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb index 54fb2aca990..84664cb8b94 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb @@ -46,7 +46,7 @@ module QA testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347931', quarantine: { type: :bug, - only: { condition: -> { QA::Runtime::Env.super_sidebar_enabled? } }, + only: { condition: -> { !QA::Runtime::Env.super_sidebar_enabled? } }, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/409336' } ) do diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/oauth_login_with_facebook_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/oauth_login_with_facebook_spec.rb new file mode 100644 index 00000000000..ee4c3b167db --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/oauth_login_with_facebook_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Manage', :orchestrated, :oauth, product_group: :authentication_and_authorization do + describe 'OAuth' do + it 'logs in with Facebook credentials', + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/417115' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + + Page::Main::Login.perform(&:sign_in_with_facebook) + + Vendor::Facebook::Page::Login.perform(&:login) + + expect(page).to have_content('Welcome to GitLab') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb index 130006fe424..63d30da9ec3 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb @@ -5,7 +5,7 @@ module QA describe 'Design Management' do let(:issue) { Resource::Issue.fabricate_via_api! } let(:design_filename) { 'banana_sample.gif' } - let(:design) { File.join(Runtime::Path.fixtures_path, 'designs', design_filename) } + let(:design) { Runtime::Path.fixture('designs', design_filename) } let(:annotation) { "This design is great!" } before do 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 4e9d74a5117..1a53fda4cdb 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 @@ -38,7 +38,7 @@ module QA def mailhog_json Support::Retrier.retry_until(sleep_interval: 1) do - Runtime::Logger.debug(%Q[retrieving "#{QA::Runtime::MailHog.api_messages_url}"]) + Runtime::Logger.debug(%[retrieving "#{QA::Runtime::MailHog.api_messages_url}"]) mailhog_response = get QA::Runtime::MailHog.api_messages_url @@ -47,8 +47,8 @@ module QA subjects = mailhog_data.dig('items') .map { |item| mailhog_item_subject(item) } - Runtime::Logger.debug(%Q[Total number of emails: #{total}]) - Runtime::Logger.debug(%Q[Subjects:\n#{subjects.join("\n")}]) + Runtime::Logger.debug(%[Total number of emails: #{total}]) + Runtime::Logger.debug(%[Subjects:\n#{subjects.join("\n")}]) # Expect at least two invitation messages: group and project mailhog_data if mailhog_project_message_count(subjects) >= 1 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 821f885c4c8..33cd3879298 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 @@ -59,9 +59,7 @@ module QA context 'when using attachments in comments', :object_storage do let(:png_file_name) { 'testfile.png' } - let(:file_to_attach) do - File.join(Runtime::Path.fixtures_path, 'designs', png_file_name) - end + let(:file_to_attach) { Runtime::Path.fixture('designs', png_file_name) } before do Resource::Issue.fabricate_via_api_unless_fips! { |issue| issue.project = project }.visit! diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb index 5febb6579df..ce6e9c6a1fb 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Plan', :reliable, product_group: :project_management do + RSpec.describe 'Plan', :reliable, :db_migrate, product_group: :project_management do describe 'Group milestone' do include Support::Dates diff --git a/qa/qa/specs/features/browser_ui/2_plan/pages/new_static_page_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/pages/new_static_page_spec.rb index 7368ca34683..919b4b2c46e 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/pages/new_static_page_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/pages/new_static_page_spec.rb @@ -30,9 +30,6 @@ module QA end before do - # Pages Menu Experiment currently progress https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98044 - # Update spec along with Feature Flag Removal. - Runtime::Feature.disable(:show_pages_in_deployments_menu) Flow::Login.sign_in Resource::ProjectRunner.fabricate_via_api! do |runner| runner.project = project @@ -41,10 +38,6 @@ module QA pipeline.visit! end - after do - Runtime::Feature.enable(:show_pages_in_deployments_menu) - end - it 'creates a Pages website', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do Page::Project::Pipeline::Show.perform do |show| @@ -57,7 +50,7 @@ module QA end Page::Project::Menu.perform(&:go_to_pages_settings) - Page::Project::Settings::Pages.perform(&:go_to_access_page) + Page::Project::Deployments::Pages.perform(&:go_to_access_page) Support::Waiter.wait_until( sleep_interval: 2, diff --git a/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb index a044bfa2054..bb411efc029 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb @@ -31,7 +31,7 @@ module QA edit.set_title(page_title) edit.use_new_editor edit.add_heading('Heading 1', heading_text) - edit.upload_image(File.join(Runtime::Path.fixtures_path, 'designs', image_file_name)) + edit.upload_image(Runtime::Path.fixture('designs', image_file_name)) end Page::Project::Wiki::Edit.perform(&:click_submit) 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 1e08fc49066..fcce6bb291c 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 @@ -46,7 +46,7 @@ module QA label = Resource::ProjectLabel.fabricate_via_api! do |label| label.project = project - label.title = 'label' + label.title = 'foo::label' end Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request| diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb index 7b89b021d89..297f91be0bb 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb @@ -15,7 +15,7 @@ module QA merge_request.title = 'Needs some suggestions' merge_request.description = '... so please add them.' merge_request.file_content = File.read( - File.join(Runtime::Path.fixtures_path, 'metrics_dashboards', 'templating.yml') + Runtime::Path.fixture('metrics_dashboards', 'templating.yml') ) end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb index 499d4c00384..ce32f4aadca 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb @@ -17,7 +17,7 @@ module QA merge_request.title = 'Needs some suggestions' merge_request.description = '... so please add them.' merge_request.file_content = File.read( - File.join(Runtime::Path.fixtures_path, 'metrics_dashboards', 'templating.yml') + Runtime::Path.fixture('metrics_dashboards', 'templating.yml') ) end end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb deleted file mode 100644 index 631b4ae099d..00000000000 --- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -# frozen_string_literal: true - -module QA - RSpec.describe 'Create' do - describe 'Create, list, and delete branches via web', :requires_admin, product_group: :source_code do - master_branch = nil - second_branch = 'second-branch' - third_branch = 'third-branch' - file_1_master = 'file.txt' - file_2_master = 'other-file.txt' - file_second_branch = 'file-2.txt' - file_third_branch = 'file-3.txt' - first_commit_message_of_master_branch = "Add #{file_1_master}" - second_commit_message_of_master_branch = "Add #{file_2_master}" - commit_message_of_second_branch = "Add #{file_second_branch}" - commit_message_of_third_branch = "Add #{file_third_branch}" - - before do - Flow::Login.sign_in - - project = Resource::Project.fabricate_via_api! do |proj| - proj.name = 'project-qa-test' - proj.description = 'project for qa test' - proj.initialize_with_readme = true - end - - master_branch = project.default_branch - - Git::Repository.perform do |repository| - repository.uri = project.repository_http_location.uri - repository.use_default_credentials - repository.try_add_credentials_to_netrc - repository.default_branch = master_branch - - repository.act do - clone - configure_identity('GitLab QA', 'root@gitlab.com') - commit_file(file_1_master, 'Test file content', first_commit_message_of_master_branch) - push_changes - checkout(second_branch, new_branch: true) - commit_file(file_second_branch, 'File 2 content', commit_message_of_second_branch) - push_changes(second_branch) - checkout(master_branch) - # This second commit on master is needed for the master branch to be ahead - # of the second branch, and when the second branch is merged to master it will - # show the 'merged' badge on it. - # Refer to the below issue note: - # https://gitlab.com/gitlab-org/gitlab-foss/issues/55524#note_126100848 - commit_file(file_2_master, 'Other test file content', second_commit_message_of_master_branch) - push_changes - merge(second_branch) - push_changes - checkout(third_branch, new_branch: true) - commit_file(file_third_branch, 'File 3 content', commit_message_of_third_branch) - push_changes(third_branch) - end - end - project.wait_for_push commit_message_of_third_branch - project.visit! - end - - it( - 'lists branches correctly after CRUD operations', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347740', - quarantine: { - issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/414026', - type: :stale - } - ) do - Page::Project::Menu.perform(&:go_to_repository_branches) - - expect(page).to have_content(master_branch) - expect(page).to have_content(second_branch) - expect(page).to have_content(third_branch) - expect(page).to have_content("Merge branch 'second-branch'") - expect(page).to have_content(commit_message_of_second_branch) - expect(page).to have_content(commit_message_of_third_branch) - - Page::Project::Branches::Show.perform do |branches_page| - expect(branches_page).to have_branch_with_badge(second_branch, 'merged') - - branches_page.delete_branch(third_branch) - - expect(branches_page).to have_no_branch(third_branch) - - branches_page.delete_merged_branches('delete') - - expect(branches_page).to have_content( - 'Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes.' - ) - - branches_page.refresh - - expect(branches_page).to have_no_branch(second_branch, reload: true) - end - end - end - end -end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb index 82074919ad4..1d9dccbddf6 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb @@ -2,11 +2,7 @@ module QA RSpec.describe 'Create' do - describe 'Branch Rules Overview', product_group: :source_code, - quarantine: { - issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/403583', - type: :flaky - } do + describe 'Branch Rules Overview', product_group: :source_code do let(:branch_name) { 'new-branch' } let(:allowed_to_push_role) { Resource::ProtectedBranch::Roles::NO_ONE } let(:allowed_to_merge_role) { Resource::ProtectedBranch::Roles::MAINTAINERS } diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb index 86a9f2c46fb..f00ef65fab4 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb @@ -11,7 +11,7 @@ module QA shared_examples 'project license detection' do it 'displays the name of the license on the repository' do - license_path = File.join(Runtime::Path.fixtures_path, 'software_licenses', license_file_name) + license_path = Runtime::Path.fixture('software_licenses', license_file_name) Resource::Repository::Commit.fabricate_via_api! do |commit| commit.project = project commit.add_files([{ file_path: 'LICENSE', content: File.read(license_path) }]) diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide_old/server_hooks_custom_error_message_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/server_hooks_custom_error_message_spec.rb index 99be95492e6..05925505610 100644 --- a/qa/qa/specs/features/browser_ui/3_create/web_ide_old/server_hooks_custom_error_message_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/server_hooks_custom_error_message_spec.rb @@ -8,7 +8,7 @@ module QA end describe 'Git Server Hooks' do - let(:file_path) { File.join(Runtime::Path.fixtures_path, 'web_ide', 'README.md') } + let(:file_path) { Runtime::Path.fixture('web_ide', 'README.md') } let(:project) do Resource::Project.fabricate_via_api! do |project| diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide_old/upload_new_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/upload_new_file_in_web_ide_spec.rb index f15f5b3a1d9..c557f2fa8a6 100644 --- a/qa/qa/specs/features/browser_ui/3_create/web_ide_old/upload_new_file_in_web_ide_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/web_ide_old/upload_new_file_in_web_ide_spec.rb @@ -8,8 +8,7 @@ module QA end describe 'Upload a file in Web IDE' do - let(:file_path) { File.join(Runtime::Path.fixtures_path, 'web_ide', file_name) } - + let(:file_path) { Runtime::Path.fixture('web_ide', file_name) } let(:project) do Resource::Project.fabricate_via_api! do |project| project.name = 'upload-file-project' diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb index f1a433984d8..41ce868f0d6 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb @@ -24,6 +24,10 @@ module QA project.visit! end + after do + runner.remove_via_api! + end + context 'when latest pipeline is successful' do before do add_ci_file(job_name: 'job_1', script: 'echo test') @@ -127,32 +131,41 @@ module QA def add_ci_file(job_name:, script:) ci_file = ci_file_with_job_artifact(job_name, script) + original_pipeline_count = pipeline_count Resource::Repository::Commit.fabricate_via_api! do |commit| commit.project = project commit.commit_message = "Set job #{job_name} script #{script}" commit.add_files([ci_file]) end + + wait_for_new_pipeline(original_pipeline_count) end def update_ci_file(job_name:, script:) ci_file = ci_file_with_job_artifact(job_name, script) + original_pipeline_count = pipeline_count Resource::Repository::Commit.fabricate_via_api! do |commit| commit.project = project commit.commit_message = "Set job #{job_name} script #{script}" commit.update_files([ci_file]) end + + wait_for_new_pipeline(original_pipeline_count) end def update_ci_with_manual_job(job_name:, script:) ci_file = ci_file_with_manual_job(job_name, script) + original_pipeline_count = pipeline_count Resource::Repository::Commit.fabricate_via_api! do |commit| commit.project = project commit.commit_message = "Set job #{job_name} script #{script}" commit.update_files([ci_file]) end + + wait_for_new_pipeline(original_pipeline_count) end def ci_file_with_job_artifact(job_name, script) @@ -199,6 +212,15 @@ module QA job.id = project.job_by_name(job_name)[:id] end end + + def pipeline_count + project.pipelines.length + end + + def wait_for_new_pipeline(original_pipeline_count) + QA::Runtime::Logger.info('Waiting for new pipeline to be created') + Support::Waiter.wait_until { pipeline_count > original_pipeline_count } + end end end end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb deleted file mode 100644 index a9f46e394f7..00000000000 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb +++ /dev/null @@ -1,118 +0,0 @@ -# frozen_string_literal: true - -module QA - RSpec.describe 'Verify' do - describe 'Pipeline editor', :reliable, product_group: :pipeline_authoring do - let(:project) do - Resource::Project.fabricate_via_api! do |project| - project.name = 'pipeline-editor-project' - end - end - - let!(:commit) do - 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 - stages: - - stage1 - - stage2 - - job1: - stage: stage1 - script: echo 'Done.' - - job2: - stage: stage2 - script: echo 'Done.' - YAML - } - ] - ) - end - end - - let(:invalid_content) do - <<~YAML - - job3: - stage: stage_foo - script: echo 'Done.' - YAML - end - - before do - # Make sure a pipeline is created before visiting pipeline editor page. - # Otherwise, test might timeout before the page finishing fetching pipeline status. - Support::Waiter.wait_until { project.pipelines.present? } - - Flow::Login.sign_in - project.visit! - Page::Project::Menu.perform(&:go_to_pipeline_editor) - end - - context 'when CI has valid syntax' do - it( - 'shows valid validations', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368332' - ) do - Page::Project::PipelineEditor::Show.perform do |show| - aggregate_failures do - expect(show.ci_syntax_validate_message).to have_content('Pipeline syntax is correct') - - show.go_to_visualize_tab - { stage1: 'job1', stage2: 'job2' }.each_pair do |stage, job| - expect(show).to have_stage(stage), "Pipeline graph does not have stage #{stage}." - expect(show).to have_job(job), "Pipeline graph does not have job #{job}." - end - - show.go_to_validate_tab - show.simulate_pipeline - expect(show.tab_alert_title).to have_content('Simulation completed successfully') - - show.go_to_full_configuration_tab - expect(show).to have_source_editor - end - end - end - end - - context 'when CI has invalid syntax' do - it( - 'shows invalid validations', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368333' - ) do - invalid_msg = 'syntax is invalid' - - Page::Project::PipelineEditor::Show.perform do |show| - show.write_to_editor(invalid_content) - - aggregate_failures do - show.go_to_visualize_tab - expect(show.tab_alert_message).to have_content(invalid_msg) - - show.go_to_validate_tab - show.simulate_pipeline - expect(show.tab_alert_title).to have_content('Pipeline simulation completed with errors') - - expect(show.ci_syntax_validate_message).to have_content('CI configuration is invalid') - - show.go_to_full_configuration_tab - - # TODO: remove page reload when - # https://gitlab.com/gitlab-org/gitlab/-/issues/378536 is resolved - expect { show.has_source_editor? } - .to eventually_be_truthy.within(max_attempts: 2, reload_page: show, sleep_interval: 1) - - expect(show.ci_syntax_validate_message).to have_content('CI configuration is invalid') - end - end - end - end - end - end -end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb index c693a57605e..1abe1df5964 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb @@ -112,7 +112,7 @@ module QA QA::Service::Shellout.shell("docker cp #{runner_name}:/etc/gitlab-runner/config.toml #{tempdir.path}") File.open(tempdir.path, 'a') do |f| - f << %Q[ allowed_pull_policies = #{allowed_policies}\n] + f << %[ allowed_pull_policies = #{allowed_policies}\n] end QA::Service::Shellout.shell("docker cp #{tempdir.path} #{runner_name}:/etc/gitlab-runner/config.toml") diff --git a/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb index 312c5a13a61..8dc9fb6db36 100644 --- a/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb @@ -1,8 +1,13 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', product_group: :package_registry do - describe 'Terraform Module Registry' do + RSpec.describe 'Package', :requires_admin, product_group: :package_registry do + describe 'Terraform Module Registry', + quarantine: { + only: { job: 'airgapped' }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/417407', + type: :investigating + } do include Runtime::Fixtures let(:group) { Resource::Group.fabricate_via_api! } @@ -25,6 +30,7 @@ module QA end before do + # Remove 'requires_admin' if below method is removed QA::Support::Helpers::ImportSource.enable('git') Flow::Login.sign_in diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb index 4179b65d930..83662e04fab 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' }, product_group: :package_registry, quarantine: { - only: { job: 'object_storage' }, - issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/335981', + RSpec.describe 'Package', :object_storage, product_group: :package_registry, quarantine: { + only: { job: %w[object_storage relative_url airgapped], condition: -> { QA::Support::FIPS.enabled? } }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/417584', type: :bug } do describe 'Conan Repository' do diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb index 19d0a4a816f..7bfda7f5956 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb @@ -1,8 +1,13 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' }, product_group: :package_registry do - describe 'Helm Registry' do + RSpec.describe 'Package', :object_storage, product_group: :package_registry do + describe 'Helm Registry', + quarantine: { + only: { job: %w[relative_url airgapped] }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/417590', + type: :investigating + } do using RSpec::Parameterized::TableSyntax include Runtime::Fixtures include Support::Helpers::MaskToken diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb index 3553e67eb2c..ce6c54b6ed8 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb @@ -1,8 +1,13 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' }, product_group: :package_registry do - describe 'Maven group level endpoint' do + RSpec.describe 'Package', :object_storage, product_group: :package_registry do + describe 'Maven group level endpoint', + quarantine: { + only: { job: %w[relative_url airgapped] }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/417600', + type: :investigating + } do include Runtime::Fixtures include Support::Helpers::MaskToken include_context 'packages registry qa scenario' diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb index 91d8f0dc181..35f80f8d447 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb @@ -1,7 +1,12 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' } do + RSpec.describe 'Package', :object_storage, + quarantine: { + only: { job: %w[relative_url airgapped] }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/417600', + type: :investigating + } do describe 'Maven project level endpoint', product_group: :package_registry do include Runtime::Fixtures include Support::Helpers::MaskToken diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb index 032c77b2519..f24466ed003 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb @@ -1,11 +1,16 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' }, product_group: :package_registry do + RSpec.describe 'Package', :object_storage, + quarantine: { + only: { job: 'relative_url', condition: -> { QA::Support::FIPS.enabled? } }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/417600', + type: :investigating + }, product_group: :package_registry do describe 'Maven Repository with Gradle' do using RSpec::Parameterized::TableSyntax include Runtime::Fixtures - include_context 'packages registry qa scenario' + include Support::Helpers::MaskToken let(:group_id) { 'com.gitlab.qa' } let(:artifact_id) { "maven_gradle-#{SecureRandom.hex(8)}" } @@ -13,6 +18,52 @@ module QA let(:package_version) { '1.3.7' } let(:package_type) { 'maven_gradle' } + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = "#{package_type}_project" + project.initialize_with_readme = true + project.visibility = :private + end + end + + let(:runner) do + Resource::ProjectRunner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.name}"] + runner.executor = :docker + runner.project = project + end + end + + let(:gitlab_address_with_port) do + uri = URI.parse(Runtime::Scenario.gitlab_address) + "#{uri.scheme}://#{uri.host}:#{uri.port}" + end + + let(:project_deploy_token) do + Resource::ProjectDeployToken.fabricate_via_api! do |deploy_token| + deploy_token.name = 'package-deploy-token' + deploy_token.project = project + deploy_token.scopes = %w[ + read_repository + read_package_registry + write_package_registry + ] + end + end + + let(:project_inbound_job_token_disabled) do + Resource::CICDSettings.fabricate_via_api! do |settings| + settings.project_path = project.full_path + settings.inbound_job_token_scope_enabled = false + end + end + + before do + Flow::Login.sign_in_unless_signed_in + runner + end + where(:case_name, :authentication_token_type, :maven_header_name, :testcase) do 'using personal access token' | :personal_access_token | 'Private-Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347601' 'using ci job token' | :ci_job_token | 'Job-Token' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347603' @@ -23,38 +74,47 @@ module QA let(:token) do case authentication_token_type when :personal_access_token - "\"#{personal_access_token}\"" + use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: Runtime::Env.personal_access_token, project: project) when :ci_job_token - package_project_inbound_job_token_disabled - client_project_inbound_job_token_disabled - 'System.getenv("CI_JOB_TOKEN")' + project_inbound_job_token_disabled + '${CI_JOB_TOKEN}' when :project_deploy_token - "\"#{project_deploy_token.token}\"" + use_ci_variable(name: 'PROJECT_DEPLOY_TOKEN', value: project_deploy_token.token, project: project) end end it 'pushes and pulls a maven package via gradle', testcase: params[:testcase] do Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do Resource::Repository::Commit.fabricate_via_api! do |commit| - gradle_upload_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_upload_package.yaml.erb')).result(binding) - build_upload_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build_upload.gradle.erb')).result(binding) + gradle_publish_install_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_upload_install_package.yaml.erb')).result(binding) + build_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build.gradle.erb')).result(binding) - commit.project = package_project + commit.project = project commit.commit_message = 'Add .gitlab-ci.yml' commit.add_files( [ - { file_path: '.gitlab-ci.yml', content: gradle_upload_yaml }, - { file_path: 'build.gradle', content: build_upload_gradle } + { file_path: '.gitlab-ci.yml', content: gradle_publish_install_yaml }, + { file_path: 'build.gradle', content: build_gradle } ]) end end - package_project.visit! + project.visit! Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform do |pipeline| - pipeline.click_job('deploy') + pipeline.click_job('publish') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + + job.click_element(:pipeline_path) + end + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('install') end Page::Project::Job::Show.perform do |job| @@ -72,33 +132,6 @@ module QA Page::Project::Packages::Show.perform do |show| expect(show).to have_package_info(package_name, package_version) end - - Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do - Resource::Repository::Commit.fabricate_via_api! do |commit| - gradle_install_yaml = ERB.new(read_fixture('package_managers/maven/gradle', 'gradle_install_package.yaml.erb')).result(binding) - build_install_gradle = ERB.new(read_fixture('package_managers/maven/gradle', 'build_install.gradle.erb')).result(binding) - - commit.project = client_project - commit.commit_message = 'Add files' - commit.add_files( - [ - { file_path: '.gitlab-ci.yml', content: gradle_install_yaml }, - { file_path: 'build.gradle', content: build_install_gradle } - ]) - end - end - - client_project.visit! - - Flow::Pipeline.visit_latest_pipeline - - Page::Project::Pipeline::Show.perform do |pipeline| - pipeline.click_job('build') - end - - Page::Project::Job::Show.perform do |job| - expect(job).to be_successful(timeout: 800) - end end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb index 63549113517..7e2885d3724 100644 --- a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb @@ -1,8 +1,13 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :object_storage, except: { job: 'relative-url' }, product_group: :package_registry do - describe 'PyPI Repository' do + RSpec.describe 'Package', :object_storage, product_group: :package_registry do + describe 'PyPI Repository', + quarantine: { + only: { job: %w[relative_url airgapped] }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/417592', + type: :investigating + } do include Runtime::Fixtures include Support::Helpers::MaskToken @@ -30,7 +35,11 @@ module QA end let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) } - let(:personal_access_token) { use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: Runtime::Env.personal_access_token, project: project) } + + let!(:personal_access_token) do + use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: Runtime::Env.personal_access_token, project: project) + end + let(:gitlab_address_with_port) { "#{uri.scheme}://#{uri.host}:#{uri.port}" } let(:gitlab_host_with_port) do # Don't specify port if it is a standard one diff --git a/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb b/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb index 5ae90d20351..55ed9abb0da 100644 --- a/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb +++ b/qa/qa/specs/features/shared_contexts/import/github_import_shared_context.rb @@ -48,7 +48,7 @@ module QA ) end - let(:mocks_path) { File.join(Runtime::Path.fixtures_path, "mocks", "import") } + let(:mocks_path) { Runtime::Path.fixture("mocks", "import") } before do set_mocks diff --git a/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb b/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb index bfd0825cf91..e702da4ad5b 100644 --- a/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb +++ b/qa/qa/specs/features/shared_contexts/import/gitlab_group_migration_common.rb @@ -32,7 +32,7 @@ module QA Resource::Sandbox.fabricate_via_api! do |group| group.api_client = source_admin_api_client group.path = "source-group-for-import-#{SecureRandom.hex(4)}" - group.avatar = File.new(File.join(Runtime::Path.fixtures_path, 'designs', 'tanuki.jpg'), "r") + group.avatar = File.new(Runtime::Path.fixture('designs', 'tanuki.jpg'), "r") end end diff --git a/qa/qa/support/formatters/allure_metadata_formatter.rb b/qa/qa/support/formatters/allure_metadata_formatter.rb index eac74a3b961..3f7ec9f62b9 100644 --- a/qa/qa/support/formatters/allure_metadata_formatter.rb +++ b/qa/qa/support/formatters/allure_metadata_formatter.rb @@ -98,7 +98,6 @@ module QA return unless flaky_specs.key?(example.metadata[:testcase]) && example.execution_result.status != :pending example.set_flaky - example.parameter("pass_rate", "#{flaky_specs[example.metadata[:testcase]].round(0)}%") log(:debug, "Setting spec as flaky because it's pass rate is below 98%") rescue StandardError => e log(:error, "Failed to add spec pass rate data for example '#{example.description}', error: #{e}") diff --git a/qa/qa/support/formatters/test_metrics_formatter.rb b/qa/qa/support/formatters/test_metrics_formatter.rb index 6e6cdc35af5..cdc0e83dc02 100644 --- a/qa/qa/support/formatters/test_metrics_formatter.rb +++ b/qa/qa/support/formatters/test_metrics_formatter.rb @@ -35,7 +35,7 @@ module QA # @param [Array<RSpec::Core::Example>] examples # @return [Array<Hash>] def execution_data(examples = nil) - @execution_metrics ||= examples.map { |example| test_stats(example) }.compact + @execution_metrics ||= examples.filter_map { |example| test_stats(example) } end alias_method :parse_execution_data, :execution_data @@ -171,11 +171,7 @@ module QA # # @return [Time] def time - @time ||= begin - return Time.now unless env('CI_PIPELINE_CREATED_AT') - - env('CI_PIPELINE_CREATED_AT').to_time - end + @time ||= env('CI_PIPELINE_CREATED_AT')&.to_time || Time.now end # Is a merge request execution diff --git a/qa/qa/support/helpers/mask_token.rb b/qa/qa/support/helpers/mask_token.rb index 3aea77779ad..928d24ec404 100644 --- a/qa/qa/support/helpers/mask_token.rb +++ b/qa/qa/support/helpers/mask_token.rb @@ -9,6 +9,7 @@ module QA ci_variable.project = project ci_variable.key = name ci_variable.value = value + ci_variable.masked = true end "${#{name}}" end @@ -18,6 +19,7 @@ module QA ci_variable.group = group ci_variable.key = name ci_variable.value = value + ci_variable.masked = true end "${#{name}}" end diff --git a/qa/qa/support/influxdb_tools.rb b/qa/qa/support/influxdb_tools.rb index efdbe1cd129..e8f73540733 100644 --- a/qa/qa/support/influxdb_tools.rb +++ b/qa/qa/support/influxdb_tools.rb @@ -48,20 +48,21 @@ module QA # # @return [String, nil] def run_type - @run_type ||= begin - return env('QA_RUN_TYPE') if env('QA_RUN_TYPE') - return unless LIVE_ENVS.include?(ci_project_name) + @run_type ||= if env('QA_RUN_TYPE') + env('QA_RUN_TYPE') + elsif LIVE_ENVS.exclude?(ci_project_name) + nil + else + test_subset = if env('NO_ADMIN') == 'true' + 'sanity-no-admin' + elsif env('SMOKE_ONLY') == 'true' + 'sanity' + else + 'full' + end - test_subset = if env('NO_ADMIN') == 'true' - 'sanity-no-admin' - elsif env('SMOKE_ONLY') == 'true' - 'sanity' - else - 'full' - end - - "#{ci_project_name}-#{test_subset}" - end + "#{ci_project_name}-#{test_subset}" + end end # Merge request iid diff --git a/qa/qa/support/matchers/have_matcher.rb b/qa/qa/support/matchers/have_matcher.rb index a9b365f7e81..c77b585ada8 100644 --- a/qa/qa/support/matchers/have_matcher.rb +++ b/qa/qa/support/matchers/have_matcher.rb @@ -8,6 +8,7 @@ module QA auto_devops_container element file_content + file_name assignee child_pipeline linked_pipeline diff --git a/qa/qa/support/parallel_pipeline_jobs.rb b/qa/qa/support/parallel_pipeline_jobs.rb index a551bf9978b..7984412685d 100644 --- a/qa/qa/support/parallel_pipeline_jobs.rb +++ b/qa/qa/support/parallel_pipeline_jobs.rb @@ -7,7 +7,7 @@ module QA class ParallelPipelineJobs include API - PARALLEL_JOB_NAME_PATTERN = %r{^\S+ \d+/\d+$}.freeze + PARALLEL_JOB_NAME_PATTERN = %r{^\S+ \d+/\d+$} def initialize(stage_name:, project_id:, pipeline_id:, access_token:) @stage_name = stage_name diff --git a/qa/qa/support/wait_for_requests.rb b/qa/qa/support/wait_for_requests.rb index ef7875eb838..2856602629a 100644 --- a/qa/qa/support/wait_for_requests.rb +++ b/qa/qa/support/wait_for_requests.rb @@ -39,12 +39,6 @@ module QA Capybara.page.has_no_css?('.gl-spinner', wait: wait) end end - - def wait_for_gitlab_to_respond - Waiter.wait_until(sleep_interval: 5, message: '502 - GitLab is taking too much time to respond') do - Capybara.page.has_no_text?('GitLab is taking too much time to respond') - end - end end end end diff --git a/qa/qa/tools/ci/qa_changes.rb b/qa/qa/tools/ci/qa_changes.rb index 1ab93b6dfbf..1e3ef9e4816 100644 --- a/qa/qa/tools/ci/qa_changes.rb +++ b/qa/qa/tools/ci/qa_changes.rb @@ -9,8 +9,8 @@ module QA class QaChanges include Helpers - QA_PATTERN = %r{^qa/}.freeze - SPEC_PATTERN = %r{^qa/qa/specs/features/\S+_spec\.rb}.freeze + QA_PATTERN = %r{^qa/} + SPEC_PATTERN = %r{^qa/qa/specs/features/\S+_spec\.rb} DEPENDENCY_PATTERN = Regexp.union( /_VERSION/, /Gemfile\.lock/, diff --git a/qa/qa/tools/test_resources_handler.rb b/qa/qa/tools/test_resources_handler.rb index fd76cc3d1a8..5a56f4a62c7 100644 --- a/qa/qa/tools/test_resources_handler.rb +++ b/qa/qa/tools/test_resources_handler.rb @@ -38,6 +38,7 @@ module QA QA::EE::Resource::VulnerabilityItem QA::EE::Resource::ScanResultPolicyProject QA::EE::Resource::ScanResultPolicyCommit + QA::EE::Resource::InstanceAuditEventExternalDestination ].freeze PROJECT = 'gitlab-qa-resources' diff --git a/qa/qa/vendor/facebook/page/login.rb b/qa/qa/vendor/facebook/page/login.rb new file mode 100644 index 00000000000..99e79d2e5a4 --- /dev/null +++ b/qa/qa/vendor/facebook/page/login.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + module Vendor + module Facebook + module Page + class Login < Vendor::Page::Base + def login + fill_in 'email', with: QA::Runtime::Env.facebook_username + fill_in 'pass', with: QA::Runtime::Env.facebook_password + find('#loginbutton').click + + confirm_oauth_access + end + + def confirm_oauth_access + first('span', text: 'Continue as').click if has_css?('span', text: 'Continue as') + end + end + end + end + end +end diff --git a/qa/qa/vendor/github/page/base.rb b/qa/qa/vendor/github/page/base.rb deleted file mode 100644 index 3b96180afe9..00000000000 --- a/qa/qa/vendor/github/page/base.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -module QA - module Vendor - module Github - module Page - class Base - include Capybara::DSL - include Scenario::Actable - end - end - end - end -end diff --git a/qa/qa/vendor/github/page/login.rb b/qa/qa/vendor/github/page/login.rb index 17a7471e251..ce71fc5f11e 100644 --- a/qa/qa/vendor/github/page/login.rb +++ b/qa/qa/vendor/github/page/login.rb @@ -1,13 +1,10 @@ # frozen_string_literal: true -require 'capybara/dsl' -require 'benchmark' - module QA module Vendor module Github module Page - class Login < Page::Base + class Login < Vendor::Page::Base def login fill_in 'login', with: QA::Runtime::Env.github_username fill_in 'password', with: QA::Runtime::Env.github_password @@ -24,11 +21,17 @@ module QA end authorize_app + + confirm_account_recovery_settings end def authorize_app click_on 'Authorize' if has_button?('Authorize') end + + def confirm_account_recovery_settings + click_on 'Confirm' if has_button?('Confirm') + end end end end diff --git a/qa/qa/vendor/page/base.rb b/qa/qa/vendor/page/base.rb new file mode 100644 index 00000000000..1cfba6bfdda --- /dev/null +++ b/qa/qa/vendor/page/base.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'capybara/dsl' + +module QA + module Vendor + module Page + class Base + include Capybara::DSL + include Scenario::Actable + end + end + end +end diff --git a/qa/qa/vendor/saml_idp/page/base.rb b/qa/qa/vendor/saml_idp/page/base.rb deleted file mode 100644 index 39413a64d5a..00000000000 --- a/qa/qa/vendor/saml_idp/page/base.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -module QA - module Vendor - module SamlIdp - module Page - class Base - include Capybara::DSL - include Scenario::Actable - end - end - end - end -end diff --git a/qa/qa/vendor/saml_idp/page/login.rb b/qa/qa/vendor/saml_idp/page/login.rb index dc6925109f7..9b4fbe15366 100644 --- a/qa/qa/vendor/saml_idp/page/login.rb +++ b/qa/qa/vendor/saml_idp/page/login.rb @@ -1,18 +1,22 @@ # frozen_string_literal: true -require 'capybara/dsl' - module QA module Vendor module SamlIdp module Page - class Login < Page::Base + class Login < Vendor::Page::Base def login(username, password) QA::Runtime::Logger.debug("Logging into SAMLIdp with username: #{username} and password:#{password}") fill_in 'username', with: username fill_in 'password', with: password click_on 'Login' + + if Runtime::Env.super_sidebar_enabled? + QA::Page::Main::Menu.perform(&:enable_new_navigation) + else + QA::Page::Main::Menu.perform(&:disable_new_navigation) + end end def login_if_required(username, password) diff --git a/qa/qa/vendor/smocker/smocker_api.rb b/qa/qa/vendor/smocker/smocker_api.rb index 0434b5dcea4..4bad41f98bd 100644 --- a/qa/qa/vendor/smocker/smocker_api.rb +++ b/qa/qa/vendor/smocker/smocker_api.rb @@ -44,7 +44,7 @@ module QA # # @param wait [Integer] wait duration for smocker readiness def wait_for_ready(wait: 10) - Support::Waiter.wait_until(max_duration: wait, reload_page: false, raise_on_failure: true) do + Support::Waiter.wait_until(max_duration: wait, sleep_interval: 1, log: false) do ready? end end diff --git a/qa/spec/runtime/feature_spec.rb b/qa/spec/runtime/feature_spec.rb index 72ba915d99b..351856de1bd 100644 --- a/qa/spec/runtime/feature_spec.rb +++ b/qa/spec/runtime/feature_spec.rb @@ -59,7 +59,7 @@ RSpec.describe QA::Runtime::Feature do .and_return(request) expect(described_class) .to receive(:get) - .and_return(Struct.new(:code, :body).new(200, %Q([{ "name": "a_flag", "state": "conditional", "gates": #{gates} }]))) + .and_return(Struct.new(:code, :body).new(200, %([{ "name": "a_flag", "state": "conditional", "gates": #{gates} }]))) expect(described_class.enabled?(feature_flag, scope => actor)).to be true end diff --git a/qa/spec/service/docker_run/video_spec.rb b/qa/spec/service/docker_run/video_spec.rb index 81be5ccffae..d8d7f680629 100644 --- a/qa/spec/service/docker_run/video_spec.rb +++ b/qa/spec/service/docker_run/video_spec.rb @@ -4,7 +4,7 @@ module QA RSpec.describe Service::DockerRun::Video do include QA::Support::Helpers::StubEnv - let(:rspec_config) { instance_double('RSpec::Core::Configuration', append_after: nil, prepend_before: nil) } + let(:rspec_config) { instance_double('RSpec::Core::Configuration', prepend_before: nil, prepend_after: nil) } let(:video_recorder_image) { 'presidenten/selenoid-manual-video-recorder' } let(:video_recorder_version) { 'latest' } let(:selenoid_browser_image) { 'selenoid/chrome' } @@ -12,6 +12,7 @@ module QA let(:remote_grid) { 'selenoid:4444' } let(:record_video) { 'true' } let(:use_selenoid) { 'true' } + let(:allure_report) { 'false' } let(:docs_link) do 'https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/running_against_remote_grid.md#testing-with-selenoid' end @@ -55,6 +56,7 @@ module QA stub_env('QA_REMOTE_GRID', remote_grid) stub_env('USE_SELENOID', use_selenoid) stub_env('QA_RECORD_VIDEO', record_video) + stub_env('QA_GENERATE_ALLURE_REPORT', allure_report) allow(RSpec).to receive(:configure).and_yield(rspec_config) allow(described_class).to receive(:get_container_name) @@ -173,7 +175,29 @@ module QA .with(/Test failure video recording setup complete!/) expect(RSpec).to have_received(:configure) expect(rspec_config).to have_received(:prepend_before) - expect(rspec_config).to have_received(:append_after) + expect(rspec_config).to have_received(:prepend_after) + end + end + + context 'with generate_allure_report' do + let(:rspec_config) do + instance_double('RSpec::Core::Configuration', + prepend_before: nil, + prepend_after: nil, + append_after: nil) + end + + let(:allure_report) { 'true' } + + it 'performs configuration with allure report' do + aggregate_failures do + expect(QA::Runtime::Logger).to have_received(:info) + .with(/Test failure video recording setup complete!/) + expect(RSpec).to have_received(:configure).twice + expect(rspec_config).to have_received(:prepend_before) + expect(rspec_config).to have_received(:prepend_after) + expect(rspec_config).to have_received(:append_after) + end end end end diff --git a/qa/spec/support/formatters/allure_metadata_formatter_spec.rb b/qa/spec/support/formatters/allure_metadata_formatter_spec.rb index ab3b753c3b0..b80c3f125e9 100644 --- a/qa/spec/support/formatters/allure_metadata_formatter_spec.rb +++ b/qa/spec/support/formatters/allure_metadata_formatter_spec.rb @@ -75,16 +75,6 @@ describe QA::Support::Formatters::AllureMetadataFormatter do allow(InfluxDB2::Client).to receive(:new) { influx_client } end - context 'with non skipped spec' do - it 'adds flaky test data' do - formatter.start(nil) - formatter.example_finished(rspec_example_notification) - - expect(rspec_example).to have_received(:set_flaky) - expect(rspec_example).to have_received(:parameter).with('pass_rate', '50%') - end - end - context 'with skipped spec' do let(:status) { :pending } |