summaryrefslogtreecommitdiff
path: root/qa/qa/page
diff options
context:
space:
mode:
Diffstat (limited to 'qa/qa/page')
-rw-r--r--qa/qa/page/admin/menu.rb46
-rw-r--r--qa/qa/page/admin/overview/users/index.rb35
-rw-r--r--qa/qa/page/admin/overview/users/show.rb21
-rw-r--r--qa/qa/page/base.rb21
-rw-r--r--qa/qa/page/component/ci_badge_link.rb36
-rw-r--r--qa/qa/page/component/note.rb11
-rw-r--r--qa/qa/page/group/new.rb2
-rw-r--r--qa/qa/page/main/login.rb18
-rw-r--r--qa/qa/page/main/menu.rb21
-rw-r--r--qa/qa/page/merge_request/show.rb66
-rw-r--r--qa/qa/page/profile/emails.rb29
-rw-r--r--qa/qa/page/profile/menu.rb14
-rw-r--r--qa/qa/page/profile/password.rb23
-rw-r--r--qa/qa/page/project/issue/index.rb16
-rw-r--r--qa/qa/page/project/issue/show.rb70
-rw-r--r--qa/qa/page/project/job/show.rb29
-rw-r--r--qa/qa/page/project/milestone/index.rb2
-rw-r--r--qa/qa/page/project/pipeline/show.rb20
-rw-r--r--qa/qa/page/project/settings/main.rb9
-rw-r--r--qa/qa/page/project/settings/merge_request.rb13
-rw-r--r--qa/qa/page/project/settings/mirroring_repositories.rb55
-rw-r--r--qa/qa/page/project/settings/repository.rb6
-rw-r--r--qa/qa/page/validator.rb2
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