diff options
Diffstat (limited to 'qa/qa/page')
-rw-r--r-- | qa/qa/page/base.rb | 16 | ||||
-rw-r--r-- | qa/qa/page/component/content_editor.rb | 54 | ||||
-rw-r--r-- | qa/qa/page/component/import/gitlab.rb | 4 | ||||
-rw-r--r-- | qa/qa/page/component/invite_members_modal.rb | 12 | ||||
-rw-r--r-- | qa/qa/page/component/wiki.rb | 12 | ||||
-rw-r--r-- | qa/qa/page/component/wiki_page_form.rb | 7 | ||||
-rw-r--r-- | qa/qa/page/dashboard/projects.rb | 8 | ||||
-rw-r--r-- | qa/qa/page/group/bulk_import.rb | 8 | ||||
-rw-r--r-- | qa/qa/page/group/dependency_proxy.rb | 26 | ||||
-rw-r--r-- | qa/qa/page/group/members.rb | 2 | ||||
-rw-r--r-- | qa/qa/page/group/menu.rb | 110 | ||||
-rw-r--r-- | qa/qa/page/group/settings/billing.rb | 13 | ||||
-rw-r--r-- | qa/qa/page/merge_request/show.rb | 9 | ||||
-rw-r--r-- | qa/qa/page/project/deployments/environments/show.rb | 23 | ||||
-rw-r--r-- | qa/qa/page/project/import/github.rb | 96 | ||||
-rw-r--r-- | qa/qa/page/project/new.rb | 4 | ||||
-rw-r--r-- | qa/qa/page/project/registry/show.rb | 2 | ||||
-rw-r--r-- | qa/qa/page/project/secure/configuration_form.rb | 31 | ||||
-rw-r--r-- | qa/qa/page/project/wiki/edit.rb | 1 |
19 files changed, 281 insertions, 157 deletions
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 6b54d8ab1ac..9debdc1d4dd 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -21,7 +21,7 @@ module QA end def to_s - <<~MSG.strip % { page: @page_class } + format(<<~MSG.strip, page: @page_class) %{page} has no required elements. See https://docs.gitlab.com/ee/development/testing_guide/end_to_end/dynamic_element_validation.html#required-elements MSG @@ -108,7 +108,7 @@ module QA wait_for_requests(skip_finished_loading_check: skip_finished_loading_check) element_selector = element_selector_css(name, reject_capybara_query_keywords(kwargs)) - find(element_selector, only_capybara_query_keywords(kwargs)) + find(element_selector, **only_capybara_query_keywords(kwargs)) end def only_capybara_query_keywords(kwargs) @@ -232,11 +232,11 @@ module QA visible = kwargs.delete(:visible) visible = visible.nil? && true - try_find_element = ->(wait) do + try_find_element = lambda do |wait| if disabled.nil? has_css?(element_selector_css(name, kwargs), text: text, wait: wait, class: klass, visible: visible) else - find_element(name, original_kwargs).disabled? == disabled + find_element(name, **original_kwargs).disabled? == disabled end end @@ -322,13 +322,13 @@ module QA # 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 # so instead we wait for the element, and then we wait a little longer - raise ElementNotFound, %Q(Couldn't find element named "#{name}") unless has_element?(name) + raise ElementNotFound, %(Couldn't find element named "#{name}") unless has_element?(name) sleep 1 end def within_element(name, **kwargs) - wait_for_requests + wait_for_requests(skip_finished_loading_check: kwargs.delete(:skip_finished_loading_check)) text = kwargs.delete(:text) page.within(element_selector_css(name, kwargs), text: text) do @@ -386,9 +386,7 @@ module QA end def self.errors - if views.empty? - return ["Page class does not have views / elements defined!"] - end + return ["Page class does not have views / elements defined!"] if views.empty? views.flat_map(&:errors) end diff --git a/qa/qa/page/component/content_editor.rb b/qa/qa/page/component/content_editor.rb new file mode 100644 index 00000000000..b3a42634fe7 --- /dev/null +++ b/qa/qa/page/component/content_editor.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module QA + module Page + module Component + module ContentEditor + extend QA::Page::PageConcern + + def self.included(base) + super + + base.view 'app/assets/javascripts/content_editor/components/content_editor.vue' do + element :content_editor_container + end + + 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 + element :file_upload_field + end + end + + def add_heading(heading, text) + within_element(:content_editor_container) do + text_area.set(text) + # 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 + end + end + + def upload_image(image_path) + within_element(:content_editor_container) do + # add image on a new line + text_area.send_keys(:return) + find_element(:file_upload_field, visible: false).send_keys(image_path) + end + end + + private + + def text_area + find('[contenteditable="true"]', visible: false) + end + end + end + end +end diff --git a/qa/qa/page/component/import/gitlab.rb b/qa/qa/page/component/import/gitlab.rb index 2fd2a45b399..5831a713ae5 100644 --- a/qa/qa/page/component/import/gitlab.rb +++ b/qa/qa/page/component/import/gitlab.rb @@ -5,6 +5,8 @@ module QA module Component module Import module Gitlab + extend QA::Page::PageConcern + def self.included(base) super @@ -30,7 +32,7 @@ module QA click_element(:import_project_button) wait_until(reload: false) do - has_notice?("The project was successfully imported.") + has_notice?("The project was successfully imported.") || has_element?(:project_name_content) end end end diff --git a/qa/qa/page/component/invite_members_modal.rb b/qa/qa/page/component/invite_members_modal.rb index 7cec4588af5..fecd61fb410 100644 --- a/qa/qa/page/component/invite_members_modal.rb +++ b/qa/qa/page/component/invite_members_modal.rb @@ -40,18 +40,20 @@ module QA click_element :invite_a_group_button end - def add_member(username, access_level = Resource::Members::AccessLevel::DEVELOPER) + def add_member(username, access_level = 'Developer') open_invite_members_modal within_element(:invite_members_modal_content) do - fill_element :access_level_dropdown, with: access_level - fill_element :members_token_select_input, username - Support::WaitForRequests.wait_for_requests - click_button username + # Guest option is selected by default, skipping these steps if desired option is 'Guest' + unless access_level == 'Guest' + click_element :access_level_dropdown + click_button access_level + end + click_element :invite_button end diff --git a/qa/qa/page/component/wiki.rb b/qa/qa/page/component/wiki.rb index 92eb25af247..c3db1d6c885 100644 --- a/qa/qa/page/component/wiki.rb +++ b/qa/qa/page/component/wiki.rb @@ -68,6 +68,18 @@ module QA def has_no_page? has_element?(:create_first_page_link) end + + def has_heading?(heading_type, text) + within_element(:wiki_page_content) do + has_css?(heading_type, text: text) + end + end + + def has_image?(image_file_name) + within_element(:wiki_page_content) do + has_css?("img[src$='#{image_file_name}']") + end + 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 bb22b7da003..6b7452b0e0f 100644 --- a/qa/qa/page/component/wiki_page_form.rb +++ b/qa/qa/page/component/wiki_page_form.rb @@ -14,6 +14,7 @@ module QA element :wiki_content_textarea element :wiki_message_textbox element :wiki_submit_button + element :try_new_editor_container end base.view 'app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue' do @@ -41,6 +42,12 @@ module QA click_element(:delete_button, Page::Modal::DeleteWiki) Page::Modal::DeleteWiki.perform(&:confirm_deletion) end + + def use_new_editor + within_element(:try_new_editor_container) do + click_button('Use the new editor') + end + end end end end diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb index 8be11550233..c0108d85365 100644 --- a/qa/qa/page/dashboard/projects.rb +++ b/qa/qa/page/dashboard/projects.rb @@ -13,6 +13,10 @@ module QA element :user_role_content end + view 'app/views/dashboard/_projects_head.html.haml' do + element :new_project_button + end + def has_project_with_access_role?(project_name, access_role) within_element(:project_content, text: project_name) do has_element?(:user_role_content, text: access_role) @@ -25,6 +29,10 @@ module QA find_link(text: name).click end + def click_new_project_button + click_element(:new_project_button, Page::Project::New) + end + def self.path '/' end diff --git a/qa/qa/page/group/bulk_import.rb b/qa/qa/page/group/bulk_import.rb index a0511c9a16c..9ba80abf21c 100644 --- a/qa/qa/page/group/bulk_import.rb +++ b/qa/qa/page/group/bulk_import.rb @@ -6,13 +6,13 @@ module QA class BulkImport < Page::Base view "app/assets/javascripts/import_entities/import_groups/components/import_table.vue" do element :import_table + element :import_item + element :import_group_button + element :import_status_indicator end - view "app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue" do - element :import_item + view "app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue" do element :target_group_dropdown_item - element :import_status_indicator - element :import_group_button end view "app/assets/javascripts/import_entities/components/group_dropdown.vue" do diff --git a/qa/qa/page/group/dependency_proxy.rb b/qa/qa/page/group/dependency_proxy.rb new file mode 100644 index 00000000000..f637c79cffc --- /dev/null +++ b/qa/qa/page/group/dependency_proxy.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module QA + module Page + module Group + class DependencyProxy < QA::Page::Base + view 'app/views/groups/dependency_proxies/show.html.haml' do + element :dependency_proxy_setting_toggle + end + + view 'app/views/groups/dependency_proxies/_url.html.haml' do + element :dependency_proxy_count + end + + def has_dependency_proxy_enabled? + toggle = find_element(:dependency_proxy_setting_toggle) + toggle[:class].include?('is-checked') + end + + def has_blob_count?(blob_text) + has_element?(:dependency_proxy_count, text: blob_text) + end + end + end + end +end diff --git a/qa/qa/page/group/members.rb b/qa/qa/page/group/members.rb index b526a4488b2..ccc901932f4 100644 --- a/qa/qa/page/group/members.rb +++ b/qa/qa/page/group/members.rb @@ -7,7 +7,7 @@ module QA include Page::Component::InviteMembersModal include Page::Component::UsersSelect - view 'app/assets/javascripts/vue_shared/components/remove_member_modal.vue' do + view 'app/assets/javascripts/members/components/modals/remove_member_modal.vue' do element :remove_member_modal_content end diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb index 338a135614d..c997598e25a 100644 --- a/qa/qa/page/group/menu.rb +++ b/qa/qa/page/group/menu.rb @@ -6,51 +6,32 @@ module QA class Menu < Page::Base include SubMenus::Common - view 'app/views/layouts/nav/sidebar/_group_menus.html.haml' do - element :general_settings_link - element :group_issues_item - element :group_members_item - element :group_milestones_link - element :group_settings - element :group_information_link - element :group_information_submenu - end - - view 'app/views/groups/sidebar/_packages_settings.html.haml' do - element :group_package_settings_link - end - - view 'app/views/layouts/nav/sidebar/_analytics_links.html.haml' do - element :analytics_link - element :analytics_sidebar_submenu - end - def click_group_members_item - hover_element(:group_information_link) do - within_submenu(:group_information_submenu) do - click_element(:group_members_item) + hover_group_information do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Members') end end end - def click_settings - within_sidebar do - click_element(:group_settings) + def click_subgroup_members_item + hover_subgroup_information do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Members') + end end end - def click_contribution_analytics_item - hover_element(:analytics_link) do - within_submenu(:analytics_sidebar_submenu) do - click_element(:contribution_analytics_link) - end + def click_settings + within_sidebar do + click_element(:sidebar_menu_link, menu_item: 'Settings') end end def click_group_general_settings_item - hover_element(:group_settings) do - within_submenu(:group_sidebar_submenu) do - click_element(:general_settings_link) + hover_group_settings do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'General') end end end @@ -58,16 +39,31 @@ module QA def go_to_milestones hover_issues do within_submenu do - click_element(:group_milestones_link) + click_element(:sidebar_menu_item_link, menu_item: 'Milestones') end end end def go_to_package_settings - scroll_to_element(:group_settings) - hover_element(:group_settings) do - within_submenu(:group_sidebar_submenu) do - click_element(:group_package_settings_link) + hover_group_settings do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Packages & Registries') + end + end + end + + def go_to_group_packages + hover_group_packages do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Package Registry') + end + end + end + + def go_to_dependency_proxy + hover_group_packages do + within_submenu do + click_element(:sidebar_menu_item_link, menu_item: 'Dependency Proxy') end end end @@ -76,8 +72,42 @@ module QA def hover_issues within_sidebar do - scroll_to_element(:group_issues_item) - find_element(:group_issues_item).hover + scroll_to_element(:sidebar_menu_link, menu_item: 'Issues') + find_element(:sidebar_menu_link, menu_item: 'Issues').hover + + yield + end + end + + def hover_group_information + within_sidebar do + find_element(:sidebar_menu_link, menu_item: 'Group information').hover + + yield + end + end + + def hover_subgroup_information + within_sidebar do + find_element(:sidebar_menu_link, menu_item: 'Subgroup information').hover + + yield + end + end + + def hover_group_packages + within_sidebar do + scroll_to_element(:sidebar_menu_link, menu_item: 'Packages & Registries') + find_element(:sidebar_menu_link, menu_item: 'Packages & Registries').hover + + yield + end + end + + def hover_group_settings + within_sidebar do + scroll_to_element(:sidebar_menu_link, menu_item: 'Settings') + find_element(:sidebar_menu_link, menu_item: 'Settings').hover yield end diff --git a/qa/qa/page/group/settings/billing.rb b/qa/qa/page/group/settings/billing.rb deleted file mode 100644 index a83af47fc35..00000000000 --- a/qa/qa/page/group/settings/billing.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module QA - module Page - module Group - module Settings - class Billing < Chemlab::Page - link :start_your_free_trial - end - end - end - end -end diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index 5f52d48e9f6..afe88fc0cdc 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -202,7 +202,9 @@ module QA 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: 60) + wait_until(sleep_interval: 5, reload: false) do + has_element?(:merge_request_pipeline_info_content, text: text, wait: 15 ) + end end def has_title?(title) @@ -236,7 +238,10 @@ module QA end def merged? - # Revisit after merge page re-architect is done https://gitlab.com/gitlab-org/gitlab/-/issues/300042 + # Reloads the page at this point to avoid the problem of the merge status failing to update + # That's the transient UX issue this test is checking for, so if the MR is merged but the UI still shows the + # status as unmerged, the test will fail. + # Revisit after merge page re-architect is done https://gitlab.com/groups/gitlab-org/-/epics/5598 # To remove page refresh logic if possible retry_until(max_attempts: 3, reload: true) do has_element?(:merged_status_content, text: 'The changes were merged into', wait: 20) diff --git a/qa/qa/page/project/deployments/environments/show.rb b/qa/qa/page/project/deployments/environments/show.rb deleted file mode 100644 index 48e4850d3be..00000000000 --- a/qa/qa/page/project/deployments/environments/show.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module QA - module Page - module Project - module Deployments - module Environments - class Show < Page::Base - view 'app/views/projects/environments/_external_url.html.haml' do - element :view_deployment - end - - def view_deployment(&block) - new_window = window_opened_by { click_element(:view_deployment) } - - within_window(new_window, &block) if block - end - end - end - end - end - end -end diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb index 74bc4cec467..bb35c5eb17c 100644 --- a/qa/qa/page/project/import/github.rb +++ b/qa/qa/page/project/import/github.rb @@ -18,12 +18,17 @@ module QA element :import_button element :project_path_content element :go_to_project_button + element :import_status_indicator end view "app/assets/javascripts/import_entities/components/group_dropdown.vue" do element :target_namespace_selector_dropdown end + # Add personal access token + # + # @param [String] personal_access_token + # @return [void] def add_personal_access_token(personal_access_token) # If for some reasons this process is retried, user cannot re-enter github token in the same group # In this case skip this step and proceed to import project row @@ -34,71 +39,50 @@ module QA finished_loading? end - def import!(full_path, name) - return if already_imported(full_path) - - choose_test_namespace(full_path) - set_path(full_path, name) - import_project(full_path) - - wait_for_success - end - - # TODO: refactor to use 'go to project' button instead of generic main menu - def go_to_project(name) - Page::Main::Menu.perform(&:go_to_projects) - Page::Dashboard::Projects.perform do |dashboard| - dashboard.go_to_project(name) - end - end - - private - - def within_repo_path(full_path, &block) - project_import_row = find_element(:project_import_row, text: full_path) - - within(project_import_row, &block) - end - - def choose_test_namespace(full_path) - within_repo_path(full_path) do - within_element(:target_namespace_selector_dropdown) { click_button(class: 'dropdown-toggle') } - click_element(:target_group_dropdown_item, group_name: Runtime::Namespace.path) - end - end - - def set_path(full_path, name) - within_repo_path(full_path) do - fill_element(:project_path_field, name) - end - end - - def import_project(full_path) - within_repo_path(full_path) do + # Import project + # + # @param [String] source_project_name + # @param [String] target_group_path + # @return [void] + def import!(gh_project_name, target_group_path, project_name) + within_element(:project_import_row, source_project: gh_project_name) do + click_element(:target_namespace_selector_dropdown) + click_element(:target_group_dropdown_item, group_name: target_group_path) + fill_element(:project_path_field, project_name) click_element(:import_button) end end - def wait_for_success - # TODO: set reload:false and remove skip_finished_loading_check_on_refresh when - # https://gitlab.com/gitlab-org/gitlab/-/issues/292861 is fixed - wait_until( - max_duration: 90, - sleep_interval: 5.0, - reload: true, - skip_finished_loading_check_on_refresh: true - ) do - # TODO: Refactor to explicitly wait for specific project import successful status - # This check can create false positive if main importing message appears with delay and check exits early - page.has_no_content?('Importing 1 repository', wait: 3) + # Check Go to project button present + # + # @param [String] gh_project_name + # @return [Boolean] + def has_go_to_project_button?(gh_project_name) + within_element(:project_import_row, source_project: gh_project_name) do + has_element?(:go_to_project_button) end end - def already_imported(full_path) - within_repo_path(full_path) do - has_element?(:project_path_content) && has_element?(:go_to_project_button) + # Check if import page has a successfully imported project + # + # @param [String] source_project_name + # @param [Integer] wait + # @return [Boolean] + def has_imported_project?(gh_project_name, wait: QA::Support::WaitForRequests::DEFAULT_MAX_WAIT_TIME) + within_element(:project_import_row, source_project: gh_project_name, skip_finished_loading_check: true) do + # TODO: remove retrier with reload:true once https://gitlab.com/gitlab-org/gitlab/-/issues/292861 is fixed + wait_until( + max_duration: wait, + sleep_interval: 5, + reload: true, + skip_finished_loading_check_on_refresh: true + ) do + has_element?(:import_status_indicator, text: "Complete") + end end end + + alias_method :wait_for_success, :has_imported_project? end end end diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb index 170cc14b27f..06e476f009a 100644 --- a/qa/qa/page/project/new.rb +++ b/qa/qa/page/project/new.rb @@ -83,8 +83,8 @@ module QA click_button 'Repo by URL' end - def enable_initialize_with_readme - check_element(:initialize_with_readme_checkbox) + def disable_initialize_with_readme + uncheck_element(:initialize_with_readme_checkbox) end end end diff --git a/qa/qa/page/project/registry/show.rb b/qa/qa/page/project/registry/show.rb index dffdb9eebba..03c547fc8b5 100644 --- a/qa/qa/page/project/registry/show.rb +++ b/qa/qa/page/project/registry/show.rb @@ -31,7 +31,7 @@ module QA def click_delete click_element(:tag_delete_button) - find_button('Confirm').click + find_button('Delete').click end end end diff --git a/qa/qa/page/project/secure/configuration_form.rb b/qa/qa/page/project/secure/configuration_form.rb new file mode 100644 index 00000000000..73d1601b61e --- /dev/null +++ b/qa/qa/page/project/secure/configuration_form.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Secure + class ConfigurationForm < QA::Page::Base + include QA::Page::Component::Select2 + include QA::Page::Settings::Common + + view 'app/assets/javascripts/security_configuration/components/feature_card.vue' do + element :sast_status, "`${feature.type}_status`" # rubocop:disable QA/ElementWithPattern + element :sast_enable_button, "`${feature.type}_enable_button`" # rubocop:disable QA/ElementWithPattern + end + + def click_sast_enable_button + click_element(:sast_enable_button) + end + + def has_sast_status?(status_text) + within_element(:sast_status) do + has_text?(status_text) + end + end + end + end + end + end +end + +QA::Page::Project::Secure::ConfigurationForm.prepend_mod_with('Page::Project::Secure::ConfigurationForm', namespace: QA) diff --git a/qa/qa/page/project/wiki/edit.rb b/qa/qa/page/project/wiki/edit.rb index 70aa10cc43e..e782bbbb432 100644 --- a/qa/qa/page/project/wiki/edit.rb +++ b/qa/qa/page/project/wiki/edit.rb @@ -7,6 +7,7 @@ module QA class Edit < Base include Page::Component::WikiPageForm include Page::Component::WikiSidebar + include Page::Component::ContentEditor end end end |