diff options
Diffstat (limited to 'qa/qa/page')
23 files changed, 461 insertions, 104 deletions
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb index 5a18ebd7af8..2d1af78046d 100644 --- a/qa/qa/page/admin/menu.rb +++ b/qa/qa/page/admin/menu.rb @@ -6,12 +6,16 @@ module QA class Menu < Page::Base view 'app/views/layouts/nav/sidebar/_admin.html.haml' do element :admin_sidebar - element :admin_sidebar_submenu + element :admin_sidebar_settings_submenu element :admin_settings_item element :admin_settings_repository_item element :admin_settings_general_item element :admin_settings_metrics_and_profiling_item element :admin_settings_preferences_link + element :admin_monitoring_link + element :admin_sidebar_monitoring_submenu_content + element :admin_sidebar_overview_submenu_content + element :users_overview_link end view 'app/views/layouts/nav/sidebar/_admin.html.haml' do @@ -19,59 +23,65 @@ module QA end def go_to_preferences_settings - hover_settings do - within_submenu do + hover_element(:admin_settings_item) do + within_submenu(:admin_sidebar_settings_submenu) do click_element :admin_settings_preferences_link end end end def go_to_repository_settings - hover_settings do - within_submenu do + hover_element(:admin_settings_item) do + within_submenu(:admin_sidebar_settings_submenu) do click_element :admin_settings_repository_item end end end def go_to_integration_settings - hover_settings do - within_submenu do + hover_element(:admin_settings_item) do + within_submenu(:admin_sidebar_settings_submenu) do click_element :integration_settings_link end end end def go_to_general_settings - hover_settings do - within_submenu do + hover_element(:admin_settings_item) do + within_submenu(:admin_sidebar_settings_submenu) do click_element :admin_settings_general_item end end end def go_to_metrics_and_profiling_settings - hover_settings do - within_submenu do + hover_element(:admin_settings_item) do + within_submenu(:admin_sidebar_settings_submenu) do click_element :admin_settings_metrics_and_profiling_item end end end def go_to_network_settings - hover_settings do - within_submenu do + hover_element(:admin_settings_item) do + within_submenu(:admin_sidebar_settings_submenu) do click_element :admin_settings_network_item end end end + def go_to_users_overview + within_submenu(:admin_sidebar_overview_submenu_content) do + click_element :users_overview_link + end + end + private - def hover_settings + def hover_element(element) within_sidebar do - scroll_to_element(:admin_settings_item) - find_element(:admin_settings_item).hover + scroll_to_element(element) + find_element(element).hover yield end @@ -83,8 +93,8 @@ module QA end end - def within_submenu - within_element(:admin_sidebar_submenu) do + def within_submenu(element) + within_element(element) do yield end end diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb new file mode 100644 index 00000000000..e374c1bf281 --- /dev/null +++ b/qa/qa/page/admin/overview/users/index.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module QA + module Page + module Admin + module Overview + module Users + class Index < QA::Page::Base + view 'app/views/admin/users/index.html.haml' do + element :user_search_field + end + + view 'app/views/admin/users/_user.html.haml' do + element :user_row_content + end + + view 'app/views/admin/users/_user_detail.html.haml' do + element :username_link + end + + def search_user(username) + find_element(:user_search_field).set(username).send_keys(:return) + end + + def click_user(username) + within_element(:user_row_content, text: username) do + click_element(:username_link) + end + end + end + end + end + end + end +end diff --git a/qa/qa/page/admin/overview/users/show.rb b/qa/qa/page/admin/overview/users/show.rb new file mode 100644 index 00000000000..11ea7bcabc8 --- /dev/null +++ b/qa/qa/page/admin/overview/users/show.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module QA + module Page + module Admin + module Overview + module Users + class Show < QA::Page::Base + view 'app/views/admin/users/_head.html.haml' do + element :impersonate_user_link + end + + def click_impersonate_user + click_element(:impersonate_user_link) + end + end + end + end + end + end +end diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 45496c6b245..71df90f2f42 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -15,6 +15,10 @@ module QA def_delegators :evaluator, :view, :views + def assert_no_element(name) + assert_no_selector(element_selector_css(name)) + end + def refresh page.refresh end @@ -90,8 +94,8 @@ module QA end # replace with (..., page = self.class) - def click_element(name, page = nil) - find_element(name).click + def click_element(name, page = nil, text: nil) + find_element(name, text: text).click page.validate_elements_present! if page end @@ -102,9 +106,9 @@ module QA def select_element(name, value) element = find_element(name) - return if element.text.downcase.to_s == value.to_s + return if element.text == value - element.select value.to_s.capitalize + element.select value end def has_element?(name, text: nil, wait: Capybara.default_max_wait_time) @@ -127,6 +131,10 @@ module QA has_no_css?('.fa-spinner', wait: Capybara.default_max_wait_time) end + def finished_loading_block? + has_no_css?('.fa-spinner.block-loading', wait: Capybara.default_max_wait_time) + end + def wait_for_animated_element(name) # It would be ideal if we could detect when the animation is complete # but in some cases there's nothing we can easily access via capybara @@ -143,6 +151,11 @@ module QA end def within_element_by_index(name, index) + # Finding all elements can be flaky if the elements don't all load + # immediately. So we wait for any to appear before trying to find a + # specific one. + has_element?(name) + page.within all_elements(name)[index] do yield end diff --git a/qa/qa/page/component/ci_badge_link.rb b/qa/qa/page/component/ci_badge_link.rb new file mode 100644 index 00000000000..aad8dc1d3df --- /dev/null +++ b/qa/qa/page/component/ci_badge_link.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module QA + module Page + module Component + module CiBadgeLink + COMPLETED_STATUSES = %w[passed failed canceled blocked skipped manual].freeze # excludes created, pending, running + PASSED_STATUS = 'passed'.freeze + + def self.included(base) + base.view 'app/assets/javascripts/vue_shared/components/ci_badge_link.vue' do + element :status_badge + end + end + + def status_badge + find_element(:status_badge).text + end + + def successful?(timeout: 60) + raise "Timed out waiting for the status to be a valid completed state" unless completed?(timeout: timeout) + + status_badge == PASSED_STATUS + end + + private + + def completed?(timeout: 60) + wait(reload: false, max: timeout) do + COMPLETED_STATUSES.include?(status_badge) + end + end + end + end + end +end diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb index 34fde045091..c85fa690d6c 100644 --- a/qa/qa/page/component/note.rb +++ b/qa/qa/page/component/note.rb @@ -10,6 +10,10 @@ module QA element :discussion_option end + base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do + element :discussion_content + end + base.view 'app/assets/javascripts/notes/components/note_actions.vue' do element :note_edit_button end @@ -21,6 +25,7 @@ module QA base.view 'app/assets/javascripts/notes/components/discussion_actions.vue' do element :discussion_reply_tab + element :resolve_discussion_button end base.view 'app/assets/javascripts/notes/components/toggle_replies_widget.vue' do @@ -54,6 +59,12 @@ module QA click_element :reply_comment_button end + def resolve_discussion_at_index(index) + within_element_by_index(:discussion_content, index) do + click_element :resolve_discussion_button + end + end + def collapse_replies click_element :collapse_replies end diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb index 9e37d14fbf3..e01b8754d55 100644 --- a/qa/qa/page/group/new.rb +++ b/qa/qa/page/group/new.rb @@ -11,7 +11,7 @@ module QA end view 'app/views/groups/new.html.haml' do - element :create_group_button, "submit 'Create group'" # rubocop:disable QA/ElementWithPattern + element :create_group_button, "submit _('Create group')" # rubocop:disable QA/ElementWithPattern element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern end diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index ca93663dba2..6e266e26d78 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -42,7 +42,7 @@ module QA element :login_page, required: true end - def sign_in_using_credentials(user = nil) + def sign_in_using_credentials(user: nil, skip_page_validation: false) # Don't try to log-in if we're already logged-in return if Page::Main::Menu.perform(&:signed_in?) @@ -52,9 +52,9 @@ module QA raise NotImplementedError if Runtime::User.ldap_user? && user&.credentials_given? if Runtime::User.ldap_user? - sign_in_using_ldap_credentials(user || Runtime::User) + sign_in_using_ldap_credentials(user: user || Runtime::User) else - sign_in_using_gitlab_credentials(user || Runtime::User) + sign_in_using_gitlab_credentials(user: user || Runtime::User, skip_page_validation: skip_page_validation) end end end @@ -68,13 +68,13 @@ module QA using_wait_time 0 do set_initial_password_if_present - sign_in_using_gitlab_credentials(admin) + sign_in_using_gitlab_credentials(user: admin) end Page::Main::Menu.perform(&:has_personal_area?) end - def sign_in_using_ldap_credentials(user) + def sign_in_using_ldap_credentials(user:) Page::Main::Menu.perform(&:sign_out_if_signed_in) using_wait_time 0 do @@ -87,7 +87,7 @@ module QA click_element :sign_in_button end - Page::Main::Menu.perform(&:has_personal_area?) + Page::Main::Menu.perform(&:signed_in?) end def self.path @@ -148,18 +148,18 @@ module QA def sign_out_and_sign_in_as(user:) Menu.perform(&:sign_out_if_signed_in) has_sign_in_tab? - sign_in_using_credentials(user) + sign_in_using_credentials(user: user) end private - def sign_in_using_gitlab_credentials(user) + def sign_in_using_gitlab_credentials(user:, skip_page_validation: false) switch_to_sign_in_tab if has_sign_in_tab? switch_to_standard_tab if has_standard_tab? fill_element :login_field, user.username fill_element :password_field, user.password - click_element :sign_in_button, Page::Main::Menu + click_element :sign_in_button, !skip_page_validation && Page::Main::Menu end def set_initial_password_if_present diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb index 751b67d7695..024f56db8e2 100644 --- a/qa/qa/page/main/menu.rb +++ b/qa/qa/page/main/menu.rb @@ -13,12 +13,14 @@ module QA element :navbar, required: true element :user_avatar, required: true element :user_menu, required: true + element :stop_impersonation_link end view 'app/views/layouts/nav/_dashboard.html.haml' do element :admin_area_link element :projects_dropdown, required: true element :groups_dropdown, required: true + element :more_dropdown, required: true element :snippets_link end @@ -51,6 +53,13 @@ module QA end end + def go_to_snippets + within_top_menu do + click_element :more_dropdown + click_element :snippets_link + end + end + def click_admin_area within_top_menu { click_element :admin_area_link } end @@ -79,10 +88,6 @@ module QA end end - def click_snippets_link - click_element :snippets_link - end - def search_for(term) fill_element :search_term_field, "#{term}\n" end @@ -95,6 +100,14 @@ module QA has_element?(:admin_area_link, wait: wait) end + def has_no_admin_area_link?(wait: Capybara.default_max_wait_time) + has_no_element?(:admin_area_link, wait: wait) + end + + def click_stop_impersonation_link + click_element(:stop_impersonation_link) + end + private def within_top_menu diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index 6e550805f9f..14b8c420b16 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -6,6 +6,17 @@ module QA class Show < Page::Base include Page::Component::Note + view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do + element :dropdown_toggle + element :download_email_patches + element :download_plain_diff + end + + view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue' do + element :merge_request_pipeline_info_content + element :pipeline_link + end + view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do element :merge_button element :fast_forward_message, 'Fast-forward merge without a merge commit' # rubocop:disable QA/ElementWithPattern @@ -27,12 +38,6 @@ module QA element :squash_checkbox end - view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do - element :dropdown_toggle - element :download_email_patches - element :download_plain_diff - end - view 'app/views/projects/merge_requests/show.html.haml' do element :notes_tab element :diffs_tab @@ -55,6 +60,18 @@ module QA element :edit_button end + def click_discussions_tab + click_element :notes_tab + end + + def click_diffs_tab + click_element :diffs_tab + end + + def click_pipeline_link + click_element :pipeline_link + end + def fast_forward_possible? has_no_text?('Fast-forward merge is not possible') end @@ -111,6 +128,11 @@ module QA end end + def has_pipeline_status?(text) + # Pipelines can be slow, so we wait a bit longer than the usual 10 seconds + has_element?(:merge_request_pipeline_info_content, text: text, wait: 30) + end + def has_title?(title) has_element?(:title, text: title) end @@ -120,17 +142,7 @@ module QA end def try_to_merge! - # The merge button is disabled on load - wait do - has_element?(:merge_button) - end - - # The merge button is enabled via JS - wait(reload: false) do - !find_element(:merge_button).disabled? - end - - merge_immediately + merge_immediately if ready_to_merge? end def merge! @@ -157,14 +169,6 @@ module QA click_element :squash_checkbox end - def click_discussions_tab - click_element :notes_tab - end - - def click_diffs_tab - click_element :diffs_tab - end - def add_comment_to_diff(text) wait(interval: 5) do has_text?("No newline at end of file") @@ -178,6 +182,18 @@ module QA click_element :edit_button end + def ready_to_merge? + # The merge button is disabled on load + wait do + has_element?(:merge_button) + end + + # The merge button is enabled via JS + wait(reload: false) do + !find_element(:merge_button).disabled? + end + end + def view_email_patches click_element :dropdown_toggle visit_link_in_element(:download_email_patches) diff --git a/qa/qa/page/profile/emails.rb b/qa/qa/page/profile/emails.rb new file mode 100644 index 00000000000..c20bc6a5c57 --- /dev/null +++ b/qa/qa/page/profile/emails.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module QA + module Page + module Profile + class Emails < Page::Base + view 'app/views/profiles/emails/index.html.haml' do + element :email_address_field + element :add_email_address_button + element :email_row_content + element :delete_email_link + end + + def add_email_address(email_address) + find_element(:email_address_field).set email_address + click_element(:add_email_address_button) + end + + def delete_email_address(email_address) + page.accept_alert do + within_element(:email_row_content, text: email_address) do + click_element(:delete_email_link) + end + end + end + end + end + end +end diff --git a/qa/qa/page/profile/menu.rb b/qa/qa/page/profile/menu.rb index 99a795a23ef..e7baaf3d40a 100644 --- a/qa/qa/page/profile/menu.rb +++ b/qa/qa/page/profile/menu.rb @@ -9,6 +9,8 @@ module QA element :access_token_title, 'Access Tokens' # rubocop:disable QA/ElementWithPattern element :top_level_items, '.sidebar-top-level-items' # rubocop:disable QA/ElementWithPattern element :ssh_keys, 'SSH Keys' # rubocop:disable QA/ElementWithPattern + element :profile_emails_link + element :profile_password_link end def click_access_tokens @@ -23,6 +25,18 @@ module QA end end + def click_emails + within_sidebar do + click_element(:profile_emails_link) + end + end + + def click_password + within_sidebar do + click_element(:profile_password_link) + end + end + private def within_sidebar diff --git a/qa/qa/page/profile/password.rb b/qa/qa/page/profile/password.rb new file mode 100644 index 00000000000..ce062f39edb --- /dev/null +++ b/qa/qa/page/profile/password.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + module Page + module Profile + class Password < Page::Base + view 'app/views/profiles/passwords/edit.html.haml' do + element :current_password_field + element :new_password_field + element :confirm_password_field + element :save_password_button + end + + def update_password(new_password, current_password) + find_element(:current_password_field).set current_password + find_element(:new_password_field).set new_password + find_element(:confirm_password_field).set new_password + click_element(:save_password_button) + end + end + end + end +end diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb index f74366f6967..befee25b37a 100644 --- a/qa/qa/page/project/issue/index.rb +++ b/qa/qa/page/project/issue/index.rb @@ -5,14 +5,30 @@ module QA module Project module Issue class Index < Page::Base + view 'app/helpers/projects_helper.rb' do + element :assignee_link + end + view 'app/views/projects/issues/_issue.html.haml' do element :issue_link, 'link_to issue.title' # rubocop:disable QA/ElementWithPattern end + view 'app/views/shared/issuable/_assignees.html.haml' do + element :avatar_counter + end + view 'app/views/shared/issuable/_nav.html.haml' do element :closed_issues_link end + def assignee_link_count + all_elements(:assignee_link).count + end + + def avatar_counter + find_element(:avatar_counter) + end + def click_issue_link(title) click_link(title) end diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb index e5e26b1864b..d2732eb7dd2 100644 --- a/qa/qa/page/project/issue/show.rb +++ b/qa/qa/page/project/issue/show.rb @@ -22,30 +22,68 @@ module QA element :noteable_note_item end + view 'app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue' do + element :avatar_image + end + + view 'app/assets/javascripts/sidebar/components/assignees/assignee_title.vue' do + element :assignee_edit_link + element :assignee_title + end + + view 'app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue' do + element :more_assignees_link + end + + view 'app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue' do + element :remove_related_issue_button + end + view 'app/helpers/dropdowns_helper.rb' do element :dropdown_input_field end - view 'app/views/shared/notes/_form.html.haml' do - element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern - element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern + view 'app/views/shared/issuable/_close_reopen_button.html.haml' do + element :reopen_issue_button end view 'app/views/shared/issuable/_sidebar.html.haml' do + element :assignee_block element :labels_block element :edit_link_labels element :dropdown_menu_labels element :milestone_link end - view 'app/views/shared/issuable/_close_reopen_button.html.haml' do - element :reopen_issue_button + view 'app/views/shared/notes/_form.html.haml' do + element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern + element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern + end + + def assign(user) + click_element(:assignee_edit_link) + select_user(user.username) + click_body + end + + def assignee_title + find_element(:assignee_title) + end + + def avatar_image_count + wait_assignees_block_finish_loading do + all_elements(:avatar_image).count + end end def click_milestone_link click_element(:milestone_link) end + def click_remove_related_issue_button + click_element(:remove_related_issue_button) + end + # Adds a comment to an issue # attachment option should be an absolute path def comment(text, attachment: nil, filter: :all_activities) @@ -66,6 +104,10 @@ module QA end end + def more_assignees_link + find_element(:more_assignees_link) + end + def select_all_activities_filter select_filter_with_text('Show all activity') end @@ -103,6 +145,10 @@ module QA find_element(:labels_block) end + def toggle_more_assignees_link + click_element(:more_assignees_link) + end + private def select_filter_with_text(text) @@ -112,6 +158,20 @@ module QA find_element(:filter_options, text: text).click end end + + def select_user(username) + find("#{element_selector_css(:assignee_block)} input").set(username) + find('.dropdown-menu-user-link', text: "@#{username}").click + end + + def wait_assignees_block_finish_loading + within_element(:assignee_block) do + wait(reload: false, max: 10, interval: 1) do + finished_loading_block? + yield + end + end + end end end end diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb index 5853f487f0b..cf847710024 100644 --- a/qa/qa/page/project/job/show.rb +++ b/qa/qa/page/project/job/show.rb @@ -3,17 +3,12 @@ module QA::Page module Project::Job class Show < QA::Page::Base - COMPLETED_STATUSES = %w[passed failed canceled blocked skipped manual].freeze # excludes created, pending, running - PASSED_STATUS = 'passed'.freeze + include Component::CiBadgeLink view 'app/assets/javascripts/jobs/components/job_log.vue' do element :build_trace end - view 'app/assets/javascripts/vue_shared/components/ci_badge_link.vue' do - element :status_badge - end - view 'app/assets/javascripts/jobs/components/stages_dropdown.vue' do element :pipeline_path end @@ -26,8 +21,16 @@ module QA::Page end # Reminder: You may wish to wait for a particular job status before checking output - def output - find_element(:build_trace).text + def output(wait: 5) + result = '' + + wait(reload: false, max: wait, interval: 1) do + result = find_element(:build_trace).text + + !result.empty? + end + + result end private @@ -37,16 +40,6 @@ module QA::Page has_element?(:build_trace, wait: 1) end end - - def completed?(timeout: 60) - wait(reload: false, max: timeout) do - COMPLETED_STATUSES.include?(status_badge) - end - end - - def status_badge - find_element(:status_badge).text - end end end end diff --git a/qa/qa/page/project/milestone/index.rb b/qa/qa/page/project/milestone/index.rb index 8ad7689ce70..6895c44f72f 100644 --- a/qa/qa/page/project/milestone/index.rb +++ b/qa/qa/page/project/milestone/index.rb @@ -17,5 +17,3 @@ module QA end end end - -QA::Page::Project::Milestone::Index.prepend_if_ee('QA::EE::Page::Project::Milestone::Index') diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb index 3dca47a57e9..fd29c5eacdc 100644 --- a/qa/qa/page/project/pipeline/show.rb +++ b/qa/qa/page/project/pipeline/show.rb @@ -3,6 +3,8 @@ module QA::Page module Project::Pipeline class Show < QA::Page::Base + include Component::CiBadgeLink + view 'app/assets/javascripts/vue_shared/components/header_ci_component.vue' do element :pipeline_header, /header class.*ci-header-container.*/ # rubocop:disable QA/ElementWithPattern end @@ -16,6 +18,10 @@ module QA::Page element :job_link end + view 'app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue' do + element :linked_pipeline_button + end + view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do element :status_icon, 'ci-status-icon-${status}' # rubocop:disable QA/ElementWithPattern end @@ -38,6 +44,14 @@ module QA::Page end end + def has_job?(job_name) + has_element?(:job_link, text: job_name) + end + + def has_no_job?(job_name) + has_no_element?(:job_link, text: job_name) + end + def has_tag?(tag_name) within_element(:pipeline_badges) do has_selector?('.badge', text: tag_name) @@ -45,7 +59,11 @@ module QA::Page end def click_job(job_name) - find_element(:job_link, text: job_name).click + click_element(:job_link, text: job_name) + end + + def click_linked_job(project_name) + click_element(:linked_pipeline_button, text: /#{project_name}/) end def click_on_first_job diff --git a/qa/qa/page/project/settings/main.rb b/qa/qa/page/project/settings/main.rb index 6b26c82a46f..18d55598d90 100644 --- a/qa/qa/page/project/settings/main.rb +++ b/qa/qa/page/project/settings/main.rb @@ -11,6 +11,7 @@ module QA view 'app/views/projects/edit.html.haml' do element :advanced_settings + element :merge_request_settings end view 'app/views/projects/settings/_general.html.haml' do @@ -41,6 +42,12 @@ module QA end end + def expand_merge_requests_settings(&block) + expand_section(:merge_request_settings) do + MergeRequest.perform(&block) + end + end + def expand_visibility_project_features_permissions(&block) expand_section(:visibility_features_permissions_content) do VisibilityFeaturesPermissions.perform(&block) @@ -51,5 +58,3 @@ module QA end end end - -QA::Page::Project::Settings::Main.prepend_if_ee('QA::EE::Page::Project::Settings::Main') diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb index f92528c4262..7da2c9d168c 100644 --- a/qa/qa/page/project/settings/merge_request.rb +++ b/qa/qa/page/project/settings/merge_request.rb @@ -8,7 +8,6 @@ module QA include Common view 'app/views/projects/edit.html.haml' do - element :merge_request_settings element :save_merge_request_changes end @@ -16,14 +15,18 @@ module QA element :radio_button_merge_ff end + def click_save_changes + click_element :save_merge_request_changes + end + def enable_ff_only - expand_section(:merge_request_settings) do - click_element :radio_button_merge_ff - click_element :save_merge_request_changes - end + click_element :radio_button_merge_ff + click_save_changes end end end end end end + +QA::Page::Project::Settings::MergeRequest.prepend_if_ee("QA::EE::Page::Project::Settings::MergeRequest") diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb index 441235afca8..4afe042d9fb 100644 --- a/qa/qa/page/project/settings/mirroring_repositories.rb +++ b/qa/qa/page/project/settings/mirroring_repositories.rb @@ -15,7 +15,9 @@ module QA element :mirror_repository_button element :mirror_repository_url_cell element :mirror_last_update_at_cell + element :mirror_error_badge element :mirrored_repository_row + element :copy_public_key_button end view 'app/views/projects/mirrors/_mirror_repos_form.html.haml' do @@ -24,6 +26,17 @@ module QA view 'app/views/shared/_remote_mirror_update_button.html.haml' do element :update_now_button + element :updating_button + end + + view 'app/views/projects/mirrors/_ssh_host_keys.html.haml' do + element :detect_host_keys + element :fingerprints_list + end + + view 'app/views/projects/mirrors/_authentication_method.html.haml' do + element :authentication_method + element :password end def repository_url=(value) @@ -35,17 +48,40 @@ module QA end def mirror_direction=(value) - raise ArgumentError, "Mirror direction must be :push or :pull" unless [:push, :pull].include? value + raise ArgumentError, "Mirror direction must be 'Push' or 'Pull'" unless %w(Push Pull).include? value select_element(:mirror_direction, value) + + # Changing the mirror direction causes the fields below to change, + # and that change is animated, so we need to wait for the animation + # to complete otherwise changes to those fields could fail + wait_for_animated_element :authentication_method end def authentication_method=(value) - raise ArgumentError, "Authentication method must be :password or :none" unless [:password, :none].include? value + raise ArgumentError, "Authentication method must be 'SSH public key', 'Password', or 'None'" unless %w(Password None SSH\ public\ key).include? value select_element(:authentication_method, value) end + def public_key(url) + row_index = find_repository_row_index url + + within_element_by_index(:mirrored_repository_row, row_index) do + find_element(:copy_public_key_button)['data-clipboard-text'] + end + end + + def detect_host_keys + click_element :detect_host_keys + + # The host key detection process is interrupted if we navigate away + # from the page before the fingerprint appears. + wait(max: 5) do + find_element(:fingerprints_list).has_text? /.*/ + end + end + def mirror_repository click_element :mirror_repository_button end @@ -54,7 +90,9 @@ module QA row_index = find_repository_row_index url within_element_by_index(:mirrored_repository_row, row_index) do - click_element :update_now_button + # When a repository is first mirrored, the update process might + # already be started, so the button is already "clicked" + click_element :update_now_button unless has_element? :updating_button end # Wait a few seconds for the sync to occur and then refresh the page @@ -72,16 +110,19 @@ module QA # Fail early if the page still shows that there has been no update within_element_by_index(:mirrored_repository_row, row_index) do find_element(:mirror_last_update_at_cell, wait: 0).assert_no_text('Never') + assert_no_element(:mirror_error_badge) end end private def find_repository_row_index(target_url) - all_elements(:mirror_repository_url_cell).index do |url| - # The url might be a sanitized url but the target_url won't be so - # we compare just the paths instead of the full url - URI.parse(url.text).path == target_url.path + wait(max: 5, reload: false) do + all_elements(:mirror_repository_url_cell).index do |url| + # The url might be a sanitized url but the target_url won't be so + # we compare just the paths instead of the full url + URI.parse(url.text).path == target_url.path + end end end end diff --git a/qa/qa/page/project/settings/repository.rb b/qa/qa/page/project/settings/repository.rb index 437a945aceb..58ed37870b7 100644 --- a/qa/qa/page/project/settings/repository.rb +++ b/qa/qa/page/project/settings/repository.rb @@ -16,7 +16,7 @@ module QA end view 'app/views/projects/mirrors/_mirror_repos.html.haml' do - element :mirroring_repositories_settings + element :mirroring_repositories_settings_section end def expand_deploy_keys(&block) @@ -38,7 +38,7 @@ module QA end def expand_mirroring_repositories(&block) - expand_section(:mirroring_repositories_settings) do + expand_section(:mirroring_repositories_settings_section) do MirroringRepositories.perform(&block) end end @@ -47,3 +47,5 @@ module QA end end end + +QA::Page::Project::Settings::Repository.prepend_if_ee('QA::EE::Page::Project::Settings::Repository') diff --git a/qa/qa/page/validator.rb b/qa/qa/page/validator.rb index 9b2d0a1a41d..75e48b5785e 100644 --- a/qa/qa/page/validator.rb +++ b/qa/qa/page/validator.rb @@ -17,7 +17,7 @@ module QA def constants @consts ||= @module.constants.map do |const| - @module.const_get(const) + @module.const_get(const, false) end end |