diff --git a/ee/spec/features/operations_nav_link_spec.rb b/ee/spec/features/operations_nav_link_spec.rb index e04472e9b2cf26472f35ea93613c10bff7d89d2b..3500891d277bd047ff05fb1e64f23043af7e1223 100644 --- a/ee/spec/features/operations_nav_link_spec.rb +++ b/ee/spec/features/operations_nav_link_spec.rb @@ -6,22 +6,50 @@ RSpec.describe 'Operations dropdown navbar EE' do let(:user) { create(:user) } let(:project) { create(:project) } - before do - stub_feature_flags(combined_menu: false) + shared_examples 'combined_menu: feature flag examples' do + before do + project.add_maintainer(user) + sign_in(user) - project.add_maintainer(user) - sign_in(user) + stub_licensed_features(operations_dashboard: true) - stub_licensed_features(operations_dashboard: true) + visit project_issues_path(project) + end - visit project_issues_path(project) + it 'has an `Operations` link' do + pending_on_combined_menu_flag + + expect(page).to have_link('Operations', href: operations_path) + end + + it 'has an `Environments` link' do + pending_on_combined_menu_flag + + expect(page).to have_link('Environments', href: operations_environments_path) + end end - it 'has an `Operations` link' do - expect(page).to have_link('Operations', href: operations_path) + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } + + before do + stub_feature_flags(combined_menu: true) + end + + it_behaves_like 'combined_menu: feature flag examples' + end + + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } + + before do + stub_feature_flags(combined_menu: false) + end + + it_behaves_like 'combined_menu: feature flag examples' end - it 'has an `Environments` link' do - expect(page).to have_link('Environments', href: operations_environments_path) + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on end end diff --git a/spec/features/admin/admin_mode/logout_spec.rb b/spec/features/admin/admin_mode/logout_spec.rb index 8cfac5d8b99d06bf056f2e10682668869c2694c1..664eb51e58f57875548681ad97799e86234d5876 100644 --- a/spec/features/admin/admin_mode/logout_spec.rb +++ b/spec/features/admin/admin_mode/logout_spec.rb @@ -8,37 +8,67 @@ RSpec.describe 'Admin Mode Logout', :js do let(:user) { create(:admin) } - before do - stub_feature_flags(combined_menu: false) + shared_examples 'combined_menu: feature flag examples' do + before do + gitlab_sign_in(user) + gitlab_enable_admin_mode_sign_in(user) + visit admin_root_path + end - gitlab_sign_in(user) - gitlab_enable_admin_mode_sign_in(user) - visit admin_root_path - end + it 'disable removes admin mode and redirects to root page' do + pending_on_combined_menu_flag - it 'disable removes admin mode and redirects to root page' do - gitlab_disable_admin_mode + gitlab_disable_admin_mode - expect(current_path).to eq root_path - expect(page).to have_link(href: new_admin_session_path) - end + expect(current_path).to eq root_path + expect(page).to have_link(href: new_admin_session_path) + end + + it 'disable shows flash notice' do + pending_on_combined_menu_flag + + gitlab_disable_admin_mode + + expect(page).to have_selector('.flash-notice') + end - it 'disable shows flash notice' do - gitlab_disable_admin_mode + context 'on a read-only instance' do + before do + allow(Gitlab::Database).to receive(:read_only?).and_return(true) + end - expect(page).to have_selector('.flash-notice') + it 'disable removes admin mode and redirects to root page' do + pending_on_combined_menu_flag + + gitlab_disable_admin_mode + + expect(current_path).to eq root_path + expect(page).to have_link(href: new_admin_session_path) + end + end end - context 'on a read-only instance' do + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } + before do - allow(Gitlab::Database).to receive(:read_only?).and_return(true) + stub_feature_flags(combined_menu: true) end - it 'disable removes admin mode and redirects to root page' do - gitlab_disable_admin_mode + it_behaves_like 'combined_menu: feature flag examples' + end - expect(current_path).to eq root_path - expect(page).to have_link(href: new_admin_session_path) + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } + + before do + stub_feature_flags(combined_menu: false) end + + it_behaves_like 'combined_menu: feature flag examples' + end + + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on end end diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb index 633de20c82dc476c3890d53d51193d767c16c1d0..8d4c563e7d49cac3a35021c5b6b930f540363c8f 100644 --- a/spec/features/admin/admin_mode_spec.rb +++ b/spec/features/admin/admin_mode_spec.rb @@ -8,55 +8,43 @@ RSpec.describe 'Admin mode' do let(:admin) { create(:admin) } - before do - stub_feature_flags(combined_menu: false) - - stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - end - - context 'application setting :admin_mode is enabled', :request_store do + shared_examples 'combined_menu: feature flag examples' do before do - sign_in(admin) + stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') end - context 'when not in admin mode' do - it 'has no leave admin mode button' do - visit new_admin_session_path - - page.within('.navbar-sub-nav') do - expect(page).not_to have_link(href: destroy_admin_session_path) - end + context 'application setting :admin_mode is enabled', :request_store do + before do + sign_in(admin) end - it 'can open pages not in admin scope' do - visit new_admin_session_path - - page.within('.navbar-sub-nav') do - find_all('a', text: 'Projects').first.click - end + context 'when not in admin mode' do + it 'has no leave admin mode button' do + pending_on_combined_menu_flag - expect(page).to have_current_path(dashboard_projects_path) - end + visit new_admin_session_path - it 'is necessary to provide credentials again before opening pages in admin scope' do - visit general_admin_application_settings_path # admin logged out because not in admin_mode + page.within('.navbar-sub-nav') do + expect(page).not_to have_link(href: destroy_admin_session_path) + end + end - expect(page).to have_current_path(new_admin_session_path) - end + it 'can open pages not in admin scope' do + pending_on_combined_menu_flag - it 'can enter admin mode' do - visit new_admin_session_path + visit new_admin_session_path - fill_in 'user_password', with: admin.password + page.within('.navbar-sub-nav') do + find_all('a', text: 'Projects').first.click + end - click_button 'Enter Admin Mode' + expect(page).to have_current_path(dashboard_projects_path) + end - expect(page).to have_current_path(admin_root_path) - end + it 'is necessary to provide credentials again before opening pages in admin scope' do + visit general_admin_application_settings_path # admin logged out because not in admin_mode - context 'on a read-only instance' do - before do - allow(Gitlab::Database).to receive(:read_only?).and_return(true) + expect(page).to have_current_path(new_admin_session_path) end it 'can enter admin mode' do @@ -68,108 +56,163 @@ RSpec.describe 'Admin mode' do expect(page).to have_current_path(admin_root_path) end - end - end - context 'when in admin_mode' do - before do - gitlab_enable_admin_mode_sign_in(admin) - end + context 'on a read-only instance' do + before do + allow(Gitlab::Database).to receive(:read_only?).and_return(true) + end - it 'contains link to leave admin mode' do - page.within('.navbar-sub-nav') do - expect(page).to have_link(href: destroy_admin_session_path) + it 'can enter admin mode' do + visit new_admin_session_path + + fill_in 'user_password', with: admin.password + + click_button 'Enter Admin Mode' + + expect(page).to have_current_path(admin_root_path) + end end end - it 'can leave admin mode using main dashboard link', :js do - page.within('.navbar-sub-nav') do - click_on 'Leave Admin Mode' + context 'when in admin_mode' do + before do + gitlab_enable_admin_mode_sign_in(admin) + end + + it 'contains link to leave admin mode' do + pending_on_combined_menu_flag - expect(page).to have_link(href: new_admin_session_path) + page.within('.navbar-sub-nav') do + expect(page).to have_link(href: destroy_admin_session_path) + end end - end - it 'can leave admin mode using dropdown menu on smaller screens', :js do - resize_screen_xs - visit root_dashboard_path + it 'can leave admin mode using main dashboard link', :js do + pending_on_combined_menu_flag + + page.within('.navbar-sub-nav') do + click_on 'Leave Admin Mode' - find('.header-more').click + expect(page).to have_link(href: new_admin_session_path) + end + end - page.within '.navbar-sub-nav' do - click_on 'Leave Admin Mode' + it 'can leave admin mode using dropdown menu on smaller screens', :js do + pending_on_combined_menu_flag + + resize_screen_xs + visit root_dashboard_path find('.header-more').click - expect(page).to have_link(href: new_admin_session_path) - end - end + page.within '.navbar-sub-nav' do + click_on 'Leave Admin Mode' - it 'can open pages not in admin scope' do - page.within('.navbar-sub-nav') do - find_all('a', text: 'Projects').first.click + find('.header-more').click - expect(page).to have_current_path(dashboard_projects_path) + expect(page).to have_link(href: new_admin_session_path) + end end - end - context 'nav bar' do - it 'shows admin dashboard links on bigger screen' do - visit root_dashboard_path + it 'can open pages not in admin scope' do + pending_on_combined_menu_flag + + page.within('.navbar-sub-nav') do + find_all('a', text: 'Projects').first.click - page.within '.navbar' do - expect(page).to have_link(text: 'Admin Area', href: admin_root_path, visible: true) - expect(page).to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true) + expect(page).to have_current_path(dashboard_projects_path) end end - it 'relocates admin dashboard links to dropdown list on smaller screen', :js do - resize_screen_xs - visit root_dashboard_path + context 'nav bar' do + it 'shows admin dashboard links on bigger screen' do + pending_on_combined_menu_flag - page.within '.navbar' do - expect(page).not_to have_link(text: 'Admin Area', href: admin_root_path, visible: true) - expect(page).not_to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true) + visit root_dashboard_path + + page.within '.navbar' do + expect(page).to have_link(text: 'Admin Area', href: admin_root_path, visible: true) + expect(page).to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true) + end end - find('.header-more').click + it 'relocates admin dashboard links to dropdown list on smaller screen', :js do + pending_on_combined_menu_flag + + resize_screen_xs + visit root_dashboard_path - page.within '.navbar' do - expect(page).to have_link(text: 'Admin Area', href: admin_root_path, visible: true) - expect(page).to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true) + page.within '.navbar' do + expect(page).not_to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true) + end + + find('.header-more').click + + page.within '.navbar' do + expect(page).to have_link(text: 'Admin Area', href: admin_root_path, visible: true) + expect(page).to have_link(text: 'Leave Admin Mode', href: destroy_admin_session_path, visible: true) + end end end - end - context 'on a read-only instance' do - before do - allow(Gitlab::Database).to receive(:read_only?).and_return(true) - end + context 'on a read-only instance' do + before do + allow(Gitlab::Database).to receive(:read_only?).and_return(true) + end - it 'can leave admin mode', :js do - page.within('.navbar-sub-nav') do - click_on 'Leave Admin Mode' + it 'can leave admin mode', :js do + pending_on_combined_menu_flag - expect(page).to have_link(href: new_admin_session_path) + page.within('.navbar-sub-nav') do + click_on 'Leave Admin Mode' + + expect(page).to have_link(href: new_admin_session_path) + end end end end end + + context 'application setting :admin_mode is disabled' do + before do + stub_application_setting(admin_mode: false) + sign_in(admin) + end + + it 'shows no admin mode buttons in navbar' do + pending_on_combined_menu_flag + + visit admin_root_path + + page.within('.navbar-sub-nav') do + expect(page).not_to have_link(href: new_admin_session_path) + expect(page).not_to have_link(href: destroy_admin_session_path) + end + end + end end - context 'application setting :admin_mode is disabled' do + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } + before do - stub_application_setting(admin_mode: false) - sign_in(admin) + stub_feature_flags(combined_menu: true) end - it 'shows no admin mode buttons in navbar' do - visit admin_root_path + it_behaves_like 'combined_menu: feature flag examples' + end - page.within('.navbar-sub-nav') do - expect(page).not_to have_link(href: new_admin_session_path) - expect(page).not_to have_link(href: destroy_admin_session_path) - end + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } + + before do + stub_feature_flags(combined_menu: false) end + + it_behaves_like 'combined_menu: feature flag examples' + end + + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on end end diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb index 3a532cb41614aa0425375f2f7b963e01c70a66bb..a1fb0beda700514efb5174f59572e69a2c43febb 100644 --- a/spec/features/dashboard/active_tab_spec.rb +++ b/spec/features/dashboard/active_tab_spec.rb @@ -3,30 +3,56 @@ require 'spec_helper' RSpec.describe 'Dashboard Active Tab', :js do - before do - stub_feature_flags(combined_menu: false) + shared_examples 'combined_menu: feature flag examples' do + before do + sign_in(create(:user)) + end - sign_in(create(:user)) - end + shared_examples 'page has active tab' do |title| + it "#{title} tab" do + pending_on_combined_menu_flag + + subject - shared_examples 'page has active tab' do |title| - it "#{title} tab" do - subject + expect(page).to have_selector('.navbar-sub-nav li.active', count: 1) + expect(find('.navbar-sub-nav li.active')).to have_content(title) + end + end + + context 'on dashboard projects' do + it_behaves_like 'page has active tab', 'Projects' do + subject { visit dashboard_projects_path } + end + end - expect(page).to have_selector('.navbar-sub-nav li.active', count: 1) - expect(find('.navbar-sub-nav li.active')).to have_content(title) + context 'on dashboard groups' do + it_behaves_like 'page has active tab', 'Groups' do + subject { visit dashboard_groups_path } + end end end - context 'on dashboard projects' do - it_behaves_like 'page has active tab', 'Projects' do - subject { visit dashboard_projects_path } + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } + + before do + stub_feature_flags(combined_menu: true) end + + it_behaves_like 'combined_menu: feature flag examples' end - context 'on dashboard groups' do - it_behaves_like 'page has active tab', 'Groups' do - subject { visit dashboard_groups_path } + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } + + before do + stub_feature_flags(combined_menu: false) end + + it_behaves_like 'combined_menu: feature flag examples' + end + + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on end end diff --git a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb index 179d9d0990561adcfbe60c511876e9e38ea537df..0620f819332462a2be1ce64db32912b0b442a592 100644 --- a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb +++ b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb @@ -7,36 +7,64 @@ RSpec.describe 'The group dashboard' do let(:user) { create(:user) } - before do - stub_feature_flags(combined_menu: false) + shared_examples 'combined_menu: feature flag examples' do + before do + sign_in user + end - sign_in user - end + describe 'The top navigation' do + it 'has all the expected links' do + pending_on_combined_menu_flag - describe 'The top navigation' do - it 'has all the expected links' do - visit dashboard_groups_path + visit dashboard_groups_path - within('.navbar') do - expect(page).to have_button('Projects') - expect(page).to have_button('Groups') - expect(page).to have_link('Activity') - expect(page).to have_link('Milestones') - expect(page).to have_link('Snippets') + within('.navbar') do + expect(page).to have_button('Projects') + expect(page).to have_button('Groups') + expect(page).to have_link('Activity') + expect(page).to have_link('Milestones') + expect(page).to have_link('Snippets') + end end - end - it 'hides some links when an external authorization service is enabled' do - enable_external_authorization_service_check - visit dashboard_groups_path + it 'hides some links when an external authorization service is enabled' do + pending_on_combined_menu_flag + + enable_external_authorization_service_check + visit dashboard_groups_path - within('.navbar') do - expect(page).to have_button('Projects') - expect(page).to have_button('Groups') - expect(page).not_to have_link('Activity') - expect(page).not_to have_link('Milestones') - expect(page).to have_link('Snippets') + within('.navbar') do + expect(page).to have_button('Projects') + expect(page).to have_button('Groups') + expect(page).not_to have_link('Activity') + expect(page).not_to have_link('Milestones') + expect(page).to have_link('Snippets') + end end end end + + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } + + before do + stub_feature_flags(combined_menu: true) + end + + it_behaves_like 'combined_menu: feature flag examples' + end + + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } + + before do + stub_feature_flags(combined_menu: false) + end + + it_behaves_like 'combined_menu: feature flag examples' + end + + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on + end end diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb index e96a60b2ab2db816fea99a717f6e8b3524faece5..5f60832dbc9c6d1de2737ee9d78f69d31902ae76 100644 --- a/spec/features/dashboard/shortcuts_spec.rb +++ b/spec/features/dashboard/shortcuts_spec.rb @@ -3,71 +3,97 @@ require 'spec_helper' RSpec.describe 'Dashboard shortcuts', :js do - before do - stub_feature_flags(combined_menu: false) - end + shared_examples 'combined_menu: feature flag examples' do + context 'logged in' do + let(:user) { create(:user) } + let(:project) { create(:project) } - context 'logged in' do - let(:user) { create(:user) } - let(:project) { create(:project) } + before do + project.add_developer(user) + sign_in(user) + visit root_dashboard_path + end - before do - project.add_developer(user) - sign_in(user) - visit root_dashboard_path - end + it 'navigate to tabs' do + pending_on_combined_menu_flag - it 'navigate to tabs' do - find('body').send_keys([:shift, 'I']) + find('body').send_keys([:shift, 'I']) - check_page_title('Issues') + check_page_title('Issues') - find('body').send_keys([:shift, 'M']) + find('body').send_keys([:shift, 'M']) - check_page_title('Merge requests') + check_page_title('Merge requests') - find('body').send_keys([:shift, 'T']) + find('body').send_keys([:shift, 'T']) - check_page_title('To-Do List') + check_page_title('To-Do List') - find('body').send_keys([:shift, 'G']) + find('body').send_keys([:shift, 'G']) - check_page_title('Groups') + check_page_title('Groups') - find('body').send_keys([:shift, 'P']) + find('body').send_keys([:shift, 'P']) - check_page_title('Projects') + check_page_title('Projects') - find('body').send_keys([:shift, 'A']) + find('body').send_keys([:shift, 'A']) - check_page_title('Activity') + check_page_title('Activity') + end end - end - context 'logged out' do - before do - visit explore_root_path + context 'logged out' do + before do + visit explore_root_path + end + + it 'navigate to tabs' do + pending_on_combined_menu_flag + + find('body').send_keys([:shift, 'G']) + + find('.nothing-here-block') + expect(page).to have_content('No public groups') + + find('body').send_keys([:shift, 'S']) + + find('.nothing-here-block') + expect(page).to have_content('No snippets found') + + find('body').send_keys([:shift, 'P']) + + find('.nothing-here-block') + expect(page).to have_content('Explore public groups to find projects to contribute to.') + end end - it 'navigate to tabs' do - find('body').send_keys([:shift, 'G']) + def check_page_title(title) + expect(find('.page-title')).to have_content(title) + end + end - find('.nothing-here-block') - expect(page).to have_content('No public groups') + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } - find('body').send_keys([:shift, 'S']) + before do + stub_feature_flags(combined_menu: true) + end - find('.nothing-here-block') - expect(page).to have_content('No snippets found') + it_behaves_like 'combined_menu: feature flag examples' + end - find('body').send_keys([:shift, 'P']) + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } - find('.nothing-here-block') - expect(page).to have_content('Explore public groups to find projects to contribute to.') + before do + stub_feature_flags(combined_menu: false) end + + it_behaves_like 'combined_menu: feature flag examples' end - def check_page_title(title) - expect(find('.page-title')).to have_content(title) + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on end end diff --git a/spec/features/frequently_visited_projects_and_groups_spec.rb b/spec/features/frequently_visited_projects_and_groups_spec.rb index 6c25afdf6d4ebcfcfaef2b58947d62af0d47d710..9110c7ad65a2399c132e7d14de939551b3e49504 100644 --- a/spec/features/frequently_visited_projects_and_groups_spec.rb +++ b/spec/features/frequently_visited_projects_and_groups_spec.rb @@ -5,45 +5,73 @@ require 'spec_helper' RSpec.describe 'Frequently visited items', :js do let_it_be(:user) { create(:user) } - before do - stub_feature_flags(combined_menu: false) + shared_examples 'combined_menu: feature flag examples' do + before do + sign_in(user) + end - sign_in(user) - end + context 'for projects' do + let_it_be(:project) { create(:project, :public) } - context 'for projects' do - let_it_be(:project) { create(:project, :public) } + it 'increments localStorage counter when visiting the project' do + pending_on_combined_menu_flag - it 'increments localStorage counter when visiting the project' do - visit project_path(project) + visit project_path(project) - frequent_projects = nil + frequent_projects = nil - wait_for('localStorage frequent-projects') do - frequent_projects = page.evaluate_script("localStorage['#{user.username}/frequent-projects']") + wait_for('localStorage frequent-projects') do + frequent_projects = page.evaluate_script("localStorage['#{user.username}/frequent-projects']") - frequent_projects.present? - end + frequent_projects.present? + end - expect(Gitlab::Json.parse(frequent_projects)).to contain_exactly(a_hash_including('id' => project.id, 'frequency' => 1)) + expect(Gitlab::Json.parse(frequent_projects)).to contain_exactly(a_hash_including('id' => project.id, 'frequency' => 1)) + end end - end - context 'for groups' do - let_it_be(:group) { create(:group, :public) } + context 'for groups' do + let_it_be(:group) { create(:group, :public) } - it 'increments localStorage counter when visiting the group' do - visit group_path(group) + it 'increments localStorage counter when visiting the group' do + pending_on_combined_menu_flag - frequent_groups = nil + visit group_path(group) - wait_for('localStorage frequent-groups') do - frequent_groups = page.evaluate_script("localStorage['#{user.username}/frequent-groups']") + frequent_groups = nil - frequent_groups.present? + wait_for('localStorage frequent-groups') do + frequent_groups = page.evaluate_script("localStorage['#{user.username}/frequent-groups']") + + frequent_groups.present? + end + + expect(Gitlab::Json.parse(frequent_groups)).to contain_exactly(a_hash_including('id' => group.id, 'frequency' => 1)) end + end + end - expect(Gitlab::Json.parse(frequent_groups)).to contain_exactly(a_hash_including('id' => group.id, 'frequency' => 1)) + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } + + before do + stub_feature_flags(combined_menu: true) end + + it_behaves_like 'combined_menu: feature flag examples' + end + + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } + + before do + stub_feature_flags(combined_menu: false) + end + + it_behaves_like 'combined_menu: feature flag examples' + end + + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on end end diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb index ba28338cae3520957bb1c11721ae0490ddd56ee8..a1523f9eb089c0b785798e7e56ee29859840e9fd 100644 --- a/spec/features/projects/new_project_spec.rb +++ b/spec/features/projects/new_project_spec.rb @@ -5,50 +5,48 @@ require 'spec_helper' RSpec.describe 'New project', :js do include Select2Helper - context 'as a user' do - let(:user) { create(:user) } + shared_examples 'combined_menu: feature flag examples' do + context 'as a user' do + let(:user) { create(:user) } - before do - sign_in(user) - end - - context 'new repo experiment', :experiment do - it 'when in control renders "project"' do - stub_experiments(new_repo: :control) + before do + sign_in(user) + end - visit new_project_path + context 'new repo experiment', :experiment do + it 'when in control renders "project"' do + stub_experiments(new_repo: :control) - find('li.header-new.dropdown').click + visit new_project_path - page.within('li.header-new.dropdown') do - expect(page).to have_selector('a', text: 'New project') - expect(page).to have_no_selector('a', text: 'New project/repository') - end + find('li.header-new.dropdown').click - expect(page).to have_selector('h3', text: 'Create blank project') - expect(page).to have_no_selector('h3', text: 'Create blank project/repository') - end + page.within('li.header-new.dropdown') do + expect(page).to have_selector('a', text: 'New project') + expect(page).to have_no_selector('a', text: 'New project/repository') + end - it 'when in candidate renders "project/repository"' do - stub_experiments(new_repo: :candidate) + expect(page).to have_selector('h3', text: 'Create blank project') + expect(page).to have_no_selector('h3', text: 'Create blank project/repository') + end - visit new_project_path + it 'when in candidate renders "project/repository"' do + stub_experiments(new_repo: :candidate) - find('li.header-new.dropdown').click + visit new_project_path - page.within('li.header-new.dropdown') do - expect(page).to have_selector('a', text: 'New project/repository') - end + find('li.header-new.dropdown').click - expect(page).to have_selector('h3', text: 'Create blank project/repository') - end + page.within('li.header-new.dropdown') do + expect(page).to have_selector('a', text: 'New project/repository') + end - context 'with combined_menu feature disabled' do - before do - stub_feature_flags(combined_menu: false) + expect(page).to have_selector('h3', text: 'Create blank project/repository') end it 'when in control it renders "project" in the new projects dropdown' do + pending_on_combined_menu_flag + stub_experiments(new_repo: :control) visit new_project_path @@ -64,6 +62,8 @@ RSpec.describe 'New project', :js do end it 'when in candidate it renders "project/repository" in the new projects dropdown' do + pending_on_combined_menu_flag + stub_experiments(new_repo: :candidate) visit new_project_path @@ -76,347 +76,373 @@ RSpec.describe 'New project', :js do end end end - end - it 'shows a message if multiple levels are restricted' do - Gitlab::CurrentSettings.update!( - restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL] - ) + it 'shows a message if multiple levels are restricted' do + Gitlab::CurrentSettings.update!( + restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL] + ) - visit new_project_path - find('[data-qa-selector="blank_project_link"]').click - - expect(page).to have_content 'Other visibility settings have been disabled by the administrator.' - end + visit new_project_path + find('[data-qa-selector="blank_project_link"]').click - it 'shows a message if all levels are restricted' do - Gitlab::CurrentSettings.update!( - restricted_visibility_levels: Gitlab::VisibilityLevel.values - ) + expect(page).to have_content 'Other visibility settings have been disabled by the administrator.' + end - visit new_project_path - find('[data-qa-selector="blank_project_link"]').click + it 'shows a message if all levels are restricted' do + Gitlab::CurrentSettings.update!( + restricted_visibility_levels: Gitlab::VisibilityLevel.values + ) - expect(page).to have_content 'Visibility settings have been disabled by the administrator.' - end - end - - context 'as an admin' do - let(:user) { create(:admin) } + visit new_project_path + find('[data-qa-selector="blank_project_link"]').click - before do - sign_in(user) + expect(page).to have_content 'Visibility settings have been disabled by the administrator.' + end end - it 'shows "New project" page', :js do - visit new_project_path - find('[data-qa-selector="blank_project_link"]').click - - expect(page).to have_content('Project name') - expect(page).to have_content('Project URL') - expect(page).to have_content('Project slug') - - click_link('New project') - find('[data-qa-selector="import_project_link"]').click + context 'as an admin' do + let(:user) { create(:admin) } - expect(page).to have_link('GitHub') - expect(page).to have_link('Bitbucket') - expect(page).to have_link('GitLab.com') - expect(page).to have_button('Repo by URL') - expect(page).to have_link('GitLab export') - end - - describe 'manifest import option' do before do + sign_in(user) + end + + it 'shows "New project" page', :js do visit new_project_path + find('[data-qa-selector="blank_project_link"]').click - find('[data-qa-selector="import_project_link"]').click - end + expect(page).to have_content('Project name') + expect(page).to have_content('Project URL') + expect(page).to have_content('Project slug') - it { expect(page).to have_link('Manifest file') } - end + click_link('New project') + find('[data-qa-selector="import_project_link"]').click - context 'Visibility level selector', :js do - Gitlab::VisibilityLevel.options.each do |key, level| - it "sets selector to #{key}" do - stub_application_setting(default_project_visibility: level) + expect(page).to have_link('GitHub') + expect(page).to have_link('Bitbucket') + expect(page).to have_link('GitLab.com') + expect(page).to have_button('Repo by URL') + expect(page).to have_link('GitLab export') + end + describe 'manifest import option' do + before do visit new_project_path - find('[data-qa-selector="blank_project_link"]').click - page.within('#blank-project-pane') do - expect(find_field("project_visibility_level_#{level}")).to be_checked - end - end - it "saves visibility level #{level} on validation error" do - visit new_project_path - find('[data-qa-selector="blank_project_link"]').click + find('[data-qa-selector="import_project_link"]').click + end - choose(key) - click_button('Create project') - page.within('#blank-project-pane') do - expect(find_field("project_visibility_level_#{level}")).to be_checked - end + it 'has Manifest file' do + expect(page).to have_link('Manifest file') end end - context 'when group visibility is private but default is internal' do - let_it_be(:group) { create(:group, visibility_level: Gitlab::VisibilityLevel::PRIVATE) } + context 'Visibility level selector', :js do + Gitlab::VisibilityLevel.options.each do |key, level| + it "sets selector to #{key}" do + stub_application_setting(default_project_visibility: level) - before do - stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL) - end + visit new_project_path + find('[data-qa-selector="blank_project_link"]').click + page.within('#blank-project-pane') do + expect(find_field("project_visibility_level_#{level}")).to be_checked + end + end - context 'when admin mode is enabled', :enable_admin_mode do - it 'has private selected' do - visit new_project_path(namespace_id: group.id) + it "saves visibility level #{level} on validation error" do + visit new_project_path find('[data-qa-selector="blank_project_link"]').click + choose(key) + click_button('Create project') page.within('#blank-project-pane') do - expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked + expect(find_field("project_visibility_level_#{level}")).to be_checked end end end - context 'when admin mode is disabled' do - it 'is not allowed' do - visit new_project_path(namespace_id: group.id) + context 'when group visibility is private but default is internal' do + let_it_be(:group) { create(:group, visibility_level: Gitlab::VisibilityLevel::PRIVATE) } - expect(page).to have_content('Not Found') + before do + stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL) end - end - end - context 'when group visibility is public but user requests private' do - let_it_be(:group) { create(:group, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + context 'when admin mode is enabled', :enable_admin_mode do + it 'has private selected' do + visit new_project_path(namespace_id: group.id) + find('[data-qa-selector="blank_project_link"]').click - before do - stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL) - end + page.within('#blank-project-pane') do + expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked + end + end + end - context 'when admin mode is enabled', :enable_admin_mode do - it 'has private selected' do - visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE }) - find('[data-qa-selector="blank_project_link"]').click + context 'when admin mode is disabled' do + it 'is not allowed' do + visit new_project_path(namespace_id: group.id) - page.within('#blank-project-pane') do - expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked + expect(page).to have_content('Not Found') end end end - context 'when admin mode is disabled' do - it 'is not allowed' do - visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE }) + context 'when group visibility is public but user requests private' do + let_it_be(:group) { create(:group, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - expect(page).to have_content('Not Found') + before do + stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL) end - end - end - end - context 'Readme selector' do - it 'shows the initialize with Readme checkbox on "Blank project" tab' do - visit new_project_path - find('[data-qa-selector="blank_project_link"]').click + context 'when admin mode is enabled', :enable_admin_mode do + it 'has private selected' do + visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE }) + find('[data-qa-selector="blank_project_link"]').click - expect(page).to have_css('input#project_initialize_with_readme') - expect(page).to have_content('Initialize repository with a README') - end + page.within('#blank-project-pane') do + expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked + end + end + end - it 'does not show the initialize with Readme checkbox on "Create from template" tab' do - visit new_project_path - find('[data-qa-selector="create_from_template_link"]').click - first('.choose-template').click + context 'when admin mode is disabled' do + it 'is not allowed' do + visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE }) - page.within '.project-fields-form' do - expect(page).not_to have_css('input#project_initialize_with_readme') - expect(page).not_to have_content('Initialize repository with a README') + expect(page).to have_content('Not Found') + end + end end end - it 'does not show the initialize with Readme checkbox on "Import project" tab' do - visit new_project_path - find('[data-qa-selector="import_project_link"]').click - first('.js-import-git-toggle-button').click + context 'Readme selector' do + it 'shows the initialize with Readme checkbox on "Blank project" tab' do + visit new_project_path + find('[data-qa-selector="blank_project_link"]').click - page.within '#import-project-pane' do - expect(page).not_to have_css('input#project_initialize_with_readme') - expect(page).not_to have_content('Initialize repository with a README') + expect(page).to have_css('input#project_initialize_with_readme') + expect(page).to have_content('Initialize repository with a README') end - end - end - context 'Namespace selector' do - context 'with user namespace' do - before do + it 'does not show the initialize with Readme checkbox on "Create from template" tab' do visit new_project_path - find('[data-qa-selector="blank_project_link"]').click + find('[data-qa-selector="create_from_template_link"]').click + first('.choose-template').click + + page.within '.project-fields-form' do + expect(page).not_to have_css('input#project_initialize_with_readme') + expect(page).not_to have_content('Initialize repository with a README') + end end - it 'selects the user namespace' do - page.within('#blank-project-pane') do - expect(page).to have_select('project[namespace_id]', visible: false, selected: user.username) + it 'does not show the initialize with Readme checkbox on "Import project" tab' do + visit new_project_path + find('[data-qa-selector="import_project_link"]').click + first('.js-import-git-toggle-button').click + + page.within '#import-project-pane' do + expect(page).not_to have_css('input#project_initialize_with_readme') + expect(page).not_to have_content('Initialize repository with a README') end end end - context 'with group namespace' do - let(:group) { create(:group, :private) } + context 'Namespace selector' do + context 'with user namespace' do + before do + visit new_project_path + find('[data-qa-selector="blank_project_link"]').click + end - before do - group.add_owner(user) - visit new_project_path(namespace_id: group.id) - find('[data-qa-selector="blank_project_link"]').click + it 'selects the user namespace' do + page.within('#blank-project-pane') do + expect(page).to have_select('project[namespace_id]', visible: false, selected: user.username) + end + end end - it 'selects the group namespace' do - page.within('#blank-project-pane') do - expect(page).to have_select('project[namespace_id]', visible: false, selected: group.name) + context 'with group namespace' do + let(:group) { create(:group, :private) } + + before do + group.add_owner(user) + visit new_project_path(namespace_id: group.id) + find('[data-qa-selector="blank_project_link"]').click + end + + it 'selects the group namespace' do + page.within('#blank-project-pane') do + expect(page).to have_select('project[namespace_id]', visible: false, selected: group.name) + end end end - end - context 'with subgroup namespace' do - let(:group) { create(:group) } - let(:subgroup) { create(:group, parent: group) } + context 'with subgroup namespace' do + let(:group) { create(:group) } + let(:subgroup) { create(:group, parent: group) } - before do - group.add_maintainer(user) - visit new_project_path(namespace_id: subgroup.id) - find('[data-qa-selector="blank_project_link"]').click - end + before do + group.add_maintainer(user) + visit new_project_path(namespace_id: subgroup.id) + find('[data-qa-selector="blank_project_link"]').click + end - it 'selects the group namespace' do - page.within('#blank-project-pane') do - expect(page).to have_select('project[namespace_id]', visible: false, selected: subgroup.full_path) + it 'selects the group namespace' do + page.within('#blank-project-pane') do + expect(page).to have_select('project[namespace_id]', visible: false, selected: subgroup.full_path) + end end end - end - context 'when changing namespaces dynamically', :js do - let(:public_group) { create(:group, :public) } - let(:internal_group) { create(:group, :internal) } - let(:private_group) { create(:group, :private) } + context 'when changing namespaces dynamically', :js do + let(:public_group) { create(:group, :public) } + let(:internal_group) { create(:group, :internal) } + let(:private_group) { create(:group, :private) } - before do - public_group.add_owner(user) - internal_group.add_owner(user) - private_group.add_owner(user) - visit new_project_path(namespace_id: public_group.id) - find('[data-qa-selector="blank_project_link"]').click - end + before do + public_group.add_owner(user) + internal_group.add_owner(user) + private_group.add_owner(user) + visit new_project_path(namespace_id: public_group.id) + find('[data-qa-selector="blank_project_link"]').click + end - it 'enables the correct visibility options' do - select2(user.namespace_id, from: '#project_namespace_id') - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).not_to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).not_to be_disabled - - select2(public_group.id, from: '#project_namespace_id') - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).not_to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).not_to be_disabled - - select2(internal_group.id, from: '#project_namespace_id') - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).not_to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).to be_disabled - - select2(private_group.id, from: '#project_namespace_id') - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).to be_disabled - expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).to be_disabled + it 'enables the correct visibility options' do + select2(user.namespace_id, from: '#project_namespace_id') + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).not_to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).not_to be_disabled + + select2(public_group.id, from: '#project_namespace_id') + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).not_to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).not_to be_disabled + + select2(internal_group.id, from: '#project_namespace_id') + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).not_to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).to be_disabled + + select2(private_group.id, from: '#project_namespace_id') + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).not_to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::INTERNAL}")).to be_disabled + expect(find("#project_visibility_level_#{Gitlab::VisibilityLevel::PUBLIC}")).to be_disabled + end end end - end - - context 'Import project options', :js do - before do - visit new_project_path - find('[data-qa-selector="import_project_link"]').click - end - context 'from git repository url, "Repo by URL"' do + context 'Import project options', :js do before do - first('.js-import-git-toggle-button').click + visit new_project_path + find('[data-qa-selector="import_project_link"]').click end - it 'does not autocomplete sensitive git repo URL' do - autocomplete = find('#project_import_url')['autocomplete'] + context 'from git repository url, "Repo by URL"' do + before do + first('.js-import-git-toggle-button').click + end - expect(autocomplete).to eq('off') - end + it 'does not autocomplete sensitive git repo URL' do + autocomplete = find('#project_import_url')['autocomplete'] - it 'shows import instructions' do - git_import_instructions = first('.js-toggle-content') + expect(autocomplete).to eq('off') + end - expect(git_import_instructions).to be_visible - expect(git_import_instructions).to have_content 'Git repository URL' - end + it 'shows import instructions' do + git_import_instructions = first('.js-toggle-content') - it 'reports error if repo URL does not end with .git' do - fill_in 'project_import_url', with: 'http://foo/bar' - fill_in 'project_name', with: 'import-project-without-git-suffix' - fill_in 'project_path', with: 'import-project-without-git-suffix' + expect(git_import_instructions).to be_visible + expect(git_import_instructions).to have_content 'Git repository URL' + end - click_button 'Create project' + it 'reports error if repo URL does not end with .git' do + fill_in 'project_import_url', with: 'http://foo/bar' + fill_in 'project_name', with: 'import-project-without-git-suffix' + fill_in 'project_path', with: 'import-project-without-git-suffix' - expect(page).to have_text('Please provide a valid URL ending with .git') - end + click_button 'Create project' - it 'keeps "Import project" tab open after form validation error' do - collision_project = create(:project, name: 'test-name-collision', namespace: user.namespace) + expect(page).to have_text('Please provide a valid URL ending with .git') + end - fill_in 'project_import_url', with: collision_project.http_url_to_repo - fill_in 'project_name', with: collision_project.name + it 'keeps "Import project" tab open after form validation error' do + collision_project = create(:project, name: 'test-name-collision', namespace: user.namespace) - click_on 'Create project' + fill_in 'project_import_url', with: collision_project.http_url_to_repo + fill_in 'project_name', with: collision_project.name - expect(page).to have_css('#import-project-pane.active') - expect(page).not_to have_css('.toggle-import-form.hide') - end - end + click_on 'Create project' - context 'from GitHub' do - before do - first('.js-import-github').click + expect(page).to have_css('#import-project-pane.active') + expect(page).not_to have_css('.toggle-import-form.hide') + end end - it 'shows import instructions' do - expect(page).to have_content('Authenticate with GitHub') - expect(current_path).to eq new_import_github_path - end - end + context 'from GitHub' do + before do + first('.js-import-github').click + end - context 'from manifest file' do - before do - first('.import_manifest').click + it 'shows import instructions' do + expect(page).to have_content('Authenticate with GitHub') + expect(current_path).to eq new_import_github_path + end end - it 'shows import instructions' do - expect(page).to have_content('Manifest file import') - expect(current_path).to eq new_import_manifest_path + context 'from manifest file' do + before do + first('.import_manifest').click + end + + it 'shows import instructions' do + expect(page).to have_content('Manifest file import') + expect(current_path).to eq new_import_manifest_path + end end end - end - context 'Namespace selector' do - context 'with group with DEVELOPER_MAINTAINER_PROJECT_ACCESS project_creation_level' do - let(:group) { create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) } + context 'Namespace selector' do + context 'with group with DEVELOPER_MAINTAINER_PROJECT_ACCESS project_creation_level' do + let(:group) { create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) } - before do - group.add_developer(user) - visit new_project_path(namespace_id: group.id) - find('[data-qa-selector="blank_project_link"]').click - end + before do + group.add_developer(user) + visit new_project_path(namespace_id: group.id) + find('[data-qa-selector="blank_project_link"]').click + end - it 'selects the group namespace' do - page.within('#blank-project-pane') do - expect(page).to have_select('project[namespace_id]', visible: false, selected: group.full_path) + it 'selects the group namespace' do + page.within('#blank-project-pane') do + expect(page).to have_select('project[namespace_id]', visible: false, selected: group.full_path) + end end end end end end + + context 'with combined_menu: feature flag on' do + let(:needs_rewrite_for_combined_menu_flag_on) { true } + + before do + stub_feature_flags(combined_menu: true) + end + + it_behaves_like 'combined_menu: feature flag examples' + end + + context 'with combined_menu feature flag off' do + let(:needs_rewrite_for_combined_menu_flag_on) { false } + + before do + stub_feature_flags(combined_menu: false) + end + + it_behaves_like 'combined_menu: feature flag examples' + end + + def pending_on_combined_menu_flag + pending 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587' if needs_rewrite_for_combined_menu_flag_on + end end