diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
commit | 8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch) | |
tree | 544930fb309b30317ae9797a9683768705d664c4 /qa | |
parent | 4b1de649d0168371549608993deac953eb692019 (diff) | |
download | gitlab-ce-8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca.tar.gz |
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'qa')
120 files changed, 1311 insertions, 302 deletions
diff --git a/qa/.gitignore b/qa/.gitignore index 7bc4effd8a8..2095d5c722c 100644 --- a/qa/.gitignore +++ b/qa/.gitignore @@ -1,4 +1,5 @@ tmp/ .ruby-version +.tool-versions .ruby-gemset urls.yml diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 883c5480689..3ad9b4fed9e 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -39,9 +39,6 @@ GEM adamantium (~> 0.2.0) equalizer (~> 0.0.9) concurrent-ruby (1.1.7) - debase (0.2.4.1) - debase-ruby_core_source (>= 0.10.2) - debase-ruby_core_source (0.10.6) diff-lcs (1.3) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) @@ -88,7 +85,7 @@ GEM byebug (~> 9.1) pry (~> 0.10) public_suffix (4.0.1) - rack (2.2.2) + rack (2.2.3) rack-test (1.1.0) rack (>= 1.0, < 3) rake (12.3.3) @@ -155,7 +152,6 @@ DEPENDENCIES airborne (~> 0.3.4) capybara (~> 3.29.0) capybara-screenshot (~> 1.0.23) - debase (~> 0.2.4.1) faker (~> 1.6, >= 1.6.6) gitlab-qa knapsack (~> 1.17) diff --git a/qa/Rakefile b/qa/Rakefile index 1ecce8fdce9..6bafec2a67d 100644 --- a/qa/Rakefile +++ b/qa/Rakefile @@ -3,6 +3,7 @@ require_relative 'qa/tools/delete_subgroups' require_relative 'qa/tools/generate_perf_testdata' require_relative 'qa/tools/delete_test_ssh_keys' require_relative 'qa/tools/initialize_gitlab_auth' +require_relative 'qa/tools/delete_projects' desc "Revokes all personal access tokens" task :revoke_personal_access_tokens do @@ -51,3 +52,8 @@ desc "Deletes test ssh keys a user" task :delete_test_ssh_keys, [:title_portion, :delete_before, :dry_run] do |t, args| QA::Tools::DeleteTestSSHKeys.new(args).run end + +desc "Deletes projects directly under the provided group" +task :delete_projects do + QA::Tools::DeleteProjects.new.run +end @@ -20,6 +20,7 @@ module QA autoload :User, 'qa/flow/user' autoload :MergeRequest, 'qa/flow/merge_request' autoload :Pipeline, 'qa/flow/pipeline' + autoload :SignUp, 'qa/flow/sign_up' end ## @@ -181,10 +182,14 @@ module QA autoload :Menu, 'qa/page/main/menu' autoload :OAuth, 'qa/page/main/oauth' autoload :TwoFactorAuth, 'qa/page/main/two_factor_auth' - autoload :SignUp, 'qa/page/main/sign_up' autoload :Terms, 'qa/page/main/terms' end + module Registration + autoload :SignUp, 'qa/page/registration/sign_up' + autoload :Welcome, 'qa/page/registration/welcome' + end + module Settings autoload :Common, 'qa/page/settings/common' end @@ -302,14 +307,12 @@ module QA module Services autoload :Jira, 'qa/page/project/settings/services/jira' + 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 :Integrations, 'qa/page/project/settings/integrations' - - module Services - autoload :Prometheus, 'qa/page/project/settings/services/prometheus' - end end module SubMenus @@ -431,6 +434,7 @@ module QA autoload :OutboundRequests, 'qa/page/admin/settings/component/outbound_requests' autoload :AccountAndLimit, 'qa/page/admin/settings/component/account_and_limit' autoload :PerformanceBar, 'qa/page/admin/settings/component/performance_bar' + autoload :SignUpRestrictions, 'qa/page/admin/settings/component/sign_up_restrictions' end end diff --git a/qa/qa/fixtures/auto_devops_rack/Gemfile.lock b/qa/qa/fixtures/auto_devops_rack/Gemfile.lock index 9c7c93fb553..04a85be4b2f 100644 --- a/qa/qa/fixtures/auto_devops_rack/Gemfile.lock +++ b/qa/qa/fixtures/auto_devops_rack/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - rack (2.0.6) + rack (2.2.3) rake (12.3.3) PLATFORMS diff --git a/qa/qa/flow/pipeline.rb b/qa/qa/flow/pipeline.rb index ff23907c081..999f352e834 100644 --- a/qa/qa/flow/pipeline.rb +++ b/qa/qa/flow/pipeline.rb @@ -6,12 +6,17 @@ module QA module_function # In some cases we don't need to wait for anything, blocked, running or pending is acceptable - # Some cases only need pipeline to finish with different condition (completion, success or replication) + # Some cases only we do need pipeline to finish with expected condition (completed, succeeded or replicated) def visit_latest_pipeline(pipeline_condition: nil) Page::Project::Menu.perform(&:click_ci_cd_pipelines) Page::Project::Pipeline::Index.perform(&:"wait_for_latest_pipeline_#{pipeline_condition}") if pipeline_condition Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) end + + def wait_for_latest_pipeline(pipeline_condition:) + Page::Project::Menu.perform(&:click_ci_cd_pipelines) + Page::Project::Pipeline::Index.perform(&:"wait_for_latest_pipeline_#{pipeline_condition}") + end end end end diff --git a/qa/qa/flow/sign_up.rb b/qa/qa/flow/sign_up.rb new file mode 100644 index 00000000000..c790a82d904 --- /dev/null +++ b/qa/qa/flow/sign_up.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module QA + module Flow + module SignUp + module_function + + def sign_up!(user) + Page::Main::Login.perform(&:switch_to_register_page) + + success = Support::Retrier.retry_until(raise_on_failure: false) do + Page::Registration::SignUp.perform do |sign_up| + sign_up.fill_new_user_first_name_field(user.first_name) + sign_up.fill_new_user_last_name_field(user.last_name) + sign_up.fill_new_user_username_field(user.username) + sign_up.fill_new_user_email_field(user.email) + sign_up.fill_new_user_password_field(user.password) + + # Because invisible_captcha would prevent submitting this form + # within 4 seconds, sleep here. This can be removed once we + # implement invisible_captcha as an application setting instead + # of a feature flag, so we can turn it off while testing. + # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/284113 + sleep 5 + + sign_up.click_new_user_register_button + end + + Page::Registration::Welcome.perform(&:click_get_started_button_if_available) + + if user.expect_fabrication_success + Page::Main::Menu.perform(&:has_personal_area?) + else + Page::Main::Menu.perform(&:not_signed_in?) + end + end + + raise "Failed to register the user" unless success + end + end + end +end diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index 0f7e4fbbc97..24a148e9330 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -14,7 +14,7 @@ module QA include Support::Run attr_writer :use_lfs, :gpg_key_id - attr_accessor :env_vars + attr_accessor :env_vars, :default_branch InvalidCredentialsError = Class.new(RuntimeError) @@ -25,6 +25,7 @@ module QA self.env_vars = [%Q{HOME="#{tmp_home_dir}"}] @use_lfs = false @gpg_key_id = nil + @default_branch = Runtime::Env.default_branch end def self.perform(*args) @@ -123,7 +124,7 @@ module QA run_git("git rev-parse --abbrev-ref HEAD").to_s end - def push_changes(branch = 'master', push_options: nil) + def push_changes(branch = @default_branch, push_options: nil) cmd = ['git push'] cmd << push_options_hash_to_string(push_options) cmd << uri @@ -209,6 +210,13 @@ module QA File.delete(netrc_file_path) if File.exist?(netrc_file_path) end + def remote_branches + # This gets the remote branch names + # When executed on a fresh repo it returns the default branch name + + run_git('git --no-pager branch --list --remotes --format="%(refname:lstrip=3)"').to_s.split("\n") + end + private attr_reader :uri, :username, :password, :ssh, :use_lfs diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb index e374c1bf281..fea95fdb84a 100644 --- a/qa/qa/page/admin/overview/users/index.rb +++ b/qa/qa/page/admin/overview/users/index.rb @@ -8,6 +8,7 @@ module QA class Index < QA::Page::Base view 'app/views/admin/users/index.html.haml' do element :user_search_field + element :pending_approval_tab end view 'app/views/admin/users/_user.html.haml' do @@ -22,6 +23,10 @@ module QA find_element(:user_search_field).set(username).send_keys(:return) end + def click_pending_approval_tab + click_element :pending_approval_tab + end + def click_user(username) within_element(:user_row_content, text: username) do click_element(:username_link) diff --git a/qa/qa/page/admin/overview/users/show.rb b/qa/qa/page/admin/overview/users/show.rb index f15ef0492fc..f455bd31d14 100644 --- a/qa/qa/page/admin/overview/users/show.rb +++ b/qa/qa/page/admin/overview/users/show.rb @@ -12,17 +12,32 @@ module QA view 'app/views/admin/users/show.html.haml' do element :confirm_user_button + element :user_id_content + end + + view 'app/views/admin/users/_approve_user.html.haml' do + element :approve_user_button end def click_impersonate_user click_element(:impersonate_user_link) end + def user_id + find_element(:user_id_content).text + end + def confirm_user accept_confirm do click_element :confirm_user_button end end + + def approve_user + accept_confirm do + click_element :approve_user_button + end + end end end end diff --git a/qa/qa/page/admin/settings/component/sign_up_restrictions.rb b/qa/qa/page/admin/settings/component/sign_up_restrictions.rb new file mode 100644 index 00000000000..8c5b4bf506b --- /dev/null +++ b/qa/qa/page/admin/settings/component/sign_up_restrictions.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + module Page + module Admin + module Settings + module Component + class SignUpRestrictions < Page::Base + view 'app/views/admin/application_settings/_signup.html.haml' do + element :require_admin_approval_after_user_signup_checkbox + element :save_changes_button + end + + def require_admin_approval_after_user_signup + check_element :require_admin_approval_after_user_signup_checkbox + click_element :save_changes_button + end + end + end + end + end + end +end diff --git a/qa/qa/page/admin/settings/general.rb b/qa/qa/page/admin/settings/general.rb index 7e35902a778..a2457dded7c 100644 --- a/qa/qa/page/admin/settings/general.rb +++ b/qa/qa/page/admin/settings/general.rb @@ -9,6 +9,7 @@ module QA view 'app/views/admin/application_settings/general.html.haml' do element :account_and_limit_settings_content + element :sign_up_restrictions_settings_content end def expand_account_and_limit(&block) @@ -16,6 +17,12 @@ module QA Component::AccountAndLimit.perform(&block) end end + + def expand_sign_up_restrictions(&block) + expand_content(:sign_up_restrictions_settings_content) do + Component::SignUpRestrictions.perform(&block) + end + end end end end diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index ce4eac7fbc4..00b48dc7fe9 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -228,7 +228,7 @@ module QA def finished_loading_block? wait_for_requests - has_no_css?('.fa-spinner.block-loading', wait: Capybara.default_max_wait_time) + has_no_css?('.gl-spinner', wait: Capybara.default_max_wait_time) end def has_loaded_all_images? diff --git a/qa/qa/page/component/design_management.rb b/qa/qa/page/component/design_management.rb index cccf1cf1a58..1f5620e30c7 100644 --- a/qa/qa/page/component/design_management.rb +++ b/qa/qa/page/component/design_management.rb @@ -108,6 +108,10 @@ module QA has_element?(:design_file_name, text: filename) end + def has_no_design?(filename) + has_no_element?(:design_file_name, text: filename) + end + def has_created_icon? has_element?(:design_status_icon, status: 'file-addition-solid') end diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb index cc39260ce38..03c0811645f 100644 --- a/qa/qa/page/component/issuable/sidebar.rb +++ b/qa/qa/page/component/issuable/sidebar.rb @@ -69,7 +69,7 @@ module QA end end - def has_no_assignee_named?(username) + def has_no_assignee?(username) within_element(:assignee_block) do has_no_text?(username, wait: 120) end diff --git a/qa/qa/page/component/legacy_clone_panel.rb b/qa/qa/page/component/legacy_clone_panel.rb index ebab9fd708c..f15d159a712 100644 --- a/qa/qa/page/component/legacy_clone_panel.rb +++ b/qa/qa/page/component/legacy_clone_panel.rb @@ -12,7 +12,7 @@ module QA base.view 'app/views/shared/_clone_panel.html.haml' do element :clone_dropdown element :clone_options_dropdown, '.clone-options-dropdown' # rubocop:disable QA/ElementWithPattern - element :project_repository_location, 'text_field_tag :project_clone' # rubocop:disable QA/ElementWithPattern + element :clone_url, 'text_field_tag :clone_url' # rubocop:disable QA/ElementWithPattern end end @@ -28,7 +28,7 @@ module QA end def repository_location - Git::Location.new(find('#project_clone').value) + Git::Location.new(find('#clone_url').value) end private diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb index 5ac72d73c78..0454042289b 100644 --- a/qa/qa/page/component/note.rb +++ b/qa/qa/page/component/note.rb @@ -122,13 +122,17 @@ module QA def select_all_activities_filter select_filter_with_text('Show all activity') + + wait_until do + has_no_element?(:discussion_filter_container) && has_element?(:comment_field) + end end def select_comments_only_filter select_filter_with_text('Show comments only') wait_until do - has_no_element?(:system_note_content) + has_no_element?(:discussion_filter_container) && has_no_element?(:system_note_content) end end @@ -145,6 +149,8 @@ module QA click_element :note_dropdown click_element :discussion_menu_item click_element :comment_button + + has_comment?(text) end def toggle_comments(position) diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb index 665b3c34dcc..28b6b3be154 100644 --- a/qa/qa/page/file/show.rb +++ b/qa/qa/page/file/show.rb @@ -46,8 +46,16 @@ module QA has_no_element?(:file_name_content, text: name) end - def has_file_content?(text) - has_element?(:file_content, text: text) + def has_file_content?(file_content, file_number = nil) + if file_number + within_element_by_index(:file_content, file_number - 1) do + has_text?(file_content) + end + else + within_element(:file_content) do + has_text?(file_content) + end + end end end end diff --git a/qa/qa/page/group/members.rb b/qa/qa/page/group/members.rb index 16e447a2be5..87423ae9d75 100644 --- a/qa/qa/page/group/members.rb +++ b/qa/qa/page/group/members.rb @@ -22,12 +22,12 @@ module QA element :group_row end - view 'app/assets/javascripts/vue_shared/components/members/table/role_dropdown.vue' do + view 'app/assets/javascripts/members/components/table/role_dropdown.vue' do element :access_level_dropdown element :access_level_link end - view 'app/assets/javascripts/vue_shared/components/members/action_buttons/remove_member_button.vue' do + view 'app/assets/javascripts/members/components/action_buttons/remove_member_button.vue' do element :delete_member_button end diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb index 88e7121dbe0..5f43cfb49c0 100644 --- a/qa/qa/page/group/new.rb +++ b/qa/qa/page/group/new.rb @@ -7,7 +7,6 @@ module QA view 'app/views/shared/_group_form.html.haml' do element :group_path_field, 'text_field :path' # rubocop:disable QA/ElementWithPattern element :group_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern - element :group_description_field, 'text_area :description' # rubocop:disable QA/ElementWithPattern end view 'app/views/groups/_new_group_fields.html.haml' do @@ -20,10 +19,6 @@ module QA fill_in 'group_name', with: path end - def set_description(description) - fill_in 'group_description', with: description - end - def set_visibility(visibility) choose visibility end diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb index 9c63ddee890..627809dacf2 100644 --- a/qa/qa/page/main/menu.rb +++ b/qa/qa/page/main/menu.rb @@ -93,6 +93,10 @@ module QA has_personal_area?(wait: 0) end + def not_signed_in? + has_no_personal_area? + end + def sign_out retry_until do wait_if_retry_later @@ -129,6 +133,10 @@ module QA has_element?(:user_avatar, wait: wait) end + def has_no_personal_area?(wait: Capybara.default_max_wait_time) + has_no_element?(:user_avatar, wait: wait) + end + def has_admin_area_link?(wait: Capybara.default_max_wait_time) has_element?(:admin_area_link, wait: wait) end diff --git a/qa/qa/page/main/sign_up.rb b/qa/qa/page/main/sign_up.rb deleted file mode 100644 index f8e85798012..00000000000 --- a/qa/qa/page/main/sign_up.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -module QA - module Page - module Main - class SignUp < Page::Base - 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/views/registrations/welcome/show.html.haml' do - element :get_started_button - end - - def sign_up!(user) - signed_in = retry_until(raise_on_failure: false) do - fill_element :new_user_first_name_field, user.first_name - fill_element :new_user_last_name_field, user.last_name - fill_element :new_user_username_field, user.username - fill_element :new_user_email_field, user.email - fill_element :new_user_password_field, user.password - click_element :new_user_register_button if has_element?(:new_user_register_button) - click_element :get_started_button if has_element?(:get_started_button) - - Page::Main::Menu.perform(&:has_personal_area?) - end - - raise "Failed to register and sign in" unless signed_in - end - end - end - end -end - -QA::Page::Main::SignUp.prepend_if_ee('QA::EE::Page::Main::SignUp') diff --git a/qa/qa/page/profile/two_factor_auth.rb b/qa/qa/page/profile/two_factor_auth.rb index 6794825769a..a0dd230d8ab 100644 --- a/qa/qa/page/profile/two_factor_auth.rb +++ b/qa/qa/page/profile/two_factor_auth.rb @@ -14,8 +14,9 @@ module QA element :register_2fa_app_button end - view 'app/views/profiles/two_factor_auths/_codes.html.haml' do + view 'app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue' do element :proceed_button + element :copy_button element :codes_content element :code_content end @@ -43,7 +44,8 @@ module QA code_elements.map { |code_content| code_content.text } end - def click_proceed_button + def click_copy_and_proceed + click_element :copy_button click_element :proceed_button end end diff --git a/qa/qa/page/project/fork/new.rb b/qa/qa/page/project/fork/new.rb index e2f2e9330dd..bbdd4748f5c 100644 --- a/qa/qa/page/project/fork/new.rb +++ b/qa/qa/page/project/fork/new.rb @@ -9,9 +9,17 @@ module QA element :fork_namespace_button end + view 'app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue' do + element :fork_groups_list_search_field + end + def choose_namespace(namespace = Runtime::Namespace.path) click_element(:fork_namespace_button, name: namespace) end + + def search_for_group(group_name) + find_element(:fork_groups_list_search_field).set(group_name) + end end end end diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb index ad1746258ea..6890c7de9f8 100644 --- a/qa/qa/page/project/import/github.rb +++ b/qa/qa/page/project/import/github.rb @@ -12,7 +12,7 @@ module QA element :authenticate_button end - view 'app/assets/javascripts/import_projects/components/provider_repo_table_row.vue' do + view 'app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue' do element :project_import_row element :project_namespace_select element :project_path_field diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb index 64bd62c2b54..e85d10e4eb8 100644 --- a/qa/qa/page/project/issue/index.rb +++ b/qa/qa/page/project/issue/index.rb @@ -79,6 +79,10 @@ module QA def has_issue?(issue) has_element? :issue_container, issue_title: issue.title end + + def has_no_issue?(issue) + has_no_element? :issue_container, issue_title: issue.title + end end end end diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb index f7bd74d1882..db2f5f9b3dc 100644 --- a/qa/qa/page/project/issue/show.rb +++ b/qa/qa/page/project/issue/show.rb @@ -14,7 +14,7 @@ module QA element :remove_related_issue_button end - view 'app/views/shared/issuable/_close_reopen_button.html.haml' do + view 'app/assets/javascripts/issue_show/components/header_actions.vue' do element :close_issue_button element :reopen_issue_button end diff --git a/qa/qa/page/project/operations/metrics/show.rb b/qa/qa/page/project/operations/metrics/show.rb index 35dfd92f119..6e8a52ab2e6 100644 --- a/qa/qa/page/project/operations/metrics/show.rb +++ b/qa/qa/page/project/operations/metrics/show.rb @@ -70,7 +70,7 @@ module QA end end - def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to master branch') + def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to default branch') click_element :actions_menu_dropdown click_on 'Duplicate current dashboard' fill_element :duplicate_dashboard_filename_field, "#{SecureRandom.hex(8)}-#{save_as}" diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb index aff2378330a..0f5a7e8c801 100644 --- a/qa/qa/page/project/pipeline/index.rb +++ b/qa/qa/page/project/pipeline/index.rb @@ -22,15 +22,17 @@ module QA all_elements(:pipeline_url_link, minimum: 1, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME).first.click end - def wait_for_latest_pipeline_success + def wait_for_latest_pipeline_succeeded wait_for_latest_pipeline_status { has_text?('passed') } end - def wait_for_latest_pipeline_completion + def wait_for_latest_pipeline_completed wait_for_latest_pipeline_status { has_text?('passed') || has_text?('failed') } end def wait_for_latest_pipeline_status + wait_until(max_duration: 30, reload: true, sleep_interval: 5) { has_pipeline? } + wait_until(reload: false, max_duration: 360) do within_element_by_index(:pipeline_commit_status, 0) { yield } end @@ -49,6 +51,10 @@ module QA has_element? :pipeline_url_link end + def has_no_pipeline? + has_no_element? :pipeline_url_link + end + def click_run_pipeline_button click_element :run_pipeline_button, Page::Project::Pipeline::New end diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb index b32d099d2b0..7f96b896c1d 100644 --- a/qa/qa/page/project/pipeline/show.rb +++ b/qa/qa/page/project/pipeline/show.rb @@ -72,6 +72,10 @@ module QA has_element? :child_pipeline end + def has_no_child_pipeline? + has_no_element? :child_pipeline + end + def click_job(job_name) click_element(:job_link, text: job_name) end diff --git a/qa/qa/page/project/settings/integrations.rb b/qa/qa/page/project/settings/integrations.rb index e18ff71bcb3..dd676c86486 100644 --- a/qa/qa/page/project/settings/integrations.rb +++ b/qa/qa/page/project/settings/integrations.rb @@ -6,8 +6,8 @@ module QA module Settings class Integrations < QA::Page::Base view 'app/views/shared/integrations/_index.html.haml' do - element :prometheus_link, '{ data: { qa_selector: "#{integration.to_param' # rubocop:disable QA/ElementWithPattern - element :jira_link, '{ data: { qa_selector: "#{integration.to_param' # rubocop:disable QA/ElementWithPattern + element :prometheus_link, 'data: { qa_selector: "#{integration.to_param' # rubocop:disable QA/ElementWithPattern + element :jira_link, 'data: { qa_selector: "#{integration.to_param' # rubocop:disable QA/ElementWithPattern end def click_on_prometheus_integration diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb index 7315bfb76a5..6616921f34c 100644 --- a/qa/qa/page/project/settings/protected_branches.rb +++ b/qa/qa/page/project/settings/protected_branches.rb @@ -58,7 +58,7 @@ module QA allowed[:roles] = Resource::ProtectedBranch::Roles::NO_ONE unless allowed.key?(:roles) within_element(:"allowed_to_#{action}_dropdown") do - click_on allowed[:roles] + click_on allowed[:roles][:description] allowed[:users].each { |user| click_on user.username } if allowed.key?(:users) allowed[:groups].each { |group| click_on group.name } if allowed.key?(:groups) end diff --git a/qa/qa/page/project/settings/services/jenkins.rb b/qa/qa/page/project/settings/services/jenkins.rb new file mode 100644 index 00000000000..3d7da8d0161 --- /dev/null +++ b/qa/qa/page/project/settings/services/jenkins.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Settings + module Services + class Jenkins < QA::Page::Base + view 'app/assets/javascripts/integrations/edit/components/dynamic_field.vue' do + element :jenkins_url_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern + element :project_name_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern + element :username_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern + element :password_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern + end + + view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do + element :save_changes_button + end + + def setup_service_with(jenkins_url:, project_name:) + set_jenkins_url(jenkins_url) + set_project_name(project_name) + set_username('admin') + set_password('password') + click_save_changes_button + end + + private + + def set_jenkins_url(jenkins_url) + fill_element(:jenkins_url_field, jenkins_url) + end + + def set_project_name(project_name) + fill_element(:project_name_field, project_name) + end + + def set_username(username) + fill_element(:username_field, username) + end + + def set_password(password) + fill_element(:password_field, password) + end + + def click_save_changes_button + click_element :save_changes_button + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index 4f0cf55c127..d2c258b90b5 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -34,6 +34,7 @@ module QA view 'app/views/projects/_home_panel.html.haml' do element :forked_from_link element :project_name_content + element :project_id_content end view 'app/views/projects/_files.html.haml' do @@ -157,6 +158,10 @@ module QA find_element(:project_name_content).text end + def project_id + find_element(:project_id_content).text.delete('Project ID: ') + end + def switch_to_branch(branch_name) find_element(:branches_select).click diff --git a/qa/qa/page/project/wiki/show.rb b/qa/qa/page/project/wiki/show.rb index 61b0d202a76..d9e0783a581 100644 --- a/qa/qa/page/project/wiki/show.rb +++ b/qa/qa/page/project/wiki/show.rb @@ -59,6 +59,10 @@ module QA has_element?(:wiki_page_content, content) end + def has_no_content?(content) + has_no_element?(:wiki_page_content, content) + end + def has_no_page? has_element? :create_first_page_link end diff --git a/qa/qa/page/registration/sign_up.rb b/qa/qa/page/registration/sign_up.rb new file mode 100644 index 00000000000..0fb4b466e62 --- /dev/null +++ b/qa/qa/page/registration/sign_up.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module QA + module Page + module Registration + class SignUp < Page::Base + 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/views/registrations/welcome/show.html.haml' do + element :get_started_button + end + + def fill_new_user_first_name_field(first_name) + fill_element :new_user_first_name_field, first_name + end + + def fill_new_user_last_name_field(last_name) + fill_element :new_user_last_name_field, last_name + end + + def fill_new_user_username_field(username) + fill_element :new_user_username_field, username + end + + def fill_new_user_email_field(email) + fill_element :new_user_email_field, email + end + + def fill_new_user_password_field(password) + fill_element :new_user_password_field, password + end + + def click_new_user_register_button + click_element :new_user_register_button if has_element?(:new_user_register_button) + end + end + end + end +end diff --git a/qa/qa/page/registration/welcome.rb b/qa/qa/page/registration/welcome.rb new file mode 100644 index 00000000000..394e94b6414 --- /dev/null +++ b/qa/qa/page/registration/welcome.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module QA + module Page + module Registration + class Welcome < Page::Base + view 'app/views/registrations/welcome/show.html.haml' do + element :get_started_button + end + + def click_get_started_button_if_available + if has_element?(:get_started_button) + Support::Retrier.retry_until do + click_element :get_started_button + has_no_element?(:get_started_button) + end + end + end + end + end + end +end + +QA::Page::Registration::Welcome.prepend_if_ee('QA::EE::Page::Registration::Welcome') diff --git a/qa/qa/resource/events/project.rb b/qa/qa/resource/events/project.rb index 8c97f66c663..0348f2f05f5 100644 --- a/qa/qa/resource/events/project.rb +++ b/qa/qa/resource/events/project.rb @@ -20,7 +20,7 @@ module QA end end - def wait_for_push_new_branch(branch_name = "master") + def wait_for_push_new_branch(branch_name = self.default_branch) QA::Runtime::Logger.debug(%Q[#{self.class.name} - wait_for_push_new_branch with branch_name "#{branch_name}"]) wait_for_event do events(action: 'pushed').any? { |event| event.dig(:push_data, :ref) == branch_name } diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb index 0d2bf9890ea..4ca180373f6 100644 --- a/qa/qa/resource/file.rb +++ b/qa/qa/resource/file.rb @@ -30,7 +30,7 @@ module QA end def branch - @branch ||= "master" + @branch ||= project.default_branch end def fabricate! diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb index 2e29ec9a6a7..135c3dea628 100644 --- a/qa/qa/resource/group.rb +++ b/qa/qa/resource/group.rb @@ -36,7 +36,6 @@ module QA Page::Group::New.perform do |group_new| group_new.set_path(path) - group_new.set_description(description) group_new.set_visibility('Public') group_new.create end diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb index dca8fb6dc6b..ecf25b797a8 100644 --- a/qa/qa/resource/merge_request.rb +++ b/qa/qa/resource/merge_request.rb @@ -34,7 +34,7 @@ module QA attribute :target do Repository::ProjectPush.fabricate! do |resource| resource.project = project - resource.branch_name = 'master' + resource.branch_name = project.default_branch resource.new_branch = @target_new_branch resource.remote_branch = target_branch end @@ -56,7 +56,6 @@ module QA @title = 'QA test - merge request' @description = 'This is a test merge request' @source_branch = "qa-test-feature-#{SecureRandom.hex(8)}" - @target_branch = "master" @assignee = nil @milestone = nil @labels = [] @@ -68,7 +67,7 @@ module QA end def fabricate! - populate(:target, :source) + populate_target_and_source_if_required project.visit! Page::Project::Show.perform(&:new_merge_request) @@ -89,7 +88,7 @@ module QA def fabricate_via_api! resource_web_url(api_get) rescue ResourceNotFoundError - populate(:target, :source) unless @no_preparation + populate_target_and_source_if_required super end @@ -144,6 +143,12 @@ module QA super(api_resource) end + + def populate_target_and_source_if_required + @target_branch ||= project.default_branch + + populate(:target, :source) unless @no_preparation + end end end end diff --git a/qa/qa/resource/merge_request_from_fork.rb b/qa/qa/resource/merge_request_from_fork.rb index d9c86b3b527..b0367df64ed 100644 --- a/qa/qa/resource/merge_request_from_fork.rb +++ b/qa/qa/resource/merge_request_from_fork.rb @@ -28,6 +28,10 @@ module QA Page::Project::Show.perform(&:new_merge_request) Page::MergeRequest::New.perform(&:create_merge_request) end + + def fabricate_via_api! + raise NotImplementedError + end end end end diff --git a/qa/qa/resource/pipeline.rb b/qa/qa/resource/pipeline.rb index a115de3e825..907a6cb8558 100644 --- a/qa/qa/resource/pipeline.rb +++ b/qa/qa/resource/pipeline.rb @@ -22,7 +22,6 @@ module QA attribute :variables def initialize - @ref = 'master' @variables = [] end @@ -34,6 +33,10 @@ module QA Page::Project::Pipeline::New.perform(&:click_run_pipeline_button) end + def ref + project.default_branch + end + def api_get_path "/projects/#{project.id}/pipelines/#{id}" end diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb index 163c0b40bb5..a92f7912b9e 100644 --- a/qa/qa/resource/project.rb +++ b/qa/qa/resource/project.rb @@ -15,7 +15,6 @@ module QA attr_writer :github_personal_access_token attr_writer :github_repository_path - attribute :default_branch attribute :id attribute :name attribute :add_name_uuid @@ -26,6 +25,10 @@ module QA attribute :template_name attribute :import + attribute :default_branch do + api_response[:default_branch] || Runtime::Env.default_branch + end + attribute :group do Group.fabricate! end @@ -200,6 +203,10 @@ 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 diff --git a/qa/qa/resource/protected_branch.rb b/qa/qa/resource/protected_branch.rb index 9b728fc4c24..51ea9d1c5b9 100644 --- a/qa/qa/resource/protected_branch.rb +++ b/qa/qa/resource/protected_branch.rb @@ -8,7 +8,6 @@ module QA attr_accessor :branch_name, :allowed_to_push, :allowed_to_merge, - :protected, :new_branch, :require_code_owner_approval @@ -20,13 +19,14 @@ module QA end attribute :branch do - Repository::ProjectPush.fabricate! do |project_push| - project_push.project = project - project_push.file_name = "new_file-#{SecureRandom.hex(8)}.md" - project_push.commit_message = 'Add new file' - project_push.branch_name = branch_name - project_push.new_branch = true - project_push.remote_branch = branch_name + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.branch = branch_name + commit.start_branch = 'master' + commit.commit_message = 'Add new file' + commit.add_files([ + { file_path: "new_file-#{SecureRandom.hex(8)}.md", content: 'new file' } + ]) end end @@ -39,16 +39,11 @@ module QA @allowed_to_merge = { roles: Resource::ProtectedBranch::Roles::DEVS_AND_MAINTAINERS } - @protected = false - @require_code_owner_approval = true + @require_code_owner_approval = false end def fabricate! - if new_branch - populate(:branch) - - project.wait_for_push_new_branch branch_name - end + populate_new_branch_if_required project.visit! Page::Project::Menu.perform(&:go_to_repository_settings) @@ -67,6 +62,12 @@ module QA end end + def fabricate_via_api! + populate_new_branch_if_required + + super + end + def self.unprotect_via_api!(&block) self.remove_via_api!(&block) end @@ -79,10 +80,49 @@ module QA "/projects/#{project.id}/protected_branches/#{branch_name}" end + def api_post_path + "/projects/#{project.id}/protected_branches" + end + + def api_post_body + { + name: branch_name, + code_owner_approval_required: require_code_owner_approval + } + .merge(allowed_to_push_hash) + .merge(allowed_to_merge_hash) + end + + def allowed_to_push_hash + allowed = {} + allowed.merge({ push_access_level: allowed_to_push[:roles][:access_level] }) if allowed_to_push.key?(:roles) + end + + def allowed_to_merge_hash + allowed = {} + allowed.merge({ merge_access_level: allowed_to_merge[:roles][:access_level] }) if allowed_to_merge.key?(:roles) + end + + def resource_web_url(resource) + super + rescue ResourceURLMissingError + # this particular resource does not expose a web_url property + end + class Roles - NO_ONE = 'No one' - DEVS_AND_MAINTAINERS = 'Developers + Maintainers' - MAINTAINERS = 'Maintainers' + NO_ONE = { description: 'No one', access_level: 0 }.freeze + DEVS_AND_MAINTAINERS = { description: 'Developers + Maintainers', access_level: 30 }.freeze + MAINTAINERS = { description: 'Maintainers', access_level: 40 }.freeze + end + + private + + def populate_new_branch_if_required + return unless new_branch + + populate(:branch) + + project.wait_for_push_new_branch(branch_name) end end end diff --git a/qa/qa/resource/repository/commit.rb b/qa/qa/resource/repository/commit.rb index d15210aa736..f5dba164de6 100644 --- a/qa/qa/resource/repository/commit.rb +++ b/qa/qa/resource/repository/commit.rb @@ -9,7 +9,8 @@ module QA :branch, :commit_message, :file_path, - :sha + :sha, + :start_branch attribute :short_id @@ -80,12 +81,12 @@ module QA def api_post_body { - branch: @branch || "master", + branch: @branch || project.default_branch, author_email: @author_email || Runtime::User.default_email, author_name: @author_name || Runtime::User.username, commit_message: commit_message, actions: actions - } + }.merge(new_branch) end def actions @@ -104,6 +105,14 @@ module QA raise ArgumentError, "Please provide an array of hashes e.g.: [{file_path: 'file1', content: 'foo'}]" end end + + def new_branch + return {} unless start_branch + + { + start_branch: start_branch + } + end end end end diff --git a/qa/qa/resource/repository/project_push.rb b/qa/qa/resource/repository/project_push.rb index c46921ad0c7..ef4873e9483 100644 --- a/qa/qa/resource/repository/project_push.rb +++ b/qa/qa/resource/repository/project_push.rb @@ -23,7 +23,6 @@ module QA @file_name = "file-#{SecureRandom.hex(8)}.txt" @file_content = '# This is test project' @commit_message = "This is a test commit" - @branch_name = 'master' @new_branch = true @project_name = 'project-with-code' @wait_for_push = true @@ -39,6 +38,8 @@ module QA end def fabricate! + @branch_name ||= project.default_branch + super project.wait_for_push @commit_message if @wait_for_push end diff --git a/qa/qa/resource/repository/push.rb b/qa/qa/resource/repository/push.rb index 5266f8b9bea..f5b6040d927 100644 --- a/qa/qa/resource/repository/push.rb +++ b/qa/qa/resource/repository/push.rb @@ -17,7 +17,6 @@ module QA @file_name = "file-#{SecureRandom.hex(8)}.txt" @file_content = '# This is test file' @commit_message = "This is a test commit" - @branch_name = 'master' @new_branch = true @repository_http_uri = "" @ssh_key = nil @@ -78,6 +77,8 @@ module QA @output += repository.clone repository.configure_identity(name, email) + @branch_name ||= default_branch(repository) + @output += repository.checkout(branch_name, new_branch: new_branch) if @tag_name @@ -105,6 +106,10 @@ module QA private + def default_branch(repository) + repository.remote_branches.last || Runtime::Env.default_branch + end + def commit_to(repository) @gpg_key_id.nil? ? repository.commit(@commit_message) : repository.commit_with_gpg(@commit_message) end diff --git a/qa/qa/resource/repository/wiki_push.rb b/qa/qa/resource/repository/wiki_push.rb index edf76c7cd78..f188e52c969 100644 --- a/qa/qa/resource/repository/wiki_push.rb +++ b/qa/qa/resource/repository/wiki_push.rb @@ -12,11 +12,14 @@ module QA end end + def branch_name + @branch_name ||= wiki.project.default_branch + end + def initialize @file_name = 'Home.md' @file_content = 'This line was created using git push' @commit_message = 'Updating using git push' - @branch_name = 'master' @new_branch = false end diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb index b351d92092f..ae183d55d89 100644 --- a/qa/qa/resource/sandbox.rb +++ b/qa/qa/resource/sandbox.rb @@ -31,7 +31,6 @@ module QA Page::Group::New.perform do |group| group.set_path(path) - group.set_description('GitLab QA Sandbox Group') group.set_visibility('Public') group.create end @@ -76,6 +75,19 @@ module QA visibility: 'public' } end + + def api_put_path + "/groups/#{id}" + end + + def update_group_setting(group_setting:, value:) + put_body = { "#{group_setting}": value } + response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body + + unless response.code == HTTP_STATUS_OK + raise ResourceUpdateFailedError, "Could not update #{group_setting} to #{value}. Request returned (#{response.code}): `#{response}`." + end + end end end end diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb index ca30ff12480..f95a68918dc 100644 --- a/qa/qa/resource/user.rb +++ b/qa/qa/resource/user.rb @@ -7,7 +7,7 @@ module QA class User < Base attr_reader :unique_id attr_writer :username, :password - attr_accessor :admin, :provider, :extern_uid + attr_accessor :admin, :provider, :extern_uid, :expect_fabrication_success attribute :id attribute :name @@ -18,6 +18,7 @@ module QA def initialize @admin = false @unique_id = SecureRandom.hex(8) + @expect_fabrication_success = true end def admin? @@ -74,12 +75,7 @@ module QA login.sign_in_using_credentials(user: self) end else - Page::Main::Login.perform do |login| - login.switch_to_register_page - end - Page::Main::SignUp.perform do |signup| - signup.sign_up!(self) - end + Flow::SignUp.sign_up!(self) end end diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb index 2bd0c6ae00e..a3fce8bff88 100644 --- a/qa/qa/runtime/browser.rb +++ b/qa/qa/runtime/browser.rb @@ -98,6 +98,10 @@ module QA # Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab/issues/4252 options.add_argument("disable-dev-shm-usage") if QA::Runtime::Env.running_in_ci? + + # Specify the user-agent to allow challenges to be bypassed + # See https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11938 + options.add_argument("user-agent=#{QA::Runtime::Env.user_agent}") if QA::Runtime::Env.user_agent end # Use the same profile on QA runs if CHROME_REUSE_PROFILE is true. diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index 4c4dd416093..24be4e4f978 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -63,7 +63,7 @@ module QA end def pipeline_from_project_name - ci_project_name.to_s.start_with?('gitlab-qa') ? 'master' : ci_project_name + ci_project_name.to_s.start_with?('gitlab-qa') ? Runtime::Env.default_branch : ci_project_name end def additional_repository_storage @@ -102,6 +102,10 @@ module QA enabled?(ENV['QA_DEBUG'], default: false) end + def default_branch + ENV['QA_DEFAULT_BRANCH'] || 'master' + end + def log_destination ENV['QA_LOG_PATH'] || $stdout end @@ -395,6 +399,14 @@ module QA ENV['DEPLOY_VERSION'] end + def user_agent + ENV['GITLAB_QA_USER_AGENT'] + end + + def geo_environment? + QA::Runtime::Scenario.attributes.include?(:geo_secondary_address) + end + private def remote_grid_credentials diff --git a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb index 6654a35915f..89bf92cd3af 100644 --- a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb +++ b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb @@ -37,7 +37,7 @@ module QA Support::Waiter.wait_until(retry_on_exception: true, sleep_interval: 5) do Resource::Repository::Commit.fabricate_via_api! do |commits| commits.project = project - commits.sha = 'master' + commits.sha = project.default_branch end end diff --git a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb index e96b9ad9258..631056ed52e 100644 --- a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb +++ b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb @@ -45,7 +45,7 @@ module QA # Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect # scenario with other tests that aren't considered orchestrated. # It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage - context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/974' do + context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/974', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284645', type: :investigating } do let(:source_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } } let(:destination_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } } let(:project) do diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb index 82a06780830..2391154030b 100644 --- a/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb +++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb @@ -7,16 +7,18 @@ module QA # # git config --global receive.advertisepushoptions true - branch = "push-options-test-#{SecureRandom.hex(8)}" - title = "MR push options test #{SecureRandom.hex(8)}" - commit_message = 'Add README.md' + let(:branch) { "push-options-test-#{SecureRandom.hex(8)}" } + let(:title) { "MR push options test #{SecureRandom.hex(8)}" } + let(:commit_message) { 'Add README.md' } - project = Resource::Project.fabricate_via_api! do |project| - project.name = 'merge-request-push-options' - project.initialize_with_readme = true + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'merge-request-push-options' + project.initialize_with_readme = true + end end - it 'sets labels', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1032' do + def create_new_mr_via_push Resource::Repository::ProjectPush.fabricate! do |push| push.project = project push.commit_message = commit_message @@ -27,6 +29,10 @@ module QA label: %w[one two three] } end + end + + it 'sets labels', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1032' do + create_new_mr_via_push merge_request = project.merge_request_with_title(title) @@ -35,7 +41,11 @@ module QA end context 'when labels are set already' do - it 'removes them', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1033' do + before do + create_new_mr_via_push + end + + it 'removes them on subsequent push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1033' do Resource::Repository::ProjectPush.fabricate! do |push| push.project = project push.file_content = "Unlabel test #{SecureRandom.hex(8)}" diff --git a/qa/qa/specs/features/api/3_create/repository/files_spec.rb b/qa/qa/specs/features/api/3_create/repository/files_spec.rb index f539aae9b29..1099234537a 100644 --- a/qa/qa/specs/features/api/3_create/repository/files_spec.rb +++ b/qa/qa/specs/features/api/3_create/repository/files_spec.rb @@ -21,27 +21,29 @@ module QA a_hash_including(name: project_name, path: project_name) ) + default_branch = json_body[:default_branch].to_s.empty? ? Runtime::Env.default_branch : json_body[:default_branch] + create_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md") - post create_file_request.url, branch: 'master', content: 'Hello world', commit_message: 'Add README.md' + post create_file_request.url, branch: default_branch, content: 'Hello world', commit_message: 'Add README.md' expect_status(201) expect(json_body).to match( - a_hash_including(branch: 'master', file_path: 'README.md') + a_hash_including(branch: default_branch, file_path: 'README.md') ) - get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", ref: 'master') + get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", ref: default_branch) get get_file_request.url expect_status(200) expect(json_body).to match( a_hash_including( - ref: 'master', + ref: default_branch, file_path: 'README.md', file_name: 'README.md', encoding: 'base64', content: 'SGVsbG8gd29ybGQ=' ) ) - delete_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", branch: 'master', commit_message: 'Remove README.md') + delete_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", branch: default_branch, commit_message: 'Remove README.md') delete delete_file_request.url expect_status(204) @@ -80,10 +82,12 @@ module QA create_project_request = Runtime::API::Request.new(@api_client, '/projects') post create_project_request.url, path: project_name, name: project_name + default_branch = json_body[:default_branch].to_s.empty? ? Runtime::Env.default_branch : json_body[:default_branch] + create_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/test.svg") - post create_file_request.url, branch: 'master', content: svg_file, commit_message: 'Add test.svg' + post create_file_request.url, branch: default_branch, content: svg_file, commit_message: 'Add test.svg' - get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/test.svg/raw", ref: 'master') + get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/test.svg/raw", ref: default_branch) 3.times do response = get get_file_request.url diff --git a/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb b/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb index 0bbb0ed897a..1d1b765bb9f 100644 --- a/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb +++ b/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb @@ -42,7 +42,7 @@ module QA end let!(:pipeline_id) do - pipeline_create_request = Runtime::API::Request.new(api_client, "/projects/#{project.id}/pipeline?ref=master") + pipeline_create_request = Runtime::API::Request.new(api_client, "/projects/#{project.id}/pipeline?ref=#{project.default_branch}") JSON.parse(post(pipeline_create_request.url, nil))['id'] end @@ -65,6 +65,9 @@ module QA deleted_pipeline = pipeline !pipeline.empty? end + + raise "Pipeline response does not have a 'message' key: #{deleted_pipeline}" unless deleted_pipeline&.key?('message') + expect(deleted_pipeline['message'].downcase).to have_content('404 not found') end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb index 163469e1e88..e38a9f47bd6 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb @@ -81,7 +81,7 @@ module QA recovery_code = two_fa_auth.recovery_codes.sample - two_fa_auth.click_proceed_button + two_fa_auth.click_copy_and_proceed recovery_code end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb index 7f3c3049499..f6d2492c011 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb @@ -56,7 +56,7 @@ module QA otp = QA::Support::OTP.new(two_fa_auth.otp_secret_content) two_fa_auth.set_pin_code(otp.fresh_otp) two_fa_auth.click_register_2fa_app_button - two_fa_auth.click_proceed_button + two_fa_auth.click_copy_and_proceed end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb index 12a1b419f8b..f81dfe4b5c8 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb @@ -99,9 +99,9 @@ module QA two_fa_auth.set_pin_code(@otp.fresh_otp) two_fa_auth.click_register_2fa_app_button - expect(two_fa_auth).to have_text('Congratulations! You have enabled Two-factor Authentication!') + two_fa_auth.click_copy_and_proceed - two_fa_auth.click_proceed_button + expect(two_fa_auth).to have_text('Congratulations! You have enabled Two-factor Authentication!') end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb index e4ac59cf5e0..6cd486bc84b 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb @@ -3,7 +3,7 @@ module QA RSpec.describe 'Manage', :orchestrated, :instance_saml do describe 'Instance wide SAML SSO' do - it 'User logs in to gitlab with SAML SSO', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/671' do + it 'user logs in to gitlab with SAML SSO', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/671' do Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.perform(&:sign_in_with_saml) diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb index 2bb03b6154f..d58857f6da2 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb @@ -26,7 +26,7 @@ module QA ldap_username = Runtime::Env.ldap_username Runtime::Env.ldap_username = nil - disable_require_admin_approval_after_user_signup + set_require_admin_approval_after_user_signup_via_api(false) Runtime::Env.ldap_username = ldap_username end @@ -39,60 +39,136 @@ module QA end describe 'standard', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/936' do - before(:all) do - disable_require_admin_approval_after_user_signup - end + context 'when admin approval is not required' do + before(:all) do + set_require_admin_approval_after_user_signup_via_api(false) + end - it_behaves_like 'registration and login' + it_behaves_like 'registration and login' + + context 'when user account is deleted' do + let(:user) do + Resource::User.fabricate_via_api! do |resource| + resource.api_client = admin_api_client + end + end + + before do + # Use the UI instead of API to delete the account since + # this is the only test that exercise this UI. + # Other tests should use the API for this purpose. + Flow::Login.sign_in(as: user) + Page::Main::Menu.perform(&:click_settings_link) + Page::Profile::Menu.perform(&:click_account) + Page::Profile::Accounts::Show.perform do |show| + show.delete_account(user.password) + end + end + + it 'allows recreating with same credentials', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/937' do + expect(Page::Main::Menu.perform(&:signed_in?)).to be_falsy + + Flow::Login.sign_in(as: user, skip_page_validation: true) - context 'when user account is deleted' do - let(:user) do - Resource::User.fabricate_via_api! do |resource| - resource.api_client = admin_api_client + expect(page).to have_text("Invalid Login or password") + + @recreated_user = Resource::User.fabricate_via_browser_ui! do |resource| + resource.name = user.name + resource.username = user.username + resource.email = user.email + end + + expect(Page::Main::Menu.perform(&:signed_in?)).to be_truthy + end + + after do + @recreated_user.remove_via_api! + end + + def admin_api_client + @admin_api_client ||= Runtime::API::Client.as_admin end end + end + + context 'when admin approval is required' do + let(:signed_up_waiting_approval_text) { 'You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator.' } + let(:pending_approval_blocked_text) { 'Your account is pending approval from your GitLab administrator and hence blocked. Please contact your GitLab administrator if you think this is an error.' } before do - # Use the UI instead of API to delete the account since - # this is the only test that exercise this UI. - # Other tests should use the API for this purpose. - Flow::Login.sign_in(as: user) - Page::Main::Menu.perform(&:click_settings_link) - Page::Profile::Menu.perform(&:click_account) - Page::Profile::Accounts::Show.perform do |show| - show.delete_account(user.password) + enable_require_admin_approval_after_user_signup_via_ui + + @user = Resource::User.fabricate_via_browser_ui! do |user| + user.expect_fabrication_success = false end end - it 'allows recreating with same credentials', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/937' do - expect(Page::Main::Menu.perform(&:signed_in?)).to be_falsy + it 'allows user login after approval', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1076' do + expect(page).to have_text(signed_up_waiting_approval_text) - Flow::Login.sign_in(as: user, skip_page_validation: true) + Flow::Login.sign_in(as: @user, skip_page_validation: true) - expect(page).to have_text("Invalid Login or password") + expect(page).to have_text(pending_approval_blocked_text) - @recreated_user = Resource::User.fabricate_via_browser_ui! do |resource| - resource.name = user.name - resource.username = user.username - resource.email = user.email - end + approve_user(@user) + + Flow::Login.sign_in(as: @user, skip_page_validation: true) + + Page::Registration::Welcome.perform(&:click_get_started_button_if_available) - expect(Page::Main::Menu.perform(&:signed_in?)).to be_truthy + Page::Main::Menu.perform do |menu| + expect(menu).to have_personal_area + end end after do - @recreated_user.remove_via_api! + set_require_admin_approval_after_user_signup_via_api(false) + @user.remove_via_api! if @user + end + end + end + + def approve_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.click_pending_approval_tab + index.search_user(user.username) + index.click_user(user.username) end - def admin_api_client - @admin_api_client ||= Runtime::API::Client.as_admin + Page::Admin::Overview::Users::Show.perform do |show| + user.id = show.user_id.to_i + show.approve_user end + + expect(page).to have_text('Successfully approved') end end - def disable_require_admin_approval_after_user_signup - Runtime::ApplicationSettings.set_application_settings(require_admin_approval_after_user_signup: false) + def set_require_admin_approval_after_user_signup_via_api(enable_or_disable) + return if Runtime::ApplicationSettings.get_application_settings[:require_admin_approval_after_user_signup] == enable_or_disable + + Runtime::ApplicationSettings.set_application_settings(require_admin_approval_after_user_signup: enable_or_disable) + sleep 10 # It takes a moment for the setting to come into effect end + + def enable_require_admin_approval_after_user_signup_via_ui + unless Runtime::ApplicationSettings.get_application_settings[:require_admin_approval_after_user_signup] + Flow::Login.while_signed_in_as_admin do + Page::Main::Menu.perform(&:go_to_admin_area) + QA::Page::Admin::Menu.perform(&:go_to_general_settings) + Page::Admin::Settings::General.perform do |setting| + setting.expand_sign_up_restrictions do |settings| + settings.require_admin_approval_after_user_signup + end + end + end + + sleep 10 # It takes a moment for the setting to come into effect + end + end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb index 2f2f40cba3b..ff13b769e3a 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb @@ -3,7 +3,9 @@ module QA RSpec.describe 'Manage', :smoke do describe 'Project creation' do - it 'user creates a new project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/429' do + it 'user creates a new project', + testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/429', + quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/283925', type: :investigating } do Flow::Login.sign_in created_project = Resource::Project.fabricate_via_browser_ui! do |project| diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb index 3609d083fde..db96c2d4ad3 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb @@ -6,17 +6,18 @@ module QA it 'user creates an event in the activity page upon Git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/407' do Flow::Login.sign_in - Resource::Repository::ProjectPush.fabricate! do |push| + project = Resource::Repository::ProjectPush.fabricate! do |push| push.file_name = 'README.md' push.file_content = '# This is a test project' push.commit_message = 'Add README.md' - end.project.visit! + end.project + project.visit! Page::Project::Menu.perform(&:click_activity) Page::Project::Activity.perform do |activity| activity.click_push_events - expect(activity).to have_content('pushed new branch master') + expect(activity).to have_content("pushed new branch #{project.default_branch}") end end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb index 5d863a80877..e394f6b1e9c 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb @@ -27,6 +27,10 @@ module QA end.visit! end + after do + user&.remove_via_api! + end + it 'mentions a user in a comment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/452' do Page::Project::Issue::Show.perform do |show| show.select_all_activities_filter diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb index 22157d648ca..6ed204a98d4 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb @@ -4,22 +4,20 @@ module QA RSpec.describe 'Plan', :reliable do describe 'collapse comments in issue discussions' do let(:my_first_reply) { 'My first reply' } + let(:one_reply) { '1 reply' } + let(:issue) { Resource::Issue.fabricate_via_api! } before do Flow::Login.sign_in - Resource::Issue.fabricate_via_api!.visit! + issue.visit! + end + it 'collapses and expands reply for comments in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/434' do Page::Project::Issue::Show.perform do |show| show.select_all_activities_filter show.start_discussion('My first discussion') show.reply_to_discussion(1, my_first_reply) - end - end - - it 'collapses and expands reply for comments in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/434' do - Page::Project::Issue::Show.perform do |show| - one_reply = "1 reply" show.collapse_replies expect(show).to have_content(one_reply) diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb index 9550572bd5c..688f42c48c6 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb @@ -19,7 +19,7 @@ module QA end end - it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1085' do + it 'closes an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1085' do closed_issue.visit! Page::Project::Issue::Show.perform do |issue_page| 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 26a83fc3caa..11f93d6a97e 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 @@ -40,12 +40,12 @@ module QA issue.set_issue_assignees(assignee_ids: [user2.id]) expect(show).to have_assignee(user2.name) - expect(show).to have_no_assignee_named(user1.name) + expect(show).not_to have_assignee(user1.name) issue.set_issue_assignees(assignee_ids: []) - expect(show).to have_no_assignee_named(user1.name) - expect(show).to have_no_assignee_named(user2.name) + expect(show).not_to have_assignee(user1.name) + expect(show).not_to have_assignee(user2.name) end end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb index 13761244300..6a133540f87 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb @@ -37,7 +37,7 @@ module QA show.click_remove_related_issue_button - expect(show).to have_no_text(issue_2.title, wait: max_wait) + expect(show).not_to have_text(issue_2.title, wait: max_wait) end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb new file mode 100644 index 00000000000..0fec7bc9e9d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb @@ -0,0 +1,155 @@ +# frozen_string_literal: true +require 'securerandom' + +module QA + RSpec.describe 'Create', :requires_admin, :skip_live_env, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/195179', type: :flaky } do + describe 'Jenkins integration' do + let(:project_name) { "project_with_jenkins_#{SecureRandom.hex(4)}" } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = project_name + project.initialize_with_readme = true + project.auto_devops_enabled = false + end + end + + before do + jenkins_server = run_jenkins_server + + Vendor::Jenkins::Page::Base.host = jenkins_server.host_address + + Runtime::Env.personal_access_token ||= fabricate_personal_access_token + + allow_requests_to_local_networks + + setup_jenkins + end + + it 'integrates and displays build status for MR pipeline in GitLab', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/719' do + login_to_gitlab + + setup_project_integration_with_jenkins + + expect(page).to have_text("Jenkins CI activated.") + + QA::Support::Retrier.retry_on_exception do + Resource::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.new_branch = false + push.file_name = "file_#{SecureRandom.hex(4)}.txt" + end + + Vendor::Jenkins::Page::LastJobConsole.perform do |job_console| + job_console.job_name = project_name + + job_console.visit! + + Support::Waiter.wait_until(sleep_interval: 2, reload_page: page) do + job_console.has_successful_build? && job_console.no_failed_status_update? + end + end + + project.visit! + + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |show| + expect(show).to have_build('jenkins', status: :success, wait: 15) + end + end + end + + after do + remove_jenkins_server + end + + def setup_jenkins + Vendor::Jenkins::Page::Login.perform do |login_page| + login_page.visit! + login_page.login + end + + token_description = "token-#{SecureRandom.hex(8)}" + + Vendor::Jenkins::Page::NewCredentials.perform do |new_credentials| + new_credentials.visit_and_set_gitlab_api_token(Runtime::Env.personal_access_token, token_description) + end + + Vendor::Jenkins::Page::Configure.perform do |configure| + configure.visit_and_setup_gitlab_connection(patch_host_name(Runtime::Scenario.gitlab_address, 'gitlab'), token_description) do + configure.click_test_connection + expect(configure).to have_success + end + end + + Vendor::Jenkins::Page::NewJob.perform do |new_job| + new_job.visit_and_create_new_job_with_name(project_name) + end + + Vendor::Jenkins::Page::ConfigureJob.perform do |configure_job| + configure_job.job_name = project_name + configure_job.configure(scm_url: patch_host_name(project.repository_http_location.git_uri, 'gitlab')) + end + end + + def run_jenkins_server + Service::DockerRun::Jenkins.new.tap do |runner| + runner.pull + runner.register! + end + end + + def remove_jenkins_server + Service::DockerRun::Jenkins.new.remove! + end + + def fabricate_personal_access_token + login_to_gitlab + + token = Resource::PersonalAccessToken.fabricate!.access_token + Page::Main::Menu.perform(&:sign_out) + token + end + + def login_to_gitlab + Flow::Login.sign_in + end + + def patch_host_name(host_name, container_name) + return host_name unless host_name.include?('localhost') + + ip_address = `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' #{container_name}`.strip + host_name.gsub('localhost', ip_address) + end + + def setup_project_integration_with_jenkins + project.visit! + + Page::Project::Menu.perform(&:click_project) + Page::Project::Menu.perform(&:go_to_integrations_settings) + Page::Project::Settings::Integrations.perform(&:click_jenkins_ci_link) + + QA::Page::Project::Settings::Services::Jenkins.perform do |jenkins| + jenkins.setup_service_with(jenkins_url: patch_host_name(Vendor::Jenkins::Page::Base.host, 'jenkins-server'), + project_name: project_name) + end + end + + def allow_requests_to_local_networks + Page::Main::Menu.perform(&:sign_out_if_signed_in) + Flow::Login.sign_in_as_admin + Page::Main::Menu.perform(&:go_to_admin_area) + Page::Admin::Menu.perform(&:go_to_network_settings) + + Page::Admin::Settings::Network.perform do |network| + network.expand_outbound_requests do |outbound_requests| + outbound_requests.allow_requests_to_local_network_from_services + end + end + + Page::Main::Menu.perform(&:sign_out) + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb index 37ddd1425a8..d53e7fcf69a 100644 --- a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb @@ -80,7 +80,6 @@ module QA def push_commit(commit_message) Resource::Repository::ProjectPush.fabricate! do |push| - push.branch_name = 'master' push.commit_message = commit_message push.file_content = commit_message push.project = project @@ -101,7 +100,7 @@ module QA end def master_branch_exists? - project.repository_branches.map { |item| item[:name] }.include?("master") + project.repository_branches.map { |item| item[:name] }.include?(project.default_branch) end end 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 b58e820a6c9..d2ba97400e6 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,21 +2,23 @@ module QA RSpec.describe 'Create' do - describe 'Merge request creation from fork' do - let(:merge_request) do - Resource::MergeRequestFromFork.fabricate_via_api! do |merge_request| + describe 'Merge request creation from fork', :smoke do + let!(:merge_request) do + Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request| merge_request.fork_branch = 'feature-branch' end end it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/928' do - Flow::Login.sign_in + Flow::Login.while_signed_in do + merge_request.visit! - merge_request.visit! + Page::MergeRequest::Show.perform do |merge_request| + merge_request.merge! - Page::MergeRequest::Show.perform(&:merge!) - - expect(page).to have_content('The changes were merged') + expect(merge_request).to have_content('The changes were merged') + end + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb index 02fbb0bbbd7..823a033ab6d 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb @@ -27,7 +27,6 @@ module QA push.project = project push.file_name = "other.txt" push.file_content = "New file added!" - push.branch_name = "master" push.new_branch = false end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb index 970615e8b90..24b92164060 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - RSpec.describe 'Create', :requires_admin do + RSpec.describe 'Create', :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/261793', type: :investigating } do describe 'View merge request merge-ref diff' do let(:project) do Resource::Project.fabricate_via_api! do |project| @@ -37,8 +37,8 @@ module QA mr_page.click_diffs_tab mr_page.click_target_version_dropdown - expect(mr_page.version_dropdown_content).to include('master (HEAD)') - expect(mr_page.version_dropdown_content).not_to include('master (base)') + expect(mr_page.version_dropdown_content).to include("#{project.default_branch} (HEAD)") + expect(mr_page.version_dropdown_content).not_to include("#{project.default_branch} (base)") expect(mr_page).to have_file(merge_request.file_name) expect(mr_page).not_to have_file(new_file_name) end @@ -62,8 +62,8 @@ module QA mr_page.click_diffs_tab mr_page.click_target_version_dropdown - expect(mr_page.version_dropdown_content).to include('master (HEAD)') - expect(mr_page.version_dropdown_content).to include('master (base)') + expect(mr_page.version_dropdown_content).to include("#{project.default_branch} (HEAD)") + expect(mr_page.version_dropdown_content).to include("#{project.default_branch} (base)") expect(mr_page).to have_file(merge_request.file_name) expect(mr_page).to have_file(new_file_name) end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb index 98cbc5c0a93..8df68e0f53b 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 @@ -3,7 +3,7 @@ module QA RSpec.describe 'Create' do describe 'Create, list, and delete branches via web' do - master_branch = 'master' + master_branch = nil second_branch = 'second-branch' third_branch = 'third-branch' file_1_master = 'file.txt' @@ -21,12 +21,16 @@ module QA project = Resource::Project.fabricate_via_api! do |proj| proj.name = 'project-qa-test' proj.description = 'project for qa test' + proj.initialize_with_readme = true end + master_branch = project.default_branch + Git::Repository.perform do |repository| repository.uri = project.repository_http_location.uri repository.use_default_credentials repository.try_add_credentials_to_netrc + repository.default_branch = master_branch repository.act do clone diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb index 54d00209cc7..2b249f779d9 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb @@ -40,7 +40,7 @@ module QA end def create_protected_branch(allowed_to_push:) - Resource::ProtectedBranch.fabricate! do |resource| + Resource::ProtectedBranch.fabricate_via_api! do |resource| resource.branch_name = branch_name resource.project = project resource.allowed_to_push = allowed_to_push diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb index efd61a2e63a..a21c5d58aad 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb @@ -7,7 +7,6 @@ module QA let(:changed_content) { 'changes' } let(:commit_message) { 'Changes to snippets' } let(:added_content) { 'updated ' } - let(:branch_name) { 'master' } let(:snippet) do Resource::Snippet.fabricate! do |snippet| @@ -41,7 +40,7 @@ module QA end it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/826' do - Resource::Repository::Push.fabricate! do |push| + push = Resource::Repository::Push.fabricate! do |push| push.repository_http_uri = repository_uri_http push.file_name = new_file push.file_content = changed_content @@ -61,7 +60,7 @@ module QA Git::Repository.perform do |repository| repository.init_repository - repository.pull(repository_uri_http, branch_name) + repository.pull(repository_uri_http, push.branch_name) expect(repository.commits.size).to eq(3) expect(repository.commits.first).to include('Update snippet') @@ -70,7 +69,7 @@ module QA end it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/825' do - Resource::Repository::Push.fabricate! do |push| + push = Resource::Repository::Push.fabricate! do |push| push.repository_ssh_uri = repository_uri_ssh push.ssh_key = ssh_key push.file_name = new_file @@ -90,7 +89,7 @@ module QA repository.use_ssh_key(ssh_key) repository.init_repository - expect { repository.pull(repository_uri_ssh, branch_name) } + expect { repository.pull(repository_uri_ssh, push.branch_name) } .to raise_error(QA::Support::Run::CommandError, /fatal: Could not read from remote repository\./) end end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb index 79e2677da66..4ce6c3fdcd3 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb @@ -7,7 +7,7 @@ module QA let(:changed_content) { 'changes' } let(:commit_message) { 'Changes to snippets' } let(:added_content) { 'updated ' } - let(:branch_name) { 'master' } + let(:branch_name) { snippet.project.default_branch } let(:snippet) do Resource::ProjectSnippet.fabricate! do |snippet| 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 8445fdafdd4..b74f27389a0 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 @@ -3,7 +3,7 @@ module QA RSpec.describe 'Create', :smoke do describe 'Personal snippet creation' do - it 'User creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/840' do + it 'user creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/840' do Flow::Login.sign_in Page::Main::Menu.perform do |menu| diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb index d80fc4c5b95..8c44cd6d642 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb @@ -3,7 +3,7 @@ module QA RSpec.describe 'Create' do # to be converted to a smoke test once proved to be stable describe 'Project snippet creation' do - it 'User creates a project snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/839' do + it 'user creates a project snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/839' do Flow::Login.sign_in Resource::ProjectSnippet.fabricate_via_browser_ui! do |snippet| @@ -16,13 +16,13 @@ module QA Page::Dashboard::Snippet::Show.perform do |snippet| expect(snippet).to have_snippet_title('Project snippet') - expect(snippet).to have_no_snippet_description + expect(snippet).not_to have_snippet_description expect(snippet).to have_visibility_type(/private/i) expect(snippet).to have_file_name('markdown_file.md') expect(snippet).to have_file_content('Snippet heading') expect(snippet).to have_file_content('Gitlab link') - expect(snippet).to have_no_file_content('###') - expect(snippet).to have_no_file_content('https://gitlab.com/') + expect(snippet).not_to have_file_content('###') + expect(snippet).not_to have_file_content('https://gitlab.com/') end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb index ca6ea5db65d..8002e95cf0d 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb @@ -46,8 +46,8 @@ module QA aggregate_failures 'file names and contents' do expect(snippet).to have_file_name('Original file name') expect(snippet).to have_file_content('Original file content') - expect(snippet).to have_no_file_name('Second file name') - expect(snippet).to have_no_file_content('Second file content') + expect(snippet).not_to have_file_name('Second file name') + expect(snippet).not_to have_file_content('Second file content') end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb index e2fa487c937..dad5ad74a4c 100644 --- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb @@ -2,7 +2,7 @@ module QA RSpec.describe 'Create' do - describe 'Open a fork in Web IDE' do + describe 'Open a fork in Web IDE', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284081', type: :investigating } do let(:parent_project) do Resource::Project.fabricate_via_api! do |project| project.name = 'parent-project' diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb index ccd4d34a916..fcd8cb02870 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb @@ -19,7 +19,7 @@ module QA it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/395' do Page::Project::Settings::CiVariables.perform do |ci_variable| expect(ci_variable).to have_text('VARIABLE_KEY') - expect(ci_variable).to have_no_text('some_CI_variable') + expect(ci_variable).not_to have_text('some_CI_variable') ci_variable.click_reveal_ci_variable_value_button diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb index cedc2db2a1a..c2ea568dbad 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb @@ -3,9 +3,8 @@ require 'faker' module QA - RSpec.describe 'Verify', :runner, :requires_admin, :skip_live_env do - describe "Include multiple files from a project" do - let(:feature_flag) { :ci_include_multiple_files_from_project } + RSpec.describe 'Verify', :runner do + describe 'Include multiple files from a project' do let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } let(:expected_text) { Faker::Lorem.sentence } let(:unexpected_text) { Faker::Lorem.sentence } @@ -31,16 +30,14 @@ module QA end before do - Runtime::Feature.enable(feature_flag) Flow::Login.sign_in add_included_files add_main_ci_file project.visit! - view_the_last_pipeline + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'succeeded') end after do - Runtime::Feature.disable(feature_flag) runner.remove_via_api! end @@ -57,7 +54,7 @@ module QA Page::Project::Job::Show.perform do |job| aggregate_failures 'main CI is not overridden' do - expect(job.output).to have_no_content("#{unexpected_text}") + expect(job.output).not_to have_content("#{unexpected_text}") expect(job.output).to have_content("#{expected_text}") end end @@ -81,12 +78,6 @@ module QA end end - def view_the_last_pipeline - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_success) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) - end - def main_ci_file { file_path: '.gitlab-ci.yml', diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb index eafe28c1ee6..519777b32d9 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb @@ -3,9 +3,8 @@ require 'faker' module QA - RSpec.describe 'Verify', :runner, :requires_admin do - describe "Pass dotenv variables to downstream via bridge" do - let(:feature_flag) { :ci_bridge_dependency_variables } + RSpec.describe 'Verify', :runner do + describe 'Pass dotenv variables to downstream via bridge' do let(:executor_1) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } let(:executor_2) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } @@ -38,16 +37,14 @@ module QA end before do - Runtime::Feature.enable(feature_flag) Flow::Login.sign_in add_ci_file(downstream_project, downstream_ci_file) add_ci_file(upstream_project, upstream_ci_file) upstream_project.visit! - Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'success') + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'succeeded') end after do - Runtime::Feature.disable(feature_flag) runner_1.remove_via_api! runner_2.remove_via_api! end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb index b79bda108af..5f3ec3ec870 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb @@ -2,7 +2,7 @@ module QA RSpec.describe 'Verify' do - describe 'Run pipeline', only: { subdomain: :staging } do + describe 'Run pipeline' do context 'with web only rule' do let(:job_name) { 'test_job' } let(:project) do diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb index 2f66ed697a3..c89cda73711 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb @@ -3,11 +3,8 @@ require 'faker' module QA - RSpec.describe 'Verify', :runner, :requires_admin do - # [TODO]: Developer to remove :requires_admin once FF is removed in follow up issue - + RSpec.describe 'Verify', :runner do describe "Trigger child pipeline with 'when:manual'" do - let(:feature_flag) { :ci_manual_bridges } # [TODO]: Developer to remove when feature flag is removed let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" } let(:project) do @@ -25,15 +22,13 @@ module QA end before do - Runtime::Feature.enable(feature_flag) # [TODO]: Developer to remove when feature flag is removed Flow::Login.sign_in add_ci_files project.visit! - Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'success') + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'succeeded') end after do - Runtime::Feature.disable(feature_flag) # [TODO]: Developer to remove when feature flag is removed runner.remove_via_api! end diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb index 7783dba3fa7..be6f3b17ccd 100644 --- a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb @@ -81,8 +81,7 @@ module QA end project.visit! - Page::Project::Menu.perform(&:click_ci_cd_pipelines) - Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline) + Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform do |pipeline| pipeline.click_job('publish') @@ -112,7 +111,7 @@ module QA Page::Project::Packages::Index.perform do |index| aggregate_failures 'package deletion' do expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).not_to have_package(package_name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb index 2b06ba8646f..ae0580ff51b 100644 --- a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb @@ -31,7 +31,7 @@ module QA runner.remove_via_api! end - it 'publishes a conan package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do + it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do Flow::Login.sign_in Resource::Repository::Commit.fabricate_via_api! do |commit| @@ -43,13 +43,14 @@ module QA <<~YAML image: conanio/gcc7 - create_package: + test_package: stage: deploy script: - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan" - "conan new #{package_name}/0.1 -t" - "conan create . mycompany/stable" - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package_name}/0.1@mycompany/stable --all --remote=gitlab" + - "conan install conantest/0.1@mycompany/stable --remote=gitlab" tags: - "runner-for-#{project.name}" YAML @@ -60,7 +61,7 @@ module QA Flow::Pipeline.visit_latest_pipeline Page::Project::Pipeline::Show.perform do |pipeline| - pipeline.click_job('create_package') + pipeline.click_job('test_package') end Page::Project::Job::Show.perform do |job| @@ -80,7 +81,7 @@ module QA Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).not_to have_package(package_name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb new file mode 100644 index 00000000000..9a0d832de09 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb @@ -0,0 +1,116 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Package', :orchestrated, :packages do + describe 'Generic Repository' do + let(:package_name) { 'my_package' } + + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'generic-package-project' + end + end + + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = "qa-runner-#{Time.now.to_i}" + runner.tags = ["runner-for-#{project.name}"] + runner.executor = :docker + runner.project = project + end + end + + let(:gitlab_ci_yaml) do + <<~YAML + image: curlimages/curl:latest + + stages: + - upload + - download + + upload: + stage: upload + script: + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file file.txt ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt' + tags: + - "runner-for-#{project.name}" + download: + stage: download + script: + - 'wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/my_package/0.0.1/file.txt -O file_downloaded.txt' + tags: + - "runner-for-#{project.name}" + YAML + end + + let(:file_txt) do + <<~EOF + Hello, world! + EOF + end + + before do + Flow::Login.sign_in + + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.commit_message = 'Add .gitlab-ci.yml' + commit.add_files([{ + file_path: '.gitlab-ci.yml', + content: gitlab_ci_yaml + }, + { + file_path: 'file.txt', + content: file_txt + }] + ) + end + + project.visit! + Flow::Pipeline.visit_latest_pipeline + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('upload') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + + job.click_element(:pipeline_path) + end + + Page::Project::Pipeline::Show.perform do |pipeline| + pipeline.click_job('download') + end + + Page::Project::Job::Show.perform do |job| + expect(job).to be_successful(timeout: 800) + end + end + + after do + runner.remove_via_api! + end + + it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1108' do + Page::Project::Menu.perform(&:click_packages_link) + + Page::Project::Packages::Index.perform do |index| + expect(index).to have_package(package_name) + index.click_package(package_name) + end + + Page::Project::Packages::Show.perform do |package| + package.click_delete + end + + Page::Project::Packages::Index.perform do |index| + aggregate_failures 'package deletion' do + expect(index).to have_content("Package deleted successfully") + expect(index).to have_no_package(package_name) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb index e163fcbe574..552302addf9 100644 --- a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb @@ -54,7 +54,7 @@ module QA script: - 'gradle publish' only: - - master + - "#{project.default_branch}" tags: - "runner-for-#{project.name}" YAML @@ -118,7 +118,7 @@ module QA Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).not_to have_package(package_name) end end end 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 4ca356c9b65..5410b5023d9 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 @@ -96,7 +96,7 @@ module QA Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).not_to have_package(package_name) end 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 817e146adfe..fa88ace1556 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 @@ -69,7 +69,7 @@ module QA Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).not_to have_package(package_name) end 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 0b70adf9ff6..be806fcbb3e 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 @@ -51,7 +51,7 @@ module QA - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text - dotnet nuget push "bin/Release/*.nupkg" --source gitlab only: - - master + - "#{project.default_branch}" tags: - "runner-for-#{project.name}" YAML @@ -84,7 +84,7 @@ module QA Page::Project::Packages::Index.perform do |index| expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).not_to have_package(package_name) end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb index 35c41bbb2b0..d5eca171d6c 100644 --- a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb @@ -87,6 +87,7 @@ module QA after do runner.remove_via_api! + project&.remove_via_api! end it 'publishes a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1087' do @@ -104,7 +105,33 @@ module QA Page::Project::Packages::Index.perform do |index| aggregate_failures do expect(index).to have_content("Package deleted successfully") - expect(index).to have_no_package(package_name) + expect(index).not_to have_package(package_name) + end + end + end + + context 'Geo', :orchestrated, :geo do + it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1120' do + QA::Runtime::Logger.debug('Visiting the secondary Geo site') + + QA::Flow::Login.while_signed_in(address: :geo_secondary) do + EE::Page::Main::Banner.perform do |banner| + expect(banner).to have_secondary_read_only_banner + end + + Page::Main::Menu.perform(&:go_to_projects) + + Page::Dashboard::Projects.perform do |dashboard| + dashboard.wait_for_project_replication(project.name) + dashboard.go_to_project(project.name) + end + + Page::Project::Menu.perform(&:click_packages_link) + + Page::Project::Packages::Index.perform do |index| + index.wait_for_package_replication(package_name) + expect(index).to have_package(package_name) + end end end end diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb index ec26e338b28..9ec05fcf5d3 100644 --- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb @@ -27,7 +27,7 @@ module QA it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/751' do add_ci_files(success_child_ci_file) - Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline @@ -37,7 +37,7 @@ module QA it 'parent pipeline fails if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/752' do add_ci_files(fail_child_ci_file) - Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb index d7f5a326b0e..ed8c8baae0e 100644 --- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb @@ -27,7 +27,7 @@ module QA it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/754' do add_ci_files(success_child_ci_file) - Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline @@ -37,7 +37,7 @@ module QA it 'parent pipeline passes even if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/753' do add_ci_files(fail_child_ci_file) - Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completion') + Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed') Page::Project::Pipeline::Show.perform do |parent_pipeline| expect(parent_pipeline).to have_child_pipeline diff --git a/qa/qa/specs/features/sanity/version_spec.rb b/qa/qa/specs/features/sanity/version_spec.rb index cace46c3590..e93a8a6fea1 100644 --- a/qa/qa/specs/features/sanity/version_spec.rb +++ b/qa/qa/specs/features/sanity/version_spec.rb @@ -7,7 +7,7 @@ module QA # environment variable is the version actually running. # # See https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1179 - RSpec.describe 'Version sanity check', :smoke do + RSpec.describe 'Version sanity check', :smoke, only: { pipeline: [:pre, :release] } do let(:api_client) { Runtime::API::Client.new(:gitlab) } let(:request) { Runtime::API::Request.new(api_client, '/version') } diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb index afeddeaa5d5..9027f17678d 100644 --- a/qa/qa/specs/runner.rb +++ b/qa/qa/specs/runner.rb @@ -40,6 +40,8 @@ module QA tags_for_rspec.push(%w[--tag ~orchestrated]) unless (%w[-t --tag] & options).any? end + tags_for_rspec.push(%w[--tag ~geo]) unless QA::Runtime::Env.geo_environment? + tags_for_rspec.push(%w[--tag ~skip_signup_disabled]) if QA::Runtime::Env.signup_disabled? tags_for_rspec.push(%w[--tag ~skip_live_env]) if QA::Runtime::Env.dot_com? diff --git a/qa/qa/support/wait_for_requests.rb b/qa/qa/support/wait_for_requests.rb index ebc473a7d86..5109f51d4d7 100644 --- a/qa/qa/support/wait_for_requests.rb +++ b/qa/qa/support/wait_for_requests.rb @@ -25,7 +25,7 @@ module QA # https://gitlab.com/groups/gitlab-org/-/epics/956 # retry_on_exception added here due to `StaleElementReferenceError`. See: https://gitlab.com/gitlab-org/gitlab/-/issues/232485 Support::Retrier.retry_on_exception do - Capybara.page.has_no_css?('.gl-spinner, .fa-spinner, .spinner', wait: wait) + Capybara.page.has_no_css?('.gl-spinner', wait: wait) end end end diff --git a/qa/qa/tools/delete_projects.rb b/qa/qa/tools/delete_projects.rb new file mode 100644 index 00000000000..bb73033e9d7 --- /dev/null +++ b/qa/qa/tools/delete_projects.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require_relative '../../qa' + +# This script deletes all projects directly under a group specified by ENV['TOP_LEVEL_GROUP_NAME'] +# Required environment variables: GITLAB_QA_ACCESS_TOKEN and GITLAB_ADDRESS +# Optional environment variable: TOP_LEVEL_GROUP_NAME (defaults to 'gitlab-qa-sandbox-group') +# Run `rake delete_projects` + +module QA + module Tools + class DeleteProjects + include Support::Api + + def initialize + raise ArgumentError, "Please provide GITLAB_ADDRESS environment variable" unless ENV['GITLAB_ADDRESS'] + raise ArgumentError, "Please provide GITLAB_QA_ACCESS_TOKEN environment variable" unless ENV['GITLAB_QA_ACCESS_TOKEN'] + + @api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['GITLAB_QA_ACCESS_TOKEN']) + end + + def run + STDOUT.puts 'Running...' + + # Fetch group's id + group_id = fetch_group_id + + projects_head_response = head Runtime::API::Request.new(@api_client, "/groups/#{group_id}/projects", per_page: "100").url + total_project_pages = projects_head_response.headers[:x_total_pages] + + # 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}" + + delete_projects(project_ids) unless project_ids.empty? + STDOUT.puts "\nDone" + end + + private + + def delete_projects(project_ids) + 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" + print dot_or_f + end + end + + def fetch_group_id + group_name = ENV['TOP_LEVEL_GROUP_NAME'] || 'gitlab-qa-sandbox-group' + group_search_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_name}").url + JSON.parse(group_search_response.body)["id"] + end + + def fetch_project_ids(group_id, total_project_pages) + projects_ids = [] + + total_project_pages.to_i.times do |page_no| + projects_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_id}/projects", page: (page_no + 1).to_s, per_page: "100").url + projects_ids.concat(JSON.parse(projects_response.body).select { |project| Date.parse(project["created_at"]) < Date.today - 3 }.map { |project| project["id"] }) + end + + projects_ids.uniq + end + end + end +end diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb index e77678a1527..546f7e7cdca 100644 --- a/qa/qa/tools/generate_perf_testdata.rb +++ b/qa/qa/tools/generate_perf_testdata.rb @@ -95,20 +95,20 @@ module QA def create_many_merge_requests 30.times do |i| - create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "branch#{i}", "master", "MR#{i}") + 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]}" end def create_many_new_files - create_a_new_file_api_req("hello.txt", "master", "#{@group_name}%2F#{@project_name}", "hello", "my new content") + create_a_new_file_api_req("hello.txt", Runtime::Env.default_branch, "#{@group_name}%2F#{@project_name}", "hello", "my new content") 30.times do |i| - create_a_new_file_api_req("hello#{i}.txt", "master", "#{@group_name}%2F#{@project_name}", "hello", "my new content") + create_a_new_file_api_req("hello#{i}.txt", Runtime::Env.default_branch, "#{@group_name}%2F#{@project_name}", "hello", "my new content") create_a_new_file_api_req("hello#{i}.txt", "branch#{i}", "#{@group_name}%2F#{@project_name}", "hello", "my new content") end - @urls[:files_page] = @urls[:project_page] + "/tree/master" + @urls[:files_page] = @urls[:project_page] + "/tree/#{Runtime::Env.default_branch}" STDOUT.puts "Added many new files: #{@urls[:files_page]}" end @@ -138,7 +138,7 @@ module QA 16.times do |i| faker_line_arr = Faker::Lorem.sentences(1500) content = faker_line_arr.join("\n\r") - create_a_new_file_api_req("hello#{i + 100}.txt", "master", "#{@group_name}%2F#{@project_name}", "Add hello#{i + 100}.txt", content) + create_a_new_file_api_req("hello#{i + 100}.txt", Runtime::Env.default_branch, "#{@group_name}%2F#{@project_name}", "Add hello#{i + 100}.txt", content) content_arr[i] = faker_line_arr end @@ -151,7 +151,7 @@ module QA update_file_api_req("hello#{i + 100}.txt", "performance", "#{@group_name}%2F#{@project_name}", "Update hello#{i + 100}.txt", content) end - create_mr_response = create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "performance", "master", "Large_MR") + create_mr_response = create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "performance", Runtime::Env.default_branch, "Large_MR") iid = JSON.parse(create_mr_response.body)["iid"] diff_refs = JSON.parse(create_mr_response.body)["diff_refs"] @@ -200,7 +200,7 @@ module QA create_a_branch_api_req(branch_name, project_path) create_a_new_file_api_req(file_name, branch_name, project_path, "Initial commit for new file", "Initial file content") - create_mr_response = create_a_merge_request_api_req(project_path, branch_name, "master", "MR with many commits-#{SecureRandom.hex(8)}") + create_mr_response = create_a_merge_request_api_req(project_path, branch_name, Runtime::Env.default_branch, "MR with many commits-#{SecureRandom.hex(8)}") @urls[:mr_with_many_commits] = JSON.parse(create_mr_response.body)["web_url"] 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")) @@ -268,7 +268,7 @@ module QA def create_a_branch_api_req(branch_name, project_path_or_id) call_api(expected_response_code: 201) do - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/branches").url, "branch=#{branch_name}&ref=master" + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/branches").url, "branch=#{branch_name}&ref=#{Runtime::Env.default_branch}" end end diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb index 02bb7783c28..77639c54b79 100644 --- a/qa/spec/git/repository_spec.rb +++ b/qa/spec/git/repository_spec.rb @@ -110,7 +110,7 @@ RSpec.describe QA::Git::Repository do end describe '#push_changes' do - let(:branch) { 'master' } + let(:branch) { QA::Runtime::Env.default_branch } let(:call_method) { repository.push_changes } let(:command) { "git push #{repo_uri_with_credentials} #{branch}" } diff --git a/qa/spec/resource/events/project_spec.rb b/qa/spec/resource/events/project_spec.rb index 88d50749a0a..fa74e2c8477 100644 --- a/qa/spec/resource/events/project_spec.rb +++ b/qa/spec/resource/events/project_spec.rb @@ -6,6 +6,10 @@ RSpec.describe QA::Resource::Events::Project do def api_get_path '/foo' end + + def default_branch + 'master' + end end end @@ -53,7 +57,7 @@ RSpec.describe QA::Resource::Events::Project do end describe "#wait_for_push_new_branch" do - it 'waits for a push to master if no branch is given' do + it 'waits for a push to the default branch if no branch is given' do expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed') expect { subject.wait_for_push_new_branch }.not_to raise_error end diff --git a/qa/spec/specs/helpers/quarantine_spec.rb b/qa/spec/specs/helpers/quarantine_spec.rb index 41bc3eadff4..80fd65faeed 100644 --- a/qa/spec/specs/helpers/quarantine_spec.rb +++ b/qa/spec/specs/helpers/quarantine_spec.rb @@ -423,17 +423,17 @@ RSpec.describe QA::Specs::Helpers::Quarantine do end end - context 'when a pipeline triggered from master runs in gitlab-qa' do + context 'when a pipeline triggered from the default branch runs in gitlab-qa' do before do stub_env('CI_PROJECT_NAME', 'gitlab-qa') described_class.configure_rspec end - it 'runs on master pipelines' 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-master pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] } ) {} + it('does not run in non-default pipelines', only: { pipeline: [:nightly, :not_nightly, :not_master] } ) {} end aggregate_failures do diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb index 8171cfcb3e6..b11054f0bd9 100644 --- a/qa/spec/specs/runner_spec.rb +++ b/qa/spec/specs/runner_spec.rb @@ -3,9 +3,9 @@ require 'active_support/core_ext/hash' RSpec.describe QA::Specs::Runner do - shared_examples 'excludes orchestrated' do - it 'excludes the orchestrated tag and includes default args' do - expect_rspec_runner_arguments(['--tag', '~orchestrated', *described_class::DEFAULT_TEST_PATH_ARGS]) + shared_examples 'excludes orchestrated and geo' do + it 'excludes the orchestrated and geo tags and includes default args' do + expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS]) subject.perform end @@ -18,13 +18,13 @@ RSpec.describe QA::Specs::Runner do QA::Runtime::Scenario.define(:gitlab_address, "http://gitlab.test") end - it_behaves_like 'excludes orchestrated' + it_behaves_like 'excludes orchestrated and geo' context 'when tty is set' do subject { described_class.new.tap { |runner| runner.tty = true } } it 'sets the `--tty` flag' do - expect_rspec_runner_arguments(['--tty', '--tag', '~orchestrated', *described_class::DEFAULT_TEST_PATH_ARGS]) + expect_rspec_runner_arguments(['--tty', '--tag', '~orchestrated', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS]) subject.perform end @@ -34,7 +34,7 @@ RSpec.describe QA::Specs::Runner do subject { described_class.new.tap { |runner| runner.tags = %i[orchestrated github] } } it 'focuses on the given tags' do - expect_rspec_runner_arguments(['--tag', 'orchestrated', '--tag', 'github', *described_class::DEFAULT_TEST_PATH_ARGS]) + expect_rspec_runner_arguments(['--tag', 'orchestrated', '--tag', 'github', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS]) subject.perform end @@ -44,7 +44,7 @@ RSpec.describe QA::Specs::Runner do subject { described_class.new.tap { |runner| runner.options = %w[--tag smoke] } } it 'focuses on the given tag without excluded the orchestrated tag' do - expect_rspec_runner_arguments(['--tag', 'smoke', *described_class::DEFAULT_TEST_PATH_ARGS]) + expect_rspec_runner_arguments(['--tag', '~geo', '--tag', 'smoke', *described_class::DEFAULT_TEST_PATH_ARGS]) subject.perform end @@ -53,8 +53,8 @@ RSpec.describe QA::Specs::Runner do context 'when "qa/specs/features/foo" is set as options' do subject { described_class.new.tap { |runner| runner.options = %w[qa/specs/features/foo] } } - it 'passes the given tests path and excludes the orchestrated tag' do - expect_rspec_runner_arguments(['--tag', '~orchestrated', 'qa/specs/features/foo']) + it 'passes the given tests path and excludes the orchestrated and geo tags' do + expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', 'qa/specs/features/foo']) subject.perform end @@ -64,7 +64,7 @@ RSpec.describe QA::Specs::Runner do subject { described_class.new.tap { |runner| runner.options = %w[--tag smoke qa/specs/features/foo] } } it 'focuses on the given tag and includes the path without excluding the orchestrated tag' do - expect_rspec_runner_arguments(['--tag', 'smoke', 'qa/specs/features/foo']) + expect_rspec_runner_arguments(['--tag', '~geo', '--tag', 'smoke', 'qa/specs/features/foo']) subject.perform end @@ -76,7 +76,7 @@ RSpec.describe QA::Specs::Runner do end it 'includes default args and excludes the skip_signup_disabled tag' do - expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS]) + expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS]) subject.perform end @@ -88,8 +88,24 @@ RSpec.describe QA::Specs::Runner do end it 'includes default args and excludes the skip_live_env tag' do - expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~skip_live_env', *described_class::DEFAULT_TEST_PATH_ARGS]) + expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', '--tag', '~skip_live_env', *described_class::DEFAULT_TEST_PATH_ARGS]) + subject.perform + end + end + + context 'when running against a Geo environment' do + before do + QA::Runtime::Scenario.define(:geo_secondary_address, "https://geo.staging.gitlab.com") + end + + after do + QA::Runtime::Scenario.attributes.delete(:geo_secondary_address) + end + + subject { described_class.new.tap { |runner| runner.tags = %i[geo] } } + it 'includes the geo tag' do + expect_rspec_runner_arguments(['--tag', 'geo', *described_class::DEFAULT_TEST_PATH_ARGS]) subject.perform end end @@ -105,7 +121,7 @@ RSpec.describe QA::Specs::Runner do end it 'includes default args and excludes all unsupported tags' do - expect_rspec_runner_arguments(['--tag', '~orchestrated', *excluded_feature_tags_except(feature), *described_class::DEFAULT_TEST_PATH_ARGS]) + expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', *excluded_feature_tags_except(feature), *described_class::DEFAULT_TEST_PATH_ARGS]) subject.perform end @@ -130,11 +146,11 @@ RSpec.describe QA::Specs::Runner do end end - it_behaves_like 'excludes orchestrated' + it_behaves_like 'excludes orchestrated and geo' end context 'when features are not specified' do - it_behaves_like 'excludes orchestrated' + it_behaves_like 'excludes orchestrated and geo' end end diff --git a/qa/spec/support/matchers/have_assignee.rb b/qa/spec/support/matchers/have_assignee.rb new file mode 100644 index 00000000000..5e7aa2162b2 --- /dev/null +++ b/qa/spec/support/matchers/have_assignee.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveAssignee + RSpec::Matchers.define :have_assignee do |assignee| + match do |page_object| + page_object.has_assignee?(assignee) + end + + match_when_negated do |page_object| + page_object.has_no_assignee?(assignee) + end + end + end +end diff --git a/qa/spec/support/matchers/have_child_pipeline.rb b/qa/spec/support/matchers/have_child_pipeline.rb new file mode 100644 index 00000000000..d05d9d4209a --- /dev/null +++ b/qa/spec/support/matchers/have_child_pipeline.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveChildPipeline + RSpec::Matchers.define :have_child_pipeline do + match do |page_object| + page_object.has_child_pipeline? + end + + match_when_negated do |page_object| + page_object.has_no_child_pipeline? + end + end + end +end diff --git a/qa/spec/support/matchers/have_content.rb b/qa/spec/support/matchers/have_content.rb new file mode 100644 index 00000000000..66b30b3b6e4 --- /dev/null +++ b/qa/spec/support/matchers/have_content.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveContent + RSpec::Matchers.define :have_content do |content| + match do |page_object| + page_object.has_content?(content) + end + + match_when_negated do |page_object| + page_object.has_no_content?(content) + end + end + end +end diff --git a/qa/spec/support/matchers/have_design.rb b/qa/spec/support/matchers/have_design.rb new file mode 100644 index 00000000000..85f1367297a --- /dev/null +++ b/qa/spec/support/matchers/have_design.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveDesign + RSpec::Matchers.define :have_design do |design| + match do |page_object| + page_object.has_design?(design) + end + + match_when_negated do |page_object| + page_object.has_no_design?(design) + end + end + end +end diff --git a/qa/spec/support/matchers/have_element.rb b/qa/spec/support/matchers/have_element.rb new file mode 100644 index 00000000000..bf74a78a3b5 --- /dev/null +++ b/qa/spec/support/matchers/have_element.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveElement + RSpec::Matchers.define :have_element do |element, **kwargs| + match do |page_object| + page_object.has_element?(element, **kwargs) + end + + match_when_negated do |page_object| + page_object.has_no_element?(element, **kwargs) + end + end + end +end diff --git a/qa/spec/support/matchers/have_file_content.rb b/qa/spec/support/matchers/have_file_content.rb new file mode 100644 index 00000000000..e42ece6d59e --- /dev/null +++ b/qa/spec/support/matchers/have_file_content.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveFileContent + RSpec::Matchers.define :have_file_content do |file_content, file_number| + match do |page_object| + page_object.has_file_content?(file_content, file_number) + end + + match_when_negated do |page_object| + page_object.has_no_file_content?(file_content, file_number) + end + end + end +end diff --git a/qa/spec/support/matchers/have_issue.rb b/qa/spec/support/matchers/have_issue.rb new file mode 100644 index 00000000000..7ef30f22726 --- /dev/null +++ b/qa/spec/support/matchers/have_issue.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveIssue + RSpec::Matchers.define :have_issue do |issue| + match do |page_object| + page_object.has_issue?(issue) + end + + match_when_negated do |page_object| + page_object.has_no_issue?(issue) + end + end + end +end diff --git a/qa/spec/support/matchers/have_job.rb b/qa/spec/support/matchers/have_job.rb new file mode 100644 index 00000000000..89829915fce --- /dev/null +++ b/qa/spec/support/matchers/have_job.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveJob + RSpec::Matchers.define :have_job do |job| + match do |page_object| + page_object.has_job?(job) + end + + match_when_negated do |page_object| + page_object.has_no_job?(job) + end + end + end +end diff --git a/qa/spec/support/matchers/have_package.rb b/qa/spec/support/matchers/have_package.rb new file mode 100644 index 00000000000..86e9bfee4d1 --- /dev/null +++ b/qa/spec/support/matchers/have_package.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HavePackage + RSpec::Matchers.define :have_package do |package| + match do |page_object| + page_object.has_package?(package) + end + + match_when_negated do |page_object| + page_object.has_no_package?(package) + end + end + end +end diff --git a/qa/spec/support/matchers/have_pipeline.rb b/qa/spec/support/matchers/have_pipeline.rb new file mode 100644 index 00000000000..2bfd49d671a --- /dev/null +++ b/qa/spec/support/matchers/have_pipeline.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HavePipeline + RSpec::Matchers.define :have_pipeline do + match do |page_object| + page_object.has_pipeline? + end + + match_when_negated do |page_object| + page_object.has_no_pipeline? + end + end + end +end diff --git a/qa/spec/support/matchers/have_related_issue_item.rb b/qa/spec/support/matchers/have_related_issue_item.rb new file mode 100644 index 00000000000..89403f2422a --- /dev/null +++ b/qa/spec/support/matchers/have_related_issue_item.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveRelatedIssueItem + RSpec::Matchers.define :have_related_issue_item do + match do |page_object| + page_object.has_related_issue_item? + end + + match_when_negated do |page_object| + page_object.has_no_related_issue_item? + end + end + end +end diff --git a/qa/spec/support/matchers/have_snippet_description.rb b/qa/spec/support/matchers/have_snippet_description.rb new file mode 100644 index 00000000000..7c407aefc83 --- /dev/null +++ b/qa/spec/support/matchers/have_snippet_description.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Matchers + module HaveSnippetDescription + RSpec::Matchers.define :have_snippet_description do |description| + match do |page_object| + page_object.has_snippet_description?(description) + end + + match_when_negated do |page_object| + page_object.has_no_snippet_description? + end + end + end +end diff --git a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb index 610bf8b9e28..40a8be8202a 100644 --- a/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb +++ b/qa/spec/support/shared_examples/merge_with_code_owner_shared_examples.rb @@ -30,10 +30,17 @@ module QA ) end - # Require approval from code owners on master - Resource::ProtectedBranch.fabricate! do |protected_branch| + # Require approval from code owners on the default branch + # The default branch is already protected, and we can't update a protected branch via the API (yet) + # so we unprotect it first and then protect it again with the desired parameters + Resource::ProtectedBranch.unprotect_via_api! do |protected_branch| protected_branch.project = project - protected_branch.branch_name = 'master' + protected_branch.branch_name = project.default_branch + end + + Resource::ProtectedBranch.fabricate_via_api! do |protected_branch| + protected_branch.project = project + protected_branch.branch_name = project.default_branch protected_branch.new_branch = false protected_branch.require_code_owner_approval = true end |