diff options
Diffstat (limited to 'spec/features/projects')
25 files changed, 396 insertions, 288 deletions
diff --git a/spec/features/projects/blobs/balsamiq_spec.rb b/spec/features/projects/blobs/balsamiq_spec.rb deleted file mode 100644 index bce60856544..00000000000 --- a/spec/features/projects/blobs/balsamiq_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Balsamiq file blob', :js do - let(:project) { create(:project, :public, :repository) } - - before do - visit project_blob_path(project, 'add-balsamiq-file/files/images/balsamiq.bmpr') - - wait_for_requests - end - - it 'displays Balsamiq file content' do - expect(page).to have_content("Mobile examples") - end -end diff --git a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb index 11e2d24c36a..9b0edcd09d2 100644 --- a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb +++ b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb @@ -39,7 +39,7 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do find('#L3').click find("#L5").click - expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: "LC5"))) + expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: "L5"))) end it 'with initial fragment hash, changes fragment hash if line number clicked' do @@ -50,7 +50,7 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do find('#L3').click find("#L5").click - expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: "LC5"))) + expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: "L5"))) end end @@ -75,7 +75,7 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do find('#L3').click find("#L5").click - expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: "LC5"))) + expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: "L5"))) end it 'with initial fragment hash, changes fragment hash if line number clicked' do @@ -86,7 +86,7 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do find('#L3').click find("#L5").click - expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: "LC5"))) + expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: "L5"))) end end end diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb index 363d08da024..d906bb396be 100644 --- a/spec/features/projects/branches_spec.rb +++ b/spec/features/projects/branches_spec.rb @@ -36,6 +36,8 @@ RSpec.describe 'Branches' do expect(page).to have_content(sorted_branches(repository, count: 5, sort_by: :updated_desc, state: 'active')) expect(page).to have_content(sorted_branches(repository, count: 4, sort_by: :updated_asc, state: 'stale')) + expect(page).to have_button('Copy branch name') + expect(page).to have_link('Show more active branches', href: project_branches_filtered_path(project, state: 'active')) expect(page).not_to have_content('Show more stale branches') end @@ -197,14 +199,6 @@ RSpec.describe 'Branches' do project.add_maintainer(user) end - describe 'Initial branches page' do - it 'shows description for admin' do - visit project_branches_filtered_path(project, state: 'all') - - expect(page).to have_content("Protected branches can be managed in project settings") - end - end - it 'shows the merge request button' do visit project_branches_path(project) diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb index e9162359940..5d931afe4a7 100644 --- a/spec/features/projects/cluster_agents_spec.rb +++ b/spec/features/projects/cluster_agents_spec.rb @@ -27,7 +27,6 @@ RSpec.describe 'ClusterAgents', :js do end it 'displays empty state', :aggregate_failures do - expect(page).to have_content('Install a new agent') expect(page).to have_selector('.empty-state') end end diff --git a/spec/features/projects/clusters/eks_spec.rb b/spec/features/projects/clusters/eks_spec.rb index 0dd6effe551..7e599ff1198 100644 --- a/spec/features/projects/clusters/eks_spec.rb +++ b/spec/features/projects/clusters/eks_spec.rb @@ -20,7 +20,7 @@ RSpec.describe 'AWS EKS Cluster', :js do visit project_clusters_path(project) click_button(class: 'dropdown-toggle-split') - click_link 'Create a new cluster' + click_link 'Create a cluster (certificate - deprecated)' end context 'when user creates a cluster on AWS EKS' do diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index 90d7e2d02e9..491121a3743 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -135,7 +135,7 @@ RSpec.describe 'Gcp Cluster', :js do visit project_clusters_path(project) click_button(class: 'dropdown-toggle-split') - click_link 'Connect with a certificate' + click_link 'Connect a cluster (certificate - deprecated)' end it 'user sees the "Environment scope" field' do @@ -154,7 +154,6 @@ RSpec.describe 'Gcp Cluster', :js do it 'user sees creation form with the successful message' do expect(page).to have_content('Kubernetes cluster integration was successfully removed.') - expect(page).to have_link('Connect with a certificate') end end end @@ -220,6 +219,6 @@ RSpec.describe 'Gcp Cluster', :js do def visit_create_cluster_page click_button(class: 'dropdown-toggle-split') - click_link 'Create a new cluster' + click_link 'Create a cluster (certificate - deprecated)' end end diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index 3fd78d338da..b6bfaa3a9b9 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -25,8 +25,8 @@ RSpec.describe 'User Cluster', :js do before do visit project_clusters_path(project) - click_link 'Certificate' - click_link 'Connect with a certificate' + click_button(class: 'dropdown-toggle-split') + click_link 'Connect a cluster (certificate - deprecated)' end context 'when user filled form with valid parameters' do @@ -108,7 +108,6 @@ RSpec.describe 'User Cluster', :js do it 'user sees creation form with the successful message' do expect(page).to have_content('Kubernetes cluster integration was successfully removed.') - expect(page).to have_link('Connect with a certificate') end end end diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb index b9a544144c3..0ecd7795964 100644 --- a/spec/features/projects/clusters_spec.rb +++ b/spec/features/projects/clusters_spec.rb @@ -20,7 +20,6 @@ RSpec.describe 'Clusters', :js do end it 'sees empty state' do - expect(page).to have_link('Connect with a certificate') expect(page).to have_selector('.empty-state') end end @@ -222,11 +221,11 @@ RSpec.describe 'Clusters', :js do visit project_clusters_path(project) click_button(class: 'dropdown-toggle-split') - click_link 'Create a new cluster' + click_link 'Create a cluster (certificate - deprecated)' end def visit_connect_cluster_page click_button(class: 'dropdown-toggle-split') - click_link 'Connect with a certificate' + click_link 'Connect a cluster (certificate - deprecated)' end end diff --git a/spec/features/projects/commits/multi_view_diff_spec.rb b/spec/features/projects/commits/multi_view_diff_spec.rb index ecdd398c739..009dd05c6d1 100644 --- a/spec/features/projects/commits/multi_view_diff_spec.rb +++ b/spec/features/projects/commits/multi_view_diff_spec.rb @@ -27,17 +27,11 @@ RSpec.describe 'Multiple view Diffs', :js do context 'when :rendered_diffs_viewer is off' do context 'and diff does not have ipynb' do - include_examples "no multiple viewers", 'ddd0f15ae83993f5cb66a927a28673882e99100b' + it_behaves_like "no multiple viewers", 'ddd0f15ae83993f5cb66a927a28673882e99100b' end context 'and diff has ipynb' do - include_examples "no multiple viewers", '5d6ed1503801ca9dc28e95eeb85a7cf863527aee' - - it 'shows the transformed diff' do - diff = page.find('.diff-file, .file-holder', match: :first) - - expect(diff['innerHTML']).to include('%% Cell type:markdown id:0aac5da7-745c-4eda-847a-3d0d07a1bb9b tags:') - end + it_behaves_like "no multiple viewers", '5d6ed1503801ca9dc28e95eeb85a7cf863527aee' end end @@ -45,14 +39,28 @@ RSpec.describe 'Multiple view Diffs', :js do let(:feature_flag_on) { true } context 'and diff does not include ipynb' do - include_examples "no multiple viewers", 'ddd0f15ae83993f5cb66a927a28673882e99100b' - end + it_behaves_like "no multiple viewers", 'ddd0f15ae83993f5cb66a927a28673882e99100b' - context 'and opening a diff with ipynb' do - context 'but the changes are not renderable' do - include_examples "no multiple viewers", 'a867a602d2220e5891b310c07d174fbe12122830' + context 'and in inline diff' do + let(:ref) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' } + + it 'does not change display for non-ipynb' do + expect(page).to have_selector line_with_content('new', 1) + end end + context 'and in parallel diff' do + let(:ref) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' } + + it 'does not change display for non-ipynb' do + page.find('#parallel-diff-btn').click + + expect(page).to have_selector line_with_content('new', 1) + end + end + end + + context 'and opening a diff with ipynb' do it 'loads the rendered diff as hidden' do diff = page.find('.diff-file, .file-holder', match: :first) @@ -76,10 +84,55 @@ RSpec.describe 'Multiple view Diffs', :js do expect(classes_for_element(diff, 'toHideBtn')).not_to include('selected') expect(classes_for_element(diff, 'toShowBtn')).to include('selected') end + + it 'transforms the diff' do + diff = page.find('.diff-file, .file-holder', match: :first) + + expect(diff['innerHTML']).to include('%% Cell type:markdown id:0aac5da7-745c-4eda-847a-3d0d07a1bb9b tags:') + end + + context 'on parallel view' do + before do + page.find('#parallel-diff-btn').click + end + + it 'lines without mapping cannot receive comments' do + expect(page).not_to have_selector('td.line_content.nomappinginraw ~ td.diff-line-num > .add-diff-note') + expect(page).to have_selector('td.line_content:not(.nomappinginraw) ~ td.diff-line-num > .add-diff-note') + end + + it 'lines numbers without mapping are empty' do + expect(page).not_to have_selector('td.nomappinginraw + td.diff-line-num') + expect(page).to have_selector('td.nomappinginraw + td.diff-line-num', visible: false) + end + + it 'transforms the diff' do + diff = page.find('.diff-file, .file-holder', match: :first) + + expect(diff['innerHTML']).to include('%% Cell type:markdown id:0aac5da7-745c-4eda-847a-3d0d07a1bb9b tags:') + end + end + + context 'on inline view' do + it 'lines without mapping cannot receive comments' do + expect(page).not_to have_selector('tr.line_holder[class$="nomappinginraw"] > td.diff-line-num > .add-diff-note') + expect(page).to have_selector('tr.line_holder:not([class$="nomappinginraw"]) > td.diff-line-num > .add-diff-note') + end + + it 'lines numbers without mapping are empty' do + elements = page.all('tr.line_holder[class$="nomappinginraw"] > td.diff-line-num').map { |e| e.text(:all) } + + expect(elements).to all(be == "") + end + end end end def classes_for_element(node, data_diff_entity, visible: true) node.find("[data-diff-toggle-entity=\"#{data_diff_entity}\"]", visible: visible)[:class] end + + def line_with_content(old_or_new, line_number) + "td.#{old_or_new}_line.diff-line-num[data-linenumber=\"#{line_number}\"] > a[data-linenumber=\"#{line_number}\"]" + end end diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index 99137018d6b..6cf59394af7 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -70,7 +70,7 @@ RSpec.describe 'Environments page', :js do it 'shows no environments' do visit_environments(project, scope: 'stopped') - expect(page).to have_content('You don\'t have any environments right now') + expect(page).to have_content(s_('Environments|You don\'t have any stopped environments.')) end end @@ -99,7 +99,7 @@ RSpec.describe 'Environments page', :js do it 'shows no environments' do visit_environments(project, scope: 'available') - expect(page).to have_content('You don\'t have any environments right now') + expect(page).to have_content(s_('Environments|You don\'t have any environments.')) end end @@ -120,7 +120,7 @@ RSpec.describe 'Environments page', :js do end it 'does not show environments and counters are set to zero' do - expect(page).to have_content('You don\'t have any environments right now') + expect(page).to have_content(s_('Environments|You don\'t have any environments.')) expect(page).to have_link("#{_('Available')} 0") expect(page).to have_link("#{_('Stopped')} 0") diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 1e5c5d33ad9..c7fbaa85483 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -24,9 +24,9 @@ RSpec.describe 'Import/Export - project import integration test', :js do context 'when selecting the namespace' do let(:user) { create(:admin) } let!(:namespace) { user.namespace } - let(:randomHex) { SecureRandom.hex } - let(:project_name) { 'Test Project Name' + randomHex } - let(:project_path) { 'test-project-name' + randomHex } + let(:random_hex) { SecureRandom.hex } + let(:project_name) { 'Test Project Name' + random_hex } + let(:project_path) { 'test-project-name' + random_hex } it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do visit new_project_path diff --git a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb index 762f9c33510..48ae70d3ec9 100644 --- a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb +++ b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb @@ -10,8 +10,8 @@ RSpec.describe 'User uploads new design', :js do let(:issue) { create(:issue, project: project) } before do - # Cause of raising query limiting threshold https://gitlab.com/gitlab-org/gitlab/-/issues/347334 - stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 102) + # Cause of raising query limiting threshold https://gitlab.com/gitlab-org/gitlab/-/issues/358845 + stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 106) sign_in(user) enable_design_management(feature_enabled) diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb index fde6240d373..3b70d177fce 100644 --- a/spec/features/projects/jobs/user_browses_jobs_spec.rb +++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb @@ -67,19 +67,8 @@ RSpec.describe 'User browses jobs' do expect(page.find('[data-testid="jobs-all-tab"] .badge').text).to include('0') end - it 'shows a tab for Pending jobs and count' do - expect(page.find('[data-testid="jobs-pending-tab"]').text).to include('Pending') - expect(page.find('[data-testid="jobs-pending-tab"] .badge').text).to include('0') - end - - it 'shows a tab for Running jobs and count' do - expect(page.find('[data-testid="jobs-running-tab"]').text).to include('Running') - expect(page.find('[data-testid="jobs-running-tab"] .badge').text).to include('0') - end - it 'shows a tab for Finished jobs and count' do expect(page.find('[data-testid="jobs-finished-tab"]').text).to include('Finished') - expect(page.find('[data-testid="jobs-finished-tab"] .badge').text).to include('0') end it 'updates the content when tab is clicked' do diff --git a/spec/features/projects/members/groups_with_access_list_spec.rb b/spec/features/projects/members/groups_with_access_list_spec.rb index 6adc3503492..9bd6476f836 100644 --- a/spec/features/projects/members/groups_with_access_list_spec.rb +++ b/spec/features/projects/members/groups_with_access_list_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe 'Projects > Members > Groups with access list', :js do include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::ModalHelpers + include Spec::Support::Helpers::Features::InviteMembersModalHelper let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group, :public) } @@ -95,8 +96,4 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do expect(members_table).to have_content(group.full_name) end end - - def click_groups_tab - click_link 'Groups' - end end diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb index 9c256504934..a48229249e0 100644 --- a/spec/features/projects/members/invite_group_spec.rb +++ b/spec/features/projects/members/invite_group_spec.rb @@ -17,20 +17,18 @@ RSpec.describe 'Project > Members > Invite group', :js do visit project_project_members_path(project) - expect(page).to have_selector('button[data-test-id="invite-group-button"]') + expect(page).to have_selector(invite_group_selector) end - it 'does not display the button when visiting the page not signed in' do + it 'does not display the button when visiting the page not signed in' do project = create(:project, namespace: create(:group)) visit project_project_members_path(project) - expect(page).not_to have_selector('button[data-test-id="invite-group-button"]') + expect(page).not_to have_selector(invite_group_selector) end describe 'Share with group lock' do - let(:invite_group_selector) { 'button[data-test-id="invite-group-button"]' } - shared_examples 'the project can be shared with groups' do it 'the "Invite a group" button exists' do visit project_project_members_path(project) @@ -158,21 +156,95 @@ RSpec.describe 'Project > Members > Invite group', :js do describe 'the groups dropdown' do let_it_be(:parent_group) { create(:group, :public) } let_it_be(:project_group) { create(:group, :public, parent: parent_group) } - let_it_be(:public_sub_subgroup) { create(:group, :public, parent: project_group) } - let_it_be(:public_sibbling_group) { create(:group, :public, parent: parent_group) } - let_it_be(:private_sibbling_group) { create(:group, :private, parent: parent_group) } - let_it_be(:private_membership_group) { create(:group, :private) } - let_it_be(:public_membership_group) { create(:group, :public) } let_it_be(:project) { create(:project, group: project_group) } - before do - private_membership_group.add_guest(maintainer) - public_membership_group.add_maintainer(maintainer) + context 'with instance admin considerations' do + let_it_be(:group_to_share) { create(:group) } - sign_in(maintainer) + context 'when user is an admin' do + let_it_be(:admin) { create(:admin) } + + before do + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) + end + + it 'shows groups where the admin has no direct membership' do + visit project_project_members_path(project) + + click_on 'Invite a group' + click_on 'Select a group' + wait_for_requests + + page.within(group_dropdown_selector) do + expect_to_have_group(group_to_share) + end + end + + it 'shows groups where the admin has at least guest level membership' do + group_to_share.add_guest(admin) + + visit project_project_members_path(project) + + click_on 'Invite a group' + click_on 'Select a group' + wait_for_requests + + page.within(group_dropdown_selector) do + expect_to_have_group(group_to_share) + end + end + end + + context 'when user is not an admin' do + before do + project.add_maintainer(maintainer) + sign_in(maintainer) + end + + it 'does not show groups where the user has no direct membership' do + visit project_project_members_path(project) + + click_on 'Invite a group' + click_on 'Select a group' + wait_for_requests + + page.within(group_dropdown_selector) do + expect_not_to_have_group(group_to_share) + end + end + + it 'shows groups where the user has at least guest level membership' do + group_to_share.add_guest(maintainer) + + visit project_project_members_path(project) + + click_on 'Invite a group' + click_on 'Select a group' + wait_for_requests + + page.within(group_dropdown_selector) do + expect_to_have_group(group_to_share) + end + end + end end context 'for a project in a nested group' do + let_it_be(:public_sub_subgroup) { create(:group, :public, parent: project_group) } + let_it_be(:public_sibbling_group) { create(:group, :public, parent: parent_group) } + let_it_be(:private_sibbling_group) { create(:group, :private, parent: parent_group) } + let_it_be(:private_membership_group) { create(:group, :private) } + let_it_be(:public_membership_group) { create(:group, :public) } + let_it_be(:project) { create(:project, group: project_group) } + + before do + private_membership_group.add_guest(maintainer) + public_membership_group.add_maintainer(maintainer) + + sign_in(maintainer) + end + it 'does not show the groups inherited from projects' do project.add_maintainer(maintainer) public_sibbling_group.add_maintainer(maintainer) @@ -183,7 +255,7 @@ RSpec.describe 'Project > Members > Invite group', :js do click_on 'Select a group' wait_for_requests - page.within('[data-testid="group-select-dropdown"]') do + page.within(group_dropdown_selector) do expect_to_have_group(public_membership_group) expect_to_have_group(public_sibbling_group) expect_to_have_group(private_membership_group) @@ -204,7 +276,7 @@ RSpec.describe 'Project > Members > Invite group', :js do click_on 'Select a group' wait_for_requests - page.within('[data-testid="group-select-dropdown"]') do + page.within(group_dropdown_selector) do expect_to_have_group(public_membership_group) expect_to_have_group(public_sibbling_group) expect_to_have_group(private_membership_group) @@ -215,14 +287,10 @@ RSpec.describe 'Project > Members > Invite group', :js do expect_not_to_have_group(project_group) end 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 + + def invite_group_selector + 'button[data-test-id="invite-group-button"]' + end end diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/manage_members_spec.rb index f2424a4acc3..0f4120e88e0 100644 --- a/spec/features/projects/members/list_spec.rb +++ b/spec/features/projects/members/manage_members_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Project members list', :js do +RSpec.describe 'Projects > Members > Manage members', :js do include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::Features::InviteMembersModalHelper include Spec::Support::Helpers::ModalHelpers @@ -48,24 +48,6 @@ RSpec.describe 'Project members list', :js do end end - it 'add user to project', :snowplow, :aggregate_failures do - visit_members_page - - invite_member(user2.name, role: 'Reporter') - - page.within find_member_row(user2) do - expect(page).to have_button('Reporter') - end - - expect_snowplow_event( - category: 'Members::CreateService', - action: 'create_member', - label: 'project-members-page', - property: 'existing_user', - user: user1 - ) - end - it 'uses ProjectMember access_level_roles for the invite members modal access option', :aggregate_failures do visit_members_page @@ -104,24 +86,41 @@ RSpec.describe 'Project members list', :js do expect(members_table).not_to have_content(other_user.name) end - it 'invite user to project', :snowplow, :aggregate_failures do - visit_members_page + it_behaves_like 'inviting members', 'project-members-page' do + let_it_be(:entity) { project } + let_it_be(:members_page_path) { project_project_members_path(entity) } + let_it_be(:subentity) { project } + let_it_be(:subentity_members_page_path) { project_project_members_path(entity) } + end - invite_member('test@example.com', role: 'Reporter') + describe 'member search results' do + it 'does not show project_bots', :aggregate_failures do + internal_project_bot = create(:user, :project_bot, name: '_internal_project_bot_') + project.add_maintainer(internal_project_bot) - click_link 'Invited' + external_group = create(:group) + external_project_bot = create(:user, :project_bot, name: '_external_project_bot_') + external_project = create(:project, group: external_group) + external_project.add_maintainer(external_project_bot) + external_project.add_maintainer(user1) - page.within find_invited_member_row('test@example.com') do - expect(page).to have_button('Reporter') - end + visit_members_page + + click_on 'Invite members' - expect_snowplow_event( - category: 'Members::InviteService', - action: 'create_member', - label: 'project-members-page', - property: 'net_new_user', - user: user1 - ) + page.within invite_modal_selector do + field = find(member_dropdown_selector) + field.native.send_keys :tab + field.click + + wait_for_requests + + expect(page).to have_content(user1.name) + expect(page).to have_content(user2.name) + expect(page).not_to have_content(internal_project_bot.name) + expect(page).not_to have_content(external_project_bot.name) + end + end end context 'as a signed out visitor viewing a public project' do diff --git a/spec/features/projects/members/sorting_spec.rb b/spec/features/projects/members/sorting_spec.rb index 653564d1566..8aadd6302d0 100644 --- a/spec/features/projects/members/sorting_spec.rb +++ b/spec/features/projects/members/sorting_spec.rb @@ -5,8 +5,8 @@ require 'spec_helper' RSpec.describe 'Projects > Members > Sorting', :js do include Spec::Support::Helpers::Features::MembersHelpers - let(:maintainer) { create(:user, name: 'John Doe') } - let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) } + let(:maintainer) { create(:user, name: 'John Doe', created_at: 5.days.ago, last_activity_on: Date.today) } + let(:developer) { create(:user, name: 'Mary Jane', created_at: 1.day.ago, last_sign_in_at: 5.days.ago, last_activity_on: Date.today - 5) } let(:project) { create(:project, namespace: maintainer.namespace, creator: maintainer) } before do @@ -42,6 +42,42 @@ RSpec.describe 'Projects > Members > Sorting', :js do expect_sort_by('Max role', :desc) end + it 'sorts by user created on ascending' do + visit_members_list(sort: :oldest_created_user) + + expect(first_row.text).to have_content(maintainer.name) + expect(second_row.text).to have_content(developer.name) + + expect_sort_by('Created on', :asc) + end + + it 'sorts by user created on descending' do + visit_members_list(sort: :recent_created_user) + + expect(first_row.text).to have_content(developer.name) + expect(second_row.text).to have_content(maintainer.name) + + expect_sort_by('Created on', :desc) + end + + it 'sorts by last activity ascending' do + visit_members_list(sort: :oldest_last_activity) + + expect(first_row.text).to have_content(developer.name) + expect(second_row.text).to have_content(maintainer.name) + + expect_sort_by('Last activity', :asc) + end + + it 'sorts by last activity descending' do + visit_members_list(sort: :recent_last_activity) + + expect(first_row.text).to have_content(maintainer.name) + expect(second_row.text).to have_content(developer.name) + + expect_sort_by('Last activity', :desc) + end + it 'sorts by access granted ascending' do visit_members_list(sort: :last_joined) diff --git a/spec/features/projects/milestones/milestones_sorting_spec.rb b/spec/features/projects/milestones/milestones_sorting_spec.rb index 565c61cfaa0..2ad820e4a06 100644 --- a/spec/features/projects/milestones/milestones_sorting_spec.rb +++ b/spec/features/projects/milestones/milestones_sorting_spec.rb @@ -5,49 +5,55 @@ require 'spec_helper' RSpec.describe 'Milestones sorting', :js do let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } + let(:milestones_for_sort_by) do + { + 'Due later' => %w[b c a], + 'Name, ascending' => %w[a b c], + 'Name, descending' => %w[c b a], + 'Start later' => %w[a c b], + 'Start soon' => %w[b c a], + 'Due soon' => %w[a c b] + } + end + + let(:ordered_milestones) do + ['Due soon', 'Due later', 'Start soon', 'Start later', 'Name, ascending', 'Name, descending'] + end before do - # Milestones - create(:milestone, - due_date: 10.days.from_now, - created_at: 2.hours.ago, - title: "aaa", project: project) - create(:milestone, - due_date: 11.days.from_now, - created_at: 1.hour.ago, - title: "bbb", project: project) + create(:milestone, start_date: 7.days.from_now, due_date: 10.days.from_now, title: "a", project: project) + create(:milestone, start_date: 6.days.from_now, due_date: 11.days.from_now, title: "c", project: project) + create(:milestone, start_date: 5.days.from_now, due_date: 12.days.from_now, title: "b", project: project) sign_in(user) end - it 'visit project milestones and sort by due_date_asc' do + it 'visit project milestones and sort by various orders' do visit project_milestones_path(project) expect(page).to have_button('Due soon') - # assert default sorting + # assert default sorting order within '.milestones' do - expect(page.all('ul.content-list > li').first.text).to include('aaa') - expect(page.all('ul.content-list > li').last.text).to include('bbb') + expect(page.all('ul.content-list > li strong > a').map(&:text)).to eq(%w[a c b]) end - click_button 'Due soon' + # assert milestones listed for given sort order + selected_sort_order = 'Due soon' + milestones_for_sort_by.each do |sort_by, expected_milestones| + within '[data-testid=milestone_sort_by_dropdown]' do + click_button selected_sort_order + milestones = find('.gl-new-dropdown-contents').all('.gl-new-dropdown-item-text-wrapper p').map(&:text) + expect(milestones).to eq(ordered_milestones) - sort_options = find('ul.dropdown-menu-sort li').all('a').collect(&:text) + click_button sort_by + expect(page).to have_button(sort_by) + end - expect(sort_options[0]).to eq('Due soon') - expect(sort_options[1]).to eq('Due later') - expect(sort_options[2]).to eq('Start soon') - expect(sort_options[3]).to eq('Start later') - expect(sort_options[4]).to eq('Name, ascending') - expect(sort_options[5]).to eq('Name, descending') + within '.milestones' do + expect(page.all('ul.content-list > li strong > a').map(&:text)).to eq(expected_milestones) + end - click_link 'Due later' - - expect(page).to have_button('Due later') - - within '.milestones' do - expect(page.all('ul.content-list > li').first.text).to include('bbb') - expect(page.all('ul.content-list > li').last.text).to include('aaa') + selected_sort_order = sort_by end end end diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index c57e39b6508..0046dfe436f 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -191,7 +191,8 @@ RSpec.describe 'New project', :js do click_link 'Create blank project' end - it 'selects the user namespace' do + it 'does not select the user namespace' do + click_on 'Pick a group or namespace' expect(page).to have_button user.username end end @@ -328,6 +329,14 @@ RSpec.describe 'New project', :js do click_on 'Create project' + expect(page).to have_content( + s_('ProjectsNew|Pick a group or namespace where you want to create this project.') + ) + + click_on 'Pick a group or namespace' + click_on user.username + click_on 'Create project' + expect(page).to have_css('#import-project-pane.active') expect(page).not_to have_css('.toggle-import-form.hide') end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 6b9dfdf3a7b..219c8ec0070 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -15,6 +15,7 @@ RSpec.describe 'Pipeline', :js do before do sign_in(user) project.add_role(user, role) + stub_feature_flags(pipeline_tabs_vue: false) end shared_context 'pipeline builds' do @@ -356,6 +357,7 @@ RSpec.describe 'Pipeline', :js do context 'page tabs' do before do + stub_feature_flags(pipeline_tabs_vue: false) visit_pipeline end @@ -388,6 +390,7 @@ RSpec.describe 'Pipeline', :js do let(:pipeline) { create(:ci_pipeline, :with_test_reports, :with_report_results, project: project) } before do + stub_feature_flags(pipeline_tabs_vue: false) visit_pipeline wait_for_requests end @@ -924,6 +927,7 @@ RSpec.describe 'Pipeline', :js do let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) } before do + stub_feature_flags(pipeline_tabs_vue: false) visit builds_project_pipeline_path(project, pipeline) end @@ -944,6 +948,10 @@ RSpec.describe 'Pipeline', :js do end context 'page tabs' do + before do + stub_feature_flags(pipeline_tabs_vue: false) + end + it 'shows Pipeline, Jobs and DAG tabs with link' do expect(page).to have_link('Pipeline') expect(page).to have_link('Jobs') @@ -1014,6 +1022,10 @@ RSpec.describe 'Pipeline', :js do end describe 'GET /:project/-/pipelines/:id/failures' do + before do + stub_feature_flags(pipeline_tabs_vue: false) + end + let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: '1234') } let(:pipeline_failures_page) { failures_project_pipeline_path(project, pipeline) } let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline) } @@ -1139,6 +1151,7 @@ RSpec.describe 'Pipeline', :js do let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) } before do + stub_feature_flags(pipeline_tabs_vue: false) visit dag_project_pipeline_path(project, pipeline) end diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 0e1728858ec..8b1a22ae05a 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -623,6 +623,7 @@ RSpec.describe 'Pipelines', :js do create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3, ref: 'master') + stub_feature_flags(pipeline_tabs_vue: false) visit project_pipeline_path(project, pipeline) wait_for_requests end diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb index 98935fdf872..a7348b62fc0 100644 --- a/spec/features/projects/releases/user_views_releases_spec.rb +++ b/spec/features/projects/releases/user_views_releases_spec.rb @@ -24,129 +24,111 @@ RSpec.describe 'User views releases', :js do stub_default_url_options(host: 'localhost') end - shared_examples 'releases index page' do - context('when the user is a maintainer') do - before do - sign_in(maintainer) + context('when the user is a maintainer') do + before do + sign_in(maintainer) - visit project_releases_path(project) + visit project_releases_path(project) - wait_for_requests - end + wait_for_requests + end - it 'sees the release' do - page.within("##{release_v1.tag}") do - expect(page).to have_content(release_v1.name) - expect(page).to have_content(release_v1.tag) - expect(page).not_to have_content('Upcoming Release') - end + it 'sees the release' do + page.within("##{release_v1.tag}") do + expect(page).to have_content(release_v1.name) + expect(page).to have_content(release_v1.tag) + expect(page).not_to have_content('Upcoming Release') end + end - it 'renders the correct links', :aggregate_failures do - page.within("##{release_v1.tag} .js-assets-list") do - external_link_indicator_selector = '[data-testid="external-link-indicator"]' + it 'renders the correct links', :aggregate_failures do + page.within("##{release_v1.tag} .js-assets-list") do + external_link_indicator_selector = '[data-testid="external-link-indicator"]' - expect(page).to have_link internal_link.name, href: internal_link.url - expect(find_link(internal_link.name)).not_to have_css(external_link_indicator_selector) + expect(page).to have_link internal_link.name, href: internal_link.url + expect(find_link(internal_link.name)).not_to have_css(external_link_indicator_selector) - expect(page).to have_link internal_link_with_redirect.name, href: Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{internal_link_with_redirect.filepath}" - expect(find_link(internal_link_with_redirect.name)).not_to have_css(external_link_indicator_selector) + expect(page).to have_link internal_link_with_redirect.name, href: Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{internal_link_with_redirect.filepath}" + expect(find_link(internal_link_with_redirect.name)).not_to have_css(external_link_indicator_selector) - expect(page).to have_link external_link.name, href: external_link.url - expect(find_link(external_link.name)).to have_css(external_link_indicator_selector) - end + expect(page).to have_link external_link.name, href: external_link.url + expect(find_link(external_link.name)).to have_css(external_link_indicator_selector) end + end - context 'with an upcoming release' do - it 'sees the upcoming tag' do - page.within("##{release_v3.tag}") do - expect(page).to have_content('Upcoming Release') - end + context 'with an upcoming release' do + it 'sees the upcoming tag' do + page.within("##{release_v3.tag}") do + expect(page).to have_content('Upcoming Release') end end + end - context 'with a tag containing a slash' do - it 'sees the release' do - page.within("##{release_v2.tag.parameterize}") do - expect(page).to have_content(release_v2.name) - expect(page).to have_content(release_v2.tag) - end + context 'with a tag containing a slash' do + it 'sees the release' do + page.within("##{release_v2.tag.parameterize}") do + expect(page).to have_content(release_v2.name) + expect(page).to have_content(release_v2.tag) end end + end - context 'sorting' do - def sort_page(by:, direction:) - within '[data-testid="releases-sort"]' do - find('.dropdown-toggle').click - - click_button(by, class: 'dropdown-item') - - find('.sorting-direction-button').click if direction == :ascending - end - end - - shared_examples 'releases sort order' do - it "sorts the releases #{description}" do - card_titles = page.all('.release-block .card-title', minimum: expected_releases.count) - - card_titles.each_with_index do |title, index| - expect(title).to have_content(expected_releases[index].name) - end - end - end + context 'sorting' do + def sort_page(by:, direction:) + within '[data-testid="releases-sort"]' do + find('.dropdown-toggle').click - context "when the page is sorted by the default sort order" do - let(:expected_releases) { [release_v3, release_v2, release_v1] } + click_button(by, class: 'dropdown-item') - it_behaves_like 'releases sort order' + find('.sorting-direction-button').click if direction == :ascending end + end - context "when the page is sorted by created_at ascending " do - let(:expected_releases) { [release_v2, release_v1, release_v3] } + shared_examples 'releases sort order' do + it "sorts the releases #{description}" do + card_titles = page.all('.release-block .card-title', minimum: expected_releases.count) - before do - sort_page by: 'Created date', direction: :ascending + card_titles.each_with_index do |title, index| + expect(title).to have_content(expected_releases[index].name) end - - it_behaves_like 'releases sort order' end end - end - context('when the user is a guest') do - before do - sign_in(guest) - end + context "when the page is sorted by the default sort order" do + let(:expected_releases) { [release_v3, release_v2, release_v1] } - it 'renders release info except for Git-related data' do - visit project_releases_path(project) + it_behaves_like 'releases sort order' + end - within('.release-block', match: :first) do - expect(page).to have_content(release_v3.description) - expect(page).to have_content(release_v3.tag) - expect(page).to have_content(release_v3.name) + context "when the page is sorted by created_at ascending " do + let(:expected_releases) { [release_v2, release_v1, release_v3] } - # The following properties (sometimes) include Git info, - # so they are not rendered for Guest users - expect(page).not_to have_content(release_v3.commit.short_id) + before do + sort_page by: 'Created date', direction: :ascending end + + it_behaves_like 'releases sort order' end end end - context 'when the releases_index_apollo_client feature flag is enabled' do + context('when the user is a guest') do before do - stub_feature_flags(releases_index_apollo_client: true) + sign_in(guest) end - it_behaves_like 'releases index page' - end + it 'renders release info except for Git-related data' do + visit project_releases_path(project) - context 'when the releases_index_apollo_client feature flag is disabled' do - before do - stub_feature_flags(releases_index_apollo_client: false) - end + within('.release-block', match: :first) do + expect(page).to have_content(release_v3.description) + expect(page).to have_content(release_v3.tag) + expect(page).to have_content(release_v3.name) - it_behaves_like 'releases index page' + # The following properties (sometimes) include Git info, + # so they are not rendered for Guest users + expect(page).not_to have_content(release_v3.commit.short_id) + end + end end end diff --git a/spec/features/projects/terraform_spec.rb b/spec/features/projects/terraform_spec.rb index 2c63f2bfc02..d9e45b5e78e 100644 --- a/spec/features/projects/terraform_spec.rb +++ b/spec/features/projects/terraform_spec.rb @@ -22,7 +22,7 @@ RSpec.describe 'Terraform', :js do end it 'sees an empty state' do - expect(page).to have_content('Get started with Terraform') + expect(page).to have_content("Your project doesn't have any Terraform state files") end end diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb index 6491a7425f7..b07f2d12660 100644 --- a/spec/features/projects/user_creates_project_spec.rb +++ b/spec/features/projects/user_creates_project_spec.rb @@ -33,29 +33,6 @@ RSpec.describe 'User creates a project', :js do end it 'creates a new project that is not blank' do - stub_experiments(new_project_sast_enabled: 'candidate') - - visit(new_project_path) - - click_link 'Create blank project' - fill_in(:project_name, with: 'With initial commits') - - expect(page).to have_checked_field 'Initialize repository with a README' - expect(page).to have_checked_field 'Enable Static Application Security Testing (SAST)' - - click_button('Create project') - - project = Project.last - - expect(page).to have_current_path(project_path(project), ignore_query: true) - expect(page).to have_content('With initial commits') - expect(page).to have_content('Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist') - expect(page).to have_content('README.md Initial commit') - end - - it 'allows creating a new project when the new_project_sast_enabled is assigned the unchecked candidate' do - stub_experiments(new_project_sast_enabled: 'unchecked_candidate') - visit(new_project_path) click_link 'Create blank project' @@ -93,7 +70,7 @@ RSpec.describe 'User creates a project', :js do fill_in :project_name, with: 'A Subgroup Project' fill_in :project_path, with: 'a-subgroup-project' - click_button user.username + click_on 'Pick a group or namespace' click_button subgroup.full_path click_button('Create project') @@ -120,9 +97,6 @@ RSpec.describe 'User creates a project', :js do fill_in :project_name, with: 'a-new-project' fill_in :project_path, with: 'a-new-project' - click_button user.username - click_button group.full_path - page.within('#content-body') do click_button('Create project') end diff --git a/spec/features/projects/user_sorts_projects_spec.rb b/spec/features/projects/user_sorts_projects_spec.rb index 71e43467a39..7c970f7ee3d 100644 --- a/spec/features/projects/user_sorts_projects_spec.rb +++ b/spec/features/projects/user_sorts_projects_spec.rb @@ -14,25 +14,29 @@ RSpec.describe 'User sorts projects and order persists' do it "is set on the dashboard_projects_path" do visit(dashboard_projects_path) - expect(find('.dropdown-menu a.is-active', text: project_paths_label)).to have_content(project_paths_label) + expect(find('#sort-projects-dropdown')).to have_content(project_paths_label) end it "is set on the explore_projects_path" do visit(explore_projects_path) - expect(find('.dropdown-menu a.is-active', text: project_paths_label)).to have_content(project_paths_label) + expect(find('#sort-projects-dropdown')).to have_content(project_paths_label) end it "is set on the group_canonical_path" do visit(group_canonical_path(group)) - expect(find('.dropdown-menu a.is-active', text: group_paths_label)).to have_content(group_paths_label) + within '[data-testid=group_sort_by_dropdown]' do + expect(find('.gl-dropdown-toggle')).to have_content(group_paths_label) + end end it "is set on the details_group_path" do visit(details_group_path(group)) - expect(find('.dropdown-menu a.is-active', text: group_paths_label)).to have_content(group_paths_label) + within '[data-testid=group_sort_by_dropdown]' do + expect(find('.gl-dropdown-toggle')).to have_content(group_paths_label) + end end end @@ -58,23 +62,27 @@ RSpec.describe 'User sorts projects and order persists' do it_behaves_like "sort order persists across all views", "Name", "Name" end - context 'from group homepage' do + context 'from group homepage', :js do before do sign_in(user) visit(group_canonical_path(group)) - find('button.dropdown-menu-toggle').click - first(:link, 'Last created').click + within '[data-testid=group_sort_by_dropdown]' do + find('button.gl-dropdown-toggle').click + first(:button, 'Last created').click + end end it_behaves_like "sort order persists across all views", "Created date", "Last created" end - context 'from group details' do + context 'from group details', :js do before do sign_in(user) visit(details_group_path(group)) - find('button.dropdown-menu-toggle').click - first(:link, 'Most stars').click + within '[data-testid=group_sort_by_dropdown]' do + find('button.gl-dropdown-toggle').click + first(:button, 'Most stars').click + end end it_behaves_like "sort order persists across all views", "Stars", "Most stars" |