diff options
Diffstat (limited to 'spec/features')
117 files changed, 1782 insertions, 1292 deletions
diff --git a/spec/features/admin/admin_dev_ops_reports_spec.rb b/spec/features/admin/admin_dev_ops_reports_spec.rb index bf32819cb52..f65862c568f 100644 --- a/spec/features/admin/admin_dev_ops_reports_spec.rb +++ b/spec/features/admin/admin_dev_ops_reports_spec.rb @@ -9,9 +9,9 @@ RSpec.describe 'DevOps Report page', :js do gitlab_enable_admin_mode_sign_in(admin) end - context 'with devops_adoption feature flag disabled' do + context 'without licensed feature devops adoption' do before do - stub_feature_flags(devops_adoption: false) + stub_licensed_features(devops_adoption: false) end it 'has dismissable intro callout' do diff --git a/spec/features/admin/admin_hook_logs_spec.rb b/spec/features/admin/admin_hook_logs_spec.rb index 6caf2b24555..a2ee6343886 100644 --- a/spec/features/admin/admin_hook_logs_spec.rb +++ b/spec/features/admin/admin_hook_logs_spec.rb @@ -3,12 +3,11 @@ require 'spec_helper' RSpec.describe 'Admin::HookLogs' do - let(:project) { create(:project) } - let(:system_hook) { create(:system_hook) } - let(:hook_log) { create(:web_hook_log, web_hook: system_hook, internal_error_message: 'some error') } + let_it_be(:system_hook) { create(:system_hook) } + let_it_be(:hook_log) { create(:web_hook_log, web_hook: system_hook, internal_error_message: 'some error') } + let_it_be(:admin) { create(:admin) } before do - admin = create(:admin) sign_in(admin) gitlab_enable_admin_mode_sign_in(admin) end diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index 901315752d6..dc5b0ae009e 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Admin::Hooks' do include Spec::Support::Helpers::ModalHelpers - let(:user) { create(:admin) } + let_it_be(:user) { create(:admin) } before do sign_in(user) diff --git a/spec/features/admin/admin_mode/workers_spec.rb b/spec/features/admin/admin_mode/workers_spec.rb index 12f5e20e176..8405e9132b6 100644 --- a/spec/features/admin/admin_mode/workers_spec.rb +++ b/spec/features/admin/admin_mode/workers_spec.rb @@ -37,56 +37,26 @@ RSpec.describe 'Admin mode for workers', :request_store do gitlab_enable_admin_mode_sign_in(user) end - context 'when user_destroy_with_limited_execution_time_worker is enabled' do - it 'can delete user', :js do - visit admin_user_path(user_to_delete) - - click_action_in_user_dropdown(user_to_delete.id, 'Delete user') - - page.within '.modal-dialog' do - find("input[name='username']").send_keys(user_to_delete.name) - click_button 'Delete user' - - wait_for_requests - end - - expect(page).to have_content('The user is being deleted.') - - # Perform jobs while logged out so that admin mode is only enabled in job metadata - execute_jobs_signed_out(user) + it 'can delete user', :js do + visit admin_user_path(user_to_delete) - visit admin_user_path(user_to_delete) + click_action_in_user_dropdown(user_to_delete.id, 'Delete user') - expect(find('h1.page-title')).to have_content('(Blocked)') - end - end + page.within '.modal-dialog' do + find("input[name='username']").send_keys(user_to_delete.name) + click_button 'Delete user' - context 'when user_destroy_with_limited_execution_time_worker is disabled' do - before do - stub_feature_flags(user_destroy_with_limited_execution_time_worker: false) + wait_for_requests end - it 'can delete user', :js do - visit admin_user_path(user_to_delete) - - click_action_in_user_dropdown(user_to_delete.id, 'Delete user') - - page.within '.modal-dialog' do - find("input[name='username']").send_keys(user_to_delete.name) - click_button 'Delete user' - - wait_for_requests - end + expect(page).to have_content('The user is being deleted.') - expect(page).to have_content('The user is being deleted.') + # Perform jobs while logged out so that admin mode is only enabled in job metadata + execute_jobs_signed_out(user) - # Perform jobs while logged out so that admin mode is only enabled in job metadata - execute_jobs_signed_out(user) - - visit admin_user_path(user_to_delete) + visit admin_user_path(user_to_delete) - expect(page).to have_title('Not Found') - end + expect(find('h1.page-title')).to have_content('(Blocked)') end end end diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 35e57213bdb..92a3b388994 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -72,19 +72,8 @@ RSpec.describe "Admin Runners" do expect(page).to have_text "#{s_('Runners|Stale')} 1" end - describe 'delete all runners in bulk' do - before do - check s_('Runners|Select all') - click_button s_('Runners|Delete selected') - - within_modal do - click_on 'Permanently delete 3 runners' - end - - wait_for_requests - end - - it_behaves_like 'shows no runners registered' + it_behaves_like 'deletes runners in bulk' do + let(:runner_count) { '3' } end end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 94c5f397670..72c9053ba49 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -205,6 +205,22 @@ RSpec.describe 'Admin updates settings' do expect(page).to have_content "Application settings saved successfully" end end + + context 'Email confirmation settings' do + it "is set to 'hard' by default" do + expect(current_settings.email_confirmation_setting).to eq('off') + end + + it 'changes the setting', :js do + page.within('.as-signup') do + choose 'Hard' + click_button 'Save changes' + end + + expect(current_settings.email_confirmation_setting).to eq('hard') + expect(page).to have_content "Application settings saved successfully" + end + end end it 'change Sign-in restrictions' do @@ -304,10 +320,12 @@ RSpec.describe 'Admin updates settings' do it 'changes the setting' do page.within('#js-jira_connect-settings') do fill_in 'Jira Connect Application ID', with: '1234' + fill_in 'Jira Connect Proxy URL', with: 'https://example.com' click_button 'Save changes' end expect(current_settings.jira_connect_application_key).to eq('1234') + expect(current_settings.jira_connect_proxy_url).to eq('https://example.com') expect(page).to have_content "Application settings saved successfully" end end diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb index 45dccf9921f..d93dac4834e 100644 --- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb +++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb @@ -4,18 +4,11 @@ require 'spec_helper' RSpec.describe 'Admin > Users > Impersonation Tokens', :js do include Spec::Support::Helpers::ModalHelpers + include Spec::Support::Helpers::AccessTokenHelpers let(:admin) { create(:admin) } let!(:user) { create(:user) } - def active_impersonation_tokens - find("[data-testid='active-tokens']") - end - - def created_impersonation_token - find_field('new-access-token').value - end - before do sign_in(admin) gitlab_enable_admin_mode_sign_in(admin) @@ -39,12 +32,12 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do click_on "Create impersonation token" - expect(active_impersonation_tokens).to have_text(name) - expect(active_impersonation_tokens).to have_text('in') - expect(active_impersonation_tokens).to have_text('read_api') - expect(active_impersonation_tokens).to have_text('read_user') + expect(active_access_tokens).to have_text(name) + expect(active_access_tokens).to have_text('in') + expect(active_access_tokens).to have_text('read_api') + expect(active_access_tokens).to have_text('read_user') expect(PersonalAccessTokensFinder.new(impersonation: true).execute.count).to equal(1) - expect(created_impersonation_token).not_to be_empty + expect(created_access_token).to match(/[\w-]{20}/) end end @@ -55,16 +48,16 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do it 'only shows impersonation tokens' do visit admin_user_impersonation_tokens_path(user_id: user.username) - expect(active_impersonation_tokens).to have_text(impersonation_token.name) - expect(active_impersonation_tokens).not_to have_text(personal_access_token.name) - expect(active_impersonation_tokens).to have_text('in') + expect(active_access_tokens).to have_text(impersonation_token.name) + expect(active_access_tokens).not_to have_text(personal_access_token.name) + expect(active_access_tokens).to have_text('in') end it 'shows absolute times' do admin.update!(time_display_relative: false) visit admin_user_impersonation_tokens_path(user_id: user.username) - expect(active_impersonation_tokens).to have_text(personal_access_token.expires_at.strftime('%b %-d')) + expect(active_access_tokens).to have_text(personal_access_token.expires_at.strftime('%b %-d')) end end @@ -76,7 +69,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do accept_gl_confirm(button_text: 'Revoke') { click_on "Revoke" } - expect(active_impersonation_tokens).to have_text("This user has no active impersonation tokens.") + expect(active_access_tokens).to have_text("This user has no active impersonation tokens.") end it "removes expired tokens from 'active' section" do @@ -84,7 +77,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do visit admin_user_impersonation_tokens_path(user_id: user.username) - expect(active_impersonation_tokens).to have_text("This user has no active impersonation tokens.") + expect(active_access_tokens).to have_text("This user has no active impersonation tokens.") end end diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb index 86acf5a05d4..35b5c755b66 100644 --- a/spec/features/admin/users/user_spec.rb +++ b/spec/features/admin/users/user_spec.rb @@ -150,13 +150,32 @@ RSpec.describe 'Admin::Users::User' do context 'before impersonating' do subject { visit admin_user_path(user_to_visit) } - let(:user_to_visit) { another_user } + let_it_be(:user_to_visit) { another_user } + + shared_examples "user that cannot be impersonated" do + it 'disables impersonate button' do + subject + + impersonate_btn = find('[data-testid="impersonate_user_link"]') + + expect(impersonate_btn).not_to be_nil + expect(impersonate_btn['disabled']).not_to be_nil + end + + it "shows tooltip with correct error message" do + subject + + expect(find("span[title='#{impersonation_error_msg}']")).not_to be_nil + end + end context 'for other users' do it 'shows impersonate button for other users' do subject expect(page).to have_content('Impersonate') + impersonate_btn = find('[data-testid="impersonate_user_link"]') + expect(impersonate_btn['disabled']).to be_nil end end @@ -171,15 +190,51 @@ RSpec.describe 'Admin::Users::User' do end context 'for blocked user' do - before do - another_user.block + let_it_be(:blocked_user) { create(:user, :blocked) } + let(:user_to_visit) { blocked_user } + let(:impersonation_error_msg) { _('You cannot impersonate a blocked user') } + + it_behaves_like "user that cannot be impersonated" + end + + context 'for user with expired password' do + let(:user_to_visit) do + another_user.update!(password_expires_at: Time.zone.now - 5.minutes) + another_user end - it 'does not show impersonate button for blocked user' do - subject + let(:impersonation_error_msg) { _("You cannot impersonate a user with an expired password") } - expect(page).not_to have_content('Impersonate') + it_behaves_like "user that cannot be impersonated" + end + + context 'for internal user' do + let_it_be(:internal_user) { create(:user, :bot) } + let(:user_to_visit) { internal_user } + let(:impersonation_error_msg) { _("You cannot impersonate an internal user") } + + it_behaves_like "user that cannot be impersonated" + end + + context 'for locked user' do + let_it_be(:locked_user) { create(:user, :locked) } + let(:user_to_visit) { locked_user } + let(:impersonation_error_msg) { _("You cannot impersonate a user who cannot log in") } + + it_behaves_like "user that cannot be impersonated" + end + + context 'when already impersonating another user' do + let_it_be(:admin_user) { create(:user, :admin) } + let(:impersonation_error_msg) { _("You are already impersonating another user") } + + subject do + visit admin_user_path(admin_user) + click_link 'Impersonate' + visit admin_user_path(another_user) end + + it_behaves_like "user that cannot be impersonated" end context 'when impersonation is disabled' do @@ -216,18 +271,6 @@ RSpec.describe 'Admin::Users::User' do icon = first('[data-testid="incognito-icon"]') expect(icon).not_to be nil end - - context 'a user with an expired password' do - before do - another_user.update!(password_expires_at: Time.zone.now - 5.minutes) - end - - it 'does not redirect to password change page' do - subject - - expect(page).to have_current_path('/') - end - end end context 'ending impersonation' do diff --git a/spec/features/admin_variables_spec.rb b/spec/features/admin_variables_spec.rb index 174d4567520..9ec22bbe948 100644 --- a/spec/features/admin_variables_spec.rb +++ b/spec/features/admin_variables_spec.rb @@ -12,23 +12,9 @@ RSpec.describe 'Instance variables', :js do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') sign_in(admin) gitlab_enable_admin_mode_sign_in(admin) + visit page_path wait_for_requests end - context 'with disabled ff `ci_variable_settings_graphql' do - before do - stub_feature_flags(ci_variable_settings_graphql: false) - visit page_path - end - - it_behaves_like 'variable list', isAdmin: true - end - - context 'with enabled ff `ci_variable_settings_graphql' do - before do - visit page_path - end - - it_behaves_like 'variable list', isAdmin: true - end + it_behaves_like 'variable list', isAdmin: true end diff --git a/spec/features/boards/board_filters_spec.rb b/spec/features/boards/board_filters_spec.rb index 2e4dc4a29fc..eab92de7e8a 100644 --- a/spec/features/boards/board_filters_spec.rb +++ b/spec/features/boards/board_filters_spec.rb @@ -7,8 +7,8 @@ RSpec.describe 'Issue board filters', :js do let_it_be(:user) { create(:user) } let_it_be(:board) { create(:board, project: project) } let_it_be(:project_label) { create(:label, project: project, title: 'Label') } - let_it_be(:milestone_1) { create(:milestone, project: project, due_date: 3.days.from_now ) } - let_it_be(:milestone_2) { create(:milestone, project: project, due_date: Date.tomorrow ) } + let_it_be(:milestone_1) { create(:milestone, project: project, due_date: 3.days.from_now) } + let_it_be(:milestone_2) { create(:milestone, project: project, due_date: Date.tomorrow) } let_it_be(:release) { create(:release, tag: 'v1.0', project: project, milestones: [milestone_1]) } let_it_be(:release_2) { create(:release, tag: 'v2.0', project: project, milestones: [milestone_2]) } let_it_be(:issue_1) { create(:issue, project: project, milestone: milestone_1, author: user) } @@ -22,6 +22,7 @@ RSpec.describe 'Issue board filters', :js do let(:filter_submit) { find('.gl-search-box-by-click-search-button') } before do + stub_feature_flags(apollo_boards: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index a09c9d258dc..fee9b5b378e 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -19,6 +19,7 @@ RSpec.describe 'Project issue boards', :js do context 'signed in user' do before do + stub_feature_flags(apollo_boards: false) project.add_maintainer(user) project.add_maintainer(user2) @@ -29,7 +30,7 @@ RSpec.describe 'Project issue boards', :js do context 'no lists' do before do - visit_project_board_path_without_query_limit(project, board) + visit_project_board(project, board) end it 'creates default lists' do @@ -73,7 +74,7 @@ RSpec.describe 'Project issue boards', :js do let_it_be(:issue10) { create(:labeled_issue, project: project, title: 'issue +', description: 'A+ great issue', labels: [a_plus]) } before do - visit_project_board_path_without_query_limit(project, board) + visit_project_board(project, board) end it 'shows description tooltip on list title', :quarantine do @@ -124,7 +125,7 @@ RSpec.describe 'Project issue boards', :js do it 'infinite scrolls list' do create_list(:labeled_issue, 30, project: project, labels: [planning]) - visit_project_board_path_without_query_limit(project, board) + visit_project_board(project, board) page.within(find('.board:nth-child(2)')) do expect(page.find('.board-header')).to have_content('38') @@ -203,7 +204,7 @@ RSpec.describe 'Project issue boards', :js do expect(find('.board:nth-child(3) [data-testid="board-list-header"]')).to have_content(planning.title) # Make sure list positions are preserved after a reload - visit_project_board_path_without_query_limit(project, board) + visit_project_board(project, board) expect(find('.board:nth-child(2) [data-testid="board-list-header"]')).to have_content(development.title) expect(find('.board:nth-child(3) [data-testid="board-list-header"]')).to have_content(planning.title) @@ -215,15 +216,19 @@ RSpec.describe 'Project issue boards', :js do let_it_be(:list2) { create(:list, board: board, label: development, position: 1) } it 'changes position of list' do - visit_project_board_path_without_query_limit(project, board) + inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do + visit_project_board(project, board) + end drag(list_from_index: 0, list_to_index: 1, selector: '.board-header') expect(find('.board:nth-child(1) [data-testid="board-list-header"]')).to have_content(development.title) expect(find('.board:nth-child(2) [data-testid="board-list-header"]')).to have_content(planning.title) - # Make sure list positions are preserved after a reload - visit_project_board_path_without_query_limit(project, board) + inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do + # Make sure list positions are preserved after a reload + visit_project_board(project, board) + end expect(find('.board:nth-child(1) [data-testid="board-list-header"]')).to have_content(development.title) expect(find('.board:nth-child(2) [data-testid="board-list-header"]')).to have_content(planning.title) @@ -234,7 +239,9 @@ RSpec.describe 'Project issue boards', :js do selector = '.board:not(.is-ghost) .board-header' expect(page).to have_selector(selector, text: development.title, count: 1) - drag(list_from_index: 2, list_to_index: 1, selector: '.board-header', perform_drop: false) + inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do + drag(list_from_index: 2, list_to_index: 1, selector: '.board-header', perform_drop: false) + end expect(page).to have_selector(selector, text: development.title, count: 1) end @@ -492,7 +499,7 @@ RSpec.describe 'Project issue boards', :js do context 'keyboard shortcuts' do before do - visit_project_board_path_without_query_limit(project, board) + visit_project_board(project, board) wait_for_requests end @@ -505,6 +512,7 @@ RSpec.describe 'Project issue boards', :js do context 'signed out user' do before do + stub_feature_flags(apollo_boards: false) visit project_board_path(project, board) wait_for_requests end @@ -526,6 +534,7 @@ RSpec.describe 'Project issue boards', :js do let_it_be(:user_guest) { create(:user) } before do + stub_feature_flags(apollo_boards: false) project.add_guest(user_guest) sign_in(user_guest) visit project_board_path(project, board) @@ -587,11 +596,9 @@ RSpec.describe 'Project issue boards', :js do end end - def visit_project_board_path_without_query_limit(project, board) - inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do - visit project_board_path(project, board) + def visit_project_board(project, board) + visit project_board_path(project, board) - wait_for_requests - end + wait_for_requests end end diff --git a/spec/features/boards/issue_ordering_spec.rb b/spec/features/boards/issue_ordering_spec.rb index 57f2bf26752..a3dda3b9d2f 100644 --- a/spec/features/boards/issue_ordering_spec.rb +++ b/spec/features/boards/issue_ordering_spec.rb @@ -15,6 +15,7 @@ RSpec.describe 'Issue Boards', :js do let!(:issue3) { create(:labeled_issue, project: project, title: 'testing 3', labels: [label], relative_position: 1) } before do + stub_feature_flags(apollo_boards: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/boards/sidebar_labels_spec.rb b/spec/features/boards/sidebar_labels_spec.rb index 511233b50c0..12d91e9c5a8 100644 --- a/spec/features/boards/sidebar_labels_spec.rb +++ b/spec/features/boards/sidebar_labels_spec.rb @@ -20,6 +20,7 @@ RSpec.describe 'Project issue boards sidebar labels', :js do let(:card) { find('.board:nth-child(2)').first('.board-card') } before do + stub_feature_flags(apollo_boards: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index 0e914ae19d1..2b2a412194a 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -15,6 +15,7 @@ RSpec.describe 'Project issue boards sidebar', :js do let_it_be(:issue, reload: true) { create(:issue, project: project, relative_position: 1) } before do + stub_feature_flags(apollo_boards: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/boards/user_adds_lists_to_board_spec.rb b/spec/features/boards/user_adds_lists_to_board_spec.rb index 26c310a6f56..480a88a6b84 100644 --- a/spec/features/boards/user_adds_lists_to_board_spec.rb +++ b/spec/features/boards/user_adds_lists_to_board_spec.rb @@ -31,13 +31,15 @@ RSpec.describe 'User adds lists', :js do with_them do before do + stub_feature_flags(apollo_boards: false) sign_in(user) set_cookie('sidebar_collapsed', 'true') - if board_type == :project + case board_type + when :project visit project_board_path(project, project_board) - elsif board_type == :group + when :group visit group_board_path(group, group_board) end diff --git a/spec/features/boards/user_visits_board_spec.rb b/spec/features/boards/user_visits_board_spec.rb index 7fe32557d6a..c386477fa9d 100644 --- a/spec/features/boards/user_visits_board_spec.rb +++ b/spec/features/boards/user_visits_board_spec.rb @@ -21,7 +21,7 @@ RSpec.describe 'User visits issue boards', :js do let_it_be(:label1) { create(:group_label, group: group, name: label_name1) } let_it_be(:label2) { create(:group_label, group: group, name: label_name2) } - let_it_be(:assignee) { create_default(:group_member, :maintainer, user: create(:user, username: assignee_username), group: group ).user } + let_it_be(:assignee) { create_default(:group_member, :maintainer, user: create(:user, username: assignee_username), group: group).user } let_it_be(:milestone) { create_default(:milestone, project: project, start_date: Date.today - 1, due_date: 7.days.from_now) } before_all do @@ -44,6 +44,7 @@ RSpec.describe 'User visits issue boards', :js do with_them do before do + stub_feature_flags(apollo_boards: false) visit board_path wait_for_requests @@ -59,6 +60,7 @@ RSpec.describe 'User visits issue boards', :js do end context "project boards" do + stub_feature_flags(apollo_boards: false) let_it_be(:board) { create_default(:board, project: project) } let_it_be(:backlog_list) { create_default(:backlog_list, board: board) } @@ -68,6 +70,7 @@ RSpec.describe 'User visits issue boards', :js do end context "group boards" do + stub_feature_flags(apollo_boards: false) let_it_be(:board) { create_default(:board, group: group) } let_it_be(:backlog_list) { create_default(:backlog_list, board: board) } diff --git a/spec/features/broadcast_messages_spec.rb b/spec/features/broadcast_messages_spec.rb index f339d45671d..1fec68a1d98 100644 --- a/spec/features/broadcast_messages_spec.rb +++ b/spec/features/broadcast_messages_spec.rb @@ -31,7 +31,8 @@ RSpec.describe 'Broadcast Messages' do expect(page).not_to have_content 'SampleMessage' end - it 'broadcast message is still hidden after refresh', :js do + it 'broadcast message is still hidden after refresh', :js, + quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/347118' do visit root_path find('.js-dismiss-current-broadcast-notification').click diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index db841ffc627..97f820c1518 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -212,13 +212,13 @@ RSpec.describe 'Commits' do end context 'author is just a name' do - let(:author) { "#{author_commit.author_name}" } + let(:author) { author_commit.author_name.to_s } it_behaves_like 'show commits by author' end context 'author is just an email' do - let(:author) { "#{author_commit.author_email}" } + let(:author) { author_commit.author_email.to_s } it_behaves_like 'show commits by author' end diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 488a4f84297..8de4c66c62f 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -56,7 +56,7 @@ RSpec.describe 'Value Stream Analytics', :js do end end - context "when there's value stream analytics data" do + context "when there's value stream analytics data", :sidekiq_inline do # NOTE: in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68595 travel back # 5 days in time before we create data for these specs, to mitigate some flakiness # So setting the date range to be the last 2 days should skip past the existing data @@ -103,7 +103,7 @@ RSpec.describe 'Value Stream Analytics', :js do end end - it 'shows data on each stage', :sidekiq_might_not_need_inline, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338332' do + it 'shows data on each stage', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338332' do expect_issue_to_be_present click_stage('Plan') @@ -207,11 +207,11 @@ RSpec.describe 'Value Stream Analytics', :js do wait_for_requests end - it 'does not show the commit stats' do + it 'does not show the commit stats', :sidekiq_inline do expect(page.find(metrics_selector)).not_to have_selector("#commits") end - it 'does not show restricted stages', :aggregate_failures do + it 'does not show restricted stages', :aggregate_failures, :sidekiq_inline do expect(find(stage_table_selector)).to have_content(issue.title) expect(page).to have_selector('.gl-path-nav-list-item', text: 'Issue') diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb index 875ae41c55d..de8858fa8fa 100644 --- a/spec/features/dashboard/datetime_on_tooltips_spec.rb +++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb @@ -14,8 +14,8 @@ RSpec.describe 'Tooltips on .timeago dates', :js do context 'on the activity tab' do before do - Event.create!( project: project, author_id: user.id, action: :joined, - updated_at: created_date, created_at: created_date) + Event.create!(project: project, author_id: user.id, action: :joined, + updated_at: created_date, created_at: created_date) sign_in user visit user_activity_path(user) diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb index 0b468854322..c132caa88c8 100644 --- a/spec/features/dashboard/projects_spec.rb +++ b/spec/features/dashboard/projects_spec.rb @@ -139,7 +139,7 @@ RSpec.describe 'Dashboard Projects' do end describe 'with a pipeline', :clean_gitlab_redis_shared_state do - let_it_be(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha, ref: project.default_branch) } + let!(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha, ref: project.default_branch) } before do # Since the cache isn't updated when a new pipeline is created @@ -151,7 +151,7 @@ RSpec.describe 'Dashboard Projects' do it 'shows that the last pipeline passed' do visit dashboard_projects_path - page.within('.controls') do + page.within('[data-testid="project_controls"]') do expect(page).to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit, ref: pipeline.ref)}']") expect(page).to have_css('.ci-status-link') expect(page).to have_css('.ci-status-icon-success') @@ -163,7 +163,7 @@ RSpec.describe 'Dashboard Projects' do it 'does not show the pipeline status' do visit dashboard_projects_path - page.within('.controls') do + page.within('[data-testid="project_controls"]') do expect(page).not_to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit, ref: pipeline.ref)}']") expect(page).not_to have_css('.ci-status-link') expect(page).not_to have_css('.ci-status-icon-success') diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb index 666bf3594de..2e63ec2d4f2 100644 --- a/spec/features/global_search_spec.rb +++ b/spec/features/global_search_spec.rb @@ -2,14 +2,13 @@ require 'spec_helper' -RSpec.describe 'Global search' do +RSpec.describe 'Global search', :js do include AfterNextHelpers - let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, namespace: user.namespace) } before do - stub_feature_flags(search_page_vertical_nav: false) project.add_maintainer(user) sign_in(user) end @@ -42,7 +41,7 @@ RSpec.describe 'Global search' do end end - it 'closes the dropdown on blur', :js do + it 'closes the dropdown on blur' do find('#search').click fill_in 'search', with: "a" @@ -59,7 +58,7 @@ RSpec.describe 'Global search' do expect(page).to have_no_selector('#js-header-search') end - it 'focuses search input when shortcut "s" is pressed', :js do + it 'focuses search input when shortcut "s" is pressed' do expect(page).not_to have_selector('#search:focus') find('body').native.send_key('s') @@ -74,7 +73,7 @@ RSpec.describe 'Global search' do stub_feature_flags(new_header_search: true) visit dashboard_projects_path - # intialize javascript loaded input search input field + # initialize javascript loaded input search input field find('#search').click find('body').click end @@ -84,7 +83,7 @@ RSpec.describe 'Global search' do expect(page).to have_selector('#js-header-search') end - it 'focuses search input when shortcut "s" is pressed', :js do + it 'focuses search input when shortcut "s" is pressed' do expect(page).not_to have_selector('#search:focus') find('body').native.send_key('s') diff --git a/spec/features/graphql_known_operations_spec.rb b/spec/features/graphql_known_operations_spec.rb index ef406f12902..80214307be3 100644 --- a/spec/features/graphql_known_operations_spec.rb +++ b/spec/features/graphql_known_operations_spec.rb @@ -24,6 +24,6 @@ RSpec.describe 'Graphql known operations', :js do expect(known_operations).to include("searchProjects") expect(known_operations.length).to be > 20 - expect(known_operations).to all( match(%r{^[a-z]+}i) ) + expect(known_operations).to all(match(%r{^[a-z]+}i)) end end diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb index ab24162ad5a..e2c659d7dfe 100644 --- a/spec/features/group_variables_spec.rb +++ b/spec/features/group_variables_spec.rb @@ -11,23 +11,9 @@ RSpec.describe 'Group variables', :js do before do group.add_owner(user) gitlab_sign_in(user) + visit page_path wait_for_requests end - context 'with disabled ff `ci_variable_settings_graphql' do - before do - stub_feature_flags(ci_variable_settings_graphql: false) - visit page_path - end - - it_behaves_like 'variable list' - end - - context 'with enabled ff `ci_variable_settings_graphql' do - before do - visit page_path - end - - it_behaves_like 'variable list' - end + it_behaves_like 'variable list' end diff --git a/spec/features/groups/activity_spec.rb b/spec/features/groups/activity_spec.rb index 6ca69e76d33..5bac80959b1 100644 --- a/spec/features/groups/activity_spec.rb +++ b/spec/features/groups/activity_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'Group activity page' do - let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user } + let(:user) { create(:group_member, :developer, user: create(:user), group: group).user } let(:group) { create(:group) } let(:path) { activity_group_path(group) } diff --git a/spec/features/groups/board_sidebar_spec.rb b/spec/features/groups/board_sidebar_spec.rb index 69a6788e438..10ef28f3fbc 100644 --- a/spec/features/groups/board_sidebar_spec.rb +++ b/spec/features/groups/board_sidebar_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Group Issue Boards', :js do include BoardHelpers let(:group) { create(:group) } - let(:user) { create(:group_member, user: create(:user), group: group ).user } + let(:user) { create(:group_member, user: create(:user), group: group).user } let!(:project_1) { create(:project, :public, group: group) } let!(:project_2) { create(:project, :public, group: group) } let!(:project_1_label) { create(:label, project: project_1, name: 'Development 1') } @@ -19,6 +19,7 @@ RSpec.describe 'Group Issue Boards', :js do let(:card) { find('.board:nth-child(1)').first('.board-card') } before do + stub_feature_flags(apollo_boards: false) sign_in(user) visit group_board_path(group, board) diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb index 84882fc674e..f1a8f97461a 100644 --- a/spec/features/groups/empty_states_spec.rb +++ b/spec/features/groups/empty_states_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Group empty states' do let(:group) { create(:group) } - let(:user) { create(:group_member, :developer, user: create(:user), group: group ).user } + let(:user) { create(:group_member, :developer, user: create(:user), group: group).user } before do sign_in(user) diff --git a/spec/features/groups/group_runners_spec.rb b/spec/features/groups/group_runners_spec.rb index e9807c487d5..c9d1c69e9e1 100644 --- a/spec/features/groups/group_runners_spec.rb +++ b/spec/features/groups/group_runners_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe "Group Runners" do include Spec::Support::Helpers::Features::RunnersHelpers + include Spec::Support::Helpers::ModalHelpers let_it_be(:group_owner) { create(:user) } let_it_be(:group) { create(:group) } @@ -157,6 +158,19 @@ RSpec.describe "Group Runners" do end end + context "with multiple runners" do + before do + create(:ci_runner, :group, groups: [group], description: 'runner-foo') + create(:ci_runner, :group, groups: [group], description: 'runner-bar') + + visit group_runners_path(group) + end + + it_behaves_like 'deletes runners in bulk' do + let(:runner_count) { '2' } + end + end + describe 'filtered search' do before do visit group_runners_path(group) @@ -201,18 +215,32 @@ RSpec.describe "Group Runners" do end describe "Group runner edit page", :js do - let!(:group_runner) do - create(:ci_runner, :group, groups: [group]) - end + context 'when updating a group runner' do + let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) } - before do - visit edit_group_runner_path(group, group_runner) - wait_for_requests + before do + visit edit_group_runner_path(group, group_runner) + wait_for_requests + end + + it_behaves_like 'submits edit runner form' do + let(:runner) { group_runner } + let(:runner_page_path) { group_runner_path(group, group_runner) } + end end - it_behaves_like 'submits edit runner form' do - let(:runner) { group_runner } - let(:runner_page_path) { group_runner_path(group, group_runner) } + context 'when updating a project runner' do + let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) } + + before do + visit edit_group_runner_path(group, project_runner) + wait_for_requests + end + + it_behaves_like 'submits edit runner form' do + let(:runner) { project_runner } + let(:runner_page_path) { group_runner_path(group, project_runner) } + end end end end diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb index 2f599d24b01..81ff0088e1e 100644 --- a/spec/features/groups/group_settings_spec.rb +++ b/spec/features/groups/group_settings_spec.rb @@ -150,13 +150,15 @@ RSpec.describe 'Edit group settings' do it 'can successfully transfer the group' do visit edit_group_path(selected_group) - page.within('.js-group-transfer-form') do - namespace_select.find('button').click - namespace_select.find('.dropdown-menu p', text: target_group_name, match: :first).click - - click_button 'Transfer group' + page.within('[data-testid="transfer-locations-dropdown"]') do + click_button _('Select parent group') + fill_in _('Search'), with: target_group_name + wait_for_requests + click_button target_group_name end + click_button s_('GroupSettings|Transfer group') + page.within(confirm_modal) do expect(page).to have_text "You are going to transfer #{selected_group.name} to another namespace. Are you ABSOLUTELY sure?" @@ -169,16 +171,16 @@ RSpec.describe 'Edit group settings' do end end - context 'from a subgroup' do + context 'when transfering from a subgroup' do let(:selected_group) { create(:group, path: 'foo-subgroup', parent: group) } - context 'to no parent group' do + context 'when transfering to no parent group' do let(:target_group_name) { 'No parent group' } it_behaves_like 'can transfer the group' end - context 'to a different parent group' do + context 'when transfering to a parent group' do let(:target_group) { create(:group, path: 'foo-parentgroup') } let(:target_group_name) { target_group.name } @@ -190,14 +192,11 @@ RSpec.describe 'Edit group settings' do end end - context 'from a root group' do + context 'when transfering from a root group to a parent group' do let(:selected_group) { create(:group, path: 'foo-rootgroup') } + let(:target_group_name) { group.name } - context 'to a parent group' do - let(:target_group_name) { group.name } - - it_behaves_like 'can transfer the group' - end + it_behaves_like 'can transfer the group' end end diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb index eec07c84cde..d4e88505118 100644 --- a/spec/features/groups/issues_spec.rb +++ b/spec/features/groups/issues_spec.rb @@ -69,7 +69,7 @@ RSpec.describe 'Group issues page' do context 'issues list', :js do let(:subgroup) { create(:group, parent: group) } let(:subgroup_project) { create(:project, :public, group: subgroup) } - let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user } + let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group).user } let!(:issue) { create(:issue, project: project, title: 'root group issue') } let!(:subgroup_issue) { create(:issue, project: subgroup_project, title: 'subgroup issue') } @@ -111,7 +111,7 @@ RSpec.describe 'Group issues page' do context 'projects with issues disabled' do describe 'issue dropdown' do - let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user } + let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group).user } before do [project, project_with_issues_disabled].each { |project| project.add_maintainer(user_in_group) } @@ -129,7 +129,7 @@ RSpec.describe 'Group issues page' do end context 'manual ordering', :js do - let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user } + let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group).user } let!(:issue1) { create(:issue, project: project, title: 'Issue #1', relative_position: 1) } let!(:issue2) { create(:issue, project: project, title: 'Issue #2', relative_position: 2) } @@ -161,6 +161,8 @@ RSpec.describe 'Group issues page' do visit issues_group_path(group) select_manual_sort + wait_for_requests + drag_to(selector: '.manual-ordering', from_index: 0, to_index: 2) expect_issue_order @@ -176,6 +178,8 @@ RSpec.describe 'Group issues page' do visit issues_group_path(group) select_manual_sort + wait_for_requests + drag_to(selector: '.manual-ordering', from_index: 0, to_index: 2) expect(page).to have_text 'An error occurred while reordering issues.' @@ -195,7 +199,7 @@ RSpec.describe 'Group issues page' do end context 'issues pagination', :js do - let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user } + let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group).user } let!(:issues) do (1..25).to_a.map { |index| create(:issue, project: project, title: "Issue #{index}") } diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb index 42eaa8358a1..92a40459737 100644 --- a/spec/features/groups/milestone_spec.rb +++ b/spec/features/groups/milestone_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Group milestones' do let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project_empty_repo, group: group) } - let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user } + let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user } around do |example| freeze_time { example.run } diff --git a/spec/features/groups/milestones_sorting_spec.rb b/spec/features/groups/milestones_sorting_spec.rb index 125bf9ce3a7..6f3fc72775f 100644 --- a/spec/features/groups/milestones_sorting_spec.rb +++ b/spec/features/groups/milestones_sorting_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'Milestones sorting', :js do let!(:project_milestone2) { create(:milestone, project: project, title: 'v2.0', due_date: 5.days.from_now) } let!(:other_project_milestone2) { create(:milestone, project: other_project, title: 'v2.0', due_date: 5.days.from_now) } let!(:group_milestone) { create(:milestone, group: group, title: 'v3.0', due_date: 7.days.from_now) } - let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user } + let(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user } before do sign_in(user) diff --git a/spec/features/groups/settings/repository_spec.rb b/spec/features/groups/settings/repository_spec.rb index f6b8bbdd35f..cd7dcbdb28d 100644 --- a/spec/features/groups/settings/repository_spec.rb +++ b/spec/features/groups/settings/repository_spec.rb @@ -23,26 +23,9 @@ RSpec.describe 'Group Repository settings', :js do stub_container_registry_config(enabled: true) end - context 'when ajax deploy tokens is enabled' do - before do - stub_feature_flags(ajax_new_deploy_token: true) - end - - it_behaves_like 'a deploy token in settings' do - let(:entity_type) { 'group' } - let(:page_path) { group_settings_repository_path(group) } - end - end - - context 'when ajax deploy tokens is disabled' do - before do - stub_feature_flags(ajax_new_deploy_token: false) - end - - it_behaves_like 'a deploy token in settings' do - let(:entity_type) { 'group' } - let(:page_path) { group_settings_repository_path(group) } - end + it_behaves_like 'a deploy token in settings' do + let(:entity_type) { 'group' } + let(:page_path) { group_settings_repository_path(group) } end end diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index 546257b9f10..eef48d09f32 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -41,7 +41,7 @@ RSpec.describe 'Help Pages' do end it 'renders the version check badge' do - expect(page).to have_selector('.js-gitlab-version-check') + expect(page).to have_selector('.js-gitlab-version-check-badge') end end diff --git a/spec/features/ide/user_opens_merge_request_spec.rb b/spec/features/ide/user_opens_merge_request_spec.rb index 8a95d7c5544..4ffa5212970 100644 --- a/spec/features/ide/user_opens_merge_request_spec.rb +++ b/spec/features/ide/user_opens_merge_request_spec.rb @@ -21,6 +21,6 @@ RSpec.describe 'IDE merge request', :js do wait_for_requests - expect(page).to have_selector('.monaco-diff-editor') + expect(page).not_to have_selector('.monaco-diff-editor') end end diff --git a/spec/features/ide_spec.rb b/spec/features/ide_spec.rb index c7c740c2293..1f6d34efc0f 100644 --- a/spec/features/ide_spec.rb +++ b/spec/features/ide_spec.rb @@ -3,47 +3,90 @@ require 'spec_helper' RSpec.describe 'IDE', :js do - describe 'sub-groups' do - let(:ide_iframe_selector) { '#ide iframe' } - let(:user) { create(:user) } - let(:group) { create(:group) } - let(:subgroup) { create(:group, parent: group) } - let(:subgroup_project) { create(:project, :repository, namespace: subgroup) } + include WebIdeSpecHelpers + + let_it_be(:ide_iframe_selector) { '#ide iframe' } + let_it_be(:normal_project) { create(:project, :repository) } + + let(:project) { normal_project } + let(:vscode_ff) { false } + let(:user) { create(:user) } + + before do + project.add_maintainer(user) + stub_feature_flags(vscode_web_ide: vscode_ff) + + sign_in(user) + end + + shared_examples "legacy Web IDE" do + it 'loads legacy Web IDE', :aggregate_failures do + expect(page).to have_selector('.context-header', text: project.name) + + # Assert new Web IDE is not loaded + expect(page).not_to have_selector(ide_iframe_selector) + end + end + + shared_examples "new Web IDE" do + it 'loads new Web IDE', :aggregate_failures do + expect(page).not_to have_selector('.context-header') + + iframe = find(ide_iframe_selector) + + page.within_frame(iframe) do + expect(page).to have_selector('.title', text: project.name.upcase) + end + end + end + context 'with vscode feature flag off' do before do - stub_feature_flags(vscode_web_ide: vscode_ff) - subgroup_project.add_maintainer(user) - sign_in(user) + ide_visit(project) + end - visit project_path(subgroup_project) + it_behaves_like 'legacy Web IDE' - click_link('Web IDE') + it 'does not show switch button' do + expect(page).not_to have_button('Switch to new Web IDE') + end + end + + context 'with vscode feature flag on and use_legacy_web_ide=true' do + let(:vscode_ff) { true } + let(:user) { create(:user, use_legacy_web_ide: true) } - wait_for_requests + before do + ide_visit(project) end - context 'with vscode feature flag on' do - let(:vscode_ff) { true } + it_behaves_like 'legacy Web IDE' - it 'loads project in Web IDE' do - iframe = find(ide_iframe_selector) + describe 'when user switches to new Web IDE' do + before do + click_button('Switch to new Web IDE') - page.within_frame(iframe) do - expect(page).to have_selector('.title', text: subgroup_project.name.upcase) + # Confirm modal + page.within('#confirmationModal') do + click_button('Switch editors') end end + + it_behaves_like 'new Web IDE' end + end - context 'with vscode feature flag off' do - let(:vscode_ff) { false } + describe 'sub-groups' do + let_it_be(:group) { create(:group) } + let_it_be(:subgroup) { create(:group, parent: group) } + let_it_be(:subgroup_project) { create(:project, :repository, namespace: subgroup) } - it 'loads project in legacy Web IDE' do - expect(page).to have_selector('.context-header', text: subgroup_project.name) - end + let(:project) { subgroup_project } - it 'does not load new Web IDE' do - expect(page).not_to have_selector(ide_iframe_selector) - end + before do + ide_visit(project) end + + it_behaves_like 'legacy Web IDE' end end diff --git a/spec/features/incidents/user_views_incident_spec.rb b/spec/features/incidents/user_views_incident_spec.rb index a669966502e..054a084ea9c 100644 --- a/spec/features/incidents/user_views_incident_spec.rb +++ b/spec/features/incidents/user_views_incident_spec.rb @@ -4,12 +4,16 @@ require "spec_helper" RSpec.describe "User views incident" do let_it_be(:project) { create(:project_empty_repo, :public) } - let_it_be(:user) { create(:user) } - let_it_be(:incident) { create(:incident, project: project, description: "# Description header\n\n**Lorem** _ipsum_ dolor sit [amet](https://example.com)", author: user) } - let_it_be(:note) { create(:note, noteable: incident, project: project, author: user) } + let_it_be(:guest) { create(:user) } + let_it_be(:developer) { create(:user) } + let_it_be(:user) { developer } + let(:author) { developer } + let(:description) { "# Description header\n\n**Lorem** _ipsum_ dolor sit [amet](https://example.com)" } + let(:incident) { create(:incident, project: project, description: description, author: author) } before_all do - project.add_developer(user) + project.add_developer(developer) + project.add_guest(guest) end before do @@ -18,57 +22,61 @@ RSpec.describe "User views incident" do visit(project_issues_incident_path(project, incident)) end - it { expect(page).to have_header_with_correct_id_and_link(1, "Description header", "description-header") } + specify do + expect(page).to have_header_with_correct_id_and_link(1, 'Description header', 'description-header') + end it_behaves_like 'page meta description', ' Description header Lorem ipsum dolor sit amet' describe 'user actions' do it 'shows the merge request and incident actions', :js, :aggregate_failures do + expected_href = new_project_issue_path(project, + issuable_template: 'incident', + issue: { issue_type: 'incident' }, + add_related_issue: incident.iid) + click_button 'Incident actions' - expect(page).to have_link('New related incident', href: new_project_issue_path(project, { issuable_template: 'incident', issue: { issue_type: 'incident' }, add_related_issue: incident.iid })) + expect(page).to have_link('New related incident', href: expected_href) expect(page).to have_button('Create merge request') expect(page).to have_button('Close incident') end - context 'when user is a guest' do - before do - project.add_guest(user) + context 'when user is guest' do + let(:user) { guest } - login_as(user) + context 'and author' do + let(:author) { guest } - visit(project_issues_incident_path(project, incident)) + it 'does not show the incident actions', :js do + expect(page).not_to have_button('Incident actions') + end end - it 'does not show the incident actions', :js, :aggregate_failures do - expect(page).not_to have_button('Incident actions') + context 'and not author' do + it 'shows incident actions', :js do + click_button 'Incident actions' + + expect(page).to have_link 'Report abuse' + end end end end context 'when the project is archived' do - before do + before_all do project.update!(archived: true) - visit(project_issues_incident_path(project, incident)) end - it 'hides the merge request and incident actions', :aggregate_failures do - expect(page).not_to have_link('New incident') - expect(page).not_to have_button('Create merge request') - expect(page).not_to have_link('Close incident') + it 'does not show the incident actions', :js do + expect(page).not_to have_button('Incident actions') end end describe 'user status' do - subject { visit(project_issues_incident_path(project, incident)) } - context 'when showing status of the author of the incident' do - it_behaves_like 'showing user status' do - let(:user_with_status) { user } - end - end + subject { visit(project_issues_incident_path(project, incident)) } - context 'when showing status of a user who commented on an incident', :js do it_behaves_like 'showing user status' do let(:user_with_status) { user } end diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb index ab7c0ce2891..c5a8e9f367c 100644 --- a/spec/features/issuables/markdown_references/internal_references_spec.rb +++ b/spec/features/issuables/markdown_references/internal_references_spec.rb @@ -21,15 +21,17 @@ RSpec.describe "Internal references", :js do sign_in(private_project_user) visit(project_issue_path(private_project, private_project_issue)) + wait_for_requests add_note("##{public_project_issue.to_reference(private_project)}") end - context "when user doesn't have access to private project", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do + context "when user doesn't have access to private project" do before do sign_in(public_project_user) visit(project_issue_path(public_project, public_project_issue)) + wait_for_requests end it { expect(page).not_to have_css(".note") } @@ -41,6 +43,7 @@ RSpec.describe "Internal references", :js do sign_in(private_project_user) visit(project_merge_request_path(private_project, private_project_merge_request)) + wait_for_requests add_note("##{public_project_issue.to_reference(private_project)}") end @@ -50,9 +53,10 @@ RSpec.describe "Internal references", :js do sign_in(public_project_user) visit(project_issue_path(public_project, public_project_issue)) + wait_for_requests end - it "doesn't show any references", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do + it "doesn't show any references" do expect(page).not_to have_text 'Related merge requests' end end @@ -60,6 +64,7 @@ RSpec.describe "Internal references", :js do context "when user has access to private project" do before do visit(project_issue_path(public_project, public_project_issue)) + wait_for_requests end it "shows references", :sidekiq_might_not_need_inline do @@ -85,15 +90,17 @@ RSpec.describe "Internal references", :js do sign_in(private_project_user) visit(project_issue_path(private_project, private_project_issue)) + wait_for_requests add_note("##{public_project_merge_request.to_reference(private_project)}") end - context "when user doesn't have access to private project", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do + context "when user doesn't have access to private project" do before do sign_in(public_project_user) visit(project_merge_request_path(public_project, public_project_merge_request)) + wait_for_requests end it { expect(page).not_to have_css(".note") } @@ -105,6 +112,7 @@ RSpec.describe "Internal references", :js do sign_in(private_project_user) visit(project_merge_request_path(private_project, private_project_merge_request)) + wait_for_requests add_note("##{public_project_merge_request.to_reference(private_project)}") end @@ -114,9 +122,10 @@ RSpec.describe "Internal references", :js do sign_in(public_project_user) visit(project_merge_request_path(public_project, public_project_merge_request)) + wait_for_requests end - it "doesn't show any references", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/257832' do + it "doesn't show any references" do expect(page).not_to have_text 'Related merge requests' end end @@ -124,6 +133,7 @@ RSpec.describe "Internal references", :js do context "when user has access to private project" do before do visit(project_merge_request_path(public_project, public_project_merge_request)) + wait_for_requests end it "shows references", :sidekiq_might_not_need_inline do diff --git a/spec/features/issues/confidential_notes_spec.rb b/spec/features/issues/confidential_notes_spec.rb new file mode 100644 index 00000000000..858c054c803 --- /dev/null +++ b/spec/features/issues/confidential_notes_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "Confidential notes on issues", :js do + it_behaves_like 'confidential notes on issuables' do + let_it_be(:issuable_parent) { create(:project) } + let_it_be(:issuable) { create(:issue, project: issuable_parent) } + let_it_be(:user) { create(:user) } + + let(:issuable_path) { project_issue_path(issuable_parent, issuable) } + end +end diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb index 05eb656461e..40b0bfd9aa4 100644 --- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb @@ -9,6 +9,10 @@ RSpec.describe 'Dropdown assignee', :js do let_it_be(:user) { create(:user) } let_it_be(:issue) { create(:issue, project: project) } + before do + stub_feature_flags(or_issuable_queries: false) + end + describe 'behavior' do before do project.add_maintainer(user) diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb index 36a8f1f3902..a67d114c6d1 100644 --- a/spec/features/issues/filtered_search/dropdown_author_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb @@ -10,6 +10,7 @@ RSpec.describe 'Dropdown author', :js do let_it_be(:issue) { create(:issue, project: project) } before do + stub_feature_flags(or_issuable_queries: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb index dcbab308efa..cbe917931aa 100644 --- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb @@ -10,6 +10,7 @@ RSpec.describe 'Dropdown hint', :js do let_it_be(:issue) { create(:issue, project: project) } before do + stub_feature_flags(or_issuable_queries: false) project.add_maintainer(user) end diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index 8d96bbc38cb..e48df1b1c53 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -19,6 +19,7 @@ RSpec.describe 'Filter issues', :js do end before do + stub_feature_flags(or_issuable_queries: false) project.add_maintainer(user) create(:issue, project: project, author: user2, title: "Bug report 1") diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb index c44181a60e4..854b88c3f81 100644 --- a/spec/features/issues/filtered_search/visual_tokens_spec.rb +++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb @@ -15,6 +15,7 @@ RSpec.describe 'Visual tokens', :js do let_it_be(:issue) { create(:issue, project: project) } before do + stub_feature_flags(or_issuable_queries: false) project.add_member(user, :maintainer) project.add_member(user_rock, :maintainer) sign_in(user) diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index e749c555dcf..fe591d7fe3a 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -140,14 +140,10 @@ RSpec.describe 'New/edit issue', :js do end expect(find('a', text: 'Assign to me', visible: false)).not_to be_visible - click_button 'Milestone' - page.within '.issue-milestone' do - click_link milestone.title - end + click_button 'Select milestone' + click_button milestone.title expect(find('input[name="issue[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) - page.within '.js-milestone-select' do - expect(page).to have_content milestone.title - end + expect(page).to have_button milestone.title click_button 'Labels' page.within '.dropdown-menu-labels' do @@ -307,14 +303,11 @@ RSpec.describe 'New/edit issue', :js do end it 'escapes milestone' do - click_button 'Milestone' + click_button 'Select milestone' + click_button milestone.title page.within '.issue-milestone' do - click_link milestone.title - end - - page.within '.js-milestone-select' do - expect(page).to have_content milestone.title + expect(page).to have_button milestone.title expect(page).not_to have_selector 'img' end end @@ -444,9 +437,7 @@ RSpec.describe 'New/edit issue', :js do expect(page).to have_content user.name end - page.within '.js-milestone-select' do - expect(page).to have_content milestone.title - end + expect(page).to have_button milestone.title click_button 'Labels' page.within '.dropdown-menu-labels' do diff --git a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb index 4837d13574c..2a201e0bc23 100644 --- a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb +++ b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb @@ -417,7 +417,7 @@ RSpec.describe 'Issues > Labels bulk assignment' do click_button 'Select milestone' wait_for_requests items.map do |item| - click_link item + click_button item end end diff --git a/spec/features/issues/user_bulk_edits_issues_spec.rb b/spec/features/issues/user_bulk_edits_issues_spec.rb index 1ef2918adec..d7fad355cb4 100644 --- a/spec/features/issues/user_bulk_edits_issues_spec.rb +++ b/spec/features/issues/user_bulk_edits_issues_spec.rb @@ -80,7 +80,7 @@ RSpec.describe 'Multiple issue updating from issues#index', :js do click_button 'Edit issues' check 'Select all' click_button 'Select milestone' - click_link milestone.title + click_button milestone.title click_update_issues_button expect(page.find('.issue')).to have_content milestone.title @@ -97,7 +97,7 @@ RSpec.describe 'Multiple issue updating from issues#index', :js do click_button 'Edit issues' check 'Select all' click_button 'Select milestone' - click_link 'No milestone' + click_button 'No milestone' click_update_issues_button expect(find('.issue:first-of-type')).not_to have_text milestone.title diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb index a1e7c007b90..ef00e66af7e 100644 --- a/spec/features/issues/user_comments_on_issue_spec.rb +++ b/spec/features/issues/user_comments_on_issue_spec.rb @@ -5,9 +5,9 @@ require "spec_helper" RSpec.describe "User comments on issue", :js do include Spec::Support::Helpers::Features::NotesHelpers - let(:project) { create(:project_empty_repo, :public) } - let(:issue) { create(:issue, project: project) } - let(:user) { create(:user) } + let_it_be(:project) { create(:project, :public) } + let_it_be(:issue) { create(:issue, project: project) } + let_it_be(:user) { create(:user) } before do project.add_guest(user) diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb index b96490bd7e7..1d023a15159 100644 --- a/spec/features/issues/user_creates_issue_spec.rb +++ b/spec/features/issues/user_creates_issue_spec.rb @@ -188,7 +188,7 @@ RSpec.describe "User creates issue" do end it 'does not hide the milestone select' do - expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]') + expect(page).to have_button 'Select milestone' end end @@ -204,7 +204,7 @@ RSpec.describe "User creates issue" do end it 'shows the milestone select' do - expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]') + expect(page).to have_button 'Select milestone' end it 'hides the incident help text' do @@ -265,7 +265,7 @@ RSpec.describe "User creates issue" do end it 'shows the milestone select' do - expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]') + expect(page).to have_button 'Select milestone' end it 'hides the weight input' do diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb index 4eecb63c47e..75df85f362f 100644 --- a/spec/features/issues/user_edits_issue_spec.rb +++ b/spec/features/issues/user_edits_issue_spec.rb @@ -101,6 +101,35 @@ RSpec.describe "Issues > User edits issue", :js do visit project_issue_path(project, issue) end + describe 'edit description' do + def click_edit_issue_description + click_on 'Edit title and description' + end + + it 'places focus on the web editor' do + toggle_editing_mode_selector = '[data-testid="toggle-editing-mode-button"] label' + content_editor_focused_selector = '[data-testid="content-editor"].is-focused' + markdown_field_focused_selector = 'textarea:focus' + click_edit_issue_description + + expect(page).to have_selector(markdown_field_focused_selector) + + find(toggle_editing_mode_selector, text: 'Rich text').click + + expect(page).not_to have_selector(content_editor_focused_selector) + + refresh + + click_edit_issue_description + + expect(page).to have_selector(content_editor_focused_selector) + + find(toggle_editing_mode_selector, text: 'Source').click + + expect(page).not_to have_selector(markdown_field_focused_selector) + end + end + describe 'update labels' do it 'will not send ajax request when no data is changed' do page.within '.labels' do @@ -186,7 +215,7 @@ RSpec.describe "Issues > User edits issue", :js do visit project_issue_path(project, issue) page.within('.assignee') do - expect(page).to have_content "#{user.name}" + expect(page).to have_content user.name.to_s click_link 'Edit' click_link 'Unassigned' @@ -261,7 +290,7 @@ RSpec.describe "Issues > User edits issue", :js do visit project_issue_path(project, issue) page.within('.assignee') do - expect(page).to have_content "#{user.name}" + expect(page).to have_content user.name.to_s click_button('Edit') wait_for_requests diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb index 47b28b88108..a2dea7f048b 100644 --- a/spec/features/issues/user_interacts_with_awards_spec.rb +++ b/spec/features/issues/user_interacts_with_awards_spec.rb @@ -209,22 +209,25 @@ RSpec.describe 'User interacts with awards' do it 'adds award to issue' do first('[data-testid="award-button"]').click - + wait_for_requests expect(page).to have_selector('[data-testid="award-button"].selected') expect(first('[data-testid="award-button"]')).to have_content '1' visit project_issue_path(project, issue) + wait_for_requests expect(first('[data-testid="award-button"]')).to have_content '1' end it 'removes award from issue', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375241' do first('[data-testid="award-button"]').click + wait_for_requests find('[data-testid="award-button"].selected').click - + wait_for_requests expect(first('[data-testid="award-button"]')).to have_content '0' visit project_issue_path(project, issue) + wait_for_requests expect(first('[data-testid="award-button"]')).to have_content '0' end diff --git a/spec/features/issues/user_sees_empty_state_spec.rb b/spec/features/issues/user_sees_empty_state_spec.rb index 0e2a7cb4358..b4c5a57de4f 100644 --- a/spec/features/issues/user_sees_empty_state_spec.rb +++ b/spec/features/issues/user_sees_empty_state_spec.rb @@ -22,9 +22,9 @@ RSpec.describe 'Issues > User sees empty state', :js do it 'user sees empty state' do visit project_issues_path(project) + expect(page).to have_content('Use issues to collaborate on ideas, solve problems, and plan work') + expect(page).to have_content('Learn more about issues.') expect(page).to have_content('Register / Sign In') - expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project.') - expect(page).to have_content('You can register or sign in to create issues for this project.') end it_behaves_like 'empty state with filters' diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb index 7add6c782f7..2716d742be3 100644 --- a/spec/features/issues/user_sorts_issues_spec.rb +++ b/spec/features/issues/user_sorts_issues_spec.rb @@ -24,7 +24,7 @@ RSpec.describe "User sorts issues" do sign_in(user) end - it 'keeps the sort option', :js do + it 'keeps the sort option', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/378184' do visit(project_issues_path(project)) click_button 'Created date' diff --git a/spec/features/jira_connect/subscriptions_spec.rb b/spec/features/jira_connect/subscriptions_spec.rb index 94c293c88b9..0468cfd70fc 100644 --- a/spec/features/jira_connect/subscriptions_spec.rb +++ b/spec/features/jira_connect/subscriptions_spec.rb @@ -30,7 +30,7 @@ RSpec.describe 'Subscriptions Content Security Policy' do p.style_src :self, 'https://some-cdn.test' end - setup_existing_csp_for_controller(JiraConnect::SubscriptionsController, csp) + setup_csp_for_controller(JiraConnect::SubscriptionsController, csp) end it 'appends to CSP directives' do diff --git a/spec/features/markdown/sandboxed_mermaid_spec.rb b/spec/features/markdown/sandboxed_mermaid_spec.rb index 05fe83b3107..2bf88d7882d 100644 --- a/spec/features/markdown/sandboxed_mermaid_spec.rb +++ b/spec/features/markdown/sandboxed_mermaid_spec.rb @@ -3,30 +3,54 @@ require 'spec_helper' RSpec.describe 'Sandboxed Mermaid rendering', :js do - let_it_be(:project) { create(:project, :public) } + let_it_be(:project) { create(:project, :public, :repository) } + let_it_be(:description) do + <<~MERMAID + ```mermaid + graph TD; + A-->B; + A-->C; + B-->D; + C-->D; + ``` + MERMAID + end - before do - stub_feature_flags(sandboxed_mermaid: true) + let_it_be(:expected) do + %(<iframe src="/-/sandbox/mermaid" sandbox="allow-scripts allow-popups" frameborder="0" scrolling="no") end - it 'includes mermaid frame correctly' do - description = <<~MERMAID - ```mermaid - graph TD; - A-->B; - A-->C; - B-->D; - C-->D; - ``` - MERMAID + context 'in an issue' do + let(:issue) { create(:issue, project: project, description: description) } + + it 'includes mermaid frame correctly' do + visit project_issue_path(project, issue) + + wait_for_requests + + expect(page.html).to include(expected) + end + end + + context 'in a merge request' do + let(:merge_request) { create(:merge_request_with_diffs, source_project: project, description: description) } + + it 'renders diffs and includes mermaid frame correctly' do + visit(diffs_project_merge_request_path(project, merge_request)) + + wait_for_requests - issue = create(:issue, project: project, description: description) + page.within('.tab-content') do + expect(page).to have_selector('.diffs') + end - visit project_issue_path(project, issue) + visit(project_merge_request_path(project, merge_request)) - wait_for_requests + wait_for_requests - expected = %(<iframe src="/-/sandbox/mermaid" sandbox="allow-scripts allow-popups" frameborder="0" scrolling="no") - expect(page.html).to include(expected) + page.within('.merge-request') do + expect(page.html).to include(expected) + end + end end end diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb index 159306b28d8..b50e6779e07 100644 --- a/spec/features/merge_request/user_accepts_merge_request_spec.rb +++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb @@ -18,6 +18,8 @@ RSpec.describe 'User accepts a merge request', :js, :sidekiq_might_not_need_inli click_button('Merge') + puts merge_request.short_merged_commit_sha + expect(page).to have_content("Changes merged into #{merge_request.target_branch} with #{merge_request.short_merged_commit_sha}") end diff --git a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb index 0dd87ac3e24..59b5923b2a1 100644 --- a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb +++ b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb @@ -88,7 +88,7 @@ RSpec.describe 'Merge request > User edits assignees sidebar', :js do end context 'when GraphQL assignees widget feature flag is enabled' do - let(:sidebar_assignee_dropdown_item) { sidebar_assignee_block.find(".dropdown-item", text: assignee.username ) } + let(:sidebar_assignee_dropdown_item) { sidebar_assignee_block.find(".dropdown-item", text: assignee.username) } let(:sidebar_assignee_dropdown_tooltip) { sidebar_assignee_dropdown_item['title'] } context 'when user is an owner' do diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb index 21f96299958..abf916c72b3 100644 --- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb @@ -151,7 +151,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do # Wait for the `ci_status` and `merge_check` requests wait_for_requests - page.within('.mr-section-container') do + page.within('.mr-state-widget') do expect(page).to have_content('Something went wrong. Try again.') end end @@ -170,7 +170,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do # Wait for the `ci_status` and `merge_check` requests wait_for_requests - page.within('.mr-section-container') do + page.within('.mr-state-widget') do expect(page).to have_content('Something went wrong. Try again.') end end diff --git a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb index 60ea168940a..cf4875a7a25 100644 --- a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb +++ b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb @@ -19,7 +19,7 @@ RSpec.describe 'Merge request > User scrolls to note on load', :js do wait_for_all_requests - expect(page).to have_selector("#{fragment_id}") + expect(page).to have_selector(fragment_id.to_s) page_scroll_y = page.evaluate_script("window.scrollY") fragment_position_top = page.evaluate_script("Math.round(document.querySelector('#{fragment_id}').getBoundingClientRect().top + window.pageYOffset)") diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb index 63ac7862b06..6f8ecf5f5c2 100644 --- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb +++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb @@ -18,6 +18,11 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do let(:build) { create(:ci_build, :with_deployment, environment: environment.name, pipeline: pipeline) } let!(:deployment) { build.deployment } + def assert_env_widget(text, env_name) + expect(find('.js-deploy-env-name')[:title]).to have_text(env_name) + expect(page).to have_content(text) + end + before do merge_request.update!(merge_commit_sha: sha) project.add_member(user, role) @@ -33,7 +38,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do visit project_merge_request_path(project, merge_request) wait_for_requests - expect(page).to have_content("Deployed to #{environment.name}") + assert_env_widget("Deployed to", environment.name) expect(find('.js-deploy-time')['title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium)) end @@ -47,8 +52,8 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do wait_for_requests expect(page).to have_selector('.js-deployment-info', count: 1) - expect(page).to have_content("#{environment.name}") - expect(page).not_to have_content("#{environment2.name}") + expect(find('.js-deploy-env-name')[:title]).to have_text(environment.name) + expect(find('.js-deploy-env-name')[:title]).not_to have_text(environment2.name) end end end @@ -62,7 +67,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do visit project_merge_request_path(project, merge_request) wait_for_requests - expect(page).to have_content("Failed to deploy to #{environment.name}") + assert_env_widget("Failed to deploy to", environment.name) expect(page).not_to have_css('.js-deploy-time') end end @@ -76,7 +81,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do visit project_merge_request_path(project, merge_request) wait_for_requests - expect(page).to have_content("Deploying to #{environment.name}") + assert_env_widget("Deploying to", environment.name) expect(page).not_to have_css('.js-deploy-time') end end @@ -89,7 +94,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do visit project_merge_request_path(project, merge_request) wait_for_requests - expect(page).to have_content("Will deploy to #{environment.name}") + assert_env_widget("Will deploy to", environment.name) expect(page).not_to have_css('.js-deploy-time') end end @@ -103,7 +108,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do visit project_merge_request_path(project, merge_request) wait_for_requests - expect(page).to have_content("Canceled deployment to #{environment.name}") + assert_env_widget("Canceled deployment to", environment.name) expect(page).not_to have_css('.js-deploy-time') end end diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb index 2e65183d26f..0bae019793c 100644 --- a/spec/features/merge_request/user_sees_diff_spec.rb +++ b/spec/features/merge_request/user_sees_diff_spec.rb @@ -38,6 +38,20 @@ RSpec.describe 'Merge request > User sees diff', :js do end end + context 'when linking to a line' do + let(:note) { create :diff_note_on_merge_request, project: project, noteable: merge_request } + let(:line) { note.diff_file.highlighted_diff_lines.last } + let(:line_code) { line.line_code } + + before do + visit "#{diffs_project_merge_request_path(project, merge_request)}##{line_code}" + end + + it 'shows the linked line' do + expect(page).to have_selector("[id='#{line_code}']", visible: true, obscured: false) + end + end + context 'when merge request has overflow' do it 'displays warning' do allow(Commit).to receive(:max_diff_options).and_return(max_files: 3) diff --git a/spec/features/merge_request/user_sees_discussions_navigation_spec.rb b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb new file mode 100644 index 00000000000..9fbe7662fc0 --- /dev/null +++ b/spec/features/merge_request/user_sees_discussions_navigation_spec.rb @@ -0,0 +1,222 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Merge request > User sees discussions navigation', :js do + let_it_be(:project) { create(:project, :public, :repository) } + let_it_be(:user) { project.creator } + let_it_be(:merge_request) { create(:merge_request, source_project: project) } + + before do + # FIXME: before removing this please fix discussions navigation with this flag enabled + stub_feature_flags(moved_mr_sidebar: false) + project.add_maintainer(user) + sign_in(user) + end + + describe 'Code discussions' do + let!(:position) do + build(:text_diff_position, :added, + file: "files/images/wm.svg", + new_line: 1, + diff_refs: merge_request.diff_refs + ) + end + + let!(:first_discussion) do + create(:diff_note_on_merge_request, + noteable: merge_request, + project: project, + position: position + ).to_discussion + end + + let!(:second_discussion) do + create(:diff_note_on_merge_request, + noteable: merge_request, + project: project, + position: position + ).to_discussion + end + + let(:first_discussion_selector) { ".discussion[data-discussion-id='#{first_discussion.id}']" } + let(:second_discussion_selector) { ".discussion[data-discussion-id='#{second_discussion.id}']" } + + shared_examples 'a page with a thread navigation' do + context 'with active threads' do + it 'navigates to the first thread' do + goto_next_thread + expect(page).to have_selector(first_discussion_selector, obscured: false) + end + + it 'navigates to the last thread' do + goto_previous_thread + expect(page).to have_selector(second_discussion_selector, obscured: false) + end + + it 'navigates through active threads' do + goto_next_thread + goto_next_thread + expect(page).to have_selector(second_discussion_selector, obscured: false) + end + + it 'cycles back to the first thread' do + goto_next_thread + goto_next_thread + goto_next_thread + expect(page).to have_selector(first_discussion_selector, obscured: false) + end + + it 'cycles back to the last thread' do + goto_previous_thread + goto_previous_thread + goto_previous_thread + expect(page).to have_selector(second_discussion_selector, obscured: false) + end + end + + context 'with resolved threads' do + let!(:resolved_discussion) do + create(:diff_note_on_merge_request, + noteable: merge_request, + project: project, + position: position + ).to_discussion + end + + let(:resolved_discussion_selector) { ".discussion[data-discussion-id='#{resolved_discussion.id}']" } + + before do + # :resolved attr doesn't actually resolve the thread but just collapses it + page.within(resolved_discussion_selector) do + click_button text: 'Resolve thread' + end + page.execute_script("window.scrollTo(0,0)") + end + + it 'excludes resolved threads during navigation' do + goto_next_thread + goto_next_thread + goto_next_thread + expect(page).to have_selector(first_discussion_selector, obscured: false) + end + end + end + + describe "Overview page discussions navigation" do + before do + visit project_merge_request_path(project, merge_request) + end + + it_behaves_like 'a page with a thread navigation' + + context 'with collapsed threads' do + before do + page.within(first_discussion_selector) do + click_button 'Hide thread' + end + end + + it 'expands threads during navigation' do + goto_next_thread + expect(page).to have_selector "#note_#{first_discussion.first_note.id}" + end + end + end + + describe "Changes page discussions navigation" do + before do + visit diffs_project_merge_request_path(project, merge_request) + end + + it_behaves_like 'a page with a thread navigation' + end + end + + describe 'Merge request discussions' do + shared_examples 'a page with no code discussions' do + let!(:first_discussion) do + create(:discussion_note_on_merge_request, + noteable: merge_request, + project: project + ).to_discussion + end + + let!(:second_discussion) do + create(:discussion_note_on_merge_request, + noteable: merge_request, + project: project + ).to_discussion + end + + let(:first_discussion_selector) { ".discussion[data-discussion-id='#{first_discussion.id}']" } + let(:second_discussion_selector) { ".discussion[data-discussion-id='#{second_discussion.id}']" } + + describe "Changes page discussions navigation" do + it 'navigates to the first discussion on the Overview page' do + goto_next_thread + expect(page).to have_selector(first_discussion_selector, obscured: false) + end + + it 'navigates to the last discussion on the Overview page' do + goto_previous_thread + expect(page).to have_selector(second_discussion_selector, obscured: false) + end + end + end + + context 'on changes page' do + before do + visit diffs_project_merge_request_path(project, merge_request) + end + + it_behaves_like 'a page with no code discussions' + end + + context 'on commits page' do + before do + # we can't go directly to the commits page since it doesn't load discussions + visit project_merge_request_path(project, merge_request) + click_link 'Commits' + end + + it_behaves_like 'a page with no code discussions' + end + + context 'on pipelines page' do + before do + visit project_merge_request_path(project, merge_request) + click_link 'Pipelines' + end + + it_behaves_like 'a page with no code discussions' + end + end + + def goto_next_thread + begin + # this is required when moved_mr_sidebar is enabled + page.within('.issue-sticky-header') do + click_button 'Go to next unresolved thread' + end + rescue StandardError + click_button 'Go to next unresolved thread' + end + wait_for_scroll_end + end + + def goto_previous_thread + begin + page.within('.issue-sticky-header') do + click_button 'Go to previous unresolved thread' + end + rescue StandardError + click_button 'Go to previous unresolved thread' + end + wait_for_scroll_end + end + + def wait_for_scroll_end + sleep(1) + end +end diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index 77ac6fac22f..c4a29c1fb07 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -14,15 +14,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do let(:merge_request_in_only_mwps_project) { create(:merge_request, source_project: project_only_mwps) } def click_expand_button - find('[data-testid="report-section-expand-button"]').click + find('[data-testid="toggle-button"]').click end before do project.add_maintainer(user) project_only_mwps.add_maintainer(user) sign_in(user) - - stub_feature_flags(refactor_mr_widget_test_summary: false) end context 'new merge request', :sidekiq_might_not_need_inline do @@ -64,7 +62,8 @@ RSpec.describe 'Merge request > User sees merge widget', :js do wait_for_requests page.within('.js-pre-deployment') do - expect(page).to have_content("Deployed to #{environment.name}") + expect(find('.js-deploy-env-name')[:title]).to have_text(environment.name) + expect(page).to have_content("Deployed to") expect(find('.js-deploy-url')[:href]).to include(environment.formatted_external_url) end end @@ -343,7 +342,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do # Wait for the `ci_status` and `merge_check` requests wait_for_requests - page.within('.mr-section-container') do + page.within('.mr-state-widget') do expect(page).to have_content('Something went wrong.') end end @@ -364,7 +363,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do # Wait for the `ci_status` and `merge_check` requests wait_for_requests - page.within('.mr-section-container') do + page.within('.mr-state-widget') do expect(page).to have_content('Something went wrong.') end end @@ -399,9 +398,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do it 'updates the MR widget', :sidekiq_might_not_need_inline do click_button 'Merge' - page.within('.mr-widget-body') do - expect(page).to have_content('An error occurred while merging') - end + expect(page).to have_content('An error occurred while merging') end end @@ -531,7 +528,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows parsing status' do - expect(page).to have_content('Test summary results are being parsed') + expect(page).to have_content('Test summary results are loading') end end @@ -546,7 +543,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows parsed results' do - expect(page).to have_content('Test summary contained') + expect(page).to have_content('Test summary:') end end @@ -560,7 +557,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows the error state' do - expect(page).to have_content('Test summary failed loading results') + expect(page).to have_content('Test summary failed to load results') end end @@ -607,13 +604,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows test reports summary which includes the new failure' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - expect(page).to have_content('Test summary contained 1 failed out of 2 total tests') - within(".js-report-section-container") do - expect(page).to have_content('rspec found no changed test results out of 1 total test') - expect(page).to have_content('junit found 1 failed out of 1 total test') + expect(page).to have_content('Test summary: 1 failed, 2 total tests') + within('[data-testid="widget-extension-collapsed-section"]') do + expect(page).to have_content('rspec: no changed test results, 1 total test') + expect(page).to have_content('junit: 1 failed, 1 total test') expect(page).to have_content('New') expect(page).to have_content('addTest') end @@ -622,15 +619,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'when user clicks the new failure' do it 'shows the test report detail' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - within(".js-report-section-container") do - click_button 'addTest' + within('[data-testid="widget-extension-collapsed-section"]') do + click_link 'addTest' end end - within("#modal-mrwidget-reports") do + within('[data-testid="test-case-details-modal"]') do expect(page).to have_content('addTest') expect(page).to have_content('6.66') expect(page).to have_content(sample_java_failed_message.gsub(/\s+/, ' ').strip) @@ -655,13 +652,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows test reports summary which includes the existing failure' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - expect(page).to have_content('Test summary contained 1 failed out of 2 total tests') - within(".js-report-section-container") do - expect(page).to have_content('rspec found 1 failed out of 1 total test') - expect(page).to have_content('junit found no changed test results out of 1 total test') + expect(page).to have_content('Test summary: 1 failed, 2 total tests') + within('[data-testid="widget-extension-collapsed-section"]') do + expect(page).to have_content('rspec: 1 failed, 1 total test') + expect(page).to have_content('junit: no changed test results, 1 total test') expect(page).to have_content('Test#sum when a is 1 and b is 3 returns summary') end end @@ -669,15 +666,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'when user clicks the existing failure' do it 'shows test report detail of it' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - within(".js-report-section-container") do - click_button 'Test#sum when a is 1 and b is 3 returns summary' + within('[data-testid="widget-extension-collapsed-section"]') do + click_link 'Test#sum when a is 1 and b is 3 returns summary' end end - within("#modal-mrwidget-reports") do + within('[data-testid="test-case-details-modal"]') do expect(page).to have_content('Test#sum when a is 1 and b is 3 returns summary') expect(page).to have_content('2.22') expect(page).to have_content(sample_rspec_failed_message.gsub(/\s+/, ' ').strip) @@ -702,13 +699,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows test reports summary which includes the resolved failure' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - expect(page).to have_content('Test summary contained 1 fixed test result out of 2 total tests') - within(".js-report-section-container") do - expect(page).to have_content('rspec found no changed test results out of 1 total test') - expect(page).to have_content('junit found 1 fixed test result out of 1 total test') + expect(page).to have_content('Test summary: 1 fixed test result, 2 total tests') + within('[data-testid="widget-extension-collapsed-section"]') do + expect(page).to have_content('rspec: no changed test results, 1 total test') + expect(page).to have_content('junit: 1 fixed test result, 1 total test') + expect(page).to have_content('Fixed') expect(page).to have_content('addTest') end end @@ -716,15 +714,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'when user clicks the resolved failure' do it 'shows test report detail of it' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - within(".js-report-section-container") do - click_button 'addTest' + within('[data-testid="widget-extension-collapsed-section"]') do + click_link 'addTest' end end - within("#modal-mrwidget-reports") do + within('[data-testid="test-case-details-modal"]') do expect(page).to have_content('addTest') expect(page).to have_content('5.55') end @@ -748,13 +746,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows test reports summary which includes the new error' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - expect(page).to have_content('Test summary contained 1 error out of 2 total tests') - within(".js-report-section-container") do - expect(page).to have_content('rspec found no changed test results out of 1 total test') - expect(page).to have_content('junit found 1 error out of 1 total test') + expect(page).to have_content('Test summary: 1 error, 2 total tests') + within('[data-testid="widget-extension-collapsed-section"]') do + expect(page).to have_content('rspec: no changed test results, 1 total test') + expect(page).to have_content('junit: 1 error, 1 total test') expect(page).to have_content('New') expect(page).to have_content('addTest') end @@ -763,15 +761,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'when user clicks the new error' do it 'shows the test report detail' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - within(".js-report-section-container") do - click_button 'addTest' + within('[data-testid="widget-extension-collapsed-section"]') do + click_link 'addTest' end end - within("#modal-mrwidget-reports") do + within('[data-testid="test-case-details-modal"]') do expect(page).to have_content('addTest') expect(page).to have_content('8.88') end @@ -795,13 +793,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows test reports summary which includes the existing error' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - expect(page).to have_content('Test summary contained 1 error out of 2 total tests') - within(".js-report-section-container") do - expect(page).to have_content('rspec found 1 error out of 1 total test') - expect(page).to have_content('junit found no changed test results out of 1 total test') + expect(page).to have_content('Test summary: 1 error, 2 total tests') + within('[data-testid="widget-extension-collapsed-section"]') do + expect(page).to have_content('rspec: 1 error, 1 total test') + expect(page).to have_content('junit: no changed test results, 1 total test') expect(page).to have_content('Test#sum when a is 4 and b is 4 returns summary') end end @@ -809,15 +807,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'when user clicks the existing error' do it 'shows test report detail of it' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - within(".js-report-section-container") do - click_button 'Test#sum when a is 4 and b is 4 returns summary' + within('[data-testid="widget-extension-collapsed-section"]') do + click_link 'Test#sum when a is 4 and b is 4 returns summary' end end - within("#modal-mrwidget-reports") do + within('[data-testid="test-case-details-modal"]') do expect(page).to have_content('Test#sum when a is 4 and b is 4 returns summary') expect(page).to have_content('4.44') end @@ -841,13 +839,14 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows test reports summary which includes the resolved error' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - expect(page).to have_content('Test summary contained 1 fixed test result out of 2 total tests') - within(".js-report-section-container") do - expect(page).to have_content('rspec found no changed test results out of 1 total test') - expect(page).to have_content('junit found 1 fixed test result out of 1 total test') + expect(page).to have_content('Test summary: 1 fixed test result, 2 total tests') + within('[data-testid="widget-extension-collapsed-section"]') do + expect(page).to have_content('rspec: no changed test results, 1 total test') + expect(page).to have_content('junit: 1 fixed test result, 1 total test') + expect(page).to have_content('Fixed') expect(page).to have_content('addTest') end end @@ -855,15 +854,15 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'when user clicks the resolved error' do it 'shows test report detail of it' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - within(".js-report-section-container") do - click_button 'addTest' + within('[data-testid="widget-extension-collapsed-section"]') do + click_link 'addTest' end end - within("#modal-mrwidget-reports") do + within('[data-testid="test-case-details-modal"]') do expect(page).to have_content('addTest') expect(page).to have_content('5.55') end @@ -895,13 +894,13 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end it 'shows test reports summary which includes the resolved failure' do - within(".js-reports-container") do + within('[data-testid="widget-extension"]') do click_expand_button - expect(page).to have_content('Test summary contained 20 failed out of 20 total tests') - within(".js-report-section-container") do - expect(page).to have_content('rspec found 10 failed out of 10 total tests') - expect(page).to have_content('junit found 10 failed out of 10 total tests') + expect(page).to have_content('Test summary: 20 failed, 20 total tests') + within('[data-testid="widget-extension-collapsed-section"]') do + expect(page).to have_content('rspec: 10 failed, 10 total tests') + expect(page).to have_content('junit: 10 failed, 10 total tests') expect(page).to have_content('Test#sum when a is 1 and b is 3 returns summary', count: 2) end diff --git a/spec/features/merge_requests/user_mass_updates_spec.rb b/spec/features/merge_requests/user_mass_updates_spec.rb index cf9760bcd7f..5c3cb098e28 100644 --- a/spec/features/merge_requests/user_mass_updates_spec.rb +++ b/spec/features/merge_requests/user_mass_updates_spec.rb @@ -130,7 +130,7 @@ RSpec.describe 'Merge requests > User mass updates', :js do click_button 'Edit merge requests' check 'Select all' click_button 'Select milestone' - click_link text + click_button text click_update_merge_requests_button end diff --git a/spec/features/monitor_sidebar_link_spec.rb b/spec/features/monitor_sidebar_link_spec.rb index f612956600f..4f529179522 100644 --- a/spec/features/monitor_sidebar_link_spec.rb +++ b/spec/features/monitor_sidebar_link_spec.rb @@ -64,7 +64,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).not_to have_link('Metrics', href: project_metrics_dashboard_path(project)) expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project)) expect(page).not_to have_link('Error Tracking', href: project_error_tracking_index_path(project)) - expect(page).not_to have_link('Product Analytics', href: project_product_analytics_path(project)) expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project)) end @@ -119,7 +118,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).not_to have_link('Metrics', href: project_metrics_dashboard_path(project)) expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project)) expect(page).not_to have_link('Error Tracking', href: project_error_tracking_index_path(project)) - expect(page).not_to have_link('Product Analytics', href: project_product_analytics_path(project)) expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project)) end @@ -135,7 +133,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).to have_link('Incidents', href: project_incidents_path(project)) expect(page).to have_link('Environments', href: project_environments_path(project)) expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project)) - expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project)) expect(page).not_to have_link('Alerts', href: project_alert_management_index_path(project)) expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project)) @@ -154,7 +151,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).to have_link('Incidents', href: project_incidents_path(project)) expect(page).to have_link('Environments', href: project_environments_path(project)) expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project)) - expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project)) expect(page).to have_link('Kubernetes', href: project_clusters_path(project)) end @@ -171,7 +167,6 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).to have_link('Incidents', href: project_incidents_path(project)) expect(page).to have_link('Environments', href: project_environments_path(project)) expect(page).to have_link('Error Tracking', href: project_error_tracking_index_path(project)) - expect(page).to have_link('Product Analytics', href: project_product_analytics_path(project)) expect(page).to have_link('Kubernetes', href: project_clusters_path(project)) end diff --git a/spec/features/nav/top_nav_tooltip_spec.rb b/spec/features/nav/top_nav_tooltip_spec.rb index 73e4571e7a2..a110c6cfecf 100644 --- a/spec/features/nav/top_nav_tooltip_spec.rb +++ b/spec/features/nav/top_nav_tooltip_spec.rb @@ -10,7 +10,8 @@ RSpec.describe 'top nav tooltips', :js do visit explore_projects_path end - it 'clicking new dropdown hides tooltip', :aggregate_failures do + it 'clicking new dropdown hides tooltip', :aggregate_failures, + quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/382786' do btn = '#js-onboarding-new-project-link' page.find(btn).hover diff --git a/spec/features/one_trust_spec.rb b/spec/features/one_trust_spec.rb index 0ed08e8b99b..a7dfbfd6bdf 100644 --- a/spec/features/one_trust_spec.rb +++ b/spec/features/one_trust_spec.rb @@ -15,7 +15,7 @@ RSpec.describe 'OneTrust' do end it 'has the OneTrust CSP settings', :aggregate_failures do - expect(response_headers['Content-Security-Policy']).to include("#{onetrust_url}") + expect(response_headers['Content-Security-Policy']).to include(onetrust_url.to_s) expect(page.html).to include("https://cdn.cookielaw.org/consent/#{one_trust_id}/OtAutoBlock.js") end end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 913c375f909..ca156642bc8 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -27,41 +27,20 @@ RSpec.describe 'Profile account page', :js do expect(User.exists?(user.id)).to be_truthy end - context 'when user_destroy_with_limited_execution_time_worker is enabled' do - it 'deletes user', :js, :sidekiq_inline do - click_button 'Delete account' - - fill_in 'password', with: user.password + it 'deletes user', :js, :sidekiq_inline do + click_button 'Delete account' - page.within '.modal' do - click_button 'Delete account' - end + fill_in 'password', with: user.password - expect(page).to have_content('Account scheduled for removal') - expect( - Users::GhostUserMigration.where(user: user, - initiator_user: user) - ).to be_exists - end - end - - context 'when user_destroy_with_limited_execution_time_worker is disabled' do - before do - stub_feature_flags(user_destroy_with_limited_execution_time_worker: false) - end - - it 'deletes user', :js, :sidekiq_inline do + page.within '.modal' do click_button 'Delete account' - - fill_in 'password', with: user.password - - page.within '.modal' do - click_button 'Delete account' - end - - expect(page).to have_content('Account scheduled for removal') - expect(User.exists?(user.id)).to be_falsy end + + expect(page).to have_content('Account scheduled for removal') + expect( + Users::GhostUserMigration.where(user: user, + initiator_user: user) + ).to be_exists end it 'shows invalid password flash message', :js do diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb index 6c860740354..8887ff1746d 100644 --- a/spec/features/profiles/password_spec.rb +++ b/spec/features/profiles/password_spec.rb @@ -152,6 +152,33 @@ RSpec.describe 'Profile > Password' do it_behaves_like 'user enters an incorrect current password' end + context 'when the password is too weak' do + let(:new_password) { 'password' } + + subject do + page.within '.update-password' do + fill_in "user_password", with: user.password + fill_passwords(new_password, new_password) + end + end + + it 'tracks the error and does not change the password', :aggregate_failures do + expect { subject }.not_to change { user.reload.valid_password?(new_password) } + expect(user.failed_attempts).to eq(0) + + page.within '.gl-alert-danger' do + expect(page).to have_content('must not contain commonly used combinations of words and letters') + end + + expect_snowplow_event( + category: 'Gitlab::Tracking::Helpers::WeakPasswordErrorEvent', + action: 'track_weak_password_error', + controller: 'Profiles::PasswordsController', + method: 'update' + ) + end + end + context 'when the password reset is successful' do subject do page.within '.update-password' do @@ -195,6 +222,23 @@ RSpec.describe 'Profile > Password' do expect(page).to have_current_path new_user_session_path, ignore_query: true end + it 'tracks weak password error' do + visit edit_profile_password_path + + expect(page).to have_current_path new_profile_password_path, ignore_query: true + + fill_in :user_password, with: user.password + fill_in :user_new_password, with: "password" + fill_in :user_password_confirmation, with: "password" + click_button 'Set new password' + expect_snowplow_event( + category: 'Gitlab::Tracking::Helpers::WeakPasswordErrorEvent', + action: 'track_weak_password_error', + controller: 'Profiles::PasswordsController', + method: 'create' + ) + end + context 'when global require_two_factor_authentication is enabled' do it 'needs change user password' do stub_application_setting(require_two_factor_authentication: true) diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb index 088c8a7a15a..3ae88da06f6 100644 --- a/spec/features/profiles/personal_access_tokens_spec.rb +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -4,22 +4,11 @@ require 'spec_helper' RSpec.describe 'Profile > Personal Access Tokens', :js do include Spec::Support::Helpers::ModalHelpers + include Spec::Support::Helpers::AccessTokenHelpers let(:user) { create(:user) } let(:pat_create_service) { double('PersonalAccessTokens::CreateService', execute: ServiceResponse.error(message: 'error', payload: { personal_access_token: PersonalAccessToken.new })) } - def active_personal_access_tokens - find("[data-testid='active-tokens']") - end - - def created_personal_access_token - find_field('new-access-token').value - end - - def feed_token_description - "Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs." - end - before do sign_in(user) end @@ -43,11 +32,11 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do click_on "Create personal access token" wait_for_all_requests - expect(active_personal_access_tokens).to have_text(name) - expect(active_personal_access_tokens).to have_text('in') - expect(active_personal_access_tokens).to have_text('read_api') - expect(active_personal_access_tokens).to have_text('read_user') - expect(created_personal_access_token).not_to be_empty + expect(active_access_tokens).to have_text(name) + expect(active_access_tokens).to have_text('in') + expect(active_access_tokens).to have_text('read_api') + expect(active_access_tokens).to have_text('read_user') + expect(created_access_token).to match(/[\w-]{20}/) end context "when creation fails" do @@ -73,8 +62,8 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do it 'only shows personal access tokens' do visit profile_personal_access_tokens_path - expect(active_personal_access_tokens).to have_text(personal_access_token.name) - expect(active_personal_access_tokens).not_to have_text(impersonation_token.name) + expect(active_access_tokens).to have_text(personal_access_token.name) + expect(active_access_tokens).not_to have_text(impersonation_token.name) end context 'when User#time_display_relative is false' do @@ -85,7 +74,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do it 'shows absolute times for expires_at' do visit profile_personal_access_tokens_path - expect(active_personal_access_tokens).to have_text(PersonalAccessToken.last.expires_at.strftime('%b %-d')) + expect(active_access_tokens).to have_text(PersonalAccessToken.last.expires_at.strftime('%b %-d')) end end end @@ -97,14 +86,14 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do visit profile_personal_access_tokens_path accept_gl_confirm(button_text: 'Revoke') { click_on "Revoke" } - expect(active_personal_access_tokens).to have_text("This user has no active personal access tokens.") + expect(active_access_tokens).to have_text("This user has no active personal access tokens.") end it "removes expired tokens from 'active' section" do personal_access_token.update!(expires_at: 5.days.ago) visit profile_personal_access_tokens_path - expect(active_personal_access_tokens).to have_text("This user has no active personal access tokens.") + expect(active_access_tokens).to have_text("This user has no active personal access tokens.") end context "when revocation fails" do @@ -115,12 +104,16 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do visit profile_personal_access_tokens_path accept_gl_confirm(button_text: "Revoke") { click_on "Revoke" } - expect(active_personal_access_tokens).to have_text(personal_access_token.name) + expect(active_access_tokens).to have_text(personal_access_token.name) end end end describe "feed token" do + def feed_token_description + "Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs." + end + context "when enabled" do it "displays feed token" do allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(false) diff --git a/spec/features/profiles/two_factor_auths_spec.rb b/spec/features/profiles/two_factor_auths_spec.rb index b4355f2d669..decc2904b6e 100644 --- a/spec/features/profiles/two_factor_auths_spec.rb +++ b/spec/features/profiles/two_factor_auths_spec.rb @@ -13,7 +13,7 @@ RSpec.describe 'Two factor auths' do end context 'when user has two-factor authentication disabled' do - let_it_be(:user) { create(:user ) } + let_it_be(:user) { create(:user) } it 'requires the current password to set up two factor authentication', :js do visit profile_two_factor_auth_path diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb index d3bedbf3a75..33b4af3b5aa 100644 --- a/spec/features/project_variables_spec.rb +++ b/spec/features/project_variables_spec.rb @@ -12,62 +12,29 @@ RSpec.describe 'Project variables', :js do sign_in(user) project.add_maintainer(user) project.variables << variable + visit page_path + wait_for_requests end - context 'with disabled ff `ci_variable_settings_graphql' do - before do - stub_feature_flags(ci_variable_settings_graphql: false) - visit page_path - end - - it_behaves_like 'variable list' - - it 'adds a new variable with an environment scope' do - click_button('Add variable') - - page.within('#add-ci-variable') do - fill_in 'Key', with: 'akey' - find('#ci-variable-value').set('akey_value') - find('[data-testid="environment-scope"]').click - find('[data-testid="ci-environment-search"]').set('review/*') - find('[data-testid="create-wildcard-button"]').click - - click_button('Add variable') - end - - wait_for_requests + it_behaves_like 'variable list' - page.within('[data-testid="ci-variable-table"]') do - expect(find('.js-ci-variable-row:first-child [data-label="Environments"]').text).to eq('review/*') - end - end - end - - context 'with enabled ff `ci_variable_settings_graphql' do - before do - visit page_path - end + it 'adds a new variable with an environment scope' do + click_button('Add variable') - it_behaves_like 'variable list' + page.within('#add-ci-variable') do + fill_in 'Key', with: 'akey' + find('#ci-variable-value').set('akey_value') + find('[data-testid="environment-scope"]').click + find('[data-testid="ci-environment-search"]').set('review/*') + find('[data-testid="create-wildcard-button"]').click - it 'adds a new variable with an environment scope' do click_button('Add variable') + end - page.within('#add-ci-variable') do - fill_in 'Key', with: 'akey' - find('#ci-variable-value').set('akey_value') - find('[data-testid="environment-scope"]').click - find('[data-testid="ci-environment-search"]').set('review/*') - find('[data-testid="create-wildcard-button"]').click - - click_button('Add variable') - end - - wait_for_requests + wait_for_requests - page.within('[data-testid="ci-variable-table"]') do - expect(find('.js-ci-variable-row:first-child [data-label="Environments"]').text).to eq('review/*') - end + page.within('[data-testid="ci-variable-table"]') do + expect(find('.js-ci-variable-row:first-child [data-label="Environments"]').text).to eq('review/*') end end end diff --git a/spec/features/projects/branches/user_views_branches_spec.rb b/spec/features/projects/branches/user_views_branches_spec.rb index b6b6dcb5cf1..3f0614532f1 100644 --- a/spec/features/projects/branches/user_views_branches_spec.rb +++ b/spec/features/projects/branches/user_views_branches_spec.rb @@ -21,7 +21,7 @@ RSpec.describe "User views branches", :js do it "shows branches" do expect(page).to have_content("Branches").and have_content("master") - expect(page.all(".graph-side")).to all( have_content(/\d+/) ) + expect(page.all(".graph-side")).to all(have_content(/\d+/)) end it "displays a disabled button with a tooltip for the default branch that cannot be deleted", :js do diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb index 361a07ebd0b..ecf6349e431 100644 --- a/spec/features/projects/branches_spec.rb +++ b/spec/features/projects/branches_spec.rb @@ -7,7 +7,20 @@ RSpec.describe 'Branches' do let_it_be(:project) { create(:project, :public, :repository) } let(:repository) { project.repository } - context 'logged in as developer' do + context 'when logged in as reporter' do + before do + sign_in(user) + project.add_reporter(user) + end + + it 'does not show delete button' do + visit project_branches_path(project) + + expect(page).not_to have_css '.js-delete-branch-button' + end + end + + context 'when logged in as developer' do before do sign_in(user) project.add_developer(user) @@ -21,11 +34,15 @@ RSpec.describe 'Branches' do before do # Add 4 stale branches (1..4).reverse_each do |i| - travel_to((threshold + i.hours).ago) { create_file(message: "a commit in stale-#{i}", branch_name: "stale-#{i}") } + travel_to((threshold + i.hours).ago) do + create_file(message: "a commit in stale-#{i}", branch_name: "stale-#{i}") + end end # Add 6 active branches (1..6).each do |i| - travel_to((threshold - i.hours).ago) { create_file(message: "a commit in active-#{i}", branch_name: "active-#{i}") } + travel_to((threshold - i.hours).ago) do + create_file(message: "a commit in active-#{i}", branch_name: "active-#{i}") + end end end @@ -38,7 +55,10 @@ RSpec.describe 'Branches' do expect(page).to have_button('Copy branch name') - expect(page).to have_link('Show more active branches', href: project_branches_filtered_path(project, state: 'active')) + expect(page).to have_link( + 'Show more active branches', + href: project_branches_filtered_path(project, state: 'active') + ) expect(page).not_to have_content('Show more stale branches') end end @@ -75,13 +95,15 @@ RSpec.describe 'Branches' do it 'shows only default_per_page active branches sorted by last updated' do visit project_branches_filtered_path(project, state: 'active') - expect(page).to have_content(sorted_branches(repository, count: Kaminari.config.default_per_page, sort_by: :updated_desc, state: 'active')) + expect(page).to have_content(sorted_branches(repository, count: Kaminari.config.default_per_page, + sort_by: :updated_desc, state: 'active')) end it 'shows only default_per_page branches sorted by last updated on All branches' do visit project_branches_filtered_path(project, state: 'all') - expect(page).to have_content(sorted_branches(repository, count: Kaminari.config.default_per_page, sort_by: :updated_desc)) + expect(page).to have_content(sorted_branches(repository, count: Kaminari.config.default_per_page, + sort_by: :updated_desc)) end end end @@ -141,7 +163,7 @@ RSpec.describe 'Branches' do it 'avoids a N+1 query in branches index' do control_count = ActiveRecord::QueryRecorder.new { visit project_branches_path(project) }.count - %w(one two three four five).each { |ref| repository.add_branch(user, ref, 'master') } + %w[one two three four five].each { |ref| repository.add_branch(user, ref, 'master') } expect { visit project_branches_filtered_path(project, state: 'all') }.not_to exceed_query_limit(control_count) end @@ -193,7 +215,7 @@ RSpec.describe 'Branches' do end end - context 'logged in as maintainer' do + context 'when logged in as maintainer' do before do sign_in(user) project.add_maintainer(user) @@ -220,7 +242,7 @@ RSpec.describe 'Branches' do end end - context 'logged out' do + context 'when logged out' do before do visit project_branches_path(project) end @@ -314,7 +336,7 @@ RSpec.describe 'Branches' do Regexp.new(sorted_branches.join('.*')) end - def create_file(message: 'message', branch_name:) + def create_file(branch_name:, message: 'message') repository.create_file(user, generate(:branch), 'content', message: message, branch_name: branch_name) end diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb index 54685441300..e99af734c43 100644 --- a/spec/features/projects/container_registry_spec.rb +++ b/spec/features/projects/container_registry_spec.rb @@ -56,10 +56,11 @@ RSpec.describe 'Container Registry', :js do expect(page).to have_content 'my/image' end - it 'user removes entire container repository', :sidekiq_might_not_need_inline do + it 'user removes entire container repository' do visit_container_registry - expect_any_instance_of(ContainerRepository).to receive(:delete_tags!).and_return(true) + expect_any_instance_of(ContainerRepository).to receive(:delete_scheduled!).and_call_original + expect(DeleteContainerRepositoryWorker).not_to receive(:perform_async) find('[title="Remove repository"]').click expect(find('.modal .modal-title')).to have_content _('Remove repository') diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index dc6e496d081..706c880d097 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'Environment' do - let(:project) { create(:project, :repository) } + let_it_be(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:role) { :developer } @@ -17,7 +17,7 @@ RSpec.describe 'Environment' do end describe 'environment details page' do - let!(:environment) { create(:environment, project: project) } + let_it_be(:environment) { create(:environment, project: project) } let!(:permissions) {} let!(:deployment) {} let!(:action) {} @@ -160,10 +160,20 @@ RSpec.describe 'Environment' do end context 'with related deployable present' do - let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, pipeline: pipeline, environment: environment.name) } + let_it_be(:previous_pipeline) { create(:ci_pipeline, project: project) } - let(:deployment) do + let_it_be(:previous_build) do + create(:ci_build, :success, pipeline: previous_pipeline, environment: environment.name) + end + + let_it_be(:previous_deployment) do + create(:deployment, :success, environment: environment, deployable: previous_build) + end + + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:build) { create(:ci_build, pipeline: pipeline, environment: environment.name) } + + let_it_be(:deployment) do create(:deployment, :success, environment: environment, deployable: build) end @@ -171,12 +181,10 @@ RSpec.describe 'Environment' do visit_environment(environment) end - it 'does show build name' do - expect(page).to have_link("#{build.name} (##{build.id})") - end - - it 'shows the re-deploy button' do + it 'shows deployment information and buttons', :js do expect(page).to have_button('Re-deploy to environment') + expect(page).to have_button('Rollback environment') + expect(page).to have_link("#{build.name} (##{build.id})") end context 'with manual action' do diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index 9ec41cd8f8d..b445b0da901 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -336,6 +336,11 @@ RSpec.describe 'Environments page', :js do accept_gl_confirm do find(action_link_selector).click end + + # Wait for UI to transition to ensure we an GraphQL request has been made + within(actions_button_selector) { find('.gl-spinner') } + within(actions_button_selector) { find('[data-testid="play-icon"]') } + wait_for_requests end diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb index 24943e7dd0f..9ceadb63178 100644 --- a/spec/features/projects/fork_spec.rb +++ b/spec/features/projects/fork_spec.rb @@ -134,7 +134,7 @@ RSpec.describe 'Project fork' do context 'fork form', :js do let(:group) { create(:group) } let(:group2) { create(:group) } - let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user } + let(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user } def submit_form(group_obj = group) find('[data-testid="select_namespace_dropdown"]').click @@ -180,7 +180,7 @@ RSpec.describe 'Project fork' do context 'with cache_home_panel feature flag' do before do - create(:group_member, :maintainer, user: user, group: group2 ) + create(:group_member, :maintainer, user: user, group: group2) end context 'when caching is enabled' do diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index c7fbaa85483..6f015f9cd22 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -3,8 +3,6 @@ require 'spec_helper' RSpec.describe 'Import/Export - project import integration test', :js do - include GitHelpers - let(:user) { create(:user) } let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } let(:export_path) { "#{Dir.tmpdir}/import_file_spec" } diff --git a/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb b/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb index e7d4ed58549..d2c48cb2af0 100644 --- a/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb +++ b/spec/features/projects/integrations/user_activates_issue_tracker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User activates issue tracker', :js do +RSpec.describe 'User activates issue tracker', :js, feature_category: :integrations do include_context 'project integration activation' let(:url) { 'http://tracker.example.com' } diff --git a/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb b/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb index b423543dc33..3d40bae8544 100644 --- a/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb +++ b/spec/features/projects/issues/viewing_issues_with_external_authorization_enabled_spec.rb @@ -41,7 +41,7 @@ RSpec.describe 'viewing an issue with cross project references' do let(:issue) do create(:issue, project: project, - description: description_referencing_other_issue ) + description: description_referencing_other_issue) end let(:confidential_issue) do @@ -102,8 +102,8 @@ RSpec.describe 'viewing an issue with cross project references' do it 'shows only the link to the cross project references' do visit project_issue_path(project, issue) - expect(page).to have_link("#{other_issue.to_reference(project)}") - expect(page).to have_link("#{other_merge_request.to_reference(project)}") + expect(page).to have_link(other_issue.to_reference(project).to_s) + expect(page).to have_link(other_merge_request.to_reference(project).to_s) expect(page).not_to have_content("#{other_issue.to_reference(project)} (#{other_issue.state})") expect(page).not_to have_xpath("//a[@title='#{other_issue.title}']") expect(page).not_to have_content("#{other_merge_request.to_reference(project)} (#{other_merge_request.state})") @@ -113,7 +113,7 @@ RSpec.describe 'viewing an issue with cross project references' do it 'does not link a cross project confidential issue if the user does not have access' do visit project_issue_path(project, issue) - expect(page).not_to have_link("#{other_confidential_issue.to_reference(project)}") + expect(page).not_to have_link(other_confidential_issue.to_reference(project).to_s) expect(page).not_to have_xpath("//a[@title='#{other_confidential_issue.title}']") end @@ -122,7 +122,7 @@ RSpec.describe 'viewing an issue with cross project references' do visit project_issue_path(project, issue) - expect(page).to have_link("#{other_confidential_issue.to_reference(project)}") + expect(page).to have_link(other_confidential_issue.to_reference(project).to_s) expect(page).not_to have_xpath("//a[@title='#{other_confidential_issue.title}']") end diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb index b6019944071..740d009d6b8 100644 --- a/spec/features/projects/jobs/permissions_spec.rb +++ b/spec/features/projects/jobs/permissions_spec.rb @@ -211,4 +211,48 @@ RSpec.describe 'Project Jobs Permissions' do end end end + + context 'with CI_DEBUG_SERVICES' do + let_it_be(:ci_instance_variable) { create(:ci_instance_variable, key: 'CI_DEBUG_SERVICES') } + + describe 'trace endpoint and raw page' do + let_it_be(:job) { create(:ci_build, :running, :coverage, :trace_artifact, pipeline: pipeline) } + + where(:public_builds, :user_project_role, :ci_debug_services, :expected_status_code, :expected_msg) do + true | 'developer' | true | 200 | nil + true | 'guest' | true | 403 | 'You must have developer or higher permissions' + true | nil | true | 404 | 'Page Not Found Make sure the address is correct' + true | 'developer' | false | 200 | nil + true | 'guest' | false | 200 | nil + true | nil | false | 404 | 'Page Not Found Make sure the address is correct' + false | 'developer' | true | 200 | nil + false | 'guest' | true | 403 | 'You must have developer or higher permissions' + false | nil | true | 404 | 'Page Not Found Make sure the address is correct' + false | 'developer' | false | 200 | nil + false | 'guest' | false | 403 | 'The current user is not authorized to access the job log' + false | nil | false | 404 | 'Page Not Found Make sure the address is correct' + end + + with_them do + before do + ci_instance_variable.update!(value: ci_debug_services) + project.update!(public_builds: public_builds) + user_project_role && project.add_role(user, user_project_role) + end + + it 'renders trace to authorized users' do + visit trace_project_job_path(project, job) + + expect(status_code).to eq(expected_status_code) + end + + it 'renders raw trace to authorized users' do + visit raw_project_job_path(project, job) + + expect(status_code).to eq(expected_status_code) + expect(page).to have_content(expected_msg) + end + end + end + end end diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb index 995f4a1e3d2..cb3c1594868 100644 --- a/spec/features/projects/jobs/user_browses_jobs_spec.rb +++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb @@ -203,15 +203,15 @@ RSpec.describe 'User browses jobs' do end it 'contains a link to the job sha' do - expect(page.find('[data-testid="job-sha"]')).to have_content "#{job.sha[0..7]}" + expect(page.find('[data-testid="job-sha"]')).to have_content job.sha[0..7].to_s end it 'contains a link to the job id' do - expect(page.find('[data-testid="job-id-link"]')).to have_content "#{job.id}" + expect(page.find('[data-testid="job-id-link"]')).to have_content job.id.to_s end it 'contains a link to the job ref' do - expect(page.find('[data-testid="job-ref"]')).to have_content "#{job.ref}" + expect(page.find('[data-testid="job-ref"]')).to have_content job.ref.to_s end end end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 84c75752bc1..96a8168e708 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -463,7 +463,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do context 'when variables are stored in trigger_request' do before do - trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' } ) + trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' }) visit project_job_path(project, job) end @@ -508,7 +508,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do context 'when variables are stored in trigger_request' do before do - trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' } ) + trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' }) visit project_job_path(project, job) end diff --git a/spec/features/projects/members/manage_members_spec.rb b/spec/features/projects/members/manage_members_spec.rb index 56eb02607a5..1f317c55256 100644 --- a/spec/features/projects/members/manage_members_spec.rb +++ b/spec/features/projects/members/manage_members_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Projects > Members > Manage members', :js do +RSpec.describe 'Projects > Members > Manage members', :js, product_group: :onboarding do include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::Features::InviteMembersModalHelper include Spec::Support::Helpers::ModalHelpers diff --git a/spec/features/projects/network_graph_spec.rb b/spec/features/projects/network_graph_spec.rb index 1ee0ea51e53..97b743b4d73 100644 --- a/spec/features/projects/network_graph_spec.rb +++ b/spec/features/projects/network_graph_spec.rb @@ -13,98 +13,110 @@ RSpec.describe 'Project Network Graph', :js do allow(Network::Graph).to receive(:max_count).and_return(10) end - context 'when branch is master' do - def switch_ref_to(ref_name) - first('.js-project-refs-dropdown').click - - page.within '.project-refs-form' do - click_link ref_name + shared_examples 'network graph' do + context 'when branch is master' do + def switch_ref_to(ref_name) + first('.js-project-refs-dropdown').click + + page.within '.project-refs-form' do + click_link ref_name + end end - end - def click_show_only_selected_branch_checkbox - find('#filter_ref').click - end + def click_show_only_selected_branch_checkbox + find('#filter_ref').click + end - before do - visit project_network_path(project, 'master') - end + before do + visit project_network_path(project, 'master') + end - it 'renders project network' do - expect(page).to have_selector ".network-graph" - expect(page).to have_selector '.dropdown-menu-toggle', text: "master" - page.within '.network-graph' do - expect(page).to have_content 'master' + it 'renders project network' do + expect(page).to have_selector ".network-graph" + expect(page).to have_selector '.dropdown-menu-toggle', text: "master" + page.within '.network-graph' do + expect(page).to have_content 'master' + end end - end - it 'switches ref to branch' do - switch_ref_to('feature') + it 'switches ref to branch' do + switch_ref_to('feature') - expect(page).to have_selector '.dropdown-menu-toggle', text: 'feature' - page.within '.network-graph' do - expect(page).to have_content 'feature' + expect(page).to have_selector '.dropdown-menu-toggle', text: 'feature' + page.within '.network-graph' do + expect(page).to have_content 'feature' + end end - end - it 'switches ref to tag' do - switch_ref_to('v1.0.0') + it 'switches ref to tag' do + switch_ref_to('v1.0.0') - expect(page).to have_selector '.dropdown-menu-toggle', text: 'v1.0.0' - page.within '.network-graph' do - expect(page).to have_content 'v1.0.0' + expect(page).to have_selector '.dropdown-menu-toggle', text: 'v1.0.0' + page.within '.network-graph' do + expect(page).to have_content 'v1.0.0' + end end - end - it 'renders by commit sha of "v1.0.0"' do - page.within ".network-form" do - fill_in 'extended_sha1', with: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' - find('button').click + it 'renders by commit sha of "v1.0.0"' do + page.within ".network-form" do + fill_in 'extended_sha1', with: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' + find('button').click + end + + expect(page).to have_selector ".network-graph" + expect(page).to have_selector '.dropdown-menu-toggle', text: "master" + page.within '.network-graph' do + expect(page).to have_content 'v1.0.0' + end end - expect(page).to have_selector ".network-graph" - expect(page).to have_selector '.dropdown-menu-toggle', text: "master" - page.within '.network-graph' do - expect(page).to have_content 'v1.0.0' - end - end + it 'filters select tag' do + switch_ref_to('v1.0.0') - it 'filters select tag' do - switch_ref_to('v1.0.0') + expect(page).to have_css 'title', text: 'Graph · v1.0.0', visible: false + page.within '.network-graph' do + expect(page).to have_content 'Change some files' + end - expect(page).to have_css 'title', text: 'Graph · v1.0.0', visible: false - page.within '.network-graph' do - expect(page).to have_content 'Change some files' - end + click_show_only_selected_branch_checkbox - click_show_only_selected_branch_checkbox + page.within '.network-graph' do + expect(page).not_to have_content 'Change some files' + end - page.within '.network-graph' do - expect(page).not_to have_content 'Change some files' + click_show_only_selected_branch_checkbox + + page.within '.network-graph' do + expect(page).to have_content 'Change some files' + end end - click_show_only_selected_branch_checkbox + it 'renders error message when sha commit not exists' do + page.within ".network-form" do + fill_in 'extended_sha1', with: ';' + find('button').click + end - page.within '.network-graph' do - expect(page).to have_content 'Change some files' + expect(page).to have_selector '[data-testid="alert-danger"]', text: "Git revision ';' does not exist." end end - it 'renders error message when sha commit not exists' do - page.within ".network-form" do - fill_in 'extended_sha1', with: ';' - find('button').click - end + it 'renders project network with test branch' do + visit project_network_path(project, "'test'") - expect(page).to have_selector '[data-testid="alert-danger"]', text: "Git revision ';' does not exist." + page.within '.network-graph' do + expect(page).to have_content "'test'" + end end end - it 'renders project network with test branch' do - visit project_network_path(project, "'test'") + it_behaves_like 'network graph' - page.within '.network-graph' do - expect(page).to have_content "'test'" + context 'when disable_network_graph_notes_count is disabled' do + before do + stub_feature_flags(disable_network_graph_notes_count: false) end + + it_behaves_like 'network graph' end end diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb index 4ed0a11da38..e569fef76f8 100644 --- a/spec/features/projects/pipeline_schedules_spec.rb +++ b/spec/features/projects/pipeline_schedules_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Pipeline Schedules', :js do include Spec::Support::Helpers::ModalHelpers let!(:project) { create(:project, :repository) } - let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) } + let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project) } let!(:pipeline) { create(:ci_pipeline, pipeline_schedule: pipeline_schedule) } let(:scope) { nil } let!(:user) { create(:user) } @@ -45,7 +45,7 @@ RSpec.describe 'Pipeline Schedules', :js do description = find_field('schedule_description').value expect(description).to eq('pipeline schedule') expect(page).to have_button('master') - expect(page).to have_button('UTC') + expect(page).to have_button('Select timezone') end it 'edits the scheduled pipeline' do @@ -164,7 +164,7 @@ RSpec.describe 'Pipeline Schedules', :js do it 'sets defaults for timezone and target branch' do expect(page).to have_button('master') - expect(page).to have_button('UTC') + expect(page).to have_button('Select timezone') end it 'creates a new scheduled pipeline' do @@ -314,8 +314,8 @@ RSpec.describe 'Pipeline Schedules', :js do end def select_timezone - find('.js-timezone-dropdown').click - click_link 'American Samoa' + find('[data-testid="schedule-timezone"] .dropdown-toggle').click + find("button", text: "Arizona").click end def select_target_branch diff --git a/spec/features/projects/pipelines/legacy_pipeline_spec.rb b/spec/features/projects/pipelines/legacy_pipeline_spec.rb index d93c951791d..c4fc194f0cd 100644 --- a/spec/features/projects/pipelines/legacy_pipeline_spec.rb +++ b/spec/features/projects/pipelines/legacy_pipeline_spec.rb @@ -726,12 +726,7 @@ RSpec.describe 'Pipeline', :js do before do schedule.owner.block! - - begin - PipelineScheduleWorker.new.perform - rescue Ci::CreatePipelineService::CreateError - # Do nothing, assert view code after the Pipeline failed to create. - end + PipelineScheduleWorker.new.perform end it 'displays the PipelineSchedule in an inactive state' do diff --git a/spec/features/projects/pipelines/legacy_pipelines_spec.rb b/spec/features/projects/pipelines/legacy_pipelines_spec.rb index 2e0ea695ab3..9d3ac71a875 100644 --- a/spec/features/projects/pipelines/legacy_pipelines_spec.rb +++ b/spec/features/projects/pipelines/legacy_pipelines_spec.rb @@ -316,7 +316,6 @@ RSpec.describe 'Pipelines', :js do end before do - stub_feature_flags(bootstrap_confirmation_modals: false) visit_project_pipelines end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 0b43e13996f..2d729af513a 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -64,7 +64,9 @@ RSpec.describe 'Pipeline', :js do let_it_be(:group) { create(:group) } let_it_be(:project, reload: true) { create(:project, :repository, group: group) } - let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id, user: user) } + let(:pipeline) do + create(:ci_pipeline, name: 'Build pipeline', project: project, ref: 'master', sha: project.commit.id, user: user) + end subject(:visit_pipeline) { visit project_pipeline_path(project, pipeline) } @@ -96,6 +98,45 @@ RSpec.describe 'Pipeline', :js do end end + context 'with pipeline_name feature flag enabled' do + before do + stub_feature_flags(pipeline_name: true) + end + + it 'displays pipeline name instead of commit title' do + visit_pipeline + + within 'h3' do + expect(page).to have_content(pipeline.name) + end + + within '.well-segment[data-testid="commit-row"]' do + expect(page).to have_content(project.commit.title) + expect(page).to have_content(project.commit.short_id) + end + end + end + + context 'with pipeline_name feature flag disabled' do + before do + stub_feature_flags(pipeline_name: false) + end + + it 'displays commit title' do + visit_pipeline + + within 'h3' do + expect(page).not_to have_content(pipeline.name) + expect(page).to have_content(project.commit.title) + end + + within '.well-segment[data-testid="commit-row"]' do + expect(page).not_to have_content(project.commit.title) + expect(page).to have_content(project.commit.short_id) + end + end + end + describe 'related merge requests' do context 'when there are no related merge requests' do it 'shows a "no related merge requests" message' do @@ -363,7 +404,7 @@ RSpec.describe 'Pipeline', :js do project: downstream_project, ref: 'master', sha: downstream_project.commit.id, - child_of: pipeline ) + child_of: pipeline) end let!(:build) { create(:ci_build, status, pipeline: downstream_pipeline, user: user) } @@ -851,12 +892,7 @@ RSpec.describe 'Pipeline', :js do before do schedule.owner.block! - - begin - PipelineScheduleWorker.new.perform - rescue Ci::CreatePipelineService::CreateError - # Do nothing, assert view code after the Pipeline failed to create. - end + PipelineScheduleWorker.new.perform end it 'displays the PipelineSchedule in an inactive state' do diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index eabbcd5e38e..b7b715cb6db 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -680,7 +680,7 @@ RSpec.describe 'Pipelines', :js do end context 'when variables are specified' do - it 'creates a new pipeline with variables', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375552' do + it 'creates a new pipeline with variables' do page.within(find("[data-testid='ci-variable-row']")) do find("[data-testid='pipeline-form-ci-variable-key']").set('key_name') find("[data-testid='pipeline-form-ci-variable-value']").set('value') @@ -708,7 +708,7 @@ RSpec.describe 'Pipelines', :js do it { expect(page).to have_content('Missing CI config file') } - it 'creates a pipeline after first request failed and a valid gitlab-ci.yml file is available when trying again', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/375552' do + it 'creates a pipeline after first request failed and a valid gitlab-ci.yml file is available when trying again' do stub_ci_pipeline_to_return_yaml_file expect do @@ -722,6 +722,7 @@ RSpec.describe 'Pipelines', :js do # Run Pipeline form with REST endpoints # TODO: Clean up tests when run_pipeline_graphql is enabled + # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/372310 context 'with feature flag disabled' do before do stub_feature_flags(run_pipeline_graphql: false) diff --git a/spec/features/projects/product_analytics/events_spec.rb b/spec/features/projects/product_analytics/events_spec.rb deleted file mode 100644 index 05d12e12acb..00000000000 --- a/spec/features/projects/product_analytics/events_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Product Analytics > Events' do - let_it_be(:project) { create(:project_empty_repo) } - let_it_be(:user) { create(:user) } - - let(:event) { create(:product_analytics_event, project: project) } - - before do - project.add_maintainer(user) - sign_in(user) - end - - it 'shows no events message' do - visit(project_product_analytics_path(project)) - - expect(page).to have_content('There are currently no events') - end - - it 'shows events' do - event - - visit(project_product_analytics_path(project)) - - expect(page).to have_content('dvce_created_tstamp') - expect(page).to have_content(event.event_id) - end -end diff --git a/spec/features/projects/product_analytics/graphs_spec.rb b/spec/features/projects/product_analytics/graphs_spec.rb deleted file mode 100644 index e2293893589..00000000000 --- a/spec/features/projects/product_analytics/graphs_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Product Analytics > Graphs' do - let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } - - before do - project.add_maintainer(user) - sign_in(user) - end - - it 'shows graphs', :js do - create(:product_analytics_event, project: project) - - visit(graphs_project_product_analytics_path(project)) - - expect(page).to have_content('Showing graphs based on events') - expect(page).to have_content('platform') - expect(page).to have_content('os_timezone') - expect(page).to have_content('br_lang') - expect(page).to have_content('doc_charset') - end -end diff --git a/spec/features/projects/product_analytics/setup_spec.rb b/spec/features/projects/product_analytics/setup_spec.rb deleted file mode 100644 index 45c2b67502c..00000000000 --- a/spec/features/projects/product_analytics/setup_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Product Analytics > Setup' do - let_it_be(:project) { create(:project_empty_repo) } - let_it_be(:user) { create(:user) } - - before do - project.add_maintainer(user) - sign_in(user) - end - - it 'shows the setup instructions' do - visit(setup_project_product_analytics_path(project)) - - expect(page).to have_content('Copy the code below to implement tracking in your application') - end -end diff --git a/spec/features/projects/product_analytics/test_spec.rb b/spec/features/projects/product_analytics/test_spec.rb deleted file mode 100644 index 8984fb409d1..00000000000 --- a/spec/features/projects/product_analytics/test_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Product Analytics > Test' do - let_it_be(:project) { create(:project_empty_repo) } - let_it_be(:user) { create(:user) } - - before do - project.add_maintainer(user) - sign_in(user) - end - - it 'says it sends a payload' do - visit(test_project_product_analytics_path(project)) - - expect(page).to have_content('This page sends a payload.') - end - - it 'shows the last event if there is one' do - event = create(:product_analytics_event, project: project) - - visit(test_project_product_analytics_path(project)) - - expect(page).to have_content(event.event_id) - end -end 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 6551b254643..78b9798941a 100644 --- a/spec/features/projects/releases/user_views_edit_release_spec.rb +++ b/spec/features/projects/releases/user_views_edit_release_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'User edits Release', :js do let_it_be(:project) { create(:project, :repository) } let_it_be(:user) { create(:user) } - let(:release) { create(:release, :with_milestones, milestones_count: 1, project: project, name: 'The first release', tag: "v1.1.0" ) } + let(:release) { create(:release, :with_milestones, milestones_count: 1, project: project, name: 'The first release', tag: "v1.1.0") } let(:release_link) { create(:release_link, release: release) } before do diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb index a7348b62fc0..10418e8072d 100644 --- a/spec/features/projects/releases/user_views_releases_spec.rb +++ b/spec/features/projects/releases/user_views_releases_spec.rb @@ -15,7 +15,7 @@ RSpec.describe 'User views releases', :js do let_it_be(:guest) { create(:user) } let_it_be(:internal_link) { create(:release_link, release: release_v1, name: 'An internal link', url: "#{project.web_url}/-/jobs/1/artifacts/download", filepath: nil) } - let_it_be(:internal_link_with_redirect) { create(:release_link, release: release_v1, name: 'An internal link with a redirect', url: "#{project.web_url}/-/jobs/2/artifacts/download", filepath: '/binaries/linux-amd64' ) } + let_it_be(:internal_link_with_redirect) { create(:release_link, release: release_v1, name: 'An internal link with a redirect', url: "#{project.web_url}/-/jobs/2/artifacts/download", filepath: '/binaries/linux-amd64') } let_it_be(:external_link) { create(:release_link, release: release_v1, name: 'An external link', url: "https://example.com/an/external/link", filepath: nil) } before do diff --git a/spec/features/projects/settings/branch_names_settings_spec.rb b/spec/features/projects/settings/branch_names_settings_spec.rb new file mode 100644 index 00000000000..fdd883bc2b6 --- /dev/null +++ b/spec/features/projects/settings/branch_names_settings_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Project settings > repositories > Branch names', :js do + let_it_be(:project) { create(:project, :public) } + let(:user) { create(:user) } + + before do + project.add_maintainer(user) + + sign_in(user) + end + + context 'when Issues are initially disabled' do + let(:project_feature) { project.project_feature } + + before do + project_feature.update!(issues_access_level: ProjectFeature::DISABLED) + visit project_settings_repository_path(project) + end + + it 'do not render the Branch names settings' do + expect(page).not_to have_content('Branch name template') + end + end + + context 'when Issues are initially enabled' do + before do + visit project_settings_repository_path(project) + end + + it 'shows the Branch names settings' do + expect(page).to have_content('Branch name template') + + value = "feature-%{id}" + + within('section#branch-defaults-settings') do + fill_in 'project[issue_branch_template]', with: value + + click_on('Save changes') + end + + expect(project.reload.issue_branch_template).to eq(value) + expect(page).to have_content('Branch name template') + end + end +end diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb index d9bdbf7aa1a..b25ae80b3c3 100644 --- a/spec/features/projects/settings/repository_settings_spec.rb +++ b/spec/features/projects/settings/repository_settings_spec.rb @@ -30,7 +30,6 @@ RSpec.describe 'Projects > Settings > Repository settings' do before do stub_container_registry_config(enabled: true) - stub_feature_flags(ajax_new_deploy_token: project) end it_behaves_like 'a deploy token in settings' do diff --git a/spec/features/projects/settings/user_changes_default_branch_spec.rb b/spec/features/projects/settings/user_changes_default_branch_spec.rb index 508bbcc5327..bf064839bd7 100644 --- a/spec/features/projects/settings/user_changes_default_branch_spec.rb +++ b/spec/features/projects/settings/user_changes_default_branch_spec.rb @@ -25,11 +25,11 @@ RSpec.describe 'Projects > Settings > User changes default branch' do fill_in 'Search branch', with: 'fix' click_button 'fix' - page.within '#default-branch-settings' do + page.within '#branch-defaults-settings' do click_button 'Save changes' end - expect(find("#{dropdown_selector} input", visible: false).value).to eq 'fix' + expect(find(dropdown_selector)).to have_text 'fix' end end diff --git a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb index eed3494ef5b..47383be1ba1 100644 --- a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb +++ b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb @@ -11,7 +11,6 @@ RSpec.describe 'Repository Settings > User sees revoke deploy token modal', :js before do project.add_role(user, role) sign_in(user) - stub_feature_flags(ajax_new_deploy_token: project) visit(project_settings_repository_path(project)) click_button('Revoke') end diff --git a/spec/features/projects/settings/webhooks_settings_spec.rb b/spec/features/projects/settings/webhooks_settings_spec.rb index 25752bcaf45..adbf2f6ee5c 100644 --- a/spec/features/projects/settings/webhooks_settings_spec.rb +++ b/spec/features/projects/settings/webhooks_settings_spec.rb @@ -48,22 +48,47 @@ RSpec.describe 'Projects > Settings > Webhook Settings' do expect(page).to have_content('Releases events') end - it 'create webhook', :js do - visit webhooks_path + context 'when feature flag "enhanced_webhook_support_regex" is disabled' do + before do + stub_feature_flags(enhanced_webhook_support_regex: false) + end - fill_in 'URL', with: url - check 'Tag push events' - fill_in 'hook_push_events_branch_filter', with: 'master' - check 'Enable SSL verification' - check 'Job events' + it 'create webhook', :js do + visit webhooks_path - click_button 'Add webhook' + fill_in 'URL', with: url + check 'Tag push events' + fill_in 'hook_push_events_branch_filter', with: 'master' + check 'Enable SSL verification' + check 'Job events' - expect(page).to have_content(url) - expect(page).to have_content('SSL Verification: enabled') - expect(page).to have_content('Push events') - expect(page).to have_content('Tag push events') - expect(page).to have_content('Job events') + click_button 'Add webhook' + + expect(page).to have_content(url) + expect(page).to have_content('SSL Verification: enabled') + expect(page).to have_content('Tag push events') + expect(page).to have_content('Job events') + expect(page).to have_content('Push events') + end + end + + context 'when feature flag "enhanced_webhook_support_regex" is enabled' do + it 'create webhook', :js do + visit webhooks_path + + fill_in 'URL', with: url + check 'Tag push events' + check 'Enable SSL verification' + check 'Job events' + + click_button 'Add webhook' + + expect(page).to have_content(url) + expect(page).to have_content('SSL Verification: enabled') + expect(page).to have_content('Tag push events') + expect(page).to have_content('Job events') + expect(page).to have_content('Push events') + end end it 'edit existing webhook', :js do diff --git a/spec/features/projects/user_changes_project_visibility_spec.rb b/spec/features/projects/user_changes_project_visibility_spec.rb index d2a7596aec0..df13bb55c6d 100644 --- a/spec/features/projects/user_changes_project_visibility_spec.rb +++ b/spec/features/projects/user_changes_project_visibility_spec.rb @@ -103,6 +103,9 @@ RSpec.describe 'User changes public project visibility', :js do sign_in(project.first_owner) visit edit_project_path(project) + + # https://gitlab.com/gitlab-org/gitlab/-/issues/381259 + allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(110) end it_behaves_like 'does not require confirmation' diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb index 50e6eb66466..ee74ac84a73 100644 --- a/spec/features/search/user_searches_for_code_spec.rb +++ b/spec/features/search/user_searches_for_code_spec.rb @@ -2,228 +2,237 @@ require 'spec_helper' -RSpec.describe 'User searches for code' do - let(:user) { create(:user) } - let(:project) { create(:project, :repository, namespace: user.namespace) } - - context 'when signed in' do - before do - stub_feature_flags(search_page_vertical_nav: false) - project.add_maintainer(user) - sign_in(user) - end - - it 'finds a file' do - visit(project_path(project)) +RSpec.describe 'User searches for code', :js, :disable_rate_limiter do + using RSpec::Parameterized::TableSyntax - submit_search('application.js') - select_search_scope('Code') + let_it_be(:user) { create(:user) } + let_it_be_with_reload(:project) { create(:project, :repository, namespace: user.namespace) } - 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: %r{master/files/js/application.js}) - expect(page).to have_button('Copy file path') - end - - context 'when on a project page', :js do + where(search_page_vertical_nav_enabled: [true, false]) + with_them do + context 'when signed in' do before do - visit(search_path) - find('[data-testid="project-filter"]').click - - wait_for_requests - - page.within('[data-testid="project-filter"]') do - click_on(project.name) - end + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) + project.add_maintainer(user) + sign_in(user) end - include_examples 'top right search form' - include_examples 'search timeouts', 'blobs' + it 'finds a file' do + visit(project_path(project)) - it 'finds code and links to blob' do - fill_in('dashboard_search', with: 'rspec') - find('.gl-search-box-by-click-search-button').click + submit_search('application.js') + select_search_scope('Code') - expect(page).to have_selector('.results', text: 'Update capybara, rspec-rails, poltergeist to recent versions') - - find("#blob-L3").click - expect(current_url).to match(%r{blob/master/.gitignore#L3}) + 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: %r{master/files/js/application.js}) + expect(page).to have_button('Copy file path') end - it 'finds code and links to blame' do - fill_in('dashboard_search', with: 'rspec') - find('.gl-search-box-by-click-search-button').click + context 'when on a project page' do + before do + visit(search_path) + find('[data-testid="project-filter"]').click - expect(page).to have_selector('.results', text: 'Update capybara, rspec-rails, poltergeist to recent versions') + wait_for_requests - find("#blame-L3").click - expect(current_url).to match(%r{blame/master/.gitignore#L3}) - end + page.within('[data-testid="project-filter"]') do + click_on(project.name) + end + end - it 'search mutiple words with refs switching' do - expected_result = 'Use `snake_case` for naming files' - search = 'for naming files' + include_examples 'top right search form' + include_examples 'search timeouts', 'blobs' do + let(:additional_params) { { project_id: project.id } } + end - fill_in('dashboard_search', with: search) - find('.gl-search-box-by-click-search-button').click + it 'finds code and links to blob' do + expected_result = 'Update capybara, rspec-rails, poltergeist to recent versions' - expect(page).to have_selector('.results', text: expected_result) + fill_in('dashboard_search', with: 'rspec') + find('.gl-search-box-by-click-search-button').click - find('.ref-selector').click - wait_for_requests + expect(page).to have_selector('.results', text: expected_result) - page.within('.ref-selector') do - find('li', text: 'v1.0.0').click + find("#blob-L3").click + expect(current_url).to match(%r{blob/master/.gitignore#L3}) end - expect(page).to have_selector('.results', text: expected_result) + it 'finds code and links to blame' do + expected_result = 'Update capybara, rspec-rails, poltergeist to recent versions' - expect(find_field('dashboard_search').value).to eq(search) - expect(find("#blob-L1502")[:href]).to match(%r{blob/v1.0.0/files/markdown/ruby-style-guide.md#L1502}) - expect(find("#blame-L1502")[:href]).to match(%r{blame/v1.0.0/files/markdown/ruby-style-guide.md#L1502}) - end - end + fill_in('dashboard_search', with: 'rspec') + find('.gl-search-box-by-click-search-button').click - context 'when :new_header_search is true' do - context 'search code within refs', :js do - let(:ref_name) { 'v1.0.0' } + expect(page).to have_selector('.results', text: expected_result) - before do - # This feature is diabled by default in spec_helper.rb. - # We missed a feature breaking bug, so to prevent this regression, testing both scenarios for this spec. - # This can be removed as part of closing https://gitlab.com/gitlab-org/gitlab/-/issues/339348. - stub_feature_flags(new_header_search: true) - visit(project_tree_path(project, ref_name)) - - submit_search('gitlab-grack') - select_search_scope('Code') + find("#blame-L3").click + expect(current_url).to match(%r{blame/master/.gitignore#L3}) end - it 'shows ref switcher in code result summary' do - expect(find('.ref-selector')).to have_text(ref_name) - end + it 'search multiple words with refs switching' do + expected_result = 'Use `snake_case` for naming files' + search = 'for naming files' - it 'persists branch name across search' do + fill_in('dashboard_search', with: search) find('.gl-search-box-by-click-search-button').click - expect(find('.ref-selector')).to have_text(ref_name) - end - # this example is use to test the desgine that the refs is not - # only repersent the branch as well as the tags. - it 'ref swither list all the branchs and tags' do + expect(page).to have_selector('.results', text: expected_result) + find('.ref-selector').click wait_for_requests page.within('.ref-selector') do - expect(page).to have_selector('li', text: 'add-ipython-files') - expect(page).to have_selector('li', text: 'v1.0.0') + find('li', text: 'v1.0.0').click end + + expect(page).to have_selector('.results', text: expected_result) + + expect(find_field('dashboard_search').value).to eq(search) + expect(find("#blob-L1502")[:href]).to match(%r{blob/v1.0.0/files/markdown/ruby-style-guide.md#L1502}) + expect(find("#blame-L1502")[:href]).to match(%r{blame/v1.0.0/files/markdown/ruby-style-guide.md#L1502}) end + end - it 'search result changes when refs switched' do - ref = 'master' - expect(find('.results')).not_to have_content('path = gitlab-grack') + context 'when :new_header_search is true' do + context 'search code within refs' do + let(:ref_name) { 'v1.0.0' } - find('.ref-selector').click - wait_for_requests + before do + # This feature is disabled by default in spec_helper.rb. + # We missed a feature breaking bug, so to prevent this regression, testing both scenarios for this spec. + # This can be removed as part of closing https://gitlab.com/gitlab-org/gitlab/-/issues/339348. + stub_feature_flags(new_header_search: true) + visit(project_tree_path(project, ref_name)) - page.within('.ref-selector') do - fill_in _('Search by Git revision'), with: ref + submit_search('gitlab-grack') + select_search_scope('Code') + end + + it 'shows ref switcher in code result summary' do + expect(find('.ref-selector')).to have_text(ref_name) + end + + it 'persists branch name across search' do + find('.gl-search-box-by-click-search-button').click + expect(find('.ref-selector')).to have_text(ref_name) + end + + # this example is use to test the design that the refs is not + # only represent the branch as well as the tags. + it 'ref switcher list all the branches and tags' do + find('.ref-selector').click wait_for_requests - find('li', text: ref).click + page.within('.ref-selector') do + expect(page).to have_selector('li', text: 'add-ipython-files') + expect(page).to have_selector('li', text: 'v1.0.0') + end end - expect(page).to have_selector('.results', text: 'path = gitlab-grack') - end - end - end + it 'search result changes when refs switched' do + ref = 'master' + expect(find('.results')).not_to have_content('path = gitlab-grack') - context 'when :new_header_search is false' do - context 'search code within refs', :js do - let(:ref_name) { 'v1.0.0' } + find('.ref-selector').click + wait_for_requests - before do - # This feature is diabled by default in spec_helper.rb. - # We missed a feature breaking bug, so to prevent this regression, testing both scenarios for this spec. - # This can be removed as part of closing https://gitlab.com/gitlab-org/gitlab/-/issues/339348. - stub_feature_flags(new_header_search: false) - visit(project_tree_path(project, ref_name)) - - submit_search('gitlab-grack') - select_search_scope('Code') - end + page.within('.ref-selector') do + fill_in _('Search by Git revision'), with: ref + wait_for_requests - it 'shows ref switcher in code result summary' do - expect(find('.ref-selector')).to have_text(ref_name) - end + find('li', text: ref).click + end - it 'persists branch name across search' do - find('.gl-search-box-by-click-search-button').click - expect(find('.ref-selector')).to have_text(ref_name) + expect(page).to have_selector('.results', text: 'path = gitlab-grack') + end end + end - # this example is use to test the desgine that the refs is not - # only repersent the branch as well as the tags. - it 'ref swither list all the branchs and tags' do - find('.ref-selector').click - wait_for_requests + context 'when :new_header_search is false' do + context 'search code within refs' do + let(:ref_name) { 'v1.0.0' } - page.within('.ref-selector') do - expect(page).to have_selector('li', text: 'add-ipython-files') - expect(page).to have_selector('li', text: 'v1.0.0') + before do + # This feature is disabled by default in spec_helper.rb. + # We missed a feature breaking bug, so to prevent this regression, testing both scenarios for this spec. + # This can be removed as part of closing https://gitlab.com/gitlab-org/gitlab/-/issues/339348. + stub_feature_flags(new_header_search: false) + visit(project_tree_path(project, ref_name)) + + submit_search('gitlab-grack') + select_search_scope('Code') end - end - it 'search result changes when refs switched' do - ref = 'master' - expect(find('.results')).not_to have_content('path = gitlab-grack') + it 'shows ref switcher in code result summary' do + expect(find('.ref-selector')).to have_text(ref_name) + end - find('.ref-selector').click - wait_for_requests + it 'persists branch name across search' do + find('.gl-search-box-by-click-search-button').click + expect(find('.ref-selector')).to have_text(ref_name) + end - page.within('.ref-selector') do - fill_in _('Search by Git revision'), with: ref + # this example is use to test the design that the refs is not + # only represent the branch as well as the tags. + it 'ref switcher list all the branches and tags' do + find('.ref-selector').click wait_for_requests - find('li', text: ref).click + page.within('.ref-selector') do + expect(page).to have_selector('li', text: 'add-ipython-files') + expect(page).to have_selector('li', text: 'v1.0.0') + end end - expect(page).to have_selector('.results', text: 'path = gitlab-grack') + it 'search result changes when refs switched' do + ref = 'master' + expect(find('.results')).not_to have_content('path = gitlab-grack') + + find('.ref-selector').click + wait_for_requests + + page.within('.ref-selector') do + fill_in _('Search by Git revision'), with: ref + wait_for_requests + + find('li', text: ref).click + end + + expect(page).to have_selector('.results', text: 'path = gitlab-grack') + end end end - end - it 'no ref switcher shown in issue result summary', :js do - issue = create(:issue, title: 'test', project: project) - visit(project_tree_path(project)) + it 'no ref switcher shown in issue result summary' do + issue = create(:issue, title: 'test', project: project) + visit(project_tree_path(project)) - submit_search('test') - select_search_scope('Code') + submit_search('test') + select_search_scope('Code') - expect(page).to have_selector('.ref-selector') + expect(page).to have_selector('.ref-selector') - select_search_scope('Issues') + select_search_scope('Issues') - expect(find(:css, '.results')).to have_link(issue.title) - expect(page).not_to have_selector('.ref-selector') + expect(find(:css, '.results')).to have_link(issue.title) + expect(page).not_to have_selector('.ref-selector') + end end - end - context 'when signed out' do - let(:project) { create(:project, :public, :repository) } - - before do - stub_feature_flags(search_page_vertical_nav: false) - visit(project_path(project)) - end + context 'when signed out' do + before do + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) + end - it 'finds code' do - submit_search('rspec') - select_search_scope('Code') + context 'when block_anonymous_global_searches is enabled' do + it 'is redirected to login page' do + visit(search_path) - expect(page).to have_selector('.results', text: 'Update capybara, rspec-rails, poltergeist to recent versions') + expect(page).to have_content('You must be logged in to search across all of GitLab') + end + end end end end diff --git a/spec/features/search/user_searches_for_comments_spec.rb b/spec/features/search/user_searches_for_comments_spec.rb index a6793bc3aa7..3c39e9f41d4 100644 --- a/spec/features/search/user_searches_for_comments_spec.rb +++ b/spec/features/search/user_searches_for_comments_spec.rb @@ -2,45 +2,52 @@ require 'spec_helper' -RSpec.describe 'User searches for comments' do - let(:project) { create(:project, :repository) } - let(:user) { create(:user) } +RSpec.describe 'User searches for comments', :js, :disable_rate_limiter do + using RSpec::Parameterized::TableSyntax - before do - stub_feature_flags(search_page_vertical_nav: false) - project.add_reporter(user) - sign_in(user) + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } - visit(project_path(project)) - end + where(search_page_vertical_nav_enabled: [true, false]) + with_them do + before do + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) + project.add_reporter(user) + sign_in(user) - include_examples 'search timeouts', 'notes' + visit(project_path(project)) + end - context 'when a comment is in commits' do - context 'when comment belongs to an invalid commit' do - let(:comment) { create(:note_on_commit, author: user, project: project, commit_id: 12345678, note: 'Bug here') } + include_examples 'search timeouts', 'notes' do + let(:additional_params) { { project_id: project.id } } + end - it 'finds a commit' do - submit_search(comment.note) - select_search_scope('Comments') + context 'when a comment is in commits' do + context 'when comment belongs to an invalid commit' do + let(:comment) { create(:note_on_commit, author: user, project: project, commit_id: 12345678, note: 'Bug here') } - page.within('.results') do - expect(page).to have_content('Commit deleted') - expect(page).to have_content('12345678') + it 'finds a commit' do + submit_search(comment.note) + select_search_scope('Comments') + + page.within('.results') do + expect(page).to have_content('Commit deleted') + expect(page).to have_content('12345678') + end end end end - end - context 'when a comment is in a snippet' do - let(:snippet) { create(:project_snippet, :private, project: project, author: user, title: 'Some title') } - let(:comment) { create(:note, noteable: snippet, author: user, note: 'Supercalifragilisticexpialidocious', project: project) } + context 'when a comment is in a snippet' do + let(:snippet) { create(:project_snippet, :private, project: project, author: user, title: 'Some title') } + let(:comment) { create(:note, noteable: snippet, author: user, note: 'Supercalifragilisticexpialidocious', project: project) } - it 'finds a snippet' do - submit_search(comment.note) - select_search_scope('Comments') + it 'finds a snippet' do + submit_search(comment.note) + select_search_scope('Comments') - expect(page).to have_selector('.results', text: snippet.title) + expect(page).to have_selector('.results', text: snippet.title) + end end end end diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb index 4ec2a9e6cff..e5d86c27942 100644 --- a/spec/features/search/user_searches_for_commits_spec.rb +++ b/spec/features/search/user_searches_for_commits_spec.rb @@ -2,54 +2,62 @@ require 'spec_helper' -RSpec.describe 'User searches for commits', :js do +RSpec.describe 'User searches for commits', :js, :clean_gitlab_redis_rate_limiting do + using RSpec::Parameterized::TableSyntax + + let_it_be(:user) { create(:user) } + let(:project) { create(:project, :repository) } let(:sha) { '6d394385cf567f80a8fd85055db1ab4c5295806f' } - let(:user) { create(:user) } - before do - stub_feature_flags(search_page_vertical_nav: false) - project.add_reporter(user) - sign_in(user) + where(search_page_vertical_nav_enabled: [true, false]) + with_them do + before do + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) + project.add_reporter(user) + sign_in(user) - visit(search_path(project_id: project.id)) - end + visit(search_path(project_id: project.id)) + end - include_examples 'search timeouts', 'commits' + include_examples 'search timeouts', 'commits' do + let(:additional_params) { { project_id: project.id } } + end - context 'when searching by SHA' do - it 'finds a commit and redirects to its page' do - submit_search(sha) + context 'when searching by SHA' do + it 'finds a commit and redirects to its page' do + submit_search(sha) - expect(page).to have_current_path(project_commit_path(project, sha)) - end + expect(page).to have_current_path(project_commit_path(project, sha)) + end - it 'finds a commit in uppercase and redirects to its page' do - submit_search(sha.upcase) + it 'finds a commit in uppercase and redirects to its page' do + submit_search(sha.upcase) - expect(page).to have_current_path(project_commit_path(project, sha)) + expect(page).to have_current_path(project_commit_path(project, sha)) + end end - end - context 'when searching by message' do - it 'finds a commit and holds on /search page' do - project.repository.commit_files( - user, - message: 'Message referencing another sha: "deadbeef"', - branch_name: 'master', - actions: [{ action: :create, file_path: 'a/new.file', contents: 'new file' }] - ) + context 'when searching by message' do + it 'finds a commit and holds on /search page' do + project.repository.commit_files( + user, + message: 'Message referencing another sha: "deadbeef"', + branch_name: 'master', + actions: [{ action: :create, file_path: 'a/new.file', contents: 'new file' }] + ) - submit_search('deadbeef') + submit_search('deadbeef') - expect(page).to have_current_path('/search', ignore_query: true) - end + expect(page).to have_current_path('/search', ignore_query: true) + end - it 'finds multiple commits' do - submit_search('See merge request') - select_search_scope('Commits') + it 'finds multiple commits' do + submit_search('See merge request') + select_search_scope('Commits') - expect(page).to have_selector('.commit-row-description', visible: false, count: 9) + expect(page).to have_selector('.commit-row-description', visible: false, count: 9) + end end end end diff --git a/spec/features/search/user_searches_for_issues_spec.rb b/spec/features/search/user_searches_for_issues_spec.rb index 51d2f355848..22d48bd38f2 100644 --- a/spec/features/search/user_searches_for_issues_spec.rb +++ b/spec/features/search/user_searches_for_issues_spec.rb @@ -2,9 +2,12 @@ require 'spec_helper' -RSpec.describe 'User searches for issues', :js do - let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } +RSpec.describe 'User searches for issues', :js, :clean_gitlab_redis_rate_limiting do + using RSpec::Parameterized::TableSyntax + + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, namespace: user.namespace) } + let!(:issue1) { create(:issue, title: 'issue Foo', project: project, created_at: 1.hour.ago) } let!(:issue2) { create(:issue, :closed, :confidential, title: 'issue Bar', project: project) } @@ -14,127 +17,133 @@ RSpec.describe 'User searches for issues', :js do select_search_scope('Issues') end - context 'when signed in' do - before do - project.add_maintainer(user) - sign_in(user) - stub_feature_flags(search_page_vertical_nav: false) - - visit(search_path) - end + where(search_page_vertical_nav_enabled: [true, false]) - include_examples 'top right search form' - include_examples 'search timeouts', 'issues' + with_them do + context 'when signed in' do + before do + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) - it 'finds an issue' do - search_for_issue(issue1.title) + project.add_maintainer(user) + sign_in(user) - page.within('.results') do - expect(page).to have_link(issue1.title) - expect(page).not_to have_link(issue2.title) + visit(search_path) end - end - - it 'hides confidential icon for non-confidential issues' do - search_for_issue(issue1.title) - page.within('.results') do - expect(page).not_to have_css('[data-testid="eye-slash-icon"]') - end - end + include_examples 'top right search form' + include_examples 'search timeouts', 'issues' - it 'shows confidential icon for confidential issues' do - search_for_issue(issue2.title) + it 'finds an issue' do + search_for_issue(issue1.title) - page.within('.results') do - expect(page).to have_css('[data-testid="eye-slash-icon"]') + page.within('.results') do + expect(page).to have_link(issue1.title) + expect(page).not_to have_link(issue2.title) + end end - end - it 'shows correct badge for open issues' do - search_for_issue(issue1.title) + it 'hides confidential icon for non-confidential issues' do + search_for_issue(issue1.title) - page.within('.results') do - expect(page).to have_css('.badge-success') - expect(page).not_to have_css('.badge-info') + page.within('.results') do + expect(page).not_to have_css('[data-testid="eye-slash-icon"]') + end end - end - it 'shows correct badge for closed issues' do - search_for_issue(issue2.title) + it 'shows confidential icon for confidential issues' do + search_for_issue(issue2.title) - page.within('.results') do - expect(page).not_to have_css('.badge-success') - expect(page).to have_css('.badge-info') + page.within('.results') do + expect(page).to have_css('[data-testid="eye-slash-icon"]') + end end - end - it 'sorts by created date' do - search_for_issue('issue') + it 'shows correct badge for open issues' do + search_for_issue(issue1.title) - page.within('.results') do - expect(page.all('.search-result-row').first).to have_link(issue2.title) - expect(page.all('.search-result-row').last).to have_link(issue1.title) + page.within('.results') do + expect(page).to have_css('.badge-success') + expect(page).not_to have_css('.badge-info') + end end - find('[data-testid="sort-highest-icon"]').click + it 'shows correct badge for closed issues' do + search_for_issue(issue2.title) - page.within('.results') do - expect(page.all('.search-result-row').first).to have_link(issue1.title) - expect(page.all('.search-result-row').last).to have_link(issue2.title) + page.within('.results') do + expect(page).not_to have_css('.badge-success') + expect(page).to have_css('.badge-info') + end end - end - - context 'when on a project page' do - it 'finds an issue' do - find('[data-testid="project-filter"]').click - wait_for_requests + it 'sorts by created date' do + search_for_issue('issue') - page.within('[data-testid="project-filter"]') do - click_on(project.name) + page.within('.results') do + expect(page.all('.search-result-row').first).to have_link(issue2.title) + expect(page.all('.search-result-row').last).to have_link(issue1.title) end - search_for_issue(issue1.title) + find('[data-testid="sort-highest-icon"]').click page.within('.results') do - expect(page).to have_link(issue1.title) - expect(page).not_to have_link(issue2.title) + expect(page.all('.search-result-row').first).to have_link(issue1.title) + expect(page.all('.search-result-row').last).to have_link(issue2.title) end end - end - end - context 'when signed out' do - context 'when block_anonymous_global_searches is disabled' do - let(:project) { create(:project, :public) } + context 'when on a project page' do + it 'finds an issue' do + find('[data-testid="project-filter"]').click - before do - stub_feature_flags(block_anonymous_global_searches: false) - stub_feature_flags(search_page_vertical_nav: false) - visit(search_path) - end + wait_for_requests - include_examples 'top right search form' + page.within('[data-testid="project-filter"]') do + click_on(project.name) + end - it 'finds an issue' do - search_for_issue(issue1.title) + search_for_issue(issue1.title) - page.within('.results') do - expect(page).to have_link(issue1.title) - expect(page).not_to have_link(issue2.title) + page.within('.results') do + expect(page).to have_link(issue1.title) + expect(page).not_to have_link(issue2.title) + end end end end - context 'when block_anonymous_global_searches is enabled' do + context 'when signed out' do before do - stub_feature_flags(search_page_vertical_nav: false) - visit(search_path) + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) end - it 'is redirected to login page' do - expect(page).to have_content('You must be logged in to search across all of GitLab') + context 'when block_anonymous_global_searches is disabled' do + let_it_be(:project) { create(:project, :public) } + + before do + stub_feature_flags(block_anonymous_global_searches: false) + + visit(search_path) + end + + include_examples 'top right search form' + + it 'finds an issue' do + search_for_issue(issue1.title) + + page.within('.results') do + expect(page).to have_link(issue1.title) + expect(page).not_to have_link(issue2.title) + end + end + end + + context 'when block_anonymous_global_searches is enabled' do + it 'is redirected to login page' do + visit(search_path) + + expect(page).to have_content('You must be logged in to search across all of GitLab') + end end end end diff --git a/spec/features/search/user_searches_for_merge_requests_spec.rb b/spec/features/search/user_searches_for_merge_requests_spec.rb index a4fbe3a6e59..9bbf2cf16d8 100644 --- a/spec/features/search/user_searches_for_merge_requests_spec.rb +++ b/spec/features/search/user_searches_for_merge_requests_spec.rb @@ -2,7 +2,9 @@ require 'spec_helper' -RSpec.describe 'User searches for merge requests', :js do +RSpec.describe 'User searches for merge requests', :js, :clean_gitlab_redis_rate_limiting do + using RSpec::Parameterized::TableSyntax + let(:user) { create(:user) } let(:project) { create(:project, namespace: user.namespace) } let!(:merge_request1) { create(:merge_request, title: 'Merge Request Foo', source_project: project, target_project: project, created_at: 1.hour.ago) } @@ -14,62 +16,64 @@ RSpec.describe 'User searches for merge requests', :js do select_search_scope('Merge requests') end - before do - stub_feature_flags(search_page_vertical_nav: false) - project.add_maintainer(user) - sign_in(user) + where(search_page_vertical_nav_enabled: [true, false]) + with_them do + before do + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) + sign_in(user) - visit(search_path) - end + visit(search_path) + end - include_examples 'top right search form' - include_examples 'search timeouts', 'merge_requests' + include_examples 'top right search form' + include_examples 'search timeouts', 'merge_requests' - it 'finds a merge request' do - search_for_mr(merge_request1.title) + it 'finds a merge request' do + search_for_mr(merge_request1.title) - page.within('.results') do - expect(page).to have_link(merge_request1.title) - expect(page).not_to have_link(merge_request2.title) + page.within('.results') do + expect(page).to have_link(merge_request1.title) + expect(page).not_to have_link(merge_request2.title) - # Each result should have MR refs like `gitlab-org/gitlab!1` - page.all('.search-result-row').each do |e| - expect(e.text).to match(/!\d+/) + # Each result should have MR refs like `gitlab-org/gitlab!1` + page.all('.search-result-row').each do |e| + expect(e.text).to match(/!\d+/) + end end end - end - it 'sorts by created date' do - search_for_mr('Merge Request') + it 'sorts by created date' do + search_for_mr('Merge Request') - page.within('.results') do - expect(page.all('.search-result-row').first).to have_link(merge_request2.title) - expect(page.all('.search-result-row').last).to have_link(merge_request1.title) - end + page.within('.results') do + expect(page.all('.search-result-row').first).to have_link(merge_request2.title) + expect(page.all('.search-result-row').last).to have_link(merge_request1.title) + end - find('[data-testid="sort-highest-icon"]').click + find('[data-testid="sort-highest-icon"]').click - page.within('.results') do - expect(page.all('.search-result-row').first).to have_link(merge_request1.title) - expect(page.all('.search-result-row').last).to have_link(merge_request2.title) + page.within('.results') do + expect(page.all('.search-result-row').first).to have_link(merge_request1.title) + expect(page.all('.search-result-row').last).to have_link(merge_request2.title) + end end - end - context 'when on a project page' do - it 'finds a merge request' do - find('[data-testid="project-filter"]').click + context 'when on a project page' do + it 'finds a merge request' do + find('[data-testid="project-filter"]').click - wait_for_requests + wait_for_requests - page.within('[data-testid="project-filter"]') do - click_on(project.name) - end + page.within('[data-testid="project-filter"]') do + click_on(project.name) + end - search_for_mr(merge_request1.title) + search_for_mr(merge_request1.title) - page.within('.results') do - expect(page).to have_link(merge_request1.title) - expect(page).not_to have_link(merge_request2.title) + page.within('.results') do + expect(page).to have_link(merge_request1.title) + expect(page).not_to have_link(merge_request2.title) + end end end end diff --git a/spec/features/search/user_searches_for_milestones_spec.rb b/spec/features/search/user_searches_for_milestones_spec.rb index 6773059830c..702d4e60022 100644 --- a/spec/features/search/user_searches_for_milestones_spec.rb +++ b/spec/features/search/user_searches_for_milestones_spec.rb @@ -2,44 +2,30 @@ require 'spec_helper' -RSpec.describe 'User searches for milestones', :js do - let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } - let!(:milestone1) { create(:milestone, title: 'Foo', project: project) } - let!(:milestone2) { create(:milestone, title: 'Bar', project: project) } +RSpec.describe 'User searches for milestones', :js, :clean_gitlab_redis_rate_limiting do + using RSpec::Parameterized::TableSyntax - before do - project.add_maintainer(user) - sign_in(user) - stub_feature_flags(search_page_vertical_nav: false) + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, namespace: user.namespace) } - visit(search_path) - end + let!(:milestone1) { create(:milestone, title: 'Foo', project: project) } + let!(:milestone2) { create(:milestone, title: 'Bar', project: project) } - include_examples 'top right search form' - include_examples 'search timeouts', 'milestones' + where(search_page_vertical_nav_enabled: [true, false]) - it 'finds a milestone' do - fill_in('dashboard_search', with: milestone1.title) - find('.gl-search-box-by-click-search-button').click - select_search_scope('Milestones') + with_them do + before do + project.add_maintainer(user) + sign_in(user) + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) - page.within('.results') do - expect(page).to have_link(milestone1.title) - expect(page).not_to have_link(milestone2.title) + visit(search_path) end - end - - context 'when on a project page' do - it 'finds a milestone' do - find('[data-testid="project-filter"]').click - - wait_for_requests - page.within('[data-testid="project-filter"]') do - click_on(project.name) - end + include_examples 'top right search form' + include_examples 'search timeouts', 'milestones' + it 'finds a milestone' do fill_in('dashboard_search', with: milestone1.title) find('.gl-search-box-by-click-search-button').click select_search_scope('Milestones') @@ -49,5 +35,26 @@ RSpec.describe 'User searches for milestones', :js do expect(page).not_to have_link(milestone2.title) end end + + context 'when on a project page' do + it 'finds a milestone' do + find('[data-testid="project-filter"]').click + + wait_for_requests + + page.within('[data-testid="project-filter"]') do + click_on(project.name) + end + + fill_in('dashboard_search', with: milestone1.title) + find('.gl-search-box-by-click-search-button').click + select_search_scope('Milestones') + + page.within('.results') do + expect(page).to have_link(milestone1.title) + expect(page).not_to have_link(milestone2.title) + end + end + end end end diff --git a/spec/features/search/user_searches_for_projects_spec.rb b/spec/features/search/user_searches_for_projects_spec.rb index 5902859d1f5..15c6224b61b 100644 --- a/spec/features/search/user_searches_for_projects_spec.rb +++ b/spec/features/search/user_searches_for_projects_spec.rb @@ -2,15 +2,12 @@ require 'spec_helper' -RSpec.describe 'User searches for projects', :js do +RSpec.describe 'User searches for projects', :js, :disable_rate_limiter do let!(:project) { create(:project, :public, name: 'Shop') } context 'when signed out' do context 'when block_anonymous_global_searches is disabled' do before do - stub_feature_flags(search_page_vertical_nav: false) - allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit).and_return(1000) - allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit_unauthenticated).and_return(1000) stub_feature_flags(block_anonymous_global_searches: false) end diff --git a/spec/features/search/user_searches_for_users_spec.rb b/spec/features/search/user_searches_for_users_spec.rb index e21a66fed92..1d649b42c8c 100644 --- a/spec/features/search/user_searches_for_users_spec.rb +++ b/spec/features/search/user_searches_for_users_spec.rb @@ -2,84 +2,90 @@ require 'spec_helper' -RSpec.describe 'User searches for users' do - let(:user1) { create(:user, username: 'gob_bluth', name: 'Gob Bluth') } - let(:user2) { create(:user, username: 'michael_bluth', name: 'Michael Bluth') } - let(:user3) { create(:user, username: 'gob_2018', name: 'George Oscar Bluth') } - - before do - stub_feature_flags(search_page_vertical_nav: false) - sign_in(user1) - end - - include_examples 'search timeouts', 'users' +RSpec.describe 'User searches for users', :js, :clean_gitlab_redis_rate_limiting do + let_it_be(:user1) { create(:user, username: 'gob_bluth', name: 'Gob Bluth') } + let_it_be(:user2) { create(:user, username: 'michael_bluth', name: 'Michael Bluth') } + let_it_be(:user3) { create(:user, username: 'gob_2018', name: 'George Oscar Bluth') } - context 'when on the dashboard' do - it 'finds the user', :js do - visit dashboard_projects_path + where(search_page_vertical_nav_enabled: [true, false]) + with_them do + before do + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) - submit_search('gob') - select_search_scope('Users') + sign_in(user1) + end - page.within('.results') do - expect(page).to have_content('Gob Bluth') - expect(page).to have_content('@gob_bluth') + include_examples 'search timeouts', 'users' do + before do + visit(search_path) end end - end - context 'when on the project page' do - let(:project) { create(:project) } + context 'when on the dashboard' do + it 'finds the user' do + visit dashboard_projects_path - before do - create(:project_member, :developer, user: user1, project: project) - create(:project_member, :developer, user: user2, project: project) - user3 + submit_search('gob') + select_search_scope('Users') + + page.within('.results') do + expect(page).to have_content('Gob Bluth') + expect(page).to have_content('@gob_bluth') + end + end end - it 'finds the user belonging to the project' do - visit project_path(project) + context 'when on the project page' do + let_it_be_with_reload(:project) { create(:project) } - submit_search('gob') - select_search_scope('Users') + before do + project.add_developer(user1) + project.add_developer(user2) + end + + it 'finds the user belonging to the project' do + visit project_path(project) - page.within('.results') do - expect(page).to have_content('Gob Bluth') - expect(page).to have_content('@gob_bluth') + submit_search('gob') + select_search_scope('Users') - expect(page).not_to have_content('Michael Bluth') - expect(page).not_to have_content('@michael_bluth') + page.within('.results') do + expect(page).to have_content('Gob Bluth') + expect(page).to have_content('@gob_bluth') - expect(page).not_to have_content('George Oscar Bluth') - expect(page).not_to have_content('@gob_2018') + expect(page).not_to have_content('Michael Bluth') + expect(page).not_to have_content('@michael_bluth') + + expect(page).not_to have_content('George Oscar Bluth') + expect(page).not_to have_content('@gob_2018') + end end end - end - context 'when on the group page' do - let(:group) { create(:group) } + context 'when on the group page' do + let(:group) { create(:group) } - before do - create(:group_member, :developer, user: user1, group: group) - create(:group_member, :developer, user: user2, group: group) - user3 - end + before do + group.add_developer(user1) + group.add_developer(user2) + end - it 'finds the user belonging to the group' do - visit group_path(group) + it 'finds the user belonging to the group' do + visit group_path(group) - submit_search('gob') - select_search_scope('Users') + submit_search('gob') + select_search_scope('Users') - page.within('.results') do - expect(page).to have_content('Gob Bluth') - expect(page).to have_content('@gob_bluth') + page.within('.results') do + expect(page).to have_content('Gob Bluth') + expect(page).to have_content('@gob_bluth') - expect(page).not_to have_content('Michael Bluth') - expect(page).not_to have_content('@michael_bluth') + expect(page).not_to have_content('Michael Bluth') + expect(page).not_to have_content('@michael_bluth') - expect(page).not_to have_content('George Oscar Bluth') - expect(page).not_to have_content('@gob_2018') + expect(page).not_to have_content('George Oscar Bluth') + expect(page).not_to have_content('@gob_2018') + end end end end diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb index 2e390309022..0f20ad0aa07 100644 --- a/spec/features/search/user_searches_for_wiki_pages_spec.rb +++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb @@ -2,55 +2,59 @@ require 'spec_helper' -RSpec.describe 'User searches for wiki pages', :js do - let(:user) { create(:user) } +RSpec.describe 'User searches for wiki pages', :js, :clean_gitlab_redis_rate_limiting do + using RSpec::Parameterized::TableSyntax + + let_it_be(:user) { create(:user) } + let(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) } let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'directory/title', content: 'Some Wiki content') } - before do - stub_feature_flags(search_page_vertical_nav: false) - project.add_maintainer(user) - sign_in(user) - - visit(search_path) - end + where(search_page_vertical_nav_enabled: [true, false]) + with_them do + before do + stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled) + project.add_maintainer(user) + sign_in(user) - include_examples 'top right search form' - include_examples 'search timeouts', 'wiki_blobs' + visit(search_path) + end - shared_examples 'search wiki blobs' do - before do - stub_feature_flags(search_page_vertical_nav: false) + include_examples 'top right search form' + include_examples 'search timeouts', 'wiki_blobs' do + let(:additional_params) { { project_id: project.id } } end - it 'finds a page' do - find('[data-testid="project-filter"]').click + shared_examples 'search wiki blobs' do + it 'finds a page' do + find('[data-testid="project-filter"]').click - wait_for_requests + wait_for_requests - page.within('[data-testid="project-filter"]') do - click_on(project.name) - end + page.within('[data-testid="project-filter"]') do + click_on(project.name) + end - fill_in('dashboard_search', with: search_term) - find('.gl-search-box-by-click-search-button').click - select_search_scope('Wiki') + fill_in('dashboard_search', with: search_term) + find('.gl-search-box-by-click-search-button').click + select_search_scope('Wiki') - page.within('.results') do - expect(page).to have_link(wiki_page.title, href: project_wiki_path(project, wiki_page.slug)) + page.within('.results') do + expect(page).to have_link(wiki_page.title, href: project_wiki_path(project, wiki_page.slug)) + end end end - end - context 'when searching by content' do - it_behaves_like 'search wiki blobs' do - let(:search_term) { 'content' } + context 'when searching by content' do + it_behaves_like 'search wiki blobs' do + let(:search_term) { 'content' } + end end - end - context 'when searching by title' do - it_behaves_like 'search wiki blobs' do - let(:search_term) { 'title' } + context 'when searching by title' do + it_behaves_like 'search wiki blobs' do + let(:search_term) { 'title' } + end end end end 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 827e3984896..04f22cd2a31 100644 --- a/spec/features/search/user_uses_header_search_field_spec.rb +++ b/spec/features/search/user_uses_header_search_field_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'User uses header search field', :js do +RSpec.describe 'User uses header search field', :js, :disable_rate_limiter do include FilteredSearchHelpers let_it_be(:project) { create(:project, :repository) } @@ -17,10 +17,6 @@ RSpec.describe 'User uses header search field', :js do end before do - stub_feature_flags(search_page_vertical_nav: false) - allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).and_return(0) - allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit).and_return(1000) - allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit_unauthenticated).and_return(1000) sign_in(user) end diff --git a/spec/features/snippets/search_snippets_spec.rb b/spec/features/snippets/search_snippets_spec.rb index 69b9a0aa64d..d18729d080a 100644 --- a/spec/features/snippets/search_snippets_spec.rb +++ b/spec/features/snippets/search_snippets_spec.rb @@ -2,11 +2,7 @@ require 'spec_helper' -RSpec.describe 'Search Snippets' do - before do - stub_feature_flags(search_page_vertical_nav: false) - end - +RSpec.describe 'Search Snippets', :js do it 'user searches for snippets by title' do public_snippet = create(:personal_snippet, :public, title: 'Beginning and Middle') private_snippet = create(:personal_snippet, :private, title: 'Middle and End') diff --git a/spec/features/user_sees_marketing_header_spec.rb b/spec/features/user_sees_marketing_header_spec.rb index 31f088ce010..eae964cec02 100644 --- a/spec/features/user_sees_marketing_header_spec.rb +++ b/spec/features/user_sees_marketing_header_spec.rb @@ -6,50 +6,14 @@ RSpec.describe 'User sees experimental lmarketing header' do let_it_be(:project) { create(:project, :public) } context 'when not logged in' do - context 'when experiment candidate' do - it 'shows marketing header links', :aggregate_failures do - stub_experiments(logged_out_marketing_header: :candidate) - - visit project_path(project) - - expect(page).to have_text "About GitLab" - expect(page).to have_text "Pricing" - expect(page).to have_text "Talk to an expert" - expect(page).to have_text "Sign up now" - expect(page).to have_text "Login" - end - end - - context 'when experiment candidate (trial focused variant)' do - it 'shows marketing header links', :aggregate_failures do - stub_experiments(logged_out_marketing_header: :trial_focused) - - visit project_path(project) - - expect(page).to have_text "About GitLab" - expect(page).to have_text "Pricing" - expect(page).to have_text "Talk to an expert" - expect(page).to have_text "Get a free trial" - expect(page).to have_text "Sign up" - expect(page).to have_text "Login" - end - end - - context 'when experiment control' do - it 'does not show marketing header links', :aggregate_failures do - stub_experiments(logged_out_marketing_header: :control) - - visit project_path(project) + it 'shows marketing header links', :aggregate_failures do + visit project_path(project) - expect(page).not_to have_text "About GitLab" - expect(page).not_to have_text "Pricing" - expect(page).not_to have_text "Talk to an expert" - expect(page).not_to have_text "Sign up now" - expect(page).not_to have_text "Login" - expect(page).not_to have_text "Get a free trial" - expect(page).not_to have_text "Sign up" - expect(page).to have_text "Sign in / Register" - end + expect(page).to have_text "About GitLab" + expect(page).to have_text "Pricing" + expect(page).to have_text "Talk to an expert" + expect(page).to have_text "Sign up now" + expect(page).to have_text "Login" end end @@ -57,8 +21,6 @@ RSpec.describe 'User sees experimental lmarketing header' do it 'does not show marketing header links', :aggregate_failures do sign_in(create(:user)) - stub_experiments(logged_out_marketing_header: :candidate) - visit project_path(project) expect(page).not_to have_text "About GitLab" diff --git a/spec/features/users/active_sessions_spec.rb b/spec/features/users/active_sessions_spec.rb index c722a4ec05c..e2ee78a7cc5 100644 --- a/spec/features/users/active_sessions_spec.rb +++ b/spec/features/users/active_sessions_spec.rb @@ -30,7 +30,7 @@ RSpec.describe 'Active user sessions', :clean_gitlab_redis_sessions do user = create(:user) Gitlab::Redis::Sessions.with do |redis| - redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') + redis.sadd?("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') end gitlab_sign_in(user) @@ -45,7 +45,7 @@ RSpec.describe 'Active user sessions', :clean_gitlab_redis_sessions do personal_access_token = create(:personal_access_token, user: user) Gitlab::Redis::Sessions.with do |redis| - redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') + redis.sadd?("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') end visit user_path(user, :atom, private_token: personal_access_token.token) diff --git a/spec/features/work_items/work_item_children_spec.rb b/spec/features/work_items/work_item_children_spec.rb index 95774680a2b..10a1bf7541e 100644 --- a/spec/features/work_items/work_item_children_spec.rb +++ b/spec/features/work_items/work_item_children_spec.rb @@ -15,7 +15,6 @@ RSpec.describe 'Work item children', :js do sign_in(user) stub_feature_flags(work_items: true) - stub_feature_flags(work_items_hierarchy: true) visit project_issue_path(project, issue) @@ -49,6 +48,7 @@ RSpec.describe 'Work item children', :js do expect(page).not_to have_selector('[data-testid="add-links-form"]') click_button 'Add' + click_button 'New task' expect(page).to have_selector('[data-testid="add-links-form"]') @@ -58,9 +58,10 @@ RSpec.describe 'Work item children', :js do end end - it 'addss a child task', :aggregate_failures do + it 'adds a new child task', :aggregate_failures do page.within('[data-testid="work-item-links"]') do click_button 'Add' + click_button 'New task' expect(page).to have_button('Create task', disabled: true) fill_in 'Add a title', with: 'Task 1' @@ -78,6 +79,7 @@ RSpec.describe 'Work item children', :js do it 'removes a child task and undoing', :aggregate_failures do page.within('[data-testid="work-item-links"]') do click_button 'Add' + click_button 'New task' fill_in 'Add a title', with: 'Task 1' click_button 'Create task' wait_for_all_requests @@ -106,5 +108,29 @@ RSpec.describe 'Work item children', :js do expect(find('[data-testid="children-count"]')).to have_content('1') end end + + context 'with existing task' do + let_it_be(:task) { create(:work_item, :task, project: project) } + + it 'adds an existing child task', :aggregate_failures do + page.within('[data-testid="work-item-links"]') do + click_button 'Add' + click_button 'Existing task' + + expect(page).to have_button('Add task', disabled: true) + find('[data-testid="work-item-token-select-input"]').set(task.title) + wait_for_all_requests + click_button task.title + + expect(page).to have_button('Add task', disabled: false) + + click_button 'Add task' + + wait_for_all_requests + + expect(find('[data-testid="links-child"]')).to have_content(task.title) + end + end + end end end |