diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-09 00:09:31 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-09 00:09:31 +0300 |
commit | d3fb07d5b10b01e24f33298252d854fc2c149786 (patch) | |
tree | 4b50c5ea23a08dc91c5adac4cec89f547b88f828 /spec | |
parent | 70b375c29f67bdc8bd7e8ade1d5355444106482d (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/features/admin/admin_appearance_spec.rb | 231 | ||||
-rw-r--r-- | spec/features/admin/admin_mode/login_spec.rb | 342 | ||||
-rw-r--r-- | spec/features/users/login_spec.rb | 4 | ||||
-rw-r--r-- | spec/features/users/signup_spec.rb | 459 | ||||
-rw-r--r-- | spec/frontend/ide/lib/common/model_manager_spec.js | 4 | ||||
-rw-r--r-- | spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js | 72 | ||||
-rw-r--r-- | spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js | 192 | ||||
-rw-r--r-- | spec/frontend/pipeline_editor/pipeline_editor_home_spec.js | 6 | ||||
-rw-r--r-- | spec/graphql/types/ci/group_variable_type_spec.rb | 2 | ||||
-rw-r--r-- | spec/graphql/types/ci/instance_variable_type_spec.rb | 2 | ||||
-rw-r--r-- | spec/graphql/types/ci/project_variable_type_spec.rb | 2 | ||||
-rw-r--r-- | spec/graphql/types/ci/variable_interface_spec.rb | 2 | ||||
-rw-r--r-- | spec/helpers/application_helper_spec.rb | 8 | ||||
-rw-r--r-- | spec/requests/projects/merge_requests_discussions_spec.rb | 18 | ||||
-rw-r--r-- | spec/views/devise/sessions/new.html.haml_spec.rb | 94 |
15 files changed, 666 insertions, 772 deletions
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb index ec0399e0ee3..b297d92b2fa 100644 --- a/spec/features/admin/admin_appearance_spec.rb +++ b/spec/features/admin/admin_appearance_spec.rb @@ -6,161 +6,168 @@ RSpec.describe 'Admin Appearance' do let!(:appearance) { create(:appearance) } let(:admin) { create(:admin) } - it 'create new appearance' do - sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) - visit admin_application_settings_appearances_path - - fill_in 'appearance_title', with: 'MyCompany' - fill_in 'appearance_description', with: 'dev server' - fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines' - fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines' - click_button 'Update appearance settings' - - expect(page).to have_current_path admin_application_settings_appearances_path, ignore_query: true - expect(page).to have_content 'Appearance' - - expect(page).to have_field('appearance_title', with: 'MyCompany') - expect(page).to have_field('appearance_description', with: 'dev server') - expect(page).to have_field('appearance_new_project_guidelines', with: 'Custom project guidelines') - expect(page).to have_field('appearance_profile_image_guidelines', with: 'Custom profile image guidelines') - expect(page).to have_content 'Last edit' - end + flag_values = [true, false] + flag_values.each do |val| + before do + stub_feature_flags(restyle_login_page: val) + end - it 'preview sign-in page appearance' do - sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + it 'create new appearance' do + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) + visit admin_application_settings_appearances_path - visit admin_application_settings_appearances_path - click_link "Sign-in page" + fill_in 'appearance_title', with: 'MyCompany' + fill_in 'appearance_description', with: 'dev server' + fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines' + fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines' + click_button 'Update appearance settings' - expect(find('#login')).to be_disabled - expect(find('#password')).to be_disabled - expect(find('button')).to be_disabled + expect(page).to have_current_path admin_application_settings_appearances_path, ignore_query: true + expect(page).to have_content 'Appearance' - expect_custom_sign_in_appearance(appearance) - end + expect(page).to have_field('appearance_title', with: 'MyCompany') + expect(page).to have_field('appearance_description', with: 'dev server') + expect(page).to have_field('appearance_new_project_guidelines', with: 'Custom project guidelines') + expect(page).to have_field('appearance_profile_image_guidelines', with: 'Custom profile image guidelines') + expect(page).to have_content 'Last edit' + end - it 'preview new project page appearance', :js do - sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) + it 'preview sign-in page appearance' do + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) - visit admin_application_settings_appearances_path - click_link "New project page" + visit admin_application_settings_appearances_path + click_link "Sign-in page" - expect_custom_new_project_appearance(appearance) - end + expect(find('#login')).to be_disabled + expect(find('#password')).to be_disabled + expect(find('button')).to be_disabled - context 'Custom system header and footer' do - before do + expect_custom_sign_in_appearance(appearance) + end + + it 'preview new project page appearance', :js do sign_in(admin) gitlab_enable_admin_mode_sign_in(admin) - end - context 'when system header and footer messages are empty' do - it 'shows custom system header and footer fields' do - visit admin_application_settings_appearances_path + visit admin_application_settings_appearances_path + click_link "New project page" - expect(page).to have_field('appearance_header_message', with: '') - expect(page).to have_field('appearance_footer_message', with: '') - expect(page).to have_field('appearance_message_background_color') - expect(page).to have_field('appearance_message_font_color') - end + expect_custom_new_project_appearance(appearance) end - context 'when system header and footer messages are not empty' do + context 'Custom system header and footer' do before do - appearance.update!(header_message: 'Foo', footer_message: 'Bar') + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) end - it 'shows custom system header and footer fields' do - visit admin_application_settings_appearances_path + context 'when system header and footer messages are empty' do + it 'shows custom system header and footer fields' do + visit admin_application_settings_appearances_path - expect(page).to have_field('appearance_header_message', with: appearance.header_message) - expect(page).to have_field('appearance_footer_message', with: appearance.footer_message) - expect(page).to have_field('appearance_message_background_color') - expect(page).to have_field('appearance_message_font_color') + expect(page).to have_field('appearance_header_message', with: '') + expect(page).to have_field('appearance_footer_message', with: '') + expect(page).to have_field('appearance_message_background_color') + expect(page).to have_field('appearance_message_font_color') + end end - end - end - it 'custom sign-in page' do - visit new_user_session_path + context 'when system header and footer messages are not empty' do + before do + appearance.update!(header_message: 'Foo', footer_message: 'Bar') + end - expect_custom_sign_in_appearance(appearance) - end + it 'shows custom system header and footer fields' do + visit admin_application_settings_appearances_path - it 'custom new project page', :js do - sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) - visit new_project_path - click_link 'Create blank project' + expect(page).to have_field('appearance_header_message', with: appearance.header_message) + expect(page).to have_field('appearance_footer_message', with: appearance.footer_message) + expect(page).to have_field('appearance_message_background_color') + expect(page).to have_field('appearance_message_font_color') + end + end + end - expect_custom_new_project_appearance(appearance) - end + it 'custom sign-in page' do + visit new_user_session_path - context 'Profile page with custom profile image guidelines' do - before do + expect_custom_sign_in_appearance(appearance) + end + + it 'custom new project page', :js do sign_in(admin) gitlab_enable_admin_mode_sign_in(admin) - visit admin_application_settings_appearances_path - fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!' - click_button 'Update appearance settings' + visit new_project_path + click_link 'Create blank project' + + expect_custom_new_project_appearance(appearance) end - it 'renders guidelines when set' do - sign_in create(:user) - visit profile_path + context 'Profile page with custom profile image guidelines' do + before do + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) + visit admin_application_settings_appearances_path + fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!' + click_button 'Update appearance settings' + end + + it 'renders guidelines when set' do + sign_in create(:user) + visit profile_path - expect(page).to have_content 'Custom profile image guidelines, please 😄!' + expect(page).to have_content 'Custom profile image guidelines, please 😄!' + end end - end - it 'appearance logo' do - sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) - visit admin_application_settings_appearances_path + it 'appearance logo' do + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) + visit admin_application_settings_appearances_path - attach_file(:appearance_logo, logo_fixture) - click_button 'Update appearance settings' - expect(page).to have_css(logo_selector) + attach_file(:appearance_logo, logo_fixture) + click_button 'Update appearance settings' + expect(page).to have_css(logo_selector) - click_link 'Remove logo' - expect(page).not_to have_css(logo_selector) - end + click_link 'Remove logo' + expect(page).not_to have_css(logo_selector) + end - it 'header logos' do - sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) - visit admin_application_settings_appearances_path + it 'header logos' do + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) + visit admin_application_settings_appearances_path - attach_file(:appearance_header_logo, logo_fixture) - click_button 'Update appearance settings' - expect(page).to have_css(header_logo_selector) + attach_file(:appearance_header_logo, logo_fixture) + click_button 'Update appearance settings' + expect(page).to have_css(header_logo_selector) - click_link 'Remove header logo' - expect(page).not_to have_css(header_logo_selector) - end + click_link 'Remove header logo' + expect(page).not_to have_css(header_logo_selector) + end - it 'Favicon' do - sign_in(admin) - gitlab_enable_admin_mode_sign_in(admin) - visit admin_application_settings_appearances_path + it 'Favicon' do + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) + visit admin_application_settings_appearances_path - attach_file(:appearance_favicon, logo_fixture) - click_button 'Update appearance settings' + attach_file(:appearance_favicon, logo_fixture) + click_button 'Update appearance settings' - expect(page).to have_css('.appearance-light-logo-preview') + expect(page).to have_css('.appearance-light-logo-preview') - click_link 'Remove favicon' + click_link 'Remove favicon' - expect(page).not_to have_css('.appearance-light-logo-preview') + expect(page).not_to have_css('.appearance-light-logo-preview') - # allowed file types - attach_file(:appearance_favicon, Rails.root.join('spec', 'fixtures', 'sanitized.svg')) - click_button 'Update appearance settings' + # allowed file types + attach_file(:appearance_favicon, Rails.root.join('spec', 'fixtures', 'sanitized.svg')) + click_button 'Update appearance settings' - expect(page).to have_content 'Favicon You are not allowed to upload "svg" files, allowed types: png, ico' + expect(page).to have_content 'Favicon You are not allowed to upload "svg" files, allowed types: png, ico' + end end def expect_custom_sign_in_appearance(appearance) diff --git a/spec/features/admin/admin_mode/login_spec.rb b/spec/features/admin/admin_mode/login_spec.rb index a16adaf6076..6b4c9adb096 100644 --- a/spec/features/admin/admin_mode/login_spec.rb +++ b/spec/features/admin/admin_mode/login_spec.rb @@ -13,248 +13,252 @@ RSpec.describe 'Admin Mode Login' do click_button 'Verify code' end - context 'with valid username/password' do - let(:user) { create(:admin, :two_factor) } - - context 'using one-time code' do - it 'blocks login if we reuse the same code immediately' do - gitlab_sign_in(user, remember: true) - - expect(page).to have_content('Two-Factor Authentication') - - repeated_otp = user.current_otp - enter_code(repeated_otp) - gitlab_enable_admin_mode_sign_in(user) - - expect(page).to have_content('Two-Factor Authentication') - - enter_code(repeated_otp) - - expect(page).to have_current_path admin_session_path, ignore_query: true - expect(page).to have_content('Invalid two-factor code') - end + flag_values = [true, false] + flag_values.each do |val| + before do + stub_feature_flags(restyle_login_page: val) + end + context 'with valid username/password' do + let(:user) { create(:admin, :two_factor) } - context 'not re-using codes' do - before do + context 'using one-time code' do + it 'blocks login if we reuse the same code immediately' do gitlab_sign_in(user, remember: true) expect(page).to have_content('Two-Factor Authentication') - enter_code(user.current_otp) + repeated_otp = user.current_otp + enter_code(repeated_otp) gitlab_enable_admin_mode_sign_in(user) expect(page).to have_content('Two-Factor Authentication') - end - it 'allows login with valid code' do - # Cannot reuse the TOTP - travel_to(30.seconds.from_now) do - enter_code(user.current_otp) + enter_code(repeated_otp) - expect(page).to have_current_path admin_root_path, ignore_query: true - expect(page).to have_content('Admin mode enabled') - end - end - - it 'blocks login with invalid code' do - # Cannot reuse the TOTP - travel_to(30.seconds.from_now) do - enter_code('foo') - - expect(page).to have_content('Invalid two-factor code') - end + expect(page).to have_current_path admin_session_path, ignore_query: true + expect(page).to have_content('Invalid two-factor code') end - it 'allows login with invalid code, then valid code' do - # Cannot reuse the TOTP - travel_to(30.seconds.from_now) do - enter_code('foo') + context 'not re-using codes' do + before do + gitlab_sign_in(user, remember: true) - expect(page).to have_content('Invalid two-factor code') + expect(page).to have_content('Two-factor authentication code') enter_code(user.current_otp) + gitlab_enable_admin_mode_sign_in(user) - expect(page).to have_current_path admin_root_path, ignore_query: true - expect(page).to have_content('Admin mode enabled') + expect(page).to have_content('Two-Factor Authentication') end - end - context 'using backup code' do - let(:codes) { user.generate_otp_backup_codes! } + it 'allows login with valid code' do + # Cannot reuse the TOTP + travel_to(30.seconds.from_now) do + enter_code(user.current_otp) - before do - expect(codes.size).to eq 10 + expect(page).to have_current_path admin_root_path, ignore_query: true + expect(page).to have_content('Admin mode enabled') + end + end + + it 'blocks login with invalid code' do + # Cannot reuse the TOTP + travel_to(30.seconds.from_now) do + enter_code('foo') - # Ensure the generated codes get saved - user.save! + expect(page).to have_content('Invalid two-factor code') + end end - context 'with valid code' do - it 'allows login' do - enter_code(codes.sample) + it 'allows login with invalid code, then valid code' do + # Cannot reuse the TOTP + travel_to(30.seconds.from_now) do + enter_code('foo') + + expect(page).to have_content('Invalid two-factor code') + + enter_code(user.current_otp) expect(page).to have_current_path admin_root_path, ignore_query: true expect(page).to have_content('Admin mode enabled') end - - it 'invalidates the used code' do - expect { enter_code(codes.sample) } - .to change { user.reload.otp_backup_codes.size }.by(-1) - end end - context 'with invalid code' do - it 'blocks login' do - code = codes.sample - expect(user.invalidate_otp_backup_code!(code)).to eq true + context 'using backup code' do + let(:codes) { user.generate_otp_backup_codes! } + + before do + expect(codes.size).to eq 10 + # Ensure the generated codes get saved user.save! - expect(user.reload.otp_backup_codes.size).to eq 9 + end + + context 'with valid code' do + it 'allows login' do + enter_code(codes.sample) - enter_code(code) + expect(page).to have_current_path admin_root_path, ignore_query: true + expect(page).to have_content('Admin mode enabled') + end - expect(page).to have_content('Invalid two-factor code.') + it 'invalidates the used code' do + expect { enter_code(codes.sample) } + .to change { user.reload.otp_backup_codes.size }.by(-1) + end end - end - end - end - end - context 'when logging in via omniauth' do - let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: 'my-uid', provider: 'saml', password_automatically_set: false) } - let(:mock_saml_response) do - File.read('spec/fixtures/authentication/saml_response.xml') - end + context 'with invalid code' do + it 'blocks login' do + code = codes.sample + expect(user.invalidate_otp_backup_code!(code)).to eq true + + user.save! + expect(user.reload.otp_backup_codes.size).to eq 9 + + enter_code(code) - before do - stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], - providers: [mock_saml_config_with_upstream_two_factor_authn_contexts]) + expect(page).to have_content('Invalid two-factor code.') + end + end + end + end end - context 'when authn_context is worth two factors' do + context 'when logging in via omniauth' do + let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: 'my-uid', provider: 'saml', password_automatically_set: false) } let(:mock_saml_response) do File.read('spec/fixtures/authentication/saml_response.xml') - .gsub('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', - 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS') end - it 'signs user in without prompting for second factor' do - sign_in_using_saml! - - expect(page).not_to have_content('Two-Factor Authentication') - - enable_admin_mode_using_saml! - - expect(page).not_to have_content('Two-Factor Authentication') - expect(page).to have_current_path admin_root_path, ignore_query: true - expect(page).to have_content('Admin mode enabled') + before do + stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config_with_upstream_two_factor_authn_contexts]) end - end - context 'when two factor authentication is required' do - it 'shows 2FA prompt after omniauth login' do - sign_in_using_saml! - - expect(page).to have_content('Two-Factor Authentication') - enter_code(user.current_otp) + context 'when authn_context is worth two factors' do + let(:mock_saml_response) do + File.read('spec/fixtures/authentication/saml_response.xml') + .gsub('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', + 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS') + end - enable_admin_mode_using_saml! + it 'signs user in without prompting for second factor' do + sign_in_using_saml! - expect(page).to have_content('Two-Factor Authentication') + expect(page).not_to have_content('Two-Factor Authentication') - # Cannot reuse the TOTP - travel_to(30.seconds.from_now) do - enter_code(user.current_otp) + enable_admin_mode_using_saml! + expect(page).not_to have_content('Two-Factor Authentication') expect(page).to have_current_path admin_root_path, ignore_query: true expect(page).to have_content('Admin mode enabled') end end - end - def sign_in_using_saml! - gitlab_sign_in_via('saml', user, 'my-uid', mock_saml_response) - end + context 'when two factor authentication is required' do + it 'shows 2FA prompt after omniauth login' do + sign_in_using_saml! - def enable_admin_mode_using_saml! - gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', mock_saml_response) - end - end + expect(page).to have_content('Two-Factor Authentication') + enter_code(user.current_otp) - context 'when logging in via ldap' do - let(:uid) { 'my-uid' } - let(:provider_label) { 'Main LDAP' } - let(:provider_name) { 'main' } - let(:provider) { "ldap#{provider_name}" } - let(:ldap_server_config) do - { - 'label' => provider_label, - 'provider_name' => provider, - 'attributes' => {}, - 'encryption' => 'plain', - 'uid' => 'uid', - 'base' => 'dc=example,dc=com' - } - end + enable_admin_mode_using_saml! + + expect(page).to have_content('Two-Factor Authentication') - let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: uid, provider: provider) } + # Cannot reuse the TOTP + travel_to(30.seconds.from_now) do + enter_code(user.current_otp) - before do - setup_ldap(provider, user, uid, ldap_server_config) + expect(page).to have_current_path admin_root_path, ignore_query: true + expect(page).to have_content('Admin mode enabled') + end + end + end + + def sign_in_using_saml! + gitlab_sign_in_via('saml', user, 'my-uid', mock_saml_response) + end + + def enable_admin_mode_using_saml! + gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', mock_saml_response) + end end - context 'when two factor authentication is required' do - it 'shows 2FA prompt after ldap login' do - sign_in_using_ldap!(user, provider_label) + context 'when logging in via ldap' do + let(:uid) { 'my-uid' } + let(:provider_label) { 'Main LDAP' } + let(:provider_name) { 'main' } + let(:provider) { "ldap#{provider_name}" } + let(:ldap_server_config) do + { + 'label' => provider_label, + 'provider_name' => provider, + 'attributes' => {}, + 'encryption' => 'plain', + 'uid' => 'uid', + 'base' => 'dc=example,dc=com' + } + end - expect(page).to have_content('Two-Factor Authentication') + let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: uid, provider: provider) } - enter_code(user.current_otp) - enable_admin_mode_using_ldap!(user) + before do + setup_ldap(provider, user, uid, ldap_server_config) + end - expect(page).to have_content('Two-Factor Authentication') + context 'when two factor authentication is required' do + it 'shows 2FA prompt after ldap login' do + sign_in_using_ldap!(user, provider_label) + expect(page).to have_content('Two-Factor Authentication') - # Cannot reuse the TOTP - travel_to(30.seconds.from_now) do enter_code(user.current_otp) + enable_admin_mode_using_ldap!(user) - expect(page).to have_current_path admin_root_path, ignore_query: true - expect(page).to have_content('Admin mode enabled') + expect(page).to have_content('Two-Factor Authentication') + + # Cannot reuse the TOTP + travel_to(30.seconds.from_now) do + enter_code(user.current_otp) + + expect(page).to have_current_path admin_root_path, ignore_query: true + expect(page).to have_content('Admin mode enabled') + end end end - end - def setup_ldap(provider, user, uid, ldap_server_config) - stub_ldap_setting(enabled: true) + def setup_ldap(provider, user, uid, ldap_server_config) + stub_ldap_setting(enabled: true) - allow(::Gitlab::Auth::Ldap::Config).to receive_messages(enabled: true, servers: [ldap_server_config]) - allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [provider.to_sym]) + allow(::Gitlab::Auth::Ldap::Config).to receive_messages(enabled: true, servers: [ldap_server_config]) + allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [provider.to_sym]) - Ldap::OmniauthCallbacksController.define_providers! - Rails.application.reload_routes! + Ldap::OmniauthCallbacksController.define_providers! + Rails.application.reload_routes! - mock_auth_hash(provider, uid, user.email) - allow(Gitlab::Auth::Ldap::Access).to receive(:allowed?).with(user).and_return(true) + mock_auth_hash(provider, uid, user.email) + allow(Gitlab::Auth::Ldap::Access).to receive(:allowed?).with(user).and_return(true) - allow_any_instance_of(ActionDispatch::Routing::RoutesProxy) - .to receive(:"user_#{provider}_omniauth_callback_path") - .and_return("/users/auth/#{provider}/callback") - end + allow_any_instance_of(ActionDispatch::Routing::RoutesProxy) + .to receive(:"user_#{provider}_omniauth_callback_path") + .and_return("/users/auth/#{provider}/callback") + end - def sign_in_using_ldap!(user, provider_label) - visit new_user_session_path - click_link provider_label - fill_in 'username', with: user.username - fill_in 'password', with: user.password - click_button 'Sign in' - end + def sign_in_using_ldap!(user, provider_label) + visit new_user_session_path + click_link provider_label + fill_in 'username', with: user.username + fill_in 'password', with: user.password + click_button 'Sign in' + end - def enable_admin_mode_using_ldap!(user) - visit new_admin_session_path - click_link provider_label - fill_in 'username', with: user.username - fill_in 'password', with: user.password - click_button 'Enter Admin Mode' + def enable_admin_mode_using_ldap!(user) + visit new_admin_session_path + click_link provider_label + fill_in 'username', with: user.username + fill_in 'password', with: user.password + click_button 'Enter Admin Mode' + end end end end diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index 22fba3af1c9..b875dbe1340 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -216,7 +216,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do before do gitlab_sign_in(user, remember: true) - expect(page).to have_content('Two-Factor Authentication') + expect(page).to have_content('Two-factor authentication code') end it 'does not show a "You are already signed in." error message' do @@ -407,7 +407,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do sign_in_using_saml! - expect(page).to have_content('Two-Factor Authentication') + expect(page).to have_content('Two-factor authentication code') enter_code(user.current_otp) diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb index 132a3f557e4..f2381e41de8 100644 --- a/spec/features/users/signup_spec.rb +++ b/spec/features/users/signup_spec.rb @@ -3,39 +3,43 @@ require 'spec_helper' RSpec.shared_examples 'Signup name validation' do |field, max_length, label| - before do - visit new_user_registration_path - end + flag_values = [true, false] + flag_values.each do |val| + before do + stub_feature_flags(restyle_login_page: val) + visit new_user_registration_path + end - describe "#{field} validation", :js do - it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do - fill_in field, with: 'u' * max_length + describe "#{field} validation", :js do + it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do + fill_in field, with: 'u' * max_length - expect(find('.name')).not_to have_css '.gl-field-error-outline' - end + expect(find('.name')).not_to have_css '.gl-field-error-outline' + end - it 'shows an error border if the user\'s fullname contains an emoji' do - simulate_input("##{field}", 'Ehsan 🦋') + it 'shows an error border if the user\'s fullname contains an emoji' do + simulate_input("##{field}", 'Ehsan 🦋') - expect(find('.name')).to have_css '.gl-field-error-outline' - end + expect(find('.name')).to have_css '.gl-field-error-outline' + end - it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do - fill_in field, with: 'n' * (max_length + 1) + it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do + fill_in field, with: 'n' * (max_length + 1) - expect(find('.name')).to have_css '.gl-field-error-outline' - end + expect(find('.name')).to have_css '.gl-field-error-outline' + end - it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do - fill_in field, with: 'n' * (max_length + 1) + it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do + fill_in field, with: 'n' * (max_length + 1) - expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).") - end + expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).") + end - it 'shows an error message if the username contains emojis' do - simulate_input("##{field}", 'Ehsan 🦋') + it 'shows an error message if the username contains emojis' do + simulate_input("##{field}", 'Ehsan 🦋') - expect(page).to have_content("Invalid input, please avoid emojis") + expect(page).to have_content("Invalid input, please avoid emojis") + end end end end @@ -43,10 +47,6 @@ end RSpec.describe 'Signup' do include TermsHelper - before do - stub_application_setting(require_admin_approval_after_user_signup: false) - end - let(:new_user) { build_stubbed(:user) } def fill_in_signup_form @@ -63,214 +63,309 @@ RSpec.describe 'Signup' do visit user_confirmation_path(confirmation_token: new_user_token) end - describe 'username validation', :js do + flag_values = [true, false] + flag_values.each do |val| before do - visit new_user_registration_path + stub_feature_flags(restyle_login_page: val) + stub_application_setting(require_admin_approval_after_user_signup: false) end - it 'does not show an error border if the username is available' do - fill_in 'new_user_username', with: 'new-user' - wait_for_requests + describe 'username validation', :js do + before do + visit new_user_registration_path + end - expect(find('.username')).not_to have_css '.gl-field-error-outline' - end + it 'does not show an error border if the username is available' do + fill_in 'new_user_username', with: 'new-user' + wait_for_requests - it 'does not show an error border if the username contains dots (.)' do - simulate_input('#new_user_username', 'new.user.username') - wait_for_requests + expect(find('.username')).not_to have_css '.gl-field-error-outline' + end - expect(find('.username')).not_to have_css '.gl-field-error-outline' - end + it 'does not show an error border if the username contains dots (.)' do + simulate_input('#new_user_username', 'new.user.username') + wait_for_requests - it 'does not show an error border if the username length is not longer than 255 characters' do - fill_in 'new_user_username', with: 'u' * 255 - wait_for_requests + expect(find('.username')).not_to have_css '.gl-field-error-outline' + end - expect(find('.username')).not_to have_css '.gl-field-error-outline' - end + it 'does not show an error border if the username length is not longer than 255 characters' do + fill_in 'new_user_username', with: 'u' * 255 + wait_for_requests - it 'shows an error border if the username already exists' do - existing_user = create(:user) + expect(find('.username')).not_to have_css '.gl-field-error-outline' + end - fill_in 'new_user_username', with: existing_user.username - wait_for_requests + it 'shows an error border if the username already exists' do + existing_user = create(:user) - expect(find('.username')).to have_css '.gl-field-error-outline' - end + fill_in 'new_user_username', with: existing_user.username + wait_for_requests - it 'shows a success border if the username is available' do - fill_in 'new_user_username', with: 'new-user' - wait_for_requests + expect(find('.username')).to have_css '.gl-field-error-outline' + end - expect(find('.username')).to have_css '.gl-field-success-outline' - end + it 'shows a success border if the username is available' do + fill_in 'new_user_username', with: 'new-user' + wait_for_requests - it 'shows an error border if the username contains special characters' do - fill_in 'new_user_username', with: 'new$user!username' - wait_for_requests + expect(find('.username')).to have_css '.gl-field-success-outline' + end - expect(find('.username')).to have_css '.gl-field-error-outline' - end + it 'shows an error border if the username contains special characters' do + fill_in 'new_user_username', with: 'new$user!username' + wait_for_requests - it 'shows an error border if the username is longer than 255 characters' do - fill_in 'new_user_username', with: 'u' * 256 - wait_for_requests + expect(find('.username')).to have_css '.gl-field-error-outline' + end - expect(find('.username')).to have_css '.gl-field-error-outline' - end + it 'shows an error border if the username is longer than 255 characters' do + fill_in 'new_user_username', with: 'u' * 256 + wait_for_requests - it 'shows an error message if the username is longer than 255 characters' do - fill_in 'new_user_username', with: 'u' * 256 - wait_for_requests + expect(find('.username')).to have_css '.gl-field-error-outline' + end - expect(page).to have_content("Username is too long (maximum is 255 characters).") - end + it 'shows an error message if the username is longer than 255 characters' do + fill_in 'new_user_username', with: 'u' * 256 + wait_for_requests - it 'shows an error message if the username is less than 2 characters' do - fill_in 'new_user_username', with: 'u' - wait_for_requests + expect(page).to have_content("Username is too long (maximum is 255 characters).") + end - expect(page).to have_content("Username is too short (minimum is 2 characters).") - end + it 'shows an error message if the username is less than 2 characters' do + fill_in 'new_user_username', with: 'u' + wait_for_requests - it 'shows an error message on submit if the username contains special characters' do - fill_in 'new_user_username', with: 'new$user!username' - wait_for_requests + expect(page).to have_content("Username is too short (minimum is 2 characters).") + end - click_button "Register" + it 'shows an error message on submit if the username contains special characters' do + fill_in 'new_user_username', with: 'new$user!username' + wait_for_requests - expect(page).to have_content("Please create a username with only alphanumeric characters.") - end + click_button "Register" - it 'shows an error border if the username contains emojis' do - simulate_input('#new_user_username', 'ehsan😀') + expect(page).to have_content("Please create a username with only alphanumeric characters.") + end - expect(find('.username')).to have_css '.gl-field-error-outline' - end + it 'shows an error border if the username contains emojis' do + simulate_input('#new_user_username', 'ehsan😀') + + expect(find('.username')).to have_css '.gl-field-error-outline' + end - it 'shows an error message if the username contains emojis' do - simulate_input('#new_user_username', 'ehsan😀') + it 'shows an error message if the username contains emojis' do + simulate_input('#new_user_username', 'ehsan😀') - expect(page).to have_content("Invalid input, please avoid emojis") - end + expect(page).to have_content("Invalid input, please avoid emojis") + end - it 'shows a pending message if the username availability is being fetched', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/31484' do - fill_in 'new_user_username', with: 'new-user' + it 'shows a pending message if the username availability is being fetched', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/31484' do + fill_in 'new_user_username', with: 'new-user' - expect(find('.username > .validation-pending')).not_to have_css '.hide' - end + expect(find('.username > .validation-pending')).not_to have_css '.hide' + end - it 'shows a success message if the username is available' do - fill_in 'new_user_username', with: 'new-user' - wait_for_requests + it 'shows a success message if the username is available' do + fill_in 'new_user_username', with: 'new-user' + wait_for_requests - expect(find('.username > .validation-success')).not_to have_css '.hide' - end + expect(find('.username > .validation-success')).not_to have_css '.hide' + end - it 'shows an error message if the username is unavailable' do - existing_user = create(:user) + it 'shows an error message if the username is unavailable' do + existing_user = create(:user) - fill_in 'new_user_username', with: existing_user.username - wait_for_requests + fill_in 'new_user_username', with: existing_user.username + wait_for_requests - expect(find('.username > .validation-error')).not_to have_css '.hide' - end + expect(find('.username > .validation-error')).not_to have_css '.hide' + end - it 'shows a success message if the username is corrected and then available' do - fill_in 'new_user_username', with: 'new-user$' - wait_for_requests - fill_in 'new_user_username', with: 'new-user' - wait_for_requests + it 'shows a success message if the username is corrected and then available' do + fill_in 'new_user_username', with: 'new-user$' + wait_for_requests + fill_in 'new_user_username', with: 'new-user' + wait_for_requests - expect(page).to have_content("Username is available.") + expect(page).to have_content("Username is available.") + end end - end - context 'with no errors' do - context 'when sending confirmation email' do - before do - stub_application_setting(send_user_confirmation_email: true) + context 'with no errors' do + context 'when sending confirmation email' do + before do + stub_application_setting(send_user_confirmation_email: true) + end + + context 'when soft email confirmation is not enabled' do + before do + stub_feature_flags(soft_email_confirmation: false) + end + + it 'creates the user account and sends a confirmation email, and pre-fills email address after confirming' do + visit new_user_registration_path + + fill_in_signup_form + + expect { click_button 'Register' }.to change { User.count }.by(1) + expect(page).to have_current_path users_almost_there_path, ignore_query: true + expect(page).to have_content("Please check your email (#{new_user.email}) to confirm your account") + + confirm_email + + expect(find_field('Username or email').value).to eq(new_user.email) + end + end + + context 'when soft email confirmation is enabled' do + before do + stub_feature_flags(soft_email_confirmation: true) + end + + it 'creates the user account and sends a confirmation email' do + visit new_user_registration_path + + fill_in_signup_form + + expect { click_button 'Register' }.to change { User.count }.by(1) + expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true + end + end end - context 'when soft email confirmation is not enabled' do + context "when not sending confirmation email" do before do - stub_feature_flags(soft_email_confirmation: false) + stub_application_setting(send_user_confirmation_email: false) end - it 'creates the user account and sends a confirmation email, and pre-fills email address after confirming' do + it 'creates the user account and goes to dashboard' do visit new_user_registration_path fill_in_signup_form + click_button "Register" - expect { click_button 'Register' }.to change { User.count }.by(1) - expect(page).to have_current_path users_almost_there_path, ignore_query: true - expect(page).to have_content("Please check your email (#{new_user.email}) to confirm your account") - - confirm_email - - expect(find_field('Username or email').value).to eq(new_user.email) + expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true end end - context 'when soft email confirmation is enabled' do + context 'with required admin approval enabled' do before do - stub_feature_flags(soft_email_confirmation: true) + stub_application_setting(require_admin_approval_after_user_signup: true) end - it 'creates the user account and sends a confirmation email' do + it 'creates the user but does not sign them in' do visit new_user_registration_path fill_in_signup_form expect { click_button 'Register' }.to change { User.count }.by(1) - expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true + expect(page).to have_current_path new_user_session_path, ignore_query: true + expect(page).to have_content("You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator") end end end - context "when not sending confirmation email" do - before do - stub_application_setting(send_user_confirmation_email: false) + context 'with errors' do + it "displays the errors" do + create(:user, email: new_user.email) + visit new_user_registration_path + + fill_in_signup_form + click_button "Register" + + expect(page).to have_current_path user_registration_path, ignore_query: true + expect(page).to have_content("error prohibited this user from being saved") + expect(page).to have_content("Email has already been taken") end - it 'creates the user account and goes to dashboard' do + it 'does not redisplay the password' do + create(:user, email: new_user.email) visit new_user_registration_path fill_in_signup_form click_button "Register" - expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true + expect(page).to have_current_path user_registration_path, ignore_query: true + expect(page.body).not_to match(/#{new_user.password}/) end end - context 'with required admin approval enabled' do + context 'when terms are enforced' do before do - stub_application_setting(require_admin_approval_after_user_signup: true) + enforce_terms end - it 'creates the user but does not sign them in' do + it 'renders text that the user confirms terms by clicking register' 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 + click_button 'Register' - expect { click_button 'Register' }.to change { User.count }.by(1) - expect(page).to have_current_path new_user_session_path, ignore_query: true - expect(page).to have_content("You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator") + expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true end end - end - context 'with errors' do - it "displays the errors" do - create(:user, email: new_user.email) + context 'when reCAPTCHA and invisible captcha are enabled' do + before do + stub_application_setting(invisible_captcha_enabled: true) + stub_application_setting(recaptcha_enabled: true) + allow_next_instance_of(RegistrationsController) do |instance| + allow(instance).to receive(:verify_recaptcha).and_return(true) + end + end + + context 'when reCAPTCHA detects malicious behaviour' do + before do + allow_next_instance_of(RegistrationsController) do |instance| + allow(instance).to receive(:verify_recaptcha).and_return(false) + end + end + + it 'prevents from signing up' do + visit new_user_registration_path + + fill_in_signup_form + + expect { click_button 'Register' }.not_to change { User.count } + expect(page).to have_content(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')) + end + end + + context 'when invisible captcha detects malicious behaviour' do + it 'prevents from signing up' do + visit new_user_registration_path + + fill_in_signup_form + + expect { click_button 'Register' }.not_to change { User.count } + expect(page).to have_content('That was a bit too quick! Please resubmit.') + end + end + end + + it 'redirects to step 2 of the signup process, sets the role and redirects back' do + stub_feature_flags(about_your_company_registration_flow: false) visit new_user_registration_path fill_in_signup_form - click_button "Register" + click_button 'Register' - expect(page).to have_current_path user_registration_path, ignore_query: true - expect(page).to have_content("error prohibited this user from being saved") - expect(page).to have_content("Email has already been taken") + visit new_project_path + + expect(page).to have_current_path(users_sign_up_welcome_path) + + select 'Software Developer', from: 'user_role' + click_button 'Get started!' + + created_user = User.find_by_username(new_user.username) + + expect(created_user.software_developer_role?).to be_truthy + expect(created_user.setup_for_company).to be_nil + expect(page).to have_current_path(new_project_path) end it 'does not redisplay the password' do @@ -304,69 +399,21 @@ RSpec.describe 'Signup' do fill_in_signup_form click_button 'Register' - expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true - end - end + visit new_project_path - context 'when reCAPTCHA and invisible captcha are enabled' do - before do - stub_application_setting(invisible_captcha_enabled: true) - stub_application_setting(recaptcha_enabled: true) - allow_next_instance_of(RegistrationsController) do |instance| - allow(instance).to receive(:verify_recaptcha).and_return(true) - end - end + expect(page).to have_current_path(users_sign_up_welcome_path) - context 'when reCAPTCHA detects malicious behaviour' do - before do - allow_next_instance_of(RegistrationsController) do |instance| - allow(instance).to receive(:verify_recaptcha).and_return(false) - end - end + select 'Software Developer', from: 'user_role' + click_button 'Get started!' - it 'prevents from signing up' do - visit new_user_registration_path + created_user = User.find_by_username(new_user.username) - fill_in_signup_form - - expect { click_button 'Register' }.not_to change { User.count } - expect(page).to have_content(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')) - end + expect(created_user.software_developer_role?).to be_truthy + expect(created_user.setup_for_company).to be_nil + expect(page).to have_current_path(new_project_path) end - context 'when invisible captcha detects malicious behaviour' do - it 'prevents from signing up' do - visit new_user_registration_path - - fill_in_signup_form - - expect { click_button 'Register' }.not_to change { User.count } - expect(page).to have_content('That was a bit too quick! Please resubmit.') - end - end + it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name' + it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name' end - - it 'redirects to step 2 of the signup process, sets the role and redirects back' do - stub_feature_flags(about_your_company_registration_flow: false) - visit new_user_registration_path - - fill_in_signup_form - click_button 'Register' - - visit new_project_path - - expect(page).to have_current_path(users_sign_up_welcome_path) - - select 'Software Developer', from: 'user_role' - click_button 'Get started!' - - created_user = User.find_by_username(new_user.username) - - expect(created_user.software_developer_role?).to be_truthy - expect(created_user.setup_for_company).to be_nil - expect(page).to have_current_path(new_project_path) - end - - it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name' - it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name' end diff --git a/spec/frontend/ide/lib/common/model_manager_spec.js b/spec/frontend/ide/lib/common/model_manager_spec.js index 08e4ab0f113..e485873e8da 100644 --- a/spec/frontend/ide/lib/common/model_manager_spec.js +++ b/spec/frontend/ide/lib/common/model_manager_spec.js @@ -59,7 +59,7 @@ describe('Multi-file editor library model manager', () => { describe('hasCachedModel', () => { it('returns false when no models exist', () => { - expect(instance.hasCachedModel('path')).toBeFalsy(); + expect(instance.hasCachedModel('path')).toBe(false); }); it('returns true when model exists', () => { @@ -67,7 +67,7 @@ describe('Multi-file editor library model manager', () => { instance.addModel(f); - expect(instance.hasCachedModel(f.key)).toBeTruthy(); + expect(instance.hasCachedModel(f.key)).toBe(true); }); }); diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js deleted file mode 100644 index 238942a34ff..00000000000 --- a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js +++ /dev/null @@ -1,72 +0,0 @@ -import { GlAlert, GlLink } from '@gitlab/ui'; -import { mount, shallowMount } from '@vue/test-utils'; -import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue'; -import { mergeUnwrappedCiConfig, mockLintHelpPagePath } from '../../mock_data'; - -describe('~/pipeline_editor/components/lint/ci_lint.vue', () => { - let wrapper; - - const createComponent = ({ props, mountFn = shallowMount } = {}) => { - wrapper = mountFn(CiLint, { - provide: { - lintHelpPagePath: mockLintHelpPagePath, - }, - propsData: { - ciConfig: mergeUnwrappedCiConfig(), - ...props, - }, - }); - }; - - const findAllByTestId = (selector) => wrapper.findAll(`[data-testid="${selector}"]`); - const findAlert = () => wrapper.find(GlAlert); - const findLintParameters = () => findAllByTestId('ci-lint-parameter'); - const findLintParameterAt = (i) => findLintParameters().at(i); - const findLintValueAt = (i) => findAllByTestId('ci-lint-value').at(i); - - afterEach(() => { - wrapper.destroy(); - }); - - describe('Valid Results', () => { - beforeEach(() => { - createComponent({ props: { isValid: true }, mountFn: mount }); - }); - - it('displays valid results', () => { - expect(findAlert().text()).toMatch('Status: Syntax is correct.'); - }); - - it('displays link to the right help page', () => { - expect(findAlert().find(GlLink).attributes('href')).toBe(mockLintHelpPagePath); - }); - - it('displays jobs', () => { - expect(findLintParameters()).toHaveLength(3); - - expect(findLintParameterAt(0).text()).toBe('Test Job - job_test_1'); - expect(findLintParameterAt(1).text()).toBe('Test Job - job_test_2'); - expect(findLintParameterAt(2).text()).toBe('Build Job - job_build'); - }); - - it('displays jobs details', () => { - expect(findLintParameters()).toHaveLength(3); - - expect(findLintValueAt(0).text()).toMatchInterpolatedText( - 'echo "test 1" Only policy: branches, tags When: on_success', - ); - expect(findLintValueAt(1).text()).toMatchInterpolatedText( - 'echo "test 2" Only policy: branches, tags When: on_success', - ); - expect(findLintValueAt(2).text()).toMatchInterpolatedText( - 'echo "build" Only policy: branches, tags When: on_success', - ); - }); - - it('displays invalid results', () => { - createComponent({ props: { isValid: false }, mountFn: mount }); - - expect(findAlert().text()).toMatch('Status: Syntax is incorrect.'); - }); - }); -}); diff --git a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js index cf28ffeabed..2f3e1b49b37 100644 --- a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js +++ b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js @@ -1,12 +1,12 @@ +// TODO + import { GlAlert, GlBadge, GlLoadingIcon, GlTabs } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import VueApollo from 'vue-apollo'; import Vue, { nextTick } from 'vue'; import createMockApollo from 'helpers/mock_apollo_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; -import waitForPromises from 'helpers/wait_for_promises'; import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue'; -import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue'; import CiValidate from '~/pipeline_editor/components/validate/ci_validate.vue'; import WalkthroughPopover from '~/pipeline_editor/components/popovers/walkthrough_popover.vue'; import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue'; @@ -23,7 +23,6 @@ import { } from '~/pipeline_editor/constants'; import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql'; -import getAppStatus from '~/pipeline_editor/graphql/queries/client/app_status.query.graphql'; import { mockBlobContentQueryResponse, mockCiLintPath, @@ -65,7 +64,12 @@ describe('Pipeline editor tabs component', () => { }; }, provide: { + ciConfigPath: '/path/to/ci-config', ciLintPath: mockCiLintPath, + currentBranch: 'main', + projectFullPath: '/path/to/project', + simulatePipelineHelpPagePath: 'path/to/help/page', + validateTabIllustrationPath: 'path/to/svg', ...provide, }, stubs: { @@ -83,15 +87,6 @@ describe('Pipeline editor tabs component', () => { const createComponentWithApollo = ({ props, provide = {}, mountFn = shallowMount } = {}) => { const handlers = [[getBlobContent, mockBlobContentData]]; mockApollo = createMockApollo(handlers); - mockApollo.clients.defaultClient.cache.writeQuery({ - query: getAppStatus, - data: { - app: { - __typename: 'PipelineEditorApp', - status: EDITOR_APP_STATUS_VALID, - }, - }, - }); createComponent({ props, @@ -104,14 +99,12 @@ describe('Pipeline editor tabs component', () => { }; const findEditorTab = () => wrapper.find('[data-testid="editor-tab"]'); - const findLintTab = () => wrapper.find('[data-testid="lint-tab"]'); const findMergedTab = () => wrapper.find('[data-testid="merged-tab"]'); const findValidateTab = () => wrapper.find('[data-testid="validate-tab"]'); const findVisualizationTab = () => wrapper.find('[data-testid="visualization-tab"]'); const findAlert = () => wrapper.findComponent(GlAlert); const findBadge = () => wrapper.findComponent(GlBadge); - const findCiLint = () => wrapper.findComponent(CiLint); const findCiValidate = () => wrapper.findComponent(CiValidate); const findGlTabs = () => wrapper.findComponent(GlTabs); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); @@ -130,7 +123,8 @@ describe('Pipeline editor tabs component', () => { describe('editor tab', () => { it('displays editor only after the tab is mounted', async () => { - createComponent({ mountFn: mount }); + mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse); + createComponentWithApollo({ mountFn: mount }); expect(findTextEditor().exists()).toBe(false); @@ -165,138 +159,57 @@ describe('Pipeline editor tabs component', () => { }); describe('validate tab', () => { - describe('with simulatePipeline feature flag ON', () => { - describe('after loading', () => { - beforeEach(() => { - createComponent({ - provide: { glFeatures: { simulatePipeline: true } }, - }); - }); - - it('displays the tab and the validate component', () => { - expect(findValidateTab().exists()).toBe(true); - expect(findCiValidate().exists()).toBe(true); - }); + describe('after loading', () => { + beforeEach(() => { + createComponent(); }); - describe('NEW badge', () => { - describe('default', () => { - beforeEach(() => { - mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse); - createComponentWithApollo({ - mountFn: mount, - props: { - currentTab: VALIDATE_TAB, - }, - provide: { - glFeatures: { simulatePipeline: true }, - ciConfigPath: '/path/to/ci-config', - currentBranch: 'main', - projectFullPath: '/path/to/project', - simulatePipelineHelpPagePath: 'path/to/help/page', - validateTabIllustrationPath: 'path/to/svg', - }, - }); - }); - - it('renders badge by default', () => { - expect(findBadge().exists()).toBe(true); - expect(findBadge().text()).toBe(wrapper.vm.$options.i18n.new); - }); - - it('hides badge when moving away from the validate tab', async () => { - expect(findBadge().exists()).toBe(true); - - await findEditorTab().vm.$emit('click'); - - expect(findBadge().exists()).toBe(false); - }); - }); - - describe('if badge has been dismissed before', () => { - it('does not render badge if it has been dismissed before', async () => { - localStorage.setItem(VALIDATE_TAB_BADGE_DISMISSED_KEY, 'true'); - mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse); - createComponentWithApollo({ - mountFn: mount, - provide: { - glFeatures: { simulatePipeline: true }, - ciConfigPath: '/path/to/ci-config', - currentBranch: 'main', - projectFullPath: '/path/to/project', - simulatePipelineHelpPagePath: 'path/to/help/page', - validateTabIllustrationPath: 'path/to/svg', - }, - }); - - await waitForPromises(); - - expect(findBadge().exists()).toBe(false); - }); - }); + it('displays the tab and the validate component', () => { + expect(findValidateTab().exists()).toBe(true); + expect(findCiValidate().exists()).toBe(true); }); }); - describe('with simulatePipeline feature flag OFF', () => { - beforeEach(() => { - createComponent({ - provide: { - glFeatures: { - simulatePipeline: false, + describe('NEW badge', () => { + describe('default', () => { + beforeEach(() => { + mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse); + createComponentWithApollo({ + mountFn: mount, + props: { + currentTab: VALIDATE_TAB, }, - }, + }); }); - }); - it('does not render the tab and the validate component', () => { - expect(findValidateTab().exists()).toBe(false); - expect(findCiValidate().exists()).toBe(false); - }); - }); - }); + it('renders badge by default', () => { + expect(findBadge().exists()).toBe(true); + expect(findBadge().text()).toBe(wrapper.vm.$options.i18n.new); + }); - describe('lint tab', () => { - describe('while loading', () => { - beforeEach(() => { - createComponent({ appStatus: EDITOR_APP_STATUS_LOADING }); - }); + it('hides badge when moving away from the validate tab', async () => { + expect(findBadge().exists()).toBe(true); - it('displays a loading icon if the lint query is loading', () => { - expect(findLoadingIcon().exists()).toBe(true); - }); + await findEditorTab().vm.$emit('click'); - it('does not display the lint component', () => { - expect(findCiLint().exists()).toBe(false); - }); - }); - describe('after loading', () => { - beforeEach(() => { - createComponent(); - }); - - it('display the tab and the lint component', () => { - expect(findLintTab().exists()).toBe(true); - expect(findCiLint().exists()).toBe(true); + expect(findBadge().exists()).toBe(false); + }); }); - }); - describe('with simulatePipeline feature flag ON', () => { - beforeEach(() => { - createComponent({ - provide: { - glFeatures: { - simulatePipeline: true, - }, - }, + describe('if badge has been dismissed before', () => { + beforeEach(() => { + localStorage.setItem(VALIDATE_TAB_BADGE_DISMISSED_KEY, 'true'); + mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse); + createComponentWithApollo({ mountFn: mount }); }); - }); - it('does not render the tab and the lint component', () => { - expect(findLintTab().exists()).toBe(false); - expect(findCiLint().exists()).toBe(false); + it('does not render badge if it has been dismissed before', () => { + expect(findBadge().exists()).toBe(false); + }); }); }); }); + describe('merged tab', () => { describe('while loading', () => { beforeEach(() => { @@ -337,19 +250,19 @@ describe('Pipeline editor tabs component', () => { describe('show tab content based on status', () => { it.each` - appStatus | editor | viz | lint | merged + appStatus | editor | viz | validate | merged ${undefined} | ${true} | ${true} | ${true} | ${true} - ${EDITOR_APP_STATUS_EMPTY} | ${true} | ${false} | ${false} | ${false} + ${EDITOR_APP_STATUS_EMPTY} | ${true} | ${false} | ${true} | ${false} ${EDITOR_APP_STATUS_INVALID} | ${true} | ${false} | ${true} | ${false} ${EDITOR_APP_STATUS_VALID} | ${true} | ${true} | ${true} | ${true} `( - 'when status is $appStatus, we show - editor:$editor | viz:$viz | lint:$lint | merged:$merged ', - ({ appStatus, editor, viz, lint, merged }) => { + 'when status is $appStatus, we show - editor:$editor | viz:$viz | validate:$validate | merged:$merged ', + ({ appStatus, editor, viz, validate, merged }) => { createComponent({ appStatus }); expect(findTextEditor().exists()).toBe(editor); expect(findPipelineGraph().exists()).toBe(viz); - expect(findCiLint().exists()).toBe(lint); + expect(findValidateTab().exists()).toBe(validate); expect(findMergedPreview().exists()).toBe(merged); }, ); @@ -395,11 +308,8 @@ describe('Pipeline editor tabs component', () => { describe('pipeline editor walkthrough', () => { describe('when isNewCiConfigFile prop is true (default)', () => { - beforeEach(async () => { - createComponent({ - mountFn: mount, - }); - await nextTick(); + beforeEach(() => { + createComponent(); }); it('shows walkthrough popover', async () => { @@ -409,8 +319,7 @@ describe('Pipeline editor tabs component', () => { describe('when isNewCiConfigFile prop is false', () => { it('does not show walkthrough popover', async () => { - createComponent({ props: { isNewCiConfigFile: false }, mountFn: mount }); - await nextTick(); + createComponent({ props: { isNewCiConfigFile: false } }); expect(findWalkthroughPopover().exists()).toBe(false); }); }); @@ -420,7 +329,6 @@ describe('Pipeline editor tabs component', () => { const handler = jest.fn(); createComponent({ - mountFn: mount, listeners: { event: handler, }, diff --git a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js index c6964f190b4..0cb7155c8c0 100644 --- a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js +++ b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js @@ -14,7 +14,7 @@ import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tab import { CREATE_TAB, FILE_TREE_DISPLAY_KEY, - LINT_TAB, + VALIDATE_TAB, MERGED_TAB, TABS_INDEX, VISUALIZE_TAB, @@ -138,7 +138,7 @@ describe('Pipeline editor home wrapper', () => { tab | shouldShow ${MERGED_TAB} | ${false} ${VISUALIZE_TAB} | ${false} - ${LINT_TAB} | ${false} + ${VALIDATE_TAB} | ${false} ${CREATE_TAB} | ${true} `( 'when the active tab is $tab the commit form is shown: $shouldShow', @@ -170,7 +170,7 @@ describe('Pipeline editor home wrapper', () => { tab | shouldShow ${MERGED_TAB} | ${false} ${VISUALIZE_TAB} | ${false} - ${LINT_TAB} | ${false} + ${VALIDATE_TAB} | ${false} ${CREATE_TAB} | ${true} `( 'when the tab query param is $tab the commit form is shown: $shouldShow', diff --git a/spec/graphql/types/ci/group_variable_type_spec.rb b/spec/graphql/types/ci/group_variable_type_spec.rb index 3680f661198..106935642f2 100644 --- a/spec/graphql/types/ci/group_variable_type_spec.rb +++ b/spec/graphql/types/ci/group_variable_type_spec.rb @@ -5,5 +5,5 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiGroupVariable'] do specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) } - specify { expect(described_class).to have_graphql_fields(:environment_scope).at_least } + specify { expect(described_class).to have_graphql_fields(:environment_scope, :masked, :protected).at_least } end diff --git a/spec/graphql/types/ci/instance_variable_type_spec.rb b/spec/graphql/types/ci/instance_variable_type_spec.rb index e534f69ea2d..cf4aaed31f1 100644 --- a/spec/graphql/types/ci/instance_variable_type_spec.rb +++ b/spec/graphql/types/ci/instance_variable_type_spec.rb @@ -4,4 +4,6 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiInstanceVariable'] do specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) } + + specify { expect(described_class).to have_graphql_fields(:masked, :protected).at_least } end diff --git a/spec/graphql/types/ci/project_variable_type_spec.rb b/spec/graphql/types/ci/project_variable_type_spec.rb index 5883a397d9f..e6e045b2bca 100644 --- a/spec/graphql/types/ci/project_variable_type_spec.rb +++ b/spec/graphql/types/ci/project_variable_type_spec.rb @@ -5,5 +5,5 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiProjectVariable'] do specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) } - it { expect(described_class).to have_graphql_fields(:environment_scope).at_least } + specify { expect(described_class).to have_graphql_fields(:environment_scope, :masked, :protected).at_least } end diff --git a/spec/graphql/types/ci/variable_interface_spec.rb b/spec/graphql/types/ci/variable_interface_spec.rb index 9bdce46eafe..8cef0ac2a14 100644 --- a/spec/graphql/types/ci/variable_interface_spec.rb +++ b/spec/graphql/types/ci/variable_interface_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiVariable'] do specify do expect(described_class).to have_graphql_fields( - :id, :key, :value, :variable_type, :protected, :masked, :raw + :id, :key, :value, :variable_type, :raw ).at_least end end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 47c31546629..264431b1bb5 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -192,6 +192,14 @@ RSpec.describe ApplicationHelper do end end + describe '#community_forum' do + subject { helper.community_forum } + + it 'returns the url' do + is_expected.to eq("https://forum.gitlab.com") + end + end + describe '#support_url' do context 'when alternate support url is specified' do let(:alternate_url) { 'http://company.example.com/getting-help' } diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb index 439d3d8c64e..9503dafcf2a 100644 --- a/spec/requests/projects/merge_requests_discussions_spec.rb +++ b/spec/requests/projects/merge_requests_discussions_spec.rb @@ -264,15 +264,6 @@ RSpec.describe 'merge requests discussions' do end end - context 'when mr_discussions_http_cache is disabled' do - before do - stub_feature_flags(mr_discussions_http_cache: false) - send_request - end - - it_behaves_like 'cache hit' - end - context 'when disabled_mr_discussions_redis_cache is disabled' do before do stub_feature_flags(disabled_mr_discussions_redis_cache: false) @@ -281,15 +272,6 @@ RSpec.describe 'merge requests discussions' do it_behaves_like 'cache hit' end - - context 'when mr_discussions_http_cache and disabled_mr_discussions_redis_cache are disabled' do - before do - stub_feature_flags(mr_discussions_http_cache: false, disabled_mr_discussions_redis_cache: false) - send_request - end - - it_behaves_like 'cache hit' - end end end end diff --git a/spec/views/devise/sessions/new.html.haml_spec.rb b/spec/views/devise/sessions/new.html.haml_spec.rb index b3cd1493149..c41e9eb7162 100644 --- a/spec/views/devise/sessions/new.html.haml_spec.rb +++ b/spec/views/devise/sessions/new.html.haml_spec.rb @@ -9,6 +9,7 @@ RSpec.describe 'devise/sessions/new' do before do stub_devise disable_captcha + stub_feature_flags(restyle_login_page: false) allow(Gitlab).to receive(:com?).and_return(true) end @@ -29,67 +30,74 @@ RSpec.describe 'devise/sessions/new' do end end - describe 'ldap' do - include LdapHelpers - - let(:server) { { provider_name: 'ldapmain', label: 'LDAP' }.with_indifferent_access } - + flag_values = [true, false] + flag_values.each do |val| before do - enable_ldap - stub_devise - disable_captcha - disable_sign_up - disable_other_signin_methods - - allow(view).to receive(:experiment_enabled?).and_return(false) + stub_feature_flags(restyle_login_page: val) end - it 'is shown when enabled' do - render + describe 'ldap' do + include LdapHelpers - expect(rendered).to have_selector('.new-session-tabs') - expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage - expect(rendered).to have_field('LDAP Username') - end + let(:server) { { provider_name: 'ldapmain', label: 'LDAP' }.with_indifferent_access } - it 'is not shown when LDAP sign in is disabled' do - disable_ldap_sign_in + before do + enable_ldap + stub_devise + disable_captcha + disable_sign_up + disable_other_signin_methods - render + allow(view).to receive(:experiment_enabled?).and_return(false) + end - expect(rendered).to have_content('No authentication methods configured') - expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage - expect(rendered).not_to have_field('LDAP Username') - end - end + it 'is shown when enabled' do + render - describe 'Google Tag Manager' do - let!(:gtm_id) { 'GTM-WWKMTWS'} + expect(rendered).to have_selector('.new-session-tabs') + expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage + expect(rendered).to have_field('LDAP Username') + end - subject { rendered } + it 'is not shown when LDAP sign in is disabled' do + disable_ldap_sign_in - before do - stub_devise - disable_captcha - stub_config(extra: { google_tag_manager_id: gtm_id, google_tag_manager_nonce_id: gtm_id }) + render + + expect(rendered).to have_content('No authentication methods configured') + expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage + expect(rendered).not_to have_field('LDAP Username') + end end - describe 'when Google Tag Manager is enabled' do + describe 'Google Tag Manager' do + let!(:gtm_id) { 'GTM-WWKMTWS'} + + subject { rendered } + before do - enable_gtm - render + stub_devise + disable_captcha + stub_config(extra: { google_tag_manager_id: gtm_id, google_tag_manager_nonce_id: gtm_id }) end - it { is_expected.to match /www.googletagmanager.com/ } - end + describe 'when Google Tag Manager is enabled' do + before do + enable_gtm + render + end - describe 'when Google Tag Manager is disabled' do - before do - disable_gtm - render + it { is_expected.to match /www.googletagmanager.com/ } end - it { is_expected.not_to match /www.googletagmanager.com/ } + describe 'when Google Tag Manager is disabled' do + before do + disable_gtm + render + end + + it { is_expected.not_to match /www.googletagmanager.com/ } + end end end |