diff options
Diffstat (limited to 'qa')
88 files changed, 1324 insertions, 461 deletions
diff --git a/qa/.gitignore b/qa/.gitignore index 2095d5c722c..b54b8666e28 100644 --- a/qa/.gitignore +++ b/qa/.gitignore @@ -3,3 +3,4 @@ tmp/ .tool-versions .ruby-gemset urls.yml +reports/ diff --git a/qa/Dockerfile b/qa/Dockerfile index dda882dc5e6..81f207cbab9 100644 --- a/qa/Dockerfile +++ b/qa/Dockerfile @@ -38,6 +38,18 @@ RUN unzip chromedriver_linux64.zip -d /usr/local/bin RUN rm -f chromedriver_linux64.zip ## +# Install client certificate - Bug in Chrome Headless: https://gitlab.com/gitlab-org/gitlab/-/issues/331492 +# +# RUN apt install -y libnss3-tools +# RUN mkdir -p $HOME/.pki/nssdb +# RUN certutil -N -d sql:$HOME/.pki/nssdb +# COPY ./qa/tls_certificates/client/client.pfx /tmp/client.pfx +# RUN pk12util -d sql:$HOME/.pki/nssdb -i /tmp/client.pfx -W '' +# RUN mkdir -p /etc/opt/chrome/policies/managed +# RUN echo '{ "AutoSelectCertificateForUrls": ["{\"pattern\":\"*\",\"filter\":{}}"] }' > /etc/opt/chrome/policies/managed/policy.json +# RUN cat /etc/opt/chrome/policies/managed/policy.json + +## # Install root certificate # RUN mkdir -p /usr/share/ca-certificates/gitlab diff --git a/qa/Gemfile b/qa/Gemfile index 8b3a9802000..0cb53ca99dc 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -3,7 +3,8 @@ source 'https://rubygems.org' gem 'gitlab-qa' -gem 'activesupport', '~> 6.0.3.3' # This should stay in sync with the root's Gemfile +gem 'activesupport', '~> 6.1.3.2' # This should stay in sync with the root's Gemfile +gem 'allure-rspec', '~> 2.14.1' gem 'capybara', '~> 3.29.0' gem 'capybara-screenshot', '~> 1.0.23' gem 'rake', '~> 12.3.3' diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 9bac86bad08..8b6c4ca0d3e 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -2,12 +2,12 @@ GEM remote: https://rubygems.org/ specs: abstract_type (0.0.7) - activesupport (6.0.3.4) + activesupport (6.1.3.2) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) adamantium (0.2.0) ice_nine (~> 0.11.0) memoizable (~> 0.4.0) @@ -19,6 +19,14 @@ GEM rack-test (>= 1.1.0, < 2.0) rest-client (>= 2.0.2, < 3.0) rspec (~> 3.8) + allure-rspec (2.14.1) + allure-ruby-commons (= 2.14.1) + rspec-core (>= 3.8, < 4) + allure-ruby-commons (2.14.1) + mime-types (>= 3.3, < 4) + oj (>= 3.10, < 4) + require_all (>= 2, < 4) + uuid (>= 2.3, < 3) ast (2.4.1) binding_ninja (0.2.3) byebug (9.1.0) @@ -44,7 +52,7 @@ GEM concord (0.1.5) adamantium (~> 0.2.0) equalizer (~> 0.0.9) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.8) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) diff-lcs (1.3) @@ -66,7 +74,7 @@ GEM http-accept (1.7.0) http-cookie (1.0.3) domain_name (~> 0.5) - i18n (1.8.5) + i18n (1.8.10) concurrent-ruby (~> 1.0) ice_nine (0.11.2) jwt (2.2.2) @@ -74,6 +82,8 @@ GEM rake launchy (2.4.3) addressable (~> 2.3) + macaddr (1.7.2) + systemu (~> 2.6.5) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) method_source (0.9.0) @@ -82,7 +92,7 @@ GEM mime-types-data (3.2020.0425) mini_mime (1.0.2) mini_portile2 (2.5.0) - minitest (5.14.2) + minitest (5.14.4) multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.1.1) @@ -96,6 +106,7 @@ GEM multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) + oj (3.11.5) parallel (1.19.2) parallel_tests (2.29.0) parallel @@ -119,6 +130,7 @@ GEM rack (>= 1.0, < 3) rake (12.3.3) regexp_parser (1.6.0) + require_all (3.0.0) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) @@ -154,10 +166,11 @@ GEM selenium-webdriver (3.142.6) childprocess (>= 0.5, < 4.0) rubyzip (>= 1.2.2) + systemu (2.6.5) thread_safe (0.3.6) timecop (0.9.1) - tzinfo (1.2.9) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) unf (0.1.4) unf_ext unf_ext (0.0.7.7) @@ -169,6 +182,8 @@ GEM equalizer (~> 0.0.9) parser (>= 2.6.5) procto (~> 0.0.2) + uuid (2.3.9) + macaddr (~> 1.0) watir (6.18.0) regexp_parser (>= 1.2, < 3) selenium-webdriver (>= 3.8) @@ -180,8 +195,9 @@ PLATFORMS ruby DEPENDENCIES - activesupport (~> 6.0.3.3) + activesupport (~> 6.1.3.2) airborne (~> 0.3.4) + allure-rspec (~> 2.14.1) capybara (~> 3.29.0) capybara-screenshot (~> 1.0.23) chemlab (~> 0.5) @@ -45,6 +45,7 @@ module QA autoload :IPAddress, 'qa/runtime/ip_address' autoload :Search, 'qa/runtime/search' autoload :ApplicationSettings, 'qa/runtime/application_settings' + autoload :AllureReport, 'qa/runtime/allure_report' module API autoload :Client, 'qa/runtime/api/client' @@ -73,7 +74,9 @@ module QA autoload :Issue, 'qa/resource/issue' autoload :ProjectIssueNote, 'qa/resource/project_issue_note' autoload :Project, 'qa/resource/project' - autoload :Label, 'qa/resource/label' + autoload :LabelBase, 'qa/resource/label_base' + autoload :ProjectLabel, 'qa/resource/project_label' + autoload :GroupLabel, 'qa/resource/group_label' autoload :MergeRequest, 'qa/resource/merge_request' autoload :ProjectImportedFromGithub, 'qa/resource/project_imported_from_github' autoload :MergeRequestFromFork, 'qa/resource/merge_request_from_fork' @@ -335,8 +338,8 @@ module QA autoload :Jenkins, 'qa/page/project/settings/services/jenkins' autoload :Prometheus, 'qa/page/project/settings/services/prometheus' end - autoload :Operations, 'qa/page/project/settings/operations' - autoload :Incidents, 'qa/page/project/settings/incidents' + autoload :Monitor, 'qa/page/project/settings/monitor' + autoload :Alerts, 'qa/page/project/settings/alerts' autoload :Integrations, 'qa/page/project/settings/integrations' end @@ -344,7 +347,9 @@ module QA autoload :CiCd, 'qa/page/project/sub_menus/ci_cd' autoload :Common, 'qa/page/project/sub_menus/common' autoload :Issues, 'qa/page/project/sub_menus/issues' - autoload :Operations, 'qa/page/project/sub_menus/operations' + autoload :Monitor, 'qa/page/project/sub_menus/monitor' + autoload :Deployments, 'qa/page/project/sub_menus/deployments' + autoload :Infrastructure, 'qa/page/project/sub_menus/infrastructure' autoload :Repository, 'qa/page/project/sub_menus/repository' autoload :Settings, 'qa/page/project/sub_menus/settings' autoload :Project, 'qa/page/project/sub_menus/project' @@ -367,25 +372,29 @@ module QA autoload :Index, 'qa/page/project/milestone/index' end - module Operations + module Deployments module Environments - autoload :Index, 'qa/page/project/operations/environments/index' - autoload :Show, 'qa/page/project/operations/environments/show' + autoload :Index, 'qa/page/project/deployments/environments/index' + autoload :Show, 'qa/page/project/deployments/environments/show' end + end + module Infrastructure module Kubernetes - autoload :Index, 'qa/page/project/operations/kubernetes/index' - autoload :Add, 'qa/page/project/operations/kubernetes/add' - autoload :AddExisting, 'qa/page/project/operations/kubernetes/add_existing' - autoload :Show, 'qa/page/project/operations/kubernetes/show' + autoload :Index, 'qa/page/project/infrastructure/kubernetes/index' + autoload :Add, 'qa/page/project/infrastructure/kubernetes/add' + autoload :AddExisting, 'qa/page/project/infrastructure/kubernetes/add_existing' + autoload :Show, 'qa/page/project/infrastructure/kubernetes/show' end + end + module Monitor module Metrics - autoload :Show, 'qa/page/project/operations/metrics/show' + autoload :Show, 'qa/page/project/monitor/metrics/show' end module Incidents - autoload :Index, 'qa/page/project/operations/incidents/index' + autoload :Index, 'qa/page/project/monitor/incidents/index' end end diff --git a/qa/qa/flow/user.rb b/qa/qa/flow/user.rb index acc77cb9830..c0bd475adb7 100644 --- a/qa/qa/flow/user.rb +++ b/qa/qa/flow/user.rb @@ -9,13 +9,13 @@ module QA Capybara.current_session end - def confirm_user(username) + def confirm_user(user) Flow::Login.while_signed_in_as_admin do Page::Main::Menu.perform(&:go_to_admin_area) Page::Admin::Menu.perform(&:go_to_users_overview) Page::Admin::Overview::Users::Index.perform do |index| - index.search_user(username) - index.click_user(username) + index.search_user(user.email) + index.click_user(user.name) end Page::Admin::Overview::Users::Show.perform(&:confirm_user) diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb index f8c79b4f72c..8a2c2303ff7 100644 --- a/qa/qa/page/admin/overview/users/index.rb +++ b/qa/qa/page/admin/overview/users/index.rb @@ -11,7 +11,7 @@ module QA element :pending_approval_tab end - view 'app/views/admin/users/_user.html.haml' do + view 'app/assets/javascripts/admin/users/components/users_table.vue' do element :user_row_content end diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb index 03c0811645f..3a9d316c321 100644 --- a/qa/qa/page/component/issuable/sidebar.rb +++ b/qa/qa/page/component/issuable/sidebar.rb @@ -30,7 +30,7 @@ module QA element :labels_dropdown_content end - base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue' do + base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue' do element :labels_edit_button end @@ -65,13 +65,13 @@ module QA def has_assignee?(username) within_element(:assignee_block) do - has_text?(username, wait: 120) + has_text?(username, wait: 1) end end def has_no_assignee?(username) within_element(:assignee_block) do - has_no_text?(username, wait: 120) + has_no_text?(username, wait: 1) end end diff --git a/qa/qa/page/component/issue_board/show.rb b/qa/qa/page/component/issue_board/show.rb index e0c8f73e1b0..1c1f7ab17f3 100644 --- a/qa/qa/page/component/issue_board/show.rb +++ b/qa/qa/page/component/issue_board/show.rb @@ -24,11 +24,11 @@ module QA element :create_new_board_button end - view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue' do + view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue' do element :labels_dropdown_content end - view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue' do + view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue' do element :labels_edit_button end diff --git a/qa/qa/page/dashboard/snippet/index.rb b/qa/qa/page/dashboard/snippet/index.rb index 63589c376f6..d8314509b1f 100644 --- a/qa/qa/page/dashboard/snippet/index.rb +++ b/qa/qa/page/dashboard/snippet/index.rb @@ -7,6 +7,9 @@ module QA class Index < Page::Base view 'app/views/layouts/header/_new_dropdown.html.haml' do element :new_menu_toggle + end + + view 'app/helpers/nav/new_dropdown_helper.rb' do element :global_new_snippet_link end diff --git a/qa/qa/page/group/members.rb b/qa/qa/page/group/members.rb index 68a169d5a7f..b526a4488b2 100644 --- a/qa/qa/page/group/members.rb +++ b/qa/qa/page/group/members.rb @@ -26,7 +26,7 @@ module QA element :delete_member_button end - view 'app/views/groups/group_members/index.html.haml' do + view 'app/assets/javascripts/members/components/members_tabs.vue' do element :groups_list_tab end diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb index 66e8b5d5863..9a3b129b6d2 100644 --- a/qa/qa/page/group/menu.rb +++ b/qa/qa/page/group/menu.rb @@ -12,6 +12,8 @@ module QA element :group_members_item element :group_milestones_link element :group_settings + element :group_information_link + element :group_information_submenu end view 'app/views/groups/sidebar/_packages_settings.html.haml' do @@ -24,8 +26,10 @@ module QA end def click_group_members_item - within_sidebar do - click_element(:group_members_item) + hover_element(:group_information_link) do + within_submenu(:group_information_submenu) do + click_element(:group_members_item) + end end end diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb index 5a908266597..66afcf7547c 100644 --- a/qa/qa/page/group/new.rb +++ b/qa/qa/page/group/new.rb @@ -38,17 +38,32 @@ module QA fill_element(:import_gitlab_token, token) end + def click_import_group + click_on 'Import group' + end + + def click_create_group + click_on 'Create group' + end + # Connect gitlab instance # # @param [String] gitlab_url # @param [String] gitlab_token # @return [void] def connect_gitlab_instance(gitlab_url, gitlab_token) + # Wait until element is present and refresh if not in case feature flag did not kick in + wait_until(max_duration: 10) { has_element?(:import_gitlab_url, wait: 1) } + set_gitlab_url(gitlab_url) set_gitlab_token(gitlab_token) click_element(:connect_instance_button) end + + def switch_to_import_tab + click_element("import-group-pane_link") + end end end end diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb index f796f4c9475..760741a9630 100644 --- a/qa/qa/page/main/menu.rb +++ b/qa/qa/page/main/menu.rb @@ -19,25 +19,23 @@ module QA element :todos_shortcut_button, required: true end - view 'app/views/layouts/nav/_dashboard.html.haml' do - element :admin_area_link - element :projects_dropdown, required: true - element :groups_dropdown, required: true - element :more_dropdown - element :snippets_link - element :groups_link - element :activity_link - element :milestones_link + view 'app/assets/javascripts/nav/components/top_nav_app.vue' do + element :navbar_dropdown + end + + view 'app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue' do + element :menu_subview_container end - view 'app/views/layouts/nav/projects_dropdown/_show.html.haml' do - element :projects_dropdown_sidebar - element :your_projects_link + view 'lib/gitlab/nav/top_nav_menu_item.rb' do + element :menu_item_link end - view 'app/views/layouts/nav/groups_dropdown/_show.html.haml' do - element :create_group_link - element :import_group_link + view 'app/helpers/nav/top_nav_helper.rb' do + element :admin_area_link + element :projects_dropdown + element :groups_dropdown + element :snippets_link end view 'app/views/layouts/_search.html.haml' do @@ -46,30 +44,32 @@ module QA def go_to_groups within_groups_menu do - click_element :your_groups_link + click_element(:menu_item_link, title: 'Your groups') end end - def go_to_import_group + def go_to_create_group within_groups_menu do - click_element :import_group_link + click_element(:menu_item_link, title: 'Create group') end end def go_to_projects - within_top_menu do - click_element :projects_dropdown + within_projects_menu do + click_element(:menu_item_link, title: 'Your projects') end + end - page.within('.qa-projects-dropdown-sidebar') do - click_element :your_projects_link + def go_to_create_project + within_projects_menu do + click_element(:menu_item_link, title: 'Create new project') end end - def go_to_more_dropdown_option(option_name) + def go_to_menu_dropdown_option(option_name) within_top_menu do - click_element :more_dropdown - click_element option_name + click_element(:navbar_dropdown, title: 'Menu') + click_element(option_name) end end @@ -88,11 +88,11 @@ module QA def go_to_admin_area click_admin_area - if has_text?('Enter Admin Mode', wait: 1.0) - Admin::NewSession.perform do |new_session| - new_session.set_password(Runtime::User.admin_password) - new_session.click_enter_admin_mode - end + return unless has_text?('Enter Admin Mode', wait: 1.0) + + Admin::NewSession.perform do |new_session| + new_session.set_password(Runtime::User.admin_password) + new_session.click_enter_admin_mode end end @@ -151,11 +151,17 @@ module QA end def has_admin_area_link?(wait: Capybara.default_max_wait_time) - has_element?(:admin_area_link, wait: wait) + within_top_menu do + click_element(:navbar_dropdown, title: 'Menu') + has_element?(:admin_area_link, wait: wait) + end end def has_no_admin_area_link?(wait: Capybara.default_max_wait_time) - has_no_element?(:admin_area_link, wait: wait) + within_top_menu do + click_element(:navbar_dropdown, title: 'Menu') + has_no_element?(:admin_area_link, wait: wait) + end end def click_stop_impersonation_link @@ -164,32 +170,32 @@ module QA private - def within_top_menu - within_element(:navbar) do - yield - end + def within_top_menu(&block) + within_element(:navbar, &block) end - def within_user_menu + def within_user_menu(&block) within_top_menu do click_element :user_avatar - within_element(:user_menu) do - yield - end + within_element(:user_menu, &block) end end def within_groups_menu(&block) - within_top_menu do - click_element :groups_dropdown - end + go_to_menu_dropdown_option(:groups_dropdown) + + within_element(:menu_subview_container, &block) + end + + def within_projects_menu(&block) + go_to_menu_dropdown_option(:projects_dropdown) - page.within('.qa-groups-dropdown-sidebar', &block) + within_element(:menu_subview_container, &block) end def click_admin_area - within_top_menu { click_element :admin_area_link } + go_to_menu_dropdown_option(:admin_area_link) end end end diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb index 63021df30f6..afec0e27a0b 100644 --- a/qa/qa/page/project/branches/show.rb +++ b/qa/qa/page/project/branches/show.rb @@ -5,13 +5,23 @@ module QA module Project module Branches class Show < Page::Base + view 'app/assets/javascripts/branches/components/delete_branch_button.vue' do + element :delete_branch_button + end + + view 'app/assets/javascripts/branches/components/delete_branch_modal.vue' do + element :delete_branch_confirmation_button + end + view 'app/views/projects/branches/_branch.html.haml' do element :remove_btn element :branch_name end + view 'app/views/projects/branches/_panel.html.haml' do element :all_branches end + view 'app/views/projects/branches/index.html.haml' do element :delete_merged_branches end @@ -19,12 +29,12 @@ module QA def delete_branch(branch_name) within_element(:all_branches) do within(".js-branch-#{branch_name}") do - accept_alert do - click_element(:remove_btn) - end + click_element(:delete_branch_button) end end + click_element(:delete_branch_confirmation_button) + finished_loading? end diff --git a/qa/qa/page/project/operations/environments/index.rb b/qa/qa/page/project/deployments/environments/index.rb index 6b46fa4985a..598e1f26815 100644 --- a/qa/qa/page/project/operations/environments/index.rb +++ b/qa/qa/page/project/deployments/environments/index.rb @@ -3,7 +3,7 @@ module QA module Page module Project - module Operations + module Deployments module Environments class Index < Page::Base view 'app/assets/javascripts/environments/components/environment_item.vue' do diff --git a/qa/qa/page/project/operations/environments/show.rb b/qa/qa/page/project/deployments/environments/show.rb index aa88c218c89..48e4850d3be 100644 --- a/qa/qa/page/project/operations/environments/show.rb +++ b/qa/qa/page/project/deployments/environments/show.rb @@ -3,7 +3,7 @@ module QA module Page module Project - module Operations + module Deployments module Environments class Show < Page::Base view 'app/views/projects/environments/_external_url.html.haml' do diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb index 58c82fa14c1..dc683f7314b 100644 --- a/qa/qa/page/project/import/github.rb +++ b/qa/qa/page/project/import/github.rb @@ -32,24 +32,20 @@ module QA end def import!(full_path, name) - unless already_imported(full_path) - choose_test_namespace(full_path) - set_path(full_path, name) - import_project(full_path) - wait_for_success - end + return if already_imported(full_path) - go_to_project(name) + choose_test_namespace(full_path) + set_path(full_path, name) + import_project(full_path) + wait_for_success end private - def within_repo_path(full_path) + def within_repo_path(full_path, &block) project_import_row = find_element(:project_import_row, text: full_path) - within(project_import_row) do - yield - end + within(project_import_row, &block) end def choose_test_namespace(full_path) @@ -75,8 +71,13 @@ module QA def wait_for_success # TODO: set reload:false and remove skip_finished_loading_check_on_refresh when # https://gitlab.com/gitlab-org/gitlab/-/issues/292861 is fixed - wait_until(max_duration: 60, sleep_interval: 5.0, reload: true, skip_finished_loading_check_on_refresh: true) do - page.has_no_content?('Importing 1 repository', wait: 3.0) + wait_until( + max_duration: 90, + sleep_interval: 5.0, + reload: true, + skip_finished_loading_check_on_refresh: true + ) do + page.has_no_content?('Importing 1 repository') end end diff --git a/qa/qa/page/project/operations/kubernetes/add.rb b/qa/qa/page/project/infrastructure/kubernetes/add.rb index 9a6ea99ac18..e2d50c1bcf1 100644 --- a/qa/qa/page/project/operations/kubernetes/add.rb +++ b/qa/qa/page/project/infrastructure/kubernetes/add.rb @@ -3,7 +3,7 @@ module QA module Page module Project - module Operations + module Infrastructure module Kubernetes class Add < Page::Base view 'app/views/clusters/clusters/new.html.haml' do diff --git a/qa/qa/page/project/operations/kubernetes/add_existing.rb b/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb index 59f59ca9966..689c2a31c4f 100644 --- a/qa/qa/page/project/operations/kubernetes/add_existing.rb +++ b/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb @@ -3,7 +3,7 @@ module QA module Page module Project - module Operations + module Infrastructure module Kubernetes class AddExisting < Page::Base view 'app/views/clusters/clusters/user/_form.html.haml' do @@ -32,7 +32,7 @@ module QA end def add_cluster! - click_element :add_kubernetes_cluster_button, Page::Project::Operations::Kubernetes::Show + click_element :add_kubernetes_cluster_button, Page::Project::Infrastructure::Kubernetes::Show end def uncheck_rbac! diff --git a/qa/qa/page/project/operations/kubernetes/index.rb b/qa/qa/page/project/infrastructure/kubernetes/index.rb index ca41dddaca2..bdcaf7ffaff 100644 --- a/qa/qa/page/project/operations/kubernetes/index.rb +++ b/qa/qa/page/project/infrastructure/kubernetes/index.rb @@ -3,7 +3,7 @@ module QA module Page module Project - module Operations + module Infrastructure module Kubernetes class Index < Page::Base view 'app/views/clusters/clusters/_empty_state.html.haml' do diff --git a/qa/qa/page/project/operations/kubernetes/show.rb b/qa/qa/page/project/infrastructure/kubernetes/show.rb index 3bb51d2d579..e3b4f8fe4d9 100644 --- a/qa/qa/page/project/operations/kubernetes/show.rb +++ b/qa/qa/page/project/infrastructure/kubernetes/show.rb @@ -3,7 +3,7 @@ module QA module Page module Project - module Operations + module Infrastructure module Kubernetes class Show < Page::Base view 'app/assets/javascripts/clusters/components/applications.vue' do @@ -77,7 +77,7 @@ module QA end def save_domain - click_element :save_changes_button, Page::Project::Operations::Kubernetes::Show + click_element :save_changes_button, Page::Project::Infrastructure::Kubernetes::Show end def wait_for_cluster_health diff --git a/qa/qa/page/project/members.rb b/qa/qa/page/project/members.rb index 09264d95aed..eeb589d6ca8 100644 --- a/qa/qa/page/project/members.rb +++ b/qa/qa/page/project/members.rb @@ -6,7 +6,7 @@ module QA class Members < Page::Base include QA::Page::Component::InviteMembersModal - view 'app/views/projects/project_members/index.html.haml' do + view 'app/assets/javascripts/members/components/members_tabs.vue' do element :groups_list_tab end diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb index ffabaf30374..db70d3e1d02 100644 --- a/qa/qa/page/project/menu.rb +++ b/qa/qa/page/project/menu.rb @@ -8,7 +8,9 @@ module QA include SubMenus::Project include SubMenus::CiCd include SubMenus::Issues - include SubMenus::Operations + include SubMenus::Deployments + include SubMenus::Monitor + include SubMenus::Infrastructure include SubMenus::Repository include SubMenus::Settings include SubMenus::Packages @@ -26,8 +28,10 @@ module QA end def click_activity - within_sidebar do - click_element(:sidebar_menu_item_link, menu_item: 'Activity') + hover_project_information do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Activity') + end end end @@ -38,8 +42,21 @@ module QA end def click_members + hover_project_information do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Members') + end + end + end + + private + + def hover_project_information within_sidebar do - click_element(:sidebar_menu_link, menu_item: 'Members') + scroll_to_element(:sidebar_menu_link, menu_item: 'Project information') + find_element(:sidebar_menu_link, menu_item: 'Project information').hover + + yield end end end diff --git a/qa/qa/page/project/operations/incidents/index.rb b/qa/qa/page/project/monitor/incidents/index.rb index fd0c5253a7f..9317cb27562 100644 --- a/qa/qa/page/project/operations/incidents/index.rb +++ b/qa/qa/page/project/monitor/incidents/index.rb @@ -3,7 +3,7 @@ module QA module Page module Project - module Operations + module Monitor module Incidents class Index < Page::Base view 'app/assets/javascripts/incidents/components/incidents_list.vue' do diff --git a/qa/qa/page/project/operations/metrics/show.rb b/qa/qa/page/project/monitor/metrics/show.rb index 22a7f1eed8f..07ceb108fa3 100644 --- a/qa/qa/page/project/operations/metrics/show.rb +++ b/qa/qa/page/project/monitor/metrics/show.rb @@ -5,7 +5,7 @@ require 'securerandom' module QA module Page module Project - module Operations + module Monitor module Metrics class Show < Page::Base EXPECTED_TITLE = 'Memory Usage (Total)' @@ -134,4 +134,4 @@ module QA end end -QA::Page::Project::Operations::Metrics::Show.prepend_mod_with('Page::Project::Operations::Metrics::Show', namespace: QA) +QA::Page::Project::Monitor::Metrics::Show.prepend_mod_with('Page::Project::Monitor::Metrics::Show', namespace: QA) diff --git a/qa/qa/page/project/settings/incidents.rb b/qa/qa/page/project/settings/alerts.rb index 610129851d9..be9b61ded80 100644 --- a/qa/qa/page/project/settings/incidents.rb +++ b/qa/qa/page/project/settings/alerts.rb @@ -4,8 +4,8 @@ module QA module Page module Project module Settings - class Incidents < Page::Base - view 'app/assets/javascripts/incidents_settings/components/alerts_form.vue' do + class Alerts < Page::Base + view 'app/assets/javascripts/alerts_settings/components/alerts_form.vue' do element :create_issue_checkbox element :incident_templates_dropdown element :save_changes_button diff --git a/qa/qa/page/project/settings/operations.rb b/qa/qa/page/project/settings/monitor.rb index 12dcb064807..87fb0698897 100644 --- a/qa/qa/page/project/settings/operations.rb +++ b/qa/qa/page/project/settings/monitor.rb @@ -4,7 +4,7 @@ module QA module Page module Project module Settings - class Operations < Page::Base + class Monitor < Page::Base include QA::Page::Settings::Common view 'app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue' do @@ -13,7 +13,7 @@ module QA def expand_incidents(&block) expand_content(:incidents_settings_content) do - Settings::Incidents.perform(&block) + Settings::Alerts.perform(&block) end end end diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index c174d4b0c3f..6e5097c3812 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -24,7 +24,10 @@ module QA view 'app/views/layouts/header/_new_dropdown.html.haml' do element :new_menu_toggle - element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern + end + + view 'app/helpers/nav/new_dropdown_helper.rb' do + element :new_issue_link end view 'app/views/projects/_last_push.html.haml' do @@ -115,7 +118,7 @@ module QA def go_to_new_issue click_element :new_menu_toggle - click_link 'New issue' + click_element(:new_issue_link) end def has_file?(name) diff --git a/qa/qa/page/project/sub_menus/deployments.rb b/qa/qa/page/project/sub_menus/deployments.rb new file mode 100644 index 00000000000..24243cb2436 --- /dev/null +++ b/qa/qa/page/project/sub_menus/deployments.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module SubMenus + module Deployments + extend QA::Page::PageConcern + + def self.included(base) + super + + base.class_eval do + include QA::Page::Project::SubMenus::Common + end + end + + def go_to_deployments_environments + hover_deployments do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Environments') + end + end + end + + private + + def hover_deployments + within_sidebar do + scroll_to_element(:sidebar_menu_link, menu_item: 'Deployments') + find_element(:sidebar_menu_link, menu_item: 'Deployments').hover + + yield + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/sub_menus/infrastructure.rb b/qa/qa/page/project/sub_menus/infrastructure.rb new file mode 100644 index 00000000000..2c207022c8d --- /dev/null +++ b/qa/qa/page/project/sub_menus/infrastructure.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module SubMenus + module Infrastructure + extend QA::Page::PageConcern + + def self.included(base) + super + + base.class_eval do + include QA::Page::Project::SubMenus::Common + end + end + + def go_to_infrastructure_kubernetes + hover_infrastructure do + within_submenu do + click_link('Kubernetes clusters') + end + end + end + + private + + def hover_infrastructure + within_sidebar do + scroll_to_element(:sidebar_menu_link, menu_item: 'Infrastructure') + find_element(:sidebar_menu_link, menu_item: 'Infrastructure').hover + + yield + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/sub_menus/operations.rb b/qa/qa/page/project/sub_menus/monitor.rb index 077da697a63..e3593e0a257 100644 --- a/qa/qa/page/project/sub_menus/operations.rb +++ b/qa/qa/page/project/sub_menus/monitor.rb @@ -4,7 +4,7 @@ module QA module Page module Project module SubMenus - module Operations + module Monitor extend QA::Page::PageConcern def self.included(base) @@ -15,32 +15,16 @@ module QA end end - def go_to_operations_environments - hover_operations do - within_submenu do - click_element(:sidebar_menu_item_link, menu_item: 'Environments') - end - end - end - - def go_to_operations_metrics - hover_operations do + def go_to_monitor_metrics + hover_monitor do within_submenu do click_element(:sidebar_menu_item_link, menu_item: 'Metrics') end end end - def go_to_operations_kubernetes - hover_operations do - within_submenu do - click_link('Kubernetes') - end - end - end - - def go_to_operations_incidents - hover_operations do + def go_to_monitor_incidents + hover_monitor do within_submenu do click_element(:sidebar_menu_item_link, menu_item: 'Incidents') end @@ -49,10 +33,10 @@ module QA private - def hover_operations + def hover_monitor within_sidebar do - scroll_to_element(:sidebar_menu_link, menu_item: 'Operations') - find_element(:sidebar_menu_link, menu_item: 'Operations').hover + scroll_to_element(:sidebar_menu_link, menu_item: 'Monitor') + find_element(:sidebar_menu_link, menu_item: 'Monitor').hover yield end diff --git a/qa/qa/page/project/sub_menus/project.rb b/qa/qa/page/project/sub_menus/project.rb index 5499a0f71e3..cd08715bcd8 100644 --- a/qa/qa/page/project/sub_menus/project.rb +++ b/qa/qa/page/project/sub_menus/project.rb @@ -12,13 +12,17 @@ module QA base.class_eval do include QA::Page::Project::SubMenus::Common + + view 'app/views/shared/nav/_scope_menu_body.html.haml' do + element :project_scope_link + end end end def click_project retry_on_exception do within_sidebar do - click_element(:sidebar_menu_link, menu_item: 'Project overview') + click_element(:project_scope_link) end end end diff --git a/qa/qa/page/project/sub_menus/settings.rb b/qa/qa/page/project/sub_menus/settings.rb index 80f62c8efde..f35d27e658d 100644 --- a/qa/qa/page/project/sub_menus/settings.rb +++ b/qa/qa/page/project/sub_menus/settings.rb @@ -53,10 +53,10 @@ module QA end end - def go_to_operations_settings + def go_to_monitor_settings hover_settings do within_submenu do - click_element(:sidebar_menu_item_link, menu_item: 'Operations') + click_element(:sidebar_menu_item_link, menu_item: 'Monitor') end end end diff --git a/qa/qa/page/registration/sign_up.rb b/qa/qa/page/registration/sign_up.rb index 0fb4b466e62..6d1b9cb3615 100644 --- a/qa/qa/page/registration/sign_up.rb +++ b/qa/qa/page/registration/sign_up.rb @@ -7,12 +7,15 @@ module QA view 'app/views/devise/shared/_signup_box.html.haml' do element :new_user_first_name_field element :new_user_last_name_field - element :new_user_username_field element :new_user_email_field element :new_user_password_field element :new_user_register_button end + view 'app/helpers/registrations_helper.rb' do + element :new_user_username_field + end + view 'app/views/registrations/welcome/show.html.haml' do element :get_started_button end diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb index c7565871b0b..0f06113f85b 100644 --- a/qa/qa/resource/group.rb +++ b/qa/qa/resource/group.rb @@ -5,6 +5,10 @@ module QA class Group < GroupBase attr_accessor :description + attribute :full_path do + determine_full_path + end + attribute :sandbox do Sandbox.fabricate_via_api! do |sandbox| sandbox.api_client = api_client @@ -29,6 +33,7 @@ module QA group_show.go_to_new_subgroup Page::Group::New.perform do |group_new| + group_new.click_create_group group_new.set_path(path) group_new.set_visibility('Public') group_new.create @@ -47,10 +52,16 @@ module QA resource_web_url(api_get) rescue ResourceNotFoundError super + + Support::Retrier.retry_on_exception(sleep_interval: 5) do + resource = resource_web_url(api_get) + populate(:runners_token) + resource + end end def api_get_path - "/groups/#{CGI.escape("#{sandbox.path}/#{path}")}" + "/groups/#{CGI.escape(determine_full_path)}" end def api_post_body @@ -93,6 +104,32 @@ module QA 'Timed out while waiting for the group repository storage move to finish' ) end + + private + + # Determine the path up to the root group. + # + # This is equivalent to the full_path API attribute. We can't use the full_path attribute + # because it depends on the group being fabricated first, and we use this method to help + # _check_ if the group exists. + # + # @param [QA::Resource::GroupBase] sandbox the immediate parent group of this group + # @param [String] path the path name of this group (the leaf, not the full path) + # @return [String] + def determine_full_path + determine_parent_group_paths(sandbox, path) + end + + # Recursively traverse the parents of this group up to the root group. + # + # @param [QA::Resource::GroupBase] parent the immediate parent group + # @param [String] path the path traversed so far + # @return [String] + def determine_parent_group_paths(parent, path) + return "#{parent.path}/#{path}" unless parent.respond_to?(:sandbox) + + determine_parent_group_paths(parent.sandbox, "#{parent.path}/#{path}") + end end end end diff --git a/qa/qa/resource/group_base.rb b/qa/qa/resource/group_base.rb index bdd442a1c8b..025d98f50e0 100644 --- a/qa/qa/resource/group_base.rb +++ b/qa/qa/resource/group_base.rb @@ -14,6 +14,29 @@ module QA attribute :name attribute :full_path + # Get group labels + # + # @return [Array<QA::Resource::GroupLabel>] + def labels + parse_body(api_get_from("#{api_get_path}/labels")).map do |label| + GroupLabel.new.tap do |resource| + resource.api_client = api_client + resource.group = self + resource.id = label[:id] + resource.title = label[:name] + resource.description = label[:description] + resource.color = label[:color] + end + end + end + + # API get path + # + # @return [String] + def api_get_path + raise NotImplementedError + end + # API post path # # @return [String] @@ -58,15 +81,21 @@ module QA def comparable_group reload! if api_response.nil? - api_resource.except( - :id, - :web_url, - :visibility, - :full_name, - :full_path, - :created_at, - :parent_id, - :runners_token + api_resource.slice( + :name, + :path, + :description, + :emails_disabled, + :lfs_enabled, + :mentions_disabled, + :project_creation_level, + :request_access_enabled, + :require_two_factor_authentication, + :share_with_group_lock, + :subgroup_creation_level, + :two_factor_grace_perion + # TODO: Add back visibility comparison once https://gitlab.com/gitlab-org/gitlab/-/issues/331252 is fixed + # :visibility ) end end diff --git a/qa/qa/resource/group_label.rb b/qa/qa/resource/group_label.rb new file mode 100644 index 00000000000..d512dfc6a89 --- /dev/null +++ b/qa/qa/resource/group_label.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module QA + module Resource + class GroupLabel < LabelBase + attribute :group do + Group.fabricate! do |resource| + resource.name = 'group-with-label' + end + end + + def fabricate! + raise NotImplementedError + end + + def api_post_path + "/groups/#{CGI.escape(group.full_path)}/labels" + end + + def api_get_path + "/groups/#{CGI.escape(group.full_path)}/labels/#{id}" + end + end + end +end diff --git a/qa/qa/resource/kubernetes_cluster/project_cluster.rb b/qa/qa/resource/kubernetes_cluster/project_cluster.rb index 78a24cdb677..b66a75d978b 100644 --- a/qa/qa/resource/kubernetes_cluster/project_cluster.rb +++ b/qa/qa/resource/kubernetes_cluster/project_cluster.rb @@ -12,22 +12,22 @@ module QA end attribute :ingress_ip do - Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip) + Page::Project::Infrastructure::Kubernetes::Show.perform(&:ingress_ip) end def fabricate! project.visit! Page::Project::Menu.perform( - &:go_to_operations_kubernetes) + &:go_to_infrastructure_kubernetes) - Page::Project::Operations::Kubernetes::Index.perform( + Page::Project::Infrastructure::Kubernetes::Index.perform( &:add_kubernetes_cluster) - Page::Project::Operations::Kubernetes::Add.perform( + Page::Project::Infrastructure::Kubernetes::Add.perform( &:add_existing_cluster) - Page::Project::Operations::Kubernetes::AddExisting.perform do |cluster_page| + Page::Project::Infrastructure::Kubernetes::AddExisting.perform do |cluster_page| cluster_page.set_cluster_name(@cluster.cluster_name) cluster_page.set_api_url(@cluster.api_url) cluster_page.set_ca_certificate(@cluster.ca_certificate) @@ -36,7 +36,7 @@ module QA cluster_page.add_cluster! end - Page::Project::Operations::Kubernetes::Show.perform do |show| + Page::Project::Infrastructure::Kubernetes::Show.perform do |show| # We must wait a few seconds for permissions to be set up correctly for new cluster sleep 25 diff --git a/qa/qa/resource/label.rb b/qa/qa/resource/label.rb deleted file mode 100644 index 6b0b0184130..00000000000 --- a/qa/qa/resource/label.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: true - -require 'securerandom' - -module QA - module Resource - class Label < Base - attr_accessor :description, :color - - attribute :id - attribute :title - - attribute :project do - Project.fabricate! do |resource| - resource.name = 'project-with-label' - end - end - - def initialize - @title = "qa-test-#{SecureRandom.hex(8)}" - @description = 'This is a test label' - @color = '#0033CC' - end - - def fabricate! - project.visit! - - Page::Project::Menu.perform(&:go_to_labels) - Page::Label::Index.perform(&:click_new_label_button) - - Page::Label::New.perform do |new_page| - new_page.fill_title(@title) - new_page.fill_description(@description) - new_page.fill_color(@color) - new_page.click_label_create_button - end - end - - def resource_web_url(resource) - super - rescue ResourceURLMissingError - # this particular resource does not expose a web_url property - end - - def api_get_path - raise NotImplementedError, "The Labels API doesn't expose a single-resource endpoint so this method cannot be properly implemented." - end - - def api_post_path - "/projects/#{project.id}/labels" - end - - def api_post_body - { - color: @color, - name: @title - } - end - end - end -end diff --git a/qa/qa/resource/label_base.rb b/qa/qa/resource/label_base.rb new file mode 100644 index 00000000000..14ddd0809ea --- /dev/null +++ b/qa/qa/resource/label_base.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +require 'securerandom' + +module QA + module Resource + # Base label class for GroupLabel and ProjectLabel + # + class LabelBase < Base + attr_accessor :title, :description, :color + + attribute :id + attribute :description_html + attribute :text_color + attribute :subscribed + + def initialize + @title = "qa-test-#{SecureRandom.hex(8)}" + @description = 'This is a test label' + @color = '#0033CC' + end + + def fabricate! + Page::Label::Index.perform(&:click_new_label_button) + Page::Label::New.perform do |new_page| + new_page.fill_title(title) + new_page.fill_description(description) + new_page.fill_color(color) + new_page.click_label_create_button + end + end + + # Resource web url + # + # @param [Hash] resource + # @return [String] + def resource_web_url(resource) + super + rescue ResourceURLMissingError + # this particular resource does not expose a web_url property + end + + # Params for label creation + # + # @return [Hash] + def api_post_body + { + name: title, + color: color, + description: description + } + end + + # Object comparison + # + # @param [QA::Resource::GroupBase] other + # @return [Boolean] + def ==(other) + other.is_a?(LabelBase) && comparable_label == other.comparable_label + end + + # Override inspect for a better rspec failure diff output + # + # @return [String] + def inspect + JSON.pretty_generate(comparable_label) + end + + # protected + + # Return subset of fields for comparing groups + # + # @return [Hash] + def comparable_label + reload! unless api_response + + api_response.slice( + :name, + :description, + :description_html, + :color, + :text_color, + :subscribed + ) + end + end + end +end diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb index 96a60381146..f8cf816d6e4 100644 --- a/qa/qa/resource/project.rb +++ b/qa/qa/resource/project.rb @@ -10,10 +10,10 @@ module QA include Visibility attr_accessor :repository_storage # requires admin access - attr_writer :initialize_with_readme - attr_writer :auto_devops_enabled - attr_writer :github_personal_access_token - attr_writer :github_repository_path + attr_writer :initialize_with_readme, + :auto_devops_enabled, + :github_personal_access_token, + :github_repository_path attribute :id attribute :name @@ -40,15 +40,11 @@ module QA end attribute :repository_ssh_location do - Page::Project::Show.perform do |show| - show.repository_clone_ssh_location - end + Page::Project::Show.perform(&:repository_clone_ssh_location) end attribute :repository_http_location do - Page::Project::Show.perform do |show| - show.repository_clone_http_location - end + Page::Project::Show.perform(&:repository_clone_http_location) end def initialize @@ -104,7 +100,7 @@ module QA def has_file?(file_path) response = repository_tree - raise ResourceNotFoundError, "#{response[:message]}" if response.is_a?(Hash) && response.has_key?(:message) + raise ResourceNotFoundError, (response[:message]).to_s if response.is_a?(Hash) && response.has_key?(:message) response.any? { |file| file[:path] == file_path } end @@ -115,14 +111,14 @@ module QA def has_branches?(branches) branches.all? do |branch| - response = get(Runtime::API::Request.new(api_client, "#{api_repository_branches_path}/#{branch}").url) + response = get(request_url("#{api_repository_branches_path}/#{branch}")) response.code == HTTP_STATUS_OK end end def has_tags?(tags) tags.all? do |tag| - response = get(Runtime::API::Request.new(api_client, "#{api_repository_tags_path}/#{tag}").url) + response = get(request_url("#{api_repository_tags_path}/#{tag}")) response.code == HTTP_STATUS_OK end end @@ -135,6 +131,18 @@ module QA "/projects/#{id}" end + def api_put_path + "/projects/#{id}" + end + + def api_post_path + '/projects' + end + + def api_delete_path + "/projects/#{id}" + end + def api_get_archive_path(type = 'tar.gz') "#{api_get_path}/repository/archive.#{type}" end @@ -183,12 +191,20 @@ module QA "#{api_get_path}/pipeline_schedules" end - def api_put_path - "/projects/#{id}" + def api_issues_path + "#{api_get_path}/issues" end - def api_post_path - '/projects' + def api_labels_path + "#{api_get_path}/labels" + end + + def api_milestones_path + "#{api_get_path}/milestones" + end + + def api_wikis_path + "#{api_get_path}/wikis" end def api_post_body @@ -211,25 +227,25 @@ module QA post_body end - def api_delete_path - "/projects/#{id}" - end - def change_repository_storage(new_storage) put_body = { repository_storage: new_storage } - response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body + response = put(request_url(api_put_path), put_body) unless response.code == HTTP_STATUS_OK - raise ResourceUpdateFailedError, "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`." + raise( + ResourceUpdateFailedError, + "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`." + ) end - wait_until(sleep_interval: 1) { Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage) } + wait_until(sleep_interval: 1) do + Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage) + end rescue Support::Repeater::RepeaterConditionExceededError - raise Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError, 'Timed out while waiting for the repository storage move to finish' - end - - def commits - parse_body(get(Runtime::API::Request.new(api_client, api_commits_path).url)) + raise( + Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError, + 'Timed out while waiting for the repository storage move to finish' + ) end def default_branch @@ -237,7 +253,7 @@ module QA end def import_status - response = get Runtime::API::Request.new(api_client, "/projects/#{id}/import").url + response = get(request_url("/projects/#{id}/import")) unless response.code == HTTP_STATUS_OK raise ResourceQueryError, "Could not get import status. Request returned (#{response.code}): `#{response}`." @@ -250,8 +266,14 @@ module QA result[:import_status] end + def commits + response = get(request_url(api_commits_path)) + parse_body(response) + end + def merge_requests - parse_body(get(Runtime::API::Request.new(api_client, api_merge_requests_path).url)) + response = get(request_url(api_merge_requests_path)) + parse_body(response) end def merge_request_with_title(title) @@ -259,43 +281,65 @@ module QA end def runners(tag_list: nil) - response = if tag_list - get Runtime::API::Request.new(api_client, "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}").url - else - get Runtime::API::Request.new(api_client, "#{api_runners_path}").url - end + url = tag_list ? "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}" : api_runners_path + response = get(request_url(url, per_page: '100')) parse_body(response) end def registry_repositories - response = get Runtime::API::Request.new(api_client, "#{api_registry_repositories_path}").url + response = get(request_url(api_registry_repositories_path)) parse_body(response) end def packages - response = get Runtime::API::Request.new(api_client, "#{api_packages_path}").url + response = get(request_url(api_packages_path)) parse_body(response) end def repository_branches - parse_body(get(Runtime::API::Request.new(api_client, api_repository_branches_path).url)) + response = get(request_url(api_repository_branches_path)) + parse_body(response) end def repository_tags - parse_body(get(Runtime::API::Request.new(api_client, api_repository_tags_path).url)) + response = get(request_url(api_repository_tags_path)) + parse_body(response) end def repository_tree - parse_body(get(Runtime::API::Request.new(api_client, api_repository_tree_path).url)) + response = get(request_url(api_repository_tree_path)) + parse_body(response) end def pipelines - parse_body(get(Runtime::API::Request.new(api_client, api_pipelines_path).url)) + response = get(request_url(api_pipelines_path)) + parse_body(response) end def pipeline_schedules - parse_body(get(Runtime::API::Request.new(api_client, api_pipeline_schedules_path).url)) + response = get(request_url(api_pipeline_schedules_path)) + parse_body(response) + end + + def issues + response = get(request_url(api_issues_path)) + parse_body(response) + end + + def labels + response = get(request_url(api_labels_path)) + parse_body(response) + end + + def milestones + response = get(request_url(api_milestones_path)) + parse_body(response) + end + + def wikis + response = get(request_url(api_wikis_path)) + parse_body(response) end private @@ -307,6 +351,14 @@ module QA Git::Location.new(api_resource[:http_url_to_repo]) api_resource end + + # Get api request url + # + # @param [String] path + # @return [String] + def request_url(path, **opts) + Runtime::API::Request.new(api_client, path, **opts).url + end end end end diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb index b06a7fe4e3d..93cd166a191 100644 --- a/qa/qa/resource/project_imported_from_github.rb +++ b/qa/qa/resource/project_imported_from_github.rb @@ -7,23 +7,19 @@ module QA class ProjectImportedFromGithub < Resource::Project def fabricate! self.import = true - super - group.visit! + Page::Main::Menu.perform(&:go_to_create_project) - Page::Group::Show.perform(&:go_to_new_project) - go_to_import_page - Page::Project::New.perform(&:click_github_link) + Page::Project::New.perform do |project_page| + project_page.click_import_project + project_page.click_github_link + end Page::Project::Import::Github.perform do |import_page| import_page.add_personal_access_token(@github_personal_access_token) import_page.import!(@github_repository_path, @name) end end - - def go_to_import_page - Page::Project::New.perform(&:click_import_project) - end end end end diff --git a/qa/qa/resource/project_label.rb b/qa/qa/resource/project_label.rb new file mode 100644 index 00000000000..6b2943a801e --- /dev/null +++ b/qa/qa/resource/project_label.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module QA + module Resource + class ProjectLabel < LabelBase + attribute :project do + Project.fabricate! do |resource| + resource.name = 'project-with-label' + end + end + + def fabricate! + project.visit! + Page::Project::Menu.perform(&:go_to_labels) + + super + end + + def api_post_path + "/projects/#{project.id}/labels" + end + + def api_get_path + "/projects/#{project.id}/labels/#{id}" + end + end + end +end diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb index 913fd6ab9ec..b351d78a184 100644 --- a/qa/qa/resource/sandbox.rb +++ b/qa/qa/resource/sandbox.rb @@ -11,6 +11,8 @@ module QA @path = Runtime::Namespace.sandbox_name end + alias_method :full_path, :path + def fabricate! Page::Main::Menu.perform(&:go_to_groups) diff --git a/qa/qa/runtime/allure_report.rb b/qa/qa/runtime/allure_report.rb new file mode 100644 index 00000000000..5e9ae3e7bbe --- /dev/null +++ b/qa/qa/runtime/allure_report.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +module QA + module Runtime + class AllureReport + class << self + # Configure allure reports + # + # @return [void] + def configure! + return unless Env.generate_allure_report? + + require 'allure-rspec' + + configure_allure + configure_attachments + configure_rspec + end + + private + + # Configure allure reporter + # + # @return [void] + def configure_allure + # Match job names like ee:relative, ce:update etc. and set as execution environment + env_matcher = /^(?<env>\w{2}:\S+)/ + + AllureRspec.configure do |config| + config.results_directory = 'tmp/allure-results' + config.clean_results_directory = true + + # Set custom environment name to separate same specs executed on different environments + if Env.running_in_ci? && Env.ci_job_name.match?(env_matcher) + config.environment = Env.ci_job_name.match(env_matcher).named_captures['env'] + end + end + end + + # Set up failure screenshot attachments + # + # @return [void] + def configure_attachments + Capybara::Screenshot.after_save_screenshot do |path| + Allure.add_attachment( + name: 'screenshot', + source: File.open(path), + type: Allure::ContentType::PNG, + test_case: true + ) + end + Capybara::Screenshot.after_save_html do |path| + Allure.add_attachment( + name: 'html', + source: File.open(path), + type: 'text/html', + test_case: true + ) + end + end + + # Configure rspec + # + # @return [void] + def configure_rspec + RSpec.configure do |config| + config.formatter = AllureRspecFormatter + + config.before do |example| + next if example.attempts && example.attempts > 0 + + testcase = example.metadata[:testcase] + example.tms('Testcase', testcase) if testcase + + issue = example.metadata.dig(:quarantine, :issue) + example.issue('Issue', issue) if issue + + example.add_link(name: "Job(#{Env.ci_job_name})", url: Env.ci_job_url) if Env.running_in_ci? + end + end + end + end + end + end +end diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index e649084a394..ccb87147a6e 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -2,7 +2,6 @@ require 'gitlab/qa' require 'uri' -require 'active_support/core_ext/object/blank' module QA module Runtime @@ -53,8 +52,12 @@ module QA enabled?(ENV['QA_DEBUG'], default: false) end + def generate_allure_report? + enabled?(ENV['QA_GENERATE_ALLURE_REPORT'], default: false) + end + def default_branch - ENV['QA_DEFAULT_BRANCH'] || 'master' + ENV['QA_DEFAULT_BRANCH'] || 'main' end def log_destination diff --git a/qa/qa/runtime/scenario.rb b/qa/qa/runtime/scenario.rb index 3662ebe671b..d44cc846128 100644 --- a/qa/qa/runtime/scenario.rb +++ b/qa/qa/runtime/scenario.rb @@ -19,15 +19,15 @@ module QA define_singleton_method(attribute) do attributes[attribute.to_sym].tap do |value| - if value.to_s.empty? - raise ArgumentError, "Empty `#{attribute}` attribute!" - end + raise ArgumentError, "Empty `#{attribute}` attribute!" if value.to_s.empty? end end end def from_env(var) - JSON.parse(Runtime::Env.runtime_scenario_attributes).each { |k, v| define(k, v) } + return if var.blank? + + JSON.parse(var).each { |k, v| define(k, v) } end def method_missing(name, *) diff --git a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb index 9bf3474ba5a..08b71258cc6 100644 --- a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb +++ b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb @@ -6,7 +6,7 @@ module QA RSpec.describe 'Create' do context 'Gitaly' do # Issue to track removal of feature flag: https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/602 - describe 'Distributed reads', :orchestrated, :gitaly_cluster, :skip_live_env, :requires_admin do + describe 'Distributed reads', :orchestrated, :gitaly_cluster, :skip_live_env, :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/322814', type: :investigating } do let(:number_of_reads_per_loop) { 9 } let(:praefect_manager) { Service::PraefectManager.new } let(:project) do diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb index 7e924475437..396d3f52798 100644 --- a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb +++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb @@ -4,7 +4,7 @@ require 'parallel' module QA RSpec.describe 'Create' do - context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env do + context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/331989', type: :investigating } do let(:praefect_manager) { Service::PraefectManager.new } let(:project) do Resource::Project.fabricate! do |project| diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb index 055300122d4..d4c4ec5611a 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb @@ -2,20 +2,21 @@ module QA RSpec.describe 'Manage', :requires_admin do - describe 'Group bulk import' do - let!(:api_client) { Runtime::API::Client.as_admin } + describe 'Bulk group import' do + let!(:admin_api_client) { Runtime::API::Client.as_admin } let!(:user) do Resource::User.fabricate_via_api! do |usr| - usr.api_client = api_client + usr.api_client = admin_api_client usr.hard_delete_on_api_removal = true end end - let!(:personal_access_token) { Runtime::API::Client.new(user: user).personal_access_token } + let!(:api_client) { Runtime::API::Client.new(user: user) } + let!(:personal_access_token) { api_client.personal_access_token } let!(:sandbox) do Resource::Sandbox.fabricate_via_api! do |group| - group.api_client = api_client + group.api_client = admin_api_client end end @@ -37,6 +38,7 @@ module QA let(:imported_group) do Resource::Group.new.tap do |group| group.api_client = api_client + group.sandbox = sandbox group.path = source_group.path end end @@ -54,42 +56,65 @@ module QA end before(:all) do - Runtime::Feature.enable(:bulk_import) + Runtime::Feature.enable(:bulk_import) unless staging? Runtime::Feature.enable(:top_level_group_creation_enabled) if staging? end before do sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER) - source_group.add_member(user, Resource::Members::AccessLevel::MAINTAINER) Flow::Login.sign_in(as: user) - Page::Main::Menu.new.go_to_import_group - Page::Group::New.new.connect_gitlab_instance(Runtime::Scenario.gitlab_address, personal_access_token) + Page::Main::Menu.perform(&:go_to_create_group) + Page::Group::New.perform do |group| + group.switch_to_import_tab + group.connect_gitlab_instance(Runtime::Scenario.gitlab_address, personal_access_token) + end end + # Non blocking issues: + # https://gitlab.com/gitlab-org/gitlab/-/issues/331252 it( - 'performs bulk group import from another gitlab instance', + 'imports group with subgroups and labels', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1785', - exclude: { job: ['ce:relative_url', 'ee:relative_url'] } # https://gitlab.com/gitlab-org/gitlab/-/issues/330344 + quarantine: { + only: { job: 'relative_url' }, + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/330344', + type: :bug + } ) do + Resource::GroupLabel.fabricate_via_api! do |label| + label.api_client = api_client + label.group = source_group + label.title = "source-group-#{SecureRandom.hex(4)}" + end + Resource::GroupLabel.fabricate_via_api! do |label| + label.api_client = api_client + label.group = subgroup + label.title = "subgroup-#{SecureRandom.hex(4)}" + end + Page::Group::BulkImport.perform do |import_page| import_page.import_group(source_group.path, sandbox.path) aggregate_failures do - expect(import_page).to have_imported_group(source_group.path, wait: 120) - expect(imported_group).to eq(source_group) - expect(imported_subgroup).to eq(subgroup) + expect(import_page).to have_imported_group(source_group.path, wait: 180) + + expect { imported_group.reload! }.to eventually_eq(source_group).within(duration: 10) + expect { imported_group.labels }.to eventually_include(*source_group.labels).within(duration: 10) + + # Do not validate subgroups until https://gitlab.com/gitlab-org/gitlab/-/issues/332818 is resolved + # expect { imported_subgroup.reload! }.to eventually_eq(subgroup).within(duration: 30) + # expect { imported_subgroup.labels }.to eventually_include(*subgroup.labels).within(duration: 30) end end end after do user.remove_via_api! - source_group.remove_via_api! end after(:all) do - Runtime::Feature.disable(:bulk_import) + Runtime::Feature.disable(:bulk_import) unless staging? Runtime::Feature.disable(:top_level_group_creation_enabled) if staging? end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb index 7bcc1fa4e1c..192c1a3908b 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb @@ -10,9 +10,13 @@ module QA Page::Dashboard::Groups.perform do |groups| groups.click_new_group - expect(groups).to have_content( - /Create a Mattermost team for this group/ - ) + Page::Group::New.perform do |group_new| + group_new.click_create_group + + expect(group_new).to have_content( + /Create a Mattermost team for this group/ + ) + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb index d6bcd134a03..84464f7174a 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb @@ -28,14 +28,17 @@ module QA end it 'transfers a subgroup to another group', - testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1724' do + testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1724' do Page::Group::Menu.perform(&:click_group_general_settings_item) Page::Group::Settings::General.perform do |general| general.transfer_group(target_group.path) + + sub_group_for_transfer.sandbox = target_group + sub_group_for_transfer.reload! end expect(page).to have_text("Group '#{sub_group_for_transfer.path}' was successfully transferred.") - expect(page.driver.current_url).to include("#{target_group.path}/#{sub_group_for_transfer.path}") + expect(page.driver.current_url).to include(sub_group_for_transfer.full_path) end after do diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb index 5072b6d48bf..55ad8baf872 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -3,25 +3,26 @@ module QA RSpec.describe 'Manage', :github, :requires_admin do describe 'Project import' do + let!(:api_client) { Runtime::API::Client.as_admin } + let!(:group) { Resource::Group.fabricate_via_api! { |resource| resource.api_client = api_client } } let!(:user) do Resource::User.fabricate_via_api! do |resource| - resource.api_client = Runtime::API::Client.as_admin + resource.api_client = api_client + resource.hard_delete_on_api_removal = true end end - let(:group) { Resource::Group.fabricate_via_api! } - let(:imported_project) do Resource::ProjectImportedFromGithub.fabricate_via_browser_ui! do |project| project.name = 'imported-project' project.group = group project.github_personal_access_token = Runtime::Env.github_access_token project.github_repository_path = 'gitlab-qa-github/test-project' + project.api_client = api_client end end before do - Runtime::Feature.enable(:invite_members_group_modal, group: group) group.add_member(user, Resource::Members::AccessLevel::MAINTAINER) end @@ -32,90 +33,90 @@ module QA it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1762' do Flow::Login.sign_in(as: user) - imported_project # import the project + imported_project.reload! # import the project and reload all fields - Page::Main::Menu.perform(&:go_to_projects) - Page::Dashboard::Projects.perform do |dashboard| - dashboard.go_to_project(imported_project.name) + aggregate_failures do + verify_repository_import + verify_commits_import + verify_labels_import + verify_issues_import + verify_milestones_import + verify_wikis_import + verify_merge_requests_import end - - Page::Project::Show.perform(&:wait_for_import) - - verify_repository_import - verify_issues_import - verify_merge_requests_import - verify_labels_import - verify_milestones_import - verify_wiki_import end def verify_repository_import - Page::Project::Show.perform do |project| - expect(project).to have_content('This test project is used for automated GitHub import by GitLab QA.') - expect(project).to have_content(imported_project.name) - end + expect(imported_project.api_response).to include( + description: 'A new repo for test', + import_status: 'finished', + import_error: nil + ) end - def verify_issues_import - QA::Support::Retrier.retry_on_exception do - Page::Project::Menu.perform(&:click_issues) - - Page::Project::Issue::Show.perform do |issue_page| - expect(issue_page).to have_content('This is a sample issue') - - click_link 'This is a sample issue' - - expect(issue_page).to have_content('This is a sample first comment') - - # Comments - comment_text = 'This is a comment from @sliaquat' - - expect(issue_page).to have_comment(comment_text) - expect(issue_page).to have_label('custom new label') - expect(issue_page).to have_label('help wanted') - expect(issue_page).to have_label('good first issue') - end - end + def verify_commits_import + expect(imported_project.commits.length).to eq(20) end - def verify_merge_requests_import - Page::Project::Menu.perform(&:click_merge_requests) - - Page::MergeRequest::Show.perform do |merge_request| - expect(merge_request).to have_content('Improve readme') - - click_link 'Improve readme' - - expect(merge_request).to have_content('This improves the README file a bit.') - - # Comments - expect(merge_request).to have_content('[PR comment by @sliaquat] Nice work!') - - # Diff comments - expect(merge_request).to have_content('[Single diff comment] Good riddance') - expect(merge_request).to have_content('[Single diff comment] Nice addition') - - expect(merge_request).to have_label('bug') - expect(merge_request).to have_label('documentation') - end + def verify_labels_import + labels = imported_project.labels.map { |label| label.slice(:name, :color) } + + expect(labels).to eq( + [ + { name: 'bug', color: '#d73a4a' }, + { name: 'custom new label', color: '#fc8f91' }, + { name: 'documentation', color: '#0075ca' }, + { name: 'duplicate', color: '#cfd3d7' }, + { name: 'enhancement', color: '#a2eeef' }, + { name: 'good first issue', color: '#7057ff' }, + { name: 'help wanted', color: '#008672' }, + { name: 'invalid', color: '#e4e669' }, + { name: 'question', color: '#d876e3' }, + { name: 'wontfix', color: '#ffffff' } + ] + ) end - def verify_labels_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/19228 - # to build upon it. + def verify_issues_import + issues = imported_project.issues + + expect(issues.length).to eq(1) + expect(issues.first).to include( + title: 'This is a sample issue', + description: "*Created by: gitlab-qa-github*\n\nThis is a sample first comment", + labels: ['custom new label', 'good first issue', 'help wanted'], + user_notes_count: 1 + ) end def verify_milestones_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/18727 - # to build upon it. + milestones = imported_project.milestones + + expect(milestones.length).to eq(1) + expect(milestones.first).to include(title: 'v1.0', description: nil, state: 'active') end - def verify_wiki_import - Page::Project::Menu.perform(&:click_wiki) + def verify_wikis_import + wikis = imported_project.wikis - Page::Project::Wiki::Show.perform do |wiki| - expect(wiki).to have_content('Welcome to the test-project wiki!') - end + expect(wikis.length).to eq(1) + expect(wikis.first).to include(title: 'Home', format: 'markdown') + end + + def verify_merge_requests_import + merge_requests = imported_project.merge_requests + + expect(merge_requests.length).to eq(1) + expect(merge_requests.first).to include( + title: 'Improve readme', + state: 'opened', + target_branch: 'main', + source_branch: 'improve-readme', + labels: %w[bug documentation], + description: <<~DSC.strip + *Created by: gitlab-qa-github*\n\nThis improves the README file a bit.\r\n\r\nTODO:\r\n\r\n \r\n\r\n- [ ] Do foo\r\n- [ ] Make bar\r\n - [ ] Think about baz + DSC + ) end end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb index 2654531bc2c..44a361df34d 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb @@ -25,6 +25,7 @@ module QA after do Runtime::Feature.disable('real_time_issue_sidebar', project: project) Runtime::Feature.disable('broadcast_issue_updates', project: project) + Runtime::Feature.disable(:invite_members_group_modal, project: project) end it 'update without refresh', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1048' do @@ -37,7 +38,9 @@ module QA Page::Project::Issue::Show.perform do |show| expect(show).to have_assignee(user1.name) - + # We need to wait 1 second for the page to connect to the websocket to subscribe to updates + # https://gitlab.com/gitlab-org/gitlab/-/issues/293699#note_583959786 + sleep 1 issue.set_issue_assignees(assignee_ids: [user2.id]) expect(show).to have_assignee(user2.name) diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb index dfdc9b7c9b4..59d34612ca7 100644 --- a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create' do + RSpec.describe 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/331978', type: :bug } do context 'Design Management' do let(:design) do Resource::Design.fabricate! do |design| 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 81ad1896075..082d001b716 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 @@ -16,7 +16,11 @@ module QA Flow::Login.sign_in end - it 'creates a basic merge request', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1276' do + it( + 'creates a basic merge request', + :smoke, + testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1850' + ) do Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request| merge_request.project = project merge_request.title = merge_request_title @@ -29,14 +33,17 @@ module QA end end - it 'creates a merge request with a milestone and label', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/514' do + it( + 'creates a merge request with a milestone and label', + testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/514' + ) do gitlab_account_username = "@#{Runtime::User.username}" milestone = Resource::ProjectMilestone.fabricate_via_api! do |milestone| milestone.project = project end - label = Resource::Label.fabricate_via_api! do |label| + label = Resource::ProjectLabel.fabricate_via_api! do |label| label.project = project label.title = 'label' end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb index c2e148e19bd..dd4b3276687 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb @@ -2,7 +2,8 @@ module QA RSpec.describe 'Create' do - describe 'Merge request creation from fork', :smoke do + describe 'Merge request creation from fork' do + # TODO: Please add this back to :smoke suite as soon as https://gitlab.com/gitlab-org/gitlab/-/issues/332588 is addressed it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1701' do merge_request = Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request| merge_request.fork_branch = 'feature-branch' 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 index d400876c838..639702f9148 100644 --- 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 @@ -2,7 +2,7 @@ module QA RSpec.describe 'Create' do - describe 'Create, list, and delete branches via web' do + describe 'Create, list, and delete branches via web', :requires_admin do master_branch = nil second_branch = 'second-branch' third_branch = 'third-branch' @@ -24,6 +24,8 @@ module QA proj.initialize_with_readme = true end + Runtime::Feature.enable(:delete_branch_confirmation_modals, project: project) + master_branch = project.default_branch Git::Repository.perform do |repository| diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb index 2c0fb5ea290..67b48d254ac 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb @@ -3,7 +3,7 @@ module QA RSpec.describe 'Create' do describe 'Git push over HTTP', :smoke do - it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1278' do + it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1848' do Flow::Login.sign_in access_token = Resource::PersonalAccessToken.fabricate!.token diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb index 4f241325437..ae8f34f9845 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb @@ -7,7 +7,7 @@ module QA Flow::Login.sign_in Page::Main::Menu.perform do |menu| - menu.go_to_more_dropdown_option(:snippets_link) + menu.go_to_menu_dropdown_option(:snippets_link) end Resource::Snippet.fabricate_via_browser_ui! do |snippet| diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb index 50f2f4789fa..8ff3222f065 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb @@ -7,7 +7,7 @@ module QA Flow::Login.sign_in Page::Main::Menu.perform do |menu| - menu.go_to_more_dropdown_option(:snippets_link) + menu.go_to_menu_dropdown_option(:snippets_link) end Resource::Snippet.fabricate_via_browser_ui! do |snippet| diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb index 9c7dc868a2e..d922950335f 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb @@ -60,7 +60,7 @@ module QA it "shows correct details of #{snippet_type} including file number" do send(snippet_type) Page::Main::Menu.perform do |menu| - menu.go_to_more_dropdown_option(:snippets_link) + menu.go_to_menu_dropdown_option(:snippets_link) end Page::Dashboard::Snippet::Index.perform do |snippet| diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb index 8617e05f912..7a81318f158 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb @@ -24,7 +24,8 @@ module QA runner.remove_via_api! end - it 'users creates a pipeline which gets processed', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1279' do + it 'users creates a pipeline which gets processed', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1849' do + # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300909 Flow::Login.sign_in Resource::Repository::Commit.fabricate_via_api! do |commit| @@ -47,7 +48,7 @@ module QA - echo 'FAILURE' - exit 1 - test-tags: + test-tags-mismatch: tags: - invalid script: echo 'NOOP' @@ -70,7 +71,7 @@ module QA { 'test-success': :passed, 'test-failure': :failed, - 'test-tags': :pending, + 'test-tags-mismatch': :pending, 'test-artifacts': :passed }.each do |job, status| Page::Project::Pipeline::Show.perform do |pipeline| diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb index 7a71d1cfbaf..9131cad7244 100644 --- a/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/container_registry_spec.rb @@ -30,6 +30,14 @@ module QA DOCKER_TLS_CERTDIR: "/certs" DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client" + before_script: + - | + echo "Waiting for docker to start..." + for i in $(seq 1 30) + do + docker info && break + sleep 1s + done script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $IMAGE_TAG . diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb index fb019290d4c..9c00f1f6d17 100644 --- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb @@ -3,7 +3,7 @@ require 'securerandom' module QA - RSpec.describe 'Package', :orchestrated, :packages do + RSpec.describe 'Package', :orchestrated, :packages, :reliable do describe 'Maven Repository' do include Runtime::Fixtures @@ -44,7 +44,7 @@ module QA runner.name = "qa-runner-#{Time.now.to_i}" runner.tags = ["runner-for-#{project.group.name}"] runner.executor = :docker - runner.token = project.group.sandbox.runners_token + runner.token = project.group.runners_token end end diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb index 4d714affd65..c4bfaacca11 100644 --- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Package', :orchestrated, :packages do + RSpec.describe 'Package', :orchestrated, :packages, :reliable do describe 'npm registry' do include Runtime::Fixtures @@ -37,7 +37,7 @@ module QA runner.name = "qa-runner-#{Time.now.to_i}" runner.tags = ["runner-for-#{project.group.name}"] runner.executor = :docker - runner.token = project.group.sandbox.runners_token + runner.token = project.group.runners_token end end diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb index 3db5b9671d9..daf41f1c6ab 100644 --- a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb @@ -31,9 +31,9 @@ module QA let!(:runner) do Resource::Runner.fabricate! do |runner| runner.name = "qa-runner-#{Time.now.to_i}" - runner.tags = ["runner-for-#{project.group.sandbox.name}"] + runner.tags = ["runner-for-#{project.group.name}"] runner.executor = :docker - runner.token = project.group.sandbox.runners_token + runner.token = project.group.runners_token end end @@ -69,7 +69,7 @@ module QA only: - "#{project.default_branch}" tags: - - "runner-for-#{project.group.sandbox.name}" + - "runner-for-#{project.group.name}" YAML } ] @@ -128,7 +128,7 @@ module QA only: - "#{another_project.default_branch}" tags: - - "runner-for-#{project.group.sandbox.name}" + - "runner-for-#{project.group.name}" YAML } ] @@ -145,7 +145,7 @@ module QA expect(job).to be_successful(timeout: 800) end - project.group.sandbox.visit! + project.group.visit! Page::Group::Menu.perform(&:go_to_group_packages) diff --git a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb index 2cb2ea2d636..1502e1ab924 100644 --- a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true module QA - RSpec.describe 'Release', :smoke, :runner do + RSpec.describe 'Release', :runner do + # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300906 describe 'Pages' do let!(:project) do Resource::Project.fabricate_via_api! do |project| diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb index fe2d821576b..2538f249010 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb @@ -18,7 +18,7 @@ module QA end where(:template) do - %w[rails spring express] + %w[express] end with_them do @@ -45,7 +45,7 @@ module QA Flow::Login.sign_in end - it 'works with Auto DevOps', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/240946', type: :flaky } do + it 'works with Auto DevOps' do %w[build code_quality test].each do |job| pipeline.visit! diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb index e2cf5c5b195..1dcc02095f6 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb @@ -81,11 +81,11 @@ module QA job.click_element(:pipeline_path) end - Page::Project::Menu.perform(&:go_to_operations_environments) - Page::Project::Operations::Environments::Index.perform do |index| + Page::Project::Menu.perform(&:go_to_deployments_environments) + Page::Project::Deployments::Environments::Index.perform do |index| index.click_environment_link('production') end - Page::Project::Operations::Environments::Show.perform do |show| + Page::Project::Deployments::Environments::Show.perform do |show| show.view_deployment do expect(page).to have_content('Hello World!') expect(page).to have_content('you_can_see_this_variable') @@ -115,7 +115,7 @@ module QA end end - it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1277' do + it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1847' do Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform do |pipeline| diff --git a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb index 09fbbf5adc5..1803b4b16de 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb @@ -26,9 +26,9 @@ module QA k8s_cluster.cluster = cluster end.project.visit! - Page::Project::Menu.perform(&:go_to_operations_kubernetes) + Page::Project::Menu.perform(&:go_to_infrastructure_kubernetes) - Page::Project::Operations::Kubernetes::Index.perform do |index| + Page::Project::Infrastructure::Kubernetes::Index.perform do |index| expect(index).to have_cluster(cluster) end end diff --git a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb index 94df408f9aa..1511f74c883 100644 --- a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb +++ b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb @@ -17,9 +17,9 @@ module QA end it 'duplicates to create dashboard to custom', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/871' do - Page::Project::Menu.perform(&:go_to_operations_metrics) + Page::Project::Menu.perform(&:go_to_monitor_metrics) - Page::Project::Operations::Metrics::Show.perform do |on_dashboard| + Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| on_dashboard.duplicate_dashboard expect(on_dashboard).to have_metrics @@ -28,9 +28,9 @@ module QA end it 'verifies data on filtered deployed environment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/874' do - Page::Project::Menu.perform(&:go_to_operations_metrics) + Page::Project::Menu.perform(&:go_to_monitor_metrics) - Page::Project::Operations::Metrics::Show.perform do |on_dashboard| + Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| on_dashboard.filter_environment expect(on_dashboard).to have_metrics @@ -38,9 +38,9 @@ module QA end it 'filters using the quick range', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/873' do - Page::Project::Menu.perform(&:go_to_operations_metrics) + Page::Project::Menu.perform(&:go_to_monitor_metrics) - Page::Project::Operations::Metrics::Show.perform do |on_dashboard| + Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| on_dashboard.show_last('30 minutes') expect(on_dashboard).to have_metrics @@ -53,13 +53,13 @@ module QA end it 'observes cluster health graph', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/920' do - Page::Project::Menu.perform(&:go_to_operations_kubernetes) + Page::Project::Menu.perform(&:go_to_infrastructure_kubernetes) - Page::Project::Operations::Kubernetes::Index.perform do |cluster_list| + Page::Project::Infrastructure::Kubernetes::Index.perform do |cluster_list| cluster_list.click_on_cluster(@cluster) end - Page::Project::Operations::Kubernetes::Show.perform do |cluster_panel| + Page::Project::Infrastructure::Kubernetes::Show.perform do |cluster_panel| cluster_panel.open_health cluster_panel.wait_for_cluster_health end @@ -78,9 +78,9 @@ module QA push.new_branch = false end - Page::Project::Menu.perform(&:go_to_operations_metrics) + Page::Project::Menu.perform(&:go_to_monitor_metrics) - Page::Project::Operations::Metrics::Show.perform do |dashboard| + Page::Project::Monitor::Metrics::Show.perform do |dashboard| dashboard.select_dashboard('templating.yml') expect(dashboard).to have_template_metric('CPU usage GitLab Runner') @@ -101,9 +101,9 @@ module QA metrics_panel.add_custom_metric end - Page::Project::Menu.perform(&:go_to_operations_metrics) + Page::Project::Menu.perform(&:go_to_monitor_metrics) - Page::Project::Operations::Metrics::Show.perform do |on_dashboard| + Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| expect(on_dashboard).to have_custom_metric('HTTP Requests Total') end end @@ -116,9 +116,9 @@ module QA metrics_panel.edit_custom_metric end - Page::Project::Menu.perform(&:go_to_operations_metrics) + Page::Project::Menu.perform(&:go_to_monitor_metrics) - Page::Project::Operations::Metrics::Show.perform do |on_dashboard| + Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| expect(on_dashboard).to have_custom_metric('Throughput') end end @@ -132,9 +132,9 @@ module QA metrics_panel.delete_custom_metric end - Page::Project::Menu.perform(&:go_to_operations_metrics) + Page::Project::Menu.perform(&:go_to_monitor_metrics) - Page::Project::Operations::Metrics::Show.perform do |on_dashboard| + Page::Project::Monitor::Metrics::Show.perform do |on_dashboard| expect(on_dashboard).not_to have_custom_metric('Throughput') end end diff --git a/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb b/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb index ed0064e8b6f..19e49400d5e 100644 --- a/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb +++ b/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb @@ -17,7 +17,7 @@ module QA %w[ CODE_QUALITY_DISABLED TEST_DISABLED LICENSE_MANAGEMENT_DISABLED SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED - CONTAINER_SCANNING_DISABLED PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED + CONTAINER_SCANNING_DISABLED BROWSER_PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED ].each do |key| Resource::CiVariable.fabricate_via_api! do |resource| resource.project = @project diff --git a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb index 302fec55c53..de425dde6c0 100644 --- a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb +++ b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb @@ -20,7 +20,7 @@ module QA end end - it 'shows results for the original request and AJAX requests', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/478', quarantine: { only: { pipeline: :master }, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/323051', type: :bug } do + it 'shows results for the original request and AJAX requests', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/478', quarantine: { only: { pipeline: :main }, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/323051', type: :bug } do # Issue pages always make AJAX requests Resource::Issue.fabricate_via_browser_ui! do |issue| issue.title = 'Performance bar test' diff --git a/qa/qa/tools/delete_projects.rb b/qa/qa/tools/delete_projects.rb index bb73033e9d7..8a690373a37 100644 --- a/qa/qa/tools/delete_projects.rb +++ b/qa/qa/tools/delete_projects.rb @@ -20,7 +20,7 @@ module QA end def run - STDOUT.puts 'Running...' + $stdout.puts 'Running...' # Fetch group's id group_id = fetch_group_id @@ -30,16 +30,16 @@ module QA # Do not delete projects that are less than 4 days old (for debugging purposes) project_ids = fetch_project_ids(group_id, total_project_pages) - STDOUT.puts "Number of projects to be deleted: #{project_ids.length}" + $stdout.puts "Number of projects to be deleted: #{project_ids.length}" delete_projects(project_ids) unless project_ids.empty? - STDOUT.puts "\nDone" + $stdout.puts "\nDone" end private def delete_projects(project_ids) - STDOUT.puts "Deleting #{project_ids.length} projects..." + $stdout.puts "Deleting #{project_ids.length} projects..." project_ids.each do |project_id| delete_response = delete Runtime::API::Request.new(@api_client, "/projects/#{project_id}").url dot_or_f = delete_response.code.between?(200, 300) ? "\e[32m.\e[0m" : "\e[31mF\e[0m" diff --git a/qa/qa/tools/delete_subgroups.rb b/qa/qa/tools/delete_subgroups.rb index 903f730a030..b9e3ed66013 100644 --- a/qa/qa/tools/delete_subgroups.rb +++ b/qa/qa/tools/delete_subgroups.rb @@ -20,7 +20,7 @@ module QA end def run - STDOUT.puts 'Running...' + $stdout.puts 'Running...' # Fetch group's id group_id = fetch_group_id @@ -29,16 +29,16 @@ module QA total_sub_group_pages = sub_groups_head_response.headers[:x_total_pages] sub_group_ids = fetch_subgroup_ids(group_id, total_sub_group_pages) - STDOUT.puts "Number of Sub Groups not already marked for deletion: #{sub_group_ids.length}" + $stdout.puts "Number of Sub Groups not already marked for deletion: #{sub_group_ids.length}" delete_subgroups(sub_group_ids) unless sub_group_ids.empty? - STDOUT.puts "\nDone" + $stdout.puts "\nDone" end private def delete_subgroups(sub_group_ids) - STDOUT.puts "Deleting #{sub_group_ids.length} subgroups..." + $stdout.puts "Deleting #{sub_group_ids.length} subgroups..." sub_group_ids.each do |subgroup_id| delete_response = delete Runtime::API::Request.new(@api_client, "/groups/#{subgroup_id}").url dot_or_f = delete_response.code == 202 ? "\e[32m.\e[0m" : "\e[31mF\e[0m" diff --git a/qa/qa/tools/delete_test_ssh_keys.rb b/qa/qa/tools/delete_test_ssh_keys.rb index 953e9fc63d1..dea6930de1e 100644 --- a/qa/qa/tools/delete_test_ssh_keys.rb +++ b/qa/qa/tools/delete_test_ssh_keys.rb @@ -30,18 +30,18 @@ module QA end def run - STDOUT.puts 'Running...' + $stdout.puts 'Running...' keys_head_response = head Runtime::API::Request.new(@api_client, "/user/keys", per_page: ITEMS_PER_PAGE).url total_pages = keys_head_response.headers[:x_total_pages] test_ssh_key_ids = fetch_test_ssh_key_ids(total_pages) - STDOUT.puts "Number of test ssh keys to be deleted: #{test_ssh_key_ids.length}" + $stdout.puts "Number of test ssh keys to be deleted: #{test_ssh_key_ids.length}" return if dry_run? delete_ssh_keys(test_ssh_key_ids) unless test_ssh_key_ids.empty? - STDOUT.puts "\nDone" + $stdout.puts "\nDone" end private @@ -50,7 +50,7 @@ module QA alias_method :dry_run?, :dry_run def delete_ssh_keys(ssh_key_ids) - STDOUT.puts "Deleting #{ssh_key_ids.length} ssh keys..." + $stdout.puts "Deleting #{ssh_key_ids.length} ssh keys..." ssh_key_ids.each do |key_id| delete_response = delete Runtime::API::Request.new(@api_client, "/user/keys/#{key_id}").url dot_or_f = delete_response.code == 204 ? "\e[32m.\e[0m" : "\e[31mF\e[0m" diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb index 546f7e7cdca..ec1aa20c3b8 100644 --- a/qa/qa/tools/generate_perf_testdata.rb +++ b/qa/qa/tools/generate_perf_testdata.rb @@ -26,7 +26,7 @@ module QA end def all - STDOUT.puts 'Running...' + $stdout.puts 'Running...' group_id = create_group create_project(group_id) @@ -50,23 +50,23 @@ module QA end threads_arr.each(&:join) - STDOUT.puts "\nURLs: #{@urls}" + $stdout.puts "\nURLs: #{@urls}" File.open("urls.yml", "w") { |file| file.puts @urls.stringify_keys.to_yaml } - STDOUT.puts "\nDone" + $stdout.puts "\nDone" end def create_group group_search_response = create_a_group_api_req(@group_name, @visibility) group = JSON.parse(group_search_response.body) @urls[:group_page] = group["web_url"] - STDOUT.puts "Created a group: #{@urls[:group_page]}" + $stdout.puts "Created a group: #{@urls[:group_page]}" group["id"] end def create_project(group_id) create_project_response = create_a_project_api_req(@project_name, group_id, @visibility) @urls[:project_page] = JSON.parse(create_project_response.body)["web_url"] - STDOUT.puts "Created a project: #{@urls[:project_page]}" + $stdout.puts "Created a project: #{@urls[:project_page]}" end def create_many_issues @@ -74,7 +74,7 @@ module QA create_an_issue_api_req("#{@group_name}%2F#{@project_name}", "issue#{i}", "desc#{i}") end @urls[:issues_list_page] = @urls[:project_page] + "/issues" - STDOUT.puts "Created many issues: #{@urls[:issues_list_page]}" + $stdout.puts "Created many issues: #{@urls[:issues_list_page]}" end def create_many_todos @@ -82,7 +82,7 @@ module QA create_a_todo_api_req("#{@group_name}%2F#{@project_name}", "#{i + 1}") end @urls[:todos_page] = ENV['GITLAB_ADDRESS'] + "/dashboard/todos" - STDOUT.puts "Created many todos: #{@urls[:todos_page]}" + $stdout.puts "Created many todos: #{@urls[:todos_page]}" end def create_many_labels @@ -90,7 +90,7 @@ module QA create_a_label_api_req("#{@group_name}%2F#{@project_name}", "label#{i}", "#{Faker::Color.hex_color}") end @urls[:labels_page] = @urls[:project_page] + "/labels" - STDOUT.puts "Created many labels: #{@urls[:labels_page]}" + $stdout.puts "Created many labels: #{@urls[:labels_page]}" end def create_many_merge_requests @@ -98,7 +98,7 @@ module QA create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "branch#{i}", Runtime::Env.default_branch, "MR#{i}") end @urls[:mr_list_page] = @urls[:project_page] + "/merge_requests" - STDOUT.puts "Created many MRs: #{@urls[:mr_list_page]}" + $stdout.puts "Created many MRs: #{@urls[:mr_list_page]}" end def create_many_new_files @@ -109,7 +109,7 @@ module QA end @urls[:files_page] = @urls[:project_page] + "/tree/#{Runtime::Env.default_branch}" - STDOUT.puts "Added many new files: #{@urls[:files_page]}" + $stdout.puts "Added many new files: #{@urls[:files_page]}" end def create_many_branches @@ -117,7 +117,7 @@ module QA create_a_branch_api_req("branch#{i}", "#{@group_name}%2F#{@project_name}") end @urls[:branches_page] = @urls[:project_page] + "/-/branches" - STDOUT.puts "Created many branches: #{@urls[:branches_page]}" + $stdout.puts "Created many branches: #{@urls[:branches_page]}" end def create_an_issue_with_many_discussions @@ -130,7 +130,7 @@ module QA # Add description and labels update_an_issue_api_req("#{@group_name}%2F#{@project_name}", issue_id, "#{Faker::Lorem.sentences(500).join(" ")}", labels_list) @urls[:large_issue] = @urls[:project_page] + "/issues/#{issue_id}" - STDOUT.puts "Created an issue with many discussions: #{@urls[:large_issue]}" + $stdout.puts "Created an issue with many discussions: #{@urls[:large_issue]}" end def create_an_mr_with_large_files_and_many_mr_discussions @@ -178,7 +178,7 @@ module QA create_a_discussion_on_mr_api_req("#{@group_name}%2F#{@project_name}", iid, "Let us discuss") end @urls[:large_mr] = JSON.parse(create_mr_response.body)["web_url"] - STDOUT.puts "Created an MR with many discussions and many very large Files: #{@urls[:large_mr]}" + $stdout.puts "Created an MR with many discussions and many very large Files: #{@urls[:large_mr]}" end def create_diff_note(iid, file_count, line_count, head_sha, start_sha, base_sha, line_type) @@ -205,7 +205,7 @@ module QA 100.times do |i| update_file_api_req(file_name, branch_name, project_path, Faker::Lorem.sentences(5).join(" "), Faker::Lorem.sentences(500).join("\n")) end - STDOUT.puts "Using branch: #{branch_name}, created an MR with many commits: #{@urls[:mr_with_many_commits]}" + $stdout.puts "Using branch: #{branch_name}, created an MR with many commits: #{@urls[:mr_with_many_commits]}" end private diff --git a/qa/qa/tools/revoke_all_personal_access_tokens.rb b/qa/qa/tools/revoke_all_personal_access_tokens.rb index 63a7b0d2d8e..c0a1697fa16 100644 --- a/qa/qa/tools/revoke_all_personal_access_tokens.rb +++ b/qa/qa/tools/revoke_all_personal_access_tokens.rb @@ -12,7 +12,7 @@ module QA def run do_run rescue Net::ReadTimeout - STDOUT.puts 'Net::ReadTimeout during run. Trying again' + $stdout.puts 'Net::ReadTimeout during run. Trying again' run end @@ -23,7 +23,7 @@ module QA raise ArgumentError, "Please provide GITLAB_PASSWORD" unless ENV['GITLAB_PASSWORD'] raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS'] - STDOUT.puts 'Running...' + $stdout.puts 'Running...' Runtime::Browser.visit(ENV['GITLAB_ADDRESS'], Page::Main::Login) Page::Main::Login.perform(&:sign_in_using_credentials) diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb index 0c9643c830b..f4bfd57504e 100644 --- a/qa/spec/spec_helper.rb +++ b/qa/spec/spec_helper.rb @@ -4,6 +4,7 @@ require_relative '../qa' require 'rspec/retry' require 'rspec-parameterized' require 'active_support/core_ext/hash' +require 'active_support/core_ext/object/blank' if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK'] require 'knapsack' @@ -11,8 +12,8 @@ if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK'] end QA::Runtime::Browser.configure! - -QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes) if QA::Runtime::Env.runtime_scenario_attributes +QA::Runtime::AllureReport.configure! +QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes) Dir[::File.join(__dir__, "support/helpers/*.rb")].sort.each { |f| require f } Dir[::File.join(__dir__, "support/matchers/*.rb")].sort.each { |f| require f } diff --git a/qa/spec/specs/helpers/context_selector_spec.rb b/qa/spec/specs/helpers/context_selector_spec.rb index 16b6c6601b1..7792d33dcf9 100644 --- a/qa/spec/specs/helpers/context_selector_spec.rb +++ b/qa/spec/specs/helpers/context_selector_spec.rb @@ -189,9 +189,9 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do it 'runs on default branch pipelines' do group = describe_successfully do - it('runs on master pipeline given a single pipeline', only: { pipeline: :master }) {} - it('runs in master given an array of pipelines', only: { pipeline: [:canary, :master] }) {} - it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] }) {} + it('runs on main pipeline given a single pipeline', only: { pipeline: :main }) {} + it('runs in main given an array of pipelines', only: { pipeline: [:canary, :main] }) {} + it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_main] }) {} end aggregate_failures do diff --git a/qa/spec/support/matchers/eventually_matcher.rb b/qa/spec/support/matchers/eventually_matcher.rb new file mode 100644 index 00000000000..3f0afd6fb54 --- /dev/null +++ b/qa/spec/support/matchers/eventually_matcher.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +# Rspec matcher with build in retry logic +# +# USAGE: +# +# Basic +# expect { Something.that.takes.time.to_appear }.to eventually_eq(expected_result) +# expect { Something.that.takes.time.to_appear }.not_to eventually_eq(expected_result) +# +# With duration and attempts override +# expect { Something.that.takes.time.to_appear }.to eventually_eq(expected_result).within(duration: 10, attempts: 5) + +module Matchers + %w[ + eq + be + include + be_truthy + be_falsey + be_empty + ].each do |op| + RSpec::Matchers.define(:"eventually_#{op}") do |*expected| + chain(:within) do |options = {}| + @duration = options[:duration] + @attempts = options[:attempts] + end + + def supports_block_expectations? + true + end + + match { |actual| wait_and_check(actual, :default_expectation) } + + match_when_negated { |actual| wait_and_check(actual, :when_negated_expectation) } + + description do + "eventually #{operator_msg} #{expected.inspect}" + end + + failure_message do + "#{e}:\nexpected to #{description}, last attempt was #{@result.nil? ? 'nil' : @result}" + end + + failure_message_when_negated do + "#{e}:\nexpected not to #{description}, last attempt was #{@result.nil? ? 'nil' : @result}" + end + + # Execute rspec expectation within retrier + # + # @param [Proc] actual + # @param [Symbol] expectation_name + # @return [Boolean] + def wait_and_check(actual, expectation_name) + QA::Support::Retrier.retry_until( + max_attempts: @attempts, + max_duration: @duration, + sleep_interval: 0.5 + ) do + public_send(expectation_name, actual) + rescue RSpec::Expectations::ExpectationNotMetError, QA::Resource::ApiFabricator::ResourceNotFoundError + false + end + rescue QA::Support::Repeater::RetriesExceededError, QA::Support::Repeater::WaitExceededError => e + @e = e + false + end + + # Execute rspec expectation + # + # @param [Proc] actual + # @return [void] + def default_expectation(actual) + expect(result(&actual)).to public_send(*expectation_args) + end + + # Execute negated rspec expectation + # + # @param [Proc] actual + # @return [void] + def when_negated_expectation(actual) + expect(result(&actual)).not_to public_send(*expectation_args) + end + + # Result of actual block + # + # @return [Object] + def result + @result = yield + end + + # Error message placeholder to indicate waiter did not fail properly + # This message should not appear under normal circumstances since it should + # always be assigned from repeater + # + # @return [String] + def e + @e ||= 'Waiter did not fail!' + end + + # Operator message + # + # @return [String] + def operator_msg + case operator + when 'eq' then 'equal' + else operator + end + end + + # Expect operator + # + # @return [String] + def operator + @operator ||= name.to_s.match(/eventually_(.+?)$/).to_a[1].to_s + end + + # Expectation args + # + # @return [String, Array] + def expectation_args + if operator.include?('truthy') || operator.include?('falsey') || operator.include?('empty') + operator + elsif operator == "include" && expected.is_a?(Array) + [operator, *expected] + else + [operator, expected] + end + end + end + end +end diff --git a/qa/tls_certificates/client/client.crt b/qa/tls_certificates/client/client.crt new file mode 100644 index 00000000000..1bbc49e77d5 --- /dev/null +++ b/qa/tls_certificates/client/client.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFLDCCAxQCAQEwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xGTAXBgNVBAoM +EEdpdExhYiBBdXRob3JpdHkwHhcNMjEwMjEyMDc0NTM0WhcNMzEwMjEwMDc0NTM0 +WjBjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +U2FuIEZyYW5jaXNjbzEWMBQGA1UECgwNR2l0TGFiIENsaWVudDEPMA0GA1UEAwwG +Q2xpZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwZHPYiri29q+ +1qDh6ucjKztoZ9I0gqG4skuYs7jxj7jTOG/+rkYUVB+Eltq0m76rWEEA6OFW5Yze +E+aZOYnLYi31BwhJZI2LHDWUsdDuX936FVr5B7l+nrvARVhhARbfhjFVAljcAmDy +Q+cSgGxgM5de/KhJ0juU25lhe2rCViuJYUsCWny4pN91KhdLJCoPxQRxFDNKG/+k +foacxKFwEtgz185xLgNZdydwhiY5yh4+P6rCMYqKAvnl2w6L/dPQmHasWbH4Gdvk +TGCaxiJ7NBM4Lkv+uZmjHPnBmIdLnt+Yjb/lQmaSPA379yLA4L1n/JucmlUCMpVa +KcJTPEUzUKM4u705XLqsRVH2YmcWAQH8XPw42Llw5T4fAooR+kyMN/zigPNdw7ZC +r+2jW5rk95gb8iEbheVaSrGIAWPqcwrSTcna5Khbzy/najf2oAM87h95D2Fhg7eW +LhoccImcuWEGFrmUGwPwS4Zxr2XeAFim8VVVMx9uGd+5u1AscfZFWKJP3j6FwpDH +L4I7OXFh34INxluxKQ22+PEcIUkbqpGaLZ5U+ZTw8WOy77oflUkAEu1xoEBah+Nf +5dr6b+n+8rSddCk3mDsgpDY5E3Uv8/FH2vxRmTpiq8ObdmMbNo9Qf+CpMNg4CG+v +f96uqj69r3aqG3MEbRdy0UjgdaaeNx0CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA +OvEPqiQx5RuiqdVDzNAGGW6SzGoyehwVL0JkYvwHPZ8gOW4XBGl9Dtnkb3M7GeYq +urZnoplk1uyMnNin2MVA0hRfCwCv7ix56Sh45odpN9scnXsr9I/e6ZfbQB7vFGnV +NDESsOZKzkydameUBTu9yBk7mlV9jA7LpKipe67doptANURZjF8crmCeTvY3b1cF +XbFe31FqvKdXeJgZU99kGUSncSS/1dWxbwyZZDBCqWfDlNh7Om+6RB1cMlQfal5z +hqCYMGBB8YsMY1+l7l8eQDawrZNbs9yE4iqd6FXvss7o02cC1b7moZB+1JhOwwJ1 +wmgXuRiR5ynsb34LjFOicdm4YVmqiqXCW6Pr/DH/pkX8CI3Zu2hjatbgQrkGxXqT +T1O/o48xwa8MBfviy7gkdCrapBkx0ojNLYNW6NTR3LNT4WYEQWOnqkm73Is9aVCy +1doL6zG8chvCxLHXtpEMMPkOKpoWjokdCD4K5HAoIqmR904kOM5jCuETTWm0MD0e +vKeWzck6YDt+zBhCD4k7yqF++d3ufcY2eCmVlwe0wH4srX/e4ni0tBKF25j3xLUA +U+HI7Wa88zBAp3iN3CD/iWu8LBwTUlmRN8l7bi+O/AaKE08KvtzV5hhZ4c1UJa+N +d4txM9tqkwMTFTFkRzduwuaIKB3Gaz1IWcOUJe5oO5M= +-----END CERTIFICATE----- diff --git a/qa/tls_certificates/client/client.csr b/qa/tls_certificates/client/client.csr new file mode 100644 index 00000000000..42c868a381c --- /dev/null +++ b/qa/tls_certificates/client/client.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEqDCCApACAQAwYzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx +FjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFjAUBgNVBAoMDUdpdExhYiBDbGllbnQx +DzANBgNVBAMMBkNsaWVudDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AMGRz2Iq4tvavtag4ernIys7aGfSNIKhuLJLmLO48Y+40zhv/q5GFFQfhJbatJu+ +q1hBAOjhVuWM3hPmmTmJy2It9QcISWSNixw1lLHQ7l/d+hVa+Qe5fp67wEVYYQEW +34YxVQJY3AJg8kPnEoBsYDOXXvyoSdI7lNuZYXtqwlYriWFLAlp8uKTfdSoXSyQq +D8UEcRQzShv/pH6GnMShcBLYM9fOcS4DWXcncIYmOcoePj+qwjGKigL55dsOi/3T +0Jh2rFmx+Bnb5ExgmsYiezQTOC5L/rmZoxz5wZiHS57fmI2/5UJmkjwN+/ciwOC9 +Z/ybnJpVAjKVWinCUzxFM1CjOLu9OVy6rEVR9mJnFgEB/Fz8ONi5cOU+HwKKEfpM +jDf84oDzXcO2Qq/to1ua5PeYG/IhG4XlWkqxiAFj6nMK0k3J2uSoW88v52o39qAD +PO4feQ9hYYO3li4aHHCJnLlhBha5lBsD8EuGca9l3gBYpvFVVTMfbhnfubtQLHH2 +RViiT94+hcKQxy+COzlxYd+CDcZbsSkNtvjxHCFJG6qRmi2eVPmU8PFjsu+6H5VJ +ABLtcaBAWofjX+Xa+m/p/vK0nXQpN5g7IKQ2ORN1L/PxR9r8UZk6YqvDm3ZjGzaP +UH/gqTDYOAhvr3/erqo+va92qhtzBG0XctFI4HWmnjcdAgMBAAGgADANBgkqhkiG +9w0BAQsFAAOCAgEAAPvL+5aGluJVNDfTyQMLKFYl7qsF6cNqwzv+Zd9bB9Suznta +c7pU2EdHO0qsqwpMvRHxdo/2R5gbnAtPLTgQA9I9aL+YjSLH7nZJPieHFt6ffSyz +rGNwXUBgKwhAoTqQpXHLRSHKsPsK3cuz1Oy5dqg1KsfdMVdkUwlErQb0Igjz2xUV +qJJ8Pil0Si4eiXvkWzbIWBcGKMiomTTOqAqr2dJ75siX5ZP6l24RqZItn7RQDuhr +y0KnZgY2SeszQb6u0JETGbKjPmnAeukg35tYFin6Z5dHsO3E9EokOi07bCN5IIw4 +AUNYSKfBIY6HYTVvbm/GsfMSntxO6R0HI6dVQKJRiJ3hrgHduANOJQBHWM7bE24A +v104OVkZ62rPZ/ypxb2Z+A0IP3ngAv6VY5oGHmOMDXtMQb+CBtmMgggyFT1DZ+Kt +AA4H3i6LHqYskv21AdPW4f+br2b69a0Y9XcNrLBkiH2j9itk6Ihw6zZD5Jqj9tDv +ZBMSIIVHlecQND2HFoCM9DCeFFaJlZVNGp9EnERyxIJezcKM0OZ7rFWv7ukbrCov +CyrK4+JLaaOlrOEXTT2ob7StxdGXQps0rOP7A0cxf3mUqfX2F6VWKslpiAa9quuC +5Auqh5vAdY4o0NObx50WRPoFSnOEpqa8yj3hAofl66mulB31VORgN6sH8l4= +-----END CERTIFICATE REQUEST----- diff --git a/qa/tls_certificates/client/client.key b/qa/tls_certificates/client/client.key new file mode 100644 index 00000000000..49d7da54058 --- /dev/null +++ b/qa/tls_certificates/client/client.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKQIBAAKCAgEAwZHPYiri29q+1qDh6ucjKztoZ9I0gqG4skuYs7jxj7jTOG/+ +rkYUVB+Eltq0m76rWEEA6OFW5YzeE+aZOYnLYi31BwhJZI2LHDWUsdDuX936FVr5 +B7l+nrvARVhhARbfhjFVAljcAmDyQ+cSgGxgM5de/KhJ0juU25lhe2rCViuJYUsC +Wny4pN91KhdLJCoPxQRxFDNKG/+kfoacxKFwEtgz185xLgNZdydwhiY5yh4+P6rC +MYqKAvnl2w6L/dPQmHasWbH4GdvkTGCaxiJ7NBM4Lkv+uZmjHPnBmIdLnt+Yjb/l +QmaSPA379yLA4L1n/JucmlUCMpVaKcJTPEUzUKM4u705XLqsRVH2YmcWAQH8XPw4 +2Llw5T4fAooR+kyMN/zigPNdw7ZCr+2jW5rk95gb8iEbheVaSrGIAWPqcwrSTcna +5Khbzy/najf2oAM87h95D2Fhg7eWLhoccImcuWEGFrmUGwPwS4Zxr2XeAFim8VVV +Mx9uGd+5u1AscfZFWKJP3j6FwpDHL4I7OXFh34INxluxKQ22+PEcIUkbqpGaLZ5U ++ZTw8WOy77oflUkAEu1xoEBah+Nf5dr6b+n+8rSddCk3mDsgpDY5E3Uv8/FH2vxR +mTpiq8ObdmMbNo9Qf+CpMNg4CG+vf96uqj69r3aqG3MEbRdy0UjgdaaeNx0CAwEA +AQKCAgB7X98pd6IudQbLr7Eu0nFk/bF28tDLLh6VbX9/lXJJo4jk4OUX2MzeLVSJ +/g29ctKtJolY5T9IgfeOAZ1Jwhzij94rxElbEKhIq5IBn+Q/MDFUaS5ukPk2XP6Y +dFMnqZeAZXMEUvSvg3EGfIIbXngWifVd3jlnCNjA+sraKdqBp7AhVfjDCdl6JH79 +++jFvRVeAo28TVB/9fm3Nz82SJsxN6Ibe5ZBuJrOSlH6/uQ4gfw1AjZR8zYx3Wt2 +qpfpiZbbhlAlvzwd5zxkvfIINTQHpfRZ9c/+JgGD12BgQmOdeHA4cMXEA7JTGqqt +Avaih7Z+mARBjcsfyHe2RAhfUs/4CruJFT1dTWpX+xM7z6dP4ILHNU7OCNXbJhSB +NBQ925lL14yvvmulyRsNgX2ewtpyMRpTjHJlBNnIn1D/zuTV/1LhGyTaj4wrCzmS +4ZLGUp/3CtfsX3m5t+wpaY5qizmVso5kyi/DkTH5HY3uoccv9iZHtvDehnDRiW4+ +Zk/B4ogna7jY/KKKKfef7P06BYP/2VIsKKGtgvp2uln13/ouT2eiWAhON8r4Kvee +miTAbiZGM345g/u461PHpMRU7n7Dz4QgAoRdjw6RyOsgBBDcLj1fOfhMWe8aA2ri +TV39ws/ZNh7tfBkkFemu1IxH95P0vswm2JvwCGV7QfZ4Oa+rYQKCAQEA30ukkYaP +1oTiIBaXP2WeO05pmB2LfYzGswFCe+f7PvNt8MoX9OylLYDHRt1pouMjO10gseSS +7dQeKzld7ZTx5AdTyvnY+/AGMuUnKeRz34pr0qYCsQ1It4lwfJijOiGGv9F7LFmm +mXra1KCPJ0pwTMmHY/f6SRIJkz1xt56zVF+i58wPjLI1WyBErSJfR5iB70dQ8jN8 +HkMrYKHwzn+I5vY0zlb9KX4EcV/XVaMcf5oRbFIJd02ZP3LaTxGevsvxndhGsBQo +FFUbdbqRfdSR+5Ngk6/dytkGKZtiYliJ4SiYBC9fYq5SSxqQNXzmVbf7izYqD94V +2Eamqn9AtQIMFQKCAQEA3eubxxspcP4T8uHwdfnF8eafxvx8Fvd0jzl7CwkkFux3 +mXMTXRvZnOWvIwfpmBk8DkVbQDhxDmp1DoAdSDr2Q1QiGGMEjLBDWC/p42Y3HQif +7u1xwQRJgLQFLmppDdSPZfWQ8H2h5ylKL15C9wzNInv5pvu0xnQjHLnrE4+Zti1B +jfhdKhw4ZFwbAYj2rnKCDJNyaQUfwG1mfNfPLkoXck5nuxuasQ0H43bCtADada0+ +QlhQ1nb1YButnx3mMOtMEK9TZLQEyYW0jOjrfo5KuCU5YbDfxWQm7/+KYFp33vLQ +IyzWrjrzd0POf1Kfu9FbIqw2V53xlSX0Qst22bJY6QKCAQEAhcBxmxnXHtAKAt6F +Slw8I5ocdhl8bH/epWqjwER8ooB94jWrk/IMHu18cF4/4GnduLlX1DbuK7dbOtjq +Al2tZsFc18BA0Og9Tk8k3lsRbV0kqND328XxQL76uidT3oYmiM+Z0D8DI/wLCEIE +fayBB/3PM3peWVaMlb3AWBSfpnKCygXZapV0kFkLyglEuUYIzqMRQYLFXfsuCHv4 +Gjkab/4aM1631hq93otiGNHTSDupJBEfym6Y1QCe863CQNc4qyvZa68nMsan5CUU +8SJbLy5gMxas68yDfHiuven67Pu70wXtRNbWRFZs+x0Ne1rxOboAB/EndJ0dSBNh +Vwsa4QKCAQEA3AjECAKycEo71VKYbSEeVt7oBRBKqSrp8yh3C1Yg5mnHm+oxhNwc +RCioIf+yaRB8L1otQ9uynSyIq7vzTK7JhbBhrfRfim8qFsJLESFD/BGVIf1kEJED +oAzeJktzpjbfh6SX9Rtb8CtMVvMLSpDyxAJQYnSnpS15sv3USyzSp4LvwKhFF3+r +mjaIwFjg3c7Di1yWz/I4rT7Lo3UHA0qLPNbomuif1HSrIambG4bNFGiVloqifEKu +wIAxAddPaamjXde4w9yJ8pYTkrNO68iB5VtjLa2F8d1/je69cRPCTthJ7taCdXYV ++GbO1AdEQaEuz44Yw37jDZL4QVIjoW3oIQKCAQBnNlJWmPBAYYcMeJpzssZkGTVM +cmIgsSx8a6IUmtNMw5ypk1e7eju87c3aGx9F+ZYBVpLsfYePt9xErH2pyR6q93jF +NwWFzoYHxqpO+FYU6Xow0aafqwndyqxZDgnpAK8TijD6XDyshTLnUQjEgut81jZ4 +ywhnlIoosn4jpESzbrSeLwvK/9RTp+1scdo8oSyeHKknb2wVq6bcs4Mk1jN9rjcM +M/NKlrozolwzkDEEx6zhCCI76GgYqawNiCAq4VjD6EQaQpB1VHe2vF93TEgeLuVE +rsKyqU9AYxECwVg8Ufyv4b1T1djh0XlL9shVNJofXP6kygCStQa6Bmnhx01O +-----END RSA PRIVATE KEY----- diff --git a/qa/tls_certificates/client/client.pem b/qa/tls_certificates/client/client.pem new file mode 100644 index 00000000000..ebca1a9920d --- /dev/null +++ b/qa/tls_certificates/client/client.pem @@ -0,0 +1,113 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIFLDCCAxQCAQEwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UEBhMCVVMxEzARBgNV +BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xGTAXBgNVBAoM +EEdpdExhYiBBdXRob3JpdHkwHhcNMjEwMjEyMDc0NTM0WhcNMzEwMjEwMDc0NTM0 +WjBjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +U2FuIEZyYW5jaXNjbzEWMBQGA1UECgwNR2l0TGFiIENsaWVudDEPMA0GA1UEAwwG +Q2xpZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwZHPYiri29q+ +1qDh6ucjKztoZ9I0gqG4skuYs7jxj7jTOG/+rkYUVB+Eltq0m76rWEEA6OFW5Yze +E+aZOYnLYi31BwhJZI2LHDWUsdDuX936FVr5B7l+nrvARVhhARbfhjFVAljcAmDy +Q+cSgGxgM5de/KhJ0juU25lhe2rCViuJYUsCWny4pN91KhdLJCoPxQRxFDNKG/+k +foacxKFwEtgz185xLgNZdydwhiY5yh4+P6rCMYqKAvnl2w6L/dPQmHasWbH4Gdvk +TGCaxiJ7NBM4Lkv+uZmjHPnBmIdLnt+Yjb/lQmaSPA379yLA4L1n/JucmlUCMpVa +KcJTPEUzUKM4u705XLqsRVH2YmcWAQH8XPw42Llw5T4fAooR+kyMN/zigPNdw7ZC +r+2jW5rk95gb8iEbheVaSrGIAWPqcwrSTcna5Khbzy/najf2oAM87h95D2Fhg7eW +LhoccImcuWEGFrmUGwPwS4Zxr2XeAFim8VVVMx9uGd+5u1AscfZFWKJP3j6FwpDH +L4I7OXFh34INxluxKQ22+PEcIUkbqpGaLZ5U+ZTw8WOy77oflUkAEu1xoEBah+Nf +5dr6b+n+8rSddCk3mDsgpDY5E3Uv8/FH2vxRmTpiq8ObdmMbNo9Qf+CpMNg4CG+v +f96uqj69r3aqG3MEbRdy0UjgdaaeNx0CAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA +OvEPqiQx5RuiqdVDzNAGGW6SzGoyehwVL0JkYvwHPZ8gOW4XBGl9Dtnkb3M7GeYq +urZnoplk1uyMnNin2MVA0hRfCwCv7ix56Sh45odpN9scnXsr9I/e6ZfbQB7vFGnV +NDESsOZKzkydameUBTu9yBk7mlV9jA7LpKipe67doptANURZjF8crmCeTvY3b1cF +XbFe31FqvKdXeJgZU99kGUSncSS/1dWxbwyZZDBCqWfDlNh7Om+6RB1cMlQfal5z +hqCYMGBB8YsMY1+l7l8eQDawrZNbs9yE4iqd6FXvss7o02cC1b7moZB+1JhOwwJ1 +wmgXuRiR5ynsb34LjFOicdm4YVmqiqXCW6Pr/DH/pkX8CI3Zu2hjatbgQrkGxXqT +T1O/o48xwa8MBfviy7gkdCrapBkx0ojNLYNW6NTR3LNT4WYEQWOnqkm73Is9aVCy +1doL6zG8chvCxLHXtpEMMPkOKpoWjokdCD4K5HAoIqmR904kOM5jCuETTWm0MD0e +vKeWzck6YDt+zBhCD4k7yqF++d3ufcY2eCmVlwe0wH4srX/e4ni0tBKF25j3xLUA +U+HI7Wa88zBAp3iN3CD/iWu8LBwTUlmRN8l7bi+O/AaKE08KvtzV5hhZ4c1UJa+N +d4txM9tqkwMTFTFkRzduwuaIKB3Gaz1IWcOUJe5oO5M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFizCCA3OgAwIBAgIUJBX+SiNuqUYjf33EuMObynTcKx0wDQYJKoZIhvcNAQEL +BQAwVTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM +DVNhbiBGcmFuY2lzY28xGTAXBgNVBAoMEEdpdExhYiBBdXRob3JpdHkwHhcNMjEw +MjExMDYyMTUzWhcNMzEwMjA5MDYyMTUzWjBVMQswCQYDVQQGEwJVUzETMBEGA1UE +CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQ +R2l0TGFiIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ALxpL/dfJwhIWGYK93ovIVj+gqvJI58Sga7eWlp2LpuFQZETjJBA79R0gcwr42ph +ch1BuxoxkYizM8sqIyFa5aW8SCWmO+IQzedKWZv+UWZg6pG+Fzyp6GO1wmXZdeXw +xRiXp2qV+rqA8DaL2g1c2u6TB/mcfNTrfsSP3045yQW+4mdNx/g4wBf0dMpHe5DJ +5jIvowa2O0kesq1UQ1eM9IMNSwW8fMQenV+F41LWE1NO726ksglih9TQjAIrlX6I +XVmw0lgYegt2G+YQJ68nf2UmvK+C0KqzTZgqmzNMQnuSiJXMnlZvlgdLXTyTWCuq +tyxp3+Z2Wshk/Cghic2MCm2XwWBIqYGu+20qoPM61c3Rk5++2VOcajD1yCYxVtM2 +akVP/e9arlCdi/CtJh3qvOlj9Uhs6a1UR/ZngpPLOa3r4JazZc04pK7q3ZynmoUL +oDPF9AKOikvhYKxTYsgZ65VhI3myTBjQFk9qX++z2HF9UImGblqUtckn3eIoI8n2 +wd4pO/OFeFSXpR7jMywCwXTpC8yTTbuVzHEz8H83/qtsbjtw961g4kb8Vzh1zy73 +PFiJNI7hZlP1I5dqNTOAv+GnwiSnF28i7xbdkIfmjYqwcwGhAO7rjifq8ygBH3sF +0I/6dnw4BvNlSgSJlJ1+2eH1uiaikpuOGtQAttz536dNAgMBAAGjUzBRMB0GA1Ud +DgQWBBQSNZ46Xu4rfGVIPIQJpduWHJ+AQjAfBgNVHSMEGDAWgBQSNZ46Xu4rfGVI +PIQJpduWHJ+AQjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQC1 +4REbDKF1tdYeCxpmQHXLHu7OkrgKIea6eKxf8mI+ZsJA4iNr3aiZYU5Wm+uAq3mK +x6mrQRaqoo6JNbie5Tw8fU2c71EO4t3vwB7YOsBtcV0YrMtg316UE0lk+6kL0TRD +tV7dAGCB3wXZVLPolC26/kecc258p6h4rCJ8Gi6FsIKGBisTFk3QOdLG3DQNulPF +2bZaJjs/6HqLL+QMdChUfJP3i71LdNxzwXNPbjJ3fm5f9RNeOcWo6oI2fkQArl2i +vcP/QtuqeOoJusbeL9zaF/EFlOggjkEtzFWCB05d6J7dMKYp5Lg4eMZQHPw6ycdk +Ek/XTupvBk+8UiXeHLvX6II9zww9+gm3uycPiO/CSPNw4yQBPPGW+30WznbedsuY +m79rxuq50KYvseJSPv7lw8v77ajQbRQzFi4frAFR+A1g8FArLxdpIptI9E+ekmaB +UMhCmi17mEuBtj8Hc3VrokTFtAJV6YNIk1X+Q/zLh4TaR5mm6C/82j/ZvkSm5OX7 +TfaayRWDr7AfDKeG5Amt52BmYncsPUXnOofSz5UkqpeOWr0rKn+A7f2BeUP9R2nY +6DncxYA+yOgU7RpnMBscsW6SkVIMJKFrfeZ1SbvZGRJd4L1PwfeaU+3yEG6oAfMa +CFquw23nWhjvUlnCe9BaUiEtOJ2ruGjdu2sdvXPcnw== +-----END CERTIFICATE----- diff --git a/qa/tls_certificates/client/client.pfx b/qa/tls_certificates/client/client.pfx Binary files differnew file mode 100644 index 00000000000..6931cfe659a --- /dev/null +++ b/qa/tls_certificates/client/client.pfx |