diff options
Diffstat (limited to 'qa/qa/page')
39 files changed, 379 insertions, 304 deletions
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb index 3164676f8e4..42dd1083bbe 100644 --- a/qa/qa/page/admin/menu.rb +++ b/qa/qa/page/admin/menu.rb @@ -92,16 +92,12 @@ module QA end end - def within_sidebar - within_element(:admin_sidebar_content) do - yield - end + def within_sidebar(&block) + within_element(:admin_sidebar_content, &block) end - def within_submenu(element) - within_element(element) do - yield - end + def within_submenu(element, &block) + within_element(element, &block) end end end diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index f59b06b4e75..ab83da7dacf 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -13,7 +13,6 @@ module QA include Support::WaitForRequests extend Validatable - extend SingleForwardable ElementNotFound = Class.new(RuntimeError) @@ -31,8 +30,6 @@ module QA end end - def_delegators :evaluator, :view, :views - def initialize @retry_later_backoff = QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME end @@ -276,7 +273,7 @@ module QA visible = kwargs.delete(:visible) visible = visible.nil? && true - try_find_element = lambda do |wait| + try_find_element = ->(wait) do if disabled.nil? has_css?(element_selector_css(name, kwargs), text: text, wait: wait, class: klass, visible: visible) else @@ -422,26 +419,30 @@ module QA URI(page.current_url).host end - def self.path - raise NotImplementedError - end + class << self + def path + raise NotImplementedError + end - def self.evaluator - @evaluator ||= Page::Base::DSL.new - end + def evaluator + @evaluator ||= Page::Base::DSL.new + end - def self.errors - return ["Page class does not have views / elements defined!"] if views.empty? + def errors + return ["Page class does not have views / elements defined!"] if views.empty? - views.flat_map(&:errors) - end + views.flat_map(&:errors) + end - def self.elements - views.flat_map(&:elements) - end + def elements + views.flat_map(&:elements) + end + + def required_elements + elements.select(&:required?) + end - def self.required_elements - elements.select(&:required?) + delegate :view, :views, to: :evaluator end def send_keys_to_element(name, keys) diff --git a/qa/qa/page/component/blob_content.rb b/qa/qa/page/component/blob_content.rb index b6001cf39b5..a57ef38f768 100644 --- a/qa/qa/page/component/blob_content.rb +++ b/qa/qa/page/component/blob_content.rb @@ -72,11 +72,11 @@ module QA private - def within_file_by_number(element, file_number) + def within_file_by_number(element, file_number, &block) if file_number - within_element_by_index(element, file_number - 1) { yield } + within_element_by_index(element, file_number - 1, &block) else - within_element(element) { yield } + within_element(element, &block) end end end diff --git a/qa/qa/page/component/custom_metric.rb b/qa/qa/page/component/custom_metric.rb deleted file mode 100644 index 094979f5e18..00000000000 --- a/qa/qa/page/component/custom_metric.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true - -module QA - module Page - module Component - module CustomMetric - extend QA::Page::PageConcern - - def self.included(base) - super - - base.view 'app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue' do - element :custom_metric_prometheus_title_field - element :custom_metric_prometheus_query_field - element :custom_metric_prometheus_y_label_field - element :custom_metric_prometheus_unit_label_field - element :custom_metric_prometheus_legend_label_field - end - end - - def add_custom_metric - fill_element :custom_metric_prometheus_title_field, 'HTTP Requests Total' - fill_element :custom_metric_prometheus_query_field, 'rate(http_requests_total[5m])' - fill_element :custom_metric_prometheus_y_label_field, 'Requests/second' - fill_element :custom_metric_prometheus_unit_label_field, 'req/sec' - fill_element :custom_metric_prometheus_legend_label_field, 'HTTP requests' - - save_changes - end - - def save_changes - click_button(class: 'btn-success') - end - - def delete_custom_metric - click_button(class: 'btn-danger') - within('.modal-content') { click_button(class: 'btn-danger') } - end - - def edit_custom_metric - fill_element :custom_metric_prometheus_title_field, '' - fill_element :custom_metric_prometheus_title_field, 'Throughput' - - save_changes - end - end - end - end -end diff --git a/qa/qa/page/component/dropdown.rb b/qa/qa/page/component/dropdown.rb new file mode 100644 index 00000000000..e6204fb5332 --- /dev/null +++ b/qa/qa/page/component/dropdown.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +module QA + module Page + module Component + module Dropdown + include Select2 + + def select_item(item_text) + return super if use_select2? + + find('li.gl-dropdown-item', text: item_text, match: :prefer_exact).click + end + + def has_item?(item_text) + return super if use_select2? + + has_css?('li.gl-dropdown-item', text: item_text, match: :prefer_exact) + end + + def current_selection + return super if use_select2? + + expand_select_list unless dropdown_open? + find('span.gl-dropdown-button-text').text + end + + def clear_current_selection_if_present + return super if use_select2? + + expand_select_list unless dropdown_open? + + if has_css?('button[data-testid="listbox-reset-button"]') + find('button[data-testid="listbox-reset-button"]').click + elsif dropdown_open? + expand_select_list + end + end + + def search_item(item_text) + return super if use_select2? + + find('div.gl-search-box-by-type input[type="Search"]').set(item_text) + wait_for_search_to_complete + end + + def search_and_select(item_text) + return super if use_select2? + + QA::Runtime::Logger.info "Searching and selecting: #{item_text}" + + search_item(item_text) + + unless has_item?(item_text) + raise QA::Page::Base::ElementNotFound, %(Couldn't find option named "#{item_text}") + end + + select_item(item_text) + end + + def search_and_select_exact(item_text) + return super if use_select2? + + QA::Runtime::Logger.info "Searching and selecting: #{item_text}" + + search_item(item_text) + + unless has_item?(item_text) + raise QA::Page::Base::ElementNotFound, %(Couldn't find option named "#{item_text}") + end + + find('li.gl-dropdown-item span:nth-child(2)', text: item_text, exact_text: true).click + end + + def expand_select_list + return super if use_select2? + + find('svg.dropdown-chevron').click + end + + def wait_for_search_to_complete + return super if use_select2? + + Support::WaitForRequests.wait_for_requests + + has_css?('div[data-testid="listbox-search-loader"]', wait: 1) + has_no_css?('div[data-testid="listbox-search-loader"]') + end + + def dropdown_open? + return super if use_select2? + + has_css?('ul.gl-dropdown-contents', wait: 1) + end + + def find_input_by_prefix_and_set(element_prefix, item_text) + find("input[id^=\"#{element_prefix}\"]").set(item_text) + end + + private + + # rubocop:disable Gitlab/PredicateMemoization + def use_select2? + @use_select2 ||= has_css?('.select2-container', wait: 1) + end + # rubocop:enable Gitlab/PredicateMemoization + 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 27dce152367..295b5134bd5 100644 --- a/qa/qa/page/component/invite_members_modal.rb +++ b/qa/qa/page/component/invite_members_modal.rb @@ -76,10 +76,7 @@ module QA def set_access_level(access_level) # 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 + select_element(:access_level_dropdown, access_level) unless access_level == 'Guest' end def send_invite diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb index fb2e7478684..0a31dee2b4f 100644 --- a/qa/qa/page/component/issuable/sidebar.rb +++ b/qa/qa/page/component/issuable/sidebar.rb @@ -22,19 +22,19 @@ module QA element :reviewers_edit_button end - base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue' do + base.view 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/labels_select_root.vue' do element :labels_block end - base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue' do + base.view 'app/assets/javascripts/sidebar/components/labels/labels_select_vue/dropdown_contents_labels_view.vue' do element :dropdown_input_field end - base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue' do + base.view 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue' do element :labels_dropdown_content end - base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue' do + base.view 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_value.vue' do element :selected_label_content end diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb index 47ed1a9616b..4e1c7f3e2bb 100644 --- a/qa/qa/page/component/snippet.rb +++ b/qa/qa/page/component/snippet.rb @@ -170,7 +170,7 @@ module QA # wait for the page to reload after deletion wait_until(reload: false) do has_no_element?(:delete_snippet_button) && - has_no_element?(:snippet_action_button, action: 'Delete') + has_no_element?(:snippet_action_button, action: 'Delete') end end diff --git a/qa/qa/page/file/edit.rb b/qa/qa/page/file/edit.rb index b9b676ee3c4..e66019279ce 100644 --- a/qa/qa/page/file/edit.rb +++ b/qa/qa/page/file/edit.rb @@ -8,8 +8,8 @@ module QA include Shared::CommitButton include Shared::Editor - view 'app/assets/javascripts/editor/components/source_editor_toolbar_button.vue' do - element :editor_toolbar_button + view 'app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js' do + element :editor_toolbar_button, "qaSelector: 'editor_toolbar_button'" # rubocop:disable QA/ElementWithPattern end def has_markdown_preview?(component, content) diff --git a/qa/qa/page/group/settings/general.rb b/qa/qa/page/group/settings/general.rb index 86585eee121..bb5a3485531 100644 --- a/qa/qa/page/group/settings/general.rb +++ b/qa/qa/page/group/settings/general.rb @@ -40,6 +40,14 @@ module QA element :project_creation_level_dropdown end + view 'app/views/groups/settings/_transfer.html.haml' do + element :transfer_group_content + end + + view 'app/assets/javascripts/groups/components/transfer_group_form.vue' do + element :transfer_group_button + end + def set_group_name(name) find_element(:group_name_field).send_keys([:command, 'a'], :backspace) find_element(:group_name_field).set name @@ -102,6 +110,38 @@ module QA click_element(:save_permissions_changes_button) end + + def transfer_group(source_group, target_group) + QA::Runtime::Logger.info "Transferring group: #{source_group.path} to target group: #{target_group.path}" + + expand_content(:advanced_settings_content) + + scroll_to_transfer_group_content + + select_namespace(target_group.path) + + wait_for_enabled_transfer_group_button + click_element(:transfer_group_button) + + fill_confirmation_text(source_group.path) + confirm_transfer + end + + private + + def scroll_to_transfer_group_content + retry_until(sleep_interval: 1, message: 'Waiting for transfer group content to display') do + has_element?(:transfer_group_content, wait: 3) + end + + scroll_to_element :transfer_group_content + end + + def wait_for_enabled_transfer_group_button + retry_until(sleep_interval: 1, message: 'Waiting for transfer group button to be enabled') do + has_element?(:transfer_group_button, disabled: false, wait: 3) + end + end end end end diff --git a/qa/qa/page/group/settings/group_deploy_tokens.rb b/qa/qa/page/group/settings/group_deploy_tokens.rb index 7d908f473de..c1c3303113b 100644 --- a/qa/qa/page/group/settings/group_deploy_tokens.rb +++ b/qa/qa/page/group/settings/group_deploy_tokens.rb @@ -54,12 +54,10 @@ module QA private - def within_new_project_deploy_token + def within_new_project_deploy_token(&block) has_element?(:created_deploy_token_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME) - within_element(:created_deploy_token_container) do - yield - end + within_element(:created_deploy_token_container, &block) end end end diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb index a30d489e6ff..46ab1e35510 100644 --- a/qa/qa/page/group/show.rb +++ b/qa/qa/page/group/show.rb @@ -39,7 +39,7 @@ module QA end def group_id - find_element(:group_id_content).text.delete('Group ID: ') + find_element(:group_id_content).text.delete('Group ID: ').sub(/\n.*/, '') end def leave_group diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index d7ca8223862..8af78bb86c6 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -12,6 +12,10 @@ module QA element :change_password_button end + view 'app/views/devise/sessions/new.html.haml' do + element :register_link + end + view 'app/views/devise/sessions/_new_base.html.haml' do element :login_field element :password_field diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb index ecd71e7c2f4..1e050d79e23 100644 --- a/qa/qa/page/main/menu.rb +++ b/qa/qa/page/main/menu.rb @@ -9,6 +9,7 @@ module QA view 'app/views/layouts/header/_current_user_dropdown.html.haml' do element :sign_out_link element :edit_profile_link + element :user_profile_link end view 'app/views/layouts/header/_default.html.haml' do @@ -39,6 +40,7 @@ module QA element :projects_dropdown element :groups_dropdown element :snippets_link + element :menu_item_link end view 'app/views/layouts/_search.html.haml' do diff --git a/qa/qa/page/merge_request/new.rb b/qa/qa/page/merge_request/new.rb index 909b37943ff..dc2f908a906 100644 --- a/qa/qa/page/merge_request/new.rb +++ b/qa/qa/page/merge_request/new.rb @@ -13,7 +13,7 @@ module QA element :source_branch_dropdown end - view 'app/views/projects/merge_requests/show.html.haml' do + view 'app/views/projects/merge_requests/_page.html.haml' do element :diffs_tab end diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index e1add9ad434..aacff7c4172 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -126,7 +126,7 @@ module QA element :title_content, required: true end - view 'app/views/projects/merge_requests/show.html.haml' do + view 'app/views/projects/merge_requests/_page.html.haml' do element :notes_tab, required: true element :commits_tab, required: true element :diffs_tab, required: true @@ -366,7 +366,7 @@ module QA # Revisit after merge page re-architect is done https://gitlab.com/gitlab-org/gitlab/-/issues/300042 # To remove page refresh logic if possible wait_until_ready_to_merge - wait_until { !find_element(:merge_button).text.include?('when pipeline succeeds') } + wait_until { !find_element(:merge_button).text.include?('when pipeline succeeds') } # rubocop:disable Rails/NegateInclude click_element(:merge_button) end @@ -390,6 +390,7 @@ module QA def click_open_in_web_ide click_element(:mr_code_dropdown) click_element(:open_in_web_ide_button) + page.driver.browser.switch_to.window(page.driver.browser.window_handles.last) wait_for_requests end @@ -433,7 +434,11 @@ module QA end def revert_change! - click_element(:revert_button, Page::Component::CommitModal) + # 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 + click_element(:revert_button, Page::Component::CommitModal) + end click_element(:submit_commit_button) end diff --git a/qa/qa/page/profile/two_factor_auth.rb b/qa/qa/page/profile/two_factor_auth.rb index 16aa60262d8..2add02b5c48 100644 --- a/qa/qa/page/profile/two_factor_auth.rb +++ b/qa/qa/page/profile/two_factor_auth.rb @@ -25,7 +25,8 @@ module QA def click_configure_it_later_button # TO DO: Investigate why button does not appear sometimes: # https://gitlab.com/gitlab-org/gitlab/-/issues/382698 - return unless has_element?(:configure_it_later_button) + page.refresh + return unless has_element?(:configure_it_later_button, wait: 60) click_element :configure_it_later_button wait_until(max_duration: 10, message: "Waiting for create a group page") do diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb index 75468c74814..c48b1a67d90 100644 --- a/qa/qa/page/project/import/github.rb +++ b/qa/qa/page/project/import/github.rb @@ -81,7 +81,19 @@ module QA reload: false, skip_finished_loading_check_on_refresh: true ) do - has_element?(:import_status_indicator, text: "Complete") + status_selector = 'import_status_indicator' + is_partial_import = has_css?(status_selector, text: "Partial import") + + # Temporarily adding this for investigation purposes. This makes sure that the details section is + # expanded when the screenshot is taken when the test fails. This can be removed or repurposed later + # after investigation. Related: https://gitlab.com/gitlab-org/gitlab/-/issues/385252#note_1211218434 + if is_partial_import + within_element_by_index(:import_status_indicator, 0) do + find('button').click + end + end + + has_element?(status_selector, text: "Complete") end end end diff --git a/qa/qa/page/project/infrastructure/kubernetes/show.rb b/qa/qa/page/project/infrastructure/kubernetes/show.rb index 6de5024e525..8725f64fe32 100644 --- a/qa/qa/page/project/infrastructure/kubernetes/show.rb +++ b/qa/qa/page/project/infrastructure/kubernetes/show.rb @@ -9,6 +9,9 @@ module QA view 'app/assets/javascripts/clusters/forms/components/integration_form.vue' do element :integration_status_toggle element :base_domain_field + end + + view 'app/assets/javascripts/integrations/edit/components/integration_form_actions.vue' do element :save_changes_button end diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb index b1417d9b9db..2f8ffc634ac 100644 --- a/qa/qa/page/project/issue/show.rb +++ b/qa/qa/page/project/issue/show.rb @@ -67,10 +67,6 @@ module QA click_element :close_issue_button end - def has_metrics_unfurled? - has_element?(:prometheus_graph_widgets, wait: 30) - end - def has_reopen_issue_button? has_element?(:reopen_issue_button) end diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb index 5506c5ed4d9..24fd34b4d22 100644 --- a/qa/qa/page/project/job/show.rb +++ b/qa/qa/page/project/job/show.rb @@ -15,7 +15,7 @@ module QA element :pipeline_path, required: true end - view 'app/assets/javascripts/jobs/components/job/sidebar/legacy_sidebar_header.vue' do + view 'app/assets/javascripts/jobs/components/job/sidebar/sidebar_header.vue' do element :retry_button end diff --git a/qa/qa/page/project/monitor/alerts/index.rb b/qa/qa/page/project/monitor/alerts/index.rb new file mode 100644 index 00000000000..50b69d59db7 --- /dev/null +++ b/qa/qa/page/project/monitor/alerts/index.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module Monitor + module Alerts + class Index < Page::Base + view 'app/assets/javascripts/alert_management/components/alert_management_table.vue' do + element :alert_table_container, required: true + end + + def has_alert_with_title?(title) + has_link?(title) + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/monitor/metrics/show.rb b/qa/qa/page/project/monitor/metrics/show.rb deleted file mode 100644 index 59602d0fcf7..00000000000 --- a/qa/qa/page/project/monitor/metrics/show.rb +++ /dev/null @@ -1,134 +0,0 @@ -# frozen_string_literal: true - -module QA - module Page - module Project - module Monitor - module Metrics - class Show < Page::Base - EXPECTED_TITLE = 'Memory Usage (Total)' - LOADING_MESSAGE = 'Waiting for performance data' - - view 'app/assets/javascripts/monitoring/components/dashboard.vue' do - element :prometheus_graphs_content - end - - view 'app/assets/javascripts/monitoring/components/dashboard_header.vue' do - element :dashboards_filter_dropdown - element :environments_dropdown - element :range_picker_dropdown - end - - view 'app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue' do - element :actions_menu_dropdown - element :edit_dashboard_button_enabled - end - - view 'app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue' do - element :duplicate_dashboard_filename_field - end - - view 'app/assets/javascripts/monitoring/components/dashboard_panel.vue' do - element :prometheus_graph_widgets - element :prometheus_widgets_dropdown - element :generate_chart_link_menu_item - end - - view 'app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue' do - element :quick_range_item - end - - view 'app/assets/javascripts/monitoring/components/variables_section.vue' do - element :variables_content - element :variable_item - end - - def wait_for_metrics - wait_for_data - return if has_metrics? - - wait_until(max_duration: 180) do - wait_for_data - has_metrics? - end - end - - def has_metrics? - within_element :prometheus_graphs_content do - has_text?(EXPECTED_TITLE) - end - end - - def has_edit_dashboard_enabled? - click_element :actions_menu_dropdown - - within_element :actions_menu_dropdown do - has_element? :edit_dashboard_button_enabled - end - end - - def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to default branch') - click_element :actions_menu_dropdown - click_on 'Duplicate current dashboard' - fill_element :duplicate_dashboard_filename_field, "#{SecureRandom.hex(8)}-#{save_as}" - choose commit_option - within('.modal-content') { click_button(class: 'btn-success') } - end - - def select_dashboard(dashboard_name) - click_element :dashboards_filter_dropdown - - within_element :dashboards_filter_dropdown do - click_on dashboard_name - end - end - - def filter_environment(environment = 'production') - click_element :environments_dropdown - - within_element :environments_dropdown do - click_link_with_text environment - end - end - - def show_last(range = '8 hours') - all_elements(:range_picker_dropdown, minimum: 1).first.click - click_element :quick_range_item, text: range - end - - def copy_link_to_first_chart - all_elements(:prometheus_widgets_dropdown, minimum: 1).first.click - find_element(:generate_chart_link_menu_item)['data-clipboard-text'] - end - - def has_custom_metric?(metric) - within_element :prometheus_graphs_content do - has_text?(metric) - end - end - - def has_templating_variable?(variable) - within_element :variables_content do - has_element?(:variable_item, text: variable) - end - end - - def has_template_metric?(metric) - within_element :prometheus_graphs_content do - has_text?(metric) - end - end - - private - - def wait_for_data - wait_until(reload: false) { !has_text?(LOADING_MESSAGE) } if has_text?(LOADING_MESSAGE) - end - end - end - end - end - end -end - -QA::Page::Project::Monitor::Metrics::Show.prepend_mod_with('Page::Project::Monitor::Metrics::Show', namespace: QA) diff --git a/qa/qa/page/project/pipeline/new.rb b/qa/qa/page/project/pipeline/new.rb index 742fcad5c07..1d85d072e34 100644 --- a/qa/qa/page/project/pipeline/new.rb +++ b/qa/qa/page/project/pipeline/new.rb @@ -5,23 +5,49 @@ module QA module Project module Pipeline class New < QA::Page::Base - view 'app/assets/javascripts/pipeline_new/components/legacy_pipeline_new_form.vue' do + view 'app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue' do element :run_pipeline_button, required: true element :ci_variable_row_container element :ci_variable_key_field element :ci_variable_value_field + element :ci_variable_value_dropdown + element :ci_variable_value_dropdown_item end def click_run_pipeline_button click_element(:run_pipeline_button, Page::Project::Pipeline::Show) end + def click_variable_dropdown + return unless has_variable_dropdown? + + click_element(:ci_variable_value_dropdown) + end + def configure_variable(key: nil, value: 'foo', row_index: 0) within_element_by_index(:ci_variable_row_container, row_index) do fill_element(:ci_variable_key_field, key) unless key.nil? fill_element(:ci_variable_value_field, value) end end + + def has_variable_dropdown? + has_element?(:ci_variable_value_dropdown) + end + + def variable_dropdown + return unless has_variable_dropdown? + + find_element(:ci_variable_value_dropdown) + end + + def variable_dropdown_item_with_index(index) + return unless has_variable_dropdown? + + within_element_by_index(:ci_variable_value_dropdown_item, index) do + find('p') + end + end end end end diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb index 33ba27a788a..e4511ababfd 100644 --- a/qa/qa/page/project/pipeline/show.rb +++ b/qa/qa/page/project/pipeline/show.rb @@ -11,6 +11,10 @@ module QA element :pipeline_header, required: true end + view 'app/views/projects/pipelines/_info.html.haml' do + element :merge_request_badge_tag + end + view 'app/assets/javascripts/pipelines/components/graph/graph_component.vue' do element :pipeline_graph, /class.*pipeline-graph.*/ # rubocop:disable QA/ElementWithPattern end @@ -27,7 +31,7 @@ module QA element :downstream_title_content end - view 'app/assets/javascripts/reports/components/report_section.vue' do + view 'app/assets/javascripts/ci/reports/components/report_section.vue' do element :expand_report_button end @@ -46,6 +50,10 @@ module QA end end + def has_merge_request_badge_tag? + has_element?(:merge_request_badge_tag) + end + def has_build?(name, status: :success, wait: nil) if status within_element(:job_item_container, text: name) do diff --git a/qa/qa/page/project/pipeline_editor/new.rb b/qa/qa/page/project/pipeline_editor/new.rb index 5d79dd86f2a..da3e772b11f 100644 --- a/qa/qa/page/project/pipeline_editor/new.rb +++ b/qa/qa/page/project/pipeline_editor/new.rb @@ -5,7 +5,7 @@ module QA module Project module PipelineEditor class New < QA::Page::Base - view 'app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/ui/pipeline_editor_empty_state.vue' do element :create_new_ci_button, required: true end diff --git a/qa/qa/page/project/pipeline_editor/show.rb b/qa/qa/page/project/pipeline_editor/show.rb index 8fa20aa57cf..0a7a4460d18 100644 --- a/qa/qa/page/project/pipeline_editor/show.rb +++ b/qa/qa/page/project/pipeline_editor/show.rb @@ -5,21 +5,21 @@ module QA module Project module PipelineEditor class Show < QA::Page::Base - view 'app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/pipeline_editor_app.vue' do element :pipeline_editor_app, required: true end - view 'app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/file_nav/branch_switcher.vue' do element :branch_selector_button, required: true element :branch_menu_item_button element :branch_menu_container end - view 'app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/commit/commit_form.vue' do element :source_branch_field, required: true end - view 'app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/editor/ci_editor_header.vue' do element :drawer_toggle, required: true element :template_repo_link, required: true end @@ -28,16 +28,16 @@ module QA element :source_editor_container, required: true end - view 'app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue' do element :pipeline_id_content end - view 'app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/commit/commit_form.vue' do element :commit_changes_button element :new_mr_checkbox end - view 'app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/header/validation_segment.vue' do element :validation_message_content end @@ -46,15 +46,15 @@ module QA element :job_container end - view 'app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/pipeline_editor_tabs.vue' do element :file_editor_container end - view 'app/assets/javascripts/pipeline_editor/components/popovers/file_tree_popover.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/popovers/file_tree_popover.vue' do element :file_tree_popover end - view 'app/assets/javascripts/pipeline_editor/components/validate/ci_validate.vue' do + view 'app/assets/javascripts/ci/pipeline_editor/components/validate/ci_validate.vue' do element :simulate_pipeline_button end diff --git a/qa/qa/page/project/settings/alerts.rb b/qa/qa/page/project/settings/alerts.rb index be9b61ded80..a74a227d697 100644 --- a/qa/qa/page/project/settings/alerts.rb +++ b/qa/qa/page/project/settings/alerts.rb @@ -6,14 +6,27 @@ module QA module Settings class Alerts < Page::Base view 'app/assets/javascripts/alerts_settings/components/alerts_form.vue' do - element :create_issue_checkbox + element :create_incident_checkbox element :incident_templates_dropdown element :save_changes_button element :incident_templates_item end - def enable_issues_for_incidents - check_element(:create_issue_checkbox) + view 'app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue' do + element :add_integration_button + end + + view 'app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue' do + element :integration_type_dropdown + element :integration_name_field + element :active_toggle_container + element :save_and_create_alert_button + element :test_payload_field + element :send_test_alert_button + end + + def enable_incident_for_alert + check_element(:create_incident_checkbox) end def select_issue_template(template) @@ -32,6 +45,43 @@ module QA has_text?(template) end end + + def add_new_integration + wait_for_requests + click_element(:add_integration_button) + end + + def select_http_endpoint + click_element(:integration_type_dropdown) + find("option[value='HTTP']").click + + # Click outside of the list to close it + click_element(:integration_name_field) + end + + def enter_integration_name(name) + fill_element(:integration_name_field, name) + end + + def activate_integration + within_element(:active_toggle_container) do + find('.gl-toggle').click + end + + wait_for_requests + end + + def save_and_create_alert + click_element(:save_and_create_alert_button) + end + + def fill_in_test_payload(payload) + fill_element(:test_payload_field, payload) + end + + def send_test_alert + click_element(:send_test_alert_button) + end end end end diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb index d862979aeec..ae6a04028c9 100644 --- a/qa/qa/page/project/settings/merge_request.rb +++ b/qa/qa/page/project/settings/merge_request.rb @@ -15,7 +15,7 @@ module QA element :merge_ff_radio end - view 'app/views/projects/_merge_request_merge_checks_settings.html.haml' do + view 'app/views/projects/_merge_request_pipelines_and_threads_options.html.haml' do element :allow_merge_if_all_discussions_are_resolved_checkbox end diff --git a/qa/qa/page/project/settings/monitor.rb b/qa/qa/page/project/settings/monitor.rb index 87fb0698897..8170ae31a13 100644 --- a/qa/qa/page/project/settings/monitor.rb +++ b/qa/qa/page/project/settings/monitor.rb @@ -11,8 +11,18 @@ module QA element :incidents_settings_content end + view 'app/views/projects/settings/operations/_alert_management.html.haml' do + element :alerts_settings_content + end + def expand_incidents(&block) expand_content(:incidents_settings_content) do + # Fill in with incidents settings + end + end + + def expand_alerts(&block) + expand_content(:alerts_settings_content) do Settings::Alerts.perform(&block) end end diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb index 4fbf656210f..659fe198d49 100644 --- a/qa/qa/page/project/settings/protected_branches.rb +++ b/qa/qa/page/project/settings/protected_branches.rb @@ -5,19 +5,19 @@ module QA module Project module Settings class ProtectedBranches < Page::Base - view 'app/views/projects/protected_branches/shared/_dropdown.html.haml' do + view 'app/views/protected_branches/shared/_dropdown.html.haml' do element :protected_branch_dropdown element :protected_branch_dropdown_content end - view 'app/views/projects/protected_branches/_create_protected_branch.html.haml' do + view 'app/views/protected_branches/_create_protected_branch.html.haml' do element :allowed_to_push_dropdown element :allowed_to_push_dropdown_content element :allowed_to_merge_dropdown element :allowed_to_merge_dropdown_content end - view 'app/views/projects/protected_branches/shared/_create_protected_branch.html.haml' do + view 'app/views/protected_branches/shared/_create_protected_branch.html.haml' do element :protect_button end diff --git a/qa/qa/page/project/settings/repository.rb b/qa/qa/page/project/settings/repository.rb index bf1c3130485..6931d26b259 100644 --- a/qa/qa/page/project/settings/repository.rb +++ b/qa/qa/page/project/settings/repository.rb @@ -7,7 +7,7 @@ module QA class Repository < Page::Base include QA::Page::Settings::Common - view 'app/views/projects/protected_branches/shared/_index.html.haml' do + view 'app/views/protected_branches/shared/_index.html.haml' do element :protected_branches_settings_content end diff --git a/qa/qa/page/project/settings/services/jenkins.rb b/qa/qa/page/project/settings/services/jenkins.rb index 39403995ce8..a9b5c84f9ee 100644 --- a/qa/qa/page/project/settings/services/jenkins.rb +++ b/qa/qa/page/project/settings/services/jenkins.rb @@ -13,7 +13,7 @@ module QA element :service_password_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern end - view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do + view 'app/assets/javascripts/integrations/edit/components/integration_form_actions.vue' do element :save_changes_button end diff --git a/qa/qa/page/project/settings/services/jira.rb b/qa/qa/page/project/settings/services/jira.rb index 41034bbd897..7a62b111f98 100644 --- a/qa/qa/page/project/settings/services/jira.rb +++ b/qa/qa/page/project/settings/services/jira.rb @@ -19,7 +19,7 @@ module QA element :service_jira_issue_transition_id_field end - view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do + view 'app/assets/javascripts/integrations/edit/components/integration_form_actions.vue' do element :save_changes_button end diff --git a/qa/qa/page/project/settings/services/pipeline_status_emails.rb b/qa/qa/page/project/settings/services/pipeline_status_emails.rb index 2f78577e3d5..3edd1d61d76 100644 --- a/qa/qa/page/project/settings/services/pipeline_status_emails.rb +++ b/qa/qa/page/project/settings/services/pipeline_status_emails.rb @@ -9,6 +9,9 @@ module QA view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do element :recipients_div, %q(:data-qa-selector="`${field.name}_div`") # rubocop:disable QA/ElementWithPattern element :notify_only_broken_pipelines_div, %q(:data-qa-selector="`${field.name}_div`") # rubocop:disable QA/ElementWithPattern + end + + view 'app/assets/javascripts/integrations/edit/components/integration_form_actions.vue' do element :save_changes_button end diff --git a/qa/qa/page/project/settings/services/prometheus.rb b/qa/qa/page/project/settings/services/prometheus.rb deleted file mode 100644 index 2e3c385a27d..00000000000 --- a/qa/qa/page/project/settings/services/prometheus.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -module QA - module Page - module Project - module Settings - module Services - class Prometheus < Page::Base - include Page::Component::CustomMetric - - view 'app/views/shared/integrations/prometheus/_custom_metrics.html.haml' do - element :custom_metrics_container - element :new_metric_button - end - - def click_on_custom_metric(custom_metric) - within_element :custom_metrics_container do - click_on custom_metric - end - end - - def click_on_new_metric - click_element :new_metric_button - end - - def has_custom_metric?(custom_metric) - within_element :custom_metrics_container do - has_text? custom_metric - end - end - end - end - end - end - end -end diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index a82fa7f5cf3..168bfd6aa0a 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -36,7 +36,6 @@ module QA end view 'app/views/projects/_home_panel.html.haml' do - element :forked_from_link element :project_name_content element :project_id_content element :project_badges_content @@ -48,6 +47,10 @@ module QA element :tree_holder, '.tree-holder' # rubocop:disable QA/ElementWithPattern end + view 'app/views/projects/_fork_info.html.haml' 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 diff --git a/qa/qa/page/project/sub_menus/monitor.rb b/qa/qa/page/project/sub_menus/monitor.rb index e3593e0a257..27fb58fb146 100644 --- a/qa/qa/page/project/sub_menus/monitor.rb +++ b/qa/qa/page/project/sub_menus/monitor.rb @@ -15,18 +15,18 @@ module QA end end - def go_to_monitor_metrics + def go_to_monitor_incidents hover_monitor do within_submenu do - click_element(:sidebar_menu_item_link, menu_item: 'Metrics') + click_element(:sidebar_menu_item_link, menu_item: 'Incidents') end end end - def go_to_monitor_incidents + def go_to_monitor_alerts hover_monitor do within_submenu do - click_element(:sidebar_menu_item_link, menu_item: 'Incidents') + click_element(:sidebar_menu_item_link, menu_item: 'Alerts') end end end diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb index 293fcd1e676..975d3c8ea14 100644 --- a/qa/qa/page/project/web_ide/edit.rb +++ b/qa/qa/page/project/web_ide/edit.rb @@ -109,6 +109,14 @@ module QA element :file_to_commit_content end + # Used for stablility, due to feature_caching of vscode_web_ide + def wait_until_ide_loads + Support::Waiter.wait_until(sleep_interval: 2, max_duration: 60, reload_page: page, + retry_on_exception: true) do + has_element?(:commit_mode_tab) + end + end + def has_file?(file_name) within_element(:file_list_container) do has_element?(:file_name_content, file_name: file_name) |