diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 13:37:47 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 13:37:47 +0000 |
commit | aee0a117a889461ce8ced6fcf73207fe017f1d99 (patch) | |
tree | 891d9ef189227a8445d83f35c1b0fc99573f4380 /spec/features | |
parent | 8d46af3258650d305f53b819eabf7ab18d22f59e (diff) | |
download | gitlab-ce-aee0a117a889461ce8ced6fcf73207fe017f1d99.tar.gz |
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'spec/features')
86 files changed, 1083 insertions, 753 deletions
diff --git a/spec/features/action_cable_logging_spec.rb b/spec/features/action_cable_logging_spec.rb index 2e6ce93f7f7..cf20b204cc5 100644 --- a/spec/features/action_cable_logging_spec.rb +++ b/spec/features/action_cable_logging_spec.rb @@ -25,7 +25,7 @@ RSpec.describe 'ActionCable logging', :js do username: user.username ) - expect(ActiveSupport::Notifications).to receive(:instrument).with('subscribe.action_cable', subscription_data) + expect(ActiveSupport::Notifications).to receive(:instrument).with('subscribe.action_cable', subscription_data).at_least(:once) gitlab_sign_in(user) visit project_issue_path(project, issue) diff --git a/spec/features/admin/admin_deploy_keys_spec.rb b/spec/features/admin/admin_deploy_keys_spec.rb index 53caf0fac33..9b74aa2ac5a 100644 --- a/spec/features/admin/admin_deploy_keys_spec.rb +++ b/spec/features/admin/admin_deploy_keys_spec.rb @@ -3,101 +3,125 @@ require 'spec_helper' RSpec.describe 'admin deploy keys' do + include Spec::Support::Helpers::ModalHelpers + let_it_be(:admin) { create(:admin) } let!(:deploy_key) { create(:deploy_key, public: true) } let!(:another_deploy_key) { create(:another_deploy_key, public: true) } before do - stub_feature_flags(admin_deploy_keys_vue: false) sign_in(admin) gitlab_enable_admin_mode_sign_in(admin) end - it 'show all public deploy keys' do - visit admin_deploy_keys_path + shared_examples 'renders deploy keys correctly' do + it 'show all public deploy keys' do + visit admin_deploy_keys_path - page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do - expect(page).to have_content(deploy_key.title) - expect(page).to have_content(another_deploy_key.title) + page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do + expect(page).to have_content(deploy_key.title) + expect(page).to have_content(another_deploy_key.title) + end end - end - it 'shows all the projects the deploy key has write access' do - write_key = create(:deploy_keys_project, :write_access, deploy_key: deploy_key) + it 'shows all the projects the deploy key has write access' do + write_key = create(:deploy_keys_project, :write_access, deploy_key: deploy_key) - visit admin_deploy_keys_path + visit admin_deploy_keys_path - page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do - expect(page).to have_content(write_key.project.full_name) + page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do + expect(page).to have_content(write_key.project.full_name) + end end - end - describe 'create a new deploy key' do - let(:new_ssh_key) { attributes_for(:key)[:key] } + describe 'create a new deploy key' do + let(:new_ssh_key) { attributes_for(:key)[:key] } - before do - visit admin_deploy_keys_path - click_link 'New deploy key' - end + before do + visit admin_deploy_keys_path + click_link 'New deploy key' + end - it 'creates a new deploy key' do - fill_in 'deploy_key_title', with: 'laptop' - fill_in 'deploy_key_key', with: new_ssh_key - click_button 'Create' + it 'creates a new deploy key' do + fill_in 'deploy_key_title', with: 'laptop' + fill_in 'deploy_key_key', with: new_ssh_key + click_button 'Create' - expect(current_path).to eq admin_deploy_keys_path + expect(current_path).to eq admin_deploy_keys_path - page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do - expect(page).to have_content('laptop') + page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do + expect(page).to have_content('laptop') + end end end - end - describe 'update an existing deploy key' do - before do - visit admin_deploy_keys_path - find('tr', text: deploy_key.title).click_link('Edit') - end + describe 'update an existing deploy key' do + before do + visit admin_deploy_keys_path + page.within('tr', text: deploy_key.title) do + click_link(_('Edit deploy key')) + end + end - it 'updates an existing deploy key' do - fill_in 'deploy_key_title', with: 'new-title' - click_button 'Save changes' + it 'updates an existing deploy key' do + fill_in 'deploy_key_title', with: 'new-title' + click_button 'Save changes' - expect(current_path).to eq admin_deploy_keys_path + expect(current_path).to eq admin_deploy_keys_path - page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do - expect(page).to have_content('new-title') + page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do + expect(page).to have_content('new-title') + end end end end - describe 'remove an existing deploy key' do - before do - visit admin_deploy_keys_path - end + context 'when `admin_deploy_keys_vue` feature flag is enabled', :js do + it_behaves_like 'renders deploy keys correctly' - it 'removes an existing deploy key' do - find('tr', text: deploy_key.title).click_link('Remove') + describe 'remove an existing deploy key' do + before do + visit admin_deploy_keys_path + end - expect(current_path).to eq admin_deploy_keys_path - page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do - expect(page).not_to have_content(deploy_key.title) + it 'removes an existing deploy key' do + accept_gl_confirm('Are you sure you want to delete this deploy key?', button_text: 'Delete') do + page.within('tr', text: deploy_key.title) do + click_button _('Delete deploy key') + end + end + + expect(current_path).to eq admin_deploy_keys_path + page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do + expect(page).not_to have_content(deploy_key.title) + end end end end - context 'when `admin_deploy_keys_vue` feature flag is enabled', :js do + context 'when `admin_deploy_keys_vue` feature flag is disabled' do before do - stub_feature_flags(admin_deploy_keys_vue: true) - - visit admin_deploy_keys_path + stub_feature_flags(admin_deploy_keys_vue: false) end - it 'renders the Vue app', :aggregate_failures do - expect(page).to have_content('Public deploy keys') - expect(page).to have_selector('[data-testid="deploy-keys-list"]') - expect(page).to have_link('New deploy key', href: new_admin_deploy_key_path) + it_behaves_like 'renders deploy keys correctly' + + describe 'remove an existing deploy key' do + before do + visit admin_deploy_keys_path + end + + it 'removes an existing deploy key' do + page.within('tr', text: deploy_key.title) do + click_link _('Remove deploy key') + end + + expect(current_path).to eq admin_deploy_keys_path + page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do + expect(page).not_to have_content(deploy_key.title) + end + end end end end diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb index 65de1160cfd..86d60b5d483 100644 --- a/spec/features/admin/admin_labels_spec.rb +++ b/spec/features/admin/admin_labels_spec.rb @@ -45,7 +45,7 @@ RSpec.describe 'admin issues labels' do wait_for_requests - expect(page).to have_content("There are no labels yet") + expect(page).to have_content("Define your default set of project labels") expect(page).not_to have_content('bug') expect(page).not_to have_content('feature_label') end diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb index a50ef34d327..8938bab60d7 100644 --- a/spec/features/admin/admin_projects_spec.rb +++ b/spec/features/admin/admin_projects_spec.rb @@ -6,6 +6,7 @@ RSpec.describe "Admin::Projects" do include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::Features::InviteMembersModalHelper include Select2Helper + include Spec::Support::Helpers::ModalHelpers let(:user) { create :user } let(:project) { create(:project) } @@ -39,7 +40,7 @@ RSpec.describe "Admin::Projects" do expect(page).to have_content(project.name) expect(page).to have_content(archived_project.name) - expect(page).to have_xpath("//span[@class='badge badge-warning']", text: 'archived') + expect(page).to have_xpath("//span[@class='gl-badge badge badge-pill badge-warning md']", text: 'archived') end it 'renders only archived projects', :js do @@ -145,7 +146,7 @@ RSpec.describe "Admin::Projects" do click_button 'Leave' end - page.within('[role="dialog"]') do + within_modal do click_button('Leave') end diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 7e2751daefa..cc2d36221dc 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe "Admin Runners" do include StubENV + include Spec::Support::Helpers::ModalHelpers before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') @@ -25,7 +26,7 @@ RSpec.describe "Admin Runners" do visit admin_runners_path expect(page).to have_text "Register an instance runner" - expect(page).to have_text "Runners currently online: 1" + expect(page).to have_text "Online Runners 1" end it 'with an instance runner shows an instance badge' do @@ -58,6 +59,55 @@ RSpec.describe "Admin Runners" do end end + it 'shows a job count' do + runner = create(:ci_runner, :project, projects: [project]) + + create(:ci_build, runner: runner) + create(:ci_build, runner: runner) + + visit admin_runners_path + + within "[data-testid='runner-row-#{runner.id}'] [data-label='Jobs']" do + expect(page).to have_content '2' + end + end + + describe 'delete runner' do + let!(:runner) { create(:ci_runner, description: 'runner-foo') } + + before do + visit admin_runners_path + + within "[data-testid='runner-row-#{runner.id}']" do + click_on 'Delete runner' + end + end + + it 'shows a confirmation modal' do + expect(page).to have_text "Delete runner ##{runner.id} (#{runner.short_sha})?" + expect(page).to have_text "Are you sure you want to continue?" + end + + it 'deletes a runner' do + within '.modal' do + click_on 'Delete runner' + end + + expect(page.find('.gl-toast')).to have_text(/Runner .+ deleted/) + expect(page).not_to have_content 'runner-foo' + end + + it 'cancels runner deletion' do + within '.modal' do + click_on 'Cancel' + end + + wait_for_requests + + expect(page).to have_content 'runner-foo' + end + end + describe 'search' do before do create(:ci_runner, :instance, description: 'runner-foo') @@ -323,7 +373,7 @@ RSpec.describe "Admin Runners" do it 'has all necessary texts including no runner message' do expect(page).to have_text "Register an instance runner" - expect(page).to have_text "Runners currently online: 0" + expect(page).to have_text "Online Runners 0" expect(page).to have_text 'No runners found' end end @@ -353,7 +403,7 @@ RSpec.describe "Admin Runners" do end it 'dismisses runner installation modal' do - page.within('[role="dialog"]') do + within_modal do click_button('Close', match: :first) end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 0a39baca259..29323c604ef 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -445,6 +445,24 @@ RSpec.describe 'Admin updates settings' do expect(current_settings.repository_storages_weighted).to eq('default' => 50) end + + context 'External storage for repository static objects' do + it 'changes Repository external storage settings' do + encrypted_token = Gitlab::CryptoHelper.aes256_gcm_encrypt('OldToken') + current_settings.update_attribute :static_objects_external_storage_auth_token_encrypted, encrypted_token + + visit repository_admin_application_settings_path + + page.within('.as-repository-static-objects') do + fill_in 'application_setting_static_objects_external_storage_url', with: 'http://example.com' + fill_in 'application_setting_static_objects_external_storage_auth_token', with: 'Token' + click_button 'Save changes' + end + + expect(current_settings.static_objects_external_storage_url).to eq('http://example.com') + expect(current_settings.static_objects_external_storage_auth_token).to eq('Token') + end + end end context 'Reporting page' do diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb index 73477fb93dd..ae940fecabe 100644 --- a/spec/features/admin/users/user_spec.rb +++ b/spec/features/admin/users/user_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'Admin::Users::User' do include Spec::Support::Helpers::Features::AdminUsersHelpers + include Spec::Support::Helpers::ModalHelpers let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') } let_it_be(:current_user) { create(:admin) } @@ -113,7 +114,7 @@ RSpec.describe 'Admin::Users::User' do click_action_in_user_dropdown(user_sole_owner_of_group.id, 'Delete user and contributions') - page.within('[role="dialog"]') do + within_modal do fill_in('username', with: user_sole_owner_of_group.name) click_button('Delete user and contributions') end @@ -426,7 +427,7 @@ RSpec.describe 'Admin::Users::User' do click_button 'Confirm user' - page.within('[role="dialog"]') do + within_modal do expect(page).to have_content("Confirm user #{unconfirmed_user.name}?") expect(page).to have_content('This user has an unconfirmed email address. You may force a confirmation.') diff --git a/spec/features/alert_management/alert_details_spec.rb b/spec/features/alert_management/alert_details_spec.rb index ce82b5adf8d..579b8221041 100644 --- a/spec/features/alert_management/alert_details_spec.rb +++ b/spec/features/alert_management/alert_details_spec.rb @@ -60,7 +60,7 @@ RSpec.describe 'Alert details', :js do expect(alert_status).to have_content('Triggered') - find('.btn-link').click + find('.gl-button').click find('.gl-new-dropdown-item', text: 'Acknowledged').click wait_for_requests @@ -79,7 +79,7 @@ RSpec.describe 'Alert details', :js do wait_for_requests - expect(alert_assignee).to have_content('Assignee Edit John Doe') + expect(alert_assignee).to have_content('Assignee Edit Sidney Jones') end end end diff --git a/spec/features/boards/board_filters_spec.rb b/spec/features/boards/board_filters_spec.rb new file mode 100644 index 00000000000..25e474bb676 --- /dev/null +++ b/spec/features/boards/board_filters_spec.rb @@ -0,0 +1,197 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Issue board filters', :js do + let_it_be(:project) { create(:project, :repository) } + 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) } + let_it_be(:milestone_2) { create(:milestone, project: project) } + 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) } + let_it_be(:issue_2) { create(:labeled_issue, project: project, milestone: milestone_2, assignees: [user], labels: [project_label], confidential: true) } + let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue_1) } + + let(:filtered_search) { find('[data-testid="issue_1-board-filtered-search"]') } + let(:filter_input) { find('.gl-filtered-search-term-input')} + let(:filter_dropdown) { find('.gl-filtered-search-suggestion-list') } + let(:filter_first_suggestion) { find('.gl-filtered-search-suggestion-list').first('.gl-filtered-search-suggestion') } + let(:filter_submit) { find('.gl-search-box-by-click-search-button') } + + before do + stub_feature_flags(issue_boards_filtered_search: true) + + project.add_maintainer(user) + sign_in(user) + + visit_project_board + end + + shared_examples 'loads all the users when opened' do + it 'and submit one as filter', :aggregate_failures do + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2) + + expect_filtered_search_dropdown_results(filter_dropdown, 3) + + click_on user.username + filter_submit.click + + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1) + expect(find('.board-card')).to have_content(issue.title) + end + end + + describe 'filters by assignee' do + before do + set_filter('assignee') + end + + it_behaves_like 'loads all the users when opened' do + let(:issue) { issue_2 } + end + end + + describe 'filters by author' do + before do + set_filter('author') + end + + it_behaves_like 'loads all the users when opened' do + let(:issue) { issue_1 } + end + end + + describe 'filters by label' do + before do + set_filter('label') + end + + it 'loads all the labels when opened and submit one as filter', :aggregate_failures do + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2) + + expect_filtered_search_dropdown_results(filter_dropdown, 3) + + filter_dropdown.click_on project_label.title + filter_submit.click + + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1) + expect(find('.board-card')).to have_content(issue_2.title) + end + end + + describe 'filters by releases' do + before do + set_filter('release') + end + + it 'loads all the releases when opened and submit one as filter', :aggregate_failures do + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2) + + expect_filtered_search_dropdown_results(filter_dropdown, 2) + + click_on release.tag + filter_submit.click + + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1) + expect(find('.board-card')).to have_content(issue_1.title) + end + end + + describe 'filters by confidentiality' do + before do + filter_input.click + filter_input.set("confidential:") + end + + it 'loads all the confidentiality options when opened and submit one as filter', :aggregate_failures do + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2) + + expect_filtered_search_dropdown_results(filter_dropdown, 2) + + filter_dropdown.click_on 'Yes' + filter_submit.click + + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1) + expect(find('.board-card')).to have_content(issue_2.title) + end + end + + describe 'filters by milestone' do + before do + set_filter('milestone') + end + + it 'loads all the milestones when opened and submit one as filter', :aggregate_failures do + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2) + + expect_filtered_search_dropdown_results(filter_dropdown, 6) + expect(filter_dropdown).to have_content('None') + expect(filter_dropdown).to have_content('Any') + expect(filter_dropdown).to have_content('Started') + expect(filter_dropdown).to have_content('Upcoming') + expect(filter_dropdown).to have_content(milestone_1.title) + expect(filter_dropdown).to have_content(milestone_2.title) + + click_on milestone_1.title + filter_submit.click + + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1) + end + end + + describe 'filters by reaction emoji' do + before do + set_filter('my-reaction') + end + + it 'loads all the emojis when opened and submit one as filter', :aggregate_failures do + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2) + + expect_filtered_search_dropdown_results(filter_dropdown, 3) + + click_on 'thumbsup' + filter_submit.click + + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1) + expect(find('.board-card')).to have_content(issue_1.title) + end + end + + describe 'filters by type' do + let_it_be(:incident) { create(:incident, project: project)} + + before do + set_filter('type') + end + + it 'loads all the types when opened and submit one as filter', :aggregate_failures do + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 3) + + expect_filtered_search_dropdown_results(filter_dropdown, 2) + + click_on 'Incident' + filter_submit.click + + expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1) + expect(find('.board-card')).to have_content(incident.title) + end + end + + def set_filter(filter) + filter_input.click + filter_input.set("#{filter}:") + filter_first_suggestion.click # Select `=` operator + end + + def expect_filtered_search_dropdown_results(filter_dropdown, count) + expect(filter_dropdown).to have_selector('.gl-new-dropdown-item', count: count) + end + + def visit_project_board + visit project_board_path(project, board) + wait_for_requests + end +end diff --git a/spec/features/boards/sidebar_due_date_spec.rb b/spec/features/boards/sidebar_due_date_spec.rb deleted file mode 100644 index 141c574ffec..00000000000 --- a/spec/features/boards/sidebar_due_date_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Project issue boards sidebar due date', :js do - include BoardHelpers - - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public) } - let_it_be(:issue) { create(:issue, project: project, relative_position: 1) } - let_it_be(:board) { create(:board, project: project) } - let_it_be(:list) { create(:list, board: board, position: 0) } - - let(:card) { find('.board:nth-child(1)').first('.board-card') } - - around do |example| - freeze_time { example.run } - end - - before do - project.add_maintainer(user) - - sign_in(user) - - visit project_board_path(project, board) - wait_for_requests - end - - context 'due date' do - it 'updates due date' do - click_card(card) - - page.within('[data-testid="sidebar-due-date"]') do - today = Date.today.day - - click_button 'Edit' - - click_button today.to_s - - wait_for_requests - - expect(page).to have_content(today.to_s(:medium)) - end - end - end -end diff --git a/spec/features/boards/sidebar_milestones_spec.rb b/spec/features/boards/sidebar_milestones_spec.rb deleted file mode 100644 index be7435263b1..00000000000 --- a/spec/features/boards/sidebar_milestones_spec.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Project issue boards sidebar milestones', :js do - include BoardHelpers - - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public) } - let_it_be(:milestone) { create(:milestone, project: project) } - let_it_be(:issue1) { create(:issue, project: project, relative_position: 1) } - let_it_be(:issue2) { create(:issue, project: project, milestone: milestone, relative_position: 2) } - let_it_be(:board) { create(:board, project: project) } - let_it_be(:list) { create(:list, board: board, position: 0) } - - let(:card1) { find('.board:nth-child(1) .board-card:nth-of-type(1)') } - let(:card2) { find('.board:nth-child(1) .board-card:nth-of-type(2)') } - - before do - project.add_maintainer(user) - - sign_in(user) - - visit project_board_path(project, board) - wait_for_requests - end - - context 'milestone' do - it 'adds a milestone' do - click_card(card1) - - page.within('[data-testid="sidebar-milestones"]') do - click_button 'Edit' - - wait_for_requests - - click_button milestone.title - - wait_for_requests - - page.within('[data-testid="select-milestone"]') do - expect(page).to have_content(milestone.title) - end - end - end - - it 'removes a milestone' do - click_card(card2) - - page.within('[data-testid="sidebar-milestones"]') do - click_button 'Edit' - - wait_for_requests - - click_button "No milestone" - - wait_for_requests - - page.within('[data-testid="select-milestone"]') do - expect(page).not_to have_content(milestone.title) - end - end - end - end -end diff --git a/spec/features/clusters/create_agent_spec.rb b/spec/features/clusters/create_agent_spec.rb index f40932c4750..7ed31a8c549 100644 --- a/spec/features/clusters/create_agent_spec.rb +++ b/spec/features/clusters/create_agent_spec.rb @@ -25,13 +25,13 @@ RSpec.describe 'Cluster agent registration', :js do it 'allows the user to select an agent to install, and displays the resulting agent token' do click_button('Actions') - expect(page).to have_content('Install new Agent') + expect(page).to have_content('Register') - click_button('Select an Agent') + click_button('Select an agent') click_button('example-agent-2') - click_button('Register Agent') + click_button('Register') - expect(page).to have_content('The token value will not be shown again after you close this window.') + expect(page).to have_content('You cannot see this token again after you close this window.') expect(page).to have_content('example-agent-token') expect(page).to have_content('docker run --pull=always --rm') diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 2dafaedd262..4378e88f7c1 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -24,14 +24,15 @@ RSpec.describe 'Commits' do end context 'commit status is Generic Commit Status' do - let!(:status) { create(:generic_commit_status, pipeline: pipeline) } + let!(:status) { create(:generic_commit_status, pipeline: pipeline, ref: pipeline.ref) } before do project.add_reporter(user) end - describe 'Commit builds' do + describe 'Commit builds with jobs_tab_feature flag off' do before do + stub_feature_flags(jobs_tab_vue: false) visit pipeline_path(pipeline) end @@ -89,8 +90,9 @@ RSpec.describe 'Commits' do end end - context 'Download artifacts' do + context 'Download artifacts with jobs_tab_vue feature flag off' do before do + stub_feature_flags(jobs_tab_vue: false) create(:ci_job_artifact, :archive, file: artifacts_file, job: build) end @@ -118,8 +120,9 @@ RSpec.describe 'Commits' do end end - context "when logged as reporter" do + context "when logged as reporter and with jobs_tab_vue feature flag off" do before do + stub_feature_flags(jobs_tab_vue: false) project.add_reporter(user) create(:ci_job_artifact, :archive, file: artifacts_file, job: build) visit pipeline_path(pipeline) diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb index 0b2811618b5..a9fb6a2ae7e 100644 --- a/spec/features/dashboard/issues_spec.rb +++ b/spec/features/dashboard/issues_spec.rb @@ -49,7 +49,7 @@ RSpec.describe 'Dashboard Issues' do describe 'new issue dropdown' do it 'shows projects only with issues feature enabled', :js do - find('.new-project-item-select-button').click + click_button 'Toggle project select' page.within('.select2-results') do expect(page).to have_content(project.full_name) @@ -58,7 +58,7 @@ RSpec.describe 'Dashboard Issues' do end it 'shows the new issue page', :js do - find('.new-project-item-select-button').click + click_button 'Toggle project select' wait_for_requests diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb index aa2485d4236..6239702edde 100644 --- a/spec/features/dashboard/merge_requests_spec.rb +++ b/spec/features/dashboard/merge_requests_spec.rb @@ -34,7 +34,7 @@ RSpec.describe 'Dashboard Merge Requests' do end it 'shows projects only with merge requests feature enabled', :js do - find('.new-project-item-select-button').click + click_button 'Toggle project select' page.within('.select2-results') do expect(page).to have_content(project.full_name) diff --git a/spec/features/dashboard/milestones_spec.rb b/spec/features/dashboard/milestones_spec.rb index 992ed2f2ce6..1ba16bf879a 100644 --- a/spec/features/dashboard/milestones_spec.rb +++ b/spec/features/dashboard/milestones_spec.rb @@ -35,7 +35,7 @@ RSpec.describe 'Dashboard > Milestones' do describe 'new milestones dropdown', :js do it 'takes user to a new milestone page', :js do - find('.new-project-item-select-button').click + click_button 'Toggle project select' page.within('.select2-results') do first('.select2-result-label').click diff --git a/spec/features/dashboard/root_spec.rb b/spec/features/dashboard/root_spec.rb deleted file mode 100644 index 55bb43c6fcf..00000000000 --- a/spec/features/dashboard/root_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Root path' do - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } - - before do - project.add_developer(user) - sign_in(user) - end - - it 'shows the customize banner', :js do - visit root_path - - expect(page).to have_content('Do you want to customize this page?') - end -end diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb index add4af2bcdb..63e16946a0b 100644 --- a/spec/features/expand_collapse_diffs_spec.rb +++ b/spec/features/expand_collapse_diffs_spec.rb @@ -7,7 +7,6 @@ RSpec.describe 'Expand and collapse diffs', :js do let(:project) { create(:project, :repository) } before do - stub_feature_flags(increased_diff_limits: false) allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes) admin = create(:admin) diff --git a/spec/features/gitlab_experiments_spec.rb b/spec/features/gitlab_experiments_spec.rb index 76b418adcea..ca772680ff6 100644 --- a/spec/features/gitlab_experiments_spec.rb +++ b/spec/features/gitlab_experiments_spec.rb @@ -31,9 +31,10 @@ RSpec.describe "Gitlab::Experiment", :js do expect(page).to have_content('Abuse Reports') - published_experiments = page.evaluate_script('window.gon.experiment') + published_experiments = page.evaluate_script('window.gl.experiments') expect(published_experiments).to include({ 'null_hypothesis' => { + 'excluded' => false, 'experiment' => 'null_hypothesis', 'key' => anything, 'variant' => 'candidate' diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb index a380edff3a4..0397e72502a 100644 --- a/spec/features/global_search_spec.rb +++ b/spec/features/global_search_spec.rb @@ -57,6 +57,14 @@ RSpec.describe 'Global search' do expect(page).to have_selector('.search-form') expect(page).to have_no_selector('#js-header-search') end + + it 'focuses search input when shortcut "s" is pressed', :js do + expect(page).not_to have_selector('#search:focus') + + find('body').native.send_key('s') + + expect(page).to have_selector('#search:focus') + end end describe 'when new_header_search feature is enabled' do @@ -70,5 +78,13 @@ RSpec.describe 'Global search' do expect(page).to have_no_selector('.search-form') expect(page).to have_selector('#js-header-search') end + + it 'focuses search input when shortcut "s" is pressed', :js do + expect(page).not_to have_selector('#search:focus') + + find('body').native.send_key('s') + + expect(page).to have_selector('#search:focus') + end end end diff --git a/spec/features/groups/container_registry_spec.rb b/spec/features/groups/container_registry_spec.rb index 098559dc3f8..f5af9ba8b7b 100644 --- a/spec/features/groups/container_registry_spec.rb +++ b/spec/features/groups/container_registry_spec.rb @@ -82,7 +82,7 @@ RSpec.describe 'Container Registry', :js do end it 'shows the image tags' do - expect(page).to have_content 'Image tags' + expect(page).to have_content '1 tag' first_tag = first('[data-testid="name"]') expect(first_tag).to have_content 'latest' end diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb index 4488f53a03f..0317f9162cc 100644 --- a/spec/features/groups/empty_states_spec.rb +++ b/spec/features/groups/empty_states_spec.rb @@ -101,7 +101,7 @@ RSpec.describe 'Group empty states' do it "the new #{issuable_name} button opens a project dropdown" do within '.empty-state' do - find('.new-project-item-select-button').click + click_button 'Toggle project select' end expect(page).to have_selector('.ajax-project-dropdown') diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb index 4e59ab40d04..1bac1bcdf5a 100644 --- a/spec/features/groups/issues_spec.rb +++ b/spec/features/groups/issues_spec.rb @@ -119,8 +119,9 @@ RSpec.describe 'Group issues page' do end it 'shows projects only with issues feature enabled', :js do - find('.empty-state .js-lazy-loaded') - find('.empty-state .new-project-item-link').click + within '.empty-state' do + click_button 'Toggle project select' + end page.within('.select2-results') do expect(page).to have_content(project.full_name) @@ -158,9 +159,7 @@ RSpec.describe 'Group issues page' do it 'each issue item has a user-can-drag css applied' do visit issues_group_path(group, sort: 'relative_position') - page.within('.manual-ordering') do - expect(page).to have_selector('.issue.user-can-drag', count: 3) - end + expect(page).to have_selector('.issue.user-can-drag', count: 3) end it 'issues should be draggable and persist order' do @@ -224,7 +223,8 @@ RSpec.describe 'Group issues page' do end it 'shows the pagination' do - expect(page).to have_selector('.gl-pagination') + expect(page).to have_link 'Prev' + expect(page).to have_link 'Next' end it 'first pagination item is active' do diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb index d822a5ea871..2beecda23b5 100644 --- a/spec/features/groups/members/manage_groups_spec.rb +++ b/spec/features/groups/members/manage_groups_spec.rb @@ -6,6 +6,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do include Select2Helper include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::Features::InviteMembersModalHelper + include Spec::Support::Helpers::ModalHelpers let_it_be(:user) { create(:user) } @@ -92,7 +93,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do click_button 'Remove group' end - page.within('[role="dialog"]') do + within_modal do click_button('Remove group') end diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb index 38e829bafcc..0ce50107e54 100644 --- a/spec/features/groups/members/manage_members_spec.rb +++ b/spec/features/groups/members/manage_members_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe 'Groups > Members > Manage members' do include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::Features::InviteMembersModalHelper + include Spec::Support::Helpers::ModalHelpers let_it_be(:user1) { create(:user, name: 'John Doe') } let_it_be(:user2) { create(:user, name: 'Mary Jane') } @@ -84,33 +85,6 @@ RSpec.describe 'Groups > Members > Manage members' do property: 'existing_user', user: user1 ) - expect_no_snowplow_event( - category: 'Members::CreateService', - action: 'area_of_focus' - ) - end - - it 'adds a user to group with area_of_focus', :js, :snowplow, :aggregate_failures do - stub_experiments(member_areas_of_focus: :candidate) - group.add_owner(user1) - - visit group_group_members_path(group) - - invite_member(user2.name, role: 'Reporter', area_of_focus: true) - wait_for_requests - - expect_snowplow_event( - category: 'Members::CreateService', - action: 'area_of_focus', - label: 'Contribute to the codebase', - property: group.members.last.id.to_s - ) - expect_snowplow_event( - category: 'Members::CreateService', - action: 'area_of_focus', - label: 'Collaborate on open issues and merge requests', - property: group.members.last.id.to_s - ) end it 'do not disclose email addresses', :js do @@ -170,7 +144,7 @@ RSpec.describe 'Groups > Members > Manage members' do click_button 'Remove member' end - page.within('[role="dialog"]') do + within_modal do expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests' click_button('Remove member') end @@ -220,36 +194,9 @@ RSpec.describe 'Groups > Members > Manage members' do property: 'net_new_user', user: user1 ) - expect_no_snowplow_event( - category: 'Members::CreateService', - action: 'area_of_focus' - ) end end - it 'invite user to group with area_of_focus', :js, :snowplow, :aggregate_failures do - stub_experiments(member_areas_of_focus: :candidate) - group.add_owner(user1) - - visit group_group_members_path(group) - - invite_member('test@example.com', role: 'Reporter', area_of_focus: true) - wait_for_requests - - expect_snowplow_event( - category: 'Members::InviteService', - action: 'area_of_focus', - label: 'Contribute to the codebase', - property: group.members.last.id.to_s - ) - expect_snowplow_event( - category: 'Members::InviteService', - action: 'area_of_focus', - label: 'Collaborate on open issues and merge requests', - property: group.members.last.id.to_s - ) - end - context 'when user is a guest' do before do group.add_guest(user1) diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb index 22409e9e7f6..da8032dc4dd 100644 --- a/spec/features/groups/navbar_spec.rb +++ b/spec/features/groups/navbar_spec.rb @@ -14,7 +14,6 @@ RSpec.describe 'Group navbar' do before do insert_package_nav(_('Kubernetes')) - stub_feature_flags(group_iterations: false) stub_feature_flags(customer_relations: false) stub_config(dependency_proxy: { enabled: false }) stub_config(registry: { enabled: false }) diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index 66ba4dc987c..a1e2990202c 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -33,7 +33,7 @@ RSpec.describe 'Help Pages' do stub_application_setting(version_check_enabled: true) stub_rails_env('production') - allow(VersionCheck).to receive(:url).and_return('/version-check-url') + allow(VersionCheck).to receive(:image_url).and_return('/version-check-url') sign_in(create(:user)) visit help_path diff --git a/spec/features/ide/clientside_preview_csp_spec.rb b/spec/features/ide/clientside_preview_csp_spec.rb index 559edb8bf53..849fdb0a44c 100644 --- a/spec/features/ide/clientside_preview_csp_spec.rb +++ b/spec/features/ide/clientside_preview_csp_spec.rb @@ -12,7 +12,7 @@ RSpec.describe 'IDE Clientside Preview CSP' do end it_behaves_like 'setting CSP', 'frame-src' do - let(:whitelisted_url) { 'https://sandbox.gitlab-static.test' } + let(:allowlisted_url) { 'https://sandbox.gitlab-static.test' } let(:extended_controller_class) { IdeController } subject do @@ -23,7 +23,7 @@ RSpec.describe 'IDE Clientside Preview CSP' do before do stub_application_setting(web_ide_clientside_preview_enabled: true) - stub_application_setting(web_ide_clientside_preview_bundler_url: whitelisted_url) + stub_application_setting(web_ide_clientside_preview_bundler_url: allowlisted_url) sign_in(user) end diff --git a/spec/features/ide/static_object_external_storage_csp_spec.rb b/spec/features/ide/static_object_external_storage_csp_spec.rb index 24d37f25739..421b5db0dbb 100644 --- a/spec/features/ide/static_object_external_storage_csp_spec.rb +++ b/spec/features/ide/static_object_external_storage_csp_spec.rb @@ -12,7 +12,7 @@ RSpec.describe 'Static Object External Storage Content Security Policy' do end it_behaves_like 'setting CSP', 'connect-src' do - let_it_be(:whitelisted_url) { 'https://static-objects.test' } + let_it_be(:allowlisted_url) { 'https://static-objects.test' } let_it_be(:extended_controller_class) { IdeController } subject do @@ -22,7 +22,7 @@ RSpec.describe 'Static Object External Storage Content Security Policy' do end before do - allow_any_instance_of(ApplicationSetting).to receive(:static_objects_external_storage_url).and_return(whitelisted_url) + allow_any_instance_of(ApplicationSetting).to receive(:static_objects_external_storage_url).and_return(allowlisted_url) allow_any_instance_of(ApplicationSetting).to receive(:static_objects_external_storage_auth_token).and_return('letmein') sign_in(user) diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb index f9ab780d2d6..9cb9416e7a0 100644 --- a/spec/features/invites_spec.rb +++ b/spec/features/invites_spec.rb @@ -226,34 +226,6 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do end end - context 'with invite email acceptance for the invite_email_preview_text experiment', :experiment do - let(:extra_params) do - { invite_type: Emails::Members::INITIAL_INVITE, experiment_name: 'invite_email_preview_text' } - end - - it 'tracks the accepted invite' do - expect(experiment(:invite_email_preview_text)).to track(:accepted) - .with_context(actor: group_invite) - .on_next_instance - - fill_in_sign_up_form(new_user) - end - end - - context 'with invite email acceptance for the invite_email_from experiment', :experiment do - let(:extra_params) do - { invite_type: Emails::Members::INITIAL_INVITE, experiment_name: 'invite_email_from' } - end - - it 'tracks the accepted invite' do - expect(experiment(:invite_email_from)).to track(:accepted) - .with_context(actor: group_invite) - .on_next_instance - - fill_in_sign_up_form(new_user) - end - end - it 'signs up and redirects to the group activity page with all the project/groups invitation automatically accepted' do fill_in_sign_up_form(new_user) fill_in_welcome_form diff --git a/spec/features/issuables/shortcuts_issuable_spec.rb b/spec/features/issuables/shortcuts_issuable_spec.rb index 78cd8d0bef3..7e8f39c47a7 100644 --- a/spec/features/issuables/shortcuts_issuable_spec.rb +++ b/spec/features/issuables/shortcuts_issuable_spec.rb @@ -44,4 +44,90 @@ RSpec.describe 'Blob shortcuts', :js do include_examples 'quotes the selected text' end end + + shared_examples "opens assignee dropdown for editing" do + it "opens assignee dropdown for editing" do + find('body').native.send_key('a') + + expect(find('.block.assignee')).to have_selector('.js-sidebar-assignee-data') + end + end + + describe 'pressing "a"' do + describe 'On an Issue' do + before do + stub_feature_flags(issue_assignees_widget: false) + visit project_issue_path(project, issue) + wait_for_requests + end + + include_examples 'opens assignee dropdown for editing' + end + + describe 'On a Merge Request' do + before do + stub_feature_flags(issue_assignees_widget: false) + visit project_merge_request_path(project, merge_request) + wait_for_requests + end + + include_examples 'opens assignee dropdown for editing' + end + end + + shared_examples "opens milestones dropdown for editing" do + it "opens milestones dropdown for editing" do + find('body').native.send_key('m') + + expect(find('[data-testid="milestone-edit"]')).to have_selector('.gl-new-dropdown-inner') + end + end + + describe 'pressing "m"' do + describe 'On an Issue' do + before do + visit project_issue_path(project, issue) + wait_for_requests + end + + include_examples 'opens milestones dropdown for editing' + end + + describe 'On a Merge Request' do + before do + visit project_merge_request_path(project, merge_request) + wait_for_requests + end + + include_examples 'opens milestones dropdown for editing' + end + end + + shared_examples "opens labels dropdown for editing" do + it "opens labels dropdown for editing" do + find('body').native.send_key('l') + + expect(find('.js-labels-block')).to have_selector('[data-testid="labels-select-dropdown-contents"]') + end + end + + describe 'pressing "l"' do + describe 'On an Issue' do + before do + visit project_issue_path(project, issue) + wait_for_requests + end + + include_examples 'opens labels dropdown for editing' + end + + describe 'On a Merge Request' do + before do + visit project_merge_request_path(project, merge_request) + wait_for_requests + end + + include_examples 'opens labels dropdown for editing' + end + end end diff --git a/spec/features/issuables/sorting_list_spec.rb b/spec/features/issuables/sorting_list_spec.rb index 6e07c6ffed2..f646cdbd71b 100644 --- a/spec/features/issuables/sorting_list_spec.rb +++ b/spec/features/issuables/sorting_list_spec.rb @@ -197,17 +197,13 @@ RSpec.describe 'Sort Issuable List' do click_button('Created date') click_on('Last updated') - wait_for_requests - - expect(first_issue).to include(last_updated_issuable.title) - expect(last_issue).to include(first_updated_issuable.title) + expect(page).to have_css('.issue:first-child', text: last_updated_issuable.title) + expect(page).to have_css('.issue:last-child', text: first_updated_issuable.title) click_on 'Sort direction' - wait_for_requests - - expect(first_issue).to include(first_updated_issuable.title) - expect(last_issue).to include(last_updated_issuable.title) + expect(page).to have_css('.issue:first-child', text: first_updated_issuable.title) + expect(page).to have_css('.issue:last-child', text: last_updated_issuable.title) end end end diff --git a/spec/features/issues/csv_spec.rb b/spec/features/issues/csv_spec.rb index b4c737495b4..9fd171bf44b 100644 --- a/spec/features/issues/csv_spec.rb +++ b/spec/features/issues/csv_spec.rb @@ -47,13 +47,13 @@ RSpec.describe 'Issues csv', :js do expect(page).to have_content "emailed to #{user.notification_email_or_default}" end - it 'includes a csv attachment', :sidekiq_might_not_need_inline do + it 'includes a csv attachment', :sidekiq_inline do request_csv expect(attachment.content_type).to include('text/csv') end - it 'ignores pagination', :sidekiq_might_not_need_inline do + it 'ignores pagination', :sidekiq_inline do create_list(:issue, 30, project: project, author: user) request_csv @@ -61,13 +61,13 @@ RSpec.describe 'Issues csv', :js do expect(csv.count).to eq 31 end - it 'uses filters from issue index', :sidekiq_might_not_need_inline do + it 'uses filters from issue index', :sidekiq_inline do request_csv(state: :closed) expect(csv.count).to eq 0 end - it 'ignores sorting from issue index', :sidekiq_might_not_need_inline do + it 'ignores sorting from issue index', :sidekiq_inline do issue2 = create(:labeled_issue, project: project, author: user, labels: [feature_label]) request_csv(sort: :label_priority) @@ -76,23 +76,11 @@ RSpec.describe 'Issues csv', :js do expect(csv.map { |row| row['Issue ID'] }).to eq expected end - it 'uses array filters, such as label_name', :sidekiq_might_not_need_inline do + it 'uses array filters, such as label_name', :sidekiq_inline do issue.update!(labels: [idea_label]) request_csv("label_name[]" => 'Bug') expect(csv.count).to eq 0 end - - it 'avoids excessive database calls' do - control_count = ActiveRecord::QueryRecorder.new { request_csv }.count - create_list(:labeled_issue, - 10, - project: project, - assignees: [user], - author: user, - milestone: milestone, - labels: [feature_label, idea_label]) - expect { request_csv }.not_to exceed_query_limit(control_count + 5) - end end diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 0cefbae4d37..b0e4729db8b 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -180,7 +180,7 @@ RSpec.describe 'GFM autocomplete', :js do describe 'assignees' do it 'does not wrap with quotes for assignee values' do - fill_in 'Comment', with: "@#{user.username[0]}" + fill_in 'Comment', with: "@#{user.username}" find_highlighted_autocomplete_item.click diff --git a/spec/features/issues/issue_header_spec.rb b/spec/features/issues/issue_header_spec.rb index cf375d8fb67..3e27ce81860 100644 --- a/spec/features/issues/issue_header_spec.rb +++ b/spec/features/issues/issue_header_spec.rb @@ -4,7 +4,8 @@ require 'spec_helper' RSpec.describe 'issue header', :js do let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } let_it_be(:issue) { create(:issue, project: project) } let_it_be(:closed_issue) { create(:issue, :closed, project: project) } let_it_be(:closed_locked_issue) { create(:issue, :closed, :locked, project: project) } @@ -12,7 +13,7 @@ RSpec.describe 'issue header', :js do context 'when user has permission to update' do before do - project.add_maintainer(user) + group.add_owner(user) sign_in(user) end @@ -24,9 +25,10 @@ RSpec.describe 'issue header', :js do click_button 'Issue actions' end - it 'only shows the "New issue" and "Report abuse" items', :aggregate_failures do + it 'shows the "New issue", "Report abuse", and "Delete issue" items', :aggregate_failures do expect(page).to have_link 'New issue' expect(page).to have_link 'Report abuse' + expect(page).to have_button 'Delete issue' expect(page).not_to have_link 'Submit as spam' end end @@ -116,6 +118,7 @@ RSpec.describe 'issue header', :js do expect(page).to have_link 'New issue' expect(page).to have_link 'Report abuse' expect(page).not_to have_link 'Submit as spam' + expect(page).not_to have_button 'Delete issue' end end diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index bd4be755a92..9da6694c681 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -11,7 +11,6 @@ RSpec.describe 'Issue Sidebar' do let_it_be(:label) { create(:label, project: project, title: 'bug') } let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label]) } let_it_be(:mock_date) { Date.today.at_beginning_of_month + 2.days } - let_it_be(:issue_with_due_date) { create(:issue, project: project, due_date: mock_date) } let_it_be(:xss_label) { create(:label, project: project, title: '<script>alert("xss");</script>') } before do @@ -201,30 +200,6 @@ RSpec.describe 'Issue Sidebar' do end end - context 'due date widget', :js do - let(:due_date_value) { find('[data-testid="due-date"] [data-testid="sidebar-date-value"]') } - - context 'when no due date exists' do - before do - visit_issue(project, issue) - end - - it "displays 'None'" do - expect(due_date_value.text).to have_content 'None' - end - end - - context 'when due date exists' do - before do - visit_issue(project, issue_with_due_date) - end - - it "displays the due date" do - expect(due_date_value.text).to have_content mock_date.strftime('%b %-d, %Y') - end - end - end - context 'as an allowed user' do before do project.add_developer(user) @@ -259,37 +234,11 @@ RSpec.describe 'Issue Sidebar' do end context 'editing issue milestone', :js do - let_it_be(:milestone_expired) { create(:milestone, project: project, title: 'Foo - expired', due_date: 5.days.ago) } - let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') } - let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) } - let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) } - let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) } - - before do - page.within('.block.milestone') do - click_button 'Edit' - end - - wait_for_all_requests - end - - it 'shows milestones list in the dropdown' do - page.within('.block.milestone') do - # 5 milestones + "No milestone" = 6 items - expect(page.find('.gl-new-dropdown-contents')).to have_selector('li.gl-new-dropdown-item', count: 6) - end - end - - it 'shows expired milestone at the bottom of the list and milestone due earliest at the top of the list', :aggregate_failures do - page.within('.block.milestone .gl-new-dropdown-contents') do - expect(page.find('li:last-child')).to have_content milestone_expired.title + it_behaves_like 'milestone sidebar widget' + end - expect(page.all('li.gl-new-dropdown-item')[1]).to have_content milestone3.title - expect(page.all('li.gl-new-dropdown-item')[2]).to have_content milestone2.title - expect(page.all('li.gl-new-dropdown-item')[3]).to have_content milestone1.title - expect(page.all('li.gl-new-dropdown-item')[4]).to have_content milestone_no_duedate.title - end - end + context 'editing issue due date', :js do + it_behaves_like 'date sidebar widget' end context 'editing issue labels', :js 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 97df2d0208b..71213fb661f 100644 --- a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb +++ b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb @@ -12,6 +12,9 @@ RSpec.describe 'Issues > Labels bulk assignment' do let!(:issue1) { create(:issue, project: project, title: "Issue 1", labels: [frontend]) } let!(:issue2) { create(:issue, project: project, title: "Issue 2") } + let(:issue_1_selector) { "#issue_#{issue1.id}" } + let(:issue_2_selector) { "#issue_#{issue2.id}" } + context 'as an allowed user', :js do before do project.add_maintainer(user) @@ -44,10 +47,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'frontend' - expect(find("#issue_#{issue2.id}")).to have_content 'bug' - expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'frontend' + expect(find(issue_2_selector)).to have_content 'bug' + expect(find(issue_2_selector)).not_to have_content 'frontend' end end @@ -60,10 +63,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'frontend' - expect(find("#issue_#{issue2.id}")).to have_content 'bug' - expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'frontend' + expect(find(issue_2_selector)).to have_content 'bug' + expect(find(issue_2_selector)).not_to have_content 'frontend' end end @@ -75,10 +78,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'frontend' - expect(find("#issue_#{issue2.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'frontend' + expect(find(issue_2_selector)).not_to have_content 'bug' + expect(find(issue_2_selector)).not_to have_content 'frontend' end end @@ -90,10 +93,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'frontend' - expect(find("#issue_#{issue2.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'frontend' + expect(find(issue_2_selector)).not_to have_content 'bug' + expect(find(issue_2_selector)).not_to have_content 'frontend' end end end @@ -107,10 +110,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'feature' - expect(find("#issue_#{issue2.id}")).to have_content 'bug' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'feature' + expect(find(issue_2_selector)).to have_content 'bug' + expect(find(issue_2_selector)).to have_content 'feature' end end @@ -122,10 +125,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'feature' - expect(find("#issue_#{issue2.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue2.id}")).not_to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'feature' + expect(find(issue_2_selector)).not_to have_content 'bug' + expect(find(issue_2_selector)).not_to have_content 'feature' end end end @@ -144,8 +147,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue2.id}")).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_2_selector)).to have_content 'bug' end end @@ -164,10 +167,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue1.id}")).not_to have_content 'feature' - expect(find("#issue_#{issue2.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue2.id}")).not_to have_content 'feature' + expect(find(issue_1_selector)).not_to have_content 'bug' + expect(find(issue_1_selector)).not_to have_content 'feature' + expect(find(issue_2_selector)).not_to have_content 'bug' + expect(find(issue_2_selector)).not_to have_content 'feature' end end @@ -183,8 +186,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' + expect(find(issue_1_selector)).not_to have_content 'bug' + expect(find(issue_2_selector)).to have_content 'feature' end end @@ -203,10 +206,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'feature' - expect(find("#issue_#{issue2.id}")).not_to have_content 'bug' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' + expect(find(issue_1_selector)).not_to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'feature' + expect(find(issue_2_selector)).not_to have_content 'bug' + expect(find(issue_2_selector)).to have_content 'feature' end end end @@ -222,18 +225,18 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it 'keeps labels' do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_2_selector)).to have_content 'feature' check 'Select all' open_milestone_dropdown(['First Release']) update_issues - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'First Release' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' - expect(find("#issue_#{issue2.id}")).to have_content 'First Release' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'First Release' + expect(find(issue_2_selector)).to have_content 'feature' + expect(find(issue_2_selector)).to have_content 'First Release' end end @@ -244,18 +247,18 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it 'keeps existing label and new label is present' do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'bug' check 'Select all' open_milestone_dropdown ['First Release'] open_labels_dropdown ['feature'] update_issues - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'feature' - expect(find("#issue_#{issue1.id}")).to have_content 'First Release' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' - expect(find("#issue_#{issue2.id}")).to have_content 'First Release' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'First Release' + expect(find(issue_2_selector)).to have_content 'feature' + expect(find(issue_2_selector)).to have_content 'First Release' end end @@ -269,9 +272,9 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it 'keeps existing label and new label is present' do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_2_selector)).to have_content 'feature' check 'Select all' @@ -279,11 +282,11 @@ RSpec.describe 'Issues > Labels bulk assignment' do unmark_labels_in_dropdown ['feature'] update_issues - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).not_to have_content 'feature' - expect(find("#issue_#{issue1.id}")).to have_content 'First Release' - expect(find("#issue_#{issue2.id}")).not_to have_content 'feature' - expect(find("#issue_#{issue2.id}")).to have_content 'First Release' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).not_to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'First Release' + expect(find(issue_2_selector)).not_to have_content 'feature' + expect(find(issue_2_selector)).to have_content 'First Release' end end @@ -300,19 +303,19 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it 'keeps labels' do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'First Release' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' - expect(find("#issue_#{issue2.id}")).to have_content 'First Release' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'First Release' + expect(find(issue_2_selector)).to have_content 'feature' + expect(find(issue_2_selector)).to have_content 'First Release' check 'Select all' open_milestone_dropdown(['No milestone']) update_issues - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).not_to have_content 'First Release' - expect(find("#issue_#{issue2.id}")).to have_content 'feature' - expect(find("#issue_#{issue2.id}")).not_to have_content 'First Release' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).not_to have_content 'First Release' + expect(find(issue_2_selector)).to have_content 'feature' + expect(find(issue_2_selector)).not_to have_content 'First Release' end end end @@ -324,7 +327,7 @@ RSpec.describe 'Issues > Labels bulk assignment' do end it do - expect(find("#issue_#{issue1.id}")).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'bug' check_issue issue1 open_labels_dropdown ['feature'] @@ -333,8 +336,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do update_issues sleep 1 # needed - expect(find("#issue_#{issue1.id}")).to have_content 'bug' - expect(find("#issue_#{issue1.id}")).to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'bug' + expect(find(issue_1_selector)).to have_content 'feature' end end @@ -350,7 +353,7 @@ RSpec.describe 'Issues > Labels bulk assignment' do update_issues - expect(find("#issue_#{issue1.id}")).to have_content 'feature' + expect(find(issue_1_selector)).to have_content 'feature' end end @@ -381,12 +384,12 @@ RSpec.describe 'Issues > Labels bulk assignment' do update_issues - first_issue = find("#issue_#{issue1.id}") + first_issue = find(issue_1_selector) expect(first_issue).not_to have_content 'bug' expect(first_issue).to have_content 'feature' expect(first_issue).to have_content 'wontfix' - second_issue = find("#issue_#{issue2.id}") + second_issue = find(issue_2_selector) expect(second_issue).not_to have_content 'bug' expect(second_issue).not_to have_content 'feature' expect(second_issue).to have_content 'wontfix' diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb index 76cec2502e3..a036a9a5bbc 100644 --- a/spec/features/issues/user_edits_issue_spec.rb +++ b/spec/features/issues/user_edits_issue_spec.rb @@ -15,7 +15,6 @@ RSpec.describe "Issues > User edits issue", :js do context 'with authorized user' do before do - stub_feature_flags(labels_widget: false) project.add_developer(user) project_with_milestones.add_developer(user) sign_in(user) @@ -146,12 +145,12 @@ RSpec.describe "Issues > User edits issue", :js do fill_in 'Comment', with: '/label ~syzygy' click_button 'Comment' - expect(page).to have_text('added syzygy label just now') + expect(page).to have_text('added syzygy label just now', wait: 300) page.within '.block.labels' do # Remove `verisimilitude` label within '.gl-label' do - click_button + click_button 'Remove label' end expect(page).to have_text('syzygy') @@ -418,7 +417,7 @@ RSpec.describe "Issues > User edits issue", :js do it 'adds due date to issue' do date = Date.today.at_beginning_of_month + 2.days - page.within '[data-testid="due-date"]' do + page.within '[data-testid="sidebar-due-date"]' do click_button 'Edit' page.within '.pika-single' do click_button date.day @@ -433,7 +432,7 @@ RSpec.describe "Issues > User edits issue", :js do it 'removes due date from issue' do date = Date.today.at_beginning_of_month + 2.days - page.within '[data-testid="due-date"]' do + page.within '[data-testid="sidebar-due-date"]' do click_button 'Edit' page.within '.pika-single' do diff --git a/spec/features/issues/user_invites_from_a_comment_spec.rb b/spec/features/issues/user_invites_from_a_comment_spec.rb deleted file mode 100644 index 82061f6ed79..00000000000 --- a/spec/features/issues/user_invites_from_a_comment_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -RSpec.describe "User invites from a comment", :js do - let_it_be(:project) { create(:project_empty_repo, :public) } - let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:user) { project.owner } - - before do - sign_in(user) - end - - it "launches the invite modal from invite link on a comment" do - stub_experiments(invite_members_in_comment: :invite_member_link) - - visit project_issue_path(project, issue) - - page.within(".new-note") do - click_button 'Invite Member' - end - - expect(page).to have_content("You're inviting members to the") - end -end diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb index 25c315f2d16..6c8d41fd96f 100644 --- a/spec/features/labels_hierarchy_spec.rb +++ b/spec/features/labels_hierarchy_spec.rb @@ -17,7 +17,6 @@ RSpec.describe 'Labels Hierarchy', :js do let!(:project_label_1) { create(:label, project: project_1, title: 'Label_4') } before do - stub_feature_flags(labels_widget: false) grandparent.add_owner(user) sign_in(user) @@ -28,13 +27,12 @@ RSpec.describe 'Labels Hierarchy', :js do [grandparent_group_label, parent_group_label, project_label_1].each do |label| page.within('.block.labels') do click_on 'Edit' - end - wait_for_requests + wait_for_requests - find('a.label-item', text: label.title).click - wait_for_requests - click_on 'Close' + click_on label.title + click_on 'Close' + end wait_for_requests @@ -66,7 +64,7 @@ RSpec.describe 'Labels Hierarchy', :js do end else expect_issues_list_count(1) - expect(page).to have_selector('span.issue-title-text', text: labeled_issue.title) + expect(page).to have_selector('.issue-title', text: labeled_issue.title) end end end @@ -76,7 +74,7 @@ RSpec.describe 'Labels Hierarchy', :js do wait_for_requests - expect(page).not_to have_selector('.btn-link', text: child_group_label.title) + expect(page).not_to have_link child_group_label.title end end @@ -109,9 +107,9 @@ RSpec.describe 'Labels Hierarchy', :js do end else expect_issues_list_count(3) - expect(page).to have_selector('span.issue-title-text', text: labeled_issue.title) - expect(page).to have_selector('span.issue-title-text', text: labeled_issue_2.title) - expect(page).to have_selector('span.issue-title-text', text: labeled_issue_3.title) + expect(page).to have_selector('.issue-title', text: labeled_issue.title) + expect(page).to have_selector('.issue-title', text: labeled_issue_2.title) + expect(page).to have_selector('.issue-title', text: labeled_issue_3.title) end end end @@ -131,7 +129,7 @@ RSpec.describe 'Labels Hierarchy', :js do end else expect_issues_list_count(1) - expect(page).to have_selector('span.issue-title-text', text: labeled_issue_3.title) + expect(page).to have_selector('.issue-title', text: labeled_issue_3.title) end end @@ -233,7 +231,7 @@ RSpec.describe 'Labels Hierarchy', :js do wait_for_requests - expect(page).not_to have_selector('.btn-link', text: child_group_label.title) + expect(page).not_to have_link child_group_label.title end end diff --git a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb index 06795344c5c..67a232607cd 100644 --- a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb +++ b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb @@ -7,19 +7,26 @@ RSpec.describe 'Merge request < User customizes merge commit message', :js do let(:user) { project.creator } let(:issue_1) { create(:issue, project: project)} let(:issue_2) { create(:issue, project: project)} + let(:source_branch) { 'csv' } + let(:target_branch) { 'master' } + let(:squash) { false } let(:merge_request) do create( :merge_request, - :simple, source_project: project, - description: "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}" + target_project: project, + source_branch: source_branch, + target_branch: target_branch, + description: "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}", + squash: squash ) end - let(:textbox) { page.find(:css, '#merge-message-edit', visible: false) } - let(:default_message) do + let(:merge_textbox) { page.find(:css, '#merge-message-edit', visible: false) } + let(:squash_textbox) { page.find(:css, '#squash-message-edit', visible: false) } + let(:default_merge_commit_message) do [ - "Merge branch 'feature' into 'master'", + "Merge branch '#{source_branch}' into '#{target_branch}'", merge_request.title, "Closes #{issue_1.to_reference} and #{issue_2.to_reference}", "See merge request #{merge_request.to_reference(full: true)}" @@ -35,8 +42,8 @@ RSpec.describe 'Merge request < User customizes merge commit message', :js do it 'has commit message without description' do expect(page).not_to have_selector('#merge-message-edit') first('.js-mr-widget-commits-count').click - expect(textbox).to be_visible - expect(textbox.value).to eq(default_message) + expect(merge_textbox).to be_visible + expect(merge_textbox.value).to eq(default_merge_commit_message) end context 'when target project has merge commit template set' do @@ -45,8 +52,34 @@ RSpec.describe 'Merge request < User customizes merge commit message', :js do it 'uses merge commit template' do expect(page).not_to have_selector('#merge-message-edit') first('.js-mr-widget-commits-count').click - expect(textbox).to be_visible - expect(textbox.value).to eq(merge_request.title) + expect(merge_textbox).to be_visible + expect(merge_textbox.value).to eq(merge_request.title) + end + end + + context 'when squash is performed' do + let(:squash) { true } + + it 'has default message with merge request title' do + expect(page).not_to have_selector('#squash-message-edit') + first('.js-mr-widget-commits-count').click + expect(squash_textbox).to be_visible + expect(merge_textbox).to be_visible + expect(squash_textbox.value).to eq(merge_request.title) + expect(merge_textbox.value).to eq(default_merge_commit_message) + end + + context 'when target project has squash commit template set' do + let(:project) { create(:project, :public, :repository, squash_commit_template: '%{description}') } + + it 'uses squash commit template' do + expect(page).not_to have_selector('#squash-message-edit') + first('.js-mr-widget-commits-count').click + expect(squash_textbox).to be_visible + expect(merge_textbox).to be_visible + expect(squash_textbox.value).to eq(merge_request.description) + expect(merge_textbox.value).to eq(default_merge_commit_message) + end end end end diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb index 09c5897f102..52554f11d28 100644 --- a/spec/features/merge_request/user_expands_diff_spec.rb +++ b/spec/features/merge_request/user_expands_diff_spec.rb @@ -7,7 +7,6 @@ RSpec.describe 'User expands diff', :js do let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) } before do - stub_feature_flags(increased_diff_limits: false) allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes) visit(diffs_project_merge_request_path(project, merge_request)) diff --git a/spec/features/merge_request/user_invites_from_a_comment_spec.rb b/spec/features/merge_request/user_invites_from_a_comment_spec.rb deleted file mode 100644 index 79865094fd0..00000000000 --- a/spec/features/merge_request/user_invites_from_a_comment_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -RSpec.describe "User invites from a comment", :js do - let_it_be(:project) { create(:project, :public, :repository) } - let_it_be(:merge_request) { create(:merge_request, source_project: project) } - let_it_be(:user) { project.owner } - - before do - sign_in(user) - end - - it "launches the invite modal from invite link on a comment" do - stub_experiments(invite_members_in_comment: :invite_member_link) - - visit project_merge_request_path(project, merge_request) - - page.within(".new-note") do - click_button 'Invite Member' - end - - expect(page).to have_content("You're inviting members to the") - end -end diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb index 79e46e69157..9e314e18563 100644 --- a/spec/features/merge_request/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'Merge request > User posts diff notes', :js do include MergeRequestDiffHelpers + include Spec::Support::Helpers::ModalHelpers let(:merge_request) { create(:merge_request) } let(:project) { merge_request.source_project } @@ -238,10 +239,8 @@ RSpec.describe 'Merge request > User posts diff notes', :js do def should_allow_dismissing_a_comment(line_holder, diff_side = nil) write_comment_on_line(line_holder, diff_side) - find('.js-close-discussion-note-form').click - - page.within('.modal') do - click_button 'OK' + accept_gl_confirm(s_('Notes|Are you sure you want to cancel creating this comment?')) do + find('.js-close-discussion-note-form').click end assert_comment_dismissal(line_holder) diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb index 93b14279a06..fd405855cf8 100644 --- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb +++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb @@ -33,7 +33,7 @@ RSpec.describe 'Merge request > User resolves Work in Progress', :js do it 'retains merge request data after clicking Resolve WIP status' do expect(page.find('.ci-widget-content')).to have_content("Pipeline ##{pipeline.id}") - expect(page).to have_content "This merge request is still a draft." + expect(page).to have_content "Merge blocked: merge request must be marked as ready. It's still marked as draft." page.within('.mr-state-widget') do click_button('Mark as ready') @@ -45,7 +45,7 @@ RSpec.describe 'Merge request > User resolves Work in Progress', :js do # merge request widget refreshes, which masks missing elements # that should already be present. expect(page.find('.ci-widget-content', wait: 0)).to have_content("Pipeline ##{pipeline.id}") - expect(page).not_to have_content('This merge request is still a draft.') + expect(page).not_to have_content("Merge blocked: merge request must be marked as ready. It's still marked as draft.") end end end diff --git a/spec/features/merge_request/user_sees_wip_help_message_spec.rb b/spec/features/merge_request/user_sees_wip_help_message_spec.rb index 0a6a3d82ee0..d33e54f2e3d 100644 --- a/spec/features/merge_request/user_sees_wip_help_message_spec.rb +++ b/spec/features/merge_request/user_sees_wip_help_message_spec.rb @@ -46,8 +46,8 @@ RSpec.describe 'Merge request > User sees draft help message' do 'It looks like you have some draft commits in this branch' ) expect(page).to have_text( - "Start the title with Draft: to prevent a merge request that is a \ -work in progress from being merged before it's ready." + "Start the title with Draft: to prevent a merge request draft \ +from merging before it's ready." ) end end diff --git a/spec/features/merge_request/user_squashes_merge_request_spec.rb b/spec/features/merge_request/user_squashes_merge_request_spec.rb index 15f59c0d7bc..2a48657ac4f 100644 --- a/spec/features/merge_request/user_squashes_merge_request_spec.rb +++ b/spec/features/merge_request/user_squashes_merge_request_spec.rb @@ -22,7 +22,7 @@ RSpec.describe 'User squashes a merge request', :js do committer_name: user.name) merge_commit = an_object_having_attributes(sha: a_string_matching(/\h{40}/), - message: a_string_starting_with("Merge branch 'csv' into 'master'"), + message: a_string_starting_with("Merge branch '#{source_branch}' into 'master'"), author_name: user.name, committer_name: user.name) @@ -57,34 +57,34 @@ RSpec.describe 'User squashes a merge request', :js do end context 'when the MR has only one commit' do - let(:source_branch) { 'master' } - let(:target_branch) { 'branch-merged' } - let(:protected_source_branch) { true } + let(:source_branch) { 'feature' } + let(:target_branch) { 'master' } let(:source_sha) { project.commit(source_branch).sha } let(:target_sha) { project.commit(target_branch).sha } before do - merge_request = create(:merge_request, source_project: project, target_project: project, source_branch: source_branch, target_branch: target_branch, squash: true) - - visit project_merge_request_path(project, merge_request) + visit project_new_merge_request_path(project, merge_request: { target_branch: target_branch, source_branch: source_branch }) + check 'merge_request[squash]' + click_on 'Create merge request' + wait_for_requests end - it 'accepts the merge request without issuing a squash request', :sidekiq_inline do - expect_next_instance_of(Gitlab::GitalyClient::OperationService) do |instance| - expect(instance).not_to receive(:user_squash) + context 'when squash message differs from existing commit message' do + before do + accept_mr end - expect(project.repository.ancestor?(source_branch, target_branch)).to be_falsey - expect(page).not_to have_field('squash') - - accept_mr - - expect(page).to have_content('Merged') + include_examples 'squash' + end - latest_target_commits = project.repository.commits_between(source_sha, target_sha).map(&:raw) + context 'when squash message is the same as existing commit message' do + before do + click_button("Modify commit messages") + fill_in('Squash commit message', with: project.commit(source_branch).safe_message) + accept_mr + end - expect(latest_target_commits.count).to eq(1) - expect(project.repository.ancestor?(source_branch, target_branch)).to be_truthy + include_examples 'no squash' end end diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb index 073706cf9d8..b5a973a53c0 100644 --- a/spec/features/merge_request/user_views_open_merge_request_spec.rb +++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb @@ -20,7 +20,7 @@ RSpec.describe 'User views an open merge request' do # Work around a weird Capybara behavior where calling `parent` on a node # returns the whole document, not the node's actual parent element - expect(find(:xpath, "#{node.path}/..").text).to eq(merge_request.description[2..-1]) + expect(find(:xpath, "#{node.path}/..").text).to eq(merge_request.description[2..]) expect(page).to have_content(merge_request.title) end diff --git a/spec/features/one_trust_spec.rb b/spec/features/one_trust_spec.rb new file mode 100644 index 00000000000..0ed08e8b99b --- /dev/null +++ b/spec/features/one_trust_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'OneTrust' do + context 'almost there page' do + context 'when OneTrust is enabled' do + let_it_be(:onetrust_url) { 'https://*.onetrust.com' } + let_it_be(:one_trust_id) { SecureRandom.uuid } + + before do + stub_config(extra: { one_trust_id: one_trust_id }) + stub_feature_flags(ecomm_instrumentation: true) + visit users_almost_there_path + end + + it 'has the OneTrust CSP settings', :aggregate_failures do + expect(response_headers['Content-Security-Policy']).to include("#{onetrust_url}") + expect(page.html).to include("https://cdn.cookielaw.org/consent/#{one_trust_id}/OtAutoBlock.js") + end + end + end +end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 7d935298f38..24ba55994ae 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -63,11 +63,24 @@ RSpec.describe 'Profile account page', :js do end describe 'when I reset feed token' do - before do + it 'resets feed token with `hide_access_tokens` feature flag enabled' do visit profile_personal_access_tokens_path + + within('[data-testid="feed-token-container"]') do + previous_token = find_field('Feed token').value + + accept_confirm { click_link('reset this token') } + + click_button('Click to reveal') + + expect(find_field('Feed token').value).not_to eq(previous_token) + end end - it 'resets feed token' do + it 'resets feed token with `hide_access_tokens` feature flag disabled' do + stub_feature_flags(hide_access_tokens: false) + visit profile_personal_access_tokens_path + within('.feed-token-reset') do previous_token = find("#feed_token").value @@ -82,10 +95,26 @@ RSpec.describe 'Profile account page', :js do before do allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) stub_feature_flags(bootstrap_confirmation_modals: false) + end + + it 'resets incoming email token with `hide_access_tokens` feature flag enabled' do visit profile_personal_access_tokens_path + + within('[data-testid="incoming-email-token-container"]') do + previous_token = find_field('Incoming email token').value + + accept_confirm { click_link('reset this token') } + + click_button('Click to reveal') + + expect(find_field('Incoming email token').value).not_to eq(previous_token) + end end - it 'resets incoming email token' do + it 'resets incoming email token with `hide_access_tokens` feature flag disabled' do + stub_feature_flags(hide_access_tokens: false) + visit profile_personal_access_tokens_path + within('.incoming-email-token-reset') do previous_token = find('#incoming_email_token').value diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb index 74505633cae..135a940807e 100644 --- a/spec/features/profiles/personal_access_tokens_spec.rb +++ b/spec/features/profiles/personal_access_tokens_spec.rb @@ -18,10 +18,6 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do find("#created-personal-access-token").value end - def feed_token - find("#feed_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 @@ -136,12 +132,24 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do describe "feed token" do context "when enabled" do - it "displays feed token" do + it "displays feed token with `hide_access_tokens` feature flag enabled" do allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(false) visit profile_personal_access_tokens_path - expect(feed_token).to eq(user.feed_token) + within('[data-testid="feed-token-container"]') do + click_button('Click to reveal') + + expect(page).to have_field('Feed token', with: user.feed_token) + expect(page).to have_content(feed_token_description) + end + end + + it "displays feed token with `hide_access_tokens` feature flag disabled" do + stub_feature_flags(hide_access_tokens: false) + allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(false) + visit profile_personal_access_tokens_path + expect(page).to have_field('Feed token', with: user.feed_token) expect(page).to have_content(feed_token_description) end end @@ -151,8 +159,8 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(true) visit profile_personal_access_tokens_path - expect(page).to have_no_content(feed_token_description) - expect(page).to have_no_css("#feed_token") + expect(page).not_to have_content(feed_token_description) + expect(page).not_to have_field('Feed token') end end end diff --git a/spec/features/profiles/two_factor_auths_spec.rb b/spec/features/profiles/two_factor_auths_spec.rb index a9256a73d7b..9a58950b8f3 100644 --- a/spec/features/profiles/two_factor_auths_spec.rb +++ b/spec/features/profiles/two_factor_auths_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe 'Two factor auths' do + include Spec::Support::Helpers::ModalHelpers + context 'when signed in' do before do sign_in(user) @@ -70,7 +72,7 @@ RSpec.describe 'Two factor auths' do click_button 'Disable two-factor authentication' - page.within('[role="dialog"]') do + within_modal do click_button 'Disable' end @@ -80,7 +82,7 @@ RSpec.describe 'Two factor auths' do click_button 'Disable two-factor authentication' - page.within('[role="dialog"]') do + within_modal do click_button 'Disable' end @@ -112,7 +114,7 @@ RSpec.describe 'Two factor auths' do click_button 'Disable two-factor authentication' - page.within('[role="dialog"]') do + within_modal do click_button 'Disable' end diff --git a/spec/features/profiles/user_visits_profile_spec.rb b/spec/features/profiles/user_visits_profile_spec.rb index 273d52996d3..d90ac439eee 100644 --- a/spec/features/profiles/user_visits_profile_spec.rb +++ b/spec/features/profiles/user_visits_profile_spec.rb @@ -29,6 +29,24 @@ RSpec.describe 'User visits their profile' do expect(find('.file-content')).to have_content('testme') end + it 'hides empty user readme' do + project = create(:project, :repository, :public, path: user.username, namespace: user.namespace) + + Files::UpdateService.new( + project, + user, + start_branch: 'master', + branch_name: 'master', + commit_message: 'Update feature', + file_path: 'README.md', + file_content: '' + ).execute + + visit(user_path(user)) + + expect(page).not_to have_selector('.file-content') + end + context 'when user has groups' do let(:group) do create :group do |group| diff --git a/spec/features/projects/ci/editor_spec.rb b/spec/features/projects/ci/editor_spec.rb index 7fe1c63f490..16cfa9f5f84 100644 --- a/spec/features/projects/ci/editor_spec.rb +++ b/spec/features/projects/ci/editor_spec.rb @@ -51,5 +51,65 @@ RSpec.describe 'Pipeline Editor', :js do expect(page).not_to have_content(default_branch) end end + + it 'displays new branch as selected after commiting on a new branch' do + find('#target-branch-field').set('new_branch', clear: :backspace) + + click_button 'Commit changes' + + page.within('[data-testid="branch-selector"]') do + expect(page).to have_content('new_branch') + expect(page).not_to have_content(default_branch) + end + end + end + + context 'Editor content' do + it 'user can reset their CI configuration' do + click_button 'Collapse' + + page.within('#source-editor-') do + find('textarea').send_keys '123' + end + + # It takes some time after sending keys for the reset + # btn to register the changes inside the editor + sleep 1 + click_button 'Reset' + + expect(page).to have_css('#reset-content') + + page.within('#reset-content') do + click_button 'Reset file' + end + + page.within('#source-editor-') do + expect(page).to have_content('Default Content') + expect(page).not_to have_content('Default Content123') + end + end + + it 'user can cancel reseting their CI configuration' do + click_button 'Collapse' + + page.within('#source-editor-') do + find('textarea').send_keys '123' + end + + # It takes some time after sending keys for the reset + # btn to register the changes inside the editor + sleep 1 + click_button 'Reset' + + expect(page).to have_css('#reset-content') + + page.within('#reset-content') do + click_button 'Cancel' + end + + page.within('#source-editor-') do + expect(page).to have_content('Default Content123') + end + end end end diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb index 3ef710169f0..4018ef2abc9 100644 --- a/spec/features/projects/cluster_agents_spec.rb +++ b/spec/features/projects/cluster_agents_spec.rb @@ -22,7 +22,7 @@ RSpec.describe 'ClusterAgents', :js do end it 'displays empty state', :aggregate_failures do - expect(page).to have_content('Install new Agent') + expect(page).to have_content('Install a new agent') expect(page).to have_selector('.empty-state') end end @@ -44,8 +44,17 @@ RSpec.describe 'ClusterAgents', :js do visit project_cluster_agent_path(project, agent.name) end - it 'displays agent and token information', :aggregate_failures do + it 'displays agent information', :aggregate_failures do expect(page).to have_content(agent.name) + end + + it 'displays agent activity tab', :aggregate_failures do + expect(page).to have_content('Activity') + end + + it 'displays agent tokens tab', :aggregate_failures do + expect(page).to have_content('Access tokens') + click_link 'Access tokens' expect(page).to have_content(token.description) end end diff --git a/spec/features/projects/clusters/eks_spec.rb b/spec/features/projects/clusters/eks_spec.rb index 09c10c0b3a9..a925e3a72f8 100644 --- a/spec/features/projects/clusters/eks_spec.rb +++ b/spec/features/projects/clusters/eks_spec.rb @@ -19,7 +19,7 @@ RSpec.describe 'AWS EKS Cluster', :js do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' click_link 'Connect with a certificate' end diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index e1659cd2fbf..6e88cbf52b5 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -33,7 +33,7 @@ RSpec.describe 'Gcp Cluster', :js do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' click_link 'Connect with a certificate' click_link 'Create new cluster' click_link 'Google GKE' @@ -49,7 +49,8 @@ RSpec.describe 'Gcp Cluster', :js do before do allow_any_instance_of(GoogleApi::CloudPlatform::Client) .to receive(:projects_zones_clusters_create) do - OpenStruct.new( + double( + 'cluster', self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', status: 'RUNNING' ) @@ -144,9 +145,9 @@ RSpec.describe 'Gcp Cluster', :js do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' click_button(class: 'dropdown-toggle-split') - click_link 'Connect with certificate' + click_link 'Connect with a certificate' end it 'user sees the "Environment scope" field' do @@ -160,7 +161,7 @@ RSpec.describe 'Gcp Cluster', :js do click_button 'Remove integration and resources' fill_in 'confirm_cluster_name_input', with: cluster.name click_button 'Remove integration' - click_link 'Certificate based' + click_link 'Certificate' end it 'user sees creation form with the successful message' do @@ -174,7 +175,7 @@ RSpec.describe 'Gcp Cluster', :js do context 'when user has not dismissed GCP signup offer' do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' end it 'user sees offer on cluster index page' do @@ -191,7 +192,7 @@ RSpec.describe 'Gcp Cluster', :js do context 'when user has dismissed GCP signup offer' do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' end it 'user does not see offer after dismissing' do diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index d3f709bfb53..d9887ea4fe0 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -25,7 +25,7 @@ RSpec.describe 'User Cluster', :js do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' click_link 'Connect with a certificate' click_link 'Connect existing cluster' end @@ -113,7 +113,7 @@ RSpec.describe 'User Cluster', :js do click_button 'Remove integration and resources' fill_in 'confirm_cluster_name_input', with: cluster.name click_button 'Remove integration' - click_link 'Certificate based' + click_link 'Certificate' end it 'user sees creation form with the successful message' do diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb index a49fa4c9e31..6e45529c659 100644 --- a/spec/features/projects/clusters_spec.rb +++ b/spec/features/projects/clusters_spec.rb @@ -10,13 +10,13 @@ RSpec.describe 'Clusters', :js do before do project.add_maintainer(user) - gitlab_sign_in(user) + sign_in(user) end context 'when user does not have a cluster and visits cluster index page' do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' end it 'sees empty state' do @@ -34,17 +34,17 @@ RSpec.describe 'Clusters', :js do before do create(:cluster, :provided_by_user, name: 'default-cluster', environment_scope: '*', projects: [project]) visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' click_button(class: 'dropdown-toggle-split') end it 'user sees an add cluster button' do - expect(page).to have_content('Connect with certificate') + expect(page).to have_content('Connect with a certificate') end context 'when user filled form with environment scope' do before do - click_link 'Connect with certificate' + click_link 'Connect with a certificate' fill_in 'cluster_name', with: 'staging-cluster' fill_in 'cluster_environment_scope', with: 'staging/*' click_button 'Add Kubernetes cluster' @@ -72,7 +72,7 @@ RSpec.describe 'Clusters', :js do context 'when user updates duplicated environment scope' do before do - click_link 'Connect with certificate' + click_link 'Connect with a certificate' fill_in 'cluster_name', with: 'staging-cluster' fill_in 'cluster_environment_scope', with: '*' fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'https://0.0.0.0' @@ -109,13 +109,13 @@ RSpec.describe 'Clusters', :js do create(:cluster, :provided_by_gcp, name: 'default-cluster', environment_scope: '*', projects: [project]) visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' end context 'when user filled form with environment scope' do before do click_button(class: 'dropdown-toggle-split') - click_link 'Create new cluster' + click_link 'Create a new cluster' click_link 'Google GKE' sleep 2 # wait for ajax @@ -160,7 +160,7 @@ RSpec.describe 'Clusters', :js do context 'when user updates duplicated environment scope' do before do click_button(class: 'dropdown-toggle-split') - click_link 'Create new cluster' + click_link 'Create a new cluster' click_link 'Google GKE' sleep 2 # wait for ajax @@ -190,7 +190,7 @@ RSpec.describe 'Clusters', :js do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' end it 'user sees a table with one cluster' do @@ -213,7 +213,7 @@ RSpec.describe 'Clusters', :js do before do visit project_clusters_path(project) - click_link 'Certificate based' + click_link 'Certificate' click_link 'Connect with a certificate' click_link 'Create new cluster' end diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb index eec50c3a66a..4ebcb69592b 100644 --- a/spec/features/projects/container_registry_spec.rb +++ b/spec/features/projects/container_registry_spec.rb @@ -87,7 +87,7 @@ RSpec.describe 'Container Registry', :js do end it 'shows the image tags' do - expect(page).to have_content 'Image tags' + expect(page).to have_content '20 tags' first_tag = first('[data-testid="name"]') expect(first_tag).to have_content '1' end diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb index fd83547d064..7159418deda 100644 --- a/spec/features/projects/files/user_creates_files_spec.rb +++ b/spec/features/projects/files/user_creates_files_spec.rb @@ -170,7 +170,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do end it 'shows a message saying the file will be committed in a fork' do - message = "A new branch will be created in your fork and a new merge request will be started." + message = "GitLab will create a branch in your fork and start a merge request." expect(page).to have_content(message) end diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb index 69e4303cce7..f9a6b67e469 100644 --- a/spec/features/projects/fork_spec.rb +++ b/spec/features/projects/fork_spec.rb @@ -59,10 +59,11 @@ RSpec.describe 'Project fork' do context 'forking is disabled' do let(:forking_access_level) { ProjectFeature::DISABLED } - it 'does not render fork button' do + it 'render a disabled fork button' do visit project_path(project) - expect(page).not_to have_css('a', text: 'Fork') + expect(page).to have_css('a.disabled', text: 'Fork') + expect(page).to have_css('a.count', text: '0') end it 'does not render new project fork page' do @@ -80,10 +81,11 @@ RSpec.describe 'Project fork' do end context 'user is not a team member' do - it 'does not render fork button' do + it 'render a disabled fork button' do visit project_path(project) - expect(page).not_to have_css('a', text: 'Fork') + expect(page).to have_css('a.disabled', text: 'Fork') + expect(page).to have_css('a.count', text: '0') end it 'does not render new project fork page' do @@ -102,6 +104,7 @@ RSpec.describe 'Project fork' do visit project_path(project) expect(page).to have_css('a', text: 'Fork') + expect(page).to have_css('a.count', text: '0') expect(page).not_to have_css('a.disabled', text: 'Fork') end diff --git a/spec/features/projects/integrations/user_activates_jira_spec.rb b/spec/features/projects/integrations/user_activates_jira_spec.rb index d7679d38cae..7a035248440 100644 --- a/spec/features/projects/integrations/user_activates_jira_spec.rb +++ b/spec/features/projects/integrations/user_activates_jira_spec.rb @@ -26,8 +26,7 @@ RSpec.describe 'User activates Jira', :js do unless Gitlab.ee? it 'adds Jira link to sidebar menu' do page.within('.nav-sidebar') do - expect(page).not_to have_link('Jira Issues') - expect(page).not_to have_link('Issue List', visible: false) + expect(page).not_to have_link('Jira issues', visible: false) expect(page).not_to have_link('Open Jira', href: url, visible: false) expect(page).to have_link('Jira', href: url) end diff --git a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb index bfa7be5bb5c..211576a93f3 100644 --- a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb +++ b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb @@ -10,6 +10,9 @@ RSpec.describe 'User uploads new design', :js do let(:issue) { create(:issue, project: project) } before do + # Cause of raising query limiting threshold https://gitlab.com/gitlab-org/gitlab/-/issues/347334 + stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 102) + sign_in(user) enable_design_management(feature_enabled) visit project_issue_path(project, issue) @@ -27,10 +30,10 @@ RSpec.describe 'User uploads new design', :js do expect(page).to have_content('dk.png') end - upload_design(gif_fixture, count: 2) + upload_design([gif_fixture, logo_svg_fixture, big_image_fixture], count: 4) - expect(page).to have_selector('.js-design-list-item', count: 2) - expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif']) + expect(page).to have_selector('.js-design-list-item', count: 4) + expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif', 'logo_sample.svg', 'big-image.png']) end end @@ -50,8 +53,16 @@ RSpec.describe 'User uploads new design', :js do Rails.root.join('spec', 'fixtures', 'banana_sample.gif') end - def upload_design(fixture, count:) - attach_file(:upload_file, fixture, match: :first, make_visible: true) + def logo_svg_fixture + Rails.root.join('spec', 'fixtures', 'logo_sample.svg') + end + + def big_image_fixture + Rails.root.join('spec', 'fixtures', 'big-image.png') + end + + def upload_design(fixtures, count:) + attach_file(:upload_file, fixtures, multiple: true, match: :first, make_visible: true) wait_for('designs uploaded') do issue.reload.designs.count == count diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb index 8538b894869..a47aab1ec70 100644 --- a/spec/features/projects/jobs/user_browses_jobs_spec.rb +++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb @@ -181,7 +181,7 @@ RSpec.describe 'User browses jobs' do name: 'rspec tests', stage: 'test') - create(:ci_job_artifact, :codequality, job: build) + create(:ci_job_artifact, :archive, job: build) end before do diff --git a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb index 4a25e28a14e..91a30004fc3 100644 --- a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb +++ b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb @@ -80,7 +80,7 @@ RSpec.describe 'Issue prioritization' do expect(issue_titles[0..1]).to contain_exactly('issue_5', 'issue_8') expect(issue_titles[2..4]).to contain_exactly('issue_1', 'issue_3', 'issue_7') - expect(issue_titles[5..-1]).to eq(%w(issue_2 issue_4 issue_6)) + expect(issue_titles[5..]).to eq(%w(issue_2 issue_4 issue_6)) end end end diff --git a/spec/features/projects/members/groups_with_access_list_spec.rb b/spec/features/projects/members/groups_with_access_list_spec.rb index eb32570448b..6adc3503492 100644 --- a/spec/features/projects/members/groups_with_access_list_spec.rb +++ b/spec/features/projects/members/groups_with_access_list_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'Projects > Members > Groups with access list', :js do include Spec::Support::Helpers::Features::MembersHelpers + include Spec::Support::Helpers::ModalHelpers let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group, :public) } @@ -70,7 +71,7 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do click_button 'Remove group' end - page.within('[role="dialog"]') do + within_modal do click_button('Remove group') end diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb index 308098c72a1..f2424a4acc3 100644 --- a/spec/features/projects/members/list_spec.rb +++ b/spec/features/projects/members/list_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe 'Project members list', :js do include Spec::Support::Helpers::Features::MembersHelpers include Spec::Support::Helpers::Features::InviteMembersModalHelper + include Spec::Support::Helpers::ModalHelpers let_it_be(:user1) { create(:user, name: 'John Doe') } let_it_be(:user2) { create(:user, name: 'Mary Jane') } @@ -93,7 +94,7 @@ RSpec.describe 'Project members list', :js do click_button 'Remove member' end - page.within('[role="dialog"]') do + within_modal do expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests' click_button('Remove member') end diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb index 9ffb1746f3e..6bd139c0ebe 100644 --- a/spec/features/projects/milestones/milestone_spec.rb +++ b/spec/features/projects/milestones/milestone_spec.rb @@ -2,10 +2,11 @@ require 'spec_helper' -RSpec.describe 'Project milestone' do +RSpec.describe 'Project milestone', :js do let(:user) { create(:user) } let(:project) { create(:project, name: 'test', namespace: user.namespace) } let(:milestone) { create(:milestone, project: project) } + let(:active_tab_selector) { '[role="tab"][aria-selected="true"]' } def toggle_sidebar find('.milestone-sidebar .gutter-toggle').click @@ -31,8 +32,9 @@ RSpec.describe 'Project milestone' do it 'shows issues tab' do within('#content-body') do expect(page).to have_link 'Issues', href: '#tab-issues' - expect(page).to have_selector '.nav-links li a.active', count: 1 - expect(find('.nav-links li a.active')).to have_content 'Issues' + expect(page).to have_selector active_tab_selector, count: 1 + expect(find(active_tab_selector)).to have_content 'Issues' + expect(page).to have_text('Unstarted Issues') end end @@ -49,6 +51,35 @@ RSpec.describe 'Project milestone' do end end + context 'when clicking on other tabs' do + using RSpec::Parameterized::TableSyntax + + where(:tab_text, :href, :panel_content) do + 'Merge requests' | '#tab-merge-requests' | 'Work in progress' + 'Participants' | '#tab-participants' | nil + 'Labels' | '#tab-labels' | nil + end + + with_them do + before do + visit project_milestone_path(project, milestone) + click_link(tab_text, href: href) + end + + it 'shows the merge requests tab and panel' do + within('#content-body') do + expect(find(active_tab_selector)).to have_content tab_text + expect(find(href)).to be_visible + expect(page).to have_text(panel_content) if panel_content + end + end + + it 'sets the location hash' do + expect(current_url).to end_with(href) + end + end + end + context 'when project has disabled issues' do before do create(:issue, project: project, milestone: milestone) @@ -59,7 +90,7 @@ RSpec.describe 'Project milestone' do it 'does not show any issues under the issues tab' do within('#content-body') do - expect(find('.nav-links li a.active')).to have_content 'Issues' + expect(find(active_tab_selector)).to have_content 'Issues' expect(page).not_to have_selector '.issuable-row' end end diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb index 06f130ae69c..bd4cb1aa39b 100644 --- a/spec/features/projects/pages/user_adds_domain_spec.rb +++ b/spec/features/projects/pages/user_adds_domain_spec.rb @@ -177,11 +177,11 @@ RSpec.describe 'User adds pages domain', :js do expect(domain.key).to be_nil end - it 'shows the DNS CNAME record' do + it 'shows the DNS ALIAS record' do visit project_pages_path(project) within('#content-body') { click_link 'Edit' } - expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}." + expect(page).to have_field :domain_dns, with: "#{domain.domain} ALIAS #{domain.project.pages_subdomain}.#{Settings.pages.host}." end end end diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb index 9df430c0f78..aae5ab58b5d 100644 --- a/spec/features/projects/pipeline_schedules_spec.rb +++ b/spec/features/projects/pipeline_schedules_spec.rb @@ -42,7 +42,7 @@ RSpec.describe 'Pipeline Schedules', :js do click_link 'Take ownership' page.within('.pipeline-schedule-table-row') do expect(page).not_to have_content('No owner') - expect(page).to have_link('John Doe') + expect(page).to have_link('Sidney Jones') end end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 944cee2a998..6ddc8e43762 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -53,6 +53,7 @@ RSpec.describe 'Pipeline', :js do pipeline: pipeline, name: 'jenkins', stage: 'external', + ref: 'master', target_url: 'http://gitlab.com/status') end end @@ -915,7 +916,7 @@ RSpec.describe 'Pipeline', :js do end end - describe 'GET /:project/-/pipelines/:id/builds' do + describe 'GET /:project/-/pipelines/:id/builds with jobs_tab_vue feature flag turned off' do include_context 'pipeline builds' let_it_be(:project) { create(:project, :repository) } @@ -923,6 +924,7 @@ RSpec.describe 'Pipeline', :js do let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) } before do + stub_feature_flags(jobs_tab_vue: false) visit builds_project_pipeline_path(project, pipeline) end diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index e38c4989f26..fb45db213d0 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -625,7 +625,7 @@ RSpec.describe 'Pipelines', :js do create_build('test', 1, 'audit', :created) create_build('deploy', 2, 'production', :created) - create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3) + create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3, ref: 'master') visit project_pipeline_path(project, pipeline) wait_for_requests diff --git a/spec/features/projects/settings/forked_project_settings_spec.rb b/spec/features/projects/settings/forked_project_settings_spec.rb index a84516e19f9..04fb6953b51 100644 --- a/spec/features/projects/settings/forked_project_settings_spec.rb +++ b/spec/features/projects/settings/forked_project_settings_spec.rb @@ -15,7 +15,7 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do end shared_examples 'project settings for a forked projects' do - it 'allows deleting the link to the forked project', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/327817' do + it 'allows deleting the link to the forked project' do visit edit_project_path(forked_project) click_button 'Remove fork relationship' diff --git a/spec/features/projects/settings/user_manages_project_members_spec.rb b/spec/features/projects/settings/user_manages_project_members_spec.rb index 02a634a0fcc..31dc939e6b8 100644 --- a/spec/features/projects/settings/user_manages_project_members_spec.rb +++ b/spec/features/projects/settings/user_manages_project_members_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe 'Projects > Settings > User manages project members' do include Spec::Support::Helpers::Features::MembersHelpers include Select2Helper + include Spec::Support::Helpers::ModalHelpers let(:group) { create(:group, name: 'OpenSource') } let(:project) { create(:project) } @@ -26,7 +27,7 @@ RSpec.describe 'Projects > Settings > User manages project members' do click_button 'Remove member' end - page.within('[role="dialog"]') do + within_modal do expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests' click_button('Remove member') end diff --git a/spec/features/projects/settings/user_transfers_a_project_spec.rb b/spec/features/projects/settings/user_transfers_a_project_spec.rb index ba4c379ef0a..a88b9101869 100644 --- a/spec/features/projects/settings/user_transfers_a_project_spec.rb +++ b/spec/features/projects/settings/user_transfers_a_project_spec.rb @@ -8,6 +8,8 @@ RSpec.describe 'Projects > Settings > User transfers a project', :js do let(:group) { create(:group) } before do + stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 120) + group.add_owner(user) sign_in(user) end @@ -16,10 +18,12 @@ RSpec.describe 'Projects > Settings > User transfers a project', :js do visit edit_project_path(project) page.within('.js-project-transfer-form') do - page.find('.select2-container').click + page.find('[data-testid="transfer-project-namespace"]').click end - page.find("div[role='option']", text: group.full_name).click + page.within('[data-testid="transfer-project-namespace"]') do + page.find("li button", text: group.full_name).click + end click_button('Transfer project') diff --git a/spec/features/projects/sourcegraph_csp_spec.rb b/spec/features/projects/sourcegraph_csp_spec.rb index 25d27462aa9..10dd050e8cc 100644 --- a/spec/features/projects/sourcegraph_csp_spec.rb +++ b/spec/features/projects/sourcegraph_csp_spec.rb @@ -13,7 +13,8 @@ RSpec.describe 'Sourcegraph Content Security Policy' do end it_behaves_like 'setting CSP', 'connect-src' do - let_it_be(:whitelisted_url) { 'https://sourcegraph.test' } + let_it_be(:sourcegraph_url) { 'https://sourcegraph.test' } + let_it_be(:allowlisted_url) { "#{sourcegraph_url}/.api/" } let_it_be(:extended_controller_class) { Projects::BlobController } subject do @@ -23,7 +24,7 @@ RSpec.describe 'Sourcegraph Content Security Policy' do end before do - allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(whitelisted_url) + allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(sourcegraph_url) allow(Gitlab::CurrentSettings).to receive(:sourcegraph_enabled).and_return(true) sign_in(user) diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb index 9f66b7274e8..17080043b6d 100644 --- a/spec/features/projects/tags/user_edits_tags_spec.rb +++ b/spec/features/projects/tags/user_edits_tags_spec.rb @@ -21,7 +21,8 @@ RSpec.describe 'Project > Tags', :js do context 'page with tags list' do it 'shows tag name' do - expect(page).to have_content 'v1.1.0 Version 1.1.0' + expect(page).to have_content 'v1.1.0' + expect(page).to have_content 'Version 1.1.0' end it 'shows tag edit button' do diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb index f5e8a5e8fc1..17c65e645f4 100644 --- a/spec/features/projects/user_creates_project_spec.rb +++ b/spec/features/projects/user_creates_project_spec.rb @@ -56,6 +56,31 @@ RSpec.describe 'User creates a project', :js do expect(page).to have_content('README.md Initial commit') end + it 'allows creating a new project when the new_project_sast_enabled is assigned the unchecked candidate' do + stub_experiments(new_project_sast_enabled: 'unchecked_candidate') + + visit(new_project_path) + + click_link 'Create blank project' + fill_in(:project_name, with: 'With initial commits') + + expect(page).to have_checked_field 'Initialize repository with a README' + expect(page).to have_unchecked_field 'Enable Static Application Security Testing (SAST)' + + check 'Enable Static Application Security Testing (SAST)' + + page.within('#content-body') do + click_button('Create project') + end + + project = Project.last + + expect(current_path).to eq(project_path(project)) + expect(page).to have_content('With initial commits') + expect(page).to have_content('Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist') + expect(page).to have_content('README.md Initial commit') + end + context 'in a subgroup they do not own' do let(:parent) { create(:group) } let!(:subgroup) { create(:group, parent: parent) } diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb index ef7af0ba138..c04a4493a9b 100644 --- a/spec/features/search/user_searches_for_code_spec.rb +++ b/spec/features/search/user_searches_for_code_spec.rb @@ -40,14 +40,24 @@ RSpec.describe 'User searches for code' do include_examples 'top right search form' include_examples 'search timeouts', 'blobs' - it 'finds code' do + it 'finds code and links to blob' do fill_in('dashboard_search', with: 'rspec') find('.btn-search').click expect(page).to have_selector('.results', text: 'Update capybara, rspec-rails, poltergeist to recent versions') - find("#L3").click - expect(current_url).to match(%r{master/.gitignore#L3}) + find("#blob-L3").click + expect(current_url).to match(%r{blob/master/.gitignore#L3}) + end + + it 'finds code and links to blame' do + fill_in('dashboard_search', with: 'rspec') + find('.btn-search').click + + expect(page).to have_selector('.results', text: 'Update capybara, rspec-rails, poltergeist to recent versions') + + find("#blame-L3").click + expect(current_url).to match(%r{blame/master/.gitignore#L3}) end it 'search mutiple words with refs switching' do @@ -65,7 +75,8 @@ RSpec.describe 'User searches for code' do expect(page).to have_selector('.results', text: expected_result) expect(find_field('dashboard_search').value).to eq(search) - expect(find("#L1502")[:href]).to match(%r{v1.0.0/files/markdown/ruby-style-guide.md#L1502}) + 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 diff --git a/spec/features/snippets/user_snippets_spec.rb b/spec/features/snippets/user_snippets_spec.rb index fe39208213a..bb733431b22 100644 --- a/spec/features/snippets/user_snippets_spec.rb +++ b/spec/features/snippets/user_snippets_spec.rb @@ -20,7 +20,7 @@ RSpec.describe 'User Snippets' do end it 'view my public snippets' do - page.within('.snippet-scope-menu') do + page.within('.js-snippets-nav-tabs') do click_link "Public" end @@ -30,7 +30,7 @@ RSpec.describe 'User Snippets' do end it 'view my internal snippets' do - page.within('.snippet-scope-menu') do + page.within('.js-snippets-nav-tabs') do click_link "Internal" end @@ -40,7 +40,7 @@ RSpec.describe 'User Snippets' do end it 'view my private snippets' do - page.within('.snippet-scope-menu') do + page.within('.js-snippets-nav-tabs') do click_link "Private" end diff --git a/spec/features/users/active_sessions_spec.rb b/spec/features/users/active_sessions_spec.rb index fab9f0884ae..6dc93fe017f 100644 --- a/spec/features/users/active_sessions_spec.rb +++ b/spec/features/users/active_sessions_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Active user sessions', :clean_gitlab_redis_shared_state do +RSpec.describe 'Active user sessions', :clean_gitlab_redis_sessions do it 'successful login adds a new active user login' do now = Time.zone.parse('2018-03-12 09:06') Timecop.freeze(now) do @@ -29,13 +29,13 @@ RSpec.describe 'Active user sessions', :clean_gitlab_redis_shared_state do it 'successful login cleans up obsolete entries' do user = create(:user) - Gitlab::Redis::SharedState.with do |redis| + Gitlab::Redis::Sessions.with do |redis| redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') end gitlab_sign_in(user) - Gitlab::Redis::SharedState.with do |redis| + Gitlab::Redis::Sessions.with do |redis| expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).not_to include '59822c7d9fcdfa03725eff41782ad97d' end end @@ -44,14 +44,14 @@ RSpec.describe 'Active user sessions', :clean_gitlab_redis_shared_state do user = create(:user) personal_access_token = create(:personal_access_token, user: user) - Gitlab::Redis::SharedState.with do |redis| + Gitlab::Redis::Sessions.with do |redis| redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d') end visit user_path(user, :atom, private_token: personal_access_token.token) expect(page.status_code).to eq 200 - Gitlab::Redis::SharedState.with do |redis| + Gitlab::Redis::Sessions.with do |redis| expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).to include '59822c7d9fcdfa03725eff41782ad97d' end end diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index 66ebd00d368..7ef11194ff9 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Login', :clean_gitlab_redis_shared_state do +RSpec.describe 'Login', :clean_gitlab_redis_sessions do include TermsHelper include UserLoginHelper include SessionHelpers @@ -84,7 +84,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do expect(page).to have_content('Your account has been blocked.') end - it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do + it 'does not update Devise trackable attributes' do expect(authentication_metrics) .to increment(:user_blocked_counter) .and increment(:user_unauthenticated_counter) @@ -161,7 +161,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do expect(page).to have_content('Invalid login or password.') end - it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do + it 'does not update Devise trackable attributes' do expect(authentication_metrics) .to increment(:user_unauthenticated_counter) .and increment(:user_password_invalid_counter) diff --git a/spec/features/users/one_trust_csp_spec.rb b/spec/features/users/one_trust_csp_spec.rb new file mode 100644 index 00000000000..382a0b4be6c --- /dev/null +++ b/spec/features/users/one_trust_csp_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'OneTrust content security policy' do + let(:user) { create(:user) } + + before do + stub_config(extra: { one_trust_id: SecureRandom.uuid }) + end + + it 'has proper Content Security Policy headers' do + visit root_path + + expect(response_headers['Content-Security-Policy']).to include('https://cdn.cookielaw.org https://*.onetrust.com') + end +end diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb index 61672662fbe..8edbf639c81 100644 --- a/spec/features/users/show_spec.rb +++ b/spec/features/users/show_spec.rb @@ -207,34 +207,31 @@ RSpec.describe 'User page' do state: :blocked, organization: 'GitLab - work info test', job_title: 'Frontend Engineer', - pronunciation: 'pruh-nuhn-see-ay-shn' + pronunciation: 'pruh-nuhn-see-ay-shn', + bio: 'My personal bio' ) end let_it_be(:status) { create(:user_status, user: user, message: "Working hard!") } - it 'shows no tab' do - subject + before do + visit_profile + end + it 'shows no tab' do expect(page).to have_css("div.profile-header") expect(page).not_to have_css("ul.nav-links") end it 'shows blocked message' do - subject - expect(page).to have_content("This user is blocked") end it 'shows user name as blocked' do - subject - expect(page).to have_css(".cover-title", text: 'Blocked user') end it 'shows no additional fields' do - subject - expect(page).not_to have_css(".profile-user-bio") expect(page).not_to have_content('GitLab - work info test') expect(page).not_to have_content('Frontend Engineer') @@ -243,10 +240,10 @@ RSpec.describe 'User page' do end it 'shows username' do - subject - expect(page).to have_content("@#{user.username}") end + + it_behaves_like 'default brand title page meta description' end context 'with unconfirmed user' do @@ -256,7 +253,8 @@ RSpec.describe 'User page' do :unconfirmed, organization: 'GitLab - work info test', job_title: 'Frontend Engineer', - pronunciation: 'pruh-nuhn-see-ay-shn' + pronunciation: 'pruh-nuhn-see-ay-shn', + bio: 'My personal bio' ) end @@ -287,6 +285,8 @@ RSpec.describe 'User page' do it 'shows private profile message' do expect(page).to have_content("This user has a private profile") end + + it_behaves_like 'default brand title page meta description' end context 'when visited by an authenticated user' do diff --git a/spec/features/webauthn_spec.rb b/spec/features/webauthn_spec.rb index 4eebc9d2c1e..215d1ff1cb6 100644 --- a/spec/features/webauthn_spec.rb +++ b/spec/features/webauthn_spec.rb @@ -113,124 +113,94 @@ RSpec.describe 'Using WebAuthn Devices for Authentication', :js do describe 'authentication' do let(:otp_required_for_login) { true } let(:user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) } + let!(:webauthn_device) do + add_webauthn_device(app_id, user) + end - describe 'when there is only an U2F device' do - let!(:u2f_device) do - fake_device = U2F::FakeU2F.new(app_id) # "Client" - u2f = U2F::U2F.new(app_id) # "Server" + describe 'when 2FA via OTP is disabled' do + let(:otp_required_for_login) { false } - challenges = u2f.registration_requests.map(&:challenge) - device_response = fake_device.register_response(challenges[0]) - device_registration_params = { device_response: device_response, - name: 'My device' } + it 'allows logging in with the WebAuthn device' do + gitlab_sign_in(user) - U2fRegistration.register(user, app_id, device_registration_params, challenges) - FakeU2fDevice.new(page, 'My device', fake_device) - end + webauthn_device.respond_to_webauthn_authentication - it 'falls back to U2F' do - # WebAuthn registration is automatically created with the U2fRegistration because of the after_create callback - # so we need to delete it - WebauthnRegistration.delete_all + expect(page).to have_css('.sign-out-link', visible: false) + end + end + describe 'when 2FA via OTP is enabled' do + it 'allows logging in with the WebAuthn device' do gitlab_sign_in(user) - u2f_device.respond_to_u2f_authentication + webauthn_device.respond_to_webauthn_authentication expect(page).to have_css('.sign-out-link', visible: false) end end - describe 'when there is a WebAuthn device' do - let!(:webauthn_device) do - add_webauthn_device(app_id, user) - end + describe 'when a given WebAuthn device has already been registered by another user' do + describe 'but not the current user' do + let(:other_user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) } - describe 'when 2FA via OTP is disabled' do - let(:otp_required_for_login) { false } + it 'does not allow logging in with that particular device' do + # Register other user with a different WebAuthn device + other_device = add_webauthn_device(app_id, other_user) - it 'allows logging in with the WebAuthn device' do + # Try authenticating user with the old WebAuthn device gitlab_sign_in(user) - - webauthn_device.respond_to_webauthn_authentication - - expect(page).to have_css('.sign-out-link', visible: false) + other_device.respond_to_webauthn_authentication + expect(page).to have_content('Authentication via WebAuthn device failed') end end - describe 'when 2FA via OTP is enabled' do - it 'allows logging in with the WebAuthn device' do - gitlab_sign_in(user) - + describe "and also the current user" do + # TODO Uncomment once WebAuthn::FakeClient supports passing credential options + # (especially allow_credentials, as this is needed to specify which credential the + # fake client should use. Currently, the first credential is always used). + # There is an issue open for this: https://github.com/cedarcode/webauthn-ruby/issues/259 + it "allows logging in with that particular device" do + pending("support for passing credential options in FakeClient") + # Register current user with the same WebAuthn device + current_user = gitlab_sign_in(:user) + visit profile_account_path + manage_two_factor_authentication + register_webauthn_device(webauthn_device) + gitlab_sign_out + + # Try authenticating user with the same WebAuthn device + gitlab_sign_in(current_user) webauthn_device.respond_to_webauthn_authentication expect(page).to have_css('.sign-out-link', visible: false) end end + end - describe 'when a given WebAuthn device has already been registered by another user' do - describe 'but not the current user' do - let(:other_user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) } - - it 'does not allow logging in with that particular device' do - # Register other user with a different WebAuthn device - other_device = add_webauthn_device(app_id, other_user) - - # Try authenticating user with the old WebAuthn device - gitlab_sign_in(user) - other_device.respond_to_webauthn_authentication - expect(page).to have_content('Authentication via WebAuthn device failed') - end - end - - describe "and also the current user" do - # TODO Uncomment once WebAuthn::FakeClient supports passing credential options - # (especially allow_credentials, as this is needed to specify which credential the - # fake client should use. Currently, the first credential is always used). - # There is an issue open for this: https://github.com/cedarcode/webauthn-ruby/issues/259 - it "allows logging in with that particular device" do - pending("support for passing credential options in FakeClient") - # Register current user with the same WebAuthn device - current_user = gitlab_sign_in(:user) - visit profile_account_path - manage_two_factor_authentication - register_webauthn_device(webauthn_device) - gitlab_sign_out - - # Try authenticating user with the same WebAuthn device - gitlab_sign_in(current_user) - webauthn_device.respond_to_webauthn_authentication - - expect(page).to have_css('.sign-out-link', visible: false) - end - end - end - - describe 'when a given WebAuthn device has not been registered' do - it 'does not allow logging in with that particular device' do - unregistered_device = FakeWebauthnDevice.new(page, 'My device') - gitlab_sign_in(user) - unregistered_device.respond_to_webauthn_authentication + describe 'when a given WebAuthn device has not been registered' do + it 'does not allow logging in with that particular device' do + unregistered_device = FakeWebauthnDevice.new(page, 'My device') + gitlab_sign_in(user) + unregistered_device.respond_to_webauthn_authentication - expect(page).to have_content('Authentication via WebAuthn device failed') - end + expect(page).to have_content('Authentication via WebAuthn device failed') end + end - describe 'when more than one device has been registered by the same user' do - it 'allows logging in with either device' do - first_device = add_webauthn_device(app_id, user) - second_device = add_webauthn_device(app_id, user) + describe 'when more than one device has been registered by the same user' do + it 'allows logging in with either device' do + first_device = add_webauthn_device(app_id, user) + second_device = add_webauthn_device(app_id, user) - # Authenticate as both devices - [first_device, second_device].each do |device| - gitlab_sign_in(user) - # register_webauthn_device(device) - device.respond_to_webauthn_authentication + # Authenticate as both devices + [first_device, second_device].each do |device| + gitlab_sign_in(user) + # register_webauthn_device(device) + device.respond_to_webauthn_authentication - expect(page).to have_css('.sign-out-link', visible: false) + expect(page).to have_css('.sign-out-link', visible: false) - gitlab_sign_out - end + gitlab_sign_out end end end |