diff options
Diffstat (limited to 'qa/qa/page')
-rw-r--r-- | qa/qa/page/component/content_editor.rb | 5 | ||||
-rw-r--r-- | qa/qa/page/component/dropdown.rb | 14 | ||||
-rw-r--r-- | qa/qa/page/component/groups_filter.rb | 45 | ||||
-rw-r--r-- | qa/qa/page/component/invite_members_modal.rb | 20 | ||||
-rw-r--r-- | qa/qa/page/component/wiki_page_form.rb | 10 | ||||
-rw-r--r-- | qa/qa/page/file/form.rb | 16 | ||||
-rw-r--r-- | qa/qa/page/group/members.rb | 11 | ||||
-rw-r--r-- | qa/qa/page/merge_request/show.rb | 7 | ||||
-rw-r--r-- | qa/qa/page/project/fork/new.rb | 16 | ||||
-rw-r--r-- | qa/qa/page/project/pipeline/new.rb | 2 | ||||
-rw-r--r-- | qa/qa/page/project/settings/alerts.rb | 25 | ||||
-rw-r--r-- | qa/qa/page/project/settings/ci_variables.rb | 2 | ||||
-rw-r--r-- | qa/qa/page/project/settings/protected_branches.rb | 9 | ||||
-rw-r--r-- | qa/qa/page/project/show.rb | 11 | ||||
-rw-r--r-- | qa/qa/page/project/web_ide/vscode.rb | 68 |
15 files changed, 186 insertions, 75 deletions
diff --git a/qa/qa/page/component/content_editor.rb b/qa/qa/page/component/content_editor.rb index e9fc575ae39..a9abda42610 100644 --- a/qa/qa/page/component/content_editor.rb +++ b/qa/qa/page/component/content_editor.rb @@ -15,7 +15,6 @@ module QA base.view 'app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue' do element :text_style_dropdown - element :text_style_menu_item end base.view 'app/assets/javascripts/content_editor/components/toolbar_image_button.vue' do @@ -33,9 +32,7 @@ module QA # wait for text style option to become active after typing has_active_element?(:text_style_dropdown, wait: 1) click_element(:text_style_dropdown) - within_element(:text_style_dropdown) do - click_element(:text_style_menu_item, text_style: heading) - end + find_element(:text_style_dropdown).find('li', text: heading).click end end diff --git a/qa/qa/page/component/dropdown.rb b/qa/qa/page/component/dropdown.rb index e6204fb5332..c3e0fefee0d 100644 --- a/qa/qa/page/component/dropdown.rb +++ b/qa/qa/page/component/dropdown.rb @@ -25,6 +25,12 @@ module QA find('span.gl-dropdown-button-text').text end + def all_items + raise NotImplementedError if use_select2? + + find_all("li.gl-dropdown-item").map(&:text) + end + def clear_current_selection_if_present return super if use_select2? @@ -40,7 +46,12 @@ module QA def search_item(item_text) return super if use_select2? - find('div.gl-search-box-by-type input[type="Search"]').set(item_text) + find('div.gl-listbox-search input[type="Search"]').set(item_text) + wait_for_search_to_complete + end + + def send_keys_to_search(item_text) + find('div.gl-listbox-search input[type="Search"]').send_keys(item_text) wait_for_search_to_complete end @@ -103,6 +114,7 @@ module QA def use_select2? @use_select2 ||= has_css?('.select2-container', wait: 1) end + # rubocop:enable Gitlab/PredicateMemoization end end diff --git a/qa/qa/page/component/groups_filter.rb b/qa/qa/page/component/groups_filter.rb index ec59d010718..ea91ced8679 100644 --- a/qa/qa/page/component/groups_filter.rb +++ b/qa/qa/page/component/groups_filter.rb @@ -24,36 +24,29 @@ module QA private + # Check if a group exists in private or public tab + # @param name [String] group name + # @return [Boolean] whether a group with given name exists def has_filtered_group?(name) - # Filter and submit to reload the page and only retrieve the filtered results - find_element(:groups_filter_field).set(name).send_keys(:return) - - # Since we submitted after filtering, the presence of - # groups_list_tree_container means we have the complete filtered list - # of groups - has_element?(:groups_list_tree_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) - # If there are no groups we'll know immediately because we filtered the list - if page.has_text?('No groups or projects matched your search', -wait: 0) || page.has_text?('No groups matched your search', wait: 0) - return false unless has_element?(:public_groups_tab) - - # Try for public groups - click_element(:public_groups_tab) - # Filter and submit to reload the page and only retrieve the filtered results - find_element(:groups_filter_field).set(name).send_keys(:return) - - # Since we submitted after filtering, the presence of - # groups_list_tree_container means we have the complete filtered list - # of groups - has_element?(:groups_list_tree_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) - - return false if page.has_text?('No groups or projects matched your search', -wait: 0) || page.has_text?('No groups matched your search', wait: 0) - end + filter_group(name) + return true if page.has_link?(name, wait: 0) # element containing link to group + + return false unless has_element?(:public_groups_tab, wait: 0) - # The name will be present as filter input so we check for a link, not text + # Check public groups + click_element(:public_groups_tab) + filter_group(name) page.has_link?(name, wait: 0) end + + # Filter by group name + # @param name [String] group name + # @return [Boolean] whether the filter returned any group + def filter_group(name) + fill_element(:groups_filter_field, name).send_keys(:return) + finished_loading? + has_element?(:groups_list_tree_container, wait: 1) + end end end end diff --git a/qa/qa/page/component/invite_members_modal.rb b/qa/qa/page/component/invite_members_modal.rb index 295b5134bd5..eb791594d22 100644 --- a/qa/qa/page/component/invite_members_modal.rb +++ b/qa/qa/page/component/invite_members_modal.rb @@ -41,7 +41,7 @@ module QA click_element :invite_a_group_button end - def add_member(username, access_level = 'Developer') + def add_member(username, access_level = 'Developer', refresh_page: true) open_invite_members_modal within_element(:invite_members_modal_content) do @@ -51,10 +51,10 @@ module QA set_access_level(access_level) end - send_invite + send_invite(refresh_page) end - def invite_group(group_name, access_level = 'Guest') + def invite_group(group_name, access_level = 'Guest', refresh_page: true) open_invite_group_modal within_element(:invite_members_modal_content) do @@ -69,7 +69,13 @@ module QA set_access_level(access_level) end - send_invite + send_invite(refresh_page) + end + + def send_invite(refresh = false) + click_element :invite_button + Support::WaitForRequests.wait_for_requests + page.refresh if refresh end private @@ -78,12 +84,6 @@ module QA # Guest option is selected by default, skipping these steps if desired option is 'Guest' select_element(:access_level_dropdown, access_level) unless access_level == 'Guest' end - - def send_invite - click_element :invite_button - Support::WaitForRequests.wait_for_requests - page.refresh - end end end end diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb index 7a7329e6110..9143a25d9ab 100644 --- a/qa/qa/page/component/wiki_page_form.rb +++ b/qa/qa/page/component/wiki_page_form.rb @@ -17,7 +17,10 @@ module QA base.view 'app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue' do element :markdown_editor_form_field - element :editing_mode_button + end + + base.view 'app/assets/javascripts/vue_shared/components/markdown/editor_mode_dropdown.vue' do + element :editing_mode_switcher end base.view 'app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue' do @@ -55,8 +58,9 @@ module QA end def use_new_editor - within_element(:editing_mode_button) do - find('label', text: 'Rich text').click + click_element(:editing_mode_switcher) + within_element(:editing_mode_switcher) do + find('button', text: 'Rich text').click end wait_until(reload: false) do diff --git a/qa/qa/page/file/form.rb b/qa/qa/page/file/form.rb index 2e0f8c59213..d0113d66dec 100644 --- a/qa/qa/page/file/form.rb +++ b/qa/qa/page/file/form.rb @@ -15,7 +15,6 @@ module QA end view 'app/views/projects/blob/_template_selectors.html.haml' do - element :template_type_dropdown element :gitignore_dropdown element :gitlab_ci_yml_dropdown element :dockerfile_dropdown @@ -23,13 +22,20 @@ module QA end def add_name(name) - fill_element(:file_name_field, with: name) + fill_element(:file_name_field, name) end - def select_template(template_type, template) - click_element :template_type_dropdown - click_link template_type + def add_custom_name(template_name) + case template_name + # Name has to be exactly LICENSE for template-type-dropdown to appear + when 'LICENSE' + add_name(template_name.to_s) + else + add_name("#{SecureRandom.hex(8)}/#{template_name}") + end + end + def select_template(template_type, template) case template_type when '.gitignore' click_element :gitignore_dropdown diff --git a/qa/qa/page/group/members.rb b/qa/qa/page/group/members.rb index 39003eb03c1..c7d63b97b4f 100644 --- a/qa/qa/page/group/members.rb +++ b/qa/qa/page/group/members.rb @@ -22,8 +22,12 @@ module QA element :access_level_link end - view 'app/assets/javascripts/members/components/action_buttons/remove_member_button.vue' do - element :delete_member_button + view 'app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue' do + element :user_action_dropdown + end + + view 'app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue' do + element :delete_member_dropdown_item end view 'app/assets/javascripts/members/components/members_tabs.vue' do @@ -41,7 +45,8 @@ module QA def remove_member(username) within_element(:member_row, text: username) do - click_element :delete_member_button + click_element :user_action_dropdown + click_element :delete_member_dropdown_item end within_element(:remove_member_modal) do diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index aacff7c4172..6fd48692730 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -409,6 +409,7 @@ module QA fill_element(:reply_field, '') fill_element(:reply_field, initial_content.gsub(/(```suggestion:-0\+0\n).*(\n```)/, "\\1#{suggestion}\\2")) click_element(:comment_now_button) + wait_for_requests end def apply_suggestion_with_message(message) @@ -434,9 +435,9 @@ module QA end def revert_change! - # retry when the modal doesn't appear for large MRs as the onClick listener is initialized after the click - # https://gitlab.com/gitlab-org/gitlab/-/issues/366336 - retry_on_exception do + # reload page when the revert modal occasionally doesn't appear in ee:large-setup job + # https://gitlab.com/gitlab-org/gitlab/-/issues/386623 (transient issue) + retry_on_exception(reload: true) do click_element(:revert_button, Page::Component::CommitModal) end click_element(:submit_commit_button) diff --git a/qa/qa/page/project/fork/new.rb b/qa/qa/page/project/fork/new.rb index b622b341685..2b36766d996 100644 --- a/qa/qa/page/project/fork/new.rb +++ b/qa/qa/page/project/fork/new.rb @@ -5,6 +5,8 @@ module QA module Project module Fork class New < Page::Base + include ::QA::Page::Component::Dropdown + view 'app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue' do element :fork_project_button element :fork_privacy_button @@ -12,9 +14,6 @@ module QA view 'app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue' do element :select_namespace_dropdown - element :select_namespace_dropdown_item - element :select_namespace_dropdown_search_field - element :select_namespace_dropdown_item end def fork_project(namespace = Runtime::Namespace.path) @@ -25,20 +24,13 @@ module QA def get_list_of_namespaces click_element(:select_namespace_dropdown) - wait_until(reload: false) do - has_element?(:select_namespace_dropdown_item) - end - all_elements(:select_namespace_dropdown_item, minimum: 1).map(&:text) + all_items end def choose_namespace(namespace) retry_on_exception do click_element(:select_namespace_dropdown) - fill_element(:select_namespace_dropdown_search_field, namespace) - wait_until(reload: false) do - has_element?(:select_namespace_dropdown_item, text: namespace) - end - click_button(namespace) + search_and_select(namespace) end end end diff --git a/qa/qa/page/project/pipeline/new.rb b/qa/qa/page/project/pipeline/new.rb index 1d85d072e34..54c3bb0ddeb 100644 --- a/qa/qa/page/project/pipeline/new.rb +++ b/qa/qa/page/project/pipeline/new.rb @@ -5,7 +5,7 @@ module QA module Project module Pipeline class New < QA::Page::Base - view 'app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue' do + view 'app/assets/javascripts/ci/pipeline_new/components/pipeline_new_form.vue' do element :run_pipeline_button, required: true element :ci_variable_row_container element :ci_variable_key_field diff --git a/qa/qa/page/project/settings/alerts.rb b/qa/qa/page/project/settings/alerts.rb index a74a227d697..7b1d738ec3c 100644 --- a/qa/qa/page/project/settings/alerts.rb +++ b/qa/qa/page/project/settings/alerts.rb @@ -23,6 +23,7 @@ module QA element :save_and_create_alert_button element :test_payload_field element :send_test_alert_button + element :prometheus_url_field end def enable_incident_for_alert @@ -59,10 +60,22 @@ module QA click_element(:integration_name_field) end + def select_prometheus + click_element(:integration_type_dropdown) + find("option[value='PROMETHEUS']").click + + # Click outside of the list to close it + click_element(:prometheus_url_field) + end + def enter_integration_name(name) fill_element(:integration_name_field, name) end + def fill_in_prometheus_url(url = Runtime::Scenario.gitlab_address) + fill_element(:prometheus_url_field, url) + end + def activate_integration within_element(:active_toggle_container) do find('.gl-toggle').click @@ -82,6 +95,18 @@ module QA def send_test_alert click_element(:send_test_alert_button) end + + def go_to_view_credentials + click_link_with_text('View credentials') + end + + def webhook_url + find('input[id="url"]').value + end + + def authorization_key + find('input[id="authorization-key"]').value + end end end end diff --git a/qa/qa/page/project/settings/ci_variables.rb b/qa/qa/page/project/settings/ci_variables.rb index 316920ffa90..8df0aaa9f27 100644 --- a/qa/qa/page/project/settings/ci_variables.rb +++ b/qa/qa/page/project/settings/ci_variables.rb @@ -7,7 +7,7 @@ module QA class CiVariables < Page::Base include QA::Page::Settings::Common - view 'app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue' do + view 'app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue' do element :ci_variable_key_field element :ci_variable_value_field element :ci_variable_save_button diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb index 659fe198d49..3eddd0fd33a 100644 --- a/qa/qa/page/project/settings/protected_branches.rb +++ b/qa/qa/page/project/settings/protected_branches.rb @@ -51,10 +51,15 @@ module QA within_element(:"allowed_to_#{action}_dropdown_content") do 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) + allowed[:users].each { |user| select_name user.username } if allowed.key?(:users) + allowed[:groups].each { |group| select_name group.name } if allowed.key?(:groups) end end + + def select_name(name) + fill_element(:dropdown_input_field, name) + click_on name + end end end end diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index 168bfd6aa0a..3c2b8d56f1d 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -47,13 +47,12 @@ module QA element :tree_holder, '.tree-holder' # rubocop:disable QA/ElementWithPattern end - view 'app/views/projects/_fork_info.html.haml' do + view 'app/assets/javascripts/repository/components/fork_info.vue' do element :forked_from_link end view 'app/views/projects/buttons/_fork.html.haml' do - element :fork_label, "%span= s_('ProjectOverview|Fork')" # rubocop:disable QA/ElementWithPattern - element :fork_link, "link_to new_project_fork_path(@project)" # rubocop:disable QA/ElementWithPattern + element :fork_button end view 'app/views/projects/empty.html.haml' do @@ -97,8 +96,12 @@ module QA click_element :new_file_menu_item end + # Click by JS is needed to bypass the VSCode Web IDE popover + # Change back to regular click_element when vscode_web_ide FF is removed + # Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/371084 def fork_project - click_on 'Fork' + fork_button = find_element(:fork_button) + click_by_javascript(fork_button) end def forked_from?(parent_project_name) diff --git a/qa/qa/page/project/web_ide/vscode.rb b/qa/qa/page/project/web_ide/vscode.rb new file mode 100644 index 00000000000..dd5222cfd93 --- /dev/null +++ b/qa/qa/page/project/web_ide/vscode.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +# VSCode WebIDE is built off an iFrame application therefore we are uanble to use `qa-selectors` +module QA + module Page + module Project + module WebIDE + class VSCode < Page::Base + # Use to Pass Test::Sanity::Selectors temporarily until iframe [data-qa-* selector added + view 'app/views/shared/_broadcast_message.html.haml' do + element :broadcast_notification_container + element :close_button + end + + # Used for stablility, due to feature_caching of vscode_web_ide + def wait_for_ide_to_load + page.driver.browser.switch_to.window(page.driver.browser.window_handles.last) + wait_for_requests + Support::Waiter.wait_until(max_duration: 60, reload_page: page, retry_on_exception: true) do + within_vscode_editor do + # vscode file_explorer element + page.has_css?('.explorer-folders-view', visible: true) + end + end + end + + def within_vscode_editor(&block) + iframe = find('#ide iframe') + page.within_frame(iframe, &block) + end + + def create_new_folder(name) + within_vscode_editor do + # Use for stability, WebIDE inside an iframe is finnicky + Support::Waiter.wait_until(max_duration: 60, retry_on_exception: true) do + page.find('.explorer-folders-view').right_click + # new_folder_button + page.has_css?('[aria-label="New Folder..."]', visible: true) + end + + # Additonal wait for stability, webdriver sometimes moves too fast + Support::Waiter.wait_until(max_duration: 60, retry_on_exception: true) do + page.find('[aria-label="New Folder..."]').click + # Verify New Folder button is triggered and textbox is waiting for input + page.find('.explorer-item-edited', visible: true) + send_keys(name, :enter) + page.has_content?(name) + end + end + end + + def commit_and_push(folder_name) + within_vscode_editor do + # Commit Tab + page.find('a.codicon-source-control-view-icon').click + send_keys(folder_name) + page.has_content?(folder_name) + + # Commit Button + page.find('a.monaco-description-button').click + page.has_css?('.notification-list-item-details-row', visible: true) + end + end + end + end + end + end +end |