diff options
Diffstat (limited to 'spec/features')
105 files changed, 1767 insertions, 854 deletions
diff --git a/spec/features/admin/admin_mode/workers_spec.rb b/spec/features/admin/admin_mode/workers_spec.rb index 0caa883fb5b..12f5e20e176 100644 --- a/spec/features/admin/admin_mode/workers_spec.rb +++ b/spec/features/admin/admin_mode/workers_spec.rb @@ -37,26 +37,56 @@ RSpec.describe 'Admin mode for workers', :request_store do gitlab_enable_admin_mode_sign_in(user) end - it 'can delete user', :js do - visit admin_user_path(user_to_delete) + context 'when user_destroy_with_limited_execution_time_worker is enabled' do + it 'can delete user', :js do + visit admin_user_path(user_to_delete) + + click_action_in_user_dropdown(user_to_delete.id, 'Delete user') + + page.within '.modal-dialog' do + find("input[name='username']").send_keys(user_to_delete.name) + click_button 'Delete user' + + wait_for_requests + end - click_action_in_user_dropdown(user_to_delete.id, 'Delete user') + expect(page).to have_content('The user is being deleted.') - page.within '.modal-dialog' do - find("input[name='username']").send_keys(user_to_delete.name) - click_button 'Delete user' + # Perform jobs while logged out so that admin mode is only enabled in job metadata + execute_jobs_signed_out(user) + + visit admin_user_path(user_to_delete) + + expect(find('h1.page-title')).to have_content('(Blocked)') + end + end - wait_for_requests + context 'when user_destroy_with_limited_execution_time_worker is disabled' do + before do + stub_feature_flags(user_destroy_with_limited_execution_time_worker: false) end - expect(page).to have_content('The user is being deleted.') + it 'can delete user', :js do + visit admin_user_path(user_to_delete) - # Perform jobs while logged out so that admin mode is only enabled in job metadata - execute_jobs_signed_out(user) + click_action_in_user_dropdown(user_to_delete.id, 'Delete user') - visit admin_user_path(user_to_delete) + page.within '.modal-dialog' do + find("input[name='username']").send_keys(user_to_delete.name) + click_button 'Delete user' + + wait_for_requests + end + + expect(page).to have_content('The user is being deleted.') - expect(page).to have_title('Not Found') + # Perform jobs while logged out so that admin mode is only enabled in job metadata + execute_jobs_signed_out(user) + + visit admin_user_path(user_to_delete) + + expect(page).to have_title('Not Found') + end end end end diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb index 24a10d3677d..33cf0e8c4f8 100644 --- a/spec/features/admin/admin_mode_spec.rb +++ b/spec/features/admin/admin_mode_spec.rb @@ -33,7 +33,7 @@ RSpec.describe 'Admin mode', :js do open_top_nav_projects within_top_nav do - click_link('Your projects') + click_link('View all projects') end expect(page).to have_current_path(dashboard_projects_path) @@ -99,7 +99,7 @@ RSpec.describe 'Admin mode', :js do open_top_nav_projects within_top_nav do - click_link('Your projects') + click_link('View all projects') end expect(page).to have_current_path(dashboard_projects_path) diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 44fd21e510a..fe9fd01d3d5 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -34,7 +34,7 @@ RSpec.describe "Admin Runners" do context "when there are runners" do context "with an instance runner" do - let!(:instance_runner) { create(:ci_runner, :instance) } + let_it_be(:instance_runner) { create(:ci_runner, :instance) } before do visit admin_runners_path @@ -50,7 +50,7 @@ RSpec.describe "Admin Runners" do it 'shows an instance badge' do within_runner_row(instance_runner.id) do - expect(page).to have_selector '.badge', text: 'shared' + expect(page).to have_selector '.badge', text: s_('Runners|Instance') end end end @@ -66,9 +66,9 @@ RSpec.describe "Admin Runners" do it 'has all necessary texts' do expect(page).to have_text "Register an instance runner" - expect(page).to have_text "Online runners 1" - expect(page).to have_text "Offline runners 2" - expect(page).to have_text "Stale runners 1" + expect(page).to have_text "#{s_('Runners|Online')} 1" + expect(page).to have_text "#{s_('Runners|Offline')} 2" + expect(page).to have_text "#{s_('Runners|Stale')} 1" end end @@ -81,15 +81,17 @@ RSpec.describe "Admin Runners" do visit admin_runners_path within_runner_row(runner.id) do - expect(find("[data-label='Jobs']")).to have_content '2' + expect(find("[data-testid='job-count']")).to have_content '2' end end describe 'search' do - before do + before_all do create(:ci_runner, :instance, description: 'runner-foo') create(:ci_runner, :instance, description: 'runner-bar') + end + before do visit admin_runners_path end @@ -130,10 +132,12 @@ RSpec.describe "Admin Runners" do end describe 'filter by paused' do - before do + before_all do create(:ci_runner, :instance, description: 'runner-active') create(:ci_runner, :instance, description: 'runner-paused', active: false) + end + before do visit admin_runners_path end @@ -145,7 +149,7 @@ RSpec.describe "Admin Runners" do end it 'shows paused runners' do - input_filtered_search_filter_is_only('Paused', 'Yes') + input_filtered_search_filter_is_only(s_('Runners|Paused'), 'Yes') expect(page).to have_link('All 1') @@ -154,7 +158,7 @@ RSpec.describe "Admin Runners" do end it 'shows active runners' do - input_filtered_search_filter_is_only('Paused', 'No') + input_filtered_search_filter_is_only(s_('Runners|Paused'), 'No') expect(page).to have_link('All 1') @@ -164,15 +168,17 @@ RSpec.describe "Admin Runners" do end describe 'filter by status' do - let!(:never_contacted) do + let_it_be(:never_contacted) do create(:ci_runner, :instance, description: 'runner-never-contacted', contacted_at: nil) end - before do + before_all do create(:ci_runner, :instance, description: 'runner-1', contacted_at: Time.zone.now) create(:ci_runner, :instance, description: 'runner-2', contacted_at: Time.zone.now) create(:ci_runner, :instance, description: 'runner-offline', contacted_at: 1.week.ago) + end + before do visit admin_runners_path end @@ -186,7 +192,7 @@ RSpec.describe "Admin Runners" do end it 'shows correct runner when status matches' do - input_filtered_search_filter_is_only('Status', 'Online') + input_filtered_search_filter_is_only('Status', s_('Runners|Online')) expect(page).to have_link('All 2') @@ -197,7 +203,7 @@ RSpec.describe "Admin Runners" do end it 'shows correct runner when status is selected and search term is entered' do - input_filtered_search_filter_is_only('Status', 'Online') + input_filtered_search_filter_is_only('Status', s_('Runners|Online')) input_filtered_search_keys('runner-1') expect(page).to have_link('All 1') @@ -220,7 +226,7 @@ RSpec.describe "Admin Runners" do expect(page).to have_content 'runner-never-contacted' within_runner_row(never_contacted.id) do - expect(page).to have_selector '.badge', text: 'never contacted' + expect(page).to have_selector '.badge', text: s_('Runners|Never contacted') end end @@ -238,7 +244,7 @@ RSpec.describe "Admin Runners" do end describe 'filter by type' do - before do + before_all do create(:ci_runner, :project, description: 'runner-project', projects: [project]) create(:ci_runner, :group, description: 'runner-group', groups: [group]) end @@ -308,7 +314,7 @@ RSpec.describe "Admin Runners" do visit admin_runners_path - input_filtered_search_filter_is_only('Paused', 'No') + input_filtered_search_filter_is_only(s_('Runners|Paused'), 'No') expect(page).to have_content 'runner-project' expect(page).to have_content 'runner-group' @@ -345,7 +351,7 @@ RSpec.describe "Admin Runners" do end describe 'filter by tag' do - before do + before_all do create(:ci_runner, :instance, description: 'runner-blue', tag_list: ['blue']) create(:ci_runner, :instance, description: 'runner-red', tag_list: ['red']) end @@ -464,7 +470,7 @@ RSpec.describe "Admin Runners" do end describe "Runner show page", :js do - let(:runner) do + let_it_be(:runner) do create( :ci_runner, description: 'runner-foo', @@ -520,20 +526,25 @@ RSpec.describe "Admin Runners" do end describe "Runner edit page" do - let(:runner) { create(:ci_runner, :project) } - let!(:project1) { create(:project) } - let!(:project2) { create(:project) } + let_it_be(:project1) { create(:project) } + let_it_be(:project2) { create(:project) } + let_it_be(:project_runner) { create(:ci_runner, :project) } before do - visit edit_admin_runner_path(runner) + visit edit_admin_runner_path(project_runner) wait_for_requests end + it_behaves_like 'submits edit runner form' do + let(:runner) { project_runner } + let(:runner_page_path) { admin_runner_path(project_runner) } + end + describe 'breadcrumbs' do it 'contains the current runner id and token' do page.within '[data-testid="breadcrumb-links"]' do - expect(page).to have_link("##{runner.id} (#{runner.short_sha})") + expect(page).to have_link("##{project_runner.id} (#{project_runner.short_sha})") expect(page.find('[data-testid="breadcrumb-current-link"]')).to have_content("Edit") end end @@ -541,7 +552,7 @@ RSpec.describe "Admin Runners" do describe 'runner header', :js do it 'contains the runner status, type and id' do - expect(page).to have_content("never contacted specific Runner ##{runner.id} created") + expect(page).to have_content("#{s_('Runners|Never contacted')} Project Runner ##{project_runner.id} created") end end @@ -556,7 +567,7 @@ RSpec.describe "Admin Runners" do end it 'redirects to runner page' do - expect(current_url).to match(admin_runner_path(runner)) + expect(current_url).to match(admin_runner_path(project_runner)) end end @@ -583,7 +594,7 @@ RSpec.describe "Admin Runners" do describe 'enable/create' do shared_examples 'assignable runner' do it 'enables a runner for a project' do - within '[data-testid="unassigned-projects"]' do + within find('[data-testid="unassigned-projects"] tr', text: project2.full_name) do click_on 'Enable' end @@ -594,21 +605,21 @@ RSpec.describe "Admin Runners" do end end - context 'with specific runner' do - let(:runner) { create(:ci_runner, :project, projects: [project1]) } + context 'with project runner' do + let(:project_runner) { create(:ci_runner, :project, projects: [project1]) } before do - visit edit_admin_runner_path(runner) + visit edit_admin_runner_path(project_runner) end it_behaves_like 'assignable runner' end context 'with locked runner' do - let(:runner) { create(:ci_runner, :project, projects: [project1], locked: true) } + let(:locked_runner) { create(:ci_runner, :project, projects: [project1], locked: true) } before do - visit edit_admin_runner_path(runner) + visit edit_admin_runner_path(locked_runner) end it_behaves_like 'assignable runner' diff --git a/spec/features/admin/admin_sees_background_migrations_spec.rb b/spec/features/admin/admin_sees_background_migrations_spec.rb index faf13374719..d72259d91b3 100644 --- a/spec/features/admin/admin_sees_background_migrations_spec.rb +++ b/spec/features/admin/admin_sees_background_migrations_spec.rb @@ -189,7 +189,7 @@ RSpec.describe "Admin > Admin sees background migrations" do visit admin_background_migrations_path within '#content-body' do - expect(page).to have_link('Learn more', href: help_page_path('development/database/batched_background_migrations')) + expect(page).to have_link('Learn more', href: help_page_path('user/admin_area/monitoring/background_migrations')) end end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 8843e13026b..a5df142d188 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -102,7 +102,7 @@ RSpec.describe 'Admin updates settings' do end it 'change Account and Limit Settings' do - page.within('.as-account-limit') do + page.within(find('[data-testid="account-limit"]')) do uncheck 'Gravatar enabled' click_button 'Save changes' end @@ -112,7 +112,7 @@ RSpec.describe 'Admin updates settings' do end it 'change Maximum export size' do - page.within('.as-account-limit') do + page.within(find('[data-testid="account-limit"]')) do fill_in 'Maximum export size (MB)', with: 25 click_button 'Save changes' end @@ -122,7 +122,7 @@ RSpec.describe 'Admin updates settings' do end it 'change Maximum import size' do - page.within('.as-account-limit') do + page.within(find('[data-testid="account-limit"]')) do fill_in 'Maximum import size (MB)', with: 15 click_button 'Save changes' end @@ -150,16 +150,20 @@ RSpec.describe 'Admin updates settings' do it 'does not expose the setting' do expect(page).to have_no_selector('#application_setting_deactivate_dormant_users') end + + it 'does not expose the setting' do + expect(page).to have_no_selector('#application_setting_deactivate_dormant_users_period') + end end context 'when not Gitlab.com' do let(:dot_com?) { false } - it 'change Dormant users' do - expect(page).to have_unchecked_field('Deactivate dormant users after 90 days of inactivity') + it 'changes Dormant users' do + expect(page).to have_unchecked_field('Deactivate dormant users after a period of inactivity') expect(current_settings.deactivate_dormant_users).to be_falsey - page.within('.as-account-limit') do + page.within(find('[data-testid="account-limit"]')) do check 'application_setting_deactivate_dormant_users' click_button 'Save changes' end @@ -169,7 +173,22 @@ RSpec.describe 'Admin updates settings' do page.refresh expect(current_settings.deactivate_dormant_users).to be_truthy - expect(page).to have_checked_field('Deactivate dormant users after 90 days of inactivity') + expect(page).to have_checked_field('Deactivate dormant users after a period of inactivity') + end + + it 'change Dormant users period' do + expect(page).to have_field _('Period of inactivity (days)') + + page.within(find('[data-testid="account-limit"]')) do + fill_in _('application_setting_deactivate_dormant_users_period'), with: '35' + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + + page.refresh + + expect(page).to have_field _('Period of inactivity (days)'), with: '35' end end end @@ -543,7 +562,7 @@ RSpec.describe 'Admin updates settings' do it 'change Prometheus settings' do page.within('.as-prometheus') do - check 'Enable health and performance metrics endpoint' + check 'Enable GitLab Prometheus metrics endpoint' click_button 'Save changes' end diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb index bc88b90a2dd..86acf5a05d4 100644 --- a/spec/features/admin/users/user_spec.rb +++ b/spec/features/admin/users/user_spec.rb @@ -205,7 +205,7 @@ RSpec.describe 'Admin::Users::User' do it 'logs in as the user when impersonate is clicked' do subject - find('[data-qa-selector="user_menu"]').click # rubocop:disable QA/SelectorUsage + find('[data-testid="user-menu"]').click expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eql(another_user.username) end @@ -241,7 +241,7 @@ RSpec.describe 'Admin::Users::User' do it 'logs out of impersonated user back to original user' do subject - find('[data-qa-selector="user_menu"]').click # rubocop:disable QA/SelectorUsage + find('[data-testid="user-menu"]').click expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eq(current_user.username) end diff --git a/spec/features/clusters/create_agent_spec.rb b/spec/features/clusters/create_agent_spec.rb index c44741b756b..b19e57c550c 100644 --- a/spec/features/clusters/create_agent_spec.rb +++ b/spec/features/clusters/create_agent_spec.rb @@ -12,10 +12,11 @@ RSpec.describe 'Cluster agent registration', :js do allow(Gitlab::Kas).to receive(:internal_url).and_return('kas.example.internal') allow_next_instance_of(Gitlab::Kas::Client) do |client| - allow(client).to receive(:list_agent_config_files).and_return([ - double(agent_name: 'example-agent-1', path: '.gitlab/agents/example-agent-1/config.yaml'), - double(agent_name: 'example-agent-2', path: '.gitlab/agents/example-agent-2/config.yaml') - ]) + allow(client).to receive(:list_agent_config_files).and_return( + [ + double(agent_name: 'example-agent-1', path: '.gitlab/agents/example-agent-1/config.yaml'), + double(agent_name: 'example-agent-2', path: '.gitlab/agents/example-agent-2/config.yaml') + ]) allow(client).to receive(:get_connected_agents).and_return([]) end diff --git a/spec/features/commits/user_view_commits_spec.rb b/spec/features/commits/user_view_commits_spec.rb index 5907534220d..f7fd3a6e209 100644 --- a/spec/features/commits/user_view_commits_spec.rb +++ b/spec/features/commits/user_view_commits_spec.rb @@ -3,14 +3,10 @@ require 'spec_helper' RSpec.describe 'Commit > User view commits' do - let_it_be(:project) { create(:project, :public, :repository) } - let_it_be(:user) { project.creator } + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group, :public) } - before do - visit project_commits_path(project) - end - - describe 'Commits List' do + shared_examples 'can view commits' do it 'displays the correct number of commits per day in the header' do expect(first('.js-commit-header').find('.commits-count').text).to eq('1 commit') end @@ -19,4 +15,51 @@ RSpec.describe 'Commit > User view commits' do expect(page).to have_selector('#commits-list > li:nth-child(2) > ul', count: 1) end end + + describe 'Commits List' do + context 'when project is public' do + let(:project) { create(:project, :public, :repository, group: group) } + + before do + visit project_commits_path(project) + end + + it_behaves_like 'can view commits' + end + + context 'when project is public with private repository' do + let(:project) { create(:project, :public, :repository, :repository_private, group: group) } + + context 'and user is an inherited member from the group' do + context 'and user is a guest' do + before do + group.add_guest(user) + sign_in(user) + visit project_commits_path(project) + end + + it_behaves_like 'can view commits' + end + end + end + + context 'when project is private' do + let(:project) { create(:project, :private, :repository, group: group) } + + context 'and user is an inherited member from the group' do + context 'and user is a guest' do + before do + group.add_guest(user) + sign_in(user) + visit project_commits_path(project) + end + + it 'renders not found' do + expect(page).to have_title('Not Found') + expect(page).to have_content('Page Not Found') + end + end + end + end + end end diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 7714783172f..488a4f84297 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -36,10 +36,6 @@ RSpec.describe 'Value Stream Analytics', :js do wait_for_all_requests end - before do - stub_feature_flags(use_vsa_aggregated_tables: false) - end - context 'as an allowed user' do context 'when project is new' do before do diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb index bf9f6895d24..48a6976f263 100644 --- a/spec/features/dashboard/datetime_on_tooltips_spec.rb +++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb @@ -15,7 +15,7 @@ RSpec.describe 'Tooltips on .timeago dates', :js do context 'on the activity tab' do before do Event.create!( project: project, author_id: user.id, action: :joined, - updated_at: created_date, created_at: created_date) + updated_at: created_date, created_at: created_date) sign_in user visit user_activity_path(user) diff --git a/spec/features/dashboard/milestones_spec.rb b/spec/features/dashboard/milestones_spec.rb index 3f89955b12b..08cb95979ac 100644 --- a/spec/features/dashboard/milestones_spec.rb +++ b/spec/features/dashboard/milestones_spec.rb @@ -41,7 +41,12 @@ RSpec.describe 'Dashboard > Milestones' do first('.select2-result-label').click end - find('.js-new-project-item-link').click + a_el = find('.js-new-project-item-link') + + expect(a_el).to have_content('New Milestone in ') + expect(a_el).to have_no_content('New New Milestone in ') + + a_el.click expect(page).to have_current_path(new_group_milestone_path(group), ignore_query: true) end diff --git a/spec/features/dashboard/todos/todos_sorting_spec.rb b/spec/features/dashboard/todos/todos_sorting_spec.rb index d593031590e..a0fa53b761b 100644 --- a/spec/features/dashboard/todos/todos_sorting_spec.rb +++ b/spec/features/dashboard/todos/todos_sorting_spec.rb @@ -28,7 +28,7 @@ RSpec.describe 'Dashboard > User sorts todos' do create(:todo, user: user, project: project, target: issue_3, created_at: 3.hours.ago, updated_at: 2.minutes.ago) create(:todo, user: user, project: project, target: issue_1, created_at: 2.hours.ago, updated_at: 2.hours.ago) create(:todo, user: user, project: project, target: merge_request_1, created_at: 1.hour.ago, - updated_at: 1.hour.ago) + updated_at: 1.hour.ago) merge_request_1.labels << label_1 issue_3.labels << label_1 diff --git a/spec/features/discussion_comments/issue_spec.rb b/spec/features/discussion_comments/issue_spec.rb index ebb57b37918..0bb43343ecd 100644 --- a/spec/features/discussion_comments/issue_spec.rb +++ b/spec/features/discussion_comments/issue_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Thread Comments Issue', :js do let(:issue) { create(:issue, project: project) } before do + stub_feature_flags(remove_user_attributes_projects: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/discussion_comments/merge_request_spec.rb b/spec/features/discussion_comments/merge_request_spec.rb index a90ff3721d3..4fa82de3b4b 100644 --- a/spec/features/discussion_comments/merge_request_spec.rb +++ b/spec/features/discussion_comments/merge_request_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'Thread Comments Merge Request', :js do let(:merge_request) { create(:merge_request, source_project: project) } before do + stub_feature_flags(remove_user_attributes_projects: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/groups/group_runners_spec.rb b/spec/features/groups/group_runners_spec.rb index b98c94b030d..ada03726c97 100644 --- a/spec/features/groups/group_runners_spec.rb +++ b/spec/features/groups/group_runners_spec.rb @@ -61,7 +61,7 @@ RSpec.describe "Group Runners" do it 'shows a group badge' do within_runner_row(group_runner.id) do - expect(page).to have_selector '.badge', text: 'group' + expect(page).to have_selector '.badge', text: s_('Runners|Group') end end @@ -101,9 +101,9 @@ RSpec.describe "Group Runners" do let(:runner) { project_runner } end - it 'shows a project (specific) badge' do + it 'shows a project badge' do within_runner_row(project_runner.id) do - expect(page).to have_selector '.badge', text: 'specific' + expect(page).to have_selector '.badge', text: s_('Runners|Project') end end @@ -137,52 +137,38 @@ RSpec.describe "Group Runners" do focus_filtered_search page.within(search_bar_selector) do - expect(page).to have_link('Paused') + expect(page).to have_link(s_('Runners|Paused')) expect(page).to have_content('Status') end end end end - describe "Group runner edit page", :js do - let!(:runner) do - create(:ci_runner, :group, groups: [group], description: 'runner-foo', contacted_at: Time.zone.now) + describe "Group runner show page", :js do + let!(:group_runner) do + create(:ci_runner, :group, groups: [group], description: 'runner-foo') end it 'user views runner details' do - visit group_runner_path(group, runner) + visit group_runner_path(group, group_runner) expect(page).to have_content "#{s_('Runners|Description')} runner-foo" end + end - it 'user edits the runner to be protected' do - visit edit_group_runner_path(group, runner) - - expect(page.find_field('runner[access_level]')).not_to be_checked - - check 'runner_access_level' - click_button _('Save changes') - - expect(page).to have_content "#{s_('Runners|Configuration')} #{s_('Runners|Protected')}" + describe "Group runner edit page", :js do + let!(:group_runner) do + create(:ci_runner, :group, groups: [group]) end - context 'when a runner has a tag' do - before do - runner.update!(tag_list: ['tag1']) - end - - it 'user edits runner not to run untagged jobs' do - visit edit_group_runner_path(group, runner) - - page.find_field('runner[tag_list]').set('tag1, tag2') - - uncheck 'runner_run_untagged' - click_button _('Save changes') + before do + visit edit_group_runner_path(group, group_runner) + wait_for_requests + end - # Tags can be in any order - expect(page).to have_content /#{s_('Runners|Tags')}.*tag1/ - expect(page).to have_content /#{s_('Runners|Tags')}.*tag2/ - end + it_behaves_like 'submits edit runner form' do + let(:runner) { group_runner } + let(:runner_page_path) { group_runner_path(group, group_runner) } end end end diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb index b4faa3ce0dd..b3fb563a202 100644 --- a/spec/features/groups/navbar_spec.rb +++ b/spec/features/groups/navbar_spec.rb @@ -14,10 +14,12 @@ RSpec.describe 'Group navbar' do before do insert_package_nav(_('Kubernetes')) + insert_after_nav_item(_('Analytics'), new_nav_item: settings_for_maintainer_nav_item) if Gitlab.ee? stub_config(dependency_proxy: { enabled: false }) stub_config(registry: { enabled: false }) stub_feature_flags(harbor_registry_integration: false) + stub_feature_flags(observability_group_tab: false) stub_group_wikis(false) group.add_maintainer(user) sign_in(user) @@ -48,7 +50,7 @@ RSpec.describe 'Group navbar' do if Gitlab.ee? insert_customer_relations_nav(_('Analytics')) else - insert_customer_relations_nav(_('Packages & Registries')) + insert_customer_relations_nav(_('Packages and registries')) end visit group_path(group) @@ -80,7 +82,11 @@ RSpec.describe 'Group navbar' do end context 'when harbor registry is available' do + let(:harbor_integration) { create(:harbor_integration, group: group, project: nil) } + before do + group.update!(harbor_integration: harbor_integration) + stub_feature_flags(harbor_registry_integration: true) insert_harbor_registry_nav(_('Package Registry')) @@ -90,4 +96,16 @@ RSpec.describe 'Group navbar' do it_behaves_like 'verified navigation bar' end + + context 'when observability tab is enabled' do + before do + stub_feature_flags(observability_group_tab: true) + + insert_observability_nav + + visit group_path(group) + end + + it_behaves_like 'verified navigation bar' + end end diff --git a/spec/features/groups/settings/packages_and_registries_spec.rb b/spec/features/groups/settings/packages_and_registries_spec.rb index 98dc534f54e..7f3f5775559 100644 --- a/spec/features/groups/settings/packages_and_registries_spec.rb +++ b/spec/features/groups/settings/packages_and_registries_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Group Packages & Registries settings' do +RSpec.describe 'Group Package and registry settings' do include WaitForRequests let(:user) { create(:user) } @@ -25,7 +25,7 @@ RSpec.describe 'Group Packages & Registries settings' do settings_menu = find_settings_menu - expect(settings_menu).not_to have_content 'Packages & Registries' + expect(settings_menu).not_to have_content 'Packages and registries' end it 'renders 404 when navigating to page' do @@ -40,57 +40,58 @@ RSpec.describe 'Group Packages & Registries settings' do visit group_path(group) settings_menu = find_settings_menu - expect(settings_menu).to have_content 'Packages & Registries' + expect(settings_menu).to have_content 'Packages and registries' end it 'has a page title set' do visit_settings_page - expect(page).to have_title _('Packages & Registries') + expect(page).to have_title _('Package and registry settings') end it 'sidebar menu is open' do visit_settings_page sidebar = find('.nav-sidebar') - expect(sidebar).to have_link _('Packages & Registries') + expect(sidebar).to have_link _('Packages and registries') end it 'has a Duplicate packages section', :js do visit_settings_page expect(page).to have_content('Duplicate packages') + expect(page).to have_content('Allow duplicates') + expect(page).to have_content('Exceptions') end it 'automatically saves changes to the server', :js do visit_settings_page + wait_for_requests within '[data-testid="maven-settings"]' do - expect(page).to have_content('Reject packages with the same name and version') - expect(page).not_to have_content('Exceptions') + expect(page).to have_field _('Exceptions'), disabled: true - find('.gl-toggle').click + click_button class: 'gl-toggle' - expect(page).to have_content('Exceptions') + expect(page).to have_field _('Exceptions'), disabled: false visit_settings_page - expect(page).to have_content('Exceptions') + expect(page).to have_field _('Exceptions'), disabled: false end end it 'shows an error on wrong regex', :js do visit_settings_page + wait_for_requests within '[data-testid="maven-settings"]' do - expect(page).to have_content('Reject packages with the same name and version') + click_button class: 'gl-toggle' - find('.gl-toggle').click - - fill_in 'Exceptions', with: ')' + fill_in _('Exceptions'), with: ')' # simulate blur event - find('#maven-duplicated-settings-regex-input').native.send_keys(:tab) + send_keys(:tab) end expect(page).to have_content('is an invalid regexp') @@ -99,13 +100,16 @@ RSpec.describe 'Group Packages & Registries settings' do context 'in a sub group' do it 'works correctly', :js do visit_sub_group_settings_page + wait_for_requests within '[data-testid="maven-settings"]' do - expect(page).to have_content('Reject packages with the same name and version') + expect(page).to have_content('Allow duplicates') + + expect(page).to have_field _('Exceptions'), disabled: true - find('.gl-toggle').click + click_button class: 'gl-toggle' - expect(page).to have_content('Exceptions') + expect(page).to have_field _('Exceptions'), disabled: false end end end diff --git a/spec/features/groups/settings/user_searches_in_settings_spec.rb b/spec/features/groups/settings/user_searches_in_settings_spec.rb index 998c3d2ca3f..fe0dd7cec9a 100644 --- a/spec/features/groups/settings/user_searches_in_settings_spec.rb +++ b/spec/features/groups/settings/user_searches_in_settings_spec.rb @@ -43,7 +43,7 @@ RSpec.describe 'User searches group settings', :js do it_behaves_like 'can search settings', 'Variables', 'Auto DevOps' end - context 'in Packages & Registries page' do + context 'in Packages and registries page' do before do visit group_settings_packages_and_registries_path(group) end diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index c93ed01b873..4e02f6f7ca2 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -517,75 +517,4 @@ RSpec.describe 'Group' do fill_in 'confirm_name_input', with: confirm_with click_button 'Confirm' end - - describe 'storage_enforcement_banner', :js do - let_it_be(:group) { create(:group) } - let_it_be_with_refind(:user) { create(:user) } - - before do - group.add_owner(user) - sign_in(user) - end - - context 'with storage_enforcement_date set' do - let_it_be(:storage_enforcement_date) { Date.today + 30 } - - before do - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date) - end - end - - it 'displays the banner in the group page' do - visit group_path(group) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - - it 'does not display the banner in a paid group page' do - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:paid?).and_return(true) - end - visit group_path(group) - expect_page_not_to_have_storage_enforcement_banner - end - - it 'does not display the banner if user has previously closed unless threshold has changed' do - visit group_path(group) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - find('.js-storage-enforcement-banner [data-testid="close-icon"]').click - wait_for_requests - page.refresh - expect_page_not_to_have_storage_enforcement_banner - - storage_enforcement_date = Date.today + 13 - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date) - end - page.refresh - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - end - - context 'with storage_enforcement_date not set' do - before do - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:storage_enforcement_date).and_return(nil) - end - end - - it 'does not display the banner in the group page' do - stub_feature_flags(namespace_storage_limit_bypass_date_check: false) - visit group_path(group) - expect_page_not_to_have_storage_enforcement_banner - end - end - end - - def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply" - end - - def expect_page_not_to_have_storage_enforcement_banner - expect(page).not_to have_text "namespace storage limits will apply" - end end diff --git a/spec/features/help_dropdown_spec.rb b/spec/features/help_dropdown_spec.rb index db98f58240d..e64c19d4708 100644 --- a/spec/features/help_dropdown_spec.rb +++ b/spec/features/help_dropdown_spec.rb @@ -51,7 +51,8 @@ RSpec.describe "Help Dropdown", :js do visit root_path end - it 'renders correct version badge variant' do + it 'renders correct version badge variant', + quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/369850' do page.within '.header-help' do find('.header-help-dropdown-toggle').click diff --git a/spec/features/ide/user_commits_changes_spec.rb b/spec/features/ide/user_commits_changes_spec.rb index e1e586a4f18..04b215710b3 100644 --- a/spec/features/ide/user_commits_changes_spec.rb +++ b/spec/features/ide/user_commits_changes_spec.rb @@ -9,6 +9,8 @@ RSpec.describe 'IDE user commits changes', :js do let(:user) { project.first_owner } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(user) ide_visit(project) diff --git a/spec/features/ide/user_opens_merge_request_spec.rb b/spec/features/ide/user_opens_merge_request_spec.rb index 8f4668d49ee..8a95d7c5544 100644 --- a/spec/features/ide/user_opens_merge_request_spec.rb +++ b/spec/features/ide/user_opens_merge_request_spec.rb @@ -8,6 +8,8 @@ RSpec.describe 'IDE merge request', :js do let(:user) { project.first_owner } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(user) visit(merge_request_path(merge_request)) diff --git a/spec/features/ide_spec.rb b/spec/features/ide_spec.rb index 2505ab0afee..c7c740c2293 100644 --- a/spec/features/ide_spec.rb +++ b/spec/features/ide_spec.rb @@ -4,12 +4,14 @@ require 'spec_helper' RSpec.describe 'IDE', :js do describe 'sub-groups' do + let(:ide_iframe_selector) { '#ide iframe' } let(:user) { create(:user) } let(:group) { create(:group) } let(:subgroup) { create(:group, parent: group) } let(:subgroup_project) { create(:project, :repository, namespace: subgroup) } before do + stub_feature_flags(vscode_web_ide: vscode_ff) subgroup_project.add_maintainer(user) sign_in(user) @@ -20,8 +22,28 @@ RSpec.describe 'IDE', :js do wait_for_requests end - it 'loads project in web IDE' do - expect(page).to have_selector('.context-header', text: subgroup_project.name) + context 'with vscode feature flag on' do + let(:vscode_ff) { true } + + it 'loads project in Web IDE' do + iframe = find(ide_iframe_selector) + + page.within_frame(iframe) do + expect(page).to have_selector('.title', text: subgroup_project.name.upcase) + end + end + end + + context 'with vscode feature flag off' do + let(:vscode_ff) { false } + + it 'loads project in legacy Web IDE' do + expect(page).to have_selector('.context-header', text: subgroup_project.name) + end + + it 'does not load new Web IDE' do + expect(page).not_to have_selector(ide_iframe_selector) + end end end end diff --git a/spec/features/incidents/incident_timeline_events_spec.rb b/spec/features/incidents/incident_timeline_events_spec.rb index e39f348013c..6db9f87d6f2 100644 --- a/spec/features/incidents/incident_timeline_events_spec.rb +++ b/spec/features/incidents/incident_timeline_events_spec.rb @@ -17,20 +17,20 @@ RSpec.describe 'Incident timeline events', :js do visit project_issues_incident_path(project, incident) wait_for_requests - click_link 'Timeline' + click_link s_('Incident|Timeline') end context 'when add event is clicked' do it 'submits event data when save is clicked' do - click_button 'Add new timeline event' + click_button s_('Incident|Add new timeline event') expect(page).to have_selector('.common-note-form') - fill_in 'Description', with: 'Event note goes here' + fill_in _('Description'), with: 'Event note goes here' fill_in 'timeline-input-hours', with: '07' fill_in 'timeline-input-minutes', with: '25' - click_button 'Save' + click_button _('Save') expect(page).to have_selector('.incident-timeline-events') @@ -41,30 +41,62 @@ RSpec.describe 'Incident timeline events', :js do end end - context 'when delete event is clicked' do + context 'when edit is clicked' do before do click_button 'Add new timeline event' - fill_in 'Description', with: 'Event note to delete' - click_button 'Save' + fill_in 'Description', with: 'Event note to edit' + click_button _('Save') + end + + it 'shows the confirmation modal and edits the event' do + click_button _('More actions') + + page.within '.gl-new-dropdown-contents' do + expect(page).to have_content(_('Edit')) + page.find('.gl-new-dropdown-item-text-primary', text: _('Edit')).click + end + + expect(page).to have_selector('.common-note-form') + + fill_in _('Description'), with: 'Event note goes here' + fill_in 'timeline-input-hours', with: '07' + fill_in 'timeline-input-minutes', with: '25' + + click_button _('Save') + + wait_for_requests + + page.within '.timeline-event-note' do + expect(page).to have_content('Event note goes here') + expect(page).to have_content('07:25') + end + end + end + + context 'when delete is clicked' do + before do + click_button s_('Incident|Add new timeline event') + fill_in _('Description'), with: 'Event note to delete' + click_button _('Save') end it 'shows the confirmation modal and deletes the event' do - click_button 'More actions' + click_button _('More actions') - page.within '.gl-new-dropdown-item-text-wrapper' do - expect(page).to have_content('Delete') + page.within '.gl-new-dropdown-contents' do + expect(page).to have_content(_('Delete')) page.find('.gl-new-dropdown-item-text-primary', text: 'Delete').click end page.within '.modal' do - expect(page).to have_content('Delete event') + expect(page).to have_content(s_('Incident|Delete event')) end - click_button 'Delete event' + click_button s_('Incident|Delete event') wait_for_requests - expect(page).to have_content('No timeline items have been added yet.') + expect(page).to have_content(s_('Incident|No timeline items have been added yet.')) end end end diff --git a/spec/features/incidents/user_uses_quick_actions_spec.rb b/spec/features/incidents/user_uses_quick_actions_spec.rb new file mode 100644 index 00000000000..fce9eadd42f --- /dev/null +++ b/spec/features/incidents/user_uses_quick_actions_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Incidents > User uses quick actions', :js do + include Spec::Support::Helpers::Features::NotesHelpers + + describe 'incident-only commands' do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:issue, reload: true) { create(:incident, project: project) } + + before do + project.add_developer(user) + sign_in(user) + visit project_issue_path(project, issue) + wait_for_all_requests + end + + after do + wait_for_requests + end + + it_behaves_like 'timeline quick action' + end +end diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb index 1baa97096d9..34990a53b51 100644 --- a/spec/features/invites_spec.rb +++ b/spec/features/invites_spec.rb @@ -10,6 +10,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do let(:group_invite) { group.group_members.invite.last } before do + stub_feature_flags(arkose_labs_signup_challenge: false) stub_application_setting(require_admin_approval_after_user_signup: false) project.add_maintainer(owner) group.add_owner(owner) @@ -245,6 +246,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do before do stub_feature_flags(soft_email_confirmation: false) allow(User).to receive(:allow_unconfirmed_access_for).and_return 0 + stub_feature_flags(identity_verification: false) end it 'signs up and redirects to the group activity page' do diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb index ae9c8d31c02..9d46b3a274e 100644 --- a/spec/features/issuables/markdown_references/jira_spec.rb +++ b/spec/features/issuables/markdown_references/jira_spec.rb @@ -15,6 +15,8 @@ RSpec.describe "Jira", :js do before do remotelink = double(:remotelink, all: [], build: double(save!: true)) + stub_feature_flags(remove_user_attributes_projects: false) + stub_request(:get, "https://jira.example.com/rest/api/2/issue/JIRA-5") stub_request(:post, "https://jira.example.com/rest/api/2/issue/JIRA-5/comment") allow_next_instance_of(JIRA::Resource::Issue) do |instance| diff --git a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb index 1e8b9b6b60b..a385e8a5fd0 100644 --- a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb @@ -18,6 +18,10 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j end end + before do + stub_feature_flags(moved_mr_sidebar: false) + end + describe 'as a user with access to the project' do before do project.add_maintainer(user) @@ -26,14 +30,16 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j end it 'shows a button to resolve all threads by creating a new issue' do + find('.discussions-counter .dropdown-toggle').click + within('.discussions-counter') do - expect(page).to have_selector resolve_all_discussions_link_selector( title: "Create issue to resolve all threads" ) + expect(page).to have_link(_("Create issue to resolve all threads"), href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid)) end end context 'resolving the thread' do before do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end it 'hides the link for creating a new issue' do @@ -44,6 +50,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j context 'creating an issue for threads' do before do + find('.discussions-counter .dropdown-toggle').click find(resolve_all_discussions_link_selector).click end diff --git a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb index 0de15d3d304..5ff61a52b21 100644 --- a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb @@ -35,7 +35,7 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue', context 'resolving the thread' do before do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end it 'hides the link for creating a new issue' do diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb index 2af54e51bb7..a253e6f4c86 100644 --- a/spec/features/issues/issue_detail_spec.rb +++ b/spec/features/issues/issue_detail_spec.rb @@ -68,8 +68,12 @@ RSpec.describe 'Issue Detail', :js do end context 'when edited by a user who is later deleted' do + let(:user_to_be_deleted) { create(:user) } + before do - sign_in(user) + project.add_developer(user_to_be_deleted) + + sign_in(user_to_be_deleted) visit project_issue_path(project, issue) wait_for_requests @@ -78,8 +82,9 @@ RSpec.describe 'Issue Detail', :js do click_button 'Save changes' wait_for_requests - Users::DestroyService.new(user).execute(user) + Users::DestroyService.new(user_to_be_deleted).execute(user_to_be_deleted) + sign_in(user) visit project_issue_path(project, issue) end diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 8819f085a5f..6fa8a52a9c5 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -302,7 +302,9 @@ RSpec.describe 'Issue Sidebar' do context 'sidebar', :js do it 'finds issue copy forwarding email' do - expect(find('[data-qa-selector="copy-forward-email"]').text).to eq "Issue email: #{issue.creatable_note_email_address(user)}" # rubocop:disable QA/SelectorUsage + expect( + find('[data-testid="copy-forward-email"]').text + ).to eq "Issue email: #{issue.creatable_note_email_address(user)}" end end @@ -338,7 +340,7 @@ RSpec.describe 'Issue Sidebar' do end it 'does not find issue email' do - expect(page).not_to have_selector('[data-qa-selector="copy-forward-email"]') # rubocop:disable QA/SelectorUsage + expect(page).not_to have_selector('[data-testid="copy-forward-email"]') end end end diff --git a/spec/features/issues/resource_label_events_spec.rb b/spec/features/issues/resource_label_events_spec.rb index e08410efc0b..e4da2f67516 100644 --- a/spec/features/issues/resource_label_events_spec.rb +++ b/spec/features/issues/resource_label_events_spec.rb @@ -14,6 +14,7 @@ RSpec.describe 'List issue resource label events', :js do let!(:event) { create(:resource_label_event, user: user, issue: issue, label: label) } before do + stub_feature_flags(remove_user_attributes_projects: false) visit project_issue_path(project, issue) wait_for_requests end diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb index e29911e3263..b96490bd7e7 100644 --- a/spec/features/issues/user_creates_issue_spec.rb +++ b/spec/features/issues/user_creates_issue_spec.rb @@ -269,7 +269,7 @@ RSpec.describe "User creates issue" do end it 'hides the weight input' do - expect(page).not_to have_selector('.qa-issuable-weight-input') # rubocop:disable QA/SelectorUsage + expect(page).not_to have_selector('[data-testid="issuable-weight-input"]') end it 'shows the incident help text' do diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb index c86a2c32e2d..8ed56108f00 100644 --- a/spec/features/issues/user_interacts_with_awards_spec.rb +++ b/spec/features/issues/user_interacts_with_awards_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe 'User interacts with awards' do + include MobileHelpers + let(:user) { create(:user) } describe 'User interacts with awards in an issue', :js do @@ -130,6 +132,7 @@ RSpec.describe 'User interacts with awards' do end it 'allows adding a new emoji' do + resize_window(1200, 800) page.within('.note-actions') do find('.note-emoji-button').click end @@ -140,6 +143,7 @@ RSpec.describe 'User interacts with awards' do expect(page).to have_emoji('8ball') end expect(note.reload.award_emoji.size).to eq(2) + restore_window_size end context 'when the project is archived' do diff --git a/spec/features/issues/user_sees_empty_state_spec.rb b/spec/features/issues/user_sees_empty_state_spec.rb index b43ba01606a..0e2a7cb4358 100644 --- a/spec/features/issues/user_sees_empty_state_spec.rb +++ b/spec/features/issues/user_sees_empty_state_spec.rb @@ -40,8 +40,8 @@ RSpec.describe 'Issues > User sees empty state', :js do it 'user sees empty state' do visit project_issues_path(project) - expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project') - expect(page).to have_content('Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.') + expect(page).to have_content('Use issues to collaborate on ideas, solve problems, and plan work') + expect(page).to have_content('Learn more about issues.') expect(page).to have_content('New issue') end diff --git a/spec/features/issues/user_sorts_issue_comments_spec.rb b/spec/features/issues/user_sorts_issue_comments_spec.rb index 555f8827374..4b38ce329b8 100644 --- a/spec/features/issues/user_sorts_issue_comments_spec.rb +++ b/spec/features/issues/user_sorts_issue_comments_spec.rb @@ -16,7 +16,9 @@ RSpec.describe 'Comment sort direction' do it 'saves sort order' do # open dropdown, and select 'Newest first' page.within('.issuable-details') do + find('#discussion-preferences-dropdown').click click_button('Oldest first') + find('#discussion-preferences-dropdown').click click_button('Newest first') end diff --git a/spec/features/jira_oauth_provider_authorize_spec.rb b/spec/features/jira_oauth_provider_authorize_spec.rb index a216d2d44b2..eb26440aff9 100644 --- a/spec/features/jira_oauth_provider_authorize_spec.rb +++ b/spec/features/jira_oauth_provider_authorize_spec.rb @@ -10,10 +10,10 @@ RSpec.describe 'JIRA OAuth Provider' do sign_in(user) visit oauth_jira_dvcs_authorize_path(client_id: application.uid, - redirect_uri: oauth_jira_dvcs_callback_url, - response_type: 'code', - state: 'my_state', - scope: 'read_user') + redirect_uri: oauth_jira_dvcs_callback_url, + response_type: 'code', + state: 'my_state', + scope: 'read_user') end it_behaves_like 'Secure OAuth Authorizations' diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb index 9eff02a8c1b..08f9b8eda13 100644 --- a/spec/features/markdown/markdown_spec.rb +++ b/spec/features/markdown/markdown_spec.rb @@ -263,6 +263,10 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do expect(doc).to parse_task_lists end + aggregate_failures 'MathFilter' do + expect(doc).to parse_math + end + aggregate_failures 'InlineDiffFilter' do expect(doc).to parse_inline_diffs end diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb index fafaea8ac68..bccdc3c4c62 100644 --- a/spec/features/merge_request/batch_comments_spec.rb +++ b/spec/features/merge_request/batch_comments_spec.rb @@ -13,6 +13,8 @@ RSpec.describe 'Merge request > Batch comments', :js do end before do + stub_feature_flags(moved_mr_sidebar: false) + project.add_maintainer(user) sign_in(user) diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb index f21929e5275..fd33731cb7b 100644 --- a/spec/features/merge_request/user_comments_on_diff_spec.rb +++ b/spec/features/merge_request/user_comments_on_diff_spec.rb @@ -14,6 +14,7 @@ RSpec.describe 'User comments on a diff', :js do let(:user) { create(:user) } before do + stub_feature_flags(remove_user_attributes_projects: false) project.add_maintainer(user) sign_in(user) @@ -256,9 +257,7 @@ RSpec.describe 'User comments on a diff', :js do click_button('Delete comment', match: :first) end - page.within('.merge-request-tabs') do - find('.notes-tab').click - end + find('.notes-tab', visible: true).click wait_for_requests diff --git a/spec/features/merge_request/user_comments_on_merge_request_spec.rb b/spec/features/merge_request/user_comments_on_merge_request_spec.rb index dbcfc2b968f..ec1e2fea851 100644 --- a/spec/features/merge_request/user_comments_on_merge_request_spec.rb +++ b/spec/features/merge_request/user_comments_on_merge_request_spec.rb @@ -10,6 +10,7 @@ RSpec.describe 'User comments on a merge request', :js do let(:user) { create(:user) } before do + stub_feature_flags(remove_user_attributes_projects: false) project.add_maintainer(user) sign_in(user) diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb index c8b22bb3125..0ae4ef18649 100644 --- a/spec/features/merge_request/user_creates_merge_request_spec.rb +++ b/spec/features/merge_request/user_creates_merge_request_spec.rb @@ -1,111 +1,164 @@ # frozen_string_literal: true -require "spec_helper" +require 'spec_helper' -RSpec.describe "User creates a merge request", :js do +RSpec.describe 'User creates a merge request', :js do include ProjectForksHelper - let_it_be(:project) { create(:project, :repository) } - let_it_be(:user) { create(:user) } - - let(:title) { "Some feature" } - - before do - project.add_maintainer(user) - sign_in(user) - end - - it "creates a merge request" do - visit(project_new_merge_request_path(project)) + shared_examples 'creates a merge request' do + specify do + visit(project_new_merge_request_path(project)) - find(".js-source-branch").click - click_link("fix") + compare_source_and_target('fix', 'feature') - find(".js-target-branch").click - click_link("feature") + page.within('.merge-request-form') do + expect(page.find('#merge_request_description')['placeholder']).to eq 'Describe the goal of the changes and what reviewers should be aware of.' + end - click_button("Compare branches") + fill_in('Title', with: title) + click_button('Create merge request') - page.within('.merge-request-form') do - expect(page.find('#merge_request_description')['placeholder']).to eq 'Describe the goal of the changes and what reviewers should be aware of.' + page.within('.merge-request') do + expect(page).to have_content(title) + end end + end - fill_in("Title", with: title) - click_button("Create merge request") + shared_examples 'renders not found' do + specify do + visit project_new_merge_request_path(project) - page.within(".merge-request") do - expect(page).to have_content(title) + expect(page).to have_title('Not Found') + expect(page).to have_content('Page Not Found') end end - context "XSS branch name exists" do + context 'when user is a direct project member' do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } + + let(:title) { 'Some feature' } + before do - project.repository.create_branch("<img/src='x'/onerror=alert('oops')>", "master") + project.add_maintainer(user) + sign_in(user) end - it "doesn't execute the dodgy branch name" do - visit(project_new_merge_request_path(project)) + it_behaves_like 'creates a merge request' - find(".js-source-branch").click - click_link("<img/src='x'/onerror=alert('oops')>") + context 'with XSS branch name' do + before do + project.repository.create_branch("<img/src='x'/onerror=alert('oops')>", 'master') + end - find(".js-target-branch").click - click_link("feature") + it 'does not execute the suspicious branch name' do + visit(project_new_merge_request_path(project)) - click_button("Compare branches") + compare_source_and_target("<img/src='x'/onerror=alert('oops')>", 'feature') - expect { page.driver.browser.switch_to.alert }.to raise_error(Selenium::WebDriver::Error::NoSuchAlertError) + expect { page.driver.browser.switch_to.alert }.to raise_error(Selenium::WebDriver::Error::NoSuchAlertError) + end end - end - context "to a forked project" do - let(:forked_project) { fork_project(project, user, namespace: user.namespace, repository: true) } + context 'to a forked project' do + let(:forked_project) { fork_project(project, user, namespace: user.namespace, repository: true) } + + it 'creates a merge request', :sidekiq_might_not_need_inline do + visit(project_new_merge_request_path(forked_project)) + + expect(page).to have_content('Source branch').and have_content('Target branch') + expect(find('#merge_request_target_project_id', visible: false).value).to eq(project.id.to_s) - it "creates a merge request", :sidekiq_might_not_need_inline do - visit(project_new_merge_request_path(forked_project)) + click_button('Compare branches and continue') - expect(page).to have_content("Source branch").and have_content("Target branch") - expect(find("#merge_request_target_project_id", visible: false).value).to eq(project.id.to_s) + expect(page).to have_content('You must select source and target branch') - click_button("Compare branches and continue") + first('.js-source-project').click + first('.dropdown-source-project a', text: forked_project.full_path) - expect(page).to have_content("You must select source and target branch") + first('.js-target-project').click + first('.dropdown-target-project a', text: project.full_path) - first(".js-source-project").click - first(".dropdown-source-project a", text: forked_project.full_path) + first('.js-source-branch').click - first(".js-target-project").click - first(".dropdown-target-project a", text: project.full_path) + wait_for_requests - first(".js-source-branch").click + source_branch = 'fix' - wait_for_requests + first('.js-source-branch-dropdown .dropdown-content a', text: source_branch).click - source_branch = "fix" + click_button('Compare branches and continue') - first(".js-source-branch-dropdown .dropdown-content a", text: source_branch).click + expect(page).to have_text _('New merge request') - click_button("Compare branches and continue") + page.within('form#new_merge_request') do + fill_in('Title', with: title) + end - expect(page).to have_text _('New merge request') + expect(find('.js-assignee-search')['data-project-id']).to eq(project.id.to_s) + find('.js-assignee-search').click - page.within("form#new_merge_request") do - fill_in("Title", with: title) + page.within('.dropdown-menu-user') do + expect(page).to have_content('Unassigned') + .and have_content(user.name) + .and have_content(project.users.first.name) + end + find('.js-assignee-search').click + + click_button('Create merge request') + + expect(page).to have_content(title).and have_content("requested to merge #{forked_project.full_path}:#{source_branch} into master") + end + end + end + + context 'when user is an inherited member from the group' do + let_it_be(:group) { create(:group, :public) } + + let(:user) { create(:user) } + + context 'when project is public and merge requests are private' do + let_it_be(:project) do + create(:project, + :public, + :repository, + group: group, + merge_requests_access_level: ProjectFeature::DISABLED) end - expect(find(".js-assignee-search")["data-project-id"]).to eq(project.id.to_s) - find('.js-assignee-search').click + context 'and user is a guest' do + before do + group.add_guest(user) + sign_in(user) + end - page.within(".dropdown-menu-user") do - expect(page).to have_content("Unassigned") - .and have_content(user.name) - .and have_content(project.users.first.name) + it_behaves_like 'renders not found' end - find('.js-assignee-search').click + end + + context 'when project is private' do + let_it_be(:project) { create(:project, :private, :repository, group: group) } - click_button("Create merge request") + context 'and user is a guest' do + before do + group.add_guest(user) + sign_in(user) + end - expect(page).to have_content(title).and have_content("requested to merge #{forked_project.full_path}:#{source_branch} into master") + it_behaves_like 'renders not found' + end end end + + private + + def compare_source_and_target(source_branch, target_branch) + find('.js-source-branch').click + click_link(source_branch) + + find('.js-target-branch').click + click_link(target_branch) + + click_button('Compare branches') + end end diff --git a/spec/features/merge_request/user_edits_merge_request_spec.rb b/spec/features/merge_request/user_edits_merge_request_spec.rb index 0b4b9d7452a..4ac25ea7ae0 100644 --- a/spec/features/merge_request/user_edits_merge_request_spec.rb +++ b/spec/features/merge_request/user_edits_merge_request_spec.rb @@ -3,8 +3,6 @@ require 'spec_helper' RSpec.describe 'User edits a merge request', :js do - include Select2Helper - let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:user) { create(:user) } @@ -89,7 +87,12 @@ RSpec.describe 'User edits a merge request', :js do it 'allows user to change target branch' do expect(page).to have_content('From master into feature') - select2('merge-test', from: '#merge_request_target_branch') + first('.js-target-branch').click + + wait_for_requests + + first('.js-target-branch-dropdown a', text: 'merge-test').click + click_button('Save changes') expect(page).to have_content("requested to merge #{merge_request.source_branch} into merge-test") @@ -101,7 +104,7 @@ RSpec.describe 'User edits a merge request', :js do it 'does not allow user to change target branch' do expect(page).to have_content('From master into feature') - expect(page).not_to have_selector('.select2-container') + expect(page).not_to have_selector('.js-target-branch.js-compare-dropdown') end end end diff --git a/spec/features/merge_request/user_manages_subscription_spec.rb b/spec/features/merge_request/user_manages_subscription_spec.rb index c64c761b8d1..9fb85957979 100644 --- a/spec/features/merge_request/user_manages_subscription_spec.rb +++ b/spec/features/merge_request/user_manages_subscription_spec.rb @@ -45,21 +45,21 @@ RSpec.describe 'User manages subscription', :js do click_button 'Toggle dropdown' - expect(page).to have_content('Turn on notifications') - click_button 'Turn on notifications' + expect(page).to have_selector('.gl-toggle:not(.is-checked)') + find('[data-testid="notifications-toggle"] .gl-toggle').click wait_for_requests click_button 'Toggle dropdown' - expect(page).to have_content('Turn off notifications') - click_button 'Turn off notifications' + expect(page).to have_selector('.gl-toggle.is-checked') + find('[data-testid="notifications-toggle"] .gl-toggle').click wait_for_requests click_button 'Toggle dropdown' - expect(page).to have_content('Turn on notifications') + expect(page).to have_selector('.gl-toggle:not(.is-checked)') end end end diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb index e09ec11f095..332426de07e 100644 --- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb +++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb @@ -15,6 +15,10 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do diff_refs: merge_request.diff_refs) end + before do + stub_feature_flags(moved_mr_sidebar: false) + end + context 'no threads' do before do project.add_maintainer(user) @@ -62,7 +66,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to mark thread as resolved' do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end expect(page).to have_selector('.discussion-body', visible: false) @@ -78,7 +82,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to unresolve thread' do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click click_button 'Unresolve thread' end @@ -90,7 +94,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do describe 'resolved thread' do before do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end visit_merge_request @@ -190,7 +194,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to resolve from reply form without a comment' do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end page.within '.discussions-counter' do @@ -225,7 +229,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'hides jump to next button when all resolved' do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end expect(page).to have_selector('.discussion-next-btn', visible: false) @@ -320,7 +324,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to mark all threads as resolved' do page.all('.discussion-reply-holder', count: 2).each do |reply_holder| page.within reply_holder do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end end @@ -331,7 +335,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to quickly scroll to next unresolved thread' do page.within('.discussion-reply-holder', match: :first) do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end page.within '.discussions-counter' do @@ -402,7 +406,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to mark thread as resolved' do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click end page.within '.diff-content .note' do @@ -416,7 +420,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to unresolve thread' do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click click_button 'Unresolve thread' end @@ -443,7 +447,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do it 'allows user to comment & unresolve thread' do page.within '.diff-content' do - find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage + find('button[data-testid="resolve-discussion-button"]').click find_field('Reply…').click diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb index c02149eed87..63ac7862b06 100644 --- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb +++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb @@ -111,7 +111,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do context 'with stop action' do let(:manual) do create(:ci_build, :manual, pipeline: pipeline, - name: 'close_app', environment: environment.name) + name: 'close_app', environment: environment.name) end before do diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index 1d3effd4a2a..c2a0e528ea7 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -219,7 +219,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do shared_examples 'pipeline widget' do it 'shows head pipeline information', :sidekiq_might_not_need_inline do within '.ci-widget-content' do - expect(page).to have_content("Detached merge request pipeline ##{pipeline.id} pending for #{pipeline.short_sha}") + expect(page).to have_content("Merge request pipeline ##{pipeline.id} pending for #{pipeline.short_sha}") end end end diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb index 563120fc8b7..ca102913369 100644 --- a/spec/features/merge_request/user_uses_quick_actions_spec.rb +++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' # for example, adding quick actions when creating the issue and checking DateTime formats on UI. # Because this kind of spec takes more time to run there is no need to add new ones # for each existing quick action unless they test something not tested by existing tests. -RSpec.describe 'Merge request > User uses quick actions', :js do +RSpec.describe 'Merge request > User uses quick actions', :js, :use_clean_rails_redis_caching do include Spec::Support::Helpers::Features::NotesHelpers let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb b/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb index b214486b3c1..d3ea8b955f2 100644 --- a/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb +++ b/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb @@ -8,6 +8,10 @@ RSpec.describe 'Project > Merge request > View user status' do create(:merge_request, source_project: project, target_project: project, author: create(:user)) end + before do + stub_feature_flags(remove_user_attributes_projects: false) + end + subject { visit merge_request_path(merge_request) } context 'for notes', :js do diff --git a/spec/features/monitor_sidebar_link_spec.rb b/spec/features/monitor_sidebar_link_spec.rb index b888e2f4171..f612956600f 100644 --- a/spec/features/monitor_sidebar_link_spec.rb +++ b/spec/features/monitor_sidebar_link_spec.rb @@ -4,39 +4,59 @@ require 'spec_helper' RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do let_it_be_with_reload(:project) { create(:project, :internal, :repository) } + let_it_be(:user) { create(:user) } - let(:user) { create(:user) } - let(:access_level) { ProjectFeature::PUBLIC } let(:role) { nil } before do project.add_role(user, role) if role - project.project_feature.update_attribute(:operations_access_level, access_level) - sign_in(user) - visit project_issues_path(project) end shared_examples 'shows Monitor menu based on the access level' do - context 'when operations project feature is PRIVATE' do - let(:access_level) { ProjectFeature::PRIVATE } - - it 'shows the `Monitor` menu' do - expect(page).to have_selector('a.shortcuts-monitor', text: 'Monitor') - end + using RSpec::Parameterized::TableSyntax + + let(:enabled) { Featurable::PRIVATE } + let(:disabled) { Featurable::DISABLED } + + where(:flag_enabled, :operations_access_level, :monitor_level, :render) do + true | ref(:disabled) | ref(:enabled) | true + true | ref(:disabled) | ref(:disabled) | false + true | ref(:enabled) | ref(:enabled) | true + true | ref(:enabled) | ref(:disabled) | false + false | ref(:disabled) | ref(:enabled) | false + false | ref(:disabled) | ref(:disabled) | false + false | ref(:enabled) | ref(:enabled) | true + false | ref(:enabled) | ref(:disabled) | true end - context 'when operations project feature is DISABLED' do - let(:access_level) { ProjectFeature::DISABLED } + with_them do + it 'renders when expected to' do + stub_feature_flags(split_operations_visibility_permissions: flag_enabled) + project.project_feature.update_attribute(:operations_access_level, operations_access_level) + project.project_feature.update_attribute(:monitor_access_level, monitor_level) + + visit project_issues_path(project) - it 'does not show the `Monitor` menu' do - expect(page).not_to have_selector('a.shortcuts-monitor') + if render + expect(page).to have_selector('a.shortcuts-monitor', text: 'Monitor') + else + expect(page).not_to have_selector('a.shortcuts-monitor') + end end end end - context 'user is not a member' do + context 'when user is not a member' do + let(:access_level) { ProjectFeature::PUBLIC } + + before do + project.project_feature.update_attribute(:operations_access_level, access_level) + project.project_feature.update_attribute(:monitor_access_level, access_level) + end + it 'has the correct `Monitor` menu items', :aggregate_failures do + visit project_issues_path(project) expect(page).to have_selector('a.shortcuts-monitor', text: 'Monitor') expect(page).to have_link('Incidents', href: project_incidents_path(project)) expect(page).to have_link('Environments', href: project_environments_path(project)) @@ -48,27 +68,50 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do expect(page).not_to have_link('Kubernetes', href: project_clusters_path(project)) end - context 'when operations project feature is PRIVATE' do - let(:access_level) { ProjectFeature::PRIVATE } + context 'with new monitor visiblity flag disabled' do + stub_feature_flags(split_operations_visibility_permissions: false) - it 'does not show the `Monitor` menu' do - expect(page).not_to have_selector('a.shortcuts-monitor') + context 'when operations project feature is PRIVATE' do + let(:access_level) { ProjectFeature::PRIVATE } + + it 'does not show the `Monitor` menu' do + expect(page).not_to have_selector('a.shortcuts-monitor') + end + end + + context 'when operations project feature is DISABLED' do + let(:access_level) { ProjectFeature::DISABLED } + + it 'does not show the `Operations` menu' do + expect(page).not_to have_selector('a.shortcuts-monitor') + end end end - context 'when operations project feature is DISABLED' do - let(:access_level) { ProjectFeature::DISABLED } + context 'with new monitor visiblity flag enabled' do + context 'when monitor project feature is PRIVATE' do + let(:access_level) { ProjectFeature::PRIVATE } + + it 'does not show the `Monitor` menu' do + expect(page).not_to have_selector('a.shortcuts-monitor') + end + end + + context 'when operations project feature is DISABLED' do + let(:access_level) { ProjectFeature::DISABLED } - it 'does not show the `Operations` menu' do - expect(page).not_to have_selector('a.shortcuts-monitor') + it 'does not show the `Operations` menu' do + expect(page).not_to have_selector('a.shortcuts-monitor') + end end end end - context 'user has guest role' do + context 'when user has guest role' do let(:role) { :guest } it 'has the correct `Monitor` menu items' do + visit project_issues_path(project) expect(page).to have_selector('a.shortcuts-monitor', text: 'Monitor') expect(page).to have_link('Incidents', href: project_incidents_path(project)) expect(page).to have_link('Environments', href: project_environments_path(project)) @@ -83,10 +126,11 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do it_behaves_like 'shows Monitor menu based on the access level' end - context 'user has reporter role' do + context 'when user has reporter role' do let(:role) { :reporter } it 'has the correct `Monitor` menu items' do + visit project_issues_path(project) expect(page).to have_link('Metrics', href: project_metrics_dashboard_path(project)) expect(page).to have_link('Incidents', href: project_incidents_path(project)) expect(page).to have_link('Environments', href: project_environments_path(project)) @@ -100,10 +144,11 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do it_behaves_like 'shows Monitor menu based on the access level' end - context 'user has developer role' do + context 'when user has developer role' do let(:role) { :developer } it 'has the correct `Monitor` menu items' do + visit project_issues_path(project) expect(page).to have_link('Metrics', href: project_metrics_dashboard_path(project)) expect(page).to have_link('Alerts', href: project_alert_management_index_path(project)) expect(page).to have_link('Incidents', href: project_incidents_path(project)) @@ -116,10 +161,11 @@ RSpec.describe 'Monitor dropdown sidebar', :aggregate_failures do it_behaves_like 'shows Monitor menu based on the access level' end - context 'user has maintainer role' do + context 'when user has maintainer role' do let(:role) { :maintainer } it 'has the correct `Monitor` menu items' do + visit project_issues_path(project) expect(page).to have_link('Metrics', href: project_metrics_dashboard_path(project)) expect(page).to have_link('Alerts', href: project_alert_management_index_path(project)) expect(page).to have_link('Incidents', href: project_incidents_path(project)) diff --git a/spec/features/populate_new_pipeline_vars_with_params_spec.rb b/spec/features/populate_new_pipeline_vars_with_params_spec.rb index 744543d1252..75fa8561235 100644 --- a/spec/features/populate_new_pipeline_vars_with_params_spec.rb +++ b/spec/features/populate_new_pipeline_vars_with_params_spec.rb @@ -7,24 +7,42 @@ RSpec.describe "Populate new pipeline CI variables with url params", :js do let(:project) { create(:project) } let(:page_path) { new_project_pipeline_path(project) } - before do - sign_in(user) - project.add_maintainer(user) + shared_examples 'form pre-filled with URL params' do + before do + sign_in(user) + project.add_maintainer(user) - visit "#{page_path}?var[key1]=value1&file_var[key2]=value2" + visit "#{page_path}?var[key1]=value1&file_var[key2]=value2" + end + + it "var[key1]=value1 populates env_var variable correctly" do + page.within(all("[data-testid='ci-variable-row']")[0]) do + expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key1') + expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value1') + end + end + + it "file_var[key2]=value2 populates file variable correctly" do + page.within(all("[data-testid='ci-variable-row']")[1]) do + expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key2') + expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value2') + end + end end - it "var[key1]=value1 populates env_var variable correctly" do - page.within(all("[data-testid='ci-variable-row']")[0]) do - expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key1') - expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value1') + context 'when feature flag is disabled' do + before do + stub_feature_flags(run_pipeline_graphql: false) end + + it_behaves_like 'form pre-filled with URL params' end - it "file_var[key2]=value2 populates file variable correctly" do - page.within(all("[data-testid='ci-variable-row']")[1]) do - expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key2') - expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value2') + context 'when feature flag is enabled' do + before do + stub_feature_flags(run_pipeline_graphql: true) end + + it_behaves_like 'form pre-filled with URL params' end end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 2836ac2f801..913c375f909 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -27,17 +27,41 @@ RSpec.describe 'Profile account page', :js do expect(User.exists?(user.id)).to be_truthy end - it 'deletes user', :js, :sidekiq_might_not_need_inline do - click_button 'Delete account' + context 'when user_destroy_with_limited_execution_time_worker is enabled' do + it 'deletes user', :js, :sidekiq_inline do + click_button 'Delete account' - fill_in 'password', with: user.password + fill_in 'password', with: user.password - page.within '.modal' do - click_button 'Delete account' + page.within '.modal' do + click_button 'Delete account' + end + + expect(page).to have_content('Account scheduled for removal') + expect( + Users::GhostUserMigration.where(user: user, + initiator_user: user) + ).to be_exists end + end - expect(page).to have_content('Account scheduled for removal') - expect(User.exists?(user.id)).to be_falsy + context 'when user_destroy_with_limited_execution_time_worker is disabled' do + before do + stub_feature_flags(user_destroy_with_limited_execution_time_worker: false) + end + + it 'deletes user', :js, :sidekiq_inline do + click_button 'Delete account' + + fill_in 'password', with: user.password + + page.within '.modal' do + click_button 'Delete account' + end + + expect(page).to have_content('Account scheduled for removal') + expect(User.exists?(user.id)).to be_falsy + end end it 'shows invalid password flash message', :js do diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb index 24c9225532b..d0819bb5363 100644 --- a/spec/features/profiles/active_sessions_spec.rb +++ b/spec/features/profiles/active_sessions_spec.rb @@ -59,7 +59,7 @@ RSpec.describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do expect(page).to( have_selector('ul.list-group li.list-group-item', text: 'Signed in on', - count: 2)) + count: 2)) expect(page).to have_content( '127.0.0.1 ' \ diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb index 2f7b722f553..d887a367fcb 100644 --- a/spec/features/profiles/user_edit_profile_spec.rb +++ b/spec/features/profiles/user_edit_profile_spec.rb @@ -8,6 +8,7 @@ RSpec.describe 'User edit profile' do let(:user) { create(:user) } before do + stub_feature_flags(remove_user_attributes_projects: false) sign_in(user) visit(profile_path) end @@ -179,7 +180,7 @@ RSpec.describe 'User edit profile' do end it 'adds emoji to user status' do - emoji = 'biohazard' + emoji = 'basketball' select_emoji(emoji) submit_settings @@ -192,7 +193,7 @@ RSpec.describe 'User edit profile' do it 'adds message to user status' do message = 'I have something to say' - fill_in 'js-status-message-field', with: message + fill_in s_("SetStatusModal|What's your status?"), with: message submit_settings visit_user @@ -207,7 +208,7 @@ RSpec.describe 'User edit profile' do emoji = '8ball' message = 'Playing outside' select_emoji(emoji) - fill_in 'js-status-message-field', with: message + fill_in s_("SetStatusModal|What's your status?"), with: message submit_settings visit_user @@ -229,7 +230,7 @@ RSpec.describe 'User edit profile' do end visit(profile_path) - click_button 'js-clear-user-status-button' + click_button s_('SetStatusModal|Clear status') submit_settings visit_user @@ -239,9 +240,9 @@ RSpec.describe 'User edit profile' do it 'displays a default emoji if only message is entered' do message = 'a status without emoji' - fill_in 'js-status-message-field', with: message + fill_in s_("SetStatusModal|What's your status?"), with: message - within('.js-toggle-emoji-menu') do + within('.emoji-menu-toggle-button') do expect(page).to have_emoji('speech_balloon') end end @@ -405,7 +406,7 @@ RSpec.describe 'User edit profile' do it 'adds message to user status' do message = 'I have something to say' open_user_status_modal - find('.js-status-message-field').native.send_keys(message) + find_field(s_("SetStatusModal|What's your status?")).native.send_keys(message) set_user_status_in_modal visit_user @@ -421,7 +422,7 @@ RSpec.describe 'User edit profile' do message = 'Playing outside' open_user_status_modal select_emoji(emoji, true) - find('.js-status-message-field').native.send_keys(message) + find_field(s_("SetStatusModal|What's your status?")).native.send_keys(message) set_user_status_in_modal visit_user @@ -445,7 +446,7 @@ RSpec.describe 'User edit profile' do open_edit_status_modal - find('.js-clear-user-status-button').click + click_button s_('SetStatusModal|Clear status') set_user_status_in_modal visit_user @@ -490,7 +491,7 @@ RSpec.describe 'User edit profile' do it 'displays a default emoji if only message is entered' do message = 'a status without emoji' open_user_status_modal - find('.js-status-message-field').native.send_keys(message) + find_field(s_("SetStatusModal|What's your status?")).native.send_keys(message) expect(page).to have_emoji('speech_balloon') end diff --git a/spec/features/profiles/user_visits_profile_spec.rb b/spec/features/profiles/user_visits_profile_spec.rb index 7dd2e6aafa3..df096c2f151 100644 --- a/spec/features/profiles/user_visits_profile_spec.rb +++ b/spec/features/profiles/user_visits_profile_spec.rb @@ -87,61 +87,4 @@ RSpec.describe 'User visits their profile' do end end end - - describe 'storage_enforcement_banner', :js do - before do - stub_feature_flags(namespace_storage_limit_bypass_date_check: false) - end - - context 'with storage_enforcement_date set' do - let_it_be(:storage_enforcement_date) { Date.today + 30 } - - before do - allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace| - allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date) - end - end - - it 'displays the banner in the profile page' do - visit(profile_path) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - - it 'does not display the banner if user has previously closed unless threshold has changed' do - visit(profile_path) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - find('.js-storage-enforcement-banner [data-testid="close-icon"]').click - page.refresh - expect_page_not_to_have_storage_enforcement_banner - - storage_enforcement_date = Date.today + 13 - allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace| - allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date) - end - page.refresh - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - end - - context 'with storage_enforcement_date not set' do - before do - allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace| - allow(user_namespace).to receive(:storage_enforcement_date).and_return(nil) - end - end - - it 'does not display the banner in the group page' do - visit(profile_path) - expect_page_not_to_have_storage_enforcement_banner - end - end - end - - def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply" - end - - def expect_page_not_to_have_storage_enforcement_banner - expect(page).not_to have_text "namespace storage limits will apply" - end end diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb index 89dbd1afc6b..d3bedbf3a75 100644 --- a/spec/features/project_variables_spec.rb +++ b/spec/features/project_variables_spec.rb @@ -14,8 +14,6 @@ RSpec.describe 'Project variables', :js do project.variables << variable end - # TODO: Add same tests but with FF enabled context when - # the new graphQL app for variable settings is enabled. context 'with disabled ff `ci_variable_settings_graphql' do before do stub_feature_flags(ci_variable_settings_graphql: false) @@ -44,4 +42,32 @@ RSpec.describe 'Project variables', :js do end end end + + context 'with enabled ff `ci_variable_settings_graphql' do + before do + visit page_path + end + + it_behaves_like 'variable list' + + it 'adds a new variable with an environment scope' do + click_button('Add variable') + + page.within('#add-ci-variable') do + fill_in 'Key', with: 'akey' + find('#ci-variable-value').set('akey_value') + find('[data-testid="environment-scope"]').click + find('[data-testid="ci-environment-search"]').set('review/*') + find('[data-testid="create-wildcard-button"]').click + + click_button('Add variable') + end + + wait_for_requests + + page.within('[data-testid="ci-variable-table"]') do + expect(find('.js-ci-variable-row:first-child [data-label="Environments"]').text).to eq('review/*') + end + end + end end diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb index 5c1bc1ad239..7555e567c37 100644 --- a/spec/features/projects/badges/coverage_spec.rb +++ b/spec/features/projects/badges/coverage_spec.rb @@ -191,7 +191,7 @@ RSpec.describe 'test coverage badge' do def show_test_coverage_badge(job: nil, min_good: nil, min_acceptable: nil, min_medium: nil) visit coverage_project_badges_path(project, ref: :master, job: job, min_good: min_good, - min_acceptable: min_acceptable, min_medium: min_medium, format: :svg) + min_acceptable: min_acceptable, min_medium: min_medium, format: :svg) end def expect_coverage_badge(coverage) diff --git a/spec/features/projects/blobs/blame_spec.rb b/spec/features/projects/blobs/blame_spec.rb index 3b2b74b469e..5287d5e4f7d 100644 --- a/spec/features/projects/blobs/blame_spec.rb +++ b/spec/features/projects/blobs/blame_spec.rb @@ -14,11 +14,32 @@ RSpec.describe 'File blame', :js do wait_for_all_requests end + context 'as a developer' do + let(:user) { create(:user) } + let(:role) { :developer } + + before do + project.add_role(user, role) + sign_in(user) + end + + it 'does not display lock, replace and delete buttons' do + visit_blob_blame(path) + + expect(page).not_to have_button("Lock") + expect(page).not_to have_button("Replace") + expect(page).not_to have_button("Delete") + end + end + it 'displays the blame page without pagination' do visit_blob_blame(path) - expect(page).to have_css('.blame-commit') - expect(page).not_to have_css('.gl-pagination') + within '[data-testid="blob-content-holder"]' do + expect(page).to have_css('.blame-commit') + expect(page).not_to have_css('.gl-pagination') + expect(page).not_to have_link _('View entire blame') + end end context 'when blob length is over the blame range limit' do @@ -29,12 +50,15 @@ RSpec.describe 'File blame', :js do it 'displays two first lines of the file with pagination' do visit_blob_blame(path) - expect(page).to have_css('.blame-commit') - expect(page).to have_css('.gl-pagination') + within '[data-testid="blob-content-holder"]' do + expect(page).to have_css('.blame-commit') + expect(page).to have_css('.gl-pagination') + expect(page).to have_link _('View entire blame') - expect(page).to have_css('#L1') - expect(page).not_to have_css('#L3') - expect(find('.page-link.active')).to have_text('1') + expect(page).to have_css('#L1') + expect(page).not_to have_css('#L3') + expect(find('.page-link.active')).to have_text('1') + end end context 'when user clicks on the next button' do @@ -45,15 +69,35 @@ RSpec.describe 'File blame', :js do end it 'displays next two lines of the file with pagination' do - expect(page).not_to have_css('#L1') - expect(page).to have_css('#L3') - expect(find('.page-link.active')).to have_text('2') + within '[data-testid="blob-content-holder"]' do + expect(page).not_to have_css('#L1') + expect(page).to have_css('#L3') + expect(find('.page-link.active')).to have_text('2') + end end it 'correctly redirects to the prior blame page' do - find('.version-link').click + within '[data-testid="blob-content-holder"]' do + find('.version-link').click + + expect(find('.page-link.active')).to have_text('2') + end + end + end + + context 'when user clicks on View entire blame button' do + before do + visit_blob_blame(path) + end + + it 'displays the blame page without pagination' do + within '[data-testid="blob-content-holder"]' do + click_link _('View entire blame') - expect(find('.page-link.active')).to have_text('2') + expect(page).to have_css('#L1') + expect(page).to have_css('#L3') + expect(page).not_to have_css('.gl-pagination') + end end end @@ -65,8 +109,11 @@ RSpec.describe 'File blame', :js do it 'displays the blame page without pagination' do visit_blob_blame(path) - expect(page).to have_css('.blame-commit') - expect(page).not_to have_css('.gl-pagination') + within '[data-testid="blob-content-holder"]' do + expect(page).to have_css('.blame-commit') + expect(page).not_to have_css('.gl-pagination') + expect(page).not_to have_link _('View entire blame') + end end end end @@ -81,25 +128,29 @@ RSpec.describe 'File blame', :js do it 'displays two hundred lines of the file with pagination' do visit_blob_blame(path) - expect(page).to have_css('.blame-commit') - expect(page).to have_css('.gl-pagination') + within '[data-testid="blob-content-holder"]' do + expect(page).to have_css('.blame-commit') + expect(page).to have_css('.gl-pagination') - expect(page).to have_css('#L1') - expect(page).not_to have_css('#L201') - expect(find('.page-link.active')).to have_text('1') + expect(page).to have_css('#L1') + expect(page).not_to have_css('#L201') + expect(find('.page-link.active')).to have_text('1') + end end context 'when user clicks on the next button' do before do visit_blob_blame(path) - - find('.js-next-button').click end it 'displays next two hundred lines of the file with pagination' do - expect(page).not_to have_css('#L1') - expect(page).to have_css('#L201') - expect(find('.page-link.active')).to have_text('2') + within '[data-testid="blob-content-holder"]' do + find('.js-next-button').click + + expect(page).not_to have_css('#L1') + expect(page).to have_css('#L201') + expect(find('.page-link.active')).to have_text('2') + end end end end diff --git a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb index 484f740faee..d2774aa74c9 100644 --- a/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb +++ b/spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb @@ -8,6 +8,10 @@ RSpec.describe 'User creates new blob', :js do let(:user) { create(:user) } let(:project) { create(:project, :empty_repo) } + before do + stub_feature_flags(vscode_web_ide: false) + end + shared_examples 'creating a file' do it 'allows the user to add a new file in Web IDE' do visit project_path(project) diff --git a/spec/features/projects/branches/user_creates_branch_spec.rb b/spec/features/projects/branches/user_creates_branch_spec.rb index 18d083f7d88..be236b7ca7e 100644 --- a/spec/features/projects/branches/user_creates_branch_spec.rb +++ b/spec/features/projects/branches/user_creates_branch_spec.rb @@ -1,48 +1,129 @@ # frozen_string_literal: true -require "spec_helper" +require 'spec_helper' -RSpec.describe "User creates branch", :js do +RSpec.describe 'User creates branch', :js do include Spec::Support::Helpers::Features::BranchesHelpers - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } + let_it_be(:group) { create(:group, :public) } + let_it_be(:user) { create(:user) } - before do - project.add_developer(user) - sign_in(user) + shared_examples 'creates new branch' do + specify do + branch_name = "deploy_keys_#{SecureRandom.hex(4)}" - visit(new_project_branch_path(project)) + create_branch(branch_name) + + expect(page).to have_content(branch_name) + end + end + + shared_examples 'renders not found page' do + specify do + expect(page).to have_title('Not Found') + expect(page).to have_content('Page Not Found') + end end - it "creates new branch" do - branch_name = "deploy_keys" + context 'when project is public with private repository' do + let_it_be(:project) { create(:project, :public, :repository, :repository_private, group: group) } - create_branch(branch_name) + context 'when user is an inherited member from the group' do + context 'and user is a guest' do + before do + group.add_guest(user) + sign_in(user) - expect(page).to have_content(branch_name) - end + visit(new_project_branch_path(project)) + end - context "when branch name is invalid" do - it "does not create new branch" do - invalid_branch_name = "1.0 stable" + it_behaves_like 'renders not found page' + end - fill_in("branch_name", with: invalid_branch_name) - page.find("body").click # defocus the branch_name input + context 'and user is a developer' do + before do + group.add_developer(user) + sign_in(user) - select_branch("master") - click_button("Create branch") + visit(new_project_branch_path(project)) + end - expect(page).to have_content("Branch name is invalid") - expect(page).to have_content("can't contain spaces") + it_behaves_like 'creates new branch' + end end end - context "when branch name already exists" do - it "does not create new branch" do - create_branch("master") + context 'when project is private' do + let_it_be(:project) { create(:project, :private, :repository, group: group) } + + context 'when user is a direct project member' do + context 'and user is a developer' do + before do + project.add_developer(user) + sign_in(user) + + visit(new_project_branch_path(project)) + end + + context 'when on new branch page' do + it 'renders I18n supported text' do + page.within('#new-branch-form') do + expect(page).to have_content(_('Branch name')) + expect(page).to have_content(_('Create from')) + expect(page).to have_content(_('Existing branch name, tag, or commit SHA')) + end + end + end + + it_behaves_like 'creates new branch' + + context 'when branch name is invalid' do + it 'does not create new branch' do + invalid_branch_name = '1.0 stable' + + fill_in('branch_name', with: invalid_branch_name) + page.find('body').click # defocus the branch_name input + + select_branch('master') + click_button('Create branch') + + expect(page).to have_content('Branch name is invalid') + expect(page).to have_content("can't contain spaces") + end + end + + context 'when branch name already exists' do + it 'does not create new branch' do + create_branch('master') + + expect(page).to have_content('Branch already exists') + end + end + end + end + + context 'when user is an inherited member from the group' do + context 'and user is a guest' do + before do + group.add_guest(user) + sign_in(user) + + visit(new_project_branch_path(project)) + end + + it_behaves_like 'renders not found page' + end + + context 'and user is a developer' do + before do + group.add_developer(user) + sign_in(user) + + visit(new_project_branch_path(project)) + end - expect(page).to have_content("Branch already exists") + it_behaves_like 'creates new branch' + end end end end diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb index e472cff38ce..417e14e2376 100644 --- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb +++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb @@ -27,7 +27,7 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do end it 'displays a mini pipeline graph' do - expect(page).to have_selector('[data-testid="commit-box-mini-graph"]') + expect(page).to have_selector('[data-testid="commit-box-pipeline-mini-graph"]') first('[data-testid="mini-pipeline-graph-dropdown"]').click @@ -35,7 +35,7 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do page.within '.js-builds-dropdown-list' do expect(page).to have_selector('.ci-status-icon-running') - expect(page).to have_content(build.stage) + expect(page).to have_content(build.stage_name) end build.drop diff --git a/spec/features/projects/commits/multi_view_diff_spec.rb b/spec/features/projects/commits/multi_view_diff_spec.rb index 5af2e367aed..c0e48b7b86c 100644 --- a/spec/features/projects/commits/multi_view_diff_spec.rb +++ b/spec/features/projects/commits/multi_view_diff_spec.rb @@ -11,8 +11,9 @@ RSpec.shared_examples "no multiple viewers" do |commit_ref| end RSpec.describe 'Multiple view Diffs', :js do - let(:user) { create(:user) } - let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + let(:ref) { '5d6ed1503801ca9dc28e95eeb85a7cf863527aee' } let(:path) { project_commit_path(project, ref) } let(:feature_flag_on) { false } diff --git a/spec/features/projects/environments/environment_metrics_spec.rb b/spec/features/projects/environments/environment_metrics_spec.rb index f5f4d13dd58..bf0949443de 100644 --- a/spec/features/projects/environments/environment_metrics_spec.rb +++ b/spec/features/projects/environments/environment_metrics_spec.rb @@ -30,9 +30,9 @@ RSpec.describe 'Environment > Metrics' do click_link 'Monitoring' expect(page).to have_current_path(project_metrics_dashboard_path(project, environment: environment.id)) - expect(page).to have_css('[data-qa-selector="environments_dropdown"]') # rubocop:disable QA/SelectorUsage + expect(page).to have_css('[data-testid="environments-dropdown"]') - within('[data-qa-selector="environments_dropdown"]') do # rubocop:disable QA/SelectorUsage + within('[data-testid="environments-dropdown"]') do # Click on the dropdown click_on(environment.name) @@ -59,7 +59,7 @@ RSpec.describe 'Environment > Metrics' do visit_environment(environment) click_link 'Monitoring' - expect(page).to have_css('[data-qa-selector="prometheus_graphs"]') # rubocop:disable QA/SelectorUsage + expect(page).to have_css('[data-testid="prometheus-graphs"]') end it_behaves_like 'has environment selector' diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index a53e8beb555..be4b21dfff4 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -264,9 +264,7 @@ RSpec.describe 'Environment' do let(:build) { create(:ci_build, :success, pipeline: pipeline, environment: environment.name) } let(:action) do - create(:ci_build, :manual, pipeline: pipeline, - name: 'close_app', - environment: environment.name) + create(:ci_build, :manual, pipeline: pipeline, name: 'close_app', environment: environment.name) end let(:deployment) do @@ -278,8 +276,7 @@ RSpec.describe 'Environment' do context 'when user has ability to stop environment' do let(:permissions) do - create(:protected_branch, :developers_can_merge, - name: action.ref, project: project) + create(:protected_branch, :developers_can_merge, name: action.ref, project: project) end it 'allows to stop environment', :js do diff --git a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb index 221f07a2f75..949e530f86d 100644 --- a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb +++ b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb @@ -30,8 +30,7 @@ RSpec.describe 'User sees feature flag list', :js do create(:operations_scope, strategy: strat, environment_scope: 'production') end end - create(:operations_feature_flag, :new_version_flag, project: project, - name: 'my_flag', active: false) + create(:operations_feature_flag, :new_version_flag, project: project, name: 'my_flag', active: false) end it 'shows the user the first flag' do @@ -91,7 +90,7 @@ RSpec.describe 'User sees feature flag list', :js do it 'shows the empty page' do expect(page).to have_text 'Get started with feature flags' expect(page).to have_selector('.btn-confirm', text: 'New feature flag') - expect(page).to have_selector('[data-qa-selector="configure_feature_flags_button"]', text: 'Configure') # rubocop:disable QA/SelectorUsage + expect(page).to have_selector('[data-testid="ff-configure-button"]', text: 'Configure') end end end diff --git a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb index 71c9d89fbde..eb9ac078662 100644 --- a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb +++ b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb @@ -18,13 +18,12 @@ RSpec.describe 'User updates feature flag', :js do context 'with a new version feature flag' do let!(:feature_flag) do - create_flag(project, 'test_flag', false, version: Operations::FeatureFlag.versions['new_version_flag'], - description: 'For testing') + create_flag(project, 'test_flag', false, + version: Operations::FeatureFlag.versions['new_version_flag'], description: 'For testing') end let!(:strategy) do - create(:operations_strategy, feature_flag: feature_flag, - name: 'default', parameters: {}) + create(:operations_strategy, feature_flag: feature_flag, name: 'default', parameters: {}) end let!(:scope) do diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 0ad44f31a52..52686469243 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -9,6 +9,8 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license let(:project_maintainer) { project.first_owner } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(project_maintainer) end diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb index d7460538be9..1a9c5483218 100644 --- a/spec/features/projects/files/user_edits_files_spec.rb +++ b/spec/features/projects/files/user_edits_files_spec.rb @@ -14,6 +14,8 @@ RSpec.describe 'Projects > Files > User edits files', :js do let(:user) { create(:user) } before do + stub_feature_flags(vscode_web_ide: false) + sign_in(user) end @@ -102,6 +104,21 @@ RSpec.describe 'Projects > Files > User edits files', :js do expect(page).to have_content('*.rbca') end + it 'shows loader on commit changes' do + set_default_button('edit') + click_link('.gitignore') + click_link_or_button('Edit') + + # why: We don't want the form to actually submit, so that we can assert the button's changed state + page.execute_script("document.querySelector('.js-edit-blob-form').addEventListener('submit', e => e.preventDefault())") + + find('.file-editor', match: :first) + editor_set_value('*.rbca') + click_button('Commit changes') + + expect(page).to have_button('Commit changes', disabled: true, class: 'js-commit-button-loading') + end + it 'shows the diff of an edited file' do set_default_button('edit') click_link('.gitignore') diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb index fb27f0961b6..b8c127f0078 100644 --- a/spec/features/projects/fork_spec.rb +++ b/spec/features/projects/fork_spec.rb @@ -126,7 +126,10 @@ RSpec.describe 'Project fork' do let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user } def submit_form - select(group.name) + find('[data-testid="select_namespace_dropdown"]').click + find('[data-testid="select_namespace_dropdown_search_field"]').fill_in(with: group.name) + click_button group.name + click_button 'Fork project' end diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb index 289ab8cffa5..995f4a1e3d2 100644 --- a/spec/features/projects/jobs/user_browses_jobs_spec.rb +++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb @@ -58,8 +58,7 @@ RSpec.describe 'User browses jobs' do context 'when a job can be canceled' do let!(:job) do - create(:ci_build, pipeline: pipeline, - stage: 'test') + create(:ci_build, pipeline: pipeline, stage: 'test') end before do @@ -81,7 +80,7 @@ RSpec.describe 'User browses jobs' do context 'when a job can be retried' do let!(:job) do create(:ci_build, pipeline: pipeline, - stage: 'test') + stage: 'test') end before do @@ -190,7 +189,7 @@ RSpec.describe 'User browses jobs' do context 'column links' do let!(:job) do create(:ci_build, pipeline: pipeline, - stage: 'test') + stage: 'test') end before do diff --git a/spec/features/projects/milestones/milestones_sorting_spec.rb b/spec/features/projects/milestones/milestones_sorting_spec.rb index 2ad820e4a06..c47350fb663 100644 --- a/spec/features/projects/milestones/milestones_sorting_spec.rb +++ b/spec/features/projects/milestones/milestones_sorting_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Milestones sorting', :js do let(:milestones_for_sort_by) do { 'Due later' => %w[b c a], - 'Name, ascending' => %w[a b c], + 'Name, ascending' => %w[a b c], 'Name, descending' => %w[c b a], 'Start later' => %w[a c b], 'Start soon' => %w[b c a], diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index e07a5d09405..5b5f7860e43 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -49,7 +49,7 @@ RSpec.describe 'Project navbar' do stub_config(pages: { enabled: true }) insert_after_sub_nav_item( - _('Packages & Registries'), + _('Packages and registries'), within: _('Settings'), new_sub_nav_item_name: _('Pages') ) @@ -83,6 +83,8 @@ RSpec.describe 'Project navbar' do end context 'when harbor registry is available' do + let_it_be(:harbor_integration) { create(:harbor_integration, project: project) } + before do stub_feature_flags(harbor_registry_integration: true) diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index f45025d079a..7cf05242a23 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -424,9 +424,10 @@ RSpec.describe 'New project', :js do it 'keeps "Import project" tab open after form validation error' do collision_project = create(:project, name: 'test-name-collision', namespace: user.namespace) - stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return({ status: 200, - body: '001e# service=git-upload-pack', - headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } }) + stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return( + { status: 200, + body: '001e# service=git-upload-pack', + headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } }) fill_in 'project_import_url', with: 'http://foo/bar' fill_in 'project_name', with: collision_project.name @@ -465,9 +466,10 @@ RSpec.describe 'New project', :js do end it 'initiates import when valid repo url is provided' do - stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return({ status: 200, - body: '001e# service=git-upload-pack', - headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } }) + stub_request(:get, "http://foo/bar/info/refs?service=git-upload-pack").to_return( + { status: 200, + body: '001e# service=git-upload-pack', + headers: { 'Content-Type': 'application/x-git-upload-pack-advertisement' } }) fill_in 'project_import_url', with: 'http://foo/bar' diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb index 0711a30e974..dcc46f5d223 100644 --- a/spec/features/projects/pipeline_schedules_spec.rb +++ b/spec/features/projects/pipeline_schedules_spec.rb @@ -95,7 +95,7 @@ RSpec.describe 'Pipeline Schedules', :js do it 'displays the required information description' do page.within('.pipeline-schedule-table-row') do expect(page).to have_content('pipeline schedule') - expect(find(".next-run-cell time")['title']) + expect(find("[data-testid='next-run-cell'] time")['title']) .to include(pipeline_schedule.real_next_run.strftime('%b %-d, %Y')) expect(page).to have_link('master') expect(page).to have_link("##{pipeline.id}") @@ -259,7 +259,7 @@ RSpec.describe 'Pipeline Schedules', :js do click_button 'Save pipeline schedule' page.within('.pipeline-schedule-table-row:nth-child(1)') do - expect(page).to have_css(".next-run-cell time") + expect(page).to have_css("[data-testid='next-run-cell'] time") end end end diff --git a/spec/features/projects/pipelines/legacy_pipeline_spec.rb b/spec/features/projects/pipelines/legacy_pipeline_spec.rb index 14f60dfe061..250a336469c 100644 --- a/spec/features/projects/pipelines/legacy_pipeline_spec.rb +++ b/spec/features/projects/pipelines/legacy_pipeline_spec.rb @@ -73,9 +73,9 @@ RSpec.describe 'Pipeline', :js do visit_pipeline expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end @@ -668,9 +668,9 @@ RSpec.describe 'Pipeline', :js do it 'shows the pipeline graph' do expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end @@ -769,13 +769,17 @@ RSpec.describe 'Pipeline', :js do let(:resource_group) { create(:ci_resource_group, project: project) } let!(:test_job) do - create(:ci_build, :pending, stage: 'test', name: 'test', - stage_idx: 1, pipeline: pipeline, project: project) + create(:ci_build, :pending, stage: 'test', name: 'test', stage_idx: 1, pipeline: pipeline, project: project) end let!(:deploy_job) do - create(:ci_build, :created, stage: 'deploy', name: 'deploy', - stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group) + create(:ci_build, :created, + stage: 'deploy', + name: 'deploy', + stage_idx: 2, + pipeline: pipeline, + project: project, + resource_group: resource_group) end describe 'GET /:project/-/pipelines/:id' do @@ -873,8 +877,14 @@ RSpec.describe 'Pipeline', :js do context 'when deploy job is a bridge to trigger a downstream pipeline' do let!(:deploy_job) do - create(:ci_bridge, :created, stage: 'deploy', name: 'deploy', - stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group) + create(:ci_bridge, :created, + stage: 'deploy', + name: 'deploy', + stage_idx: 2, + pipeline: pipeline, + project: project, + resource_group: resource_group + ) end it 'shows deploy job as waiting for resource' do @@ -895,8 +905,14 @@ RSpec.describe 'Pipeline', :js do context 'when deploy job is a bridge to trigger a downstream pipeline' do let!(:deploy_job) do - create(:ci_bridge, :created, stage: 'deploy', name: 'deploy', - stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group) + create(:ci_bridge, :created, + stage: 'deploy', + name: 'deploy', + stage_idx: 2, + pipeline: pipeline, + project: project, + resource_group: resource_group + ) end it 'shows deploy job as waiting for resource' do @@ -1207,7 +1223,7 @@ RSpec.describe 'Pipeline', :js do subject expect(page).to have_content(failed_build.name) - expect(page).to have_content(failed_build.stage) + expect(page).to have_content(failed_build.stage_name) end it 'shows build failure logs' do @@ -1253,7 +1269,7 @@ RSpec.describe 'Pipeline', :js do subject expect(page).to have_content(failed_build.name) - expect(page).to have_content(failed_build.stage) + expect(page).to have_content(failed_build.stage_name) end it 'does not show log' do diff --git a/spec/features/projects/pipelines/legacy_pipelines_spec.rb b/spec/features/projects/pipelines/legacy_pipelines_spec.rb index eb8f2de3aba..2e0ea695ab3 100644 --- a/spec/features/projects/pipelines/legacy_pipelines_spec.rb +++ b/spec/features/projects/pipelines/legacy_pipelines_spec.rb @@ -546,8 +546,8 @@ RSpec.describe 'Pipelines', :js do context 'for a failed pipeline' do let!(:build) do create(:ci_build, :failed, pipeline: pipeline, - stage: 'build', - name: 'build') + stage: 'build', + name: 'build') end it 'displays the failure reason' do @@ -652,10 +652,10 @@ RSpec.describe 'Pipelines', :js do expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user)) # stages - expect(page).to have_text('Build') - expect(page).to have_text('Test') - expect(page).to have_text('Deploy') - expect(page).to have_text('External') + expect(page).to have_text('build') + expect(page).to have_text('test') + expect(page).to have_text('deploy') + expect(page).to have_text('external') # builds expect(page).to have_text('rspec') @@ -674,6 +674,7 @@ RSpec.describe 'Pipelines', :js do let(:project) { create(:project, :repository) } before do + stub_feature_flags(run_pipeline_graphql: false) visit new_project_pipeline_path(project) end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index cfdd851cb80..51a6fbc4d36 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -72,9 +72,9 @@ RSpec.describe 'Pipeline', :js do visit_pipeline expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end @@ -793,9 +793,9 @@ RSpec.describe 'Pipeline', :js do it 'shows the pipeline graph' do expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end @@ -895,12 +895,12 @@ RSpec.describe 'Pipeline', :js do let!(:test_job) do create(:ci_build, :pending, stage: 'test', name: 'test', - stage_idx: 1, pipeline: pipeline, project: project) + stage_idx: 1, pipeline: pipeline, project: project) end let!(:deploy_job) do create(:ci_build, :created, stage: 'deploy', name: 'deploy', - stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group) + stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group) end describe 'GET /:project/-/pipelines/:id' do @@ -998,8 +998,14 @@ RSpec.describe 'Pipeline', :js do context 'when deploy job is a bridge to trigger a downstream pipeline' do let!(:deploy_job) do - create(:ci_bridge, :created, stage: 'deploy', name: 'deploy', - stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group) + create(:ci_bridge, :created, + stage: 'deploy', + name: 'deploy', + stage_idx: 2, + pipeline: pipeline, + project: project, + resource_group: resource_group + ) end it 'shows deploy job as waiting for resource' do @@ -1126,7 +1132,7 @@ RSpec.describe 'Pipeline', :js do subject expect(page).to have_content(failed_build.name) - expect(page).to have_content(failed_build.stage) + expect(page).to have_content(failed_build.stage_name) end it 'shows build failure logs' do @@ -1172,7 +1178,7 @@ RSpec.describe 'Pipeline', :js do subject expect(page).to have_content(failed_build.name) - expect(page).to have_content(failed_build.stage) + expect(page).to have_content(failed_build.stage_name) end it 'does not show log' do diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index bf521971ae0..404e51048bc 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -536,8 +536,8 @@ RSpec.describe 'Pipelines', :js do context 'for a failed pipeline' do let!(:build) do create(:ci_build, :failed, pipeline: pipeline, - stage: 'build', - name: 'build') + stage: 'build', + name: 'build') end it 'displays the failure reason' do @@ -635,10 +635,10 @@ RSpec.describe 'Pipelines', :js do expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user)) # stages - expect(page).to have_text('Build') - expect(page).to have_text('Test') - expect(page).to have_text('Deploy') - expect(page).to have_text('External') + expect(page).to have_text('build') + expect(page).to have_text('test') + expect(page).to have_text('deploy') + expect(page).to have_text('external') # builds expect(page).to have_text('rspec') @@ -656,19 +656,7 @@ RSpec.describe 'Pipelines', :js do describe 'POST /:project/-/pipelines' do let(:project) { create(:project, :repository) } - before do - visit new_project_pipeline_path(project) - end - - context 'for valid commit', :js do - before do - click_button project.default_branch - wait_for_requests - - find('p', text: 'master').click - wait_for_requests - end - + shared_examples 'run pipeline form with gitlab-ci.yml' do context 'with gitlab-ci.yml', :js do before do stub_ci_pipeline_to_return_yaml_file @@ -702,7 +690,9 @@ RSpec.describe 'Pipelines', :js do end end end + end + shared_examples 'run pipeline form without gitlab-ci.yml' do context 'without gitlab-ci.yml' do before do click_on 'Run pipeline' @@ -722,6 +712,51 @@ RSpec.describe 'Pipelines', :js do end end end + + # Run Pipeline form with REST endpoints + # TODO: Clean up tests when run_pipeline_graphql is enabled + context 'with feature flag disabled' do + before do + stub_feature_flags(run_pipeline_graphql: false) + visit new_project_pipeline_path(project) + end + + context 'for valid commit', :js do + before do + click_button project.default_branch + wait_for_requests + + find('p', text: 'master').click + wait_for_requests + end + + it_behaves_like 'run pipeline form with gitlab-ci.yml' + + it_behaves_like 'run pipeline form without gitlab-ci.yml' + end + end + + # Run Pipeline form with GraphQL + context 'with feature flag enabled' do + before do + stub_feature_flags(run_pipeline_graphql: true) + visit new_project_pipeline_path(project) + end + + context 'for valid commit', :js do + before do + click_button project.default_branch + wait_for_requests + + find('p', text: 'master').click + wait_for_requests + end + + it_behaves_like 'run pipeline form with gitlab-ci.yml' + + it_behaves_like 'run pipeline form without gitlab-ci.yml' + end + end end describe 'Reset runner caches' do diff --git a/spec/features/projects/releases/user_creates_release_spec.rb b/spec/features/projects/releases/user_creates_release_spec.rb index 10c4395da81..d82c4229b71 100644 --- a/spec/features/projects/releases/user_creates_release_spec.rb +++ b/spec/features/projects/releases/user_creates_release_spec.rb @@ -47,7 +47,7 @@ RSpec.describe 'User creates release', :js do fill_out_form_and_submit end - it 'creates a new release when "Create release" is clicked and redirects to the release\'s dedicated page', :aggregate_failures do + it 'creates a new release when "Create release" is clicked and redirects to the release\'s dedicated page', :aggregate_failures, :sidekiq_inline do release = project.releases.last expect(release.tag).to eq(tag_name) @@ -66,6 +66,11 @@ RSpec.describe 'User creates release', :js do expect(link.url).to eq(link_2[:url]) expect(link.name).to eq(link_2[:title]) + expect(release).not_to be_historical_release + expect(release).not_to be_upcoming_release + + expect(release.evidences.length).to eq(1) + expect(page).to have_current_path(project_release_path(project, release)) end end diff --git a/spec/features/projects/settings/merge_requests_settings_spec.rb b/spec/features/projects/settings/merge_requests_settings_spec.rb new file mode 100644 index 00000000000..ba84d8b6d1a --- /dev/null +++ b/spec/features/projects/settings/merge_requests_settings_spec.rb @@ -0,0 +1,261 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Projects > Settings > Merge requests' do + include ProjectForksHelper + + let(:user) { create(:user) } + let(:project) { create(:project, :public, namespace: user.namespace, path: 'gitlab', name: 'sample') } + + before do + sign_in(user) + + visit(project_settings_merge_requests_path(project)) + end + + it 'shows "Merge commit" strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Merge commit' + end + end + + it 'shows "Merge commit with semi-linear history " strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Merge commit with semi-linear history' + end + end + + it 'shows "Fast-forward merge" strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Fast-forward merge' + end + end + + it 'shows Squash commit options', :aggregate_failures do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Do not allow' + expect(page).to have_content 'Squashing is never performed and the checkbox is hidden.' + + expect(page).to have_content 'Allow' + expect(page).to have_content 'Checkbox is visible and unselected by default.' + + expect(page).to have_content 'Encourage' + expect(page).to have_content 'Checkbox is visible and selected by default.' + + expect(page).to have_content 'Require' + end + end + + context 'when Merge Request and Pipelines are initially enabled', :js do + context 'when Pipelines are initially enabled' do + it 'shows the Merge Requests settings' do + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' + + visit edit_project_path(project) + + within('.sharing-permissions-form') do + within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do + find('.gl-toggle').click + end + end + + find('[data-testid="project-features-save-button"]').send_keys(:return) + + visit project_settings_merge_requests_path(project) + + expect(page).to have_content('Not Found') + end + end + + context 'when Pipelines are initially disabled', :js do + before do + project.project_feature.update_attribute('builds_access_level', ProjectFeature::DISABLED) + + visit project_settings_merge_requests_path(project) + end + + it 'shows the Merge Requests settings that do not depend on Builds feature' do + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' + + visit edit_project_path(project) + + within('.sharing-permissions-form') do + within('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"]') do + find('.gl-toggle').click + end + end + + find('[data-testid="project-features-save-button"]').send_keys(:return) + + visit project_settings_merge_requests_path(project) + + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' + end + end + end + + context 'when Merge Request are initially disabled', :js do + before do + project.project_feature.update_attribute('merge_requests_access_level', ProjectFeature::DISABLED) + + visit(project_settings_merge_requests_path(project)) + end + + it 'does not show the Merge Requests settings' do + expect(page).to have_content('Not Found') + + visit edit_project_path(project) + + within('.sharing-permissions-form') do + within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do + find('.gl-toggle').click + end + end + + find('[data-testid="project-features-save-button"]').send_keys(:return) + + visit project_settings_merge_requests_path(project) + + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' + end + end + + describe 'Checkbox to enable merge request link', :js do + it 'is initially checked' do + checkbox = find_field('project_printing_merge_request_link_enabled') + expect(checkbox).to be_checked + end + + it 'when unchecked sets :printing_merge_request_link_enabled to false' do + uncheck('project_printing_merge_request_link_enabled') + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + find('.flash-notice') + checkbox = find_field('project_printing_merge_request_link_enabled') + + expect(checkbox).not_to be_checked + + project.reload + expect(project.printing_merge_request_link_enabled).to be(false) + end + end + + describe 'Checkbox to remove source branch after merge', :js do + it 'is initially checked' do + checkbox = find_field('project_remove_source_branch_after_merge') + expect(checkbox).to be_checked + end + + it 'when unchecked sets :remove_source_branch_after_merge to false' do + uncheck('project_remove_source_branch_after_merge') + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + find('.flash-notice') + checkbox = find_field('project_remove_source_branch_after_merge') + + expect(checkbox).not_to be_checked + + project.reload + expect(project.remove_source_branch_after_merge).to be(false) + end + end + + describe 'Squash commits when merging', :js do + it 'initially has :squash_option set to :default_off' do + radio = find_field('project_project_setting_attributes_squash_option_default_off') + expect(radio).to be_checked + end + + it 'allows :squash_option to be set to :default_on' do + choose('project_project_setting_attributes_squash_option_default_on') + + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + wait_for_requests + + radio = find_field('project_project_setting_attributes_squash_option_default_on') + + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('default_on') + end + + it 'allows :squash_option to be set to :always' do + choose('project_project_setting_attributes_squash_option_always') + + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + wait_for_requests + + radio = find_field('project_project_setting_attributes_squash_option_always') + + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('always') + end + + it 'allows :squash_option to be set to :never' do + choose('project_project_setting_attributes_squash_option_never') + + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + wait_for_requests + + radio = find_field('project_project_setting_attributes_squash_option_never') + + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('never') + end + end + + describe 'target project settings' do + context 'when project is a fork' do + let_it_be(:upstream) { create(:project, :public) } + + let(:project) { fork_project(upstream, user) } + + it 'allows to change merge request target project behavior' do + expect(page).to have_content 'The default target project for merge requests' + + radio = find_field('project_project_setting_attributes_mr_default_target_self_false') + expect(radio).to be_checked + + choose('project_project_setting_attributes_mr_default_target_self_true') + + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + wait_for_requests + + radio = find_field('project_project_setting_attributes_mr_default_target_self_true') + + expect(radio).to be_checked + expect(project.reload.project_setting.mr_default_target_self).to be_truthy + end + end + + it 'does not show target project section' do + expect(page).not_to have_content 'The default target project for merge requests' + end + end +end diff --git a/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb b/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb index 5a50b3de772..477c4c2e1ba 100644 --- a/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb +++ b/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Project > Settings > Packages & Registries > Container registry tag expiration policy' do +RSpec.describe 'Project > Settings > Packages and registries > Container registry tag expiration policy' do let_it_be(:user) { create(:user) } let_it_be(:project, reload: true) { create(:project, namespace: user.namespace) } @@ -20,10 +20,89 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry end context 'as owner', :js do + it 'shows active tab on sidebar' do + subject + + expect(find('.sidebar-top-level-items > li.active')).to have_content('Settings') + expect(find('.sidebar-sub-level-items > li.active:not(.fly-out-top-item)')) + .to have_content('Packages and registries') + end + it 'shows available section' do subject expect(find('.breadcrumbs')).to have_content('Clean up image tags') + + section = find('[data-testid="container-expiration-policy-project-settings"]') + expect(section).to have_text 'Clean up image tags' + end + + it 'saves cleanup policy submit the form' do + subject + + within '[data-testid="container-expiration-policy-project-settings"]' do + select('Every day', from: 'Run cleanup') + select('50 tags per image name', from: 'Keep the most recent:') + fill_in('Keep tags matching:', with: 'stable') + select('7 days', from: 'Remove tags older than:') + fill_in('Remove tags matching:', with: '.*-production') + + submit_button = find('[data-testid="save-button"') + expect(submit_button).not_to be_disabled + submit_button.click + end + + expect(page).to have_current_path(project_settings_packages_and_registries_path(project)) + expect(find('.gl-alert-body')).to have_content('Cleanup policy successfully saved.') + end + + it 'does not save cleanup policy submit form with invalid regex' do + subject + + within '[data-testid="container-expiration-policy-project-settings"]' do + fill_in('Remove tags matching:', with: '*-production') + + submit_button = find('[data-testid="save-button"') + expect(submit_button).not_to be_disabled + submit_button.click + end + + expect(find('.gl-toast')).to have_content('Something went wrong while updating the cleanup policy.') + end + end + + context 'with a project without expiration policy', :js do + before do + project.container_expiration_policy.destroy! + end + + context 'with container_expiration_policies_enable_historic_entries enabled' do + before do + stub_application_setting(container_expiration_policies_enable_historic_entries: true) + end + + it 'displays the related section' do + subject + + within '[data-testid="container-expiration-policy-project-settings"]' do + expect(find('[data-testid="enable-toggle"]')) + .to have_content('Disabled - Tags will not be automatically deleted.') + end + end + end + + context 'with container_expiration_policies_enable_historic_entries disabled' do + before do + stub_application_setting(container_expiration_policies_enable_historic_entries: false) + end + + it 'does not display the related section' do + subject + + within '[data-testid="container-expiration-policy-project-settings"]' do + expect(find('.gl-alert-title')).to have_content('Cleanup policy for tags is disabled') + end + end end end diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb index 1fb46c669e7..d64570cd5cc 100644 --- a/spec/features/projects/settings/registry_settings_spec.rb +++ b/spec/features/projects/settings/registry_settings_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Project > Settings > Packages & Registries > Container registry tag expiration policy', :js do +RSpec.describe 'Project > Settings > Packages and registries > Container registry tag expiration policy' do let_it_be(:user) { create(:user) } let_it_be(:project, reload: true) { create(:project, namespace: user.namespace) } @@ -19,48 +19,30 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry stub_container_registry_config(enabled: container_registry_enabled) end - context 'as owner' do - it 'shows available section' do + context 'as owner', :js do + it 'shows active tab on sidebar' do subject - settings_block = find('[data-testid="container-expiration-policy-project-settings"]') - expect(settings_block).to have_text 'Clean up image tags' + expect(find('.sidebar-top-level-items > li.active')).to have_content('Settings') + expect(find('.sidebar-sub-level-items > li.active:not(.fly-out-top-item)')) + .to have_content('Packages and registries') end - it 'saves cleanup policy submit the form' do + it 'shows available section' do subject - within '[data-testid="container-expiration-policy-project-settings"]' do - select('Every day', from: 'Run cleanup') - select('50 tags per image name', from: 'Keep the most recent:') - fill_in('Keep tags matching:', with: 'stable') - select('7 days', from: 'Remove tags older than:') - fill_in('Remove tags matching:', with: '.*-production') - - submit_button = find('[data-testid="save-button"') - expect(submit_button).not_to be_disabled - submit_button.click - end - - expect(find('.gl-toast')).to have_content('Cleanup policy successfully saved.') + settings_block = find('[data-testid="container-expiration-policy-project-settings"]') + expect(settings_block).to have_text 'Clean up image tags' end - it 'does not save cleanup policy submit form with invalid regex' do + it 'contains link to clean up image tags page' do subject - within '[data-testid="container-expiration-policy-project-settings"]' do - fill_in('Remove tags matching:', with: '*-production') - - submit_button = find('[data-testid="save-button"') - expect(submit_button).not_to be_disabled - submit_button.click - end - - expect(find('.gl-toast')).to have_content('Something went wrong while updating the cleanup policy.') + expect(page).to have_link('Edit cleanup rules', href: cleanup_image_tags_project_settings_packages_and_registries_path(project)) end end - context 'with a project without expiration policy' do + context 'with a project without expiration policy', :js do before do project.container_expiration_policy.destroy! end @@ -74,7 +56,7 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry subject within '[data-testid="container-expiration-policy-project-settings"]' do - expect(find('[data-testid="enable-toggle"]')).to have_content('Disabled - Tags will not be automatically deleted.') + expect(page).to have_link('Set cleanup rules', href: cleanup_image_tags_project_settings_packages_and_registries_path(project)) end end end diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb index 6aa59f72d2a..c76b4d0af88 100644 --- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb @@ -9,29 +9,29 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do before do sign_in(user) - visit edit_project_path(project) + visit project_settings_merge_requests_path(project) end it 'shows "Merge commit" strategy' do - page.within '#js-merge-request-settings' do + page.within '.merge-request-settings-form' do expect(page).to have_content 'Merge commit' end end it 'shows "Merge commit with semi-linear history " strategy' do - page.within '#js-merge-request-settings' do + page.within '.merge-request-settings-form' do expect(page).to have_content 'Merge commit with semi-linear history' end end it 'shows "Fast-forward merge" strategy' do - page.within '#js-merge-request-settings' do + page.within '.merge-request-settings-form' do expect(page).to have_content 'Fast-forward merge' end end it 'shows Squash commit options', :aggregate_failures do - page.within '#js-merge-request-settings' do + page.within '.merge-request-settings-form' do expect(page).to have_content 'Do not allow' expect(page).to have_content 'Squashing is never performed and the checkbox is hidden.' @@ -52,30 +52,33 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do expect(page).to have_content 'Pipelines must succeed' expect(page).to have_content 'All threads must be resolved' - within('.sharing-permissions-form') do - find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click - find('[data-testid="project-features-save-button"]').send_keys(:return) - end + visit edit_project_path(project) + + find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click + find('[data-testid="project-features-save-button"]').send_keys(:return) + + visit project_settings_merge_requests_path(project) - expect(page).not_to have_content 'Pipelines must succeed' - expect(page).not_to have_content 'All threads must be resolved' + expect(page).to have_content "Page Not Found" end end context 'when Pipelines are initially disabled', :js do before do project.project_feature.update_attribute('builds_access_level', ProjectFeature::DISABLED) - visit edit_project_path(project) + visit project_settings_merge_requests_path(project) end it 'shows the Merge Requests settings that do not depend on Builds feature' do expect(page).to have_content 'Pipelines must succeed' expect(page).to have_content 'All threads must be resolved' - within('.sharing-permissions-form') do - find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .gl-toggle').click - find('[data-testid="project-features-save-button"]').send_keys(:return) - end + visit edit_project_path(project) + + find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .gl-toggle').click + find('[data-testid="project-features-save-button"]').send_keys(:return) + + visit project_settings_merge_requests_path(project) expect(page).to have_content 'Pipelines must succeed' expect(page).to have_content 'All threads must be resolved' @@ -86,18 +89,22 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do context 'when Merge Request are initially disabled', :js do before do project.project_feature.update_attribute('merge_requests_access_level', ProjectFeature::DISABLED) - visit edit_project_path(project) + visit project_settings_merge_requests_path(project) end it 'does not show the Merge Requests settings' do expect(page).not_to have_content 'Pipelines must succeed' expect(page).not_to have_content 'All threads must be resolved' + visit edit_project_path(project) + within('.sharing-permissions-form') do find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click find('[data-testid="project-features-save-button"]').send_keys(:return) end + visit project_settings_merge_requests_path(project) + expect(page).to have_content 'Pipelines must succeed' expect(page).to have_content 'All threads must be resolved' end diff --git a/spec/features/projects/settings/visibility_settings_spec.rb b/spec/features/projects/settings/visibility_settings_spec.rb index fc78b5b5769..5cb12544066 100644 --- a/spec/features/projects/settings/visibility_settings_spec.rb +++ b/spec/features/projects/settings/visibility_settings_spec.rb @@ -28,26 +28,12 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do expect(visibility_select_container).to have_content 'Only accessible by project members. Membership must be explicitly granted to each user.' end - context 'merge requests select' do - it 'hides merge requests section' do - find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click - - expect(page).to have_selector('.merge-requests-feature', visible: false) - end - - context 'given project with merge_requests_disabled access level' do - let(:project) { create(:project, :merge_requests_disabled, namespace: user.namespace) } - - it 'hides merge requests section' do - expect(page).to have_selector('.merge-requests-feature', visible: false) - end - end - end - context 'builds select' do it 'hides builds select section' do find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .gl-toggle').click + visit project_settings_merge_requests_path(project) + expect(page).to have_selector('.builds-feature', visible: false) end @@ -55,6 +41,8 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do let(:project) { create(:project, :builds_disabled, namespace: user.namespace) } it 'hides builds select section' do + visit project_settings_merge_requests_path(project) + expect(page).to have_selector('.builds-feature', visible: false) end end diff --git a/spec/features/projects/settings/webhooks_settings_spec.rb b/spec/features/projects/settings/webhooks_settings_spec.rb index c84de7fc03f..d525544ac15 100644 --- a/spec/features/projects/settings/webhooks_settings_spec.rb +++ b/spec/features/projects/settings/webhooks_settings_spec.rb @@ -139,6 +139,12 @@ RSpec.describe 'Projects > Settings > Webhook Settings' do expect(page).to have_current_path(edit_project_hook_path(project, hook), ignore_query: true) end + + it 'does not show search settings on the hook log details' do + visit project_hook_hook_log_path(project, hook, hook_log) + + expect(page).not_to have_field(placeholder: 'Search settings', disabled: true) + end end end end diff --git a/spec/features/projects/show/user_interacts_with_stars_spec.rb b/spec/features/projects/show/user_interacts_with_stars_spec.rb index aa61b629d92..e0dd4f65010 100644 --- a/spec/features/projects/show/user_interacts_with_stars_spec.rb +++ b/spec/features/projects/show/user_interacts_with_stars_spec.rb @@ -14,14 +14,36 @@ RSpec.describe 'Projects > Show > User interacts with project stars' do end it 'toggles the star' do - find('.star-btn').click + star_project expect(page).to have_css('.star-count', text: 1) - find('.star-btn').click + unstar_project expect(page).to have_css('.star-count', text: 0) end + + it 'validates starring a project' do + project.add_owner(user) + + star_project + + visit(dashboard_projects_path) + + expect(page).to have_css('.stars', text: 1) + end + + it 'validates un-starring a project' do + project.add_owner(user) + + star_project + + unstar_project + + visit(dashboard_projects_path) + + expect(page).to have_css('.stars', text: 0) + end end context 'when user is not signed in' do @@ -38,3 +60,15 @@ RSpec.describe 'Projects > Show > User interacts with project stars' do end end end + +private + +def star_project + click_button(_('Star')) + wait_for_requests +end + +def unstar_project + click_button(_('Unstar')) + wait_for_requests +end diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb index fb2f0539558..1440db141a6 100644 --- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb +++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb @@ -39,7 +39,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do # The dropdown above the tree page.within('.repo-breadcrumb') do - find('.qa-add-to-tree').click # rubocop:disable QA/SelectorUsage + find('[data-testid="add-to-tree"]').click aggregate_failures 'dropdown links above the repo tree' do expect(page).to have_link('New file') @@ -71,7 +71,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do find_new_menu_toggle.click end - expect(page).not_to have_selector('.qa-add-to-tree') # rubocop:disable QA/SelectorUsage + expect(page).not_to have_selector('[data-testid="add-to-tree"]') expect(page).not_to have_link('Web IDE') end diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb index 89f6b4237a4..5056e245fed 100644 --- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb +++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb @@ -288,6 +288,17 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do end end + it 'no Auto DevOps button if builds feature is disabled' do + project.project_feature.update_attribute(:builds_access_level, ProjectFeature::DISABLED) + + visit project_path(project) + + page.within('.project-buttons') do + expect(page).not_to have_link('Enable Auto DevOps') + expect(page).not_to have_link('Auto DevOps enabled') + end + end + it 'no "Enable Auto DevOps" button when .gitlab-ci.yml already exists' do Files::CreateService.new( project, diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb index 074469a9b55..9c950cfee6e 100644 --- a/spec/features/projects/tree/create_directory_spec.rb +++ b/spec/features/projects/tree/create_directory_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'Multi-file editor new directory', :js do let(:project) { create(:project, :repository) } before do + stub_feature_flags(vscode_web_ide: false) + project.add_maintainer(user) sign_in(user) diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb index 85c644fa528..c0567ed4580 100644 --- a/spec/features/projects/tree/create_file_spec.rb +++ b/spec/features/projects/tree/create_file_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'Multi-file editor new file', :js do let(:project) { create(:project, :repository) } before do + stub_feature_flags(vscode_web_ide: false) + project.add_maintainer(user) sign_in(user) diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb index 163e347d03d..eb0ef756b30 100644 --- a/spec/features/projects/tree/tree_show_spec.rb +++ b/spec/features/projects/tree/tree_show_spec.rb @@ -26,7 +26,7 @@ RSpec.describe 'Projects tree', :js do expect(page).to have_selector('.tree-item') expect(page).to have_content('add tests for .gitattributes custom highlighting') expect(page).not_to have_selector('[data-testid="alert-danger"]') - expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage + expect(page).not_to have_selector('[data-testid="label-lfs"]', text: 'LFS') end it 'renders tree table for a subtree without errors' do @@ -35,7 +35,7 @@ RSpec.describe 'Projects tree', :js do expect(page).to have_selector('.tree-item') expect(page).to have_content('add spaces in whitespace file') - expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage + expect(page).not_to have_selector('[data-testid="label-lfs"]', text: 'LFS') expect(page).not_to have_selector('[data-testid="alert-danger"]') end @@ -112,11 +112,15 @@ RSpec.describe 'Projects tree', :js do it 'renders LFS badge on blob item' do visit project_tree_path(project, File.join('master', 'files/lfs')) - expect(page).to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage + expect(page).to have_selector('[data-testid="label-lfs"]', text: 'LFS') end end context 'web IDE' do + before do + stub_feature_flags(vscode_web_ide: false) + end + it 'opens folder in IDE' do visit project_tree_path(project, File.join('master', 'bar')) diff --git a/spec/features/projects/tree/upload_file_spec.rb b/spec/features/projects/tree/upload_file_spec.rb index ce00483bc91..f32141d6051 100644 --- a/spec/features/projects/tree/upload_file_spec.rb +++ b/spec/features/projects/tree/upload_file_spec.rb @@ -9,6 +9,8 @@ RSpec.describe 'Multi-file editor upload file', :js do let(:img_file) { File.join(Rails.root, 'spec', 'fixtures', 'dk.png') } before do + stub_feature_flags(vscode_web_ide: false) + project.add_maintainer(user) sign_in(user) diff --git a/spec/features/projects/user_sorts_projects_spec.rb b/spec/features/projects/user_sorts_projects_spec.rb index 7c970f7ee3d..b9b28398279 100644 --- a/spec/features/projects/user_sorts_projects_spec.rb +++ b/spec/features/projects/user_sorts_projects_spec.rb @@ -24,6 +24,7 @@ RSpec.describe 'User sorts projects and order persists' do end it "is set on the group_canonical_path" do + stub_feature_flags(group_overview_tabs_vue: false) visit(group_canonical_path(group)) within '[data-testid=group_sort_by_dropdown]' do @@ -32,6 +33,7 @@ RSpec.describe 'User sorts projects and order persists' do end it "is set on the details_group_path" do + stub_feature_flags(group_overview_tabs_vue: false) visit(details_group_path(group)) within '[data-testid=group_sort_by_dropdown]' do @@ -64,6 +66,7 @@ RSpec.describe 'User sorts projects and order persists' do context 'from group homepage', :js do before do + stub_feature_flags(group_overview_tabs_vue: false) sign_in(user) visit(group_canonical_path(group)) within '[data-testid=group_sort_by_dropdown]' do @@ -77,6 +80,7 @@ RSpec.describe 'User sorts projects and order persists' do context 'from group details', :js do before do + stub_feature_flags(group_overview_tabs_vue: false) sign_in(user) visit(details_group_path(group)) within '[data-testid=group_sort_by_dropdown]' do diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index d228fb084c3..cbd9340b737 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -418,8 +418,7 @@ RSpec.describe 'Project' do visit path end - it_behaves_like 'dirty submit form', [{ form: '.js-general-settings-form', input: 'input[name="project[name]"]' }, - { form: '.rspec-merge-request-settings', input: '#project_printing_merge_request_link_enabled' }] + it_behaves_like 'dirty submit form', [{ form: '.js-general-settings-form', input: 'input[name="project[name]"]' }] end describe 'view for a user without an access to a repo' do @@ -440,103 +439,6 @@ RSpec.describe 'Project' do end end - describe 'storage_enforcement_banner', :js do - let_it_be(:group) { create(:group) } - let_it_be_with_refind(:user) { create(:user) } - let_it_be(:project) { create(:project, group: group) } - - before do - group.add_maintainer(user) - sign_in(user) - end - - context 'with storage_enforcement_date set' do - let_it_be(:storage_enforcement_date) { Date.today + 30 } - - before do - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date) - end - end - - it 'displays the banner in the project page' do - visit project_path(project) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - - context 'when in a subgroup project page' do - let_it_be(:subgroup) { create(:group, parent: group) } - let_it_be(:project) { create(:project, namespace: subgroup) } - - it 'displays the banner' do - visit project_path(project) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - end - - context 'when in a user namespace project page' do - let_it_be(:project) { create(:project, namespace: user.namespace) } - - before do - allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace| - allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date) - end - end - - it 'displays the banner' do - visit project_path(project) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - end - - it 'does not display the banner in a paid group project page' do - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:paid?).and_return(true) - end - visit project_path(project) - expect_page_not_to_have_storage_enforcement_banner - end - - it 'does not display the banner if user has previously closed unless threshold has changed' do - visit project_path(project) - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - find('.js-storage-enforcement-banner [data-testid="close-icon"]').click - wait_for_requests - page.refresh - expect_page_not_to_have_storage_enforcement_banner - - storage_enforcement_date = Date.today + 13 - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date) - end - page.refresh - expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - end - end - - context 'with storage_enforcement_date not set' do - before do - allow_next_found_instance_of(Group) do |group| - allow(group).to receive(:storage_enforcement_date).and_return(nil) - end - end - - it 'does not display the banner in the group page' do - stub_feature_flags(namespace_storage_limit_bypass_date_check: false) - visit project_path(project) - expect_page_not_to_have_storage_enforcement_banner - end - end - end - - def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date) - expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply" - end - - def expect_page_not_to_have_storage_enforcement_banner - expect(page).not_to have_text "namespace storage limits will apply" - end - def remove_with_confirm(button_text, confirm_with, confirm_button_text = 'Confirm') click_button button_text fill_in 'confirm_name_input', with: confirm_with diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index 2600c00346e..482f3d62f36 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'Runners' do - let(:user) { create(:user) } + let_it_be(:user) { create(:user) } before do sign_in(user) @@ -24,25 +24,25 @@ RSpec.describe 'Runners' do end context 'when a project has enabled shared_runners' do - let(:project) { create(:project) } + let_it_be(:project) { create(:project) } before do project.add_maintainer(user) end context 'when a project_type runner is activated on the project' do - let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) } + let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) } it 'user sees the specific runner' do visit project_runners_path(project) within '.activated-specific-runners' do - expect(page).to have_content(specific_runner.display_name) + expect(page).to have_content(project_runner.display_name) end - click_on specific_runner.short_sha + click_on project_runner.short_sha - expect(page).to have_content(specific_runner.platform) + expect(page).to have_content(project_runner.platform) end it 'user can pause and resume the specific runner' do @@ -72,7 +72,7 @@ RSpec.describe 'Runners' do click_on 'Remove runner' end - expect(page).not_to have_content(specific_runner.display_name) + expect(page).not_to have_content(project_runner.display_name) end it 'user edits the runner to be protected' do @@ -92,7 +92,7 @@ RSpec.describe 'Runners' do context 'when a runner has a tag' do before do - specific_runner.update!(tag_list: ['tag']) + project_runner.update!(tag_list: ['tag']) end it 'user edits runner not to run untagged jobs' do @@ -120,24 +120,23 @@ RSpec.describe 'Runners' do expect(page.find('.available-shared-runners')).to have_content(shared_runner.display_name) end end - end - context 'when multiple runners are configured' do - let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) } - let!(:specific_runner_2) { create(:ci_runner, :project, projects: [project]) } + context 'when multiple runners are configured' do + let!(:project_runner_2) { create(:ci_runner, :project, projects: [project]) } - it 'adds pagination to the runner list' do - stub_const('Projects::Settings::CiCdController::NUMBER_OF_RUNNERS_PER_PAGE', 1) + it 'adds pagination to the runner list' do + stub_const('Projects::Settings::CiCdController::NUMBER_OF_RUNNERS_PER_PAGE', 1) - visit project_runners_path(project) + visit project_runners_path(project) - expect(find('.pagination')).not_to be_nil + expect(find('.pagination')).not_to be_nil + end end end context 'when a specific runner exists in another project' do let(:another_project) { create(:project) } - let!(:specific_runner) { create(:ci_runner, :project, projects: [another_project]) } + let!(:project_runner) { create(:ci_runner, :project, projects: [another_project]) } before do another_project.add_maintainer(user) @@ -150,13 +149,13 @@ RSpec.describe 'Runners' do click_on 'Enable for this project' end - expect(page.find('.activated-specific-runners')).to have_content(specific_runner.display_name) + expect(page.find('.activated-specific-runners')).to have_content(project_runner.display_name) within '.activated-specific-runners' do click_on 'Disable for this project' end - expect(page.find('.available-specific-runners')).to have_content(specific_runner.display_name) + expect(page.find('.available-specific-runners')).to have_content(project_runner.display_name) end end @@ -255,7 +254,8 @@ RSpec.describe 'Runners' do project.add_maintainer(user) end - let(:group) { create :group } + let_it_be(:group) { create :group } + let_it_be(:project) { create :project, group: group } context 'as project and group maintainer' do before do @@ -263,8 +263,6 @@ RSpec.describe 'Runners' do end context 'project with a group but no group runner' do - let(:project) { create :project, group: group } - it 'group runners are not available' do visit project_runners_path(project) @@ -280,8 +278,6 @@ RSpec.describe 'Runners' do end context 'project with a group but no group runner' do - let(:project) { create :project, group: group } - it 'group runners are available' do visit project_runners_path(project) @@ -304,44 +300,46 @@ RSpec.describe 'Runners' do end end - context 'project with a group but no group runner' do - let(:group) { create(:group) } - let(:project) { create(:project, group: group) } + context 'with group project' do + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } - it 'group runners are not available' do - visit project_runners_path(project) + context 'project with a group but no group runner' do + it 'group runners are not available' do + visit project_runners_path(project) - expect(page).to have_content 'This group does not have any group runners yet.' + expect(page).to have_content 'This group does not have any group runners yet.' - expect(page).not_to have_content 'To register them, go to the group\'s Runners page.' - expect(page).to have_content 'Ask your group owner to set up a group runner.' + expect(page).not_to have_content 'To register them, go to the group\'s Runners page.' + expect(page).to have_content 'Ask your group owner to set up a group runner.' + end end - end - context 'project with a group and a group runner' do - let(:group) { create(:group) } - let(:project) { create(:project, group: group) } - let!(:ci_runner) { create(:ci_runner, :group, groups: [group], description: 'group-runner') } + context 'project with a group and a group runner' do + let_it_be(:ci_runner) do + create(:ci_runner, :group, groups: [group], description: 'group-runner') + end - it 'group runners are available' do - visit project_runners_path(project) + it 'group runners are available' do + visit project_runners_path(project) - expect(page).to have_content 'Available group runners: 1' - expect(page).to have_content 'group-runner' - end + expect(page).to have_content 'Available group runners: 1' + expect(page).to have_content 'group-runner' + end - it 'group runners may be disabled for a project' do - visit project_runners_path(project) + it 'group runners may be disabled for a project' do + visit project_runners_path(project) - click_on 'Disable group runners' + click_on 'Disable group runners' - expect(page).to have_content 'Enable group runners' - expect(project.reload.group_runners_enabled).to be false + expect(page).to have_content 'Enable group runners' + expect(project.reload.group_runners_enabled).to be false - click_on 'Enable group runners' + click_on 'Enable group runners' - expect(page).to have_content 'Disable group runners' - expect(project.reload.group_runners_enabled).to be true + expect(page).to have_content 'Disable group runners' + expect(project.reload.group_runners_enabled).to be true + end end end end diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb index 53c95b4a446..e2c8708be78 100644 --- a/spec/features/search/user_searches_for_code_spec.rb +++ b/spec/features/search/user_searches_for_code_spec.rb @@ -69,8 +69,12 @@ RSpec.describe 'User searches for code' do expect(page).to have_selector('.results', text: expected_result) - find('.js-project-refs-dropdown').click - find('.dropdown-page-one .dropdown-content').click_link('v1.0.0') + find('.ref-selector').click + wait_for_requests + + page.within('.ref-selector') do + find('li', text: 'v1.0.0').click + end expect(page).to have_selector('.results', text: expected_result) @@ -96,36 +100,41 @@ RSpec.describe 'User searches for code' do end it 'shows ref switcher in code result summary' do - expect(find('.js-project-refs-dropdown')).to have_text(ref_name) + expect(find('.ref-selector')).to have_text(ref_name) end it 'persists branch name across search' do find('.gl-search-box-by-click-search-button').click - expect(find('.js-project-refs-dropdown')).to have_text(ref_name) + expect(find('.ref-selector')).to have_text(ref_name) end # this example is use to test the desgine that the refs is not # only repersent the branch as well as the tags. it 'ref swither list all the branchs and tags' do - find('.js-project-refs-dropdown').click - expect(find('.dropdown-page-one .dropdown-content')).to have_link('sha-starting-with-large-number') - expect(find('.dropdown-page-one .dropdown-content')).to have_link('v1.0.0') + find('.ref-selector').click + wait_for_requests + + page.within('.ref-selector') do + expect(page).to have_selector('li', text: 'add-ipython-files') + expect(page).to have_selector('li', text: 'v1.0.0') + end end it 'search result changes when refs switched' do + ref = 'master' expect(find('.results')).not_to have_content('path = gitlab-grack') - find('.js-project-refs-dropdown').click - find('.dropdown-page-one .dropdown-content').click_link('master') + find('.ref-selector').click + wait_for_requests - expect(page).to have_selector('.results', text: 'path = gitlab-grack') - end + page.within('.ref-selector') do + fill_in _('Search by Git revision'), with: ref + wait_for_requests + + find('li', text: ref).click + end - it 'persist refs over browser tabs' do - ref = 'feature' - find('.js-project-refs-dropdown').click - link = find_link(ref)[:href] - expect(link.include?("repository_ref=" + ref)).to be(true) + expect(page).to have_selector('.results', text: 'path = gitlab-grack') end end end @@ -146,36 +155,41 @@ RSpec.describe 'User searches for code' do end it 'shows ref switcher in code result summary' do - expect(find('.js-project-refs-dropdown')).to have_text(ref_name) + expect(find('.ref-selector')).to have_text(ref_name) end it 'persists branch name across search' do find('.gl-search-box-by-click-search-button').click - expect(find('.js-project-refs-dropdown')).to have_text(ref_name) + expect(find('.ref-selector')).to have_text(ref_name) end # this example is use to test the desgine that the refs is not # only repersent the branch as well as the tags. it 'ref swither list all the branchs and tags' do - find('.js-project-refs-dropdown').click - expect(find('.dropdown-page-one .dropdown-content')).to have_link('sha-starting-with-large-number') - expect(find('.dropdown-page-one .dropdown-content')).to have_link('v1.0.0') + find('.ref-selector').click + wait_for_requests + + page.within('.ref-selector') do + expect(page).to have_selector('li', text: 'add-ipython-files') + expect(page).to have_selector('li', text: 'v1.0.0') + end end it 'search result changes when refs switched' do + ref = 'master' expect(find('.results')).not_to have_content('path = gitlab-grack') - find('.js-project-refs-dropdown').click - find('.dropdown-page-one .dropdown-content').click_link('master') + find('.ref-selector').click + wait_for_requests - expect(page).to have_selector('.results', text: 'path = gitlab-grack') - end + page.within('.ref-selector') do + fill_in _('Search by Git revision'), with: ref + wait_for_requests + + find('li', text: ref).click + end - it 'persist refs over browser tabs' do - ref = 'feature' - find('.js-project-refs-dropdown').click - link = find_link(ref)[:href] - expect(link.include?("repository_ref=" + ref)).to be(true) + expect(page).to have_selector('.results', text: 'path = gitlab-grack') end end end @@ -187,12 +201,12 @@ RSpec.describe 'User searches for code' do submit_search('test') select_search_scope('Code') - expect(page).to have_selector('.js-project-refs-dropdown') + expect(page).to have_selector('.ref-selector') select_search_scope('Issues') expect(find(:css, '.results')).to have_link(issue.title) - expect(page).not_to have_selector('.js-project-refs-dropdown') + expect(page).not_to have_selector('.ref-selector') end end diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb index 1523586ab26..41288a34fb2 100644 --- a/spec/features/search/user_uses_header_search_field_spec.rb +++ b/spec/features/search/user_uses_header_search_field_spec.rb @@ -17,6 +17,7 @@ RSpec.describe 'User uses header search field', :js do end before do + allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).and_return(0) allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit).and_return(1000) allow(Gitlab::ApplicationRateLimiter).to receive(:threshold).with(:search_rate_limit_unauthenticated).and_return(1000) sign_in(user) diff --git a/spec/features/snippets/user_creates_snippet_spec.rb b/spec/features/snippets/user_creates_snippet_spec.rb index 628468a2abe..fd95516090a 100644 --- a/spec/features/snippets/user_creates_snippet_spec.rb +++ b/spec/features/snippets/user_creates_snippet_spec.rb @@ -80,7 +80,7 @@ RSpec.describe 'User creates snippet', :js do context 'when snippets default visibility level is restricted' do before do stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE], - default_snippet_visibility: Gitlab::VisibilityLevel::PRIVATE) + default_snippet_visibility: Gitlab::VisibilityLevel::PRIVATE) end it 'creates a snippet using the lowest available visibility level as default' do diff --git a/spec/features/tags/developer_creates_tag_spec.rb b/spec/features/tags/developer_creates_tag_spec.rb index b0219cb546d..ca76a94092e 100644 --- a/spec/features/tags/developer_creates_tag_spec.rb +++ b/spec/features/tags/developer_creates_tag_spec.rb @@ -60,7 +60,7 @@ RSpec.describe 'Developer creates tag' do it 'opens dropdown for ref', :js do click_link 'New tag' - ref_row = find('.form-group:nth-of-type(2) .col-sm-10') + ref_row = find('.form-group:nth-of-type(2) .col-sm-12') page.within ref_row do ref_input = find('[name="ref"]', visible: false) expect(ref_input.value).to eq 'master' diff --git a/spec/features/user_opens_link_to_comment_spec.rb b/spec/features/user_opens_link_to_comment_spec.rb index ae84f69f432..3fb1505ff5b 100644 --- a/spec/features/user_opens_link_to_comment_spec.rb +++ b/spec/features/user_opens_link_to_comment_spec.rb @@ -20,7 +20,7 @@ RSpec.describe 'User opens link to comment', :js do wait_for_requests - expect(page.find('#discussion-filter-dropdown')).to have_content('Show all activity') + expect(find('#discussion-preferences-dropdown')).to have_content('Sort or filter') expect(page).not_to have_content('Something went wrong while fetching comments') # Auto-switching to show all notes shouldn't be persisted diff --git a/spec/features/users/email_verification_on_login_spec.rb b/spec/features/users/email_verification_on_login_spec.rb index c8301c2fc91..f7102eaf9b7 100644 --- a/spec/features/users/email_verification_on_login_spec.rb +++ b/spec/features/users/email_verification_on_login_spec.rb @@ -118,7 +118,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting # Expect an error message expect_log_message('Failed Attempt', reason: 'rate_limited') expect(page).to have_content("You've reached the maximum amount of tries. "\ - 'Wait 10 minutes or resend a new code and try again.') + 'Wait 10 minutes or send a new code and try again.') # Wait for 10 minutes travel 10.minutes @@ -138,7 +138,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting # Expect an error message expect_log_message('Failed Attempt', reason: 'invalid') - expect(page).to have_content('The code is incorrect. Enter it again, or resend a new code.') + expect(page).to have_content('The code is incorrect. Enter it again, or send a new code.') end it 'verifies expired codes' do @@ -150,12 +150,12 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting code = expect_instructions_email_and_extract_code # Wait for the code to expire before verifying - travel VerifiesWithEmail::TOKEN_VALID_FOR_MINUTES.minutes + 1.second + travel Users::EmailVerification::ValidateTokenService::TOKEN_VALID_FOR_MINUTES.minutes + 1.second verify_code(code) # Expect an error message expect_log_message('Failed Attempt', reason: 'expired') - expect(page).to have_content('The code has expired. Resend a new code and try again.') + expect(page).to have_content('The code has expired. Send a new code and try again.') end end end @@ -255,7 +255,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting perform_enqueued_jobs do # The user is prompted for a verification code gitlab_sign_in(user) - expect(page).to have_content('Help us protect your account') + expect(page).to have_content(s_('IdentityVerification|Help us protect your account')) code = expect_instructions_email_and_extract_code # We toggle the feature flag off @@ -266,12 +266,13 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting new_code = expect_instructions_email_and_extract_code verify_code(code) - expect(page).to have_content('The code is incorrect. Enter it again, or resend a new code.') + expect(page) + .to have_content(s_('IdentityVerification|The code is incorrect. Enter it again, or send a new code.')) - travel VerifiesWithEmail::TOKEN_VALID_FOR_MINUTES.minutes + 1.second + travel Users::EmailVerification::ValidateTokenService::TOKEN_VALID_FOR_MINUTES.minutes + 1.second verify_code(new_code) - expect(page).to have_content('The code has expired. Resend a new code and try again.') + expect(page).to have_content(s_('IdentityVerification|The code has expired. Send a new code and try again.')) click_link 'Resend code' another_code = expect_instructions_email_and_extract_code @@ -296,7 +297,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting it 'the unlock link still works' do # The user is locked and unlock instructions are sent - expect(page).to have_content('Invalid login or password.') + expect(page).to have_content(_('Invalid login or password.')) user.reload expect(user.locked_at).not_to be_nil expect(user.unlock_token).not_to be_nil @@ -334,24 +335,24 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting def expect_instructions_email_and_extract_code mail = find_email_for(user) expect(mail.to).to match_array([user.email]) - expect(mail.subject).to eq('Verify your identity') - code = mail.body.parts.first.to_s[/\d{#{VerifiesWithEmail::TOKEN_LENGTH}}/o] + expect(mail.subject).to eq(s_('IdentityVerification|Verify your identity')) + code = mail.body.parts.first.to_s[/\d{#{Users::EmailVerification::GenerateTokenService::TOKEN_LENGTH}}/o] reset_delivered_emails! code end def verify_code(code) - fill_in 'Verification code', with: code - click_button 'Verify code' + fill_in s_('IdentityVerification|Verification code'), with: code + click_button s_('IdentityVerification|Verify code') end def expect_log_message(event = nil, times = 1, reason: '', message: nil) expect(Gitlab::AppLogger).to have_received(:info) .exactly(times).times .with(message || hash_including(message: 'Email Verification', - event: event, - username: user.username, - ip: '127.0.0.1', - reason: reason)) + event: event, + username: user.username, + ip: '127.0.0.1', + reason: reason)) end end diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index b875dbe1340..5ca5bd72b79 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -105,6 +105,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do before do stub_application_setting(send_user_confirmation_email: true) allow(User).to receive(:allow_unconfirmed_access_for).and_return grace_period + stub_feature_flags(identity_verification: false) end context 'within the grace period' do @@ -862,7 +863,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do context 'when the user already enabled 2FA' do before do user.update!(otp_required_for_login: true, - otp_secret: User.generate_otp_secret(32)) + otp_secret: User.generate_otp_secret(32)) end it 'asks the user to accept the terms' do @@ -954,6 +955,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do before do stub_application_setting(send_user_confirmation_email: true) stub_feature_flags(soft_email_confirmation: true) + stub_feature_flags(identity_verification: false) allow(User).to receive(:allow_unconfirmed_access_for).and_return grace_period end diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb index 068e1fd4243..bbf5882f89f 100644 --- a/spec/features/users/show_spec.rb +++ b/spec/features/users/show_spec.rb @@ -339,7 +339,7 @@ RSpec.describe 'User page' do subject - page.within '.navbar-nav' do + page.within '.navbar-gitlab' do expect(page).to have_link('Sign in') end end @@ -351,7 +351,7 @@ RSpec.describe 'User page' do subject - page.within '.navbar-nav' do + page.within '.navbar-gitlab' do expect(page).to have_link('Sign in / Register') end end diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb index f2381e41de8..de53e722603 100644 --- a/spec/features/users/signup_spec.rb +++ b/spec/features/users/signup_spec.rb @@ -66,6 +66,7 @@ RSpec.describe 'Signup' do flag_values = [true, false] flag_values.each do |val| before do + stub_feature_flags(arkose_labs_signup_challenge: false) stub_feature_flags(restyle_login_page: val) stub_application_setting(require_admin_approval_after_user_signup: false) end @@ -202,6 +203,7 @@ RSpec.describe 'Signup' do context 'when soft email confirmation is not enabled' do before do stub_feature_flags(soft_email_confirmation: false) + stub_feature_flags(identity_verification: false) end it 'creates the user account and sends a confirmation email, and pre-fills email address after confirming' do @@ -297,9 +299,8 @@ RSpec.describe 'Signup' do enforce_terms end - it 'renders text that the user confirms terms by clicking register' do + it 'renders text that the user confirms terms by signing in' do visit new_user_registration_path - expect(page).to have_content(/By clicking Register, I agree that I have read and accepted the Terms of Use and Privacy Policy/) fill_in_signup_form @@ -391,7 +392,7 @@ RSpec.describe 'Signup' do enforce_terms end - it 'renders text that the user confirms terms by clicking register' do + it 'renders text that the user confirms terms by signing in' do visit new_user_registration_path expect(page).to have_content(/By clicking Register, I agree that I have read and accepted the Terms of Use and Privacy Policy/) diff --git a/spec/features/work_items/work_item_children_spec.rb b/spec/features/work_items/work_item_children_spec.rb new file mode 100644 index 00000000000..95774680a2b --- /dev/null +++ b/spec/features/work_items/work_item_children_spec.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Work item children', :js do + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :public, namespace: group) } + let_it_be(:user) { create(:user) } + let_it_be(:issue) { create(:issue, project: project) } + + context 'for signed in user' do + before do + project.add_developer(user) + + sign_in(user) + + stub_feature_flags(work_items: true) + stub_feature_flags(work_items_hierarchy: true) + + visit project_issue_path(project, issue) + + wait_for_requests + end + + it 'are not displayed when issue does not have work item children', :aggregate_failures do + page.within('[data-testid="work-item-links"]') do + expect(find('[data-testid="links-empty"]')).to have_content(_('No tasks are currently assigned.')) + expect(page).not_to have_selector('[data-testid="add-links-form"]') + expect(page).not_to have_selector('[data-testid="links-child"]') + end + end + + it 'toggles widget body', :aggregate_failures do + page.within('[data-testid="work-item-links"]') do + expect(page).to have_selector('[data-testid="links-body"]') + + click_button 'Collapse tasks' + + expect(page).not_to have_selector('[data-testid="links-body"]') + + click_button 'Expand tasks' + + expect(page).to have_selector('[data-testid="links-body"]') + end + end + + it 'toggles form', :aggregate_failures do + page.within('[data-testid="work-item-links"]') do + expect(page).not_to have_selector('[data-testid="add-links-form"]') + + click_button 'Add' + + expect(page).to have_selector('[data-testid="add-links-form"]') + + click_button 'Cancel' + + expect(page).not_to have_selector('[data-testid="add-links-form"]') + end + end + + it 'addss a child task', :aggregate_failures do + page.within('[data-testid="work-item-links"]') do + click_button 'Add' + + expect(page).to have_button('Create task', disabled: true) + fill_in 'Add a title', with: 'Task 1' + + expect(page).to have_button('Create task', disabled: false) + + click_button 'Create task' + + wait_for_all_requests + + expect(find('[data-testid="links-child"]')).to have_content('Task 1') + end + end + + it 'removes a child task and undoing', :aggregate_failures do + page.within('[data-testid="work-item-links"]') do + click_button 'Add' + fill_in 'Add a title', with: 'Task 1' + click_button 'Create task' + wait_for_all_requests + + expect(find('[data-testid="links-child"]')).to have_content('Task 1') + expect(find('[data-testid="children-count"]')).to have_content('1') + + find('[data-testid="links-menu"]').click + click_button 'Remove' + + wait_for_all_requests + + expect(page).not_to have_content('Task 1') + expect(find('[data-testid="children-count"]')).to have_content('0') + end + + page.within('.gl-toast') do + expect(find('.toast-body')).to have_content(_('Child removed')) + find('.b-toaster a', text: 'Undo').click + end + + wait_for_all_requests + + page.within('[data-testid="work-item-links"]') do + expect(find('[data-testid="links-child"]')).to have_content('Task 1') + expect(find('[data-testid="children-count"]')).to have_content('1') + end + end + end +end |