Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 11:17:02 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 11:17:02 +0300
commitb39512ed755239198a9c294b6a45e65c05900235 (patch)
treed234a3efade1de67c46b9e5a38ce813627726aa7 /spec/features
parentd31474cf3b17ece37939d20082b07f6657cc79a9 (diff)
Add latest changes from gitlab-org/gitlab@15-3-stable-eev15.3.0-rc42
Diffstat (limited to 'spec/features')
-rw-r--r--spec/features/admin/admin_appearance_spec.rb233
-rw-r--r--spec/features/admin/admin_mode/login_spec.rb342
-rw-r--r--spec/features/admin/users/users_spec.rb4
-rw-r--r--spec/features/admin_variables_spec.rb34
-rw-r--r--spec/features/boards/board_filters_spec.rb4
-rw-r--r--spec/features/boards/boards_spec.rb8
-rw-r--r--spec/features/boards/reload_boards_on_browser_back_spec.rb6
-rw-r--r--spec/features/clusters/create_agent_spec.rb5
-rw-r--r--spec/features/cycle_analytics_spec.rb18
-rw-r--r--spec/features/dashboard/archived_projects_spec.rb2
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb78
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb4
-rw-r--r--spec/features/error_tracking/user_filters_errors_by_status_spec.rb4
-rw-r--r--spec/features/group_variables_spec.rb10
-rw-r--r--spec/features/groups/crm/contacts/create_spec.rb4
-rw-r--r--spec/features/groups/group_runners_spec.rb74
-rw-r--r--spec/features/groups/issues_spec.rb6
-rw-r--r--spec/features/groups/members/manage_members_spec.rb4
-rw-r--r--spec/features/groups/show_spec.rb45
-rw-r--r--spec/features/groups_spec.rb80
-rw-r--r--spec/features/invites_spec.rb22
-rw-r--r--spec/features/issuables/user_sees_sidebar_spec.rb2
-rw-r--r--spec/features/issues/form_spec.rb7
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb2
-rw-r--r--spec/features/issues/incident_issue_spec.rb70
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb8
-rw-r--r--spec/features/issues/related_issues_spec.rb20
-rw-r--r--spec/features/issues/todo_spec.rb2
-rw-r--r--spec/features/issues/user_bulk_edits_issues_spec.rb2
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb8
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb6
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb2
-rw-r--r--spec/features/issues/user_uses_quick_actions_spec.rb2
-rw-r--r--spec/features/markdown/copy_as_gfm_spec.rb19
-rw-r--r--spec/features/markdown/gitlab_flavored_markdown_spec.rb2
-rw-r--r--spec/features/markdown/json_table_spec.rb40
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb10
-rw-r--r--spec/features/merge_request/maintainer_edits_fork_spec.rb6
-rw-r--r--spec/features/merge_request/user_approves_spec.rb2
-rw-r--r--spec/features/merge_request/user_comments_on_merge_request_spec.rb39
-rw-r--r--spec/features/merge_request/user_customizes_merge_commit_message_spec.rb4
-rw-r--r--spec/features/merge_request/user_edits_assignees_sidebar_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_merge_request_spec.rb21
-rw-r--r--spec/features/merge_request/user_opens_context_commits_modal_spec.rb26
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb1
-rw-r--r--spec/features/merge_request/user_sees_closing_issues_message_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb11
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb2
-rw-r--r--spec/features/merge_request/user_uses_quick_actions_spec.rb2
-rw-r--r--spec/features/merge_requests/user_mass_updates_spec.rb14
-rw-r--r--spec/features/oauth_registration_spec.rb39
-rw-r--r--spec/features/populate_new_pipeline_vars_with_params_spec.rb2
-rw-r--r--spec/features/profile_spec.rb2
-rw-r--r--spec/features/profiles/password_spec.rb15
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb6
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb4
-rw-r--r--spec/features/profiles/user_visits_profile_spec.rb20
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb2
-rw-r--r--spec/features/projects/blobs/edit_spec.rb5
-rw-r--r--spec/features/projects/ci/lint_spec.rb5
-rw-r--r--spec/features/projects/ci/secure_files_spec.rb61
-rw-r--r--spec/features/projects/cluster_agents_spec.rb2
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb2
-rw-r--r--spec/features/projects/compare_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb8
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb4
-rw-r--r--spec/features/projects/files/user_creates_files_spec.rb19
-rw-r--r--spec/features/projects/files/user_edits_files_spec.rb26
-rw-r--r--spec/features/projects/issuable_templates_spec.rb28
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb1
-rw-r--r--spec/features/projects/members/manage_groups_spec.rb2
-rw-r--r--spec/features/projects/members/manage_members_spec.rb200
-rw-r--r--spec/features/projects/merge_request_button_spec.rb20
-rw-r--r--spec/features/projects/new_project_spec.rb32
-rw-r--r--spec/features/projects/pages/user_adds_domain_spec.rb6
-rw-r--r--spec/features/projects/pages/user_configures_pages_pipeline_spec.rb59
-rw-r--r--spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb3
-rw-r--r--spec/features/projects/pages/user_edits_settings_spec.rb13
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb7
-rw-r--r--spec/features/projects/pipelines/legacy_pipeline_spec.rb31
-rw-r--r--spec/features/projects/pipelines/legacy_pipelines_spec.rb3
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb9
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb3
-rw-r--r--spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb49
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb4
-rw-r--r--spec/features/projects/settings/service_desk_setting_spec.rb2
-rw-r--r--spec/features/projects/tags/user_edits_tags_spec.rb74
-rw-r--r--spec/features/projects/tags/user_views_tag_spec.rb8
-rw-r--r--spec/features/projects/tags/user_views_tags_spec.rb30
-rw-r--r--spec/features/projects/tree/create_directory_spec.rb4
-rw-r--r--spec/features/projects/tree/create_file_spec.rb4
-rw-r--r--spec/features/projects/tree/tree_show_spec.rb2
-rw-r--r--spec/features/projects_spec.rb30
-rw-r--r--spec/features/runners_spec.rb6
-rw-r--r--spec/features/search/user_searches_for_commits_spec.rb2
-rw-r--r--spec/features/signed_commits_spec.rb2
-rw-r--r--spec/features/tags/developer_updates_tag_spec.rb56
-rw-r--r--spec/features/task_lists_spec.rb12
-rw-r--r--spec/features/uploads/user_uploads_avatar_to_profile_spec.rb2
-rw-r--r--spec/features/uploads/user_uploads_file_to_note_spec.rb11
-rw-r--r--spec/features/users/email_verification_on_login_spec.rb2
-rw-r--r--spec/features/users/login_spec.rb38
-rw-r--r--spec/features/users/show_spec.rb10
-rw-r--r--spec/features/users/signup_spec.rb465
108 files changed, 1532 insertions, 1253 deletions
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 8bf8ef56353..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
- sign_in(create(:admin))
+ 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
- expect(page).to have_content 'Custom profile image guidelines, please 😄!'
+ it 'renders guidelines when set' do
+ sign_in create(:user)
+ visit profile_path
+
+ 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 659f66a67d2..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/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb
index e5df6cc0fd3..236327ea687 100644
--- a/spec/features/admin/users/users_spec.rb
+++ b/spec/features/admin/users/users_spec.rb
@@ -357,7 +357,7 @@ RSpec.describe 'Admin::Users' do
end
it 'creates new user' do
- expect { click_button 'Create user' }.to change {User.count}.by(1)
+ expect { click_button 'Create user' }.to change { User.count }.by(1)
end
it 'applies defaults to user' do
@@ -400,7 +400,7 @@ RSpec.describe 'Admin::Users' do
let_it_be(:user_username) { 'Bing bang' }
it "doesn't create the user and shows an error message" do
- expect { click_button 'Create user' }.to change {User.count}.by(0)
+ expect { click_button 'Create user' }.to change { User.count }.by(0)
expect(page).to have_content('The form contains the following error')
expect(page).to have_content('Username can contain only letters, digits')
diff --git a/spec/features/admin_variables_spec.rb b/spec/features/admin_variables_spec.rb
new file mode 100644
index 00000000000..174d4567520
--- /dev/null
+++ b/spec/features/admin_variables_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Instance variables', :js do
+ let(:admin) { create(:admin) }
+ let(:page_path) { ci_cd_admin_application_settings_path }
+
+ let_it_be(:variable) { create(:ci_instance_variable, key: 'test_key', value: 'test_value', masked: true) }
+
+ before do
+ stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ wait_for_requests
+ end
+
+ context 'with disabled ff `ci_variable_settings_graphql' do
+ before do
+ stub_feature_flags(ci_variable_settings_graphql: false)
+ visit page_path
+ end
+
+ it_behaves_like 'variable list', isAdmin: true
+ end
+
+ context 'with enabled ff `ci_variable_settings_graphql' do
+ before do
+ visit page_path
+ end
+
+ it_behaves_like 'variable list', isAdmin: true
+ end
+end
diff --git a/spec/features/boards/board_filters_spec.rb b/spec/features/boards/board_filters_spec.rb
index 537b677cbd0..2e4dc4a29fc 100644
--- a/spec/features/boards/board_filters_spec.rb
+++ b/spec/features/boards/board_filters_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'Issue board filters', :js do
let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue_1) }
let(:filtered_search) { find('[data-testid="issue-board-filtered-search"]') }
- let(:filter_input) { find('.gl-filtered-search-term-input')}
+ let(:filter_input) { find('.gl-filtered-search-term-input') }
let(:filter_dropdown) { find('.gl-filtered-search-suggestion-list') }
let(:filter_first_suggestion) { find('.gl-filtered-search-suggestion-list').first('.gl-filtered-search-suggestion') }
let(:filter_submit) { find('.gl-search-box-by-click-search-button') }
@@ -164,7 +164,7 @@ RSpec.describe 'Issue board filters', :js do
end
describe 'filters by type' do
- let_it_be(:incident) { create(:incident, project: project)}
+ let_it_be(:incident) { create(:incident, project: project) }
before do
set_filter('type')
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index e8321adeb42..f279af90aa3 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -135,6 +135,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -144,6 +145,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -153,6 +155,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -272,7 +275,7 @@ RSpec.describe 'Project issue boards', :js do
context 'issue card' do
it 'shows assignee' do
page.within(find('.board:nth-child(2)')) do
- expect(page).to have_selector('.avatar', count: 1)
+ expect(page).to have_selector('.gl-avatar', count: 1)
end
end
@@ -400,6 +403,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -409,6 +413,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -417,6 +422,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
diff --git a/spec/features/boards/reload_boards_on_browser_back_spec.rb b/spec/features/boards/reload_boards_on_browser_back_spec.rb
index 6a09e3c9506..7fa440befc1 100644
--- a/spec/features/boards/reload_boards_on_browser_back_spec.rb
+++ b/spec/features/boards/reload_boards_on_browser_back_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
- let(:project) {create(:project, :public)}
- let(:board) {create(:board, project: project)}
- let(:user) {create(:user)}
+ let(:project) { create(:project, :public) }
+ let(:board) { create(:board, project: project) }
+ let(:user) { create(:user) }
context 'authorized user' do
before do
diff --git a/spec/features/clusters/create_agent_spec.rb b/spec/features/clusters/create_agent_spec.rb
index b879ae645f7..c44741b756b 100644
--- a/spec/features/clusters/create_agent_spec.rb
+++ b/spec/features/clusters/create_agent_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Cluster agent registration', :js do
let_it_be(:project) { create(:project, :custom_repo, files: { '.gitlab/agents/example-agent-1/config.yaml' => '' }) }
let_it_be(:current_user) { create(:user, maintainer_projects: [project]) }
+ let_it_be(:token) { Devise.friendly_token }
before do
allow(Gitlab::Kas).to receive(:enabled?).and_return(true)
@@ -18,7 +19,7 @@ RSpec.describe 'Cluster agent registration', :js do
allow(client).to receive(:get_connected_agents).and_return([])
end
- allow(Devise).to receive(:friendly_token).and_return('example-agent-token')
+ allow(Devise).to receive(:friendly_token).and_return(token)
sign_in(current_user)
visit project_clusters_path(project)
@@ -33,7 +34,7 @@ RSpec.describe 'Cluster agent registration', :js do
click_button('Register')
expect(page).to have_content('You cannot see this token again after you close this window.')
- expect(page).to have_content('example-agent-token')
+ expect(page).to have_content(token)
expect(page).to have_content('helm upgrade --install')
expect(page).to have_content('example-agent-2')
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 03d61020ff0..7714783172f 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Value Stream Analytics', :js do
+ include CycleAnalyticsHelpers
+
let_it_be(:user) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:stage_table_selector) { '[data-testid="vsa-stage-table"]' }
@@ -213,14 +215,20 @@ RSpec.describe 'Value Stream Analytics', :js do
expect(page.find(metrics_selector)).not_to have_selector("#commits")
end
- it 'needs permissions to see restricted stages' do
+ it 'does not show restricted stages', :aggregate_failures do
expect(find(stage_table_selector)).to have_content(issue.title)
- click_stage('Code')
- expect(find(stage_table_selector)).to have_content('You need permission.')
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Issue')
+
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Plan')
+
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Test')
+
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Staging')
+
+ expect(page).not_to have_selector('.gl-path-nav-list-item', text: 'Code')
- click_stage('Review')
- expect(find(stage_table_selector)).to have_content('You need permission.')
+ expect(page).not_to have_selector('.gl-path-nav-list-item', text: 'Review')
end
end
diff --git a/spec/features/dashboard/archived_projects_spec.rb b/spec/features/dashboard/archived_projects_spec.rb
index 1b349fa2276..d157d44bab7 100644
--- a/spec/features/dashboard/archived_projects_spec.rb
+++ b/spec/features/dashboard/archived_projects_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Dashboard Archived Project' do
let(:user) { create :user }
- let(:project) { create :project}
+ let(:project) { create :project }
let(:archived_project) { create(:project, :archived) }
before do
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index f8b68be7f93..91901414dde 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -8,73 +8,41 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
let(:issue) { create(:issue, project: project) }
let(:merge_request) { create(:merge_request, source_project: project) }
- describe 'feature flag mr_attention_requests is disabled' do
- before do
- stub_feature_flags(mr_attention_requests: false)
-
- issue.assignees = [user]
- merge_request.update!(assignees: [user])
- sign_in(user)
- end
-
- it 'reflects dashboard issues count' do
- visit issues_path
-
- expect_counters('issues', '1', n_("%d assigned issue", "%d assigned issues", 1) % 1)
-
- issue.assignees = []
-
- user.invalidate_cache_counts
+ before do
+ issue.assignees = [user]
+ merge_request.update!(assignees: [user])
+ sign_in(user)
+ end
- travel_to(3.minutes.from_now) do
- visit issues_path
+ it 'reflects dashboard issues count' do
+ visit issues_path
- expect_counters('issues', '0', n_("%d assigned issue", "%d assigned issues", 0) % 0)
- end
- end
-
- it 'reflects dashboard merge requests count', :js do
- visit merge_requests_path
+ expect_counters('issues', '1', n_("%d assigned issue", "%d assigned issues", 1) % 1)
- expect_counters('merge_requests', '1', n_("%d merge request", "%d merge requests", 1) % 1)
+ issue.assignees = []
- merge_request.update!(assignees: [])
+ user.invalidate_cache_counts
- user.invalidate_cache_counts
-
- travel_to(3.minutes.from_now) do
- visit merge_requests_path
+ travel_to(3.minutes.from_now) do
+ visit issues_path
- expect_counters('merge_requests', '0', n_("%d merge request", "%d merge requests", 0) % 0)
- end
+ expect_counters('issues', '0', n_("%d assigned issue", "%d assigned issues", 0) % 0)
end
end
- describe 'feature flag mr_attention_requests is enabled' do
- before do
- merge_request.update!(assignees: [user])
-
- merge_request.find_assignee(user).update!(state: :attention_requested)
-
- user.invalidate_attention_requested_count
-
- sign_in(user)
- end
-
- it 'reflects dashboard merge requests count', :js do
- visit merge_requests_attention_path
+ it 'reflects dashboard merge requests count', :js do
+ visit merge_requests_path
- expect_counters('merge_requests', '1', n_("%d merge request", "%d merge requests", 1) % 1)
+ expect_counters('merge_requests', '1', n_("%d merge request", "%d merge requests", 1) % 1)
- merge_request.find_assignee(user).update!(state: :reviewed)
+ merge_request.update!(assignees: [])
- user.invalidate_attention_requested_count
+ user.invalidate_cache_counts
- travel_to(3.minutes.from_now) do
- visit merge_requests_attention_path
+ travel_to(3.minutes.from_now) do
+ visit merge_requests_path
- expect_counters('merge_requests', '0', n_("%d merge request", "%d merge requests", 0) % 0)
- end
+ expect_counters('merge_requests', '0', n_("%d merge request", "%d merge requests", 0) % 0)
end
end
@@ -86,10 +54,6 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
merge_requests_dashboard_path(assignee_username: user.username)
end
- def merge_requests_attention_path
- merge_requests_dashboard_path(attention: user.username)
- end
-
def expect_counters(issuable_type, count, badge_label)
dashboard_count = find('.gl-tabs-nav li a.active')
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index fd580b679ad..70f614cdcef 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -112,8 +112,8 @@ RSpec.describe 'Dashboard Merge Requests' do
end
it 'includes assigned and reviewers in badge' do
- within("span[aria-label='#{n_("%d merge request", "%d merge requests", 0) % 0}']") do
- expect(page).to have_content('0')
+ within("span[aria-label='#{n_("%d merge request", "%d merge requests", 3) % 3}']") do
+ expect(page).to have_content('3')
end
find('.dashboard-shortcuts-merge_requests').click
diff --git a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
index d5dbe259159..2ac43f67f64 100644
--- a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
+++ b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
@@ -10,8 +10,8 @@ RSpec.describe 'When a user filters Sentry errors by status', :js, :use_clean_ra
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_filter) { "#{sentry_api_urls.issues_url}?limit=20&query=is:ignored" }
- let(:auth_token) {{ 'Authorization' => 'Bearer access_token_123' }}
- let(:return_header) {{ 'Content-Type' => 'application/json' }}
+ let(:auth_token) { { 'Authorization' => 'Bearer access_token_123' } }
+ let(:return_header) { { 'Content-Type' => 'application/json' } }
before do
stub_request(:get, issues_api_url).with(headers: auth_token)
diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb
index 9af9baeb5bb..ab24162ad5a 100644
--- a/spec/features/group_variables_spec.rb
+++ b/spec/features/group_variables_spec.rb
@@ -23,7 +23,11 @@ RSpec.describe 'Group variables', :js do
it_behaves_like 'variable list'
end
- # TODO: Uncomment when the new graphQL app for variable settings
- # is enabled.
- # it_behaves_like 'variable list'
+ context 'with enabled ff `ci_variable_settings_graphql' do
+ before do
+ visit page_path
+ end
+
+ it_behaves_like 'variable list'
+ end
end
diff --git a/spec/features/groups/crm/contacts/create_spec.rb b/spec/features/groups/crm/contacts/create_spec.rb
index d6c6e3f1745..b10b2afe35c 100644
--- a/spec/features/groups/crm/contacts/create_spec.rb
+++ b/spec/features/groups/crm/contacts/create_spec.rb
@@ -22,7 +22,9 @@ RSpec.describe 'Create a CRM contact', :js do
fill_in 'description', with: 'VIP'
click_button 'Save changes'
- expect(page).to have_content 'gitlab@example.com'
+ wait_for_requests
+
+ expect(group.contacts.first.email).to eq('gitlab@example.com')
expect(page).to have_current_path("#{group_crm_contacts_path(group)}/", ignore_query: true)
end
end
diff --git a/spec/features/groups/group_runners_spec.rb b/spec/features/groups/group_runners_spec.rb
index a129db6cb6f..b98c94b030d 100644
--- a/spec/features/groups/group_runners_spec.rb
+++ b/spec/features/groups/group_runners_spec.rb
@@ -149,77 +149,39 @@ RSpec.describe "Group Runners" do
create(:ci_runner, :group, groups: [group], description: 'runner-foo', contacted_at: Time.zone.now)
end
- context 'when group_runner_view_ui is disabled' do
- before do
- stub_feature_flags(group_runner_view_ui: false)
- end
-
- it 'user edits the runner to be protected' do
- visit edit_group_runner_path(group, runner)
+ it 'user views runner details' do
+ visit group_runner_path(group, runner)
- expect(page.find_field('runner[access_level]')).not_to be_checked
-
- check 'runner_access_level'
- click_button 'Save changes'
-
- expect(page).to have_content 'Protected Yes'
- end
-
- context 'when a runner has a tag' do
- before do
- runner.update!(tag_list: ['tag'])
- end
+ expect(page).to have_content "#{s_('Runners|Description')} runner-foo"
+ end
- it 'user edits runner not to run untagged jobs' do
- visit edit_group_runner_path(group, runner)
+ it 'user edits the runner to be protected' do
+ visit edit_group_runner_path(group, runner)
- expect(page.find_field('runner[run_untagged]')).to be_checked
+ expect(page.find_field('runner[access_level]')).not_to be_checked
- uncheck 'runner_run_untagged'
- click_button 'Save changes'
+ check 'runner_access_level'
+ click_button _('Save changes')
- expect(page).to have_content 'Can run untagged jobs No'
- end
- end
+ expect(page).to have_content "#{s_('Runners|Configuration')} #{s_('Runners|Protected')}"
end
- context 'when group_runner_view_ui is enabled' do
+ context 'when a runner has a tag' do
before do
- stub_feature_flags(group_runner_view_ui: true)
+ runner.update!(tag_list: ['tag1'])
end
- it 'user views runner details' do
- visit group_runner_path(group, runner)
-
- expect(page).to have_content "#{s_('Runners|Description')} runner-foo"
- end
-
- it 'user edits the runner to be protected' do
+ it 'user edits runner not to run untagged jobs' do
visit edit_group_runner_path(group, runner)
- expect(page.find_field('runner[access_level]')).not_to be_checked
+ page.find_field('runner[tag_list]').set('tag1, tag2')
- check 'runner_access_level'
+ uncheck 'runner_run_untagged'
click_button _('Save changes')
- expect(page).to have_content "#{s_('Runners|Configuration')} #{s_('Runners|Protected')}"
- end
-
- context 'when a runner has a tag' do
- before do
- runner.update!(tag_list: ['tag'])
- end
-
- it 'user edits runner not to run untagged jobs' do
- visit edit_group_runner_path(group, runner)
-
- page.find_field('runner[tag_list]').set('tag, tag2')
-
- uncheck 'runner_run_untagged'
- click_button _('Save changes')
-
- expect(page).to have_content "#{s_('Runners|Tags')} tag tag2"
- end
+ # Tags can be in any order
+ expect(page).to have_content /#{s_('Runners|Tags')}.*tag1/
+ expect(page).to have_content /#{s_('Runners|Tags')}.*tag2/
end
end
end
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index c86705832b1..eec07c84cde 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -7,12 +7,12 @@ RSpec.describe 'Group issues page' do
include DragTo
let(:group) { create(:group) }
- let(:project) { create(:project, :public, group: group)}
+ let(:project) { create(:project, :public, group: group) }
let(:project_with_issues_disabled) { create(:project, :issues_disabled, group: group) }
let(:path) { issues_group_path(group) }
context 'with shared examples', :js do
- let(:issuable) { create(:issue, project: project, title: "this is my created issuable")}
+ let(:issuable) { create(:issue, project: project, title: "this is my created issuable") }
include_examples 'project features apply to issuables', Issue
@@ -68,7 +68,7 @@ RSpec.describe 'Group issues page' do
context 'issues list', :js do
let(:subgroup) { create(:group, parent: group) }
- let(:subgroup_project) { create(:project, :public, group: subgroup)}
+ let(:subgroup_project) { create(:project, :public, group: subgroup) }
let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
let!(:issue) { create(:issue, project: project, title: 'root group issue') }
let!(:subgroup_issue) { create(:issue, project: subgroup_project, title: 'subgroup issue') }
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index 468001c3be6..5f28afc23f1 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -74,8 +74,8 @@ RSpec.describe 'Groups > Members > Manage members' do
invite_member(user1.name, role: 'Reporter', refresh: false)
- expect(page).to have_selector(invite_modal_selector)
- expect(page).to have_content("not authorized to update member")
+ invite_modal = page.find(invite_modal_selector)
+ expect(invite_modal).to have_content("not authorized to update member")
page.refresh
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index 9a1e216c6d2..d814906a274 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe 'Group show page' do
it 'shows `Create new subgroup` link' do
expect(page).to have_link(
s_('GroupsEmptyState|Create new subgroup'),
- href: new_group_path(parent_id: group.id)
+ href: new_group_path(parent_id: group.id, anchor: 'create-group-pane')
)
end
@@ -97,28 +97,43 @@ RSpec.describe 'Group show page' do
end
end
- context 'when a public project is shared with a private group' do
- let_it_be(:private_group) { create(:group, :private) }
+ context 'visibility warning popover' do
let_it_be(:public_project) { create(:project, :public) }
- let_it_be(:project_group_link) { create(:project_group_link, group: private_group, project: public_project) }
- before do
- private_group.add_owner(user)
- sign_in(user)
- end
+ shared_examples 'it shows warning popover' do
+ it 'shows warning popover', :js do
+ group_to_share_with.add_owner(user)
+ sign_in(user)
+ visit group_path(group_to_share_with)
+
+ click_link _('Shared projects')
+
+ wait_for_requests
- it 'shows warning popover', :js do
- visit group_path(private_group)
+ page.within("[data-testid=\"group-overview-item-#{public_project.id}\"]") do
+ click_button _('Less restrictive visibility')
+ end
+
+ expect(page).to have_content _('Project visibility level is less restrictive than the group settings.')
+ end
+ end
- click_link _('Shared projects')
+ context 'when a public project is shared with a private group' do
+ let_it_be(:group_to_share_with) { create(:group, :private) }
+ let_it_be(:project_group_link) do
+ create(:project_group_link, group: group_to_share_with, project: public_project)
+ end
- wait_for_requests
+ include_examples 'it shows warning popover'
+ end
- page.within("[data-testid=\"group-overview-item-#{public_project.id}\"]") do
- click_button _('Less restrictive visibility')
+ context 'when a public project is shared with an internal group' do
+ let_it_be(:group_to_share_with) { create(:group, :internal) }
+ let_it_be(:project_group_link) do
+ create(:project_group_link, group: group_to_share_with, project: public_project)
end
- expect(page).to have_content _('Project visibility level is less restrictive than the group settings.')
+ include_examples 'it shows warning popover'
end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index ece6167b193..c93ed01b873 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -221,14 +221,13 @@ RSpec.describe 'Group' do
let(:user) { create(:admin) }
before do
- visit new_group_path(parent_id: group.id)
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
end
context 'when admin mode is enabled', :enable_admin_mode do
it 'creates a nested group' do
- click_link 'Create group'
- fill_in 'Group name', with: 'bar'
- click_button 'Create group'
+ fill_in 'Subgroup name', with: 'bar'
+ click_button 'Create subgroup'
expect(page).to have_current_path(group_path('foo/bar'), ignore_query: true)
expect(page).to have_selector 'h1', text: 'bar'
@@ -237,7 +236,7 @@ RSpec.describe 'Group' do
context 'when admin mode is disabled' do
it 'is not allowed' do
- expect(page).not_to have_button('Create group')
+ expect(page).not_to have_button('Create subgroup')
end
end
end
@@ -250,11 +249,10 @@ RSpec.describe 'Group' do
sign_out(:user)
sign_in(user)
- visit new_group_path(parent_id: group.id)
- click_link 'Create group'
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
- fill_in 'Group name', with: 'bar'
- click_button 'Create group'
+ fill_in 'Subgroup name', with: 'bar'
+ click_button 'Create subgroup'
expect(page).to have_current_path(group_path('foo/bar'), ignore_query: true)
expect(page).to have_selector 'h1', text: 'bar'
@@ -268,7 +266,7 @@ RSpec.describe 'Group' do
end
context 'when creating subgroup' do
- let(:path) { new_group_path(parent_id: group.id) }
+ let(:path) { new_group_path(parent_id: group.id, anchor: 'create-group-pane') }
it 'does not render recaptcha' do
visit path
@@ -278,24 +276,50 @@ RSpec.describe 'Group' do
end
end
+ context 'when many parent groups are available' do
+ let_it_be(:group2) { create(:group, path: 'foo2') }
+ let_it_be(:group3) { create(:group, path: 'foo3') }
+
+ before do
+ group.add_owner(user)
+ group2.add_maintainer(user)
+ group3.add_developer(user)
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
+ end
+
+ it 'creates private subgroup' do
+ fill_in 'Subgroup name', with: 'bar'
+ click_button 'foo'
+
+ expect(page).to have_css('[data-testid="select_group_dropdown_item"]', text: 'foo2')
+ expect(page).not_to have_css('[data-testid="select_group_dropdown_item"]', text: 'foo3')
+
+ click_button 'foo2'
+ click_button 'Create subgroup'
+
+ expect(page).to have_current_path(group_path('foo2/bar'), ignore_query: true)
+ expect(page).to have_selector('h1', text: 'bar')
+ expect(page).to have_selector('.visibility-icon [data-testid="lock-icon"]')
+ end
+ end
+
describe 'real-time group url validation', :js do
let_it_be(:subgroup) { create(:group, path: 'sub', parent: group) }
before do
group.add_owner(user)
- visit new_group_path(parent_id: group.id)
- click_link 'Create group'
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
end
it 'shows a message if group url is available' do
- fill_in 'Group URL', with: group.path
+ fill_in 'Subgroup slug', with: group.path
wait_for_requests
expect(page).to have_content('Group path is available')
end
it 'shows an error if group url is taken' do
- fill_in 'Group URL', with: subgroup.path
+ fill_in 'Subgroup slug', with: subgroup.path
wait_for_requests
expect(page).to have_content("Group path is unavailable. Path has been replaced with a suggested available path.")
@@ -308,7 +332,7 @@ RSpec.describe 'Group' do
sign_out(:user)
sign_in(create(:user))
- visit new_group_path(parent_id: group.id)
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
expect(page).to have_title('Not Found')
expect(page).to have_content('Page Not Found')
@@ -354,7 +378,7 @@ RSpec.describe 'Group' do
end
it 'removes group', :sidekiq_might_not_need_inline do
- expect { remove_with_confirm('Remove group', group.path) }.to change {Group.count}.by(-1)
+ expect { remove_with_confirm('Remove group', group.path) }.to change { Group.count }.by(-1)
expect(group.members.all.count).to be_zero
expect(page).to have_content "scheduled for deletion"
end
@@ -507,8 +531,8 @@ RSpec.describe 'Group' do
let_it_be(:storage_enforcement_date) { Date.today + 30 }
before do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -518,8 +542,8 @@ RSpec.describe 'Group' do
end
it 'does not display the banner in a paid group page' do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:paid?).and_return(true)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:paid?).and_return(true)
end
visit group_path(group)
expect_page_not_to_have_storage_enforcement_banner
@@ -534,8 +558,8 @@ RSpec.describe 'Group' do
expect_page_not_to_have_storage_enforcement_banner
storage_enforcement_date = Date.today + 13
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
page.refresh
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
@@ -543,8 +567,12 @@ RSpec.describe 'Group' do
end
context 'with storage_enforcement_date not set' do
- # This test should break and be rewritten after the implementation of the storage_enforcement_date
- # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ before do
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(nil)
+ end
+ end
+
it 'does not display the banner in the group page' do
stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
visit group_path(group)
@@ -554,10 +582,10 @@ RSpec.describe 'Group' do
end
def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
- expect(page).to have_text "From #{storage_enforcement_date} storage limits will apply to this namespace"
+ expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply"
end
def expect_page_not_to_have_storage_enforcement_banner
- expect(page).not_to have_text "storage limits will apply to this namespace"
+ expect(page).not_to have_text "namespace storage limits will apply"
end
end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index fe804dc52d7..1baa97096d9 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -182,12 +182,14 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
context 'email confirmation disabled' do
let(:send_email_confirmation) { false }
- it 'signs up and redirects to the most recent membership activity page with all the projects/groups invitations automatically accepted' do
- fill_in_sign_up_form(new_user)
- fill_in_welcome_form
+ context 'the user signs up for an account with the invitation email address' do
+ it 'redirects to the most recent membership activity page with all the projects/groups invitations automatically accepted' do
+ fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
- expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
- expect(page).to have_content('You have been granted Owner access to group Owned.')
+ expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
+ expect(page).to have_content('You have been granted Owner access to group Owned.')
+ end
end
context 'the user sign-up using a different email address' do
@@ -227,11 +229,13 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
end
- it 'signs up and redirects to the group activity page with all the project/groups invitation automatically accepted' do
- fill_in_sign_up_form(new_user)
- fill_in_welcome_form
+ context 'the user signs up for an account with the invitation email address' do
+ it 'redirects to the most recent membership activity page with all the projects/groups invitations automatically accepted' do
+ fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
- expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
+ expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
+ end
end
context 'the user sign-up using a different email address' do
diff --git a/spec/features/issuables/user_sees_sidebar_spec.rb b/spec/features/issuables/user_sees_sidebar_spec.rb
index 04bf704b6a4..66ed6044de6 100644
--- a/spec/features/issuables/user_sees_sidebar_spec.rb
+++ b/spec/features/issuables/user_sees_sidebar_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Issue Sidebar on Mobile' do
let(:project) { create(:project, :public, :repository) }
let(:merge_request) { create(:merge_request, source_project: project) }
let(:issue) { create(:issue, project: project) }
- let!(:user) { create(:user)}
+ let!(:user) { create(:user) }
before do
sign_in(user)
diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb
index 0700423983f..e749c555dcf 100644
--- a/spec/features/issues/form_spec.rb
+++ b/spec/features/issues/form_spec.rb
@@ -319,6 +319,13 @@ RSpec.describe 'New/edit issue', :js do
end
end
end
+
+ describe 'when repository contains CONTRIBUTING.md' do
+ it 'has contribution guidelines prompt' do
+ text = _('Please review the %{linkStart}contribution guidelines%{linkEnd} for this project.') % { linkStart: nil, linkEnd: nil }
+ expect(find('#new_issue')).to have_text(text)
+ end
+ end
end
describe 'new issue with query parameters' do
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 8732e2ecff2..fa4ce6fe1c1 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -414,7 +414,7 @@ RSpec.describe 'GFM autocomplete', :js do
it 'shows all contacts' do
page.within(find_autocomplete_menu) do
- expected_data = contacts.map { |c| "#{c.first_name} #{c.last_name} #{c.email}"}
+ expected_data = contacts.map { |c| "#{c.first_name} #{c.last_name} #{c.email}" }
expect(page.all('li').map(&:text)).to match_array(expected_data)
end
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
index d6ec7f1c539..56be1493ed2 100644
--- a/spec/features/issues/incident_issue_spec.rb
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Incident Detail', :js do
project.add_developer(user)
sign_in(user)
- visit project_issue_path(project, incident)
+ visit project_issues_incident_path(project, incident)
wait_for_requests
end
@@ -49,72 +49,32 @@ RSpec.describe 'Incident Detail', :js do
expect(incident_tabs).to have_content('Original alert: #1')
end
- aggregate_failures 'shows the Alert details tab' do
- click_link 'Alert details'
-
- expect(incident_tabs).to have_content('"title": "Alert title"')
- expect(incident_tabs).to have_content('"yet.another": 73')
- end
- end
- end
-
- context 'when on summary tab' do
- before do
- click_link 'Summary'
- end
-
- it 'shows the summary tab with all components' do
- page.within('.issuable-details') do
+ aggregate_failures 'when on summary tab (default tab)' do
hidden_items = find_all('.js-issue-widgets')
# Linked Issues/MRs and comment box
expect(hidden_items.count).to eq(2)
-
expect(hidden_items).to all(be_visible)
- end
- end
-
- it 'shows the edit title and description button' do
- edit_button = find_all('[aria-label="Edit title and description"]')
-
- expect(edit_button).to all(be_visible)
- end
- end
-
- context 'when on alert details tab' do
- before do
- click_link 'Alert details'
- end
-
- it 'does not show the linked issues and notes/comment components' do
- page.within('.issuable-details') do
- hidden_items = find_all('.js-issue-widgets')
- # Linked Issues/MRs and comment box are hidden on page
- expect(hidden_items.count).to eq(0)
+ edit_button = find_all('[aria-label="Edit title and description"]')
+ expect(edit_button).to all(be_visible)
end
- end
- it 'does not show the edit title and description button' do
- edit_button = find_all('[aria-label="Edit title and description"]')
-
- expect(edit_button.count).to eq(0)
- end
- end
+ aggregate_failures 'shows the Alert details tab' do
+ click_link 'Alert details'
- context 'when on timeline events tab from incident route' do
- before do
- visit project_issues_incident_path(project, incident)
- wait_for_requests
- click_link 'Timeline'
- end
+ expect(incident_tabs).to have_content('"title": "Alert title"')
+ expect(incident_tabs).to have_content('"yet.another": 73')
- it 'does not show the linked issues and notes/comment components' do
- page.within('.issuable-details') do
+ # does not show the linked issues and notes/comment components' do
hidden_items = find_all('.js-issue-widgets')
# Linked Issues/MRs and comment box are hidden on page
expect(hidden_items.count).to eq(0)
+
+ # does not show the edit title and description button
+ edit_button = find_all('[aria-label="Edit title and description"]')
+ expect(edit_button.count).to eq(0)
end
end
end
@@ -126,7 +86,7 @@ RSpec.describe 'Incident Detail', :js do
click_link 'Timeline'
end
- it 'does not show the linked issues and notes/comment commponents' do
+ it 'does not show the linked issues and notes/comment components' do
page.within('.issuable-details') do
hidden_items = find_all('.js-issue-widgets')
@@ -140,7 +100,7 @@ RSpec.describe 'Incident Detail', :js do
before do
stub_feature_flags(incident_timeline: false)
- visit project_issue_path(project, incident)
+ visit project_issues_incident_path(project, incident)
wait_for_requests
end
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index aaa478378a9..8819f085a5f 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -84,8 +84,10 @@ RSpec.describe 'Issue Sidebar' do
click_link user2.name
end
- find('.js-right-sidebar').click
- find('.block.assignee .edit-link').click
+ within '.js-right-sidebar' do
+ find('.block.assignee').click(x: 0, y: 0)
+ find('.block.assignee .edit-link').click
+ end
expect(page.all('.dropdown-menu-user li').length).to eq(1)
expect(find('.dropdown-input-field').value).to eq(user2.name)
@@ -182,7 +184,7 @@ RSpec.describe 'Issue Sidebar' do
page.within '.dropdown-menu-user' do
expect(page).not_to have_content 'Unassigned'
- click_link user2.name
+ click_button user2.name
end
find('.participants').click
diff --git a/spec/features/issues/related_issues_spec.rb b/spec/features/issues/related_issues_spec.rb
index a95229d4f1b..818e99f2ec9 100644
--- a/spec/features/issues/related_issues_spec.rb
+++ b/spec/features/issues/related_issues_spec.rb
@@ -232,7 +232,9 @@ RSpec.describe 'Related issues', :js do
it 'add related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "#{issue_b.to_reference(project)} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -249,7 +251,9 @@ RSpec.describe 'Related issues', :js do
it 'add cross-project related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "#{issue_project_b_a.to_reference(project)} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -359,7 +363,9 @@ RSpec.describe 'Related issues', :js do
it 'add related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "##{issue_d.iid} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -375,7 +381,9 @@ RSpec.describe 'Related issues', :js do
it 'add invalid related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: '#9999999 '
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -390,7 +398,9 @@ RSpec.describe 'Related issues', :js do
it 'add unauthorized related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "#{issue_project_unauthorized_a.to_reference(project)} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
diff --git a/spec/features/issues/todo_spec.rb b/spec/features/issues/todo_spec.rb
index d63d21353e5..6a53c12eda3 100644
--- a/spec/features/issues/todo_spec.rb
+++ b/spec/features/issues/todo_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Manually create a todo item from issue', :js do
let!(:project) { create(:project) }
let!(:issue) { create(:issue, project: project) }
- let!(:user) { create(:user)}
+ let!(:user) { create(:user) }
before do
project.add_maintainer(user)
diff --git a/spec/features/issues/user_bulk_edits_issues_spec.rb b/spec/features/issues/user_bulk_edits_issues_spec.rb
index 0533f1688e2..1ef2918adec 100644
--- a/spec/features/issues/user_bulk_edits_issues_spec.rb
+++ b/spec/features/issues/user_bulk_edits_issues_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Multiple issue updating from issues#index', :js do
let!(:project) { create(:project) }
let!(:issue) { create(:issue, project: project) }
- let!(:user) { create(:user)}
+ let!(:user) { create(:user) }
before do
project.add_maintainer(user)
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 151d3c60fa2..e29911e3263 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -151,7 +151,7 @@ RSpec.describe "User creates issue" do
click_button 'Cancel'
end
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_button('Cancel')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
@@ -188,7 +188,7 @@ RSpec.describe "User creates issue" do
end
it 'does not hide the milestone select' do
- expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]')
end
end
@@ -204,7 +204,7 @@ RSpec.describe "User creates issue" do
end
it 'shows the milestone select' do
- expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]')
end
it 'hides the incident help text' do
@@ -265,7 +265,7 @@ RSpec.describe "User creates issue" do
end
it 'shows the milestone select' do
- expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]')
end
it 'hides the weight input' do
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 3b440002cb5..4eecb63c47e 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe "Issues > User edits issue", :js do
page.within '.block.labels' do
# Remove `verisimilitude` label
- within '.gl-label' do
+ within '.gl-label', text: 'verisimilitude' do
click_button 'Remove label'
end
@@ -285,7 +285,7 @@ RSpec.describe "Issues > User edits issue", :js do
end
page.within '.dropdown-menu-user' do
- click_link user.name
+ click_button user.name
end
page.within('.assignee') do
@@ -306,7 +306,7 @@ RSpec.describe "Issues > User edits issue", :js do
click_button('Edit')
wait_for_requests
- click_link user.name
+ click_button user.name
find('[data-testid="title"]').click
wait_for_requests
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 892b57bac5c..c86a2c32e2d 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'User interacts with awards' do
let(:user) { create(:user) }
describe 'User interacts with awards in an issue', :js do
- let(:issue) { create(:issue, project: project)}
+ let(:issue) { create(:issue, project: project) }
let(:project) { create(:project) }
before do
diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb
index c6d743ed38f..d458c991668 100644
--- a/spec/features/issues/user_uses_quick_actions_spec.rb
+++ b/spec/features/issues/user_uses_quick_actions_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'Issues > User uses quick actions', :js do
let!(:label_feature) { create(:label, project: project, title: 'feature') }
let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
let(:issuable) { create(:issue, project: project) }
- let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])}
+ let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature]) }
it_behaves_like 'close quick action', :issue
it_behaves_like 'issuable time tracker', :issue
diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb
index d472134a2c7..b5bf9279371 100644
--- a/spec/features/markdown/copy_as_gfm_spec.rb
+++ b/spec/features/markdown/copy_as_gfm_spec.rb
@@ -109,10 +109,24 @@ RSpec.describe 'Copy as GFM', :js do
<<~GFM,
* [ ] Unchecked task
* [x] Checked task
+ * [~] Inapplicable task
+ * [~] Inapplicable task with ~~del~~ and <s>strike</s> embedded
GFM
- <<~GFM
+ <<~GFM,
1. [ ] Unchecked ordered task
1. [x] Checked ordered task
+ 1. [~] Inapplicable ordered task
+ 1. [~] Inapplicable ordered task with ~~del~~ and <s>strike</s> embedded
+ GFM
+ <<~GFM
+ * [ ] Unchecked loose list task
+ * [x] Checked loose list task
+ * [~] Inapplicable loose list task
+
+ With a paragraph
+ * [~] Inapplicable loose list task with ~~del~~ and <s>strike</s> embedded
+
+ With a paragraph
GFM
)
@@ -605,7 +619,8 @@ RSpec.describe 'Copy as GFM', :js do
'###### Heading',
'**Bold**',
'*Italics*',
- '~~Strikethrough~~',
+ '~~Strikethrough (del)~~',
+ '<s>Strikethrough</s>',
'---',
# table
<<~GFM,
diff --git a/spec/features/markdown/gitlab_flavored_markdown_spec.rb b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
index da4208318eb..e831d1be608 100644
--- a/spec/features/markdown/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe "GitLab Flavored Markdown" do
+ include CycleAnalyticsHelpers
+
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:issue) { create(:issue, project: project) }
diff --git a/spec/features/markdown/json_table_spec.rb b/spec/features/markdown/json_table_spec.rb
new file mode 100644
index 00000000000..6b74dbac255
--- /dev/null
+++ b/spec/features/markdown/json_table_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Rendering json:table code block in markdown', :js do
+ let_it_be(:project) { create(:project, :public) }
+
+ it 'creates table correctly' do
+ description = <<~JSONTABLE
+ Hello world!
+
+ ```json:table
+ {
+ "fields" : [
+ {"key": "a", "label": "AA"},
+ {"key": "b", "label": "BB"}
+ ],
+ "items" : [
+ {"a": "11", "b": "22"},
+ {"a": "211", "b": "222"}
+ ]
+ }
+ ```
+ JSONTABLE
+
+ issue = create(:issue, project: project, description: description)
+
+ visit project_issue_path(project, issue)
+
+ wait_for_requests
+
+ within ".js-json-table table" do
+ headers = all("thead th").collect { |column| column.text.strip }
+ data = all("tbody td").collect { |column| column.text.strip }
+
+ expect(headers).to eql(%w[AA BB])
+ expect(data).to eql(%w[11 22 211 222])
+ end
+ end
+end
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index fafaea8ac68..f892b01e624 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
write_diff_comment
- visit_overview
+ visit_overview_with_pending_comment
end
it 'can add comment to review' do
@@ -232,6 +232,14 @@ RSpec.describe 'Merge request > Batch comments', :js do
wait_for_requests
end
+ def visit_overview_with_pending_comment
+ accept_alert do
+ visit project_merge_request_path(merge_request.project, merge_request)
+ end
+
+ wait_for_requests
+ end
+
def write_diff_comment(**params)
click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[0][:line_code]}']"))
diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb
index a98bfd1c8a4..39d948bb6fb 100644
--- a/spec/features/merge_request/maintainer_edits_fork_spec.rb
+++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork', :js, :sidekiq_might_not_need_inline do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include ProjectForksHelper
let(:user) { create(:user, username: 'the-maintainer') }
let(:target_project) { create(:project, :public, :repository) }
@@ -40,12 +41,13 @@ RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork
end
it 'allows committing to the source branch' do
- execute_script("monaco.editor.getModels()[0].setValue('Updated the readme')")
+ content = 'Updated the readme'
+ editor_set_value(content)
click_button 'Commit changes'
wait_for_requests
expect(page).to have_content('Your changes have been successfully committed')
- expect(page).to have_content('Updated the readme')
+ expect(page).to have_content(content)
end
end
diff --git a/spec/features/merge_request/user_approves_spec.rb b/spec/features/merge_request/user_approves_spec.rb
index 4f7bcb58551..9670012803e 100644
--- a/spec/features/merge_request/user_approves_spec.rb
+++ b/spec/features/merge_request/user_approves_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Merge request > User approves', :js do
def verify_approvals_count_on_index!
visit(project_merge_requests_path(project, state: :all))
- expect(page.all('li').any? { |item| item["title"] == "1 approver (you've approved)"}).to be true
+ expect(page.all('li').any? { |item| item["title"] == "1 approver (you've approved)" }).to be true
visit project_merge_request_path(project, merge_request)
end
diff --git a/spec/features/merge_request/user_comments_on_merge_request_spec.rb b/spec/features/merge_request/user_comments_on_merge_request_spec.rb
index 43096f8e7f9..dbcfc2b968f 100644
--- a/spec/features/merge_request/user_comments_on_merge_request_spec.rb
+++ b/spec/features/merge_request/user_comments_on_merge_request_spec.rb
@@ -51,6 +51,45 @@ RSpec.describe 'User comments on a merge request', :js do
expect(page).to have_button('Resolve thread')
end
+ array = [':', '@', '#', '%', '!', '~', '$', '[contact:']
+ array.each do |x|
+ it 'handles esc key correctly when atwho is active' do
+ page.within('.js-main-target-form') do
+ fill_in('note[note]', with: 'comment 1')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ page.within('.note') do
+ click_button('Reply to comment')
+ fill_in('note[note]', with: x)
+ send_keys :escape
+ end
+
+ wait_for_requests
+ expect(page.html).not_to include('Are you sure you want to cancel creating this comment?')
+ end
+ end
+
+ it 'handles esc key correctly when atwho is not active' do
+ page.within('.js-main-target-form') do
+ fill_in('note[note]', with: 'comment 1')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ page.within('.note') do
+ click_button('Reply to comment')
+ fill_in('note[note]', with: 'comment 2')
+ send_keys :escape
+ end
+
+ wait_for_requests
+ expect(page.html).to include('Are you sure you want to cancel creating this comment?')
+ end
+
it 'loads new comment' do
# Add new comment in background in order to check
# if it's going to be loaded automatically for current user.
diff --git a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
index 059e1eb89c5..f0c0142a6cc 100644
--- a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
+++ b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe 'Merge request < User customizes merge commit message', :js do
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
- let(:issue_1) { create(:issue, project: project)}
- let(:issue_2) { create(:issue, project: project)}
+ let(:issue_1) { create(:issue, project: project) }
+ let(:issue_2) { create(:issue, project: project) }
let(:source_branch) { 'csv' }
let(:target_branch) { 'master' }
let(:squash) { false }
diff --git a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
index 92b9b785148..0dd87ac3e24 100644
--- a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
+++ b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe 'Merge request > User edits assignees sidebar', :js do
context 'when GraphQL assignees widget feature flag is enabled' do
let(:sidebar_assignee_dropdown_item) { sidebar_assignee_block.find(".dropdown-item", text: assignee.username ) }
- let(:sidebar_assignee_dropdown_tooltip) { sidebar_assignee_dropdown_item['title']}
+ let(:sidebar_assignee_dropdown_tooltip) { sidebar_assignee_dropdown_item['title'] }
context 'when user is an owner' do
before do
diff --git a/spec/features/merge_request/user_merges_merge_request_spec.rb b/spec/features/merge_request/user_merges_merge_request_spec.rb
index 6a9a30953df..c91dc7b1c00 100644
--- a/spec/features/merge_request/user_merges_merge_request_spec.rb
+++ b/spec/features/merge_request/user_merges_merge_request_spec.rb
@@ -21,27 +21,6 @@ RSpec.describe "User merges a merge request", :js do
end
end
- context "ff-only merge" do
- let(:project) { create(:project, :public, :repository, merge_requests_ff_only_enabled: true) }
-
- before do
- stub_feature_flags(restructured_mr_widget: false)
- visit(merge_request_path(merge_request))
- end
-
- context "when branch is rebased" do
- let!(:merge_request) { create(:merge_request, :rebased, source_project: project) }
-
- it_behaves_like "fast forward merge a merge request"
- end
-
- context "when branch is merged" do
- let!(:merge_request) { create(:merge_request, :merged_target, source_project: project) }
-
- it_behaves_like "fast forward merge a merge request"
- end
- end
-
context 'sidebar merge requests counter' do
let(:project) { create(:project, :public, :repository) }
let!(:merge_request) { create(:merge_request, source_project: project) }
diff --git a/spec/features/merge_request/user_opens_context_commits_modal_spec.rb b/spec/features/merge_request/user_opens_context_commits_modal_spec.rb
new file mode 100644
index 00000000000..2d574e57fe9
--- /dev/null
+++ b/spec/features/merge_request/user_opens_context_commits_modal_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge request > Context commits', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+
+ before do
+ project.add_developer(user)
+
+ sign_in(user)
+
+ visit commits_project_merge_request_path(project, merge_request)
+
+ wait_for_requests
+ end
+
+ it 'opens modal' do
+ click_button 'Add previously merged commits'
+
+ expect(page).to have_selector('#add-review-item')
+ expect(page).to have_content('Add or remove previously merged commits')
+ end
+end
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index d461170c990..1eebb6c2e28 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -19,7 +19,6 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
project.add_developer(user)
sign_in(user)
- stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 104)
end
context 'when hovering over a parallel view diff file' do
diff --git a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb
index 7b7fff5c936..f56db3d3dbe 100644
--- a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb
+++ b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe 'Merge request > User sees closing issues message', :js do
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
- let(:issue_1) { create(:issue, project: project)}
- let(:issue_2) { create(:issue, project: project)}
+ let(:issue_1) { create(:issue, project: project) }
+ let(:issue_2) { create(:issue, project: project) }
let(:merge_request) do
create(
:merge_request,
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index e045f11c0d8..c02149eed87 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
let(:ref) { merge_request.target_branch }
let(:sha) { project.commit(ref).id }
let(:pipeline) { create(:ci_pipeline, sha: sha, project: project, ref: ref) }
- let!(:manual) { }
+ let!(:manual) {}
let(:build) { create(:ci_build, :with_deployment, environment: environment.name, pipeline: pipeline) }
let!(:deployment) { build.deployment }
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index 50f4cce5c23..2e65183d26f 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
context 'when file contains html' do
let(:current_user) { project.first_owner }
- let(:branch_name) {"test_branch"}
+ let(:branch_name) { "test_branch" }
it 'escapes any HTML special characters in the diff chunk header' do
file_content =
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index 09c6b6bce3b..2a1b9ea6009 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
}
end
- let(:expected_detached_mr_tag) {'merge request'}
+ let(:expected_detached_mr_tag) { 'merge request' }
before do
stub_application_setting(auto_devops_enabled: false)
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 16b1de0393f..11e542916f9 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -78,9 +78,18 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
it 'user visits merge request page' do
page.within('.merge-request-tabs') do
- expect(page).to have_no_link('Pipelines')
+ expect(page).to have_link('Pipelines')
end
end
+
+ it 'shows empty state with run pipeline button' do
+ page.within('.merge-request-tabs') do
+ click_link('Pipelines')
+ end
+
+ expect(page).to have_content('There are currently no pipelines.')
+ expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run pipeline')
+ end
end
end
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 2c2a2dfd4a8..0e86e970f46 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -232,7 +232,7 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it 'only shows diffs from the commit' do
- diff_commit_ids = find_all('.diff-file [data-commit-id]').map {|diff| diff['data-commit-id']}
+ diff_commit_ids = find_all('.diff-file [data-commit-id]').map { |diff| diff['data-commit-id'] }
expect(diff_commit_ids).not_to be_empty
expect(diff_commit_ids).to all(eq(params[:commit_id]))
diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb
index b48659353ec..563120fc8b7 100644
--- a/spec/features/merge_request/user_uses_quick_actions_spec.rb
+++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Merge request > User uses quick actions', :js do
let!(:label_feature) { create(:label, project: project, title: 'feature') }
let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
let(:issuable) { create(:merge_request, source_project: project) }
- let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])}
+ let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature]) }
it_behaves_like 'close quick action', :merge_request
it_behaves_like 'issuable time tracker', :merge_request
diff --git a/spec/features/merge_requests/user_mass_updates_spec.rb b/spec/features/merge_requests/user_mass_updates_spec.rb
index fa866beb773..cf9760bcd7f 100644
--- a/spec/features/merge_requests/user_mass_updates_spec.rb
+++ b/spec/features/merge_requests/user_mass_updates_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe 'Merge requests > User mass updates', :js do
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
before do
- stub_feature_flags(mr_attention_requests: false)
-
project.add_maintainer(user)
project.add_maintainer(user2)
sign_in(user)
@@ -63,18 +61,6 @@ RSpec.describe 'Merge requests > User mass updates', :js do
expect(find('.merge-request')).to have_link "Assigned to #{user.name}"
end
-
- describe 'with attention requests feature flag on' do
- before do
- stub_feature_flags(mr_attention_requests: true)
- end
-
- it 'updates merge request with assignee' do
- change_assignee(user2.name)
-
- expect(find('.issuable-meta a.author-link')[:title]).to eq "Attention requested from assignee #{user2.name}"
- end
- end
end
describe 'remove assignee' do
diff --git a/spec/features/oauth_registration_spec.rb b/spec/features/oauth_registration_spec.rb
index 18dd10755b1..cb8343b8065 100644
--- a/spec/features/oauth_registration_spec.rb
+++ b/spec/features/oauth_registration_spec.rb
@@ -85,7 +85,46 @@ RSpec.describe 'OAuth Registration', :js, :allow_forgery_protection do
expect(page).to have_content('Please complete your profile with email address')
end
end
+
+ context 'when registering via an invitation email' do
+ let_it_be(:owner) { create(:user) }
+ let_it_be(:group) { create(:group, name: 'Owned') }
+ let_it_be(:project) { create(:project, :repository, namespace: group) }
+
+ let(:invite_email) { generate(:email) }
+ let(:extra_params) { { invite_type: Emails::Members::INITIAL_INVITE } }
+ let(:group_invite) do
+ create(
+ :group_member, :invited,
+ group: group,
+ invite_email: invite_email,
+ created_by: owner
+ )
+ end
+
+ before do
+ project.add_maintainer(owner)
+ group.add_owner(owner)
+ group_invite.generate_invite_token!
+
+ mock_auth_hash(provider, uid, invite_email, additional_info: additional_info)
+ end
+
+ it 'redirects to the activity page with all the projects/groups invitations accepted' do
+ visit invite_path(group_invite.raw_invite_token, extra_params)
+ click_link_or_button "oauth-login-#{provider}"
+ fill_in_welcome_form
+
+ expect(page).to have_content('You have been granted Owner access to group Owned.')
+ expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
+ end
+ end
end
end
end
+
+ def fill_in_welcome_form
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
+ end
end
diff --git a/spec/features/populate_new_pipeline_vars_with_params_spec.rb b/spec/features/populate_new_pipeline_vars_with_params_spec.rb
index 937f99558ad..744543d1252 100644
--- a/spec/features/populate_new_pipeline_vars_with_params_spec.rb
+++ b/spec/features/populate_new_pipeline_vars_with_params_spec.rb
@@ -16,7 +16,6 @@ RSpec.describe "Populate new pipeline CI variables with url params", :js do
it "var[key1]=value1 populates env_var variable correctly" do
page.within(all("[data-testid='ci-variable-row']")[0]) do
- expect(find("[data-testid='pipeline-form-ci-variable-type']").value).to eq('env_var')
expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key1')
expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value1')
end
@@ -24,7 +23,6 @@ RSpec.describe "Populate new pipeline CI variables with url params", :js do
it "file_var[key2]=value2 populates file variable correctly" do
page.within(all("[data-testid='ci-variable-row']")[1]) do
- expect(find("[data-testid='pipeline-form-ci-variable-type']").value).to eq('file')
expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key2')
expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value2')
end
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 1013937ebb9..2836ac2f801 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Profile account page', :js do
it 'deletes user', :js, :sidekiq_might_not_need_inline do
click_button 'Delete account'
- fill_in 'password', with: '12345678'
+ fill_in 'password', with: user.password
page.within '.modal' do
click_button 'Delete account'
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 07dfbca8cbd..1d0db488751 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe 'Profile > Password' do
end
context 'Password authentication enabled' do
+ let(:new_password) { User.random_password }
let(:user) { create(:user, password_automatically_set: true) }
before do
@@ -23,7 +24,7 @@ RSpec.describe 'Profile > Password' do
context 'User with password automatically set' do
describe 'User puts different passwords in the field and in the confirmation' do
it 'shows an error message' do
- fill_passwords('mypassword', 'mypassword2')
+ fill_passwords(new_password, "#{new_password}2")
page.within('.gl-alert-danger') do
expect(page).to have_content("Password confirmation doesn't match Password")
@@ -31,7 +32,7 @@ RSpec.describe 'Profile > Password' do
end
it 'does not contain the current password field after an error' do
- fill_passwords('mypassword', 'mypassword2')
+ fill_passwords(new_password, "#{new_password}2")
expect(page).to have_no_field('user[current_password]')
end
@@ -39,7 +40,7 @@ RSpec.describe 'Profile > Password' do
describe 'User puts the same passwords in the field and in the confirmation' do
it 'shows a success message' do
- fill_passwords('mypassword', 'mypassword')
+ fill_passwords(new_password, new_password)
page.within('[data-testid="alert-info"]') do
expect(page).to have_content('Password was successfully updated. Please sign in again.')
@@ -79,7 +80,7 @@ RSpec.describe 'Profile > Password' do
end
context 'Change password' do
- let(:new_password) { '22233344' }
+ let(:new_password) { User.random_password }
before do
sign_in(user)
@@ -156,6 +157,8 @@ RSpec.describe 'Profile > Password' do
end
context 'when password is expired' do
+ let(:new_password) { User.random_password }
+
before do
sign_in(user)
@@ -170,8 +173,8 @@ RSpec.describe 'Profile > Password' do
expect(page).to have_current_path new_profile_password_path, ignore_query: true
fill_in :user_password, with: user.password
- fill_in :user_new_password, with: '12345678'
- fill_in :user_password_confirmation, with: '12345678'
+ fill_in :user_new_password, with: new_password
+ fill_in :user_password_confirmation, with: new_password
click_button 'Set new password'
expect(page).to have_current_path new_user_session_path, ignore_query: true
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index bca1bc4df4d..088c8a7a15a 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -146,12 +146,6 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
end
end
- it 'pushes `personal_access_tokens_scoped_to_projects` feature flag to the frontend' do
- visit profile_personal_access_tokens_path
-
- expect(page).to have_pushed_frontend_feature_flags(personalAccessTokensScopedToProjects: true)
- end
-
it "prefills token details" do
name = 'My PAT'
scopes = 'api,read_user'
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index 4b6ed458c68..2f7b722f553 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -294,7 +294,7 @@ RSpec.describe 'User edit profile' do
end
context 'user menu' do
- let(:issue) { create(:issue, project: project)}
+ let(:issue) { create(:issue, project: project) }
let(:project) { create(:project) }
def open_modal(button_text)
@@ -536,7 +536,7 @@ RSpec.describe 'User edit profile' do
end
context 'User time preferences', :js do
- let(:issue) { create(:issue, project: project)}
+ let(:issue) { create(:issue, project: project) }
let(:project) { create(:project) }
before do
diff --git a/spec/features/profiles/user_visits_profile_spec.rb b/spec/features/profiles/user_visits_profile_spec.rb
index 8b1af283765..7dd2e6aafa3 100644
--- a/spec/features/profiles/user_visits_profile_spec.rb
+++ b/spec/features/profiles/user_visits_profile_spec.rb
@@ -97,8 +97,8 @@ RSpec.describe 'User visits their profile' do
let_it_be(:storage_enforcement_date) { Date.today + 30 }
before do
- allow_next_found_instance_of(Namespaces::UserNamespace) do |g|
- allow(g).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -115,8 +115,8 @@ RSpec.describe 'User visits their profile' do
expect_page_not_to_have_storage_enforcement_banner
storage_enforcement_date = Date.today + 13
- allow_next_found_instance_of(Namespaces::UserNamespace) do |g|
- allow(g).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
page.refresh
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
@@ -124,8 +124,12 @@ RSpec.describe 'User visits their profile' do
end
context 'with storage_enforcement_date not set' do
- # This test should break and be rewritten after the implementation of the storage_enforcement_date
- # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ before do
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(nil)
+ end
+ end
+
it 'does not display the banner in the group page' do
visit(profile_path)
expect_page_not_to_have_storage_enforcement_banner
@@ -134,10 +138,10 @@ RSpec.describe 'User visits their profile' do
end
def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
- expect(page).to have_text "From #{storage_enforcement_date} storage limits will apply to this namespace"
+ expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply"
end
def expect_page_not_to_have_storage_enforcement_banner
- expect(page).not_to have_text "storage limits will apply to this namespace"
+ expect(page).not_to have_text "namespace storage limits will apply"
end
end
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index f5cafa2b2ec..13a4c1b5912 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -137,7 +137,7 @@ RSpec.describe 'File blob', :js do
context 'when ref switch' do
def switch_ref_to(ref_name)
- first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
+ first('[data-testid="branches-select"]').click
page.within '.project-refs-form' do
click_link ref_name
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index 54176378de8..f198a1f42e2 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Editing file blob', :js do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include TreeHelper
include BlobSpecHelpers
@@ -42,7 +43,7 @@ RSpec.describe 'Editing file blob', :js do
def fill_editor(content: 'class NextFeature\\nend\\n')
wait_for_requests
- execute_script("monaco.editor.getModels()[0].setValue('#{content}')")
+ editor_set_value(content)
end
context 'from MR diff' do
@@ -98,10 +99,8 @@ RSpec.describe 'Editing file blob', :js do
click_link 'Preview changes'
wait_for_requests
- old_line_count = page.all('.line_holder.old').size
new_line_count = page.all('.line_holder.new').size
- expect(old_line_count).to be > 0
expect(new_line_count).to be > 0
end
end
diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb
index 7f10c6afcd5..608511ae5a5 100644
--- a/spec/features/projects/ci/lint_spec.rb
+++ b/spec/features/projects/ci/lint_spec.rb
@@ -16,16 +16,13 @@ RSpec.describe 'CI Lint', :js do
visit project_ci_lint_path(project)
editor_set_value(yaml_content)
-
- wait_for('YAML content') do
- find(content_selector).text.present?
- end
end
describe 'YAML parsing' do
shared_examples 'validates the YAML' do
before do
click_on 'Validate'
+ scroll_to(page.find('[data-testid="ci-lint-status"]'))
end
context 'YAML is correct' do
diff --git a/spec/features/projects/ci/secure_files_spec.rb b/spec/features/projects/ci/secure_files_spec.rb
deleted file mode 100644
index 412330eb5d6..00000000000
--- a/spec/features/projects/ci/secure_files_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Secure Files', :js do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
-
- before do
- stub_feature_flags(ci_secure_files_read_only: false)
- project.add_maintainer(user)
- sign_in(user)
- end
-
- it 'user sees the Secure Files list component' do
- visit project_ci_secure_files_path(project)
- expect(page).to have_content('There are no secure files yet.')
- end
-
- it 'prompts the user to confirm before deleting a file' do
- file = create(:ci_secure_file, project: project)
-
- visit project_ci_secure_files_path(project)
-
- expect(page).to have_content(file.name)
-
- find('button.btn-danger').click
-
- expect(page).to have_content("Delete #{file.name}?")
-
- click_on('Delete secure file')
-
- visit project_ci_secure_files_path(project)
-
- expect(page).not_to have_content(file.name)
- end
-
- it 'displays an uploaded file in the file list' do
- visit project_ci_secure_files_path(project)
- expect(page).to have_content('There are no secure files yet.')
-
- page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
- click_button 'Upload File'
- end
-
- expect(page).to have_content('upload-keystore.jks')
- end
-
- it 'displays an error when a duplicate file upload is attempted' do
- create(:ci_secure_file, project: project, name: 'upload-keystore.jks')
- visit project_ci_secure_files_path(project)
-
- expect(page).to have_content('upload-keystore.jks')
-
- page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
- click_button 'Upload File'
- end
-
- expect(page).to have_content('A file with this name already exists.')
- end
-end
diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb
index 5d931afe4a7..8c557a9c37a 100644
--- a/spec/features/projects/cluster_agents_spec.rb
+++ b/spec/features/projects/cluster_agents_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'ClusterAgents', :js do
- let_it_be(:token) { create(:cluster_agent_token, description: 'feature test token')}
+ let_it_be(:token) { create(:cluster_agent_token, description: 'feature test token') }
let(:agent) { token.agent }
let(:project) { agent.project }
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 863fdbdadaa..2719316c5dc 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -150,7 +150,7 @@ RSpec.describe 'User browses commits' do
let(:ref) { project.repository.root_ref }
let(:newrev) { project.repository.commit('master').sha }
let(:short_newrev) { project.repository.commit('master').short_id }
- let(:message) { 'Glob characters'}
+ let(:message) { 'Glob characters' }
before do
create_file_in_repo(project, ref, ref, filename, 'Test file', commit_message: message)
diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb
index bc3ef2af9b0..22b0f344606 100644
--- a/spec/features/projects/compare_spec.rb
+++ b/spec/features/projects/compare_spec.rb
@@ -113,7 +113,7 @@ RSpec.describe "Compare", :js do
click_button('Compare')
- page.within('.gl-alert') do
+ page.within('[data-testid="too-many-changes-alert"]') do
expect(page).to have_text("Too many changes to show. To preserve performance only 3 of 3+ files are displayed.")
end
end
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 951b24eafac..a53e8beb555 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -18,10 +18,10 @@ RSpec.describe 'Environment' do
describe 'environment details page' do
let!(:environment) { create(:environment, project: project) }
- let!(:permissions) { }
- let!(:deployment) { }
- let!(:action) { }
- let!(:cluster) { }
+ let!(:permissions) {}
+ let!(:deployment) {}
+ let!(:action) {}
+ let!(:cluster) {}
context 'with auto-stop' do
let!(:environment) { create(:environment, :will_auto_stop, name: 'staging', project: project) }
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 6b1e60db5b1..0ad44f31a52 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license
expect(page).to have_current_path("/-/ide/project/#{project.full_path}/edit/master/-/LICENSE", ignore_query: true)
- expect(page).to have_selector('.qa-file-templates-bar') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="file-templates-bar"]')
select_template('MIT License')
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index 53fdd5a15dd..0f3ce5a2bad 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -348,7 +348,7 @@ RSpec.describe "User browses files", :js do
end
it "shows raw file content in a new tab" do
- new_tab = window_opened_by {click_link 'Open raw'}
+ new_tab = window_opened_by { click_link 'Open raw' }
within_window new_tab do
expect(page).to have_content("Test file")
@@ -366,7 +366,7 @@ RSpec.describe "User browses files", :js do
end
it "shows raw file content in a new tab" do
- new_tab = window_opened_by {click_link 'Open raw'}
+ new_tab = window_opened_by { click_link 'Open raw' }
within_window new_tab do
expect(page).to have_content("*.rbc")
diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb
index 7344c91b6dc..a81f31d663e 100644
--- a/spec/features/projects/files/user_creates_files_spec.rb
+++ b/spec/features/projects/files/user_creates_files_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User creates files', :js do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include BlobSpecHelpers
let(:fork_message) do
@@ -89,8 +90,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
end
it 'creates and commit a new file' do
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -107,8 +107,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
it 'creates and commit a new file with new lines at the end of file' do
set_default_button('edit')
- find('#editor')
- execute_script('monaco.editor.getModels()[0].setValue("Sample\n\n\n")')
+ editor_set_value('Sample\n\n\n')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -119,8 +118,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
click_link('Edit')
- find('#editor')
- expect(evaluate_script('monaco.editor.getModels()[0].getValue()')).to eq("Sample\n\n\n")
+ expect(find('.monaco-editor')).to have_content('Sample\n\n\n')
end
it 'creates and commit a new file with a directory name' do
@@ -128,8 +126,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
expect(page).to have_selector('.file-editor')
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -143,8 +140,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
it 'creates and commit a new file specifying a new branch' do
expect(page).to have_selector('.file-editor')
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
fill_in(:branch_name, with: 'new_branch_name', visible: true)
@@ -178,8 +174,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
it 'creates and commit new file in forked project' do
expect(page).to have_selector('.file-editor')
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb
index 1ac45970828..d7460538be9 100644
--- a/spec/features/projects/files/user_edits_files_spec.rb
+++ b/spec/features/projects/files/user_edits_files_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User edits files', :js do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include ProjectForksHelper
include BlobSpecHelpers
@@ -50,10 +51,9 @@ RSpec.describe 'Projects > Files > User edits files', :js do
click_link_or_button('Edit')
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
- expect(editor_value).to eq('*.rbca')
+ expect(find('.monaco-editor')).to have_content('*.rbca')
end
it 'does not show the edit link if a file is binary' do
@@ -72,8 +72,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
click_link_or_button('Edit')
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -91,8 +90,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
fill_in(:branch_name, with: 'new_branch_name', visible: true)
click_button('Commit changes')
@@ -110,8 +108,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
click_link_or_button('Edit')
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
click_link('Preview changes')
expect(page).to have_css('.line_holder.new')
@@ -156,10 +153,9 @@ RSpec.describe 'Projects > Files > User edits files', :js do
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
- expect(editor_value).to eq('*.rbca')
+ expect(find('.monaco-editor')).to have_content('*.rbca')
end
it 'opens the Web IDE in a forked project', :sidekiq_might_not_need_inline do
@@ -187,8 +183,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -216,8 +211,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
expect(page).not_to have_link('Fork')
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'Another commit', visible: true)
click_button('Commit changes')
diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb
index 12c5820a69d..ac83de3e765 100644
--- a/spec/features/projects/issuable_templates_spec.rb
+++ b/spec/features/projects/issuable_templates_spec.rb
@@ -90,6 +90,34 @@ RSpec.describe 'issuable templates', :js do
end
end
+ context 'user creates an issue with a default template from the repo' do
+ let(:template_content) { 'this is the default template' }
+
+ before do
+ project.repository.create_file(
+ user,
+ '.gitlab/issue_templates/default.md',
+ template_content,
+ message: 'added default issue template',
+ branch_name: 'master'
+ )
+ end
+
+ it 'does not overwrite autosaved description' do
+ visit new_project_issue_path project
+ wait_for_requests
+
+ assert_template # default template is loaded the first time
+
+ fill_in 'issue_description', with: 'my own description', fill_options: { clear: :backspace }
+
+ visit new_project_issue_path project
+ wait_for_requests
+
+ assert_template(expected_content: 'my own description')
+ end
+ end
+
context 'user creates a merge request using templates' do
let(:template_content) { 'this is a test "feature-proposal" template' }
let(:bug_template_content) { 'this is merge request bug template' }
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index bb44b70bb3a..289ab8cffa5 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -74,6 +74,7 @@ RSpec.describe 'User browses jobs' do
wait_for_requests
expect(page).to have_selector('.ci-canceled')
+ expect(page).not_to have_selector('[data-testid="jobs-table-error-alert"]')
end
end
diff --git a/spec/features/projects/members/manage_groups_spec.rb b/spec/features/projects/members/manage_groups_spec.rb
index 006fa3b6eff..e86affbbca1 100644
--- a/spec/features/projects/members/manage_groups_spec.rb
+++ b/spec/features/projects/members/manage_groups_spec.rb
@@ -162,7 +162,7 @@ RSpec.describe 'Project > Members > Manage groups', :js do
let_it_be(:user) { maintainer }
let_it_be(:group) { parent_group }
let_it_be(:group_within_hierarchy) { create(:group, parent: group) }
- let_it_be(:project_within_hierarchy) { create(:project, group: group_within_hierarchy)}
+ let_it_be(:project_within_hierarchy) { create(:project, group: group_within_hierarchy) }
let_it_be(:members_page_path) { project_project_members_path(project) }
let_it_be(:members_page_path_within_hierarchy) { project_project_members_path(project_within_hierarchy) }
end
diff --git a/spec/features/projects/members/manage_members_spec.rb b/spec/features/projects/members/manage_members_spec.rb
index 8d229530ef5..56eb02607a5 100644
--- a/spec/features/projects/members/manage_members_spec.rb
+++ b/spec/features/projects/members/manage_members_spec.rb
@@ -12,106 +12,188 @@ RSpec.describe 'Projects > Members > Manage members', :js do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :internal, namespace: group) }
+ let(:project_owner) { create(:user, name: "ProjectOwner", username: "project_owner") }
+ let(:project_maintainer) { create(:user, name: "ProjectMaintainer", username: "project_maintainer") }
+ let(:group_owner) { user1 }
+ let(:project_developer) { user2 }
+
before do
- sign_in(user1)
- group.add_owner(user1)
+ project.add_maintainer(project_maintainer)
+ project.add_owner(project_owner)
+ group.add_owner(group_owner)
+
+ sign_in(group_owner)
end
it 'show members from project and group', :aggregate_failures do
- project.add_developer(user2)
+ project.add_developer(project_developer)
visit_members_page
- expect(first_row).to have_content(user1.name)
- expect(second_row).to have_content(user2.name)
+ expect(first_row).to have_content(group_owner.name)
+ expect(second_row).to have_content(project_developer.name)
end
it 'show user once if member of both group and project', :aggregate_failures do
- project.add_developer(user1)
+ group.add_reporter(project_maintainer)
visit_members_page
- expect(first_row).to have_content(user1.name)
- expect(second_row).to be_blank
+ expect(first_row).to have_content(group_owner.name)
+ expect(second_row).to have_content(project_maintainer.name)
+ expect(third_row).to have_content(project_owner.name)
+ expect(all_rows[3]).to be_blank
end
- it 'update user access level' do
- project.add_developer(user2)
+ context 'update user access level' do
+ before do
+ sign_in(current_user)
+ end
+
+ context 'as maintainer' do
+ let(:current_user) { project_maintainer }
- visit_members_page
+ it 'can update a non-Owner member' do
+ project.add_developer(project_developer)
- page.within find_member_row(user2) do
- click_button('Developer')
- click_button('Reporter')
+ visit_members_page
+
+ page.within find_member_row(project_developer) do
+ click_button('Developer')
+
+ page.within '.dropdown-menu' do
+ expect(page).not_to have_button('Owner')
+ end
+
+ click_button('Reporter')
+
+ expect(page).to have_button('Reporter')
+ end
+ end
- expect(page).to have_button('Reporter')
+ it 'cannot update an Owner member' do
+ visit_members_page
+
+ page.within find_member_row(project_owner) do
+ expect(page).not_to have_button('Owner')
+ end
+ end
end
- end
- context 'when owner' do
- it 'uses ProjectMember access_level_roles for the invite members modal access option', :aggregate_failures do
- visit_members_page
+ context 'as owner' do
+ let(:current_user) { group_owner }
- click_on 'Invite members'
+ it 'can update a project Owner member' do
+ visit_members_page
- click_on 'Guest'
- wait_for_requests
+ page.within find_member_row(project_owner) do
+ click_button('Owner')
+ click_button('Reporter')
- page.within '.dropdown-menu' do
- expect(page).to have_button('Guest')
- expect(page).to have_button('Reporter')
- expect(page).to have_button('Developer')
- expect(page).to have_button('Maintainer')
- expect(page).to have_button('Owner')
+ expect(page).to have_button('Reporter')
+ end
end
end
end
- context 'when maintainer' do
- let(:maintainer) { create(:user) }
-
+ context 'uses ProjectMember valid_access_level_roles for the invite members modal options', :aggregate_failures do
before do
- project.add_maintainer(maintainer)
- sign_in(maintainer)
- end
+ sign_in(current_user)
- it 'uses ProjectMember access_level_roles for the invite members modal access option', :aggregate_failures do
visit_members_page
click_on 'Invite members'
click_on 'Guest'
wait_for_requests
+ end
- page.within '.dropdown-menu' do
- expect(page).to have_button('Guest')
- expect(page).to have_button('Reporter')
- expect(page).to have_button('Developer')
- expect(page).to have_button('Maintainer')
- expect(page).not_to have_button('Owner')
+ context 'when owner' do
+ let(:current_user) { project_owner }
+
+ it 'shows Owner in the dropdown' do
+ page.within '.dropdown-menu' do
+ expect(page).to have_button('Guest')
+ expect(page).to have_button('Reporter')
+ expect(page).to have_button('Developer')
+ expect(page).to have_button('Maintainer')
+ expect(page).to have_button('Owner')
+ end
+ end
+ end
+
+ context 'when maintainer' do
+ let(:current_user) { project_maintainer }
+
+ it 'does not show the Owner option' do
+ page.within '.dropdown-menu' do
+ expect(page).to have_button('Guest')
+ expect(page).to have_button('Reporter')
+ expect(page).to have_button('Developer')
+ expect(page).to have_button('Maintainer')
+ expect(page).not_to have_button('Owner')
+ end
end
end
end
- it 'remove user from project' do
- other_user = create(:user)
- project.add_developer(other_user)
+ describe 'remove user from project' do
+ before do
+ project.add_developer(project_developer)
- visit_members_page
+ sign_in(current_user)
- # Open modal
- page.within find_member_row(other_user) do
- click_button 'Remove member'
+ visit_members_page
end
- within_modal do
- expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
- click_button('Remove member')
+ context 'when maintainer' do
+ let(:current_user) { project_maintainer }
+
+ it 'can only remove non-Owner members' do
+ page.within find_member_row(project_owner) do
+ expect(page).not_to have_button('Remove member')
+ end
+
+ # Open modal
+ page.within find_member_row(project_developer) do
+ click_button 'Remove member'
+ end
+
+ within_modal do
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ click_button('Remove member')
+ end
+
+ wait_for_requests
+
+ expect(members_table).not_to have_content(project_developer.name)
+ expect(members_table).to have_content(project_owner.name)
+ end
end
- wait_for_requests
+ context 'when owner' do
+ let(:current_user) { group_owner }
+
+ it 'can remove any direct member' do
+ page.within find_member_row(project_owner) do
+ expect(page).to have_button('Remove member')
+ end
+
+ # Open modal
+ page.within find_member_row(project_owner) do
+ click_button 'Remove member'
+ end
- expect(members_table).not_to have_content(other_user.name)
+ within_modal do
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ click_button('Remove member')
+ end
+
+ wait_for_requests
+
+ expect(members_table).not_to have_content(project_owner.name)
+ end
+ end
end
it_behaves_like 'inviting members', 'project-members-page' do
@@ -130,7 +212,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
external_project_bot = create(:user, :project_bot, name: '_external_project_bot_')
external_project = create(:project, group: external_group)
external_project.add_maintainer(external_project_bot)
- external_project.add_maintainer(user1)
+ external_project.add_maintainer(group_owner)
visit_members_page
@@ -143,8 +225,8 @@ RSpec.describe 'Projects > Members > Manage members', :js do
wait_for_requests
- expect(page).to have_content(user1.name)
- expect(page).to have_content(user2.name)
+ expect(page).to have_content(group_owner.name)
+ expect(page).to have_content(project_developer.name)
expect(page).not_to have_content(internal_project_bot.name)
expect(page).not_to have_content(external_project_bot.name)
end
@@ -155,7 +237,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
let_it_be(:project) { create(:project, :public) }
before do
- sign_out(user1)
+ sign_out(group_owner)
end
it 'does not show the Invite members button when not signed in' do
@@ -192,7 +274,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
end
it 'shows 2FA badge to user with "Maintainer" access level' do
- project.add_maintainer(user1)
+ sign_in(project_maintainer)
visit_members_page
@@ -209,7 +291,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
end
it 'does not show 2FA badge to users with access level below "Maintainer"' do
- group.add_developer(user1)
+ group.add_developer(group_owner)
visit_members_page
diff --git a/spec/features/projects/merge_request_button_spec.rb b/spec/features/projects/merge_request_button_spec.rb
index 335ae6794b7..eb52a7821f9 100644
--- a/spec/features/projects/merge_request_button_spec.rb
+++ b/spec/features/projects/merge_request_button_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe 'Merge Request button' do
let(:forked_project) { fork_project(project, user, repository: true) }
shared_examples 'Merge request button only shown when allowed' do
+ let(:extra_mr_params) { {} }
+
context 'not logged in' do
it 'does not show Create merge request button' do
visit url
@@ -31,11 +33,8 @@ RSpec.describe 'Merge Request button' do
href = project_new_merge_request_path(
project,
merge_request: {
- source_project_id: project.id,
- source_branch: 'feature',
- target_project_id: project.id,
- target_branch: 'master'
- }
+ source_branch: 'feature'
+ }.merge(extra_mr_params)
)
visit url
@@ -90,11 +89,8 @@ RSpec.describe 'Merge Request button' do
href = project_new_merge_request_path(
forked_project,
merge_request: {
- source_project_id: forked_project.id,
- source_branch: 'feature',
- target_project_id: forked_project.id,
- target_branch: 'master'
- }
+ source_branch: 'feature'
+ }.merge(extra_mr_params)
)
visit fork_url
@@ -121,6 +117,7 @@ RSpec.describe 'Merge Request button' do
it_behaves_like 'Merge request button only shown when allowed' do
let(:url) { project_compare_path(project, from: 'master', to: 'feature') }
let(:fork_url) { project_compare_path(forked_project, from: 'master', to: 'feature') }
+ let(:extra_mr_params) { { target_project_id: project.id, target_branch: 'master' } }
end
it 'shows the correct merge request button when viewing across forks', :js do
@@ -128,9 +125,8 @@ RSpec.describe 'Merge Request button' do
project.add_developer(user)
href = project_new_merge_request_path(
- project,
+ forked_project,
merge_request: {
- source_project_id: forked_project.id,
source_branch: 'feature',
target_project_id: project.id,
target_branch: 'master'
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index 9d2d1454d77..f45025d079a 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -3,16 +3,44 @@
require 'spec_helper'
RSpec.describe 'New project', :js do
- include Select2Helper
include Spec::Support::Helpers::Features::TopNavSpecHelpers
context 'as a user' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
end
+ it 'shows the project description field when it should' do
+ description_label = 'Project description (optional)'
+
+ visit new_project_path
+ click_link 'Create blank project'
+
+ page.within('#blank-project-pane') do
+ expect(page).not_to have_content(description_label)
+ end
+
+ visit new_project_path
+ click_link 'Import project'
+
+ page.within('#import-project-pane') do
+ click_button 'Repository by URL'
+
+ expect(page).to have_content(description_label)
+ end
+
+ visit new_project_path
+ click_link 'Create from template'
+
+ page.within('#create-from-template-pane') do
+ find("[data-testid='use_template_#{Gitlab::ProjectTemplate.localized_templates_table.first.name}']").click
+
+ expect(page).to have_content(description_label)
+ end
+ end
+
it 'shows a message if multiple levels are restricted' do
Gitlab::CurrentSettings.update!(
restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL]
diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb
index afa3f29ce0d..5cb4fa163c8 100644
--- a/spec/features/projects/pages/user_adds_domain_spec.rb
+++ b/spec/features/projects/pages/user_adds_domain_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'User adds pages domain', :js do
include LetsEncryptHelpers
include Spec::Support::Helpers::ModalHelpers
- let_it_be(:project) { create(:project, pages_https_only: false) }
+ let_it_be(:project) { create(:project, :pages_published, pages_https_only: false) }
let(:user) { create(:user) }
@@ -18,8 +18,6 @@ RSpec.describe 'User adds pages domain', :js do
end
context 'when pages are exposed on external HTTP address', :http_pages_enabled do
- let(:project) { create(:project, pages_https_only: false) }
-
shared_examples 'adds new domain' do
it 'adds new domain' do
visit new_project_pages_domain_path(project)
@@ -42,7 +40,7 @@ RSpec.describe 'User adds pages domain', :js do
context 'when project in group namespace' do
it_behaves_like 'adds new domain' do
let(:group) { create :group }
- let(:project) { create(:project, namespace: group, pages_https_only: false) }
+ let(:project) { create(:project, :pages_published, namespace: group, pages_https_only: false) }
end
end
diff --git a/spec/features/projects/pages/user_configures_pages_pipeline_spec.rb b/spec/features/projects/pages/user_configures_pages_pipeline_spec.rb
new file mode 100644
index 00000000000..029479d6b95
--- /dev/null
+++ b/spec/features/projects/pages/user_configures_pages_pipeline_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'Pages edits pages settings', :js do
+ include Spec::Support::Helpers::ModalHelpers
+
+ let_it_be(:project) { create(:project, pages_https_only: false) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+
+ project.add_maintainer(user)
+
+ sign_in(user)
+ end
+
+ context 'when pipeline wizard feature is enabled' do
+ before do
+ Feature.enable(:use_pipeline_wizard_for_pages)
+ end
+
+ context 'when onboarding is not complete' do
+ it 'renders onboarding instructions' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Get started with Pages')
+ end
+ end
+
+ context 'when onboarding is complete' do
+ before do
+ project.mark_pages_onboarding_complete
+ end
+
+ it 'shows waiting screen' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Waiting for the Pages Pipeline to complete...')
+ end
+ end
+ end
+
+ context 'when pipeline wizard feature is disabled' do
+ before do
+ Feature.disable(:use_pipeline_wizard_for_pages)
+ end
+
+ it 'shows configure pages instructions' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Configure pages')
+ end
+
+ after do
+ Feature.enable(:use_pipeline_wizard_for_pages)
+ end
+ end
+end
diff --git a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
index 4c633bea64e..2e28fa20b90 100644
--- a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
@@ -5,7 +5,8 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
include LetsEncryptHelpers
include Spec::Support::Helpers::ModalHelpers
- let(:project) { create(:project, pages_https_only: false) }
+ let_it_be_with_reload(:project) { create(:project, :pages_published, pages_https_only: false) }
+
let(:user) { create(:user) }
let(:role) { :maintainer }
let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] }
diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb
index bd163f4a109..88c27a6adf2 100644
--- a/spec/features/projects/pages/user_edits_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_settings_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe 'Pages edits pages settings', :js do
include Spec::Support::Helpers::ModalHelpers
- let(:project) { create(:project, pages_https_only: false) }
- let(:user) { create(:user) }
+ let_it_be_with_reload(:project) { create(:project, :pages_published, pages_https_only: false) }
+ let_it_be(:user) { create(:user) }
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
@@ -80,13 +80,6 @@ RSpec.describe 'Pages edits pages settings', :js do
end
end
- it 'does not see anything to destroy' do
- visit project_pages_path(project)
-
- expect(page).to have_content('Configure pages')
- expect(page).not_to have_link('Remove pages')
- end
-
describe 'project settings page' do
it 'renders "Pages" tab' do
visit edit_project_path(project)
@@ -151,7 +144,7 @@ RSpec.describe 'Pages edits pages settings', :js do
end
context 'non-HTTPS domain exists' do
- let(:project) { create(:project, pages_https_only: false) }
+ let(:project) { create(:project, :pages_published, pages_https_only: false) }
before do
create(:pages_domain, :without_key, :without_certificate, project: project)
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 8cf6d5bd29b..0711a30e974 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -109,7 +109,12 @@ RSpec.describe 'Pipeline Schedules', :js do
end
it 'changes ownership of the pipeline' do
- click_link 'Take ownership'
+ click_button 'Take ownership'
+
+ page.within('#pipeline-take-ownership-modal') do
+ click_link 'Take ownership'
+ end
+
page.within('.pipeline-schedule-table-row') do
expect(page).not_to have_content('No owner')
expect(page).to have_link('Sidney Jones')
diff --git a/spec/features/projects/pipelines/legacy_pipeline_spec.rb b/spec/features/projects/pipelines/legacy_pipeline_spec.rb
index db6feecba03..14f60dfe061 100644
--- a/spec/features/projects/pipelines/legacy_pipeline_spec.rb
+++ b/spec/features/projects/pipelines/legacy_pipeline_spec.rb
@@ -385,6 +385,37 @@ RSpec.describe 'Pipeline', :js do
end
end
+ describe 'test tabs' do
+ let(:pipeline) { create(:ci_pipeline, :with_test_reports, :with_report_results, project: project) }
+
+ before do
+ stub_feature_flags(pipeline_tabs_vue: false)
+ visit_pipeline
+ wait_for_requests
+ end
+
+ context 'with test reports' do
+ it 'shows badge counter in Tests tab' do
+ expect(page.find('.js-test-report-badge-counter').text).to eq(pipeline.test_report_summary.total[:count].to_s)
+ end
+
+ it 'calls summary.json endpoint', :js do
+ find('.js-tests-tab-link').click
+
+ expect(page).to have_content('Jobs')
+ expect(page).to have_selector('[data-testid="tests-detail"]', visible: :all)
+ end
+ end
+
+ context 'without test reports' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ it 'shows zero' do
+ expect(page.find('.js-test-report-badge-counter', visible: :all).text).to eq("0")
+ end
+ end
+ end
+
context 'retrying jobs' do
before do
visit_pipeline
diff --git a/spec/features/projects/pipelines/legacy_pipelines_spec.rb b/spec/features/projects/pipelines/legacy_pipelines_spec.rb
index 15d889933bf..eb8f2de3aba 100644
--- a/spec/features/projects/pipelines/legacy_pipelines_spec.rb
+++ b/spec/features/projects/pipelines/legacy_pipelines_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Pipelines', :js do
include Spec::Support::Helpers::ModalHelpers
let(:project) { create(:project) }
- let(:expected_detached_mr_tag) {'merge request'}
+ let(:expected_detached_mr_tag) { 'merge request' }
context 'when user is logged in' do
let(:user) { create(:user) }
@@ -727,6 +727,7 @@ RSpec.describe 'Pipelines', :js do
end
it { expect(page).to have_content('Missing CI config file') }
+
it 'creates a pipeline after first request failed and a valid gitlab-ci.yml file' \
'is available when trying again' do
stub_ci_pipeline_to_return_yaml_file
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index a83d4191f38..cfdd851cb80 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -394,7 +394,7 @@ RSpec.describe 'Pipeline', :js do
expect(page).to have_selector('button[aria-label="Cancel downstream pipeline"]')
end
- context 'when canceling' do
+ context 'when canceling', :sidekiq_inline do
before do
find('button[aria-label="Cancel downstream pipeline"]').click
wait_for_requests
@@ -515,18 +515,17 @@ RSpec.describe 'Pipeline', :js do
let(:pipeline) { create(:ci_pipeline, :with_test_reports, :with_report_results, project: project) }
before do
- stub_feature_flags(pipeline_tabs_vue: false)
visit_pipeline
wait_for_requests
end
context 'with test reports' do
it 'shows badge counter in Tests tab' do
- expect(page.find('.js-test-report-badge-counter').text).to eq(pipeline.test_report_summary.total[:count].to_s)
+ expect(page.find('[data-testid="tests-counter"]').text).to eq(pipeline.test_report_summary.total[:count].to_s)
end
it 'calls summary.json endpoint', :js do
- find('.js-tests-tab-link').click
+ find('.gl-tab-nav-item', text: 'Tests').click
expect(page).to have_content('Jobs')
expect(page).to have_selector('[data-testid="tests-detail"]', visible: :all)
@@ -537,7 +536,7 @@ RSpec.describe 'Pipeline', :js do
let(:pipeline) { create(:ci_pipeline, project: project) }
it 'shows zero' do
- expect(page.find('.js-test-report-badge-counter', visible: :all).text).to eq("0")
+ expect(page.find('[data-testid="tests-counter"]', visible: :all).text).to eq("0")
end
end
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 785edc69623..bf521971ae0 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Pipelines', :js do
include Spec::Support::Helpers::ModalHelpers
let(:project) { create(:project) }
- let(:expected_detached_mr_tag) {'merge request'}
+ let(:expected_detached_mr_tag) { 'merge request' }
context 'when user is logged in' do
let(:user) { create(:user) }
@@ -710,6 +710,7 @@ RSpec.describe 'Pipelines', :js do
end
it { expect(page).to have_content('Missing CI config file') }
+
it 'creates a pipeline after first request failed and a valid gitlab-ci.yml file is available when trying again' do
stub_ci_pipeline_to_return_yaml_file
diff --git a/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb b/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb
new file mode 100644
index 00000000000..5a50b3de772
--- /dev/null
+++ b/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project > Settings > Packages & Registries > Container registry tag expiration policy' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, namespace: user.namespace) }
+
+ let(:container_registry_enabled) { true }
+ let(:container_registry_enabled_on_project) { ProjectFeature::ENABLED }
+
+ subject { visit cleanup_image_tags_project_settings_packages_and_registries_path(project) }
+
+ before do
+ project.project_feature.update!(container_registry_access_level: container_registry_enabled_on_project)
+ project.container_expiration_policy.update!(enabled: true)
+
+ sign_in(user)
+ stub_container_registry_config(enabled: container_registry_enabled)
+ end
+
+ context 'as owner', :js do
+ it 'shows available section' do
+ subject
+
+ expect(find('.breadcrumbs')).to have_content('Clean up image tags')
+ end
+ end
+
+ context 'when registry is disabled' do
+ let(:container_registry_enabled) { false }
+
+ it 'does not exists' do
+ subject
+
+ expect(page).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when container registry is disabled on project' do
+ let(:container_registry_enabled_on_project) { ProjectFeature::DISABLED }
+
+ it 'does not exists' do
+ subject
+
+ expect(page).to have_gitlab_http_status(:not_found)
+ end
+ end
+end
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 9468540736f..1fb46c669e7 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -31,7 +31,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
select('Every day', from: 'Run cleanup')
select('50 tags per image name', from: 'Keep the most recent:')
fill_in('Keep tags matching:', with: 'stable')
@@ -50,7 +49,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
fill_in('Remove tags matching:', with: '*-production')
submit_button = find('[data-testid="save-button"')
@@ -76,7 +74,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
expect(find('[data-testid="enable-toggle"]')).to have_content('Disabled - Tags will not be automatically deleted.')
end
end
@@ -91,7 +88,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
expect(find('.gl-alert-title')).to have_content('Cleanup policy for tags is disabled')
end
end
diff --git a/spec/features/projects/settings/service_desk_setting_spec.rb b/spec/features/projects/settings/service_desk_setting_spec.rb
index 0df4bd3f0d9..86c5c3d2d8c 100644
--- a/spec/features/projects/settings/service_desk_setting_spec.rb
+++ b/spec/features/projects/settings/service_desk_setting_spec.rb
@@ -81,7 +81,7 @@ RSpec.describe 'Service Desk Setting', :js, :clean_gitlab_redis_cache do
}
end
- let_it_be_with_reload(:group) { create(:group)}
+ let_it_be_with_reload(:group) { create(:group) }
let_it_be_with_reload(:project) { create(:project, :custom_repo, group: group, files: issuable_project_template_files) }
let_it_be(:group_template_repo) { create(:project, :custom_repo, group: group, files: issuable_group_template_files) }
diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb
index c8438b73dc3..857d0696659 100644
--- a/spec/features/projects/tags/user_edits_tags_spec.rb
+++ b/spec/features/projects/tags/user_edits_tags_spec.rb
@@ -15,6 +15,13 @@ RSpec.describe 'Project > Tags', :js do
end
shared_examples "can create and update release" do
+ it 'shows tag information' do
+ visit page_url
+
+ expect(page).to have_content 'v1.1.0'
+ expect(page).to have_content 'Version 1.1.0'
+ end
+
it 'can create new release' do
visit page_url
page.find("a[href=\"#{new_project_release_path(project, tag_name: 'v1.1.0')}\"]").click
@@ -52,71 +59,4 @@ RSpec.describe 'Project > Tags', :js do
include_examples "can create and update release"
end
-
- # TODO: remove most of these together with FF https://gitlab.com/gitlab-org/gitlab/-/issues/366244
- describe 'when opening project tags' do
- before do
- stub_feature_flags(edit_tag_release_notes_via_release_page: false)
- visit project_tags_path(project)
- end
-
- context 'page with tags list' do
- it 'shows tag name' do
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Version 1.1.0'
- end
-
- it 'shows tag edit button' do
- page.within '.tags > .content-list' do
- edit_btn = page.find("li > .row-fixed-content.controls a.btn-edit[href='/#{project.full_path}/-/tags/v1.1.0/release/edit']")
-
- expect(edit_btn['href']).to end_with("/#{project.full_path}/-/tags/v1.1.0/release/edit")
- end
- end
- end
-
- context 'edit tag release notes' do
- before do
- page.find("li > .row-fixed-content.controls a.btn-edit[href='/#{project.full_path}/-/tags/v1.1.0/release/edit']").click
- end
-
- it 'shows tag name header' do
- page.within('.content') do
- expect(page.find('.sub-header-block')).to have_content 'Release notes for tag v1.1.0'
- end
- end
-
- it 'shows release notes form' do
- page.within('.content') do
- expect(page).to have_selector('form.release-form')
- end
- end
-
- it 'toolbar buttons on release notes form are functional' do
- page.within('.content form.release-form') do
- note_textarea = page.find('.js-gfm-input')
-
- # Click on Bold button
- page.find('.md-header-toolbar button:first-child').click
-
- expect(note_textarea.value).to eq('****')
- end
- end
-
- it 'release notes form shows "Attach a file" button', :js do
- page.within('.content form.release-form') do
- expect(page).to have_button('Attach a file')
- expect(page).not_to have_selector('.uploading-progress-container', visible: true)
- end
- end
-
- it 'shows "Attaching a file" message on uploading 1 file', :js, :capybara_ignore_server_errors do
- slow_requests do
- dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
-
- expect(page).to have_selector('.attaching-file-message', visible: true, text: 'Attaching a file -')
- end
- end
- end
- end
end
diff --git a/spec/features/projects/tags/user_views_tag_spec.rb b/spec/features/projects/tags/user_views_tag_spec.rb
new file mode 100644
index 00000000000..3978c5b7b78
--- /dev/null
+++ b/spec/features/projects/tags/user_views_tag_spec.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'User views tag', :feature do
+ include_examples 'user views tag' do
+ let(:tag_page) { project_tag_path(project, id: tag_name) }
+ end
+end
diff --git a/spec/features/projects/tags/user_views_tags_spec.rb b/spec/features/projects/tags/user_views_tags_spec.rb
index dfb5d5d9221..d3849df023e 100644
--- a/spec/features/projects/tags/user_views_tags_spec.rb
+++ b/spec/features/projects/tags/user_views_tags_spec.rb
@@ -2,34 +2,8 @@
require 'spec_helper'
RSpec.describe 'User views tags', :feature do
- context 'with html' do
- let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
- let(:user) { create(:user) }
- let(:tag_name) { "stable" }
- let!(:release) { create(:release, project: project, tag: tag_name) }
-
- before do
- project.add_developer(user)
- project.repository.add_tag(user, tag_name, project.default_branch_or_main)
-
- sign_in(user)
- end
-
- shared_examples 'renders the tag index page' do
- it do
- visit project_tags_path(project)
-
- expect(page).to have_content tag_name
- end
- end
-
- it_behaves_like 'renders the tag index page'
-
- context 'when tag name contains a slash' do
- let(:tag_name) { "stable/v0.1" }
-
- it_behaves_like 'renders the tag index page'
- end
+ include_examples 'user views tag' do
+ let(:tag_page) { project_tags_path(project) }
end
context 'rss' do
diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb
index f6127b38bd6..074469a9b55 100644
--- a/spec/features/projects/tree/create_directory_spec.rb
+++ b/spec/features/projects/tree/create_directory_spec.rb
@@ -49,8 +49,8 @@ RSpec.describe 'Multi-file editor new directory', :js do
# Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
# (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
# taller (as it is by default with chrome headless) then the button will not exist.
- if page.has_css?('.qa-begin-commit-button') # rubocop:disable QA/SelectorUsage
- find('.qa-begin-commit-button').click # rubocop:disable QA/SelectorUsage
+ if page.has_css?('[data-testid="begin-commit-button"]')
+ find('[data-testid="begin-commit-button"]').click
end
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb
index 33be02a9121..85c644fa528 100644
--- a/spec/features/projects/tree/create_file_spec.rb
+++ b/spec/features/projects/tree/create_file_spec.rb
@@ -39,8 +39,8 @@ RSpec.describe 'Multi-file editor new file', :js do
# Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
# (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
# taller (as it is by default with chrome headless) then the button will not exist.
- if page.has_css?('.qa-begin-commit-button') # rubocop:disable QA/SelectorUsage
- find('.qa-begin-commit-button').click # rubocop:disable QA/SelectorUsage
+ if page.has_css?('[data-testid="begin-commit-button"]')
+ find('[data-testid="begin-commit-button"]').click
end
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb
index 53e89cd2959..163e347d03d 100644
--- a/spec/features/projects/tree/tree_show_spec.rb
+++ b/spec/features/projects/tree/tree_show_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe 'Projects tree', :js do
let(:filename) { File.join(path, 'test.txt') }
let(:newrev) { project.repository.commit('master').sha }
let(:short_newrev) { project.repository.commit('master').short_id }
- let(:message) { 'Glob characters'}
+ let(:message) { 'Glob characters' }
before do
create_file_in_repo(project, 'master', 'master', filename, 'Test file', commit_message: message)
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index f6f9c7f0d3c..d228fb084c3 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -329,7 +329,7 @@ RSpec.describe 'Project' do
it 'has working links to submodules' do
click_link('645f6c4c')
- expect(page).to have_selector('.qa-branches-select', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="branches-select"]', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6')
end
context 'for signed commit on default branch', :js do
@@ -454,8 +454,8 @@ RSpec.describe 'Project' do
let_it_be(:storage_enforcement_date) { Date.today + 30 }
before do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -478,8 +478,8 @@ RSpec.describe 'Project' do
let_it_be(:project) { create(:project, namespace: user.namespace) }
before do
- allow_next_found_instance_of(Namespaces::UserNamespace) do |namspace|
- allow(namspace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -490,8 +490,8 @@ RSpec.describe 'Project' do
end
it 'does not display the banner in a paid group project page' do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:paid?).and_return(true)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:paid?).and_return(true)
end
visit project_path(project)
expect_page_not_to_have_storage_enforcement_banner
@@ -506,8 +506,8 @@ RSpec.describe 'Project' do
expect_page_not_to_have_storage_enforcement_banner
storage_enforcement_date = Date.today + 13
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
page.refresh
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
@@ -515,8 +515,12 @@ RSpec.describe 'Project' do
end
context 'with storage_enforcement_date not set' do
- # This test should break and be rewritten after the implementation of the storage_enforcement_date
- # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ before do
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(nil)
+ end
+ end
+
it 'does not display the banner in the group page' do
stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
visit project_path(project)
@@ -526,11 +530,11 @@ RSpec.describe 'Project' do
end
def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
- expect(page).to have_text "From #{storage_enforcement_date} storage limits will apply to this namespace"
+ expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply"
end
def expect_page_not_to_have_storage_enforcement_banner
- expect(page).not_to have_text "storage limits will apply to this namespace"
+ expect(page).not_to have_text "namespace storage limits will apply"
end
def remove_with_confirm(button_text, confirm_with, confirm_button_text = 'Confirm')
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index 534da71e39a..2600c00346e 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -268,7 +268,7 @@ RSpec.describe 'Runners' do
it 'group runners are not available' do
visit project_runners_path(project)
- expect(page).not_to have_content 'Group owners can register group runners in the group\'s CI/CD settings.'
+ expect(page).not_to have_content 'To register them, go to the group\'s Runners page.'
expect(page).to have_content 'Ask your group owner to set up a group runner'
end
end
@@ -287,7 +287,7 @@ RSpec.describe 'Runners' do
expect(page).to have_content 'This group does not have any group runners yet.'
- expect(page).to have_content 'Group owners can register group runners in the group\'s CI/CD settings.'
+ expect(page).to have_content 'To register them, go to the group\'s Runners page.'
expect(page).not_to have_content 'Ask your group owner to set up a group runner'
end
end
@@ -313,7 +313,7 @@ RSpec.describe 'Runners' do
expect(page).to have_content 'This group does not have any group runners yet.'
- expect(page).not_to have_content 'Group owners can register group runners in the group\'s CI/CD settings.'
+ expect(page).not_to have_content 'To register them, go to the group\'s Runners page.'
expect(page).to have_content 'Ask your group owner to set up a group runner.'
end
end
diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb
index 279db686aa9..2dceda09d7c 100644
--- a/spec/features/search/user_searches_for_commits_spec.rb
+++ b/spec/features/search/user_searches_for_commits_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'User searches for commits', :js do
+ include CycleAnalyticsHelpers
+
let(:project) { create(:project, :repository) }
let(:sha) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
let(:user) { create(:user) }
diff --git a/spec/features/signed_commits_spec.rb b/spec/features/signed_commits_spec.rb
index dbf35567803..8725dbcafe8 100644
--- a/spec/features/signed_commits_spec.rb
+++ b/spec/features/signed_commits_spec.rb
@@ -93,7 +93,7 @@ RSpec.describe 'GPG signed commits' do
page.find('.gpg-status-box', text: 'Unverified').click
within '.popover' do
- expect(page).to have_content 'This commit was signed with a verified signature, but the committer email is not verified to belong to the same user.'
+ expect(page).to have_content 'This commit was signed with a verified signature, but the committer email is not associated with the GPG Key.'
expect(page).to have_content 'Bette Cartwright'
expect(page).to have_content '@bette.cartwright'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User2.primary_keyid}"
diff --git a/spec/features/tags/developer_updates_tag_spec.rb b/spec/features/tags/developer_updates_tag_spec.rb
deleted file mode 100644
index 531ed91c057..00000000000
--- a/spec/features/tags/developer_updates_tag_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# TODO: remove this file together with FF https://gitlab.com/gitlab-org/gitlab/-/issues/366244
-RSpec.describe 'Developer updates tag' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project) { create(:project, :repository, namespace: group) }
-
- before do
- project.add_developer(user)
- sign_in(user)
- stub_feature_flags(edit_tag_release_notes_via_release_page: false)
- visit project_tags_path(project)
- end
-
- context 'from the tags list page' do
- it 'updates the release notes' do
- find("li > .row-fixed-content.controls a.btn-edit[href='/#{project.full_path}/-/tags/v1.1.0/release/edit']").click
-
- fill_in 'release_description', with: 'Awesome release notes'
- click_button 'Save changes'
-
- expect(page).to have_current_path(
- project_tag_path(project, 'v1.1.0'), ignore_query: true)
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Awesome release notes'
- end
-
- it 'description has emoji autocomplete', :js do
- page.within(first('.content-list .controls')) do
- click_link 'Edit release notes'
- end
-
- find('#release_description').native.send_keys('')
- fill_in 'release_description', with: ':'
-
- expect(page).to have_selector('.atwho-view')
- end
- end
-
- context 'from a specific tag page' do
- it 'updates the release notes' do
- click_on 'v1.1.0'
- click_link 'Edit release notes'
- fill_in 'release_description', with: 'Awesome release notes'
- click_button 'Save changes'
-
- expect(page).to have_current_path(
- project_tag_path(project, 'v1.1.0'), ignore_query: true)
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Awesome release notes'
- end
- end
-end
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index 6907701de9c..07de3789c08 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on Issues#index' do
visit project_issues_path(project)
- expect(page).to have_content("2 of 6 tasks completed")
+ expect(page).to have_content("2 of 6 checklist items completed")
end
end
@@ -108,7 +108,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on Issues#index' do
visit project_issues_path(project)
- expect(page).to have_content("0 of 1 task completed")
+ expect(page).to have_content("0 of 1 checklist item completed")
end
end
@@ -127,7 +127,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on Issues#index' do
visit project_issues_path(project)
- expect(page).to have_content("1 of 1 task completed")
+ expect(page).to have_content("1 of 1 checklist item completed")
end
end
end
@@ -253,7 +253,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on MergeRequests#index' do
visit project_merge_requests_path(project)
- expect(page).to have_content("2 of 6 tasks completed")
+ expect(page).to have_content("2 of 6 checklist items completed")
end
end
@@ -278,7 +278,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on MergeRequests#index' do
visit project_merge_requests_path(project)
- expect(page).to have_content("0 of 1 task completed")
+ expect(page).to have_content("0 of 1 checklist item completed")
end
end
@@ -297,7 +297,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on MergeRequests#index' do
visit project_merge_requests_path(project)
- expect(page).to have_content("1 of 1 task completed")
+ expect(page).to have_content("1 of 1 checklist item completed")
end
end
end
diff --git a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
index 900cd72c17f..cbd2d30d726 100644
--- a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
+++ b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'User uploads avatar to profile' do
visit user_path(user)
- expect(page).to have_selector(%Q(img[data-src$="/uploads/-/system/user/avatar/#{user.id}/dk.png?width=90"]))
+ expect(page).to have_selector(%Q(img[src$="/uploads/-/system/user/avatar/#{user.id}/dk.png?width=96"]))
# Cheating here to verify something that isn't user-facing, but is important
expect(user.reload.avatar.file).to exist
diff --git a/spec/features/uploads/user_uploads_file_to_note_spec.rb b/spec/features/uploads/user_uploads_file_to_note_spec.rb
index 589cc9f9b02..2547e2d274c 100644
--- a/spec/features/uploads/user_uploads_file_to_note_spec.rb
+++ b/spec/features/uploads/user_uploads_file_to_note_spec.rb
@@ -16,8 +16,8 @@ RSpec.describe 'User uploads file to note' do
end
context 'before uploading' do
- it 'shows "Attach a file" button', :js do
- expect(page).to have_button('Attach a file')
+ it 'shows "Attach a file or image" button', :js do
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
end
@@ -30,7 +30,7 @@ RSpec.describe 'User uploads file to note' do
click_button 'Cancel'
end
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_button('Cancel')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
@@ -60,16 +60,15 @@ RSpec.describe 'User uploads file to note' do
expect(page).to have_selector('.uploading-error-message', visible: true, text: error_text)
expect(page).to have_button('Try again', visible: true)
expect(page).to have_button('attach a new file', visible: true)
- expect(page).not_to have_button('Attach a file')
end
end
context 'uploading is complete' do
- it 'shows "Attach a file" button on uploading complete', :js do
+ it 'shows "Attach a file or image" button on uploading complete', :js do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')])
wait_for_requests
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
diff --git a/spec/features/users/email_verification_on_login_spec.rb b/spec/features/users/email_verification_on_login_spec.rb
index 0833f7f6f8e..c8301c2fc91 100644
--- a/spec/features/users/email_verification_on_login_spec.rb
+++ b/spec/features/users/email_verification_on_login_spec.rb
@@ -335,7 +335,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting
mail = find_email_for(user)
expect(mail.to).to match_array([user.email])
expect(mail.subject).to eq('Verify your identity')
- code = mail.body.parts.first.to_s[/\d{#{VerifiesWithEmail::TOKEN_LENGTH}}/]
+ code = mail.body.parts.first.to_s[/\d{#{VerifiesWithEmail::TOKEN_LENGTH}}/o]
reset_delivered_emails!
code
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 3ba3650b608..b875dbe1340 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -49,15 +49,15 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
expect(page).to have_current_path edit_user_password_path, ignore_query: true
expect(page).to have_content('Please create a password for your new account.')
- fill_in 'user_password', with: 'password'
- fill_in 'user_password_confirmation', with: 'password'
+ fill_in 'user_password', with: user.password
+ fill_in 'user_password_confirmation', with: user.password
click_button 'Change your password'
expect(page).to have_current_path new_user_session_path, ignore_query: true
expect(page).to have_content(I18n.t('devise.passwords.updated_not_active'))
fill_in 'user_login', with: user.username
- fill_in 'user_password', with: 'password'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
expect_single_session_with_authenticated_ttl
@@ -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
@@ -231,7 +231,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
end
it 'does not allow sign-in if the user password is updated before entering a one-time code' do
- user.update!(password: 'new_password')
+ user.update!(password: User.random_password)
enter_code(user.current_otp)
@@ -365,7 +365,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
end
context 'when logging in via OAuth' do
- let(:user) { create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml')}
+ let(:user) { create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml') }
let(:mock_saml_response) do
File.read('spec/fixtures/authentication/saml_response.xml')
end
@@ -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)
@@ -468,7 +468,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
expect(page).to have_current_path(new_profile_password_path, ignore_query: true)
@@ -477,14 +477,14 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
end
context 'with invalid username and password' do
- let(:user) { create(:user, password: 'not-the-default') }
+ let(:user) { create(:user) }
it 'blocks invalid login' do
expect(authentication_metrics)
.to increment(:user_unauthenticated_counter)
.and increment(:user_password_invalid_counter)
- gitlab_sign_in(user)
+ gitlab_sign_in(user, password: 'incorrect-password')
expect_single_session_with_short_ttl
expect(page).to have_content('Invalid login or password.')
@@ -788,7 +788,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
@@ -809,7 +809,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
@@ -830,7 +830,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
@@ -873,7 +873,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
fill_in 'user_otp_attempt', with: user.reload.current_otp
@@ -899,7 +899,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
expect_to_be_on_terms_page
@@ -907,9 +907,11 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
expect(page).to have_current_path(new_profile_password_path, ignore_query: true)
- fill_in 'user_password', with: '12345678'
- fill_in 'user_new_password', with: 'new password'
- fill_in 'user_password_confirmation', with: 'new password'
+ new_password = User.random_password
+
+ fill_in 'user_password', with: user.password
+ fill_in 'user_new_password', with: new_password
+ fill_in 'user_password_confirmation', with: new_password
click_button 'Set new password'
expect(page).to have_content('Password successfully changed')
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index 2a444dad486..068e1fd4243 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -132,10 +132,10 @@ RSpec.describe 'User page' do
let_it_be(:followee) { create(:user) }
let_it_be(:follower) { create(:user) }
- it 'does not show link to follow' do
+ it 'does not show button to follow' do
subject
- expect(page).not_to have_link(text: 'Follow', class: 'gl-button')
+ expect(page).not_to have_button(text: 'Follow', class: 'gl-button')
end
it 'shows 0 followers and 0 following' do
@@ -155,11 +155,11 @@ RSpec.describe 'User page' do
expect(page).to have_content('1 following')
end
- it 'does show link to follow' do
+ it 'does show button to follow' do
sign_in(user)
visit user_path(followee)
- expect(page).to have_link(text: 'Follow', class: 'gl-button')
+ expect(page).to have_button(text: 'Follow', class: 'gl-button')
end
it 'does show link to unfollow' do
@@ -168,7 +168,7 @@ RSpec.describe 'User page' do
visit user_path(followee)
- expect(page).to have_link(text: 'Unfollow', class: 'gl-button')
+ expect(page).to have_button(text: 'Unfollow', class: 'gl-button')
end
end
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 30441dac7b6..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😀')
- it 'shows an error message if the username contains emojis' do
- simulate_input('#new_user_username', 'ehsan😀')
+ expect(find('.username')).to have_css '.gl-field-error-outline'
+ end
- expect(page).to have_content("Invalid input, please avoid emojis")
- end
+ it 'shows an error message if the username contains emojis' do
+ simulate_input('#new_user_username', 'ehsan😀')
- 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(page).to have_content("Invalid input, please avoid emojis")
+ end
- expect(find('.username > .validation-pending')).not_to have_css '.hide'
- 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 success message if the username is available' do
- fill_in 'new_user_username', with: 'new-user'
- wait_for_requests
+ expect(find('.username > .validation-pending')).not_to have_css '.hide'
+ end
- expect(find('.username > .validation-success')).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 an error message if the username is unavailable' do
- existing_user = create(:user)
+ expect(find('.username > .validation-success')).not_to have_css '.hide'
+ end
- fill_in 'new_user_username', with: existing_user.username
- wait_for_requests
+ it 'shows an error message if the username is unavailable' do
+ existing_user = create(:user)
- expect(find('.username > .validation-error')).not_to have_css '.hide'
- end
+ fill_in 'new_user_username', with: existing_user.username
+ 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(find('.username > .validation-error')).not_to have_css '.hide'
+ end
- expect(page).to have_content("Username is available.")
+ 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.")
+ 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
@@ -283,6 +378,12 @@ RSpec.describe 'Signup' do
expect(page).to have_current_path user_registration_path, ignore_query: true
expect(page.body).not_to match(/#{new_user.password}/)
end
+
+ context 'with invalid email', :saas, :js do
+ it_behaves_like 'user email validation' do
+ let(:path) { new_user_registration_path }
+ end
+ end
end
context 'when terms are enforced' do
@@ -298,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
-
- 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
+ visit new_project_path
- fill_in_signup_form
+ expect(page).to have_current_path(users_sign_up_welcome_path)
- 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
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
- fill_in_signup_form
+ created_user = User.find_by_username(new_user.username)
- expect { click_button 'Register' }.not_to change { User.count }
- expect(page).to have_content('That was a bit too quick! Please resubmit.')
- 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
- 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)
+ 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_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