diff options
Diffstat (limited to 'spec/features')
87 files changed, 1274 insertions, 1776 deletions
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 38f0b813183..e1df1c69351 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -130,6 +130,38 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n expect(user_internal_regex['placeholder']).to eq 'Regex pattern' end + context 'Change Sign-up restrictions' do + context 'Require Admin approval for new signup setting' do + context 'when feature is enabled' do + before do + stub_feature_flags(admin_approval_for_new_user_signups: true) + end + + it 'changes the setting' do + page.within('.as-signup') do + check 'Require admin approval for new sign-ups' + click_button 'Save changes' + end + + expect(current_settings.require_admin_approval_after_user_signup).to be_truthy + expect(page).to have_content "Application settings saved successfully" + end + end + + context 'when feature is disabled' do + before do + stub_feature_flags(admin_approval_for_new_user_signups: false) + end + + it 'does not show the the setting' do + page.within('.as-signup') do + expect(page).not_to have_selector('.application_setting_require_admin_approval_after_user_signup') + end + end + end + end + end + it 'Change Sign-in restrictions' do page.within('.as-signin') do fill_in 'Home page URL', with: 'https://about.gitlab.com/' diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index a37210d2acc..8b7750ab4ec 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -31,6 +31,7 @@ RSpec.describe "Admin::Users" do expect(page).to have_content(current_user.last_activity_on.strftime("%e %b, %Y")) expect(page).to have_content(user.email) expect(page).to have_content(user.name) + expect(page).to have_content('Projects') expect(page).to have_button('Block') expect(page).to have_button('Deactivate') expect(page).to have_button('Delete user') @@ -48,6 +49,19 @@ RSpec.describe "Admin::Users" do end end + context 'user project count' do + before do + project = create(:project) + project.add_maintainer(current_user) + end + + it 'displays count of users projects' do + visit admin_users_path + + expect(page.find("[data-testid='user-project-count-#{current_user.id}']").text).to eq("1") + end + end + describe 'search and sort' do before do create(:user, name: 'Foo Bar', last_activity_on: 3.days.ago) @@ -606,7 +620,7 @@ RSpec.describe "Admin::Users" do end end - describe 'show user keys' do + describe 'show user keys', :js do let!(:key1) do create(:key, user: user, title: "ssh-rsa Key1", key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4FIEBXGi4bPU8kzxMefudPIJ08/gNprdNTaO9BR/ndy3+58s2HCTw2xCHcsuBmq+TsAqgEidVq4skpqoTMB+Uot5Uzp9z4764rc48dZiI661izoREoKnuRQSsRqUTHg5wrLzwxlQbl1MVfRWQpqiz/5KjBC7yLEb9AbusjnWBk8wvC1bQPQ1uLAauEA7d836tgaIsym9BrLsMVnR4P1boWD3Xp1B1T/ImJwAGHvRmP/ycIqmKdSpMdJXwxcb40efWVj0Ibbe7ii9eeoLdHACqevUZi6fwfbymdow+FeqlkPoHyGg3Cu4vD/D8+8cRc7mE/zGCWcQ15Var83Tczour Key1") end @@ -629,7 +643,11 @@ RSpec.describe "Admin::Users" do expect(page).to have_content(key2.title) expect(page).to have_content(key2.key) - click_link 'Remove' + click_button 'Delete' + + page.within('.modal') do + page.click_button('Delete') + end expect(page).not_to have_content(key2.title) end diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index b8851c28531..44642983a36 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -46,7 +46,7 @@ RSpec.describe 'Admin uses repository checks', :request_store, :clean_gitlab_red ) visit_admin_project_page(project) - page.within('.alert') do + page.within('.gl-alert') do expect(page.text).to match(/Last repository check \(just now\) failed/) end end diff --git a/spec/features/admin/clusters/eks_spec.rb b/spec/features/admin/clusters/eks_spec.rb index ef49aebc7c5..ad7122bf182 100644 --- a/spec/features/admin/clusters/eks_spec.rb +++ b/spec/features/admin/clusters/eks_spec.rb @@ -13,7 +13,7 @@ RSpec.describe 'Instance-level AWS EKS Cluster', :js do before do visit admin_clusters_path - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' end context 'when user creates a cluster on AWS EKS' do diff --git a/spec/features/admin/dashboard_spec.rb b/spec/features/admin/dashboard_spec.rb index 4ffa5e3be0b..acb8fb54e11 100644 --- a/spec/features/admin/dashboard_spec.rb +++ b/spec/features/admin/dashboard_spec.rb @@ -28,11 +28,9 @@ RSpec.describe 'admin visits dashboard' do describe 'Users statistic' do let_it_be(:users_statistics) { create(:users_statistics) } + let_it_be(:users_count_label) { Gitlab.ee? ? 'Billable users 71' : 'Active users 71' } it 'shows correct amounts of users', :aggregate_failures do - expected_active_users_text = Gitlab.ee? ? 'Active users (Billable users) 71' : 'Active users 71' - - sign_in(create(:admin)) visit admin_dashboard_stats_path expect(page).to have_content('Users without a Group and Project 23') @@ -42,9 +40,9 @@ RSpec.describe 'admin visits dashboard' do expect(page).to have_content('Users with highest role Maintainer 6') expect(page).to have_content('Users with highest role Owner 5') expect(page).to have_content('Bots 2') - expect(page).to have_content(expected_active_users_text) expect(page).to have_content('Blocked users 7') expect(page).to have_content('Total users 78') + expect(page).to have_content(users_count_label) end end end diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb index d432825e113..d4a26ba0098 100644 --- a/spec/features/boards/add_issues_modal_spec.rb +++ b/spec/features/boards/add_issues_modal_spec.rb @@ -79,7 +79,7 @@ RSpec.describe 'Issue Boards add issue modal', :js do it 'loads issues' do page.within('.add-issues-modal') do - page.within('.nav-links') do + page.within('.gl-tabs') do expect(page).to have_content('2') end @@ -146,7 +146,7 @@ RSpec.describe 'Issue Boards add issue modal', :js do page.within('.add-issues-modal') do first('.board-card .board-card-number').click - page.within('.nav-links') do + page.within('.gl-tabs') do expect(page).to have_content('Selected issues 1') end end diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index e36378bd34e..eb8c1826dfd 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -24,33 +24,11 @@ RSpec.describe 'Issue Boards', :js do context 'no lists' do before do visit project_board_path(project, board) - wait_for_requests - expect(page).to have_selector('.board', count: 3) - end - - it 'shows blank state' do - expect(page).to have_content('Welcome to your Issue Board!') - end - - it 'shows tooltip on add issues button' do - button = page.find('.filter-dropdown-container button', text: 'Add issues') - - expect(button[:"data-original-title"]).to eq("Please add a list to your board first") - end - - it 'hides the blank state when clicking nevermind button' do - page.within(find('.board-blank-state')) do - click_button("Nevermind, I'll use my own") - end - expect(page).to have_selector('.board', count: 2) end it 'creates default lists' do lists = ['Open', 'To Do', 'Doing', 'Closed'] - page.within(find('.board-blank-state')) do - click_button('Add default lists') - end wait_for_requests expect(page).to have_selector('.board', count: 4) diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index 346f305f0d0..5f58fa420fb 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -180,7 +180,7 @@ RSpec.describe 'Contributions Calendar', :js do before do push_code_contribution - Timecop.freeze(Date.yesterday) do + travel_to(Date.yesterday) do Issues::CreateService.new(contributed_project, user, issue_params).execute end end diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb index 4f7f62d00a5..31d6bcda9e8 100644 --- a/spec/features/clusters/cluster_detail_page_spec.rb +++ b/spec/features/clusters/cluster_detail_page_spec.rb @@ -87,6 +87,7 @@ RSpec.describe 'Clusterable > Show page' do within('#advanced-settings-section') do expect(page).to have_content('Google Kubernetes Engine') expect(page).to have_content('Manage your Kubernetes cluster by visiting') + expect_common_advanced_options end end end @@ -117,6 +118,7 @@ RSpec.describe 'Clusterable > Show page' do within('#advanced-settings-section') do expect(page).not_to have_content('Google Kubernetes Engine') expect(page).not_to have_content('Manage your Kubernetes cluster by visiting') + expect_common_advanced_options end end end @@ -176,4 +178,14 @@ RSpec.describe 'Clusterable > Show page' do let(:cluster) { create(:cluster, :provided_by_user, :instance) } end end + + private + + def expect_common_advanced_options + aggregate_failures do + expect(page).to have_content('Cluster management project') + expect(page).to have_content('Clear cluster cache') + expect(page).to have_content('Remove Kubernetes cluster integration') + end + end end diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index e66a40720da..97ee891dbb8 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -140,6 +140,7 @@ RSpec.describe 'Commits' do context 'when accessing internal project with disallowed access', :js do before do + stub_feature_flags(graphql_pipeline_header: false) project.update( visibility_level: Gitlab::VisibilityLevel::INTERNAL, public_builds: false) diff --git a/spec/features/dashboard/todos/todos_filtering_spec.rb b/spec/features/dashboard/todos/todos_filtering_spec.rb index f60b07c976e..b1464af4194 100644 --- a/spec/features/dashboard/todos/todos_filtering_spec.rb +++ b/spec/features/dashboard/todos/todos_filtering_spec.rb @@ -130,6 +130,7 @@ RSpec.describe 'Dashboard > User filters todos', :js do before do create(:todo, :build_failed, user: user_1, author: user_2, project: project_1) create(:todo, :marked, user: user_1, author: user_2, project: project_1, target: issue1) + create(:todo, :review_requested, user: user_1, author: user_2, project: project_1, target: issue1) end it 'filters by Assigned' do @@ -138,6 +139,12 @@ RSpec.describe 'Dashboard > User filters todos', :js do expect_to_see_action(:assigned) end + it 'filters by Review Requested' do + filter_action('Review requested') + + expect_to_see_action(:review_requested) + end + it 'filters by Mentioned' do filter_action('Mentioned') @@ -168,6 +175,7 @@ RSpec.describe 'Dashboard > User filters todos', :js do def expect_to_see_action(action_name) action_names = { assigned: ' assigned you ', + review_requested: ' requested a review of ', mentioned: ' mentioned ', marked: ' added a todo for ', build_failed: ' build failed for ' diff --git a/spec/features/dashboard/todos/todos_spec.rb b/spec/features/dashboard/todos/todos_spec.rb index cf773d2caed..7243b5d3483 100644 --- a/spec/features/dashboard/todos/todos_spec.rb +++ b/spec/features/dashboard/todos/todos_spec.rb @@ -197,6 +197,21 @@ RSpec.describe 'Dashboard Todos' do end end end + + context 'review request todo' do + let(:merge_request) { create(:merge_request, title: "Fixes issue") } + + before do + create(:todo, :review_requested, user: user, project: project, target: merge_request, author: user) + visit dashboard_todos_path + end + + it 'shows you set yourself as an reviewer message' do + page.within('.js-todos-all') do + expect(page).to have_content("You requested a review of merge request #{merge_request.to_reference} \"Fixes issue\" at #{project.namespace.owner_name} / #{project.name} from yourself") + end + end + end end context 'User has done todos', :js do diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb index e705f2916da..49343cc7a57 100644 --- a/spec/features/expand_collapse_diffs_spec.rb +++ b/spec/features/expand_collapse_diffs_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'Expand and collapse diffs', :js do let(:project) { create(:project, :repository) } before do + stub_feature_flags(increased_diff_limits: false) sign_in(create(:admin)) # Ensure that undiffable.md is in .gitattributes diff --git a/spec/features/groups/clusters/eks_spec.rb b/spec/features/groups/clusters/eks_spec.rb index 5a62741250a..c361c502cbb 100644 --- a/spec/features/groups/clusters/eks_spec.rb +++ b/spec/features/groups/clusters/eks_spec.rb @@ -19,7 +19,7 @@ RSpec.describe 'Group AWS EKS Cluster', :js do before do visit group_clusters_path(group) - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' end context 'when user creates a cluster on AWS EKS' do diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb index 90253451d6b..97f8864aab2 100644 --- a/spec/features/groups/clusters/user_spec.rb +++ b/spec/features/groups/clusters/user_spec.rb @@ -25,7 +25,7 @@ RSpec.describe 'User Cluster', :js do before do visit group_clusters_path(group) - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' click_link 'Connect existing cluster' end @@ -66,6 +66,10 @@ RSpec.describe 'User Cluster', :js do expect(page.find_field('cluster[platform_kubernetes_attributes][authorization_type]', disabled: true)).to be_checked end end + + it 'user sees namespace per environment is enabled by default' do + expect(page).to have_checked_field('Namespace per environment') + end end context 'when user filled form with invalid parameters' do @@ -125,7 +129,7 @@ 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('Add Kubernetes cluster') + expect(page).to have_link('Integrate with a cluster certificate') end end end diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb index e3bbbd4d73b..8a7d997d5ac 100644 --- a/spec/features/groups/members/manage_groups_spec.rb +++ b/spec/features/groups/members/manage_groups_spec.rb @@ -6,62 +6,115 @@ RSpec.describe 'Groups > Members > Manage groups', :js do include Select2Helper include Spec::Support::Helpers::Features::ListRowsHelpers - let(:user) { create(:user) } - let(:shared_with_group) { create(:group) } - let(:shared_group) { create(:group) } + let_it_be(:user) { create(:user) } before do stub_feature_flags(vue_group_members_list: false) - shared_group.add_owner(user) sign_in(user) end - it 'add group to group' do - visit group_group_members_path(shared_group) + context 'when group link does not exist' do + let_it_be(:group) { create(:group) } + let_it_be(:group_to_add) { create(:group) } - add_group(shared_with_group.id, 'Reporter') + before do + group.add_owner(user) + visit group_group_members_path(group) + end - click_groups_tab + it 'add group to group' do + add_group(group_to_add.id, 'Reporter') - page.within(first_row) do - expect(page).to have_content(shared_with_group.name) - expect(page).to have_content('Reporter') + click_groups_tab + + page.within(first_row) do + expect(page).to have_content(group_to_add.name) + expect(page).to have_content('Reporter') + end end end - it 'remove group from group' do - create(:group_group_link, shared_group: shared_group, - shared_with_group: shared_with_group, group_access: ::Gitlab::Access::DEVELOPER) + context 'when group link exists' do + let_it_be(:shared_with_group) { create(:group) } + let_it_be(:shared_group) { create(:group) } - visit group_group_members_path(shared_group) + let(:additional_link_attrs) { {} } - click_groups_tab + let_it_be(:group_link, refind: true) do + create( + :group_group_link, + shared_group: shared_group, + shared_with_group: shared_with_group, + group_access: ::Gitlab::Access::DEVELOPER + ) + end - expect(page).to have_content(shared_with_group.name) + before do + travel_to Time.now.utc.beginning_of_day + group_link.update!(additional_link_attrs) - accept_confirm do - find(:css, '#tab-groups li', text: shared_with_group.name).find(:css, 'a.btn-remove').click + shared_group.add_owner(user) + visit group_group_members_path(shared_group) end - expect(page).not_to have_content(shared_with_group.name) - end + it 'remove group from group' do + click_groups_tab + + expect(page).to have_content(shared_with_group.name) + + accept_confirm do + find(:css, '#tab-groups li', text: shared_with_group.name).find(:css, 'a.btn-remove').click + end + + expect(page).not_to have_content(shared_with_group.name) + end - it 'update group to owner level' do - create(:group_group_link, shared_group: shared_group, - shared_with_group: shared_with_group, group_access: ::Gitlab::Access::DEVELOPER) + it 'update group to owner level' do + click_groups_tab - visit group_group_members_path(shared_group) + page.within(first_row) do + click_button('Developer') + click_link('Maintainer') - click_groups_tab + wait_for_requests - page.within(first_row) do - click_button('Developer') - click_link('Maintainer') + expect(page).to have_button('Maintainer') + end + end + + it 'updates expiry date' do + click_groups_tab + + expires_at_field = "member_expires_at_#{shared_with_group.id}" + fill_in "member_expires_at_#{shared_with_group.id}", with: 3.days.from_now.to_date + find_field(expires_at_field).native.send_keys :enter wait_for_requests - expect(page).to have_button('Maintainer') + page.within(find('li.group_member')) do + expect(page).to have_content('Expires in 3 days') + end + end + + context 'when expiry date is set' do + let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } } + + it 'clears expiry date' do + click_groups_tab + + page.within(find('li.group_member')) do + expect(page).to have_content('Expires in 3 days') + + page.within(find('.js-edit-member-form')) do + find('.js-clear-input').click + end + + wait_for_requests + + expect(page).not_to have_content('Expires in') + end + end end end diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb index 60f1c404e78..e81f2370d10 100644 --- a/spec/features/groups/navbar_spec.rb +++ b/spec/features/groups/navbar_spec.rb @@ -72,4 +72,12 @@ RSpec.describe 'Group navbar' do it_behaves_like 'verified navigation bar' end + + context 'when invite team members is not available' do + it 'does not display the js-invite-members-trigger' do + visit group_path(group) + + expect(page).not_to have_selector('.js-invite-members-trigger') + end + end end diff --git a/spec/features/groups/packages_spec.rb b/spec/features/groups/packages_spec.rb index d81e4aa70cf..60e0c08b3d4 100644 --- a/spec/features/groups/packages_spec.rb +++ b/spec/features/groups/packages_spec.rb @@ -48,7 +48,7 @@ RSpec.describe 'Group Packages' do it 'allows you to navigate to the project page' do page.within('[data-qa-selector="packages-table"]') do - click_link project.name + find('[data-qa-selector="package-path"]', text: project.name).click end expect(page).to have_current_path(project_path(project)) diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb index ec30f34199d..304573ecd6e 100644 --- a/spec/features/groups/show_spec.rb +++ b/spec/features/groups/show_spec.rb @@ -184,4 +184,17 @@ RSpec.describe 'Group show page' do expect(page).to have_selector('.notifications-btn.disabled', visible: true) end end + + context 'page og:description' do + let(:group) { create(:group, description: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') } + let(:maintainer) { create(:user) } + + before do + group.add_maintainer(maintainer) + sign_in(maintainer) + visit path + end + + it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet' + end end diff --git a/spec/features/incidents/incident_details_spec.rb b/spec/features/incidents/incident_details_spec.rb new file mode 100644 index 00000000000..6db767dbddb --- /dev/null +++ b/spec/features/incidents/incident_details_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Incident details', :js do + let_it_be(:project) { create(:project) } + let_it_be(:developer) { create(:user) } + let_it_be(:incident) { create(:incident, project: project, author: developer) } + + before_all do + project.add_developer(developer) + end + + before do + sign_in(developer) + + visit project_issues_incident_path(project, incident) + wait_for_requests + end + + context 'when a developer+ displays the incident' do + it 'shows the incident' do + page.within('.issuable-details') do + expect(find('h2')).to have_content(incident.title) + end + end + + it 'does not show design management' do + expect(page).not_to have_selector('.js-design-management') + end + end +end diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb index 3954de56eea..8a4c4cc1eca 100644 --- a/spec/features/invites_spec.rb +++ b/spec/features/invites_spec.rb @@ -81,10 +81,10 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do end end - context 'when inviting a user using their email address' do + context 'when inviting a user' do let(:new_user) { build_stubbed(:user) } let(:invite_email) { new_user.email } - let(:group_invite) { create(:group_member, :invited, group: group, invite_email: invite_email) } + let(:group_invite) { create(:group_member, :invited, group: group, invite_email: invite_email, created_by: owner) } let!(:project_invite) { create(:project_member, :invited, project: project, invite_email: invite_email) } context 'when user has not signed in yet' do @@ -210,30 +210,43 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do context 'when declining the invitation' do let(:send_email_confirmation) { true } - context 'when signed in' do - before do - sign_in(user) - visit invite_path(group_invite.raw_invite_token) + context 'as an existing user' do + let(:group_invite) { create(:group_member, user: user, group: group, created_by: owner) } + + context 'when signed in' do + before do + sign_in(user) + visit decline_invite_path(group_invite.raw_invite_token) + end + + it 'declines application and redirects to dashboard' do + expect(current_path).to eq(dashboard_projects_path) + expect(page).to have_content('You have declined the invitation to join group Owned.') + expect { group_invite.reload }.to raise_error ActiveRecord::RecordNotFound + end end - it 'declines application and redirects to dashboard' do - page.click_link 'Decline' + context 'when signed out' do + before do + visit decline_invite_path(group_invite.raw_invite_token) + end - expect(current_path).to eq(dashboard_projects_path) - expect(page).to have_content('You have declined the invitation to join group Owned.') - expect { group_invite.reload }.to raise_error ActiveRecord::RecordNotFound + it 'declines application and redirects to sign in page' do + expect(current_path).to eq(new_user_session_path) + expect(page).to have_content('You have declined the invitation to join group Owned.') + expect { group_invite.reload }.to raise_error ActiveRecord::RecordNotFound + end end end - context 'when signed out' do + context 'as a non-existing user' do before do visit decline_invite_path(group_invite.raw_invite_token) end - it 'declines application and redirects to sign in page' do - expect(current_path).to eq(new_user_session_path) - - expect(page).to have_content('You have declined the invitation to join group Owned.') + it 'declines application and shows a decline page' do + expect(current_path).to eq(decline_invite_path(group_invite.raw_invite_token)) + expect(page).to have_content('You successfully declined the invitation') expect { group_invite.reload }.to raise_error ActiveRecord::RecordNotFound end end diff --git a/spec/features/issuables/close_reopen_report_toggle_spec.rb b/spec/features/issuables/close_reopen_report_toggle_spec.rb index 5ea89a7984f..6e99cfb3293 100644 --- a/spec/features/issuables/close_reopen_report_toggle_spec.rb +++ b/spec/features/issuables/close_reopen_report_toggle_spec.rb @@ -23,7 +23,15 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do expect(container).to have_content("Close #{human_model_name}") expect(container).to have_content('Report abuse') expect(container).to have_content("Report #{human_model_name.pluralize} that are abusive, inappropriate or spam.") - expect(container).to have_selector('.close-item.droplab-item-selected') + + if issuable.is_a?(MergeRequest) + page.within('.js-issuable-close-dropdown') do + expect(page).to have_link('Close merge request') + end + else + expect(container).to have_selector('.close-item.droplab-item-selected') + end + expect(container).to have_selector('.report-item') expect(container).not_to have_selector('.report-item.droplab-item-selected') expect(container).not_to have_selector('.reopen-item') @@ -123,7 +131,7 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do it 'shows only the `Edit` button' do expect(page).to have_link('Edit') - expect(page).not_to have_link('Report abuse') + expect(page).to have_link('Report abuse') expect(page).not_to have_button('Close merge request') expect(page).not_to have_button('Reopen merge request') end diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb index aceaea8d2ed..07d4271eed7 100644 --- a/spec/features/issuables/markdown_references/internal_references_spec.rb +++ b/spec/features/issuables/markdown_references/internal_references_spec.rb @@ -25,7 +25,7 @@ RSpec.describe "Internal references", :js do add_note("##{public_project_issue.to_reference(private_project)}") end - context "when user doesn't have access to private project" do + context "when user doesn't have access to private project", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do before do sign_in(public_project_user) @@ -52,7 +52,7 @@ RSpec.describe "Internal references", :js do visit(project_issue_path(public_project, public_project_issue)) end - it "doesn't show any references" do + it "doesn't show any references", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do page.within(".issue-details") do expect(page).not_to have_content("#merge-requests .merge-requests-title") end @@ -94,7 +94,7 @@ RSpec.describe "Internal references", :js do add_note("##{public_project_merge_request.to_reference(private_project)}") end - context "when user doesn't have access to private project" do + context "when user doesn't have access to private project", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do before do sign_in(public_project_user) @@ -121,7 +121,7 @@ RSpec.describe "Internal references", :js do visit(project_merge_request_path(public_project, public_project_merge_request)) end - it "doesn't show any references" do + it "doesn't show any references", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do page.within(".merge-request-details") do expect(page).not_to have_content("#merge-requests .merge-requests-title") end diff --git a/spec/features/issuables/merge_request_discussion_lock_spec.rb b/spec/features/issuables/merge_request_discussion_lock_spec.rb new file mode 100644 index 00000000000..4e0265839f6 --- /dev/null +++ b/spec/features/issuables/merge_request_discussion_lock_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true +# TODO use shared examples to merge this spec with discussion_lock_spec.rb +# https://gitlab.com/gitlab-org/gitlab/-/issues/255910 + +require 'spec_helper' + +RSpec.describe 'Merge Request Discussion Lock', :js do + let(:user) { create(:user) } + let(:project) { create(:project, :public, :repository) } + let(:merge_request) { create(:merge_request, source_project: project, author: user) } + + before do + sign_in(user) + end + + context 'when a user is a team member' do + before do + project.add_developer(user) + end + + context 'when the discussion is unlocked' do + it 'the user can lock the merge_request' do + visit project_merge_request_path(merge_request.project, merge_request) + + expect(find('.issuable-sidebar')).to have_content('Unlocked') + + page.within('.issuable-sidebar') do + find('.lock-edit').click + click_button('Lock') + end + + expect(find('[data-testid="lock-status"]')).to have_content('Locked') + end + end + + context 'when the discussion is locked' do + before do + merge_request.update_attribute(:discussion_locked, true) + visit project_merge_request_path(merge_request.project, merge_request) + end + + it 'the user can unlock the merge_request' do + expect(find('.issuable-sidebar')).to have_content('Locked') + + page.within('.issuable-sidebar') do + find('.lock-edit').click + click_button('Unlock') + end + + expect(find('[data-testid="lock-status"]')).to have_content('Unlocked') + end + end + end + + context 'when a user is not a team member' do + context 'when the discussion is unlocked' do + before do + visit project_merge_request_path(merge_request.project, merge_request) + end + + it 'the user can not lock the merge_request' do + expect(find('.issuable-sidebar')).to have_content('Unlocked') + expect(find('.issuable-sidebar')).not_to have_selector('.lock-edit') + end + end + + context 'when the discussion is locked' do + before do + merge_request.update_attribute(:discussion_locked, true) + visit project_merge_request_path(merge_request.project, merge_request) + end + + it 'the user can not unlock the merge_request' do + expect(find('.issuable-sidebar')).to have_content('Locked') + expect(find('.issuable-sidebar')).not_to have_selector('.lock-edit') + end + end + end +end diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 0165fba9ace..ff78b9e608f 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -6,7 +6,9 @@ RSpec.describe 'GFM autocomplete', :js do let_it_be(:user_xss_title) { 'eve <img src=x onerror=alert(2)<img src=x onerror=alert(1)>' } let_it_be(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') } let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } - let_it_be(:project) { create(:project) } + let_it_be(:group) { create(:group, name: 'Ancestor') } + let_it_be(:child_group) { create(:group, parent: group, name: 'My group') } + let_it_be(:project) { create(:project, group: child_group) } let_it_be(:label) { create(:label, project: project, title: 'special+') } let(:issue) { create(:issue, project: project) } @@ -530,7 +532,7 @@ RSpec.describe 'GFM autocomplete', :js do expect(page).to have_selector('.tribute-container', visible: true) - expect(find('.tribute-container ul', visible: true).text).to have_content(user_xss.username) + expect(find('.tribute-container ul', visible: true)).to have_text(user_xss.username) end it 'selects the first item for assignee dropdowns' do @@ -558,6 +560,24 @@ RSpec.describe 'GFM autocomplete', :js do expect(find('.tribute-container ul', visible: true)).to have_content(user.name) end + context 'when autocompleting for groups' do + it 'shows the group when searching for the name of the group' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('@mygroup') + end + + expect(find('.tribute-container ul', visible: true)).to have_text('My group') + end + + it 'does not show the group when searching for the name of the parent of the group' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('@ancestor') + end + + expect(find('.tribute-container ul', visible: true)).not_to have_text('My group') + end + end + context 'if a selected value has special characters' do it 'wraps the result in double quotes' do note = find('#note-body') diff --git a/spec/features/issues/user_sees_live_update_spec.rb b/spec/features/issues/user_sees_live_update_spec.rb index c9b751715bc..d27cdb774a5 100644 --- a/spec/features/issues/user_sees_live_update_spec.rb +++ b/spec/features/issues/user_sees_live_update_spec.rb @@ -39,7 +39,7 @@ RSpec.describe 'Issues > User sees live update', :js do expect(page).to have_css('.sidebar-item-warning-message') within('.sidebar-item-warning-message') do - find('.btn-close').click + find('[data-testid="confidential-toggle"]').click end wait_for_requests diff --git a/spec/features/issues/user_views_issue_spec.rb b/spec/features/issues/user_views_issue_spec.rb index 3f18764aa58..9b1c8be1513 100644 --- a/spec/features/issues/user_views_issue_spec.rb +++ b/spec/features/issues/user_views_issue_spec.rb @@ -5,7 +5,7 @@ require "spec_helper" RSpec.describe "User views issue" do let_it_be(:project) { create(:project_empty_repo, :public) } let_it_be(:user) { create(:user) } - let_it_be(:issue) { create(:issue, project: project, description: "# Description header", author: user) } + let_it_be(:issue) { create(:issue, project: project, description: "# Description header\n\n**Lorem** _ipsum_ dolor sit [amet](https://example.com)", author: user) } let_it_be(:note) { create(:note, noteable: issue, project: project, author: user) } before_all do @@ -20,6 +20,8 @@ RSpec.describe "User views issue" do it { expect(page).to have_header_with_correct_id_and_link(1, "Description header", "description-header") } + it_behaves_like 'page meta description', ' Description header Lorem ipsum dolor sit amet' + it 'shows the merge request and issue actions', :aggregate_failures do expect(page).to have_link('New issue') expect(page).to have_button('Create merge request') diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb index 40f6482c948..c8fc23bebf9 100644 --- a/spec/features/merge_request/batch_comments_spec.rb +++ b/spec/features/merge_request/batch_comments_spec.rb @@ -41,7 +41,6 @@ RSpec.describe 'Merge request > Batch comments', :js do write_comment page.within('.review-bar-content') do - click_button 'Finish review' click_button 'Submit review' end @@ -64,18 +63,6 @@ RSpec.describe 'Merge request > Batch comments', :js do expect(page).to have_selector('.note:not(.draft-note)', text: 'Line is wrong') end - it 'discards review' do - write_comment - - click_button 'Discard review' - - click_button 'Delete all pending comments' - - wait_for_requests - - expect(page).not_to have_selector('.draft-note-component') - end - it 'deletes draft note' do write_comment @@ -149,7 +136,6 @@ RSpec.describe 'Merge request > Batch comments', :js do write_reply_to_discussion(resolve: true) page.within('.review-bar-content') do - click_button 'Finish review' click_button 'Submit review' end @@ -192,7 +178,6 @@ RSpec.describe 'Merge request > Batch comments', :js do write_reply_to_discussion(button_text: 'Start a review', unresolve: true) page.within('.review-bar-content') do - click_button 'Finish review' click_button 'Submit review' end diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb index 0e65cb358da..a98bfd1c8a4 100644 --- a/spec/features/merge_request/maintainer_edits_fork_spec.rb +++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb @@ -26,7 +26,12 @@ RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork visit project_merge_request_path(target_project, merge_request) click_link 'Changes' wait_for_requests - first('.js-file-title').find('.js-edit-blob').click + + page.within(first('.js-file-title')) do + find('.js-diff-more-actions').click + find('.js-edit-blob').click + end + wait_for_requests end diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb index 3a199951b56..ad1ad067935 100644 --- a/spec/features/merge_request/user_comments_on_diff_spec.rb +++ b/spec/features/merge_request/user_comments_on_diff_spec.rb @@ -34,7 +34,8 @@ RSpec.describe 'User comments on a diff', :js do page.within('.diff-files-holder > div:nth-child(3)') do expect(page).to have_content('Line is wrong') - find('.js-btn-vue-toggle-comments').click + find('.js-diff-more-actions').click + click_button 'Hide comments on this file' expect(page).not_to have_content('Line is wrong') end @@ -67,7 +68,8 @@ RSpec.describe 'User comments on a diff', :js do # Hide the comment. page.within('.diff-files-holder > div:nth-child(3)') do - find('.js-btn-vue-toggle-comments').click + find('.js-diff-more-actions').click + click_button 'Hide comments on this file' expect(page).not_to have_content('Line is wrong') end @@ -80,7 +82,8 @@ RSpec.describe 'User comments on a diff', :js do # Show the comment. page.within('.diff-files-holder > div:nth-child(3)') do - find('.js-btn-vue-toggle-comments').click + find('.js-diff-more-actions').click + click_button 'Show comments on this file' end # Now both the comments should be shown. diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb index 397ca70f4a1..817b4e0b48e 100644 --- a/spec/features/merge_request/user_edits_mr_spec.rb +++ b/spec/features/merge_request/user_edits_mr_spec.rb @@ -21,24 +21,6 @@ RSpec.describe 'Merge request > User edits MR' do it_behaves_like 'an editable merge request' end - context 'when merge_request_reviewers is turned on' do - before do - stub_feature_flags(merge_request_reviewers: true) - end - - context 'non-fork merge request' do - include_context 'merge request edit context' - it_behaves_like 'an editable merge request with reviewers' - end - - context 'for a forked project' do - let(:source_project) { fork_project(target_project, nil, repository: true) } - - include_context 'merge request edit context' - it_behaves_like 'an editable merge request with reviewers' - end - end - context 'when merge_request_reviewers is turned off' do before do stub_feature_flags(merge_request_reviewers: false) diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb index 0e39cce13a1..0cdc87de761 100644 --- a/spec/features/merge_request/user_expands_diff_spec.rb +++ b/spec/features/merge_request/user_expands_diff_spec.rb @@ -7,6 +7,7 @@ RSpec.describe 'User expands diff', :js do let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) } before do + stub_feature_flags(increased_diff_limits: false) visit(diffs_project_merge_request_path(project, merge_request)) wait_for_requests @@ -14,11 +15,11 @@ RSpec.describe 'User expands diff', :js do it 'allows user to expand diff' do page.within find('[id="19763941ab80e8c09871c0a425f0560d9053bcb3"]') do - find('[data-testid="expandButton"]').click + click_link 'Click to expand it.' wait_for_requests - expect(page).not_to have_content('Expand File') + expect(page).not_to have_content('Click to expand it.') expect(page).to have_selector('.code') end end diff --git a/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb b/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb new file mode 100644 index 00000000000..f5bca7cf015 --- /dev/null +++ b/spec/features/merge_request/user_marks_merge_request_as_draft_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Merge request > User marks merge request as draft', :js do + let(:user) { create(:user) } + let(:project) { create(:project, :public, :repository) } + let(:merge_request) { create(:merge_request, source_project: project) } + + before do + project.add_maintainer(user) + + sign_in(user) + + visit project_merge_request_path(project, merge_request) + end + + it 'toggles draft status' do + click_link 'Mark as draft' + + expect(page).to have_content("Draft: #{merge_request.title}") + + page.within('.detail-page-header-actions') do + click_link 'Mark as ready' + end + + expect(page).to have_content(merge_request.title) + end +end diff --git a/spec/features/merge_request/user_reopens_merge_request_spec.rb b/spec/features/merge_request/user_reopens_merge_request_spec.rb index 7866ece84ac..4a05a3be59a 100644 --- a/spec/features/merge_request/user_reopens_merge_request_spec.rb +++ b/spec/features/merge_request/user_reopens_merge_request_spec.rb @@ -15,7 +15,11 @@ RSpec.describe 'User reopens a merge requests', :js do end it 'reopens a merge request' do - click_button('Reopen merge request', match: :first) + find('.js-issuable-close-dropdown .dropdown-toggle').click + + click_link('Reopen merge request', match: :first) + + wait_for_requests page.within('.status-box') do expect(page).to have_content('Open') diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb index a9d4c4df507..b67167252e1 100644 --- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb +++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb @@ -35,7 +35,9 @@ RSpec.describe 'Merge request > User resolves Work in Progress', :js do expect(page.find('.ci-widget-content')).to have_content("Pipeline ##{pipeline.id}") expect(page).to have_content "This merge request is still a work in progress." - click_button('Mark as ready') + page.within('.mr-state-widget') do + click_button('Mark as ready') + end wait_for_requests diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb index 7a3a14e61e3..a7713ed9964 100644 --- a/spec/features/merge_request/user_sees_diff_spec.rb +++ b/spec/features/merge_request/user_sees_diff_spec.rb @@ -63,7 +63,7 @@ RSpec.describe 'Merge request > User sees diff', :js do visit diffs_project_merge_request_path(project, merge_request) # Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax - expect(page).to have_selector("[id=\"#{changelog_id}\"] a.js-edit-blob") + expect(page).to have_selector("[id=\"#{changelog_id}\"] .js-edit-blob", visible: false) end end @@ -73,6 +73,7 @@ RSpec.describe 'Merge request > User sees diff', :js do visit diffs_project_merge_request_path(project, merge_request) # Throws `Capybara::Poltergeist::InvalidSelector` if we try to use `#hash` syntax + find("[id=\"#{changelog_id}\"] .js-diff-more-actions").click find("[id=\"#{changelog_id}\"] .js-edit-blob").click expect(page).to have_selector('.js-fork-suggestion-button', count: 1) diff --git a/spec/features/merge_request/user_sees_page_metadata_spec.rb b/spec/features/merge_request/user_sees_page_metadata_spec.rb new file mode 100644 index 00000000000..7b3e07152a0 --- /dev/null +++ b/spec/features/merge_request/user_sees_page_metadata_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Merge request > User sees page metadata' do + let(:merge_request) { create(:merge_request, description: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') } + let(:project) { merge_request.target_project } + let(:user) { project.creator } + + before do + project.add_maintainer(user) + sign_in(user) + visit project_merge_request_path(project, merge_request) + end + + it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet' +end diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb index 8e15ba6cf8d..107fc002ebd 100644 --- a/spec/features/merge_request/user_sees_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_spec.rb @@ -50,7 +50,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do wait_for_requests - expect(page.find('.js-run-mr-pipeline')).to have_text('Run Pipeline') + expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run Pipeline') end end @@ -66,7 +66,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do wait_for_requests - expect(page.find('.js-run-mr-pipeline')).to have_text('Run Pipeline') + expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run Pipeline') end end end diff --git a/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb new file mode 100644 index 00000000000..93807512d9c --- /dev/null +++ b/spec/features/merge_request/user_sees_suggest_pipeline_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Merge request > User sees suggest pipeline', :js do + let(:merge_request) { create(:merge_request) } + let(:project) { merge_request.source_project } + let(:user) { project.creator } + + before do + stub_application_setting(auto_devops_enabled: false) + stub_experiment(suggest_pipeline: true) + stub_experiment_for_user(suggest_pipeline: true) + project.add_maintainer(user) + sign_in(user) + visit project_merge_request_path(project, merge_request) + end + + it 'shows the suggest pipeline widget and then allows dismissal correctly' do + expect(page).to have_content('Are you adding technical debt or code vulnerabilities?') + + page.within '.mr-pipeline-suggest' do + find('[data-testid="close"]').click + end + + wait_for_requests + + expect(page).not_to have_content('Are you adding technical debt or code vulnerabilities?') + + # Reload so we know the user callout was registered + visit page.current_url + + expect(page).not_to have_content('Are you adding technical debt or code vulnerabilities?') + end +end diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb index 39495832547..abdbd3a6f8a 100644 --- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb +++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb @@ -119,7 +119,8 @@ RSpec.describe 'User comments on a diff', :js do it 'can add and remove suggestions from a batch' do files.each_with_index do |file, index| page.within("[id='#{file[:hash]}']") do - find("button[title='Show full file']").click + find('.js-diff-more-actions').click + click_button 'Show full file' wait_for_requests click_diff_line(find("[id='#{file[:line_code]}']")) @@ -130,7 +131,9 @@ RSpec.describe 'User comments on a diff', :js do wait_for_requests end end + end + files.each_with_index do |file, index| page.within("[id='#{file[:hash]}']") do expect(page).not_to have_content('Applied') diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb index 448844ae57d..e8998f9457a 100644 --- a/spec/features/merge_request/user_views_open_merge_request_spec.rb +++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb @@ -22,7 +22,24 @@ RSpec.describe 'User views an open merge request' do # returns the whole document, not the node's actual parent element expect(find(:xpath, "#{node.path}/..").text).to eq(merge_request.description[2..-1]) - expect(page).to have_content(merge_request.title).and have_content(merge_request.description) + expect(page).to have_content(merge_request.title) + end + + it 'has reviewers in sidebar' do + expect(page).to have_css('.reviewer') + end + end + + context 'when merge_request_reviewers is turned off' do + let(:project) { create(:project, :public, :repository) } + + before do + stub_feature_flags(merge_request_reviewers: false) + visit(merge_request_path(merge_request)) + end + + it 'has reviewers in sidebar' do + expect(page).not_to have_css('.reviewer') end end diff --git a/spec/features/milestones/user_views_milestone_spec.rb b/spec/features/milestones/user_views_milestone_spec.rb index 420f8d49483..9c19f842427 100644 --- a/spec/features/milestones/user_views_milestone_spec.rb +++ b/spec/features/milestones/user_views_milestone_spec.rb @@ -4,15 +4,27 @@ require 'spec_helper' RSpec.describe "User views milestone" do let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } - let_it_be(:milestone) { create(:milestone, project: project) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :repository, group: group) } + let_it_be(:milestone) { create(:milestone, project: project, description: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') } let_it_be(:labels) { create_list(:label, 2, project: project) } - before do + before_all do project.add_developer(user) + end + + before do sign_in(user) end + context 'page description' do + before do + visit(project_milestone_path(project, milestone)) + end + + it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet' + end + it "avoids N+1 database queries" do issue_params = { project: project, assignees: [user], author: user, milestone: milestone, labels: labels }.freeze @@ -25,7 +37,7 @@ RSpec.describe "User views milestone" do expect { visit_milestone }.not_to exceed_query_limit(control) end - context 'limiting milestone issues' do + context 'issues list', :js do before_all do 2.times do create(:issue, milestone: milestone, project: project) @@ -34,6 +46,28 @@ RSpec.describe "User views milestone" do end end + context 'for a project milestone' do + it 'does not show the project name' do + visit(project_milestone_path(project, milestone)) + + wait_for_requests + + expect(page.find('#tab-issues')).not_to have_text(project.name) + end + end + + context 'for a group milestone' do + let(:group_milestone) { create(:milestone, group: group) } + + it 'shows the project name' do + create(:issue, project: project, milestone: group_milestone) + + visit(group_milestone_path(group, group_milestone)) + + expect(page.find('#tab-issues')).to have_text(project.name) + end + end + context 'when issues on milestone are over DISPLAY_ISSUES_LIMIT' do it "limits issues to display and shows warning" do stub_const('Milestoneish::DISPLAY_ISSUES_LIMIT', 3) @@ -56,6 +90,40 @@ RSpec.describe "User views milestone" do end end + context 'merge requests list', :js do + context 'for a project milestone' do + it 'does not show the project name' do + create(:merge_request, source_project: project, milestone: milestone) + + visit(project_milestone_path(project, milestone)) + + within('.js-milestone-tabs') do + click_link('Merge Requests') + end + + wait_for_requests + + expect(page.find('#tab-merge-requests')).not_to have_text(project.name) + end + end + + context 'for a group milestone' do + let(:group_milestone) { create(:milestone, group: group) } + + it 'shows the project name' do + create(:merge_request, source_project: project, milestone: group_milestone) + + visit(group_milestone_path(group, group_milestone)) + + within('.js-milestone-tabs') do + click_link('Merge Requests') + end + + expect(page.find('#tab-merge-requests')).to have_text(project.name) + end + end + end + private def visit_milestone diff --git a/spec/features/milestones/user_views_milestones_spec.rb b/spec/features/milestones/user_views_milestones_spec.rb index 3f606577121..f8b4b802a60 100644 --- a/spec/features/milestones/user_views_milestones_spec.rb +++ b/spec/features/milestones/user_views_milestones_spec.rb @@ -21,7 +21,7 @@ RSpec.describe "User views milestones" do .and have_content("Merge Requests") end - context "with issues" do + context "with issues", :js do let_it_be(:issue) { create(:issue, project: project, milestone: milestone) } let_it_be(:closed_issue) { create(:closed_issue, project: project, milestone: milestone) } @@ -33,7 +33,6 @@ RSpec.describe "User views milestones" do .and have_selector("#tab-issues li.issuable-row", count: 2) .and have_content(issue.title) .and have_content(closed_issue.title) - .and have_selector("#tab-merge-requests") end end diff --git a/spec/features/operations_sidebar_link_spec.rb b/spec/features/operations_sidebar_link_spec.rb new file mode 100644 index 00000000000..32e2833dafb --- /dev/null +++ b/spec/features/operations_sidebar_link_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Operations dropdown sidebar' do + let_it_be(:project) { create(:project, :repository) } + let(:user) { create(:user) } + + before do + project.add_role(user, role) + sign_in(user) + visit project_issues_path(project) + end + + context 'user has guest role' do + let(:role) { :guest } + + it 'has the correct `Operations` menu items' do + expect(page).to have_link(title: 'Incidents', href: project_incidents_path(project)) + + expect(page).not_to have_link(title: 'Metrics', href: project_metrics_dashboard_path(project)) + expect(page).not_to have_link(title: 'Alerts', href: project_alert_management_index_path(project)) + expect(page).not_to have_link(title: 'Environments', href: project_environments_path(project)) + expect(page).not_to have_link(title: 'Error Tracking', href: project_error_tracking_index_path(project)) + expect(page).not_to have_link(title: 'Product Analytics', href: project_product_analytics_path(project)) + expect(page).not_to have_link(title: 'Serverless', href: project_serverless_functions_path(project)) + expect(page).not_to have_link(title: 'Logs', href: project_logs_path(project)) + expect(page).not_to have_link(title: 'Kubernetes', href: project_clusters_path(project)) + end + end + + context 'user has reporter role' do + let(:role) { :reporter } + + it 'has the correct `Operations` menu items' do + expect(page).to have_link(title: 'Metrics', href: project_metrics_dashboard_path(project)) + expect(page).to have_link(title: 'Incidents', href: project_incidents_path(project)) + expect(page).to have_link(title: 'Environments', href: project_environments_path(project)) + expect(page).to have_link(title: 'Error Tracking', href: project_error_tracking_index_path(project)) + expect(page).to have_link(title: 'Product Analytics', href: project_product_analytics_path(project)) + + expect(page).not_to have_link(title: 'Alerts', href: project_alert_management_index_path(project)) + expect(page).not_to have_link(title: 'Serverless', href: project_serverless_functions_path(project)) + expect(page).not_to have_link(title: 'Logs', href: project_logs_path(project)) + expect(page).not_to have_link(title: 'Kubernetes', href: project_clusters_path(project)) + end + end + + context 'user has developer role' do + let(:role) { :developer } + + it 'has the correct `Operations` menu items' do + expect(page).to have_link(title: 'Metrics', href: project_metrics_dashboard_path(project)) + expect(page).to have_link(title: 'Alerts', href: project_alert_management_index_path(project)) + expect(page).to have_link(title: 'Incidents', href: project_incidents_path(project)) + expect(page).to have_link(title: 'Environments', href: project_environments_path(project)) + expect(page).to have_link(title: 'Error Tracking', href: project_error_tracking_index_path(project)) + expect(page).to have_link(title: 'Product Analytics', href: project_product_analytics_path(project)) + expect(page).to have_link(title: 'Logs', href: project_logs_path(project)) + + expect(page).not_to have_link(title: 'Serverless', href: project_serverless_functions_path(project)) + expect(page).not_to have_link(title: 'Kubernetes', href: project_clusters_path(project)) + end + end + + context 'user has maintainer role' do + let(:role) { :maintainer } + + it 'has the correct `Operations` menu items' do + expect(page).to have_link(title: 'Metrics', href: project_metrics_dashboard_path(project)) + expect(page).to have_link(title: 'Alerts', href: project_alert_management_index_path(project)) + expect(page).to have_link(title: 'Incidents', href: project_incidents_path(project)) + expect(page).to have_link(title: 'Environments', href: project_environments_path(project)) + expect(page).to have_link(title: 'Error Tracking', href: project_error_tracking_index_path(project)) + expect(page).to have_link(title: 'Product Analytics', href: project_product_analytics_path(project)) + expect(page).to have_link(title: 'Serverless', href: project_serverless_functions_path(project)) + expect(page).to have_link(title: 'Logs', href: project_logs_path(project)) + expect(page).to have_link(title: 'Kubernetes', href: project_clusters_path(project)) + end + end +end diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb index b5e784a749f..23bbe9c1587 100644 --- a/spec/features/profiles/keys_spec.rb +++ b/spec/features/profiles/keys_spec.rb @@ -71,21 +71,35 @@ RSpec.describe 'Profile > SSH Keys' do expect(page).to have_content(key.title) end - it 'User removes a key via the key index' do - create(:key, user: user) - visit profile_keys_path + describe 'User removes a key', :js do + shared_examples 'removes key' do + it 'removes key' do + visit path + click_button('Delete') - click_link('Remove') + page.within('.modal') do + page.click_button('Delete') + end - expect(page).to have_content('Your SSH keys (0)') - end + expect(page).to have_content('Your SSH keys (0)') + end + end - it 'User removes a key via its details page' do - key = create(:key, user: user) - visit profile_key_path(key) + context 'via the key index' do + before do + create(:key, user: user) + end + + let(:path) { profile_keys_path } - click_link('Remove') + it_behaves_like 'removes key' + end - expect(page).to have_content('Your SSH keys (0)') + context 'via its details page' do + let(:key) { create(:key, user: user) } + let(:path) { profile_keys_path(key) } + + it_behaves_like 'removes key' + end end end diff --git a/spec/features/projects/activity/user_sees_design_comment_spec.rb b/spec/features/projects/activity/user_sees_design_comment_spec.rb index e60deba65f0..3a8e2790858 100644 --- a/spec/features/projects/activity/user_sees_design_comment_spec.rb +++ b/spec/features/projects/activity/user_sees_design_comment_spec.rb @@ -12,7 +12,7 @@ RSpec.describe 'Projects > Activity > User sees design comment', :js do let_it_be(:design) { create(:design, issue: issue) } let(:design_activity) do - "#{commenter.name} #{commenter.to_reference} commented on design" + "#{commenter.name} #{commenter.to_reference} commented on design #{design.to_reference}" end let(:issue_activity) do diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index 5aca994f53e..90d9263b515 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -20,9 +20,14 @@ RSpec.describe 'Editing file blob', :js do sign_in(user) end - def edit_and_commit(commit_changes: true) + def edit_and_commit(commit_changes: true, is_diff: false) wait_for_requests - find('.js-edit-blob').click + + if is_diff + first('.js-diff-more-actions').click + end + + first('.js-edit-blob').click fill_editor(content: 'class NextFeature\\nend\\n') if commit_changes @@ -38,7 +43,7 @@ RSpec.describe 'Editing file blob', :js do context 'from MR diff' do before do visit diffs_project_merge_request_path(project, merge_request) - edit_and_commit + edit_and_commit(is_diff: true) end it 'returns me to the mr' do diff --git a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb index 8b43687c71c..023e00a3e02 100644 --- a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb +++ b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb @@ -10,7 +10,7 @@ RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled describe 'viewing the new blob page' do before do - stub_feature_flags(suggest_pipeline: true) + stub_experiment_for_user(suggest_pipeline: true) sign_in(user) end diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb index 0e2444c5434..4224fdbc1fc 100644 --- a/spec/features/projects/branches_spec.rb +++ b/spec/features/projects/branches_spec.rb @@ -21,11 +21,11 @@ RSpec.describe 'Branches' do before do # Add 4 stale branches (1..4).reverse_each do |i| - Timecop.freeze((threshold + i).ago) { create_file(message: "a commit in stale-#{i}", branch_name: "stale-#{i}") } + travel_to((threshold + i).ago) { create_file(message: "a commit in stale-#{i}", branch_name: "stale-#{i}") } end # Add 6 active branches (1..6).each do |i| - Timecop.freeze((threshold - i).ago) { create_file(message: "a commit in active-#{i}", branch_name: "active-#{i}") } + travel_to((threshold - i).ago) { create_file(message: "a commit in active-#{i}", branch_name: "active-#{i}") } end end diff --git a/spec/features/projects/clusters/eks_spec.rb b/spec/features/projects/clusters/eks_spec.rb index c5feef6c6f3..9f3f331cfab 100644 --- a/spec/features/projects/clusters/eks_spec.rb +++ b/spec/features/projects/clusters/eks_spec.rb @@ -19,7 +19,7 @@ RSpec.describe 'AWS EKS Cluster', :js do before do visit project_clusters_path(project) - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' 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 04339d20d77..a0519d88532 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -33,7 +33,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do before do visit project_clusters_path(project) - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' click_link 'Create new cluster' click_link 'Google GKE' end @@ -143,7 +143,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do before do visit project_clusters_path(project) - click_link 'Add Kubernetes cluster' + click_link 'Connect cluster with certificate' click_link 'Connect existing cluster' end @@ -162,7 +162,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode 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('Add Kubernetes cluster') + expect(page).to have_link('Integrate with a cluster certificate') end end end @@ -178,7 +178,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do end it 'user sees offer on cluster create page' do - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' expect(page).to have_css('.gcp-signup-offer') end @@ -192,10 +192,10 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do it 'user does not see offer after dismissing' do expect(page).to have_css('.gcp-signup-offer') - find('.gcp-signup-offer .close').click + find('.gcp-signup-offer .js-close').click wait_for_requests - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' expect(page).not_to have_css('.gcp-signup-offer') end diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index 9d0dc65093e..748eba558aa 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -25,7 +25,7 @@ RSpec.describe 'User Cluster', :js do before do visit project_clusters_path(project) - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' click_link 'Connect existing cluster' end @@ -52,6 +52,10 @@ RSpec.describe 'User Cluster', :js do it 'user sees RBAC is enabled by default' do expect(page).to have_checked_field('RBAC-enabled cluster') end + + it 'user sees namespace per environment is enabled by default' do + expect(page).to have_checked_field('Namespace per environment') + end end context 'when user filled form with invalid parameters' do @@ -112,7 +116,7 @@ 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('Add Kubernetes cluster') + expect(page).to have_link('Integrate with a cluster certificate') end end end diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb index d674fbc457e..6c6e65005f6 100644 --- a/spec/features/projects/clusters_spec.rb +++ b/spec/features/projects/clusters_spec.rb @@ -11,7 +11,6 @@ RSpec.describe 'Clusters', :js do before do project.add_maintainer(user) gitlab_sign_in(user) - stub_feature_flags(clusters_list_redesign: false) end context 'when user does not have a cluster and visits cluster index page' do @@ -20,7 +19,7 @@ RSpec.describe 'Clusters', :js do end it 'sees empty state' do - expect(page).to have_link('Add Kubernetes cluster') + expect(page).to have_link('Integrate with a cluster certificate') expect(page).to have_selector('.empty-state') end end @@ -42,7 +41,7 @@ RSpec.describe 'Clusters', :js do context 'when user filled form with environment scope' do before do - click_link 'Add Kubernetes cluster' + click_link 'Connect cluster with certificate' click_link 'Connect existing cluster' fill_in 'cluster_name', with: 'staging-cluster' fill_in 'cluster_environment_scope', with: 'staging/*' @@ -71,7 +70,7 @@ RSpec.describe 'Clusters', :js do context 'when user updates duplicated environment scope' do before do - click_link 'Add Kubernetes cluster' + click_link 'Connect cluster with certificate' click_link 'Connect existing cluster' fill_in 'cluster_name', with: 'staging-cluster' fill_in 'cluster_environment_scope', with: '*' @@ -117,7 +116,7 @@ RSpec.describe 'Clusters', :js do context 'when user filled form with environment scope' do before do - click_link 'Add Kubernetes cluster' + click_link 'Connect cluster with certificate' click_link 'Create new cluster' click_link 'Google GKE' @@ -162,7 +161,7 @@ RSpec.describe 'Clusters', :js do context 'when user updates duplicated environment scope' do before do - click_link 'Add Kubernetes cluster' + click_link 'Connect cluster with certificate' click_link 'Create new cluster' click_link 'Google GKE' @@ -196,8 +195,7 @@ RSpec.describe 'Clusters', :js do end it 'user sees a table with one cluster' do - # One is the header row, the other the cluster row - expect(page).to have_selector('.gl-responsive-table-row', count: 2) + expect(page).to have_selector('[data-testid="cluster_list_table"] tbody tr', count: 1) end context 'when user clicks on a cluster' do @@ -216,7 +214,7 @@ RSpec.describe 'Clusters', :js do before do visit project_clusters_path(project) - click_link 'Add Kubernetes cluster' + click_link 'Integrate with a cluster certificate' click_link 'Create new cluster' end diff --git a/spec/features/projects/commit/user_comments_on_commit_spec.rb b/spec/features/projects/commit/user_comments_on_commit_spec.rb index 87a022d74a3..0fa4975bb25 100644 --- a/spec/features/projects/commit/user_comments_on_commit_spec.rb +++ b/spec/features/projects/commit/user_comments_on_commit_spec.rb @@ -6,19 +6,22 @@ RSpec.describe "User comments on commit", :js do include Spec::Support::Helpers::Features::NotesHelpers include RepoHelpers - let(:project) { create(:project, :repository) } - let(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } let(:comment_text) { "XML attached" } - before do - sign_in(user) + before_all do project.add_developer(user) + end - visit(project_commit_path(project, sample_commit.id)) + before do + sign_in(user) end context "when adding new comment" do it "adds comment" do + visit(project_commit_path(project, sample_commit.id)) + emoji_code = ":+1:" page.within(".js-main-target-form") do @@ -57,6 +60,8 @@ RSpec.describe "User comments on commit", :js do context "when editing comment" do before do + visit(project_commit_path(project, sample_commit.id)) + add_note(comment_text) end @@ -87,6 +92,8 @@ RSpec.describe "User comments on commit", :js do context "when deleting comment" do before do + visit(project_commit_path(project, sample_commit.id)) + add_note(comment_text) end @@ -108,4 +115,35 @@ RSpec.describe "User comments on commit", :js do expect(page).not_to have_css(".note") end end + + context 'when checking task lists' do + let(:note_with_task) do + <<-EOT.strip_heredoc + + - [ ] Task 1 + EOT + end + + before do + create(:note_on_commit, project: project, commit_id: sample_commit.id, note: note_with_task, author: user) + create(:note_on_commit, project: project, commit_id: sample_commit.id, note: note_with_task, author: user) + + visit(project_commit_path(project, sample_commit.id)) + end + + it 'allows the tasks to be checked' do + expect(page).to have_selector('li.task-list-item', count: 2) + expect(page).to have_selector('li.task-list-item input[checked]', count: 0) + + all('.task-list-item-checkbox').each do |checkbox| + checkbox.click + end + wait_for_requests + + visit(project_commit_path(project, sample_commit.id)) + + expect(page).to have_selector('li.task-list-item', count: 2) + expect(page).to have_selector('li.task-list-item input[checked]', count: 2) + end + end end diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index 7f2ef61bcbe..8c032660726 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -372,7 +372,7 @@ RSpec.describe 'Environments page', :js do let(:role) { :developer } it 'developer creates a new environment with a valid name' do - within(".top-area") { click_link 'New environment' } + within(".environments-section") { click_link 'New environment' } fill_in('Name', with: 'production') click_on 'Save' @@ -380,7 +380,7 @@ RSpec.describe 'Environments page', :js do end it 'developer creates a new environmetn with invalid name' do - within(".top-area") { click_link 'New environment' } + within(".environments-section") { click_link 'New environment' } fill_in('Name', with: 'name,with,commas') click_on 'Save' diff --git a/spec/features/projects/issues/design_management/user_links_to_designs_in_issue_spec.rb b/spec/features/projects/issues/design_management/user_links_to_designs_in_issue_spec.rb index 8d5e99d7e2b..78fb470d4ea 100644 --- a/spec/features/projects/issues/design_management/user_links_to_designs_in_issue_spec.rb +++ b/spec/features/projects/issues/design_management/user_links_to_designs_in_issue_spec.rb @@ -90,34 +90,5 @@ RSpec.describe 'viewing issues with design references' do expect(page).not_to have_link(design_ref_b) end end - - context 'design management is enabled, but the filter is disabled globally' do - before do - enable_design_management - stub_feature_flags( - Banzai::Filter::DesignReferenceFilter::FEATURE_FLAG => false - ) - end - - it 'processes design tab links successfully, and design references as issue references', :aggregate_failures do - visit_page_with_design_references - - expect(page).to have_text('The designs I mentioned') - expect(page).to have_link(design_tab_ref) - expect(page).to have_link(issue_ref) - expect(page).not_to have_link(design_ref_a) - expect(page).not_to have_link(design_ref_b) - end - end - - context 'design management is enabled, and the filter is enabled for the current project' do - before do - stub_feature_flags( - Banzai::Filter::DesignReferenceFilter::FEATURE_FLAG => public_project - ) - end - - it_behaves_like 'successful use of design link references' - end end end diff --git a/spec/features/projects/issues/viewing_relocated_issues_spec.rb b/spec/features/projects/issues/viewing_relocated_issues_spec.rb new file mode 100644 index 00000000000..10d5ad1747c --- /dev/null +++ b/spec/features/projects/issues/viewing_relocated_issues_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'issues canonical link' do + include Spec::Support::Helpers::Features::CanonicalLinkHelpers + + let_it_be(:original_project) { create(:project, :public) } + let_it_be(:original_issue) { create(:issue, project: original_project) } + let_it_be(:canonical_issue) { create(:issue) } + let_it_be(:canonical_url) { issue_url(canonical_issue, Gitlab::Application.routes.default_url_options) } + + it "doesn't show the canonical URL" do + visit(issue_path(original_issue)) + + expect(page).not_to have_any_canonical_links + end + + context 'when the issue was moved' do + it 'shows the canonical URL' do + original_issue.moved_to = canonical_issue + original_issue.save! + + visit(issue_path(original_issue)) + + expect(page).to have_canonical_link(canonical_url) + end + end + + context 'when the issue was duplicated' do + it 'shows the canonical URL' do + original_issue.duplicated_to = canonical_issue + original_issue.save! + + visit(issue_path(original_issue)) + + expect(page).to have_canonical_link(canonical_url) + end + end +end 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 2ee6bc103e9..d652f6715db 100644 --- a/spec/features/projects/members/groups_with_access_list_spec.rb +++ b/spec/features/projects/members/groups_with_access_list_spec.rb @@ -3,20 +3,23 @@ require 'spec_helper' RSpec.describe 'Projects > Members > Groups with access list', :js do - let(:user) { create(:user) } - let(:group) { create(:group, :public) } - let(:project) { create(:project, :public) } + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group, :public) } + let_it_be(:project) { create(:project, :public) } + + let(:additional_link_attrs) { {} } + let!(:group_link) { create(:project_group_link, project: project, group: group, **additional_link_attrs) } before do - project.add_maintainer(user) - @group_link = create(:project_group_link, project: project, group: group) + travel_to Time.now.utc.beginning_of_day + project.add_maintainer(user) sign_in(user) visit project_project_members_path(project) end it 'updates group access level' do - click_button @group_link.human_access + click_button group_link.human_access page.within '.dropdown-menu' do click_link 'Guest' @@ -30,14 +33,32 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do end it 'updates expiry date' do - tomorrow = Date.today + 3 + expires_at_field = "member_expires_at_#{group.id}" + fill_in expires_at_field, with: 3.days.from_now.to_date - fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F") - find('body').click + find_field(expires_at_field).native.send_keys :enter wait_for_requests page.within(find('li.group_member')) do - expect(page).to have_content('Expires in') + expect(page).to have_content('Expires in 3 days') + end + end + + context 'when link has expiry date set' do + let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } } + + it 'clears expiry date' do + page.within(find('li.group_member')) do + expect(page).to have_content('Expires in 3 days') + + page.within(find('.js-edit-member-form')) do + find('.js-clear-input').click + end + + wait_for_requests + + expect(page).not_to have_content('Expires in') + end end end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index f59dc5dd074..c8c3a52d427 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -172,10 +172,17 @@ RSpec.describe 'Pipeline', :js do end end - it_behaves_like 'showing user status' do - let(:user_with_status) { pipeline.user } + describe 'pipelines details view' do + let!(:status) { create(:user_status, user: pipeline.user, emoji: 'smirk', message: 'Authoring this object') } - subject { visit project_pipeline_path(project, pipeline) } + it 'pipeline header shows the user status and emoji' do + visit project_pipeline_path(project, pipeline) + + within '[data-testid="pipeline-header-content"]' do + expect(page).to have_selector("[data-testid='#{status.message}']") + expect(page).to have_selector("[data-name='#{status.emoji}']") + end + end end describe 'pipeline graph' do @@ -400,7 +407,7 @@ RSpec.describe 'Pipeline', :js do context 'when retrying' do before do - find('[data-testid="retryButton"]').click + find('[data-testid="retryPipeline"]').click end it 'does not show a "Retry" button', :sidekiq_might_not_need_inline do @@ -902,7 +909,7 @@ RSpec.describe 'Pipeline', :js do context 'when retrying' do before do - find('[data-testid="retryButton"]').click + find('[data-testid="retryPipeline"]').click end it 'does not show a "Retry" button', :sidekiq_might_not_need_inline do diff --git a/spec/features/projects/releases/user_creates_release_spec.rb b/spec/features/projects/releases/user_creates_release_spec.rb index 5d05a7e4c91..a440a4211e3 100644 --- a/spec/features/projects/releases/user_creates_release_spec.rb +++ b/spec/features/projects/releases/user_creates_release_spec.rb @@ -18,7 +18,7 @@ RSpec.describe 'User creates release', :js do project.add_developer(user) - gitlab_sign_in(user) + sign_in(user) visit new_page_url @@ -108,6 +108,24 @@ RSpec.describe 'User creates release', :js do end end + context 'when the release notes "Preview" tab is clicked' do + before do + find_field('Release notes').click + + fill_release_notes('**some** _markdown_ [content](https://example.com)') + + click_on 'Preview' + + wait_for_all_requests + end + + it 'renders a preview of the release notes markdown' do + within('[data-testid="release-notes"]') do + expect(page).to have_text('some markdown content') + end + end + end + def fill_out_form_and_submit fill_tag_name(tag_name) diff --git a/spec/features/projects/releases/user_views_edit_release_spec.rb b/spec/features/projects/releases/user_views_edit_release_spec.rb index 4ed1be6db6b..976840ee4e7 100644 --- a/spec/features/projects/releases/user_views_edit_release_spec.rb +++ b/spec/features/projects/releases/user_views_edit_release_spec.rb @@ -13,7 +13,7 @@ RSpec.describe 'User edits Release', :js do project.add_developer(user) - gitlab_sign_in(user) + sign_in(user) visit edit_project_release_path(project, release) diff --git a/spec/features/projects/releases/user_views_release_spec.rb b/spec/features/projects/releases/user_views_release_spec.rb index c82588746a8..4410f345e56 100644 --- a/spec/features/projects/releases/user_views_release_spec.rb +++ b/spec/features/projects/releases/user_views_release_spec.rb @@ -4,17 +4,25 @@ require 'spec_helper' RSpec.describe 'User views Release', :js do let(:project) { create(:project, :repository) } - let(:release) { create(:release, project: project, name: 'The first release' ) } let(:user) { create(:user) } + let(:release) do + create(:release, + project: project, + name: 'The first release', + description: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') + end + before do project.add_developer(user) - gitlab_sign_in(user) + sign_in(user) visit project_release_path(project, release) end + it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet' + it 'renders the breadcrumbs' do within('.breadcrumbs') do expect(page).to have_content("#{project.creator.name} #{project.name} Releases #{release.name}") @@ -31,7 +39,7 @@ RSpec.describe 'User views Release', :js do expect(page).to have_content(release.name) expect(page).to have_content(release.tag) expect(page).to have_content(release.commit.short_id) - expect(page).to have_content(release.description) + expect(page).to have_content('Lorem ipsum dolor sit amet') end end end diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb index 993d3371904..3bf472e82ec 100644 --- a/spec/features/projects/releases/user_views_releases_spec.rb +++ b/spec/features/projects/releases/user_views_releases_spec.rb @@ -16,7 +16,7 @@ RSpec.describe 'User views releases', :js do shared_examples 'releases page' do context('when the user is a maintainer') do before do - gitlab_sign_in(maintainer) + sign_in(maintainer) end it 'sees the release' do @@ -110,7 +110,7 @@ RSpec.describe 'User views releases', :js do context('when the user is a guest') do before do - gitlab_sign_in(guest) + sign_in(guest) end it 'renders release info except for Git-related data' do diff --git a/spec/features/projects/show/user_manages_notifications_spec.rb b/spec/features/projects/show/user_manages_notifications_spec.rb index 9d9a75c22be..d444ea27d35 100644 --- a/spec/features/projects/show/user_manages_notifications_spec.rb +++ b/spec/features/projects/show/user_manages_notifications_spec.rb @@ -18,7 +18,9 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do click_notifications_button click_link 'On mention' - wait_for_requests + page.within('.notification-dropdown') do + expect(page).not_to have_css('.gl-spinner') + end click_notifications_button expect(find('.update-notification.is-active')).to have_content('On mention') @@ -30,7 +32,9 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do click_notifications_button click_link 'Disabled' - wait_for_requests + page.within('.notification-dropdown') do + expect(page).not_to have_css('.gl-spinner') + end expect(page).to have_css('.notifications-icon[data-testid="notifications-off-icon"]') end diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb index 81736fefae9..afa9de5ce86 100644 --- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb +++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb @@ -226,7 +226,7 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do expect(project.repository.gitlab_ci_yml).to be_nil page.within('.project-buttons') do - expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_ide_path) + expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_path) end end diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb index bd2af66710a..ca9e0a23888 100644 --- a/spec/features/projects/tree/tree_show_spec.rb +++ b/spec/features/projects/tree/tree_show_spec.rb @@ -69,7 +69,7 @@ RSpec.describe 'Projects tree', :js do # Check last commit expect(find('.commit-content').text).to include(message) - expect(find('.commit-sha-group').text).to eq(short_newrev) + expect(find('.js-commit-sha-group').text).to eq(short_newrev) end end diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb index 50d7b353c46..040e8741b6e 100644 --- a/spec/features/projects/user_sees_sidebar_spec.rb +++ b/spec/features/projects/user_sees_sidebar_spec.rb @@ -145,11 +145,11 @@ RSpec.describe 'Projects > User sees sidebar' do expect(page).to have_content 'Project' expect(page).to have_content 'Issues' expect(page).to have_content 'Wiki' + expect(page).to have_content 'Operations' expect(page).not_to have_content 'Repository' expect(page).not_to have_content 'CI / CD' expect(page).not_to have_content 'Merge Requests' - expect(page).not_to have_content 'Operations' end end diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb deleted file mode 100644 index 8f2fb9e827c..00000000000 --- a/spec/features/projects/wiki/markdown_preview_spec.rb +++ /dev/null @@ -1,168 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Projects > Wiki > User previews markdown changes', :js do - let_it_be(:user) { create(:user) } - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)') } - let(:wiki_content) do - <<-HEREDOC -Some text so key event for [ does not trigger an incorrect replacement. -[regular link](regular) -[relative link 1](../relative) -[relative link 2](./relative) -[relative link 3](./e/f/relative) -[spaced link](title with spaces) - HEREDOC - end - - before do - project.add_maintainer(user) - - sign_in(user) - end - - context "while creating a new wiki page" do - context "when there are no spaces or hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a/b/c/d', content: wiki_content) - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a/b/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a/b/c/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a/b/c/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are spaces in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a page/b page/c page/d page', content: wiki_content) - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a-page/b-page/c-page/d-page', content: wiki_content) - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/title%20with%20spaces\">spaced link</a>") - end - end - end - - context "while editing a wiki page" do - context "when there are no spaces or hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a/b/c/d') - click_link 'Edit' - - fill_in :wiki_content, with: wiki_content - click_on "Preview" - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a/b/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a/b/c/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a/b/c/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are spaces in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a page/b page/c page/d page') - click_link 'Edit' - - fill_in :wiki_content, with: wiki_content - click_on "Preview" - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a-page/b-page/c-page/d-page') - click_link 'Edit' - - fill_in :wiki_content, with: wiki_content - click_on "Preview" - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/-/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context 'when rendering the preview' do - it 'renders content with CommonMark' do - create_wiki_page('a-page/b-page/c-page/common-mark') - click_link 'Edit' - - fill_in :wiki_content, with: "1. one\n - sublist\n" - click_on "Preview" - - # the above generates two separate lists (not embedded) in CommonMark - expect(page).to have_content("sublist") - expect(page).not_to have_xpath("//ol//li//ul") - end - end - end - - it "does not linkify double brackets inside code blocks as expected" do - wiki_content = <<-HEREDOC - `[[do_not_linkify]]` - ``` - [[also_do_not_linkify]] - ``` - HEREDOC - - create_wiki_page('linkify_test', wiki_content) - - expect(page).to have_content("do_not_linkify") - - expect(page.html).to include('[[do_not_linkify]]') - expect(page.html).to include('[[also_do_not_linkify]]') - end - - private - - def create_wiki_page(path, content = 'content') - visit project_wiki_path(project, wiki_page) - - click_link 'New page' - - fill_in :wiki_title, with: path - fill_in :wiki_content, with: content - - click_button 'Create page' - end -end diff --git a/spec/features/projects/wiki/shortcuts_spec.rb b/spec/features/projects/wiki/shortcuts_spec.rb deleted file mode 100644 index 170e7afb51f..00000000000 --- a/spec/features/projects/wiki/shortcuts_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Wiki shortcuts', :js do - let(:user) { create(:user) } - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: 'Home page') } - - before do - sign_in(user) - visit project_wiki_path(project, wiki_page) - end - - it 'Visit edit wiki page using "e" keyboard shortcut' do - find('body').native.send_key('e') - - expect(find('.wiki-page-title')).to have_content('Edit Page') - end -end diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb deleted file mode 100644 index eba1b63765a..00000000000 --- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb +++ /dev/null @@ -1,360 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -RSpec.describe "User creates wiki page" do - include WikiHelpers - - let(:user) { create(:user) } - let(:wiki) { ProjectWiki.new(project, user) } - let(:project) { create(:project) } - - before do - project.add_maintainer(user) - - sign_in(user) - end - - context "when wiki is empty" do - before do |example| - visit(project_wikis_path(project)) - - wait_for_svg_to_be_loaded(example) - - click_link "Create your first page" - end - - context "in a user namespace" do - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - - it "shows validation error message" do - page.within(".wiki-form") do - fill_in(:wiki_content, with: "") - - click_on("Create page") - end - - expect(page).to have_content("The form contains the following error:").and have_content("Content can't be blank") - - page.within(".wiki-form") do - fill_in(:wiki_content, with: "[link test](test)") - - click_on("Create page") - end - - expect(page).to have_content("Home").and have_content("link test") - - click_link("link test") - - expect(page).to have_content("Create New Page") - end - - it "shows non-escaped link in the pages list" do - fill_in(:wiki_title, with: "one/two/three-test") - - page.within(".wiki-form") do - fill_in(:wiki_content, with: "wiki content") - - click_on("Create page") - end - - expect(current_path).to include("one/two/three-test") - expect(page).to have_xpath("//a[@href='/#{project.full_path}/-/wikis/one/two/three-test']") - end - - it "has `Create home` as a commit message", :js do - wait_for_requests - - expect(page).to have_field("wiki[message]", with: "Create home") - end - - it "creates a page from the home page" do - fill_in(:wiki_content, with: "[test](test)\n[GitLab API doc](api)\n[Rake tasks](raketasks)\n# Wiki header\n") - fill_in(:wiki_message, with: "Adding links to wiki") - - page.within(".wiki-form") do - click_button("Create page") - end - - expect(current_path).to eq(project_wiki_path(project, "home")) - expect(page).to have_content("test GitLab API doc Rake tasks Wiki header") - .and have_content("Home") - .and have_content("Last edited by #{user.name}") - .and have_header_with_correct_id_and_link(1, "Wiki header", "wiki-header") - - click_link("test") - - expect(current_path).to eq(project_wiki_path(project, "test")) - - page.within(:css, ".nav-text") do - expect(page).to have_content("Create New Page") - end - - click_link("Home") - - expect(current_path).to eq(project_wiki_path(project, "home")) - - click_link("GitLab API") - - expect(current_path).to eq(project_wiki_path(project, "api")) - - page.within(:css, ".nav-text") do - expect(page).to have_content("Create") - end - - click_link("Home") - - expect(current_path).to eq(project_wiki_path(project, "home")) - - click_link("Rake tasks") - - expect(current_path).to eq(project_wiki_path(project, "raketasks")) - - page.within(:css, ".nav-text") do - expect(page).to have_content("Create") - end - end - - it "creates ASCII wiki with LaTeX blocks", :js do - stub_application_setting(plantuml_url: "http://localhost", plantuml_enabled: true) - - ascii_content = <<~MD - :stem: latexmath - - [stem] - ++++ - \\sqrt{4} = 2 - ++++ - - another part - - [latexmath] - ++++ - \\beta_x \\gamma - ++++ - - stem:[2+2] is 4 - MD - - find("#wiki_format option[value=asciidoc]").select_option - - fill_in(:wiki_content, with: ascii_content) - - page.within(".wiki-form") do - click_button("Create page") - end - - page.within ".md" do - expect(page).to have_selector(".katex", count: 3).and have_content("2+2 is 4") - end - end - - it 'creates a wiki page with Org markup', :aggregate_failures do - org_content = <<~ORG - * Heading - ** Subheading - [[home][Link to Home]] - ORG - - page.within('.wiki-form') do - find('#wiki_format option[value=org]').select_option - fill_in(:wiki_content, with: org_content) - click_button('Create page') - end - - expect(page).to have_selector('h1', text: 'Heading') - expect(page).to have_selector('h2', text: 'Subheading') - expect(page).to have_link('Link to Home', href: "/#{project.full_path}/-/wikis/home") - end - - it_behaves_like 'wiki file attachments' - end - - context "in a group namespace", :js do - let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } - - it "has `Create home` as a commit message" do - wait_for_requests - - expect(page).to have_field("wiki[message]", with: "Create home") - end - - it "creates a page from the home page" do - page.within(".wiki-form") do - fill_in(:wiki_content, with: "My awesome wiki!") - - click_button("Create page") - end - - expect(page).to have_content("Home") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end - end - end - - context "when wiki is not empty", :js do - before do - create(:wiki_page, wiki: wiki, title: 'home', content: 'Home page') - - visit(project_wikis_path(project)) - end - - context "in a user namespace" do - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - - context "via the `new wiki page` page" do - it "creates a page with a single word" do - click_link("New page") - - page.within(".wiki-form") do - fill_in(:wiki_title, with: "foo") - fill_in(:wiki_content, with: "My awesome wiki!") - end - - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create foo") - - click_button("Create page") - - expect(page).to have_content("foo") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end - - it "creates a page with spaces in the name" do - click_link("New page") - - page.within(".wiki-form") do - fill_in(:wiki_title, with: "Spaces in the name") - fill_in(:wiki_content, with: "My awesome wiki!") - end - - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create Spaces in the name") - - click_button("Create page") - - expect(page).to have_content("Spaces in the name") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end - - it "creates a page with hyphens in the name" do - click_link("New page") - - page.within(".wiki-form") do - fill_in(:wiki_title, with: "hyphens-in-the-name") - fill_in(:wiki_content, with: "My awesome wiki!") - end - - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create hyphens in the name") - - page.within(".wiki-form") do - fill_in(:wiki_content, with: "My awesome wiki!") - - click_button("Create page") - end - - expect(page).to have_content("hyphens in the name") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end - end - - it "shows the emoji autocompletion dropdown" do - click_link("New page") - - page.within(".wiki-form") do - find("#wiki_content").native.send_keys("") - - fill_in(:wiki_content, with: ":") - end - - expect(page).to have_selector(".atwho-view") - end - end - - context "in a group namespace" do - let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } - - context "via the `new wiki page` page" do - it "creates a page" do - click_link("New page") - - page.within(".wiki-form") do - fill_in(:wiki_title, with: "foo") - fill_in(:wiki_content, with: "My awesome wiki!") - end - - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create foo") - - click_button("Create page") - - expect(page).to have_content("foo") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end - end - end - end - - describe 'sidebar feature' do - context 'when there are some existing pages' do - before do - create(:wiki_page, wiki: wiki, title: 'home', content: 'home') - create(:wiki_page, wiki: wiki, title: 'another', content: 'another') - end - - it 'renders a default sidebar when there is no customized sidebar' do - visit(project_wikis_path(project)) - - expect(page).to have_content('another') - expect(page).not_to have_link('View All Pages') - end - - context 'when there is a customized sidebar' do - before do - create(:wiki_page, wiki: wiki, title: '_sidebar', content: 'My customized sidebar') - end - - it 'renders my customized sidebar instead of the default one' do - visit(project_wikis_path(project)) - - expect(page).to have_content('My customized sidebar') - expect(page).not_to have_content('Another') - end - end - end - - context 'when there are 15 existing pages' do - before do - (1..5).each { |i| create(:wiki_page, wiki: wiki, title: "my page #{i}") } - (6..10).each { |i| create(:wiki_page, wiki: wiki, title: "parent/my page #{i}") } - (11..15).each { |i| create(:wiki_page, wiki: wiki, title: "grandparent/parent/my page #{i}") } - end - - it 'shows all pages in the sidebar' do - visit(project_wikis_path(project)) - - (1..15).each { |i| expect(page).to have_content("my page #{i}") } - expect(page).not_to have_link('View All Pages') - end - - context 'when there are more than 15 existing pages' do - before do - create(:wiki_page, wiki: wiki, title: 'my page 16') - end - - it 'shows the first 15 pages in the sidebar' do - visit(project_wikis_path(project)) - - expect(page).to have_text('my page', count: 15) - expect(page).to have_link('View All Pages') - end - end - end - end -end diff --git a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb deleted file mode 100644 index a5d865d581b..00000000000 --- a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'User deletes wiki page', :js do - let(:user) { create(:user) } - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - let(:wiki_page) { create(:wiki_page, wiki: project.wiki) } - - before do - sign_in(user) - visit(project_wiki_path(project, wiki_page)) - end - - it 'deletes a page' do - click_on('Edit') - click_on('Delete') - find('.modal-footer .btn-danger').click - - expect(page).to have_content('Page was successfully deleted') - end -end diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb deleted file mode 100644 index fdab63a56b8..00000000000 --- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb +++ /dev/null @@ -1,263 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'User updates wiki page' do - include WikiHelpers - - let(:user) { create(:user) } - - before do - project.add_maintainer(user) - sign_in(user) - end - - context 'when wiki is empty' do - before do |example| - visit(project_wikis_path(project)) - - wait_for_svg_to_be_loaded(example) - - click_link "Create your first page" - end - - context 'in a user namespace' do - let(:project) { create(:project, :wiki_repo) } - - it 'redirects back to the home edit page' do - page.within(:css, '.wiki-form .form-actions') do - click_on('Cancel') - end - - expect(current_path).to eq wiki_path(project.wiki) - end - - it 'updates a page that has a path', :js do - fill_in(:wiki_title, with: 'one/two/three-test') - - page.within '.wiki-form' do - fill_in(:wiki_content, with: 'wiki content') - click_on('Create page') - end - - expect(current_path).to include('one/two/three-test') - expect(find('.wiki-pages')).to have_content('three') - - first(:link, text: 'three').click - - expect(find('.nav-text')).to have_content('three') - - click_on('Edit') - - expect(current_path).to include('one/two/three-test') - expect(page).to have_content('Edit Page') - - fill_in('Content', with: 'Updated Wiki Content') - click_on('Save changes') - - expect(page).to have_content('Updated Wiki Content') - end - - it_behaves_like 'wiki file attachments' - end - end - - context 'when wiki is not empty' do - let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) } - let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, title: 'home', content: 'Home page') } - - before do - visit(project_wikis_path(project)) - - click_link('Edit') - end - - context 'in a user namespace' do - let(:project) { create(:project, :wiki_repo) } - - it 'updates a page', :js do - # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Update home') - - fill_in(:wiki_content, with: 'My awesome wiki!') - click_button('Save changes') - - expect(page).to have_content('Home') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') - end - - it 'updates the commit message as the title is changed', :js do - fill_in(:wiki_title, with: '& < > \ \ { } &') - - expect(page).to have_field('wiki[message]', with: 'Update & < > \ \ { } &') - end - - it 'correctly escapes the commit message entities', :js do - fill_in(:wiki_title, with: 'Wiki title') - - expect(page).to have_field('wiki[message]', with: 'Update Wiki title') - end - - it 'shows a validation error message' do - fill_in(:wiki_content, with: '') - click_button('Save changes') - - expect(page).to have_selector('.wiki-form') - expect(page).to have_content('Edit Page') - expect(page).to have_content('The form contains the following error:') - expect(page).to have_content("Content can't be blank") - expect(find('textarea#wiki_content').value).to eq('') - end - - it 'shows the emoji autocompletion dropdown', :js do - find('#wiki_content').native.send_keys('') - fill_in(:wiki_content, with: ':') - - expect(page).to have_selector('.atwho-view') - end - - it 'shows the error message' do - wiki_page.update(content: 'Update') - - click_button('Save changes') - - expect(page).to have_content('Someone edited the page the same time you did.') - end - - it 'updates a page' do - fill_in('Content', with: 'Updated Wiki Content') - click_on('Save changes') - - expect(page).to have_content('Updated Wiki Content') - end - - it 'cancels editing of a page' do - page.within(:css, '.wiki-form .form-actions') do - click_on('Cancel') - end - - expect(current_path).to eq(project_wiki_path(project, wiki_page)) - end - - it_behaves_like 'wiki file attachments' - end - - context 'in a group namespace' do - let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } - - it 'updates a page', :js do - # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Update home') - - fill_in(:wiki_content, with: 'My awesome wiki!') - - click_button('Save changes') - - expect(page).to have_content('Home') - expect(page).to have_content("Last edited by #{user.name}") - expect(page).to have_content('My awesome wiki!') - end - - it_behaves_like 'wiki file attachments' - end - end - - context 'when the page is in a subdir' do - let!(:project) { create(:project, :wiki_repo) } - let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) } - let(:page_name) { 'page_name' } - let(:page_dir) { "foo/bar/#{page_name}" } - let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, title: page_dir, content: 'Home page') } - - before do - visit(project_wiki_edit_path(project, wiki_page)) - end - - it 'moves the page to the root folder' do - fill_in(:wiki_title, with: "/#{page_name}") - - click_button('Save changes') - - expect(current_path).to eq(project_wiki_path(project, page_name)) - end - - it 'moves the page to other dir' do - new_page_dir = "foo1/bar1/#{page_name}" - - fill_in(:wiki_title, with: new_page_dir) - - click_button('Save changes') - - expect(current_path).to eq(project_wiki_path(project, new_page_dir)) - end - - it 'remains in the same place if title has not changed' do - original_path = project_wiki_path(project, wiki_page) - - fill_in(:wiki_title, with: page_name) - - click_button('Save changes') - - expect(current_path).to eq(original_path) - end - - it 'can be moved to a different dir with a different name' do - new_page_dir = "foo1/bar1/new_page_name" - - fill_in(:wiki_title, with: new_page_dir) - - click_button('Save changes') - - expect(current_path).to eq(project_wiki_path(project, new_page_dir)) - end - - it 'can be renamed and moved to the root folder' do - new_name = 'new_page_name' - - fill_in(:wiki_title, with: "/#{new_name}") - - click_button('Save changes') - - expect(current_path).to eq(project_wiki_path(project, new_name)) - end - - it 'squishes the title before creating the page' do - new_page_dir = " foo1 / bar1 / #{page_name} " - - fill_in(:wiki_title, with: new_page_dir) - - click_button('Save changes') - - expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}")) - end - - it_behaves_like 'wiki file attachments' - end - - context 'when an existing page exceeds the content size limit' do - let_it_be(:project) { create(:project, :wiki_repo) } - let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, content: "one\ntwo\nthree") } - - before do - stub_application_setting(wiki_page_max_content_bytes: 10) - - visit wiki_page_path(wiki_page.wiki, wiki_page, action: :edit) - end - - it 'allows changing the title if the content does not change' do - fill_in 'Title', with: 'new title' - click_on 'Save changes' - - expect(page).to have_content('Wiki was successfully updated.') - end - - it 'shows a validation error when trying to change the content' do - fill_in 'Content', with: 'new content' - click_on 'Save changes' - - expect(page).to have_content('The form contains the following error:') - expect(page).to have_content('Content is too long (11 Bytes). The maximum size is 10 Bytes.') - end - end -end diff --git a/spec/features/projects/wiki/user_views_wiki_empty_spec.rb b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb index 0af40a2d760..1f460f39267 100644 --- a/spec/features/projects/wiki/user_views_wiki_empty_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb @@ -2,108 +2,86 @@ require 'spec_helper' -RSpec.describe 'User views empty wiki' do - let(:user) { create(:user) } - let(:confluence_link) { 'Enable the Confluence Wiki integration' } - let(:element) { page.find('.row.empty-state') } - - shared_examples 'empty wiki and accessible issues' do - it 'show "issue tracker" message' do - visit(project_wikis_path(project)) - - expect(element).to have_content('This project has no wiki pages') - expect(element).to have_content('You must be a project member') - expect(element).to have_content('improve the wiki for this project') - expect(element).to have_link("issue tracker", href: project_issues_path(project)) - expect(element).to have_link("Suggest wiki improvement", href: new_project_issue_path(project)) - expect(element).to have_no_link(confluence_link) - end - end - - shared_examples 'empty wiki and non-accessible issues' do - it 'does not show "issue tracker" message' do - visit(project_wikis_path(project)) +RSpec.describe 'Project > User views empty wiki' do + let_it_be(:user) { create(:user) } - expect(element).to have_content('This project has no wiki pages') - expect(element).to have_content('You must be a project member') - expect(element).to have_no_link('Suggest wiki improvement') - expect(element).to have_no_link(confluence_link) - end - end + let(:wiki) { create(:project_wiki, project: project) } - context 'when user is logged out and issue tracker is public' do - let(:project) { create(:project, :public, :wiki_repo) } + it_behaves_like 'User views empty wiki' do + context 'when project is public' do + let(:project) { create(:project, :public) } - it_behaves_like 'empty wiki and accessible issues' - end + it_behaves_like 'empty wiki message', issuable: true - context 'when user is logged in and not a member' do - let(:project) { create(:project, :public, :wiki_repo) } + context 'when issue tracker is private' do + let(:project) { create(:project, :public, :issues_private) } - before do - sign_in(user) - end + it_behaves_like 'empty wiki message', issuable: false + end - it_behaves_like 'empty wiki and accessible issues' - end + context 'when issue tracker is disabled' do + let(:project) { create(:project, :public, :issues_disabled) } - context 'when issue tracker is private' do - let(:project) { create(:project, :public, :wiki_repo, :issues_private) } + it_behaves_like 'empty wiki message', issuable: false + end - it_behaves_like 'empty wiki and non-accessible issues' - end + context 'and user is logged in' do + before do + sign_in(user) + end - context 'when issue tracker is disabled' do - let(:project) { create(:project, :public, :wiki_repo, :issues_disabled) } + context 'and user is not a member' do + it_behaves_like 'empty wiki message', issuable: true + end - it_behaves_like 'empty wiki and non-accessible issues' - end + context 'and user is a member' do + before do + project.add_developer(user) + end - context 'when user is logged in and a member' do - let(:project) { create(:project, :public) } - - before do - sign_in(user) - project.add_developer(user) + it_behaves_like 'empty wiki message', writable: true, issuable: true + end + end end - it 'shows "create first page" message' do - visit(project_wikis_path(project)) - - expect(element).to have_content('your project', count: 2) + context 'when project is private' do + let(:project) { create(:project, :private) } - element.click_link 'Create your first page' + it_behaves_like 'wiki is not found' - expect(page).to have_button('Create page') - end + context 'and user is logged in' do + before do + sign_in(user) + end - it 'does not show the "enable confluence" button' do - visit(project_wikis_path(project)) + context 'and user is not a member' do + it_behaves_like 'wiki is not found' + end - expect(element).to have_no_link(confluence_link) - end - end + context 'and user is a member' do + before do + project.add_developer(user) + end - context 'when user is logged in and an admin' do - let(:project) { create(:project, :public, :wiki_repo) } + it_behaves_like 'empty wiki message', writable: true, issuable: true + end - before do - sign_in(user) - project.add_maintainer(user) - end - - it 'shows the "enable confluence" button' do - visit(project_wikis_path(project)) - - expect(element).to have_link(confluence_link) - end + context 'and user is a maintainer' do + before do + project.add_maintainer(user) + end - it 'does not show "enable confluence" button if confluence is already enabled' do - create(:confluence_service, project: project) + it_behaves_like 'empty wiki message', writable: true, issuable: true, confluence: true - visit(project_wikis_path(project)) + context 'and Confluence is already enabled' do + before do + create(:confluence_service, project: project) + end - expect(element).to have_no_link(confluence_link) + it_behaves_like 'empty wiki message', writable: true, issuable: true, confluence: false + end + end + end end end end diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb deleted file mode 100644 index e93689af0aa..00000000000 --- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb +++ /dev/null @@ -1,276 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'User views a wiki page' do - include WikiHelpers - - let(:user) { create(:user) } - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - let(:path) { 'image.png' } - let(:wiki) { project.wiki } - let(:wiki_page) do - create(:wiki_page, - wiki: wiki, - title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})") - end - - before do - project.add_maintainer(user) - sign_in(user) - end - - context 'when wiki is empty', :js do - before do - visit project_wikis_path(project) - - wait_for_svg_to_be_loaded - - click_link "Create your first page" - - fill_in(:wiki_title, with: 'one/two/three-test') - - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'wiki content') - click_on('Create page') - end - - expect(page).to have_content('Wiki was successfully updated.') - end - - it 'shows the history of a page that has a path' do - expect(current_path).to include('one/two/three-test') - - first(:link, text: 'three').click - click_on('Page history') - - expect(current_path).to include('one/two/three-test') - - page.within(:css, '.nav-text') do - expect(page).to have_content('History') - end - end - - it 'shows an old version of a page' do - expect(current_path).to include('one/two/three-test') - expect(find('.wiki-pages')).to have_content('three') - - first(:link, text: 'three').click - - expect(find('.nav-text')).to have_content('three') - - click_on('Edit') - - expect(current_path).to include('one/two/three-test') - expect(page).to have_content('Edit Page') - - fill_in('Content', with: 'Updated Wiki Content') - click_on('Save changes') - - expect(page).to have_content('Wiki was successfully updated.') - - click_on('Page history') - - within('.nav-text') do - expect(page).to have_content('History') - end - - within('.wiki-history') do - expect(page).to have_css('a[href*="?version_id"]', count: 4) - end - end - end - - context 'when a page does not have history' do - before do - visit(project_wiki_path(project, wiki_page)) - end - - it 'shows all the pages' do - expect(page).to have_content(user.name) - expect(find('.wiki-pages')).to have_content(wiki_page.title.capitalize) - end - - context 'shows a file stored in a page' do - let(:path) { upload_file_to_wiki(project, user, 'dk.png') } - - it do - expect(page).to have_xpath("//img[@data-src='#{wiki.wiki_base_path}/#{path}']") - expect(page).to have_link('image', href: "#{wiki.wiki_base_path}/#{path}") - - click_on('image') - - expect(current_path).to match("wikis/#{path}") - expect(page).not_to have_xpath('/html') # Page should render the image which means there is no html involved - end - end - - it 'shows the creation page if file does not exist' do - expect(page).to have_link('image', href: "#{wiki.wiki_base_path}/#{path}") - - click_on('image') - - expect(current_path).to match("wikis/#{path}") - expect(page).to have_content('Create New Page') - end - end - - context 'when a page has history' do - before do - wiki_page.update(message: 'updated home', content: 'updated [some link](other-page)') # rubocop:disable Rails/SaveBang - end - - it 'shows the page history' do - visit(project_wiki_path(project, wiki_page)) - - expect(page).to have_selector('a.btn', text: 'Edit') - - click_on('Page history') - - expect(page).to have_content(user.name) - expect(page).to have_content("#{user.username} created page: home") - expect(page).to have_content('updated home') - end - - it 'does not show the "Edit" button' do - visit(project_wiki_path(project, wiki_page, version_id: wiki_page.versions.last.id)) - - expect(page).not_to have_selector('a.btn', text: 'Edit') - end - - context 'show the diff' do - def expect_diff_links(commit) - diff_path = wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) - - expect(page).to have_link('Hide whitespace changes', href: "#{diff_path}&w=1") - expect(page).to have_link('Inline', href: "#{diff_path}&view=inline") - expect(page).to have_link('Side-by-side', href: "#{diff_path}&view=parallel") - expect(page).to have_link("View page @ #{commit.short_id}", href: wiki_page_path(wiki, wiki_page, version_id: commit)) - expect(page).to have_css('.diff-file[data-blob-diff-path="%s"]' % diff_path) - end - - it 'links to the correct diffs' do - visit project_wiki_history_path(project, wiki_page) - - commit1 = wiki.commit('HEAD^') - commit2 = wiki.commit - - expect(page).to have_link('created page: home', href: wiki_page_path(wiki, wiki_page, version_id: commit1, action: :diff)) - expect(page).to have_link('updated home', href: wiki_page_path(wiki, wiki_page, version_id: commit2, action: :diff)) - end - - it 'between the current and the previous version of a page' do - commit = wiki.commit - visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) - - expect(page).to have_content('by John Doe') - expect(page).to have_content('updated home') - expect(page).to have_content('Showing 1 changed file with 1 addition and 3 deletions') - expect(page).to have_content('some link') - - expect_diff_links(commit) - end - - it 'between two old versions of a page' do - wiki_page.update(message: 'latest home change', content: 'updated [another link](other-page)') # rubocop:disable Rails/SaveBang: - commit = wiki.commit('HEAD^') - visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) - - expect(page).to have_content('by John Doe') - expect(page).to have_content('updated home') - expect(page).to have_content('Showing 1 changed file with 1 addition and 3 deletions') - expect(page).to have_content('some link') - expect(page).not_to have_content('latest home change') - expect(page).not_to have_content('another link') - - expect_diff_links(commit) - end - - it 'for the oldest version of a page' do - commit = wiki.commit('HEAD^') - visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) - - expect(page).to have_content('by John Doe') - expect(page).to have_content('created page: home') - expect(page).to have_content('Showing 1 changed file with 4 additions and 0 deletions') - expect(page).to have_content('Look at this') - - expect_diff_links(commit) - end - end - end - - context 'when a page has special characters in its title' do - let(:title) { '<foo> !@#$%^&*()[]{}=_+\'"\\|<>? <bar>' } - - before do - wiki_page.update(title: title ) # rubocop:disable Rails/SaveBang - end - - it 'preserves the special characters' do - visit(project_wiki_path(project, wiki_page)) - - expect(page).to have_css('.wiki-page-title', text: title) - expect(page).to have_css('.wiki-pages li', text: title) - end - end - - context 'when a page has XSS in its title or content' do - let(:title) { '<script>alert("title")<script>' } - - before do - wiki_page.update(title: title, content: 'foo <script>alert("content")</script> bar') # rubocop:disable Rails/SaveBang - end - - it 'safely displays the page' do - visit(project_wiki_path(project, wiki_page)) - - expect(page).to have_css('.wiki-page-title', text: title) - expect(page).to have_content('foo bar') - end - end - - context 'when a page has XSS in its message' do - before do - wiki_page.update(message: '<script>alert(true)<script>', content: 'XSS update') # rubocop:disable Rails/SaveBang - end - - it 'safely displays the message' do - visit(project_wiki_history_path(project, wiki_page)) - - expect(page).to have_content('<script>alert(true)<script>') - end - end - - context 'when page has invalid content encoding' do - let(:content) { (+'whatever').force_encoding('ISO-8859-1') } - - before do - allow(Gitlab::EncodingHelper).to receive(:encode!).and_return(content) - - visit(project_wiki_path(project, wiki_page)) - end - - it 'does not show "Edit" button' do - expect(page).not_to have_selector('a.btn', text: 'Edit') - end - - it 'shows error' do - page.within(:css, '.flash-notice') do - expect(page).to have_content('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.') - end - end - end - - it 'opens a default wiki page', :js do - visit project_path(project) - - find('.shortcuts-wiki').click - - wait_for_svg_to_be_loaded - - click_link "Create your first page" - - expect(page).to have_content('Create New Page') - end -end diff --git a/spec/features/projects/wiki/user_views_wiki_pages_spec.rb b/spec/features/projects/wiki/user_views_wiki_pages_spec.rb deleted file mode 100644 index 4f29ae0cc8a..00000000000 --- a/spec/features/projects/wiki/user_views_wiki_pages_spec.rb +++ /dev/null @@ -1,91 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'User views wiki pages' do - include WikiHelpers - - let(:user) { create(:user) } - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - - let!(:wiki_page1) do - create(:wiki_page, wiki: project.wiki, title: '3 home', content: '3') - end - - let!(:wiki_page2) do - create(:wiki_page, wiki: project.wiki, title: '1 home', content: '1') - end - - let!(:wiki_page3) do - create(:wiki_page, wiki: project.wiki, title: '2 home', content: '2') - end - - let(:pages) do - page.find('.wiki-pages-list').all('li').map { |li| li.find('a') } - end - - before do - project.add_maintainer(user) - sign_in(user) - visit(project_wikis_pages_path(project)) - end - - context 'ordered by title' do - let(:pages_ordered_by_title) { [wiki_page2, wiki_page3, wiki_page1] } - - context 'asc' do - it 'pages are displayed in direct order' do - pages.each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_title[index].title) - end - end - end - - context 'desc' do - before do - page.within('.wiki-sort-dropdown') do - page.find('.rspec-reverse-sort').click - end - end - - it 'pages are displayed in reversed order' do - pages.reverse_each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_title[index].title) - end - end - end - end - - context 'ordered by created_at' do - let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3] } - - before do - page.within('.wiki-sort-dropdown') do - click_button('Title') - click_link('Created date') - end - end - - context 'asc' do - it 'pages are displayed in direct order' do - pages.each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_created_at[index].title) - end - end - end - - context 'desc' do - before do - page.within('.wiki-sort-dropdown') do - page.find('.rspec-reverse-sort').click - end - end - - it 'pages are displayed in reversed order' do - pages.reverse_each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_created_at[index].title) - end - end - end - end -end diff --git a/spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb b/spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb deleted file mode 100644 index 5c45e34595f..00000000000 --- a/spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb +++ /dev/null @@ -1,79 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'User views AsciiDoc page with includes', :js do - let_it_be(:user) { create(:user) } - let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' } - let(:project) { create(:project, :public, :wiki_repo) } - let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')} - let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") } - - def create_wiki_page(title, content:) - attrs = { - title: title, - content: content, - format: :asciidoc - } - - create(:wiki_page, wiki: project.wiki, **attrs) - end - - before do - sign_in(user) - end - - context 'when the file being included exists' do - it 'includes the file contents' do - visit(project_wiki_path(project, wiki_page)) - - page.within(:css, wiki_content_selector) do - expect(page).to have_content('Content from the main page. Content from the included page') - end - end - - context 'when there are multiple versions of the wiki pages' do - before do - included_wiki_page.update(message: 'updated included file', content: 'Updated content from the included page') - wiki_page.update(message: 'updated wiki page', content: "Updated content from the main page.\ninclude::included_page.asciidoc[]") - end - - let(:latest_version_id) { wiki_page.versions.first.id } - let(:oldest_version_id) { wiki_page.versions.last.id } - - context 'viewing the latest version' do - it 'includes the latest content' do - visit(project_wiki_path(project, wiki_page, version_id: latest_version_id)) - - page.within(:css, wiki_content_selector) do - expect(page).to have_content('Updated content from the main page. Updated content from the included page') - end - end - end - - context 'viewing the original version' do - it 'includes the content from the original version' do - visit(project_wiki_path(project, wiki_page, version_id: oldest_version_id)) - - page.within(:css, wiki_content_selector) do - expect(page).to have_content('Content from the main page. Content from the included page') - end - end - end - end - end - - context 'when the file being included does not exist' do - before do - included_wiki_page.delete - end - - it 'outputs an error' do - visit(project_wiki_path(project, wiki_page)) - - page.within(:css, wiki_content_selector) do - expect(page).to have_content('Content from the main page. [ERROR: include::included_page.asciidoc[] - unresolved directive]') - end - end - end -end diff --git a/spec/features/projects/wikis_spec.rb b/spec/features/projects/wikis_spec.rb new file mode 100644 index 00000000000..1c66ad81145 --- /dev/null +++ b/spec/features/projects/wikis_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe 'Project wikis' do + let_it_be(:user) { create(:user) } + + let(:wiki) { create(:project_wiki, user: user, project: project) } + let(:project) { create(:project, namespace: user.namespace, creator: user) } + + it_behaves_like 'User creates wiki page' + it_behaves_like 'User deletes wiki page' + it_behaves_like 'User previews wiki changes' + it_behaves_like 'User updates wiki page' + it_behaves_like 'User uses wiki shortcuts' + it_behaves_like 'User views AsciiDoc page with includes' + it_behaves_like 'User views a wiki page' + it_behaves_like 'User views wiki pages' + it_behaves_like 'User views wiki sidebar' +end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 970500985ae..6c1e1eab968 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -99,6 +99,15 @@ RSpec.describe 'Project' do expect(page).to have_css('.home-panel-description .is-expanded') end end + + context 'page description' do + before do + project.update_attribute(:description, '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') + visit path + end + + it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet' + end end describe 'project topics' do diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb index f0707610c3f..d8d9ccb5c6f 100644 --- a/spec/features/protected_branches_spec.rb +++ b/spec/features/protected_branches_spec.rb @@ -9,6 +9,10 @@ RSpec.describe 'Protected Branches', :js do let(:admin) { create(:admin) } let(:project) { create(:project, :repository) } + before do + stub_feature_flags(deploy_keys_on_protected_branches: false) + end + context 'logged in as developer' do before do project.add_developer(user) @@ -163,4 +167,14 @@ RSpec.describe 'Protected Branches', :js do include_examples "protected branches > access control > CE" end end + + context 'when the users for protected branches feature is off' do + before do + stub_licensed_features(protected_refs_for_users: false) + end + + include_examples 'when the deploy_keys_on_protected_branches FF is turned on' do + let(:all_dropdown_sections) { %w(Roles Deploy\ Keys) } + end + end end diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb index 227e75088d2..a88043c98ac 100644 --- a/spec/features/search/user_searches_for_code_spec.rb +++ b/spec/features/search/user_searches_for_code_spec.rb @@ -21,6 +21,7 @@ RSpec.describe 'User searches for code' do expect(page).to have_selector('.results', text: 'application.js') expect(page).to have_selector('.file-content .code') expect(page).to have_selector("span.line[lang='javascript']") + expect(page).to have_link('application.js', href: /master\/files\/js\/application.js/) end context 'when on a project page', :js do diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb index cfda25b9ab4..5cbfacf4e48 100644 --- a/spec/features/search/user_uses_header_search_field_spec.rb +++ b/spec/features/search/user_uses_header_search_field_spec.rb @@ -30,6 +30,8 @@ RSpec.describe 'User uses header search field', :js do before do find('#search') find('body').native.send_keys('s') + + wait_for_all_requests end it 'shows the category search dropdown' do @@ -89,9 +91,7 @@ RSpec.describe 'User uses header search field', :js do context 'when entering text into the search field' do it 'does not display the category search dropdown' do - page.within('.search-input-wrap') do - fill_in('search', with: scope_name.first(4)) - end + fill_in_search(scope_name.first(4)) expect(page).not_to have_selector('.dropdown-header', text: /#{scope_name}/i) end @@ -105,9 +105,7 @@ RSpec.describe 'User uses header search field', :js do end it 'displays search options' do - page.within('.search-input-wrap') do - fill_in('search', with: 'test') - end + fill_in_search('test') expect(page).to have_selector(scoped_search_link('test')) end @@ -140,9 +138,7 @@ RSpec.describe 'User uses header search field', :js do end it 'displays search options' do - page.within('.search-input-wrap') do - fill_in('search', with: 'test') - end + fill_in_search('test') expect(page).to have_selector(scoped_search_link('test')) expect(page).to have_selector(scoped_search_link('test', group_id: group.id)) @@ -157,9 +153,7 @@ RSpec.describe 'User uses header search field', :js do end it 'displays search options' do - page.within('.search-input-wrap') do - fill_in('search', with: 'test') - end + fill_in_search('test') expect(page).to have_selector(scoped_search_link('test')) expect(page).not_to have_selector(scoped_search_link('test', group_id: project.namespace_id)) @@ -182,9 +176,7 @@ RSpec.describe 'User uses header search field', :js do end it 'displays search options' do - page.within('.search-input-wrap') do - fill_in('search', with: 'test') - end + fill_in_search('test') expect(page).to have_selector(scoped_search_link('test')) expect(page).to have_selector(scoped_search_link('test', group_id: group.id)) @@ -208,9 +200,7 @@ RSpec.describe 'User uses header search field', :js do end it 'displays search options' do - page.within('.search-input-wrap') do - fill_in('search', with: 'test') - end + fill_in_search('test') expect(page).to have_selector(scoped_search_link('test')) expect(page).to have_selector(scoped_search_link('test', group_id: subgroup.id)) diff --git a/spec/features/static_site_editor_spec.rb b/spec/features/static_site_editor_spec.rb index b67e47b6ac4..03085917d67 100644 --- a/spec/features/static_site_editor_spec.rb +++ b/spec/features/static_site_editor_spec.rb @@ -6,18 +6,71 @@ RSpec.describe 'Static Site Editor' do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :public, :repository) } + let(:sse_path) { project_show_sse_path(project, 'master/README.md') } + + before_all do + project.add_developer(user) + end + before do - project.add_maintainer(user) sign_in(user) + end + + context "when no config file is present" do + before do + visit sse_path + end - visit project_show_sse_path(project, 'master/README.md') + it 'renders SSE page with all generated config values and default config file values' do + node = page.find('#static-site-editor') + + # assert generated config values are present + expect(node['data-base-url']).to eq("/#{project.full_path}/-/sse/master%2FREADME.md") + expect(node['data-branch']).to eq('master') + expect(node['data-commit-id']).to match(/\A[0-9a-f]{40}\z/) + expect(node['data-is-supported-content']).to eq('true') + expect(node['data-merge-requests-illustration-path']) + .to match(%r{/assets/illustrations/merge_requests-.*\.svg}) + expect(node['data-namespace']).to eq(project.namespace.full_path) + expect(node['data-project']).to eq(project.path) + expect(node['data-project-id']).to eq(project.id.to_s) + + # assert default config file values are present + expect(node['data-image-upload-path']).to eq('source/images') + expect(node['data-mounts']).to eq('[{"source":"source","target":""}]') + expect(node['data-static-site-generator']).to eq('middleman') + end end - it 'renders Static Site Editor page with generated and file attributes' do - # assert generated config value is present - expect(page).to have_css('#static-site-editor[data-branch="master"]') + context "when a config file is present" do + let(:config_file_yml) do + <<~YAML + image_upload_path: custom-image-upload-path + mounts: + - source: source1 + target: "" + - source: source2 + target: target2 + static_site_generator: middleman + YAML + end + + before do + allow_next_instance_of(Repository) do |repository| + allow(repository).to receive(:blob_data_at).and_return(config_file_yml) + end + + visit sse_path + end + + it 'renders Static Site Editor page values read from config file' do + node = page.find('#static-site-editor') - # assert file config value is present - expect(page).to have_css('#static-site-editor[data-static-site-generator="middleman"]') + # assert user-specified config file values are present + expected_mounts = '[{"source":"source1","target":""},{"source":"source2","target":"target2"}]' + expect(node['data-image-upload-path']).to eq('custom-image-upload-path') + expect(node['data-mounts']).to eq(expected_mounts) + expect(node['data-static-site-generator']).to eq('middleman') + end end end diff --git a/spec/features/tags/developer_deletes_tag_spec.rb b/spec/features/tags/developer_deletes_tag_spec.rb index de9296bc08e..7c4c6f54685 100644 --- a/spec/features/tags/developer_deletes_tag_spec.rb +++ b/spec/features/tags/developer_deletes_tag_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Developer deletes tag' do +RSpec.describe 'Developer deletes tag', :js do let(:user) { create(:user) } let(:group) { create(:group) } let(:project) { create(:project, :repository, namespace: group) } @@ -13,11 +13,12 @@ RSpec.describe 'Developer deletes tag' do visit project_tags_path(project) end - context 'from the tags list page', :js do + context 'from the tags list page' do it 'deletes the tag' do expect(page).to have_content 'v1.1.0' - delete_tag 'v1.1.0' + container = page.find('.content .flex-row', text: 'v1.1.0') + delete_tag container expect(page).not_to have_content 'v1.1.0' end @@ -29,15 +30,15 @@ RSpec.describe 'Developer deletes tag' do expect(current_path).to eq( project_tag_path(project, 'v1.0.0')) - click_on 'Delete tag' + container = page.find('.nav-controls') + delete_tag container - expect(current_path).to eq( - project_tags_path(project)) + expect(current_path).to eq("#{project_tags_path(project)}/") expect(page).not_to have_content 'v1.0.0' end end - context 'when pre-receive hook fails', :js do + context 'when pre-receive hook fails' do before do allow_next_instance_of(Gitlab::GitalyClient::OperationService) do |instance| allow(instance).to receive(:rm_tag) @@ -46,15 +47,17 @@ RSpec.describe 'Developer deletes tag' do end it 'shows the error message' do - delete_tag 'v1.1.0' + container = page.find('.content .flex-row', text: 'v1.1.0') + delete_tag container expect(page).to have_content('Do not delete tags') end end - def delete_tag(tag) - page.within('.content') do - accept_confirm { find("li > .row-fixed-content.controls a.btn-remove[href='/#{project.full_path}/-/tags/#{tag}']").click } - end + def delete_tag(container) + container.find('.js-remove-tag').click + + page.within('.modal') { click_button('Delete tag') } + wait_for_requests end end diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb index a9cfe794177..0f8daaf8e15 100644 --- a/spec/features/task_lists_spec.rb +++ b/spec/features/task_lists_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Task Lists' do +RSpec.describe 'Task Lists', :js do include Warden::Test::Helpers let_it_be(:project) { create(:project, :public, :repository) } @@ -38,41 +38,7 @@ RSpec.describe 'Task Lists' do MARKDOWN end - let(:nested_tasks_markdown) do - <<-EOT.strip_heredoc - - [ ] Task a - - [x] Task a.1 - - [ ] Task a.2 - - [ ] Task b - - 1. [ ] Task 1 - 1. [ ] Task 1.1 - 1. [x] Task 1.2 - EOT - end - - let(:commented_tasks_markdown) do - <<-EOT.strip_heredoc - <!-- - - [ ] a - --> - - - [ ] b - EOT - end - - let(:summary_no_blank_line_markdown) do - <<-EOT.strip_heredoc - <details> - <summary>No blank line after summary element breaks task list</summary> - 1. [ ] People Ops: do such and such - </details> - - * [ ] Task 1 - EOT - end - - before(:all) do + before_all do project.add_maintainer(user) project.add_guest(user2) end @@ -86,7 +52,7 @@ RSpec.describe 'Task Lists' do end describe 'for Issues' do - describe 'multiple tasks', :js do + describe 'multiple tasks' do let!(:issue) { create(:issue, description: markdown, author: user, project: project) } it 'renders' do @@ -127,7 +93,7 @@ RSpec.describe 'Task Lists' do end end - describe 'single incomplete task', :js do + describe 'single incomplete task' do let!(:issue) { create(:issue, description: singleIncompleteMarkdown, author: user, project: project) } it 'renders' do @@ -146,7 +112,7 @@ RSpec.describe 'Task Lists' do end end - describe 'single complete task', :js do + describe 'single complete task' do let!(:issue) { create(:issue, description: singleCompleteMarkdown, author: user, project: project) } it 'renders' do @@ -175,7 +141,7 @@ RSpec.describe 'Task Lists' do project: project, author: user) end - it 'renders for note body', :js do + it 'renders for note body' do visit_issue(project, issue) expect(page).to have_selector('.note ul.task-list', count: 1) @@ -183,14 +149,14 @@ RSpec.describe 'Task Lists' do expect(page).to have_selector('.note ul input[checked]', count: 2) end - it 'contains the required selectors', :js do + it 'contains the required selectors' do visit_issue(project, issue) expect(page).to have_selector('.note .js-task-list-container') expect(page).to have_selector('.note .js-task-list-container .task-list .task-list-item .task-list-item-checkbox') end - it 'is only editable by author', :js do + it 'is only editable by author' do visit_issue(project, issue) expect(page).to have_selector('.js-task-list-container') @@ -209,7 +175,7 @@ RSpec.describe 'Task Lists' do project: project, author: user) end - it 'renders for note body', :js do + it 'renders for note body' do visit_issue(project, issue) expect(page).to have_selector('.note ul.task-list', count: 1) @@ -224,7 +190,7 @@ RSpec.describe 'Task Lists' do project: project, author: user) end - it 'renders for note body', :js do + it 'renders for note body' do visit_issue(project, issue) expect(page).to have_selector('.note ul.task-list', count: 1) @@ -240,7 +206,7 @@ RSpec.describe 'Task Lists' do end shared_examples 'multiple tasks' do - it 'renders for description', :js do + it 'renders for description' do visit_merge_request(project, merge) wait_for_requests @@ -249,7 +215,7 @@ RSpec.describe 'Task Lists' do expect(page).to have_selector('ul input[checked]', count: 2) end - it 'contains the required selectors', :js do + it 'contains the required selectors' do visit_merge_request(project, merge) wait_for_requests @@ -261,7 +227,7 @@ RSpec.describe 'Task Lists' do expect(page).to have_selector('form.js-issuable-update') end - it 'is only editable by author', :js do + it 'is only editable by author' do visit_merge_request(project, merge) wait_for_requests @@ -300,7 +266,7 @@ RSpec.describe 'Task Lists' do describe 'single incomplete task' do let!(:merge) { create(:merge_request, :simple, description: singleIncompleteMarkdown, author: user, source_project: project) } - it 'renders for description', :js do + it 'renders for description' do visit_merge_request(project, merge) wait_for_requests @@ -319,7 +285,7 @@ RSpec.describe 'Task Lists' do describe 'single complete task' do let!(:merge) { create(:merge_request, :simple, description: singleCompleteMarkdown, author: user, source_project: project) } - it 'renders for description', :js do + it 'renders for description' do visit_merge_request(project, merge) wait_for_requests @@ -337,7 +303,17 @@ RSpec.describe 'Task Lists' do end describe 'markdown task edge cases' do - describe 'commented tasks', :js do + describe 'commented tasks' do + let(:commented_tasks_markdown) do + <<-EOT.strip_heredoc + <!-- + - [ ] a + --> + + - [ ] b + EOT + end + let!(:issue) { create(:issue, description: commented_tasks_markdown, author: user, project: project) } it 'renders' do @@ -360,7 +336,18 @@ RSpec.describe 'Task Lists' do end end - describe 'summary with no blank line', :js do + describe 'summary with no blank line' do + let(:summary_no_blank_line_markdown) do + <<-EOT.strip_heredoc + <details> + <summary>No blank line after summary element breaks task list</summary> + 1. [ ] People Ops: do such and such + </details> + + * [ ] Task 1 + EOT + end + let!(:issue) { create(:issue, description: summary_no_blank_line_markdown, author: user, project: project) } it 'renders' do @@ -382,5 +369,31 @@ RSpec.describe 'Task Lists' do expect(page).to have_selector('ul input[checked]', count: 1) end end + + describe 'markdown starting with new line character' do + let(:markdown_starting_with_new_line) do + <<-EOT.strip_heredoc + + - [ ] Task 1 + EOT + end + + let(:merge_request) { create(:merge_request, description: markdown_starting_with_new_line, author: user, source_project: project) } + + it 'allows the task to be checked' do + visit project_merge_request_path(project, merge_request) + wait_for_requests + + expect(page).to have_selector('ul input[checked]', count: 0) + + find('.task-list-item-checkbox').click + wait_for_requests + + visit project_merge_request_path(project, merge_request) + wait_for_requests + + expect(page).to have_selector('ul input[checked]', count: 1) + end + end end end diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb index 4be27673adf..6fa805d8c74 100644 --- a/spec/features/triggers_spec.rb +++ b/spec/features/triggers_spec.rb @@ -19,114 +19,132 @@ RSpec.describe 'Triggers', :js do visit project_settings_ci_cd_path(@project) end - describe 'create trigger workflow' do - it 'prevents adding new trigger with no description' do - fill_in 'trigger_description', with: '' - click_button 'Add trigger' - - # See if input has error due to empty value - expect(page.find('form.gl-show-field-errors .gl-field-error')).to be_visible - end + shared_examples 'triggers page' do + describe 'create trigger workflow' do + it 'prevents adding new trigger with no description' do + fill_in 'trigger_description', with: '' + click_button 'Add trigger' + + # See if input has error due to empty value + expect(page.find('form.gl-show-field-errors .gl-field-error')).to be_visible + end - it 'adds new trigger with description' do - fill_in 'trigger_description', with: 'trigger desc' - click_button 'Add trigger' + it 'adds new trigger with description' do + fill_in 'trigger_description', with: 'trigger desc' + click_button 'Add trigger' - # See if "trigger creation successful" message displayed and description and owner are correct - expect(page.find('.flash-notice')).to have_content 'Trigger was created successfully.' - expect(page.find('.triggers-list')).to have_content 'trigger desc' - expect(page.find('.triggers-list .trigger-owner')).to have_content user.name + aggregate_failures 'display creation notice and trigger is created' do + expect(page.find('.flash-notice')).to have_content 'Trigger was created successfully.' + expect(page.find('.triggers-list')).to have_content 'trigger desc' + expect(page.find('.triggers-list .trigger-owner')).to have_content user.name + end + end end - end - - describe 'edit trigger workflow' do - let(:new_trigger_title) { 'new trigger' } - it 'click on edit trigger opens edit trigger page' do - create(:ci_trigger, owner: user, project: @project, description: trigger_title) - visit project_settings_ci_cd_path(@project) + describe 'edit trigger workflow' do + let(:new_trigger_title) { 'new trigger' } - # See if edit page has correct descrption - find('a[title="Edit"]').send_keys(:return) - expect(page.find('#trigger_description').value).to have_content 'trigger desc' - end + it 'click on edit trigger opens edit trigger page' do + create(:ci_trigger, owner: user, project: @project, description: trigger_title) + visit project_settings_ci_cd_path(@project) - it 'edit trigger and save' do - create(:ci_trigger, owner: user, project: @project, description: trigger_title) - visit project_settings_ci_cd_path(@project) + # See if edit page has correct descrption + find('a[title="Edit"]').send_keys(:return) + expect(page.find('#trigger_description').value).to have_content 'trigger desc' + end - # See if edit page opens, then fill in new description and save - find('a[title="Edit"]').send_keys(:return) - fill_in 'trigger_description', with: new_trigger_title - click_button 'Save trigger' + it 'edit trigger and save' do + create(:ci_trigger, owner: user, project: @project, description: trigger_title) + visit project_settings_ci_cd_path(@project) - # See if "trigger updated successfully" message displayed and description and owner are correct - expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.' - expect(page.find('.triggers-list')).to have_content new_trigger_title - expect(page.find('.triggers-list .trigger-owner')).to have_content user.name - end - end + # See if edit page opens, then fill in new description and save + find('a[title="Edit"]').send_keys(:return) + fill_in 'trigger_description', with: new_trigger_title + click_button 'Save trigger' - describe 'trigger "Revoke" workflow' do - before do - create(:ci_trigger, owner: user2, project: @project, description: trigger_title) - visit project_settings_ci_cd_path(@project) + aggregate_failures 'display update notice and trigger is updated' do + expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.' + expect(page.find('.triggers-list')).to have_content new_trigger_title + expect(page.find('.triggers-list .trigger-owner')).to have_content user.name + end + end end - it 'button "Revoke" has correct alert' do - expected_alert = 'By revoking a trigger you will break any processes making use of it. Are you sure?' - expect(page.find('a.btn-trigger-revoke')['data-confirm']).to eq expected_alert - end + describe 'trigger "Revoke" workflow' do + before do + create(:ci_trigger, owner: user2, project: @project, description: trigger_title) + visit project_settings_ci_cd_path(@project) + end - it 'revoke trigger' do - # See if "Revoke" on trigger works post trigger creation - page.accept_confirm do - find('a.btn-trigger-revoke').send_keys(:return) + it 'button "Revoke" has correct alert' do + expected_alert = 'By revoking a trigger you will break any processes making use of it. Are you sure?' + expect(page.find('[data-testid="trigger_revoke_button"]')['data-confirm']).to eq expected_alert end - expect(page.find('.flash-notice')).to have_content 'Trigger removed' - expect(page).to have_selector('p.settings-message.text-center.gl-mb-3') - end - end + it 'revoke trigger' do + # See if "Revoke" on trigger works post trigger creation + page.accept_confirm do + find('[data-testid="trigger_revoke_button"]').send_keys(:return) + end - describe 'show triggers workflow' do - it 'contains trigger description placeholder' do - expect(page.find('#trigger_description')['placeholder']).to eq 'Trigger description' + aggregate_failures 'trigger is removed' do + expect(page.find('.flash-notice')).to have_content 'Trigger removed' + expect(page).to have_css('[data-testid="no_triggers_content"]') + end + end end - it 'show "invalid" badge for trigger with owner having insufficient permissions' do - create(:ci_trigger, owner: guest_user, project: @project, description: trigger_title) - visit project_settings_ci_cd_path(@project) + describe 'show triggers workflow' do + it 'contains trigger description placeholder' do + expect(page.find('#trigger_description')['placeholder']).to eq 'Trigger description' + end - expect(page.find('.triggers-list')).to have_content 'invalid' - expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]') - end + it 'show "invalid" badge for trigger with owner having insufficient permissions' do + create(:ci_trigger, owner: guest_user, project: @project, description: trigger_title) + visit project_settings_ci_cd_path(@project) + + aggregate_failures 'has invalid badge and no edit link' do + expect(page.find('.triggers-list')).to have_content 'invalid' + expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]') + end + end - it 'do not show "Edit" or full token for not owned trigger' do - # Create trigger with user different from current_user - create(:ci_trigger, owner: user2, project: @project, description: trigger_title) - visit project_settings_ci_cd_path(@project) + it 'do not show "Edit" or full token for not owned trigger' do + # Create trigger with user different from current_user + create(:ci_trigger, owner: user2, project: @project, description: trigger_title) + visit project_settings_ci_cd_path(@project) + + aggregate_failures 'shows truncated token, no clipboard button and no edit link' do + expect(page.find('.triggers-list')).to have_content(@project.triggers.first.token[0..3]) + expect(page.find('.triggers-list')).not_to have_selector('[data-testid="clipboard-btn"]') + expect(page.find('.triggers-list .trigger-owner')).not_to have_content user.name + expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]') + end + end - # See if trigger not owned by current_user shows only first few token chars and doesn't have copy-to-clipboard button - expect(page.find('.triggers-list')).to have_content(@project.triggers.first.token[0..3]) - expect(page.find('.triggers-list')).not_to have_selector('button.btn-clipboard') + it 'show "Edit" and full token for owned trigger' do + create(:ci_trigger, owner: user, project: @project, description: trigger_title) + visit project_settings_ci_cd_path(@project) - # See if trigger owner name doesn't match with current_user and trigger is non-editable - expect(page.find('.triggers-list .trigger-owner')).not_to have_content user.name - expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]') + aggregate_failures 'shows full token, clipboard button and edit link' do + expect(page.find('.triggers-list')).to have_content @project.triggers.first.token + expect(page.find('.triggers-list')).to have_selector('[data-testid="clipboard-btn"]') + expect(page.find('.triggers-list .trigger-owner')).to have_content user.name + expect(page.find('.triggers-list')).to have_selector('a[title="Edit"]') + end + end end + end - it 'show "Edit" and full token for owned trigger' do - create(:ci_trigger, owner: user, project: @project, description: trigger_title) - visit project_settings_ci_cd_path(@project) - - # See if trigger shows full token and has copy-to-clipboard button - expect(page.find('.triggers-list')).to have_content @project.triggers.first.token - expect(page.find('.triggers-list')).to have_selector('button.btn-clipboard') + context 'when ci_pipeline_triggers_settings_vue_ui is enabled' do + it_behaves_like 'triggers page' + end - # See if trigger owner name matches with current_user and is editable - expect(page.find('.triggers-list .trigger-owner')).to have_content user.name - expect(page.find('.triggers-list')).to have_selector('a[title="Edit"]') + context 'when ci_pipeline_triggers_settings_vue_ui is disabled' do + before do + stub_feature_flags(ci_pipeline_triggers_settings_vue_ui: false) end + + it_behaves_like 'triggers page' end end diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb index dd5c2442d00..b3c8cf8d326 100644 --- a/spec/features/users/show_spec.rb +++ b/spec/features/users/show_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'User page' do include ExternalAuthorizationServiceHelpers - let(:user) { create(:user) } + let(:user) { create(:user, bio: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') } context 'with public profile' do it 'shows all the tabs' do @@ -174,4 +174,12 @@ RSpec.describe 'User page' do end end end + + context 'page description' do + before do + visit(user_path(user)) + end + + it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet' + end end diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb index 5275845fe5b..7500f2fe59a 100644 --- a/spec/features/users/terms_spec.rb +++ b/spec/features/users/terms_spec.rb @@ -26,6 +26,21 @@ RSpec.describe 'Users > Terms' do expect(page).not_to have_content('Continue') end + context 'when user is a project bot' do + let(:project_bot) { create(:user, :project_bot) } + + before do + enforce_terms + end + + it 'auto accepts the terms' do + visit terms_path + + expect(page).not_to have_content('Accept terms') + expect(project_bot.terms_accepted?).to be(true) + end + end + context 'when signed in' do let(:user) { create(:user) } |