diff options
Diffstat (limited to 'spec/support/helpers/features')
23 files changed, 725 insertions, 779 deletions
diff --git a/spec/support/helpers/features/access_token_helpers.rb b/spec/support/helpers/features/access_token_helpers.rb index f4bdb70c160..bc839642914 100644 --- a/spec/support/helpers/features/access_token_helpers.rb +++ b/spec/support/helpers/features/access_token_helpers.rb @@ -1,18 +1,15 @@ # frozen_string_literal: true -module Spec - module Support - module Helpers - module AccessTokenHelpers - def active_access_tokens - find("[data-testid='active-tokens']") - end - def created_access_token - within('[data-testid=access-token-section]') do - find('[data-testid=toggle-visibility-button]').click - find_field('new-access-token').value - end - end +module Features + module AccessTokenHelpers + def active_access_tokens + find("[data-testid='active-tokens']") + end + + def created_access_token + within('[data-testid=access-token-section]') do + find('[data-testid=toggle-visibility-button]').click + find_field('new-access-token').value end end end diff --git a/spec/support/helpers/features/admin_users_helpers.rb b/spec/support/helpers/features/admin_users_helpers.rb index 99b19eedcff..9a87ccf113a 100644 --- a/spec/support/helpers/features/admin_users_helpers.rb +++ b/spec/support/helpers/features/admin_users_helpers.rb @@ -1,24 +1,18 @@ # frozen_string_literal: true -module Spec - module Support - module Helpers - module Features - module AdminUsersHelpers - def click_user_dropdown_toggle(user_id) - page.within("[data-testid='user-actions-#{user_id}']") do - find("[data-testid='dropdown-toggle']").click - end - end +module Features + module AdminUsersHelpers + def click_user_dropdown_toggle(user_id) + page.within("[data-testid='user-actions-#{user_id}']") do + find("[data-testid='dropdown-toggle']").click + end + end - def click_action_in_user_dropdown(user_id, action) - click_user_dropdown_toggle(user_id) + def click_action_in_user_dropdown(user_id, action) + click_user_dropdown_toggle(user_id) - within find("[data-testid='user-actions-#{user_id}']") do - find('li button', exact_text: action).click - end - end - end + within find("[data-testid='user-actions-#{user_id}']") do + find('li button', exact_text: action).click end end end diff --git a/spec/support/helpers/features/blob_spec_helpers.rb b/spec/support/helpers/features/blob_spec_helpers.rb index 7ccfc9be7e2..8254e1d76bd 100644 --- a/spec/support/helpers/features/blob_spec_helpers.rb +++ b/spec/support/helpers/features/blob_spec_helpers.rb @@ -1,14 +1,16 @@ # frozen_string_literal: true -# These helpers help you interact within the blobs page and blobs edit page (Single file editor). -module BlobSpecHelpers - include ActionView::Helpers::JavaScriptHelper +module Features + # These helpers help you interact within the blobs page and blobs edit page (Single file editor). + module BlobSpecHelpers + include ActionView::Helpers::JavaScriptHelper - def set_default_button(type) - evaluate_script("localStorage.setItem('gl-web-ide-button-selected', '#{type}')") - end + def set_default_button(type) + evaluate_script("localStorage.setItem('gl-web-ide-button-selected', '#{type}')") + end - def unset_default_button - set_default_button('') + def unset_default_button + set_default_button('') + end end end diff --git a/spec/support/helpers/features/branches_helpers.rb b/spec/support/helpers/features/branches_helpers.rb index dc4fa448167..9fb6236d052 100644 --- a/spec/support/helpers/features/branches_helpers.rb +++ b/spec/support/helpers/features/branches_helpers.rb @@ -4,31 +4,28 @@ # # Usage: # describe "..." do -# include Spec::Support::Helpers::Features::BranchesHelpers +# include Features::BranchesHelpers # ... # # create_branch("feature") # select_branch("master") # -module Spec - module Support - module Helpers - module Features - module BranchesHelpers - def create_branch(branch_name, source_branch_name = "master") - fill_in("branch_name", with: branch_name) - select_branch(source_branch_name) - click_button("Create branch") - end +module Features + module BranchesHelpers + include ListboxHelpers - def select_branch(branch_name) - wait_for_requests + def create_branch(branch_name, source_branch_name = "master") + fill_in("branch_name", with: branch_name) + select_branch(source_branch_name) + click_button("Create branch") + end + + def select_branch(branch_name) + wait_for_requests - click_button branch_name - send_keys branch_name - end - end - end + click_button branch_name + send_keys branch_name + select_listbox_item(branch_name) end end end diff --git a/spec/support/helpers/features/canonical_link_helpers.rb b/spec/support/helpers/features/canonical_link_helpers.rb index da3a28f1cb2..6ef934a924b 100644 --- a/spec/support/helpers/features/canonical_link_helpers.rb +++ b/spec/support/helpers/features/canonical_link_helpers.rb @@ -4,25 +4,19 @@ # # Usage: # describe "..." do -# include Spec::Support::Helpers::Features::CanonicalLinkHelpers +# include Features::CanonicalLinkHelpers # ... # # expect(page).to have_canonical_link(url) # -module Spec - module Support - module Helpers - module Features - module CanonicalLinkHelpers - def have_canonical_link(url) - have_xpath("//link[@rel=\"canonical\" and @href=\"#{url}\"]", visible: false) - end +module Features + module CanonicalLinkHelpers + def have_canonical_link(url) + have_xpath("//link[@rel=\"canonical\" and @href=\"#{url}\"]", visible: false) + end - def have_any_canonical_links - have_xpath('//link[@rel="canonical"]', visible: false) - end - end - end + def have_any_canonical_links + have_xpath('//link[@rel="canonical"]', visible: false) end end end diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb deleted file mode 100644 index 47cbd6b5208..00000000000 --- a/spec/support/helpers/features/invite_members_modal_helper.rb +++ /dev/null @@ -1,154 +0,0 @@ -# frozen_string_literal: true - -module Spec - module Support - module Helpers - module Features - module InviteMembersModalHelper - def invite_member(names, role: 'Guest', expires_at: nil) - click_on 'Invite members' - - page.within invite_modal_selector do - select_members(names) - choose_options(role, expires_at) - submit_invites - end - - wait_for_requests - end - - def invite_member_by_email(role) - click_on _('Invite members') - - page.within invite_modal_selector do - choose_options(role, nil) - find(member_dropdown_selector).set('new_email@gitlab.com') - wait_for_requests - - find('.dropdown-item', text: 'Invite "new_email@gitlab.com" by email').click - - submit_invites - - wait_for_requests - end - end - - def input_invites(names) - click_on 'Invite members' - - page.within invite_modal_selector do - select_members(names) - end - end - - def select_members(names) - Array.wrap(names).each do |name| - find(member_dropdown_selector).set(name) - - wait_for_requests - click_button name - end - end - - def invite_group(name, role: 'Guest', expires_at: nil) - click_on 'Invite a group' - - click_on 'Select a group' - wait_for_requests - click_button name - choose_options(role, expires_at) - - submit_invites - end - - def submit_invites - click_button 'Invite' - end - - def choose_options(role, expires_at) - select role, from: 'Select a role' - fill_in 'YYYY-MM-DD', with: expires_at.strftime('%Y-%m-%d') if expires_at - end - - def click_groups_tab - expect(page).to have_link 'Groups' - click_link "Groups" - end - - def group_dropdown_selector - '[data-testid="group-select-dropdown"]' - end - - def member_dropdown_selector - '[data-testid="members-token-select-input"]' - end - - def invite_modal_selector - '[data-testid="invite-modal"]' - end - - def member_token_error_selector(id) - "[data-testid='error-icon-#{id}']" - end - - def member_token_avatar_selector - "[data-testid='token-avatar']" - end - - def member_token_selector(id) - "[data-token-id='#{id}']" - end - - def more_invite_errors_button_selector - "[data-testid='accordion-button']" - end - - def limited_invite_error_selector - "[data-testid='errors-limited-item']" - end - - def expanded_invite_error_selector - "[data-testid='errors-expanded-item']" - end - - def remove_token(id) - page.within member_token_selector(id) do - find('[data-testid="close-icon"]').click - end - end - - def expect_to_have_successful_invite_indicator(page, user) - expect(page).to have_selector("#{member_token_selector(user.id)} .gl-bg-green-100") - expect(page).not_to have_text("#{user.name}: ") - end - - def expect_to_have_invalid_invite_indicator(page, user, message: true) - expect(page).to have_selector("#{member_token_selector(user.id)} .gl-bg-red-100") - expect(page).to have_selector(member_token_error_selector(user.id)) - expect(page).to have_text("#{user.name}: Access level should be greater than or equal to") if message - end - - def expect_to_have_normal_invite_indicator(page, user) - expect(page).to have_selector(member_token_selector(user.id)) - expect(page).not_to have_selector("#{member_token_selector(user.id)} .gl-bg-red-100") - expect(page).not_to have_selector("#{member_token_selector(user.id)} .gl-bg-green-100") - expect(page).not_to have_text("#{user.name}: ") - end - - def expect_to_have_invite_removed(page, user) - expect(page).not_to have_selector(member_token_selector(user.id)) - expect(page).not_to have_text("#{user.name}: Access level should be greater than or equal to") - end - - def expect_to_have_group(group) - expect(page).to have_selector("[entity-id='#{group.id}']") - end - - def expect_not_to_have_group(group) - expect(page).not_to have_selector("[entity-id='#{group.id}']") - end - end - end - end - end -end diff --git a/spec/support/helpers/features/invite_members_modal_helpers.rb b/spec/support/helpers/features/invite_members_modal_helpers.rb new file mode 100644 index 00000000000..75573616686 --- /dev/null +++ b/spec/support/helpers/features/invite_members_modal_helpers.rb @@ -0,0 +1,148 @@ +# frozen_string_literal: true + +module Features + module InviteMembersModalHelpers + def invite_member(names, role: 'Guest', expires_at: nil) + click_on 'Invite members' + + page.within invite_modal_selector do + select_members(names) + choose_options(role, expires_at) + submit_invites + end + + wait_for_requests + end + + def invite_member_by_email(role) + click_on _('Invite members') + + page.within invite_modal_selector do + choose_options(role, nil) + find(member_dropdown_selector).set('new_email@gitlab.com') + wait_for_requests + + find('.dropdown-item', text: 'Invite "new_email@gitlab.com" by email').click + + submit_invites + + wait_for_requests + end + end + + def input_invites(names) + click_on 'Invite members' + + page.within invite_modal_selector do + select_members(names) + end + end + + def select_members(names) + Array.wrap(names).each do |name| + find(member_dropdown_selector).set(name) + + wait_for_requests + click_button name + end + end + + def invite_group(name, role: 'Guest', expires_at: nil) + click_on 'Invite a group' + + click_on 'Select a group' + wait_for_requests + click_button name + choose_options(role, expires_at) + + submit_invites + end + + def submit_invites + click_button 'Invite' + end + + def choose_options(role, expires_at) + select role, from: 'Select a role' + fill_in 'YYYY-MM-DD', with: expires_at.strftime('%Y-%m-%d') if expires_at + end + + def click_groups_tab + expect(page).to have_link 'Groups' + click_link "Groups" + end + + def group_dropdown_selector + '[data-testid="group-select-dropdown"]' + end + + def member_dropdown_selector + '[data-testid="members-token-select-input"]' + end + + def invite_modal_selector + '[data-testid="invite-modal"]' + end + + def member_token_error_selector(id) + "[data-testid='error-icon-#{id}']" + end + + def member_token_avatar_selector + "[data-testid='token-avatar']" + end + + def member_token_selector(id) + "[data-token-id='#{id}']" + end + + def more_invite_errors_button_selector + "[data-testid='accordion-button']" + end + + def limited_invite_error_selector + "[data-testid='errors-limited-item']" + end + + def expanded_invite_error_selector + "[data-testid='errors-expanded-item']" + end + + def remove_token(id) + page.within member_token_selector(id) do + find('[data-testid="close-icon"]').click + end + end + + def expect_to_have_successful_invite_indicator(page, user) + expect(page).to have_selector("#{member_token_selector(user.id)} .gl-bg-green-100") + expect(page).not_to have_text("#{user.name}: ") + end + + def expect_to_have_invalid_invite_indicator(page, user, message: true) + expect(page).to have_selector("#{member_token_selector(user.id)} .gl-bg-red-100") + expect(page).to have_selector(member_token_error_selector(user.id)) + expect(page).to have_text("#{user.name}: Access level should be greater than or equal to") if message + end + + def expect_to_have_normal_invite_indicator(page, user) + expect(page).to have_selector(member_token_selector(user.id)) + expect(page).not_to have_selector("#{member_token_selector(user.id)} .gl-bg-red-100") + expect(page).not_to have_selector("#{member_token_selector(user.id)} .gl-bg-green-100") + expect(page).not_to have_text("#{user.name}: ") + end + + def expect_to_have_invite_removed(page, user) + expect(page).not_to have_selector(member_token_selector(user.id)) + expect(page).not_to have_text("#{user.name}: Access level should be greater than or equal to") + end + + def expect_to_have_group(group) + expect(page).to have_selector("[entity-id='#{group.id}']") + end + + def expect_not_to_have_group(group) + expect(page).not_to have_selector("[entity-id='#{group.id}']") + end + end +end diff --git a/spec/support/helpers/features/iteration_helpers.rb b/spec/support/helpers/features/iteration_helpers.rb index 8e1d252f55f..fab373a547f 100644 --- a/spec/support/helpers/features/iteration_helpers.rb +++ b/spec/support/helpers/features/iteration_helpers.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true -module IterationHelpers - def iteration_period(iteration) - "#{iteration.start_date.to_s(:medium)} - #{iteration.due_date.to_s(:medium)}" + +module Features + module IterationHelpers + def iteration_period(iteration) + "#{iteration.start_date.to_s(:medium)} - #{iteration.due_date.to_s(:medium)}" + end end end diff --git a/spec/support/helpers/features/list_rows_helpers.rb b/spec/support/helpers/features/list_rows_helpers.rb deleted file mode 100644 index 0626415361c..00000000000 --- a/spec/support/helpers/features/list_rows_helpers.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true -# These helpers allow you to access rows in the list -# -# Usage: -# describe "..." do -# include Spec::Support::Helpers::Features::ListRowsHelpers -# ... -# -# expect(first_row.text).to include("John Doe") -# expect(second_row.text).to include("John Smith") -# -module Spec - module Support - module Helpers - module Features - module ListRowsHelpers - def first_row - page.all('ul.content-list > li')[0] - end - - def second_row - page.all('ul.content-list > li')[1] - end - end - end - end - end -end diff --git a/spec/support/helpers/features/members_helpers.rb b/spec/support/helpers/features/members_helpers.rb index 2d3f0902a3c..9882767cecf 100644 --- a/spec/support/helpers/features/members_helpers.rb +++ b/spec/support/helpers/features/members_helpers.rb @@ -1,78 +1,72 @@ # frozen_string_literal: true -module Spec - module Support - module Helpers - module Features - module MembersHelpers - def members_table - page.find('[data-testid="members-table"]') - end +module Features + module MembersHelpers + def members_table + page.find('[data-testid="members-table"]') + end - def all_rows - page.within(members_table) do - page.all('tbody > tr') - end - end + def all_rows + page.within(members_table) do + page.all('tbody > tr') + end + end - def first_row - all_rows[0] - end + def first_row + all_rows[0] + end - def second_row - all_rows[1] - end + def second_row + all_rows[1] + end - def third_row - all_rows[2] - end + def third_row + all_rows[2] + end - def find_row(name) - page.within(members_table) do - page.find('tbody > tr', text: name) - end - end + def find_row(name) + page.within(members_table) do + page.find('tbody > tr', text: name) + end + end - def find_member_row(user) - find_row(user.name) - end + def find_member_row(user) + find_row(user.name) + end - def find_username_row(user) - find_row(user.username) - end + def find_username_row(user) + find_row(user.username) + end - def find_invited_member_row(email) - find_row(email) - end + def find_invited_member_row(email) + find_row(email) + end - def find_group_row(group) - find_row(group.full_name) - end + def find_group_row(group) + find_row(group.full_name) + end - def fill_in_filtered_search(label, with:) - page.within '[data-testid="members-filtered-search-bar"]' do - find_field(label).click - find('input').native.send_keys(with) - click_button 'Search' - end - end + def fill_in_filtered_search(label, with:) + page.within '[data-testid="members-filtered-search-bar"]' do + find_field(label).click + find('input').native.send_keys(with) + click_button 'Search' + end + end - def user_action_dropdown - '[data-testid="user-action-dropdown"]' - end + def user_action_dropdown + '[data-testid="user-action-dropdown"]' + end - def show_actions - within user_action_dropdown do - find('button').click - end - end + def show_actions + within user_action_dropdown do + find('button').click + end + end - def show_actions_for_username(user) - within find_username_row(user) do - show_actions - end - end - end + def show_actions_for_username(user) + within find_username_row(user) do + show_actions end end end diff --git a/spec/support/helpers/features/merge_request_helpers.rb b/spec/support/helpers/features/merge_request_helpers.rb index 53896e1fe12..260a55487ea 100644 --- a/spec/support/helpers/features/merge_request_helpers.rb +++ b/spec/support/helpers/features/merge_request_helpers.rb @@ -1,25 +1,19 @@ # frozen_string_literal: true -module Spec - module Support - module Helpers - module Features - module MergeRequestHelpers - def preload_view_requirements(merge_request, note) - # This will load the status fields of the author of the note and merge request - # to avoid queries when rendering the view being tested. - # - merge_request.author.status - note.author.status - end +module Features + module MergeRequestHelpers + def preload_view_requirements(merge_request, note) + # This will load the status fields of the author of the note and merge request + # to avoid queries when rendering the view being tested. + # + merge_request.author.status + note.author.status + end - def serialize_issuable_sidebar(user, project, merge_request) - MergeRequestSerializer - .new(current_user: user, project: project) - .represent(merge_request, serializer: 'sidebar') - end - end - end + def serialize_issuable_sidebar(user, project, merge_request) + MergeRequestSerializer + .new(current_user: user, project: project) + .represent(merge_request, serializer: 'sidebar') end end end diff --git a/spec/support/helpers/features/mirroring_helpers.rb b/spec/support/helpers/features/mirroring_helpers.rb new file mode 100644 index 00000000000..0c3006cd1d1 --- /dev/null +++ b/spec/support/helpers/features/mirroring_helpers.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# These helpers allow you to set up mirroring. +# +# Usage: +# describe "..." do +# include Features::MirroringHelpers +# ... +# +# fill_and_wait_for_mirror_url_javascript("url", "ssh://user@localhost/project.git") +# wait_for_mirror_field_javascript("protected", "0") +# +module Features + module MirroringHelpers + # input_identifier - identifier of the input field, passed to `fill_in` (can be an ID or a label). + # url - the URL to fill the input field with. + def fill_and_wait_for_mirror_url_javascript(input_identifier, url) + fill_in input_identifier, with: url + wait_for_mirror_field_javascript('url', url) + end + + # attribute - can be `url` or `protected`. It's used in the `.js-mirror-<field>-hidden` selector. + # expected_value - the expected value of the hidden field. + def wait_for_mirror_field_javascript(attribute, expected_value) + expect(page).to have_css(".js-mirror-#{attribute}-hidden[value=\"#{expected_value}\"]", visible: :hidden) + end + end +end diff --git a/spec/support/helpers/features/notes_helpers.rb b/spec/support/helpers/features/notes_helpers.rb index f8252254531..7973d541f9c 100644 --- a/spec/support/helpers/features/notes_helpers.rb +++ b/spec/support/helpers/features/notes_helpers.rb @@ -4,53 +4,47 @@ # # Usage: # describe "..." do -# include Spec::Support::Helpers::Features::NotesHelpers +# include Features::NotesHelpers # ... # # add_note("Hello world!") # -module Spec - module Support - module Helpers - module Features - module NotesHelpers - def add_note(text) - perform_enqueued_jobs do - page.within(".js-main-target-form") do - fill_in("note[note]", with: text) - find(".js-comment-submit-button").click - end - end - - wait_for_requests - end - - def edit_note(note_text_to_edit, new_note_text) - page.within('#notes-list li.note', text: note_text_to_edit) do - find('.js-note-edit').click - fill_in('note[note]', with: new_note_text) - find('.js-comment-button').click - end - - wait_for_requests - end - - def preview_note(text) - page.within('.js-main-target-form') do - filled_text = fill_in('note[note]', with: text) - - # Wait for quick action prompt to load and then dismiss it with ESC - # because it may block the Preview button - wait_for_requests - filled_text.send_keys(:escape) - - click_on('Preview') - - yield if block_given? - end - end +module Features + module NotesHelpers + def add_note(text) + perform_enqueued_jobs do + page.within(".js-main-target-form") do + fill_in("note[note]", with: text) + find(".js-comment-submit-button").click end end + + wait_for_requests + end + + def edit_note(note_text_to_edit, new_note_text) + page.within('#notes-list li.note', text: note_text_to_edit) do + find('.js-note-edit').click + fill_in('note[note]', with: new_note_text) + find('.js-comment-button').click + end + + wait_for_requests + end + + def preview_note(text) + page.within('.js-main-target-form') do + filled_text = fill_in('note[note]', with: text) + + # Wait for quick action prompt to load and then dismiss it with ESC + # because it may block the Preview button + wait_for_requests + filled_text.send_keys(:escape) + + click_button("Preview") + + yield if block_given? + end end end end diff --git a/spec/support/helpers/features/releases_helpers.rb b/spec/support/helpers/features/releases_helpers.rb index 545e12341ef..d5846aad15d 100644 --- a/spec/support/helpers/features/releases_helpers.rb +++ b/spec/support/helpers/features/releases_helpers.rb @@ -4,80 +4,83 @@ # # Usage: # describe "..." do -# include Spec::Support::Helpers::Features::ReleasesHelpers +# include Features::ReleasesHelpers # ... # # fill_tag_name("v1.0") # select_create_from("my-feature-branch") # -module Spec - module Support - module Helpers - module Features - module ReleasesHelpers - include ListboxHelpers +module Features + module ReleasesHelpers + include ListboxHelpers - def select_new_tag_name(tag_name) - page.within '[data-testid="tag-name-field"]' do - find('button').click - wait_for_all_requests + def select_new_tag_name(tag_name) + open_tag_popover - find('input[aria-label="Search or create tag"]').set(tag_name) - wait_for_all_requests + page.within '[data-testid="tag-name-search"]' do + find('input[type="search"]').set(tag_name) + wait_for_all_requests - click_button("Create tag #{tag_name}") - click_button tag_name - end - end - - def select_create_from(branch_name) - page.within '[data-testid="create-from-field"]' do - find('button').click + click_button("Create tag #{tag_name}") + end + end - wait_for_all_requests + def select_create_from(branch_name) + open_tag_popover - find('input[aria-label="Search branches, tags, and commits"]').set(branch_name) + page.within '[data-testid="create-from-field"]' do + find('.ref-selector button').click - wait_for_all_requests + wait_for_all_requests - select_listbox_item(branch_name.to_s, exact_text: true) - end - end + find('input[aria-label="Search branches, tags, and commits"]').set(branch_name) - def fill_release_title(release_title) - fill_in('Release title', with: release_title) - end + wait_for_all_requests - def select_milestone(milestone_title) - page.within '[data-testid="milestones-field"]' do - find('button').click + select_listbox_item(branch_name.to_s, exact_text: true) - wait_for_all_requests + click_button _('Save') + end + end - find('input[aria-label="Search Milestones"]').set(milestone_title) + def fill_release_title(release_title) + fill_in('Release title', with: release_title) + end - wait_for_all_requests + def select_milestone(milestone_title) + page.within '[data-testid="milestones-field"]' do + find('button').click - find('button', text: milestone_title, match: :first).click - end - end + wait_for_all_requests - def fill_release_notes(release_notes) - fill_in('Release notes', with: release_notes) - end + find('input[aria-label="Search Milestones"]').set(milestone_title) - def fill_asset_link(link) - all('input[name="asset-url"]').last.set(link[:url]) - all('input[name="asset-link-name"]').last.set(link[:title]) - all('select[name="asset-type"]').last.find("option[value=\"#{link[:type]}\"").select_option - end + wait_for_all_requests - # Click "Add another link" and tab back to the beginning of the new row - def add_another_asset_link - click_button('Add another link') - end - end + find('button', text: milestone_title, match: :first).click end end + + def fill_release_notes(release_notes) + fill_in('Release notes', with: release_notes) + end + + def fill_asset_link(link) + all('input[name="asset-url"]').last.set(link[:url]) + all('input[name="asset-link-name"]').last.set(link[:title]) + all('select[name="asset-type"]').last.find("option[value=\"#{link[:type]}\"").select_option + end + + # Click "Add another link" and tab back to the beginning of the new row + def add_another_asset_link + click_button('Add another link') + end + + def open_tag_popover(name = s_('Release|Search or create tag name')) + return if page.has_css? '.release-tag-selector' + + click_button name + wait_for_all_requests + end end end diff --git a/spec/support/helpers/features/responsive_table_helpers.rb b/spec/support/helpers/features/responsive_table_helpers.rb index 7a175219fe9..980f09b7eea 100644 --- a/spec/support/helpers/features/responsive_table_helpers.rb +++ b/spec/support/helpers/features/responsive_table_helpers.rb @@ -3,7 +3,7 @@ # # Usage: # describe "..." do -# include Spec::Support::Helpers::Features::ResponsiveTableHelpers +# include Features::ResponsiveTableHelpers # ... # # expect(first_row.text).to include("John Doe") @@ -13,20 +13,14 @@ # index starts at 1 as index 0 is expected to be the table header # # -module Spec - module Support - module Helpers - module Features - module ResponsiveTableHelpers - def first_row - page.all('.gl-responsive-table-row')[1] - end +module Features + module ResponsiveTableHelpers + def first_row + page.all('.gl-responsive-table-row')[1] + end - def second_row - page.all('.gl-responsive-table-row')[2] - end - end - end + def second_row + page.all('.gl-responsive-table-row')[2] end end end diff --git a/spec/support/helpers/features/runners_helpers.rb b/spec/support/helpers/features/runners_helpers.rb index c5d26108953..0504e883b82 100644 --- a/spec/support/helpers/features/runners_helpers.rb +++ b/spec/support/helpers/features/runners_helpers.rb @@ -1,68 +1,62 @@ # frozen_string_literal: true -module Spec - module Support - module Helpers - module Features - module RunnersHelpers - def within_runner_row(runner_id) - within "[data-testid='runner-row-#{runner_id}']" do - yield - end - end - - def search_bar_selector - '[data-testid="runners-filtered-search"]' - end +module Features + module RunnersHelpers + def within_runner_row(runner_id) + within "[data-testid='runner-row-#{runner_id}']" do + yield + end + end - # The filters must be clicked first to be able to receive events - # See: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1493 - def focus_filtered_search - page.within(search_bar_selector) do - page.find('.gl-filtered-search-term-token').click - end - end + def search_bar_selector + '[data-testid="runners-filtered-search"]' + end - def input_filtered_search_keys(search_term) - focus_filtered_search + # The filters must be clicked first to be able to receive events + # See: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1493 + def focus_filtered_search + page.within(search_bar_selector) do + page.find('.gl-filtered-search-term-token').click + end + end - page.within(search_bar_selector) do - page.find('input').send_keys(search_term) - click_on 'Search' - end + def input_filtered_search_keys(search_term) + focus_filtered_search - wait_for_requests - end + page.within(search_bar_selector) do + page.find('input').send_keys(search_term) + click_on 'Search' + end - def open_filtered_search_suggestions(filter) - focus_filtered_search + wait_for_requests + end - page.within(search_bar_selector) do - click_on filter - end + def open_filtered_search_suggestions(filter) + focus_filtered_search - wait_for_requests - end + page.within(search_bar_selector) do + click_on filter + end - def input_filtered_search_filter_is_only(filter, value) - focus_filtered_search + wait_for_requests + end - page.within(search_bar_selector) do - click_on filter + def input_filtered_search_filter_is_only(filter, value) + focus_filtered_search - # For OPERATORS_IS, clicking the filter - # immediately preselects "=" operator + page.within(search_bar_selector) do + click_on filter - page.find('input').send_keys(value) - page.find('input').send_keys(:enter) + # For OPERATORS_IS, clicking the filter + # immediately preselects "=" operator - click_on 'Search' - end + page.find('input').send_keys(value) + page.find('input').send_keys(:enter) - wait_for_requests - end - end + click_on 'Search' end + + wait_for_requests end end end diff --git a/spec/support/helpers/features/snippet_helpers.rb b/spec/support/helpers/features/snippet_helpers.rb deleted file mode 100644 index 3e32b0e4c67..00000000000 --- a/spec/support/helpers/features/snippet_helpers.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: true - -# These helpers help you interact within the Source Editor (single-file editor, snippets, etc.). -# - -require Rails.root.join("spec/support/helpers/features/source_editor_spec_helpers.rb") - -module Spec - module Support - module Helpers - module Features - module SnippetSpecHelpers - include ActionView::Helpers::JavaScriptHelper - include Spec::Support::Helpers::Features::SourceEditorSpecHelpers - - def snippet_description_locator - 'snippet-description' - end - - def snippet_blob_path_locator - 'snippet_file_name' - end - - def snippet_description_view_selector - '.snippet-header .snippet-description' - end - - def snippet_description_field_collapsed - find('.js-description-input').find('input,textarea') - end - - def snippet_get_first_blob_path - page.find_field('snippet_file_name', match: :first).value - end - - def snippet_get_first_blob_value - page.find('.gl-source-editor', match: :first) - end - - def snippet_description_value - page.find_field(snippet_description_locator).value - end - - def snippet_fill_in_visibility(text) - page.find('#visibility-level-setting').choose(text) - end - - def snippet_fill_in_title(value) - fill_in 'snippet-title', with: value - end - - def snippet_fill_in_description(value) - # Click placeholder first to expand full description field - snippet_description_field_collapsed.click - fill_in snippet_description_locator, with: value - end - - def snippet_fill_in_content(value) - page.within('.gl-source-editor') do - el = find('.inputarea') - el.send_keys value - end - end - - def snippet_fill_in_file_name(value) - fill_in(snippet_blob_path_locator, match: :first, with: value) - end - - def snippet_fill_in_form(title: nil, content: nil, file_name: nil, description: nil, visibility: nil) - if content - snippet_fill_in_content(content) - # It takes some time after sending keys for the vue component to - # update so let Capybara wait for the content before proceeding - expect(page).to have_content(content) - end - - snippet_fill_in_title(title) if title - - snippet_fill_in_description(description) if description - - snippet_fill_in_file_name(file_name) if file_name - - snippet_fill_in_visibility(visibility) if visibility - end - end - end - end - end -end diff --git a/spec/support/helpers/features/snippet_spec_helpers.rb b/spec/support/helpers/features/snippet_spec_helpers.rb new file mode 100644 index 00000000000..19393f6e438 --- /dev/null +++ b/spec/support/helpers/features/snippet_spec_helpers.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +# These helpers help you interact within the Source Editor (single-file editor, snippets, etc.). +# + +require Rails.root.join("spec/support/helpers/features/source_editor_spec_helpers.rb") + +module Features + module SnippetSpecHelpers + include ActionView::Helpers::JavaScriptHelper + include Features::SourceEditorSpecHelpers + + def snippet_description_locator + 'snippet-description' + end + + def snippet_blob_path_locator + 'snippet_file_name' + end + + def snippet_description_view_selector + '.snippet-header .snippet-description' + end + + def snippet_description_field_collapsed + find('.js-description-input').find('input,textarea') + end + + def snippet_get_first_blob_path + page.find_field('snippet_file_name', match: :first).value + end + + def snippet_get_first_blob_value + page.find('.gl-source-editor', match: :first) + end + + def snippet_description_value + page.find_field(snippet_description_locator).value + end + + def snippet_fill_in_visibility(text) + page.find('#visibility-level-setting').choose(text) + end + + def snippet_fill_in_title(value) + fill_in 'snippet-title', with: value + end + + def snippet_fill_in_description(value) + # Click placeholder first to expand full description field + snippet_description_field_collapsed.click + fill_in snippet_description_locator, with: value + end + + def snippet_fill_in_content(value) + page.within('.gl-source-editor') do + el = find('.inputarea') + el.send_keys value + end + end + + def snippet_fill_in_file_name(value) + fill_in(snippet_blob_path_locator, match: :first, with: value) + end + + def snippet_fill_in_form(title: nil, content: nil, file_name: nil, description: nil, visibility: nil) + if content + snippet_fill_in_content(content) + # It takes some time after sending keys for the vue component to + # update so let Capybara wait for the content before proceeding + expect(page).to have_content(content) + end + + snippet_fill_in_title(title) if title + + snippet_fill_in_description(description) if description + + snippet_fill_in_file_name(file_name) if file_name + + snippet_fill_in_visibility(visibility) if visibility + end + end +end diff --git a/spec/support/helpers/features/sorting_helpers.rb b/spec/support/helpers/features/sorting_helpers.rb index 504a9b764cf..8dda16af625 100644 --- a/spec/support/helpers/features/sorting_helpers.rb +++ b/spec/support/helpers/features/sorting_helpers.rb @@ -4,33 +4,27 @@ # # Usage: # describe "..." do -# include Spec::Support::Helpers::Features::SortingHelpers +# include Features::SortingHelpers # ... # # sort_by("Last updated") # -module Spec - module Support - module Helpers - module Features - module SortingHelpers - def sort_by(value) - find('.filter-dropdown-container .dropdown').click +module Features + module SortingHelpers + def sort_by(value) + find('.filter-dropdown-container .dropdown').click - page.within('ul.dropdown-menu.dropdown-menu-right li') do - click_link(value) - end - end - - # pajamas_sort_by is used to sort new pajamas dropdowns. When - # all of the dropdowns are converted, pajamas_sort_by can be renamed to sort_by - # https://gitlab.com/groups/gitlab-org/-/epics/7551 - def pajamas_sort_by(value) - find('.filter-dropdown-container .gl-new-dropdown').click - find('.gl-new-dropdown-item', text: value).click - end - end + page.within('ul.dropdown-menu.dropdown-menu-right li') do + click_link(value) end end + + # pajamas_sort_by is used to sort new pajamas dropdowns. When + # all of the dropdowns are converted, pajamas_sort_by can be renamed to sort_by + # https://gitlab.com/groups/gitlab-org/-/epics/7551 + def pajamas_sort_by(value) + find('.filter-dropdown-container .gl-new-dropdown').click + find('.gl-new-dropdown-item', text: value).click + end end end diff --git a/spec/support/helpers/features/source_editor_spec_helpers.rb b/spec/support/helpers/features/source_editor_spec_helpers.rb index f7eb2a52507..e20ded60b01 100644 --- a/spec/support/helpers/features/source_editor_spec_helpers.rb +++ b/spec/support/helpers/features/source_editor_spec_helpers.rb @@ -2,24 +2,18 @@ # These helpers help you interact within the Source Editor (single-file editor, snippets, etc.). # -module Spec - module Support - module Helpers - module Features - module SourceEditorSpecHelpers - include ActionView::Helpers::JavaScriptHelper +module Features + module SourceEditorSpecHelpers + include ActionView::Helpers::JavaScriptHelper - def editor_set_value(value) - editor = find('.monaco-editor') - uri = editor['data-uri'] - execute_script("localMonaco.getModel('#{uri}').setValue('#{escape_javascript(value)}')") + def editor_set_value(value) + editor = find('.monaco-editor') + uri = editor['data-uri'] + execute_script("localMonaco.getModel('#{uri}').setValue('#{escape_javascript(value)}')") - # We only check that the first line is present because when the content is long, - # only a part of the text will be rendered in the DOM due to scrolling - page.has_selector?('.gl-source-editor .view-lines', text: value.lines.first) - end - end - end + # We only check that the first line is present because when the content is long, + # only a part of the text will be rendered in the DOM due to scrolling + page.has_selector?('.gl-source-editor .view-lines', text: value.lines.first) end end end diff --git a/spec/support/helpers/features/top_nav_spec_helpers.rb b/spec/support/helpers/features/top_nav_spec_helpers.rb index de495eceabc..ecc05189fb4 100644 --- a/spec/support/helpers/features/top_nav_spec_helpers.rb +++ b/spec/support/helpers/features/top_nav_spec_helpers.rb @@ -2,37 +2,31 @@ # These helpers help you interact within the Source Editor (single-file editor, snippets, etc.). # -module Spec - module Support - module Helpers - module Features - module TopNavSpecHelpers - def open_top_nav - find('.js-top-nav-dropdown-toggle').click - end +module Features + module TopNavSpecHelpers + def open_top_nav + find('.js-top-nav-dropdown-toggle').click + end - def within_top_nav - within('.js-top-nav-dropdown-menu') do - yield - end - end + def within_top_nav + within('.js-top-nav-dropdown-menu') do + yield + end + end - def open_top_nav_projects - open_top_nav + def open_top_nav_projects + open_top_nav - within_top_nav do - click_button('Projects') - end - end + within_top_nav do + click_button('Projects') + end + end - def open_top_nav_groups - open_top_nav + def open_top_nav_groups + open_top_nav - within_top_nav do - click_button('Groups') - end - end - end + within_top_nav do + click_button('Groups') end end end diff --git a/spec/support/helpers/features/two_factor_helpers.rb b/spec/support/helpers/features/two_factor_helpers.rb index 08a7665201f..e0469091d96 100644 --- a/spec/support/helpers/features/two_factor_helpers.rb +++ b/spec/support/helpers/features/two_factor_helpers.rb @@ -4,71 +4,86 @@ # # Usage: # describe "..." do -# include Spec::Support::Helpers::Features::TwoFactorHelpers +# include Features::TwoFactorHelpers # ... # # manage_two_factor_authentication # -module Spec - module Support - module Helpers - module Features - module TwoFactorHelpers - def manage_two_factor_authentication - click_on 'Manage two-factor authentication' - expect(page).to have_content("Set up new device") - wait_for_requests - end - - def register_u2f_device(u2f_device = nil, name: 'My device') - u2f_device ||= FakeU2fDevice.new(page, name) - u2f_device.respond_to_u2f_registration - click_on 'Set up new device' - expect(page).to have_content('Your device was successfully set up') - fill_in "Pick a name", with: name - click_on 'Register device' - u2f_device - end +module Features + module TwoFactorHelpers + def copy_recovery_codes + click_on _('Copy codes') + click_on _('Proceed') + end - # Registers webauthn device via UI - def register_webauthn_device(webauthn_device = nil, name: 'My device') - webauthn_device ||= FakeWebauthnDevice.new(page, name) - webauthn_device.respond_to_webauthn_registration - click_on 'Set up new device' - expect(page).to have_content('Your device was successfully set up') - fill_in 'Pick a name', with: name - click_on 'Register device' - webauthn_device - end + def enable_two_factor_authentication + click_on _('Enable two-factor authentication') + expect(page).to have_content(_('Set up new device')) + wait_for_requests + end - # Adds webauthn device directly via database - def add_webauthn_device(app_id, user, fake_device = nil, name: 'My device') - fake_device ||= WebAuthn::FakeClient.new(app_id) + def manage_two_factor_authentication + click_on 'Manage two-factor authentication' + expect(page).to have_content("Set up new device") + wait_for_requests + end - options_for_create = WebAuthn::Credential.options_for_create( - user: { id: user.webauthn_xid, name: user.username }, - authenticator_selection: { user_verification: 'discouraged' }, - rp: { name: 'GitLab' } - ) - challenge = options_for_create.challenge + # Registers webauthn device via UI + # Remove after `webauthn_without_totp` feature flag is deleted. + def register_webauthn_device(webauthn_device = nil, name: 'My device') + webauthn_device ||= FakeWebauthnDevice.new(page, name) + webauthn_device.respond_to_webauthn_registration + click_on 'Set up new device' + expect(page).to have_content('Your device was successfully set up') + fill_in 'Pick a name', with: name + click_on 'Register device' + webauthn_device + end - device_response = fake_device.create(challenge: challenge).to_json # rubocop:disable Rails/SaveBang - device_registration_params = { device_response: device_response, - name: name } + def webauthn_device_registration(webauthn_device: nil, name: 'My device', password: 'fake') + webauthn_device ||= FakeWebauthnDevice.new(page, name) + webauthn_device.respond_to_webauthn_registration + click_on _('Set up new device') + webauthn_fill_form_and_submit(name: name, password: password) + webauthn_device + end - Webauthn::RegisterService.new( - user, device_registration_params, challenge).execute - FakeWebauthnDevice.new(page, name, fake_device) - end + def webauthn_fill_form_and_submit(name: 'My device', password: 'fake') + content = _('Your device was successfully set up! Give it a name and register it with the GitLab server.') + expect(page).to have_content(content) - def assert_fallback_ui(page) - expect(page).to have_button('Verify code') - expect(page).to have_css('#user_otp_attempt') - expect(page).not_to have_link('Sign in via 2FA code') - expect(page).not_to have_css("#js-authenticate-token-2fa") - end - end + within '[data-testid="create-webauthn"]' do + fill_in _('Device name'), with: name + fill_in _('Current password'), with: password + click_on _('Register device') end end + + # Adds webauthn device directly via database + def add_webauthn_device(app_id, user, fake_device = nil, name: 'My device') + fake_device ||= WebAuthn::FakeClient.new(app_id) + + options_for_create = WebAuthn::Credential.options_for_create( + user: { id: user.webauthn_xid, name: user.username }, + authenticator_selection: { user_verification: 'discouraged' }, + rp: { name: 'GitLab' } + ) + challenge = options_for_create.challenge + + device_response = fake_device.create(challenge: challenge).to_json # rubocop:disable Rails/SaveBang + device_registration_params = { device_response: device_response, + name: name } + + Webauthn::RegisterService.new( + user, device_registration_params, challenge).execute + FakeWebauthnDevice.new(page, name, fake_device) + end + + def assert_fallback_ui(page) + expect(page).to have_button('Verify code') + expect(page).to have_css('#user_otp_attempt') + expect(page).not_to have_link('Sign in via 2FA code') + expect(page).not_to have_css("#js-authenticate-token-2fa") + end end end diff --git a/spec/support/helpers/features/web_ide_spec_helpers.rb b/spec/support/helpers/features/web_ide_spec_helpers.rb index 4793c9479fe..c51116b55b2 100644 --- a/spec/support/helpers/features/web_ide_spec_helpers.rb +++ b/spec/support/helpers/features/web_ide_spec_helpers.rb @@ -4,119 +4,120 @@ # # Usage: # describe "..." do -# include WebIdeSpecHelpers +# include Features::WebIdeSpecHelpers # ... # # ide_visit(project) # ide_commit -# -module WebIdeSpecHelpers - include Spec::Support::Helpers::Features::SourceEditorSpecHelpers - - # Open the IDE from anywhere by first visiting the given project's page - def ide_visit(project) - visit project_path(project) - - ide_visit_from_link - end +module Features + module WebIdeSpecHelpers + include Features::SourceEditorSpecHelpers - # Open the IDE from the current page by clicking the Web IDE link - def ide_visit_from_link(link_sel = 'Web IDE') - new_tab = window_opened_by { click_link(link_sel) } + # Open the IDE from anywhere by first visiting the given project's page + def ide_visit(project) + visit project_path(project) - switch_to_window new_tab - end + ide_visit_from_link + end - def ide_tree_body - page.find('.ide-tree-body') - end + # Open the IDE from the current page by clicking the Web IDE link + def ide_visit_from_link(link_sel = 'Web IDE') + new_tab = window_opened_by { click_link(link_sel) } - def ide_tree_actions - page.find('.ide-tree-actions') - end + switch_to_window new_tab + end - def ide_tab_selector(mode) - ".js-ide-#{mode}-mode" - end + def ide_tree_body + page.find('.ide-tree-body') + end - def ide_folder_row_open?(row) - row.matches_css?('.folder.is-open') - end + def ide_tree_actions + page.find('.ide-tree-actions') + end - # Deletes a file by traversing to `path` - # then clicking the 'Delete' action. - # - # - Throws an error if the file is not found - def ide_delete_file(path) - container = ide_traverse_to_file(path) + def ide_tab_selector(mode) + ".js-ide-#{mode}-mode" + end - click_file_action(container, 'Delete') - end + def ide_folder_row_open?(row) + row.matches_css?('.folder.is-open') + end - # Opens parent directories until the file at `path` - # is exposed. - # - # - Returns a reference to the file row at `path` - # - Throws an error if the file is not found - def ide_traverse_to_file(path) - paths = path.split('/') - container = nil + # Deletes a file by traversing to `path` + # then clicking the 'Delete' action. + # + # - Throws an error if the file is not found + def ide_delete_file(path) + container = ide_traverse_to_file(path) - paths.each_with_index do |path, index| - ide_open_file_row(container) if container - container = find_file_child(container, path, level: index) + click_file_action(container, 'Delete') end - container - end + # Opens parent directories until the file at `path` + # is exposed. + # + # - Returns a reference to the file row at `path` + # - Throws an error if the file is not found + def ide_traverse_to_file(path) + paths = path.split('/') + container = nil + + paths.each_with_index do |path, index| + ide_open_file_row(container) if container + container = find_file_child(container, path, level: index) + end + + container + end - def ide_open_file_row(row) - return if ide_folder_row_open?(row) + def ide_open_file_row(row) + return if ide_folder_row_open?(row) - row.click - end + row.click + end - def ide_set_editor_value(value) - editor_set_value(value) - end + def ide_set_editor_value(value) + editor_set_value(value) + end - def ide_commit_tab_selector - ide_tab_selector('commit') - end + def ide_commit_tab_selector + ide_tab_selector('commit') + end - def ide_commit - find(ide_commit_tab_selector).click + def ide_commit + find(ide_commit_tab_selector).click - commit_to_current_branch - end + commit_to_current_branch + end - private + private - def file_row_container(row) - row ? row.find(:xpath, '..') : ide_tree_body - end + def file_row_container(row) + row ? row.find(:xpath, '..') : ide_tree_body + end - def find_file_child(row, name, level: nil) - container = file_row_container(row) - container.find(".file-row[data-level=\"#{level}\"]", text: name) - end + def find_file_child(row, name, level: nil) + container = file_row_container(row) + container.find(".file-row[data-level=\"#{level}\"]", text: name) + end - def click_file_action(row, text) - row.hover - dropdown = row.find('.ide-new-btn') - dropdown.find('button').click - dropdown.find('button', text: text).click - end + def click_file_action(row, text) + row.hover + dropdown = row.find('.ide-new-btn') + dropdown.find('button').click + dropdown.find('button', text: text).click + end - def commit_to_current_branch(option: 'Commit to master branch', message: '') - within '.multi-file-commit-form' do - fill_in('commit-message', with: message) if message + def commit_to_current_branch(option: 'Commit to master branch', message: '') + within '.multi-file-commit-form' do + fill_in('commit-message', with: message) if message - choose(option) + choose(option) - click_button('Commit') + click_button('Commit') - wait_for_requests + wait_for_requests + end end end end |