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:
Diffstat (limited to 'spec/features')
-rw-r--r--spec/features/abuse_report_spec.rb121
-rw-r--r--spec/features/admin/admin_abuse_reports_spec.rb214
-rw-r--r--spec/features/admin/admin_labels_spec.rb6
-rw-r--r--spec/features/admin/admin_runners_spec.rb16
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb1
-rw-r--r--spec/features/admin/broadcast_messages_spec.rb14
-rw-r--r--spec/features/admin_variables_spec.rb11
-rw-r--r--spec/features/broadcast_messages_spec.rb4
-rw-r--r--spec/features/dashboard/projects_spec.rb4
-rw-r--r--spec/features/dashboard/todos/todos_filtering_spec.rb2
-rw-r--r--spec/features/group_variables_spec.rb12
-rw-r--r--spec/features/groups/container_registry_spec.rb1
-rw-r--r--spec/features/groups/labels/edit_spec.rb2
-rw-r--r--spec/features/groups/settings/group_badges_spec.rb41
-rw-r--r--spec/features/incidents/incident_details_spec.rb2
-rw-r--r--spec/features/incidents/user_views_incident_spec.rb31
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb34
-rw-r--r--spec/features/issues/incident_issue_spec.rb4
-rw-r--r--spec/features/issues/note_polling_spec.rb20
-rw-r--r--spec/features/issues/service_desk_spec.rb38
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb19
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb6
-rw-r--r--spec/features/issues/user_toggles_subscription_spec.rb6
-rw-r--r--spec/features/issues/user_views_issue_spec.rb38
-rw-r--r--spec/features/markdown/gitlab_flavored_markdown_spec.rb35
-rw-r--r--spec/features/merge_request/creating_mr_for_projects_with_different_visibility_spec.rb100
-rw-r--r--spec/features/merge_request/user_edits_mr_spec.rb5
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb24
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb9
-rw-r--r--spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb4
-rw-r--r--spec/features/merge_requests/user_sees_note_updates_in_real_time_spec.rb45
-rw-r--r--spec/features/nav/top_nav_tooltip_spec.rb2
-rw-r--r--spec/features/oauth_provider_authorize_spec.rb12
-rw-r--r--spec/features/participants_autocomplete_spec.rb3
-rw-r--r--spec/features/profile_spec.rb11
-rw-r--r--spec/features/profiles/active_sessions_spec.rb4
-rw-r--r--spec/features/profiles/gpg_keys_spec.rb12
-rw-r--r--spec/features/profiles/keys_spec.rb25
-rw-r--r--spec/features/profiles/list_users_comment_template_spec.rb2
-rw-r--r--spec/features/profiles/oauth_applications_spec.rb28
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb5
-rw-r--r--spec/features/profiles/user_changes_notified_of_own_activity_spec.rb2
-rw-r--r--spec/features/profiles/user_creates_comment_template_spec.rb3
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb2
-rw-r--r--spec/features/profiles/user_manages_emails_spec.rb6
-rw-r--r--spec/features/profiles/user_visits_notifications_tab_spec.rb2
-rw-r--r--spec/features/project_variables_spec.rb12
-rw-r--r--spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb2
-rw-r--r--spec/features/projects/ci/editor_spec.rb68
-rw-r--r--spec/features/projects/commit/mini_pipeline_graph_spec.rb29
-rw-r--r--spec/features/projects/container_registry_spec.rb4
-rw-r--r--spec/features/projects/files/dockerfile_dropdown_spec.rb14
-rw-r--r--spec/features/projects/files/gitignore_dropdown_spec.rb14
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb18
-rw-r--r--spec/features/projects/files/project_owner_creates_license_file_spec.rb7
-rw-r--r--spec/features/projects/files/template_selector_menu_spec.rb2
-rw-r--r--spec/features/projects/files/undo_template_spec.rb8
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb2
-rw-r--r--spec/features/projects/fork_spec.rb113
-rw-r--r--spec/features/projects/labels/user_edits_labels_spec.rb2
-rw-r--r--spec/features/projects/labels/user_removes_labels_spec.rb2
-rw-r--r--spec/features/projects/members/import_project_members_spec.rb79
-rw-r--r--spec/features/projects/members/user_manages_project_members_spec.rb (renamed from spec/features/projects/settings/user_manages_project_members_spec.rb)23
-rw-r--r--spec/features/projects/new_project_spec.rb23
-rw-r--r--spec/features/projects/pages/user_adds_domain_spec.rb7
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb4
-rw-r--r--spec/features/projects/settings/access_tokens_spec.rb3
-rw-r--r--spec/features/projects/settings/packages_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb40
-rw-r--r--spec/features/projects/settings/project_badges_spec.rb41
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb1
-rw-r--r--spec/features/projects/settings/secure_files_spec.rb2
-rw-r--r--spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb11
-rw-r--r--spec/features/projects/settings/user_renames_a_project_spec.rb2
-rw-r--r--spec/features/projects/settings/user_searches_in_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/visibility_settings_spec.rb6
-rw-r--r--spec/features/projects/show/user_manages_notifications_spec.rb2
-rw-r--r--spec/features/projects/user_changes_project_visibility_spec.rb4
-rw-r--r--spec/features/projects/work_items/work_item_spec.rb2
-rw-r--r--spec/features/protected_branches_spec.rb16
-rw-r--r--spec/features/protected_tags_spec.rb13
-rw-r--r--spec/features/triggers_spec.rb7
-rw-r--r--spec/features/uploads/user_uploads_avatar_to_profile_spec.rb69
-rw-r--r--spec/features/users/email_verification_on_login_spec.rb113
-rw-r--r--spec/features/users/google_syndication_csp_spec.rb54
-rw-r--r--spec/features/users/rss_spec.rb57
-rw-r--r--spec/features/users/signup_spec.rb4
87 files changed, 1353 insertions, 519 deletions
diff --git a/spec/features/abuse_report_spec.rb b/spec/features/abuse_report_spec.rb
index ae3859280b1..f934736ced9 100644
--- a/spec/features/abuse_report_spec.rb
+++ b/spec/features/abuse_report_spec.rb
@@ -13,10 +13,19 @@ RSpec.describe 'Abuse reports', :js, feature_category: :insider_threat do
before do
sign_in(reporter1)
stub_feature_flags(moved_mr_sidebar: false)
- stub_feature_flags(user_profile_overflow_menu_vue: false)
end
describe 'report abuse to administrator' do
+ shared_examples 'cancel report' do
+ it 'redirects backs to user profile when cancel button is clicked' do
+ fill_and_submit_abuse_category_form
+
+ click_link 'Cancel'
+
+ expect(page).to have_current_path(user_path(abusive_user))
+ end
+ end
+
context 'when reporting an issue for abuse' do
before do
visit project_issue_path(project, issue)
@@ -46,54 +55,102 @@ RSpec.describe 'Abuse reports', :js, feature_category: :insider_threat do
it_behaves_like 'reports the user with an abuse category'
end
- context 'when reporting a user profile for abuse' do
- let_it_be(:reporter2) { create(:user) }
+ describe 'when user_profile_overflow_menu FF turned on' do
+ context 'when reporting a user profile for abuse' do
+ let_it_be(:reporter2) { create(:user) }
- before do
- visit user_path(abusive_user)
- end
+ before do
+ visit user_path(abusive_user)
+ find_by_testid('base-dropdown-toggle').click
+ end
- it_behaves_like 'reports the user with an abuse category'
+ it_behaves_like 'reports the user with an abuse category'
- it 'allows the reporter to report the same user for different abuse categories' do
- visit user_path(abusive_user)
+ it 'allows the reporter to report the same user for different abuse categories' do
+ visit user_path(abusive_user)
- fill_and_submit_abuse_category_form
- fill_and_submit_report_abuse_form
+ find_by_testid('base-dropdown-toggle').click
+ fill_and_submit_abuse_category_form
+ fill_and_submit_report_abuse_form
- expect(page).to have_content 'Thank you for your report'
+ expect(page).to have_content 'Thank you for your report'
- visit user_path(abusive_user)
+ visit user_path(abusive_user)
- fill_and_submit_abuse_category_form("They're being offensive or abusive.")
- fill_and_submit_report_abuse_form
+ find_by_testid('base-dropdown-toggle').click
+ fill_and_submit_abuse_category_form("They're being offensive or abusive.")
+ fill_and_submit_report_abuse_form
- expect(page).to have_content 'Thank you for your report'
- end
+ expect(page).to have_content 'Thank you for your report'
+ end
- it 'allows multiple users to report the same user' do
- fill_and_submit_abuse_category_form
- fill_and_submit_report_abuse_form
+ it 'allows multiple users to report the same user' do
+ fill_and_submit_abuse_category_form
+ fill_and_submit_report_abuse_form
- expect(page).to have_content 'Thank you for your report'
+ expect(page).to have_content 'Thank you for your report'
- gitlab_sign_out
- gitlab_sign_in(reporter2)
+ gitlab_sign_out
+ gitlab_sign_in(reporter2)
- visit user_path(abusive_user)
+ visit user_path(abusive_user)
- fill_and_submit_abuse_category_form
- fill_and_submit_report_abuse_form
+ find_by_testid('base-dropdown-toggle').click
+ fill_and_submit_abuse_category_form
+ fill_and_submit_report_abuse_form
- expect(page).to have_content 'Thank you for your report'
+ expect(page).to have_content 'Thank you for your report'
+ end
+
+ it_behaves_like 'cancel report'
end
+ end
- it 'redirects backs to user profile when cancel button is clicked' do
- fill_and_submit_abuse_category_form
+ describe 'when user_profile_overflow_menu FF turned off' do
+ context 'when reporting a user profile for abuse' do
+ let_it_be(:reporter2) { create(:user) }
- click_link 'Cancel'
+ before do
+ stub_feature_flags(user_profile_overflow_menu_vue: false)
+ visit user_path(abusive_user)
+ end
- expect(page).to have_current_path(user_path(abusive_user))
+ it_behaves_like 'reports the user with an abuse category'
+
+ it 'allows the reporter to report the same user for different abuse categories' do
+ visit user_path(abusive_user)
+
+ fill_and_submit_abuse_category_form
+ fill_and_submit_report_abuse_form
+
+ expect(page).to have_content 'Thank you for your report'
+
+ visit user_path(abusive_user)
+
+ fill_and_submit_abuse_category_form("They're being offensive or abusive.")
+ fill_and_submit_report_abuse_form
+
+ expect(page).to have_content 'Thank you for your report'
+ end
+
+ it 'allows multiple users to report the same user' do
+ fill_and_submit_abuse_category_form
+ fill_and_submit_report_abuse_form
+
+ expect(page).to have_content 'Thank you for your report'
+
+ gitlab_sign_out
+ gitlab_sign_in(reporter2)
+
+ visit user_path(abusive_user)
+
+ fill_and_submit_abuse_category_form
+ fill_and_submit_report_abuse_form
+
+ expect(page).to have_content 'Thank you for your report'
+ end
+
+ it_behaves_like 'cancel report'
end
end
@@ -102,7 +159,7 @@ RSpec.describe 'Abuse reports', :js, feature_category: :insider_threat do
before do
visit project_merge_request_path(project, merge_request)
- find('[data-testid="merge-request-actions"]').click
+ find_by_testid('merge-request-actions').click
end
it_behaves_like 'reports the user with an abuse category'
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
index 9739ea53f81..18bc851558d 100644
--- a/spec/features/admin/admin_abuse_reports_spec.rb
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -2,27 +2,29 @@
require 'spec_helper'
-RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
+RSpec.describe "Admin::AbuseReports", :js, feature_category: :insider_threat do
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
- context 'as an admin' do
- describe 'displayed reports' do
- include FilteredSearchHelpers
+ let_it_be(:open_report) { create(:abuse_report, created_at: 5.days.ago, updated_at: 2.days.ago, category: 'spam', user: user) }
+ let_it_be(:open_report2) { create(:abuse_report, created_at: 4.days.ago, updated_at: 3.days.ago, category: 'phishing') }
+ let_it_be(:closed_report) { create(:abuse_report, :closed, user: user, category: 'spam') }
- let_it_be(:open_report) { create(:abuse_report, created_at: 5.days.ago, updated_at: 2.days.ago) }
- let_it_be(:open_report2) { create(:abuse_report, created_at: 4.days.ago, updated_at: 3.days.ago, category: 'phishing') }
- let_it_be(:closed_report) { create(:abuse_report, :closed) }
+ describe 'as an admin' do
+ before do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ end
- let(:abuse_report_row_selector) { '[data-testid="abuse-report-row"]' }
+ context 'when abuse_reports_list feature flag is enabled' do
+ include FilteredSearchHelpers
before do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
-
visit admin_abuse_reports_path
end
+ let(:abuse_report_row_selector) { '[data-testid="abuse-report-row"]' }
+
it 'only includes open reports by default' do
expect_displayed_reports_count(2)
@@ -68,7 +70,8 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
end
it 'can be sorted by created_at and updated_at in desc and asc order', :aggregate_failures do
- # created_at desc (default)
+ sort_by 'Created date'
+ # created_at desc
expect(report_rows[0].text).to include(report_text(open_report2))
expect(report_rows[1].text).to include(report_text(open_report))
@@ -78,25 +81,90 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
expect(report_rows[0].text).to include(report_text(open_report))
expect(report_rows[1].text).to include(report_text(open_report2))
- # updated_at ascending
+ # updated_at asc
sort_by 'Updated date'
expect(report_rows[0].text).to include(report_text(open_report2))
expect(report_rows[1].text).to include(report_text(open_report))
- # updated_at descending
+ # updated_at desc
toggle_sort_direction
expect(report_rows[0].text).to include(report_text(open_report))
expect(report_rows[1].text).to include(report_text(open_report2))
end
+ context 'when multiple reports for the same user are created' do
+ let_it_be(:open_report3) { create(:abuse_report, category: 'spam', user: user) }
+ let_it_be(:closed_report2) { create(:abuse_report, :closed, user: user, category: 'spam') }
+
+ it 'aggregates open reports by user & category', :aggregate_failures do
+ expect_displayed_reports_count(2)
+
+ expect_aggregated_report_shown(open_report, 2)
+ expect_report_shown(open_report2)
+ end
+
+ it 'can sort aggregated reports by number_of_reports in desc order only', :aggregate_failures do
+ sort_by 'Number of Reports'
+
+ expect(report_rows[0].text).to include(aggregated_report_text(open_report, 2))
+ expect(report_rows[1].text).to include(report_text(open_report2))
+
+ toggle_sort_direction
+
+ expect(report_rows[0].text).to include(aggregated_report_text(open_report, 2))
+ expect(report_rows[1].text).to include(report_text(open_report2))
+ end
+
+ it 'can sort aggregated reports by created_at and updated_at in desc and asc order', :aggregate_failures do
+ # number_of_reports desc (default)
+ expect(report_rows[0].text).to include(aggregated_report_text(open_report, 2))
+ expect(report_rows[1].text).to include(report_text(open_report2))
+
+ # created_at desc
+ sort_by 'Created date'
+
+ expect(report_rows[0].text).to include(report_text(open_report2))
+ expect(report_rows[1].text).to include(aggregated_report_text(open_report, 2))
+
+ # created_at asc
+ toggle_sort_direction
+
+ expect(report_rows[0].text).to include(aggregated_report_text(open_report, 2))
+ expect(report_rows[1].text).to include(report_text(open_report2))
+
+ sort_by 'Updated date'
+
+ # updated_at asc
+ expect(report_rows[0].text).to include(report_text(open_report2))
+ expect(report_rows[1].text).to include(aggregated_report_text(open_report, 2))
+
+ # updated_at desc
+ toggle_sort_direction
+
+ expect(report_rows[0].text).to include(aggregated_report_text(open_report, 2))
+ expect(report_rows[1].text).to include(report_text(open_report2))
+ end
+
+ it 'does not aggregate closed reports', :aggregate_failures do
+ filter %w[Status Closed]
+
+ expect_displayed_reports_count(2)
+ expect_report_shown(closed_report, closed_report2)
+ end
+ end
+
def report_rows
page.all(abuse_report_row_selector)
end
def report_text(report)
- "#{report.user.name} reported for #{report.category}"
+ "#{report.user.name} reported for #{report.category} by #{report.reporter.name}"
+ end
+
+ def aggregated_report_text(report, count)
+ "#{report.user.name} reported for #{report.category} by #{count} users"
end
def expect_report_shown(*reports)
@@ -111,6 +179,12 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
end
end
+ def expect_aggregated_report_shown(*reports, count)
+ reports.each do |r|
+ expect(page).to have_content(aggregated_report_text(r, count))
+ end
+ end
+
def expect_displayed_reports_count(count)
expect(page).to have_css(abuse_report_row_selector, count: count)
end
@@ -138,71 +212,30 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
before do
stub_feature_flags(abuse_reports_list: false)
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ visit admin_abuse_reports_path
end
- describe 'if a user has been reported for abuse' do
- let_it_be(:abuse_report) { create(:abuse_report, user: user) }
-
- describe 'in the abuse report view' do
- before do
- visit admin_abuse_reports_path
- end
-
- it 'presents information about abuse report' do
- expect(page).to have_content('Abuse Reports')
-
- expect(page).to have_content(user.name)
- expect(page).to have_content(abuse_report.reporter.name)
- expect(page).to have_content(abuse_report.message)
- expect(page).to have_link(user.name, href: user_path(user))
- end
-
- it 'present actions items' do
- expect(page).to have_link('Remove user & report')
- expect(page).to have_link('Block user')
- expect(page).to have_link('Remove user')
- end
- end
+ it 'displays all abuse reports', :aggregate_failures do
+ expect_report_shown(open_report)
+ expect_report_actions_shown(open_report)
- describe 'in the profile page of the user' do
- it 'shows a link to view user in the admin area' do
- visit user_path(user)
+ expect_report_shown(open_report2)
+ expect_report_actions_shown(open_report2)
- expect(page).to have_link 'View user in admin area', href: admin_user_path(user)
- end
- end
+ expect_report_shown(closed_report)
+ expect_report_actions_shown(closed_report)
end
- describe 'if an admin has been reported for abuse' do
+ context 'when an admin has been reported for abuse' do
let_it_be(:admin_abuse_report) { create(:abuse_report, user: admin) }
- describe 'in the abuse report view' do
- before do
- visit admin_abuse_reports_path
- end
-
- it 'presents information about abuse report' do
- page.within(:table_row, { "User" => admin.name }) do
- expect(page).to have_content(admin.name)
- expect(page).to have_content(admin_abuse_report.reporter.name)
- expect(page).to have_content(admin_abuse_report.message)
- expect(page).to have_link(admin.name, href: user_path(admin))
- end
- end
-
- it 'does not present actions items' do
- page.within(:table_row, { "User" => admin.name }) do
- expect(page).not_to have_link('Remove user & report')
- expect(page).not_to have_link('Block user')
- expect(page).not_to have_link('Remove user')
- end
- end
+ it 'displays the abuse report without actions' do
+ expect_report_shown(admin_abuse_report)
+ expect_report_actions_not_shown(admin_abuse_report)
end
end
- describe 'if a many users have been reported for abuse' do
+ context 'when multiple users have been reported for abuse' do
let(:report_count) { AbuseReport.default_per_page + 3 }
before do
@@ -211,8 +244,8 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
end
end
- describe 'in the abuse report view' do
- it 'presents information about abuse report' do
+ context 'in the abuse report view', :aggregate_failures do
+ it 'adds pagination' do
visit admin_abuse_reports_path
expect(page).to have_selector('.pagination')
@@ -221,12 +254,8 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
end
end
- describe 'filtering by user' do
- let!(:user2) { create(:user) }
- let!(:abuse_report) { create(:abuse_report, user: user) }
- let!(:abuse_report_2) { create(:abuse_report, user: user2) }
-
- it 'shows only single user report' do
+ context 'when filtering reports' do
+ it 'can be filtered by reported-user', :aggregate_failures do
visit admin_abuse_reports_path
page.within '.filter-form' do
@@ -234,14 +263,39 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :shared do
wait_for_requests
page.within '.dropdown-menu-user' do
- click_link user2.name
+ click_link user.name
end
wait_for_requests
end
- expect(page).to have_content(user2.name)
- expect(page).not_to have_content(user.name)
+ expect_report_shown(open_report)
+ expect_report_shown(closed_report)
+ end
+ end
+
+ def expect_report_shown(report)
+ page.within(:table_row, { "User" => report.user.name, "Reported by" => report.reporter.name }) do
+ expect(page).to have_content(report.user.name)
+ expect(page).to have_content(report.reporter.name)
+ expect(page).to have_content(report.message)
+ expect(page).to have_link(report.user.name, href: user_path(report.user))
+ end
+ end
+
+ def expect_report_actions_shown(report)
+ page.within(:table_row, { "User" => report.user.name, "Reported by" => report.reporter.name }) do
+ expect(page).to have_link('Remove user & report')
+ expect(page).to have_link('Block user')
+ expect(page).to have_link('Remove user')
+ end
+ end
+
+ def expect_report_actions_not_shown(report)
+ page.within(:table_row, { "User" => report.user.name, "Reported by" => report.reporter.name }) do
+ expect(page).not_to have_link('Remove user & report')
+ expect(page).not_to have_link('Block user')
+ expect(page).not_to have_link('Remove user')
end
end
end
diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb
index 68d63ac321e..47dc8577037 100644
--- a/spec/features/admin/admin_labels_spec.rb
+++ b/spec/features/admin/admin_labels_spec.rb
@@ -50,6 +50,10 @@ RSpec.describe 'admin issues labels', feature_category: :team_planning do
expect(page).to have_content("Define your default set of project labels")
expect(page).not_to have_content('bug')
expect(page).not_to have_content('feature_label')
+
+ page.within '.js-admin-labels-count' do
+ expect(page).to have_content('0')
+ end
end
end
@@ -113,7 +117,7 @@ RSpec.describe 'admin issues labels', feature_category: :team_planning do
click_link 'Delete label'
end
- expect(page).to have_content('Label was removed')
+ expect(page).to have_content("#{bug_label.title} was removed").and have_no_content("#{bug_label.title}</span>")
end
end
end
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 7fb2202ca1d..af6ba318ac6 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -117,8 +117,8 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
describe 'search' do
before_all do
- create(:ci_runner, :instance, description: 'runner-foo')
- create(:ci_runner, :instance, description: 'runner-bar')
+ create(:ci_runner, :instance, description: 'runner foo')
+ create(:ci_runner, :instance, description: 'runner bar')
end
before do
@@ -133,23 +133,23 @@ RSpec.describe "Admin Runners", feature_category: :runner_fleet do
end
it 'shows runners' do
- expect(page).to have_content("runner-foo")
- expect(page).to have_content("runner-bar")
+ expect(page).to have_content("runner foo")
+ expect(page).to have_content("runner bar")
end
it 'shows correct runner when description matches' do
- input_filtered_search_keys('runner-foo')
+ input_filtered_search_keys('runner foo')
expect(page).to have_link('All 1')
expect(page).to have_link('Instance 1')
- expect(page).to have_content("runner-foo")
- expect(page).not_to have_content("runner-bar")
+ expect(page).to have_content("runner foo")
+ expect(page).not_to have_content("runner bar")
end
context 'when description does not match' do
before do
- input_filtered_search_keys('runner-baz')
+ input_filtered_search_keys('runner baz')
end
it_behaves_like 'shows no runners found'
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index 0350c8ab066..543dc2cc2a6 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js, feature_category: :s
name = 'Hello World'
visit admin_user_impersonation_tokens_path(user_id: user.username)
+ click_button 'Add new token'
fill_in "Token name", with: name
# Set date to 1st of next month
diff --git a/spec/features/admin/broadcast_messages_spec.rb b/spec/features/admin/broadcast_messages_spec.rb
index fca4cdb0ff4..b89ebc34d6a 100644
--- a/spec/features/admin/broadcast_messages_spec.rb
+++ b/spec/features/admin/broadcast_messages_spec.rb
@@ -12,6 +12,12 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
# create
visit admin_broadcast_messages_path
+ click_button('Add new message')
+
+ page.within(preview_container) do
+ expect(page).to have_content('Your message here')
+ end
+
fill_in 'Message', with: 'test message'
wait_for_requests
@@ -24,10 +30,6 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
wait_for_requests
- page.within(preview_container) do
- expect(page).to have_content('Your message here')
- end
-
page.within(first_message_container) do
expect(page).to have_content('test message')
end
@@ -53,10 +55,6 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
wait_for_requests
- page.within(preview_container) do
- expect(page).to have_content('Your message here')
- end
-
page.within(first_message_container) do
expect(page).to have_content('changed test message')
end
diff --git a/spec/features/admin_variables_spec.rb b/spec/features/admin_variables_spec.rb
index 744d18a3b6d..91e7a46849c 100644
--- a/spec/features/admin_variables_spec.rb
+++ b/spec/features/admin_variables_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe 'Instance variables', :js, feature_category: :secrets_management
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
+ stub_feature_flags(ci_variable_drawer: false)
visit page_path
wait_for_requests
end
@@ -29,4 +30,14 @@ RSpec.describe 'Instance variables', :js, feature_category: :secrets_management
it_behaves_like 'variable list', is_admin: true
end
+
+ context 'when ci_variable_drawer FF is enabled' do
+ before do
+ stub_feature_flags(ci_variable_drawer: true)
+ visit page_path
+ wait_for_requests
+ end
+
+ it_behaves_like 'variable list drawer', is_admin: true
+ end
end
diff --git a/spec/features/broadcast_messages_spec.rb b/spec/features/broadcast_messages_spec.rb
index 2e0f4e3b83b..98f87face15 100644
--- a/spec/features/broadcast_messages_spec.rb
+++ b/spec/features/broadcast_messages_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Broadcast Messages', feature_category: :onboarding do
+ include Spec::Support::Helpers::ModalHelpers
+
let_it_be(:user) { create(:user) }
let(:path) { explore_projects_path }
@@ -127,6 +129,8 @@ RSpec.describe 'Broadcast Messages', feature_category: :onboarding do
find("[data-testid='delete-message-#{message.id}']").click
end
+ accept_gl_confirm(button_text: 'Delete message')
+
visit path
expect_no_broadcast_message
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 04b7f1ca821..747d09f5d08 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -117,9 +117,7 @@ RSpec.describe 'Dashboard Projects', feature_category: :groups_and_projects do
it 'shows the empty state when there are no starred projects' do
visit(starred_dashboard_projects_path)
- element = page.find('.row.empty-state')
-
- expect(element).to have_content("You don't have starred projects yet.")
+ expect(page).to have_text(s_("StarredProjectsEmptyState|You don't have starred projects yet."))
end
it 'shows only starred projects' do
diff --git a/spec/features/dashboard/todos/todos_filtering_spec.rb b/spec/features/dashboard/todos/todos_filtering_spec.rb
index ea8c7e800c5..990b2f18120 100644
--- a/spec/features/dashboard/todos/todos_filtering_spec.rb
+++ b/spec/features/dashboard/todos/todos_filtering_spec.rb
@@ -130,7 +130,7 @@ RSpec.describe 'Dashboard > User filters todos', :js, feature_category: :team_pl
before do
create(:todo, :build_failed, user: user_1, author: user_2, project: project_1, target: merge_request)
create(:todo, :marked, user: user_1, author: user_2, project: project_1, target: issue1)
- create(:todo, :review_requested, user: user_1, author: user_2, project: project_1, target: issue1)
+ create(:todo, :review_requested, user: user_1, author: user_2, project: project_1, target: merge_request)
end
it 'filters by Assigned' do
diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb
index 3e87c90e7dc..b4a0678cb5f 100644
--- a/spec/features/group_variables_spec.rb
+++ b/spec/features/group_variables_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe 'Group variables', :js, feature_category: :secrets_management do
before do
group.add_owner(user)
gitlab_sign_in(user)
+
+ stub_feature_flags(ci_variable_drawer: false)
visit page_path
wait_for_requests
end
@@ -27,4 +29,14 @@ RSpec.describe 'Group variables', :js, feature_category: :secrets_management do
it_behaves_like 'variable list'
end
+
+ context 'when ci_variable_drawer FF is enabled' do
+ before do
+ stub_feature_flags(ci_variable_drawer: true)
+ visit page_path
+ wait_for_requests
+ end
+
+ it_behaves_like 'variable list drawer'
+ end
end
diff --git a/spec/features/groups/container_registry_spec.rb b/spec/features/groups/container_registry_spec.rb
index ab8d8238bdc..d68b4ccf8f8 100644
--- a/spec/features/groups/container_registry_spec.rb
+++ b/spec/features/groups/container_registry_spec.rb
@@ -49,6 +49,7 @@ RSpec.describe 'Container Registry', :js, feature_category: :container_registry
it 'list page has a list of images' do
visit_container_registry
+ expect(page).to have_content '1 Image repository'
expect(page).to have_content 'my/image'
end
diff --git a/spec/features/groups/labels/edit_spec.rb b/spec/features/groups/labels/edit_spec.rb
index 2cbe44e11bf..6e056d35435 100644
--- a/spec/features/groups/labels/edit_spec.rb
+++ b/spec/features/groups/labels/edit_spec.rb
@@ -32,6 +32,6 @@ RSpec.describe 'Edit group label', feature_category: :team_planning do
click_link 'Delete label'
end
- expect(page).to have_content("#{label.title} deleted permanently")
+ expect(page).to have_content("#{label.title} was removed").and have_no_content("#{label.title}</span>")
end
end
diff --git a/spec/features/groups/settings/group_badges_spec.rb b/spec/features/groups/settings/group_badges_spec.rb
index 4a4cb297fcf..1f16a288882 100644
--- a/spec/features/groups/settings/group_badges_spec.rb
+++ b/spec/features/groups/settings/group_badges_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Group Badges', feature_category: :groups_and_projects do
page.within '.badge-settings' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
expect(rows[0]).to have_content badge_1.link_url
expect(rows[1]).to have_content badge_2.link_url
@@ -33,6 +33,7 @@ RSpec.describe 'Group Badges', feature_category: :groups_and_projects do
context 'adding a badge', :js do
it 'user can preview a badge' do
+ click_button 'Add badge'
page.within '.badge-settings form' do
fill_in 'badge-link-url', with: badge_link_url
fill_in 'badge-image-url', with: badge_image_url
@@ -44,6 +45,7 @@ RSpec.describe 'Group Badges', feature_category: :groups_and_projects do
end
it do
+ click_button 'Add badge'
page.within '.badge-settings' do
fill_in 'badge-link-url', with: badge_link_url
fill_in 'badge-image-url', with: badge_image_url
@@ -51,7 +53,7 @@ RSpec.describe 'Group Badges', feature_category: :groups_and_projects do
click_button 'Add badge'
wait_for_requests
- within '.card-body' do
+ within '.gl-card-body' do
expect(find('a')[:href]).to eq badge_link_url
expect(find('a img')[:src]).to eq badge_image_url
end
@@ -63,32 +65,35 @@ RSpec.describe 'Group Badges', feature_category: :groups_and_projects do
it 'form is shown when clicking edit button in list' do
page.within '.badge-settings' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
rows[1].find('[aria-label="Edit"]').click
+ end
- within 'form' do
- expect(find('#badge-link-url').value).to eq badge_2.link_url
- expect(find('#badge-image-url').value).to eq badge_2.image_url
- end
+ page.within '.gl-modal' do
+ expect(find('#badge-link-url').value).to eq badge_2.link_url
+ expect(find('#badge-image-url').value).to eq badge_2.image_url
end
end
it 'updates a badge when submitting the edit form' do
page.within '.badge-settings' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
rows[1].find('[aria-label="Edit"]').click
- within 'form' do
- fill_in 'badge-link-url', with: badge_link_url
- fill_in 'badge-image-url', with: badge_image_url
+ end
- click_button 'Save changes'
- wait_for_requests
- end
+ page.within '.gl-modal' do
+ fill_in 'badge-link-url', with: badge_link_url
+ fill_in 'badge-image-url', with: badge_image_url
- rows = all('.card-body > div')
+ click_button 'Save changes'
+ wait_for_requests
+ end
+
+ page.within '.badge-settings' do
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
expect(rows[1]).to have_content badge_link_url
end
@@ -102,7 +107,7 @@ RSpec.describe 'Group Badges', feature_category: :groups_and_projects do
it 'shows a modal when deleting a badge' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
click_delete_button(rows[1])
@@ -112,14 +117,14 @@ RSpec.describe 'Group Badges', feature_category: :groups_and_projects do
it 'deletes a badge when confirming the modal' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
click_delete_button(rows[1])
find('.modal .btn-danger').click
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 1
expect(rows[0]).to have_content badge_1.link_url
end
diff --git a/spec/features/incidents/incident_details_spec.rb b/spec/features/incidents/incident_details_spec.rb
index 2be0c95addd..d6feb008d47 100644
--- a/spec/features/incidents/incident_details_spec.rb
+++ b/spec/features/incidents/incident_details_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Incident details', :js, feature_category: :incident_management d
private
def dropdown_options
- widget.all('[data-testid="status-dropdown-item"]', count: 3)
+ widget.all('[data-testid="escalation-status-dropdown"] .gl-new-dropdown-item', count: 3)
end
def select_resolved(options)
diff --git a/spec/features/incidents/user_views_incident_spec.rb b/spec/features/incidents/user_views_incident_spec.rb
index bbf579b09a8..65bd88582db 100644
--- a/spec/features/incidents/user_views_incident_spec.rb
+++ b/spec/features/incidents/user_views_incident_spec.rb
@@ -75,35 +75,4 @@ RSpec.describe "User views incident", feature_category: :incident_management do
expect(page).not_to have_button('Incident actions')
end
end
-
- describe 'user status' do
- context 'when showing status of the author of the incident' do
- subject { visit(incident_project_issues_path(project, incident)) }
-
- it_behaves_like 'showing user status' do
- let(:user_with_status) { user }
- end
- end
-
- context 'when status message has an emoji', :js do
- let_it_be(:message) { 'My status with an emoji' }
- let_it_be(:message_emoji) { 'basketball' }
- let_it_be(:status) { create(:user_status, user: user, emoji: 'smirk', message: "#{message} :#{message_emoji}:") }
-
- it 'correctly renders the emoji' do
- wait_for_requests
-
- tooltip_span = page.first(".user-status-emoji[title^='#{message}']")
- tooltip_span.hover
-
- wait_for_requests
-
- tooltip = page.find('.tooltip .tooltip-inner')
-
- page.within(tooltip) do
- expect(page).to have_emoji(message_emoji)
- end
- end
- end
- end
end
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index 57270e8f7c7..0a06a052bc2 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe 'Dropdown assignee', :js, feature_category: :team_planning do
sign_in(subgroup_user)
end
- it 'shows inherited, direct, and invited group members but not descendent members', :aggregate_failures do
+ it 'shows inherited, direct, and invited group members including descendent members', :aggregate_failures do
visit issues_group_path(subgroup)
select_tokens 'Assignee', '='
@@ -100,8 +100,8 @@ RSpec.describe 'Dropdown assignee', :js, feature_category: :team_planning do
expect(page).to have_text group_user.name
expect(page).to have_text subgroup_user.name
expect(page).to have_text invited_to_group_group_user.name
- expect(page).not_to have_text subsubgroup_user.name
- expect(page).not_to have_text invited_to_project_group_user.name
+ expect(page).to have_text subsubgroup_user.name
+ expect(page).to have_text invited_to_project_group_user.name
visit project_issues_path(subgroup_project)
@@ -113,5 +113,33 @@ RSpec.describe 'Dropdown assignee', :js, feature_category: :team_planning do
expect(page).to have_text invited_to_group_group_user.name
expect(page).not_to have_text subsubgroup_user.name
end
+
+ context 'when new_graphql_users_autocomplete is disabled' do
+ before do
+ stub_feature_flags(new_graphql_users_autocomplete: false)
+ end
+
+ it 'shows inherited, direct, and invited group members but not descendent members', :aggregate_failures do
+ visit issues_group_path(subgroup)
+
+ select_tokens 'Assignee', '='
+
+ expect(page).to have_text group_user.name
+ expect(page).to have_text subgroup_user.name
+ expect(page).to have_text invited_to_group_group_user.name
+ expect(page).not_to have_text subsubgroup_user.name
+ expect(page).not_to have_text invited_to_project_group_user.name
+
+ visit project_issues_path(subgroup_project)
+
+ select_tokens 'Assignee', '='
+
+ expect(page).to have_text group_user.name
+ expect(page).to have_text subgroup_user.name
+ expect(page).to have_text invited_to_project_group_user.name
+ expect(page).to have_text invited_to_group_group_user.name
+ expect(page).not_to have_text subsubgroup_user.name
+ end
+ end
end
end
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
index 145b51d207a..5197f5d1e33 100644
--- a/spec/features/issues/incident_issue_spec.rb
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -70,10 +70,6 @@ RSpec.describe 'Incident Detail', :js, feature_category: :team_planning do
# 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"]', wait: false)
- expect(edit_button.count).to eq(0)
end
end
end
diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb
index 23f9347d726..a390dca6822 100644
--- a/spec/features/issues/note_polling_spec.rb
+++ b/spec/features/issues/note_polling_spec.rb
@@ -10,17 +10,31 @@ RSpec.describe 'Issue notes polling', :js, feature_category: :team_planning do
let(:issue) { create(:issue, project: project) }
describe 'creates' do
- before do
+ it 'displays the new comment' do
visit project_issue_path(project, issue)
close_rich_text_promo_popover_if_present
- end
- it 'displays the new comment' do
note = create(:note, noteable: issue, project: project, note: 'Looks good!')
wait_for_requests
expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!')
end
+
+ context 'when action_cable_notes is disabled' do
+ before do
+ stub_feature_flags(action_cable_notes: false)
+ end
+
+ it 'displays the new comment' do
+ visit project_issue_path(project, issue)
+ close_rich_text_promo_popover_if_present
+
+ note = create(:note, noteable: issue, project: project, note: 'Looks good!')
+ wait_for_requests
+
+ expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!')
+ end
+ end
end
describe 'updates' do
diff --git a/spec/features/issues/service_desk_spec.rb b/spec/features/issues/service_desk_spec.rb
index 923967c52c0..1b99c8b39d3 100644
--- a/spec/features/issues/service_desk_spec.rb
+++ b/spec/features/issues/service_desk_spec.rb
@@ -184,6 +184,42 @@ RSpec.describe 'Service Desk Issue Tracker', :js, feature_category: :service_des
stub_feature_flags(frontend_caching: true)
end
+ context 'when there are no issues' do
+ describe 'service desk empty state' do
+ it 'displays the large empty state, documentation, and the email address' do
+ visit service_desk_project_issues_path(project)
+
+ aggregate_failures do
+ expect(page).to have_css('.empty-state')
+ expect(page).to have_text('Use Service Desk to connect with your users')
+ expect(page).to have_link('Learn more about Service Desk', href: help_page_path('user/project/service_desk/index'))
+ expect(page).not_to have_link('Enable Service Desk')
+ expect(page).to have_content(project.service_desk_address)
+ end
+ end
+
+ context 'when user does not have permission to edit project settings' do
+ before do
+ user_2 = create(:user)
+
+ project.add_guest(user_2)
+ sign_in(user_2)
+ visit service_desk_project_issues_path(project)
+ end
+
+ it 'displays the large info box and the documentation link' do
+ aggregate_failures do
+ expect(page).to have_css('.empty-state')
+ expect(page).to have_text('Use Service Desk to connect with your users')
+ expect(page).to have_link('Learn more about Service Desk', href: help_page_path('user/project/service_desk/index'))
+ expect(page).not_to have_link('Enable Service Desk')
+ expect(page).not_to have_content(project.service_desk_address)
+ end
+ end
+ end
+ end
+ end
+
context 'when there are issues' do
let_it_be(:project) { create(:project, :private, service_desk_enabled: true) }
let_it_be(:other_user) { create(:user) }
@@ -197,7 +233,7 @@ RSpec.describe 'Service Desk Issue Tracker', :js, feature_category: :service_des
it 'displays the small info box, documentation, a button to configure service desk, and the address' do
aggregate_failures do
- expect(page).to have_link('Learn more', href: help_page_path('user/project/service_desk'))
+ expect(page).to have_link('Learn more about Service Desk', href: help_page_path('user/project/service_desk/index'))
expect(page).not_to have_link('Enable Service Desk')
expect(page).to have_content(project.service_desk_address)
end
diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index ecb899a7ca2..0c50b7b2475 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -112,6 +112,18 @@ RSpec.describe 'User creates branch and merge request on issue page', :js, featu
expect(page).to have_selector('.ref-selector', text: branch_name)
expect(page).to have_current_path project_tree_path(project, branch_name), ignore_query: true
end
+
+ context 'when source branch is non-default' do
+ let(:source_branch) { 'feature' }
+
+ it 'creates a branch' do
+ select_dropdown_option('create-branch', branch_name, source_branch)
+ wait_for_requests
+
+ expect(page).to have_selector('.ref-selector', text: branch_name)
+ expect(page).to have_current_path project_tree_path(project, branch_name), ignore_query: true
+ end
+ end
end
context 'when branch name is invalid' do
@@ -231,12 +243,13 @@ RSpec.describe 'User creates branch and merge request on issue page', :js, featu
private
- def select_dropdown_option(option, branch_name = nil)
+ def select_dropdown_option(option, branch_name = nil, source_branch = nil)
find('.create-mr-dropdown-wrap .dropdown-toggle').click
find("li[data-value='#{option}']").click
- if branch_name
- find('.js-branch-name').set(branch_name)
+ if branch_name || source_branch
+ find('.js-branch-name').set(branch_name) if branch_name
+ find('.js-ref').set(source_branch) if source_branch
# Javascript debounces AJAX calls.
# So we have to wait until AJAX requests are started.
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 0938f9c7d12..45d95db8ff1 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -130,7 +130,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin
click_button("Switch to rich text editing")
end
- expect(issuable_form).not_to have_selector(content_editor_focused_selector)
+ expect(issuable_form).to have_selector(content_editor_focused_selector)
refresh
@@ -142,11 +142,11 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin
click_button("Switch to plain text editing")
end
- expect(issuable_form).not_to have_selector(markdown_field_focused_selector)
+ expect(issuable_form).to have_selector(markdown_field_focused_selector)
end
end
- describe 'update labels' do
+ describe 'update labels', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/345229' do
it 'will not send ajax request when no data is changed' do
page.within '.labels' do
click_on 'Edit'
diff --git a/spec/features/issues/user_toggles_subscription_spec.rb b/spec/features/issues/user_toggles_subscription_spec.rb
index 00b04c10d33..af8a31afd5f 100644
--- a/spec/features/issues/user_toggles_subscription_spec.rb
+++ b/spec/features/issues/user_toggles_subscription_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe "User toggles subscription", :js, feature_category: :team_plannin
expect(subscription_button).to have_css("button.is-checked")
# Toggle subscription.
- find('[data-testid="subscription-toggle"]').click
+ subscription_button.find('button').click
wait_for_requests
# Check we're unsubscribed.
@@ -42,7 +42,7 @@ RSpec.describe "User toggles subscription", :js, feature_category: :team_plannin
end
context 'when project emails are disabled' do
- let(:project) { create(:project_empty_repo, :public, emails_disabled: true) }
+ let_it_be(:project) { create(:project_empty_repo, :public, emails_enabled: false) }
it 'is disabled' do
expect(page).to have_content('Disabled by project owner')
@@ -66,7 +66,7 @@ RSpec.describe "User toggles subscription", :js, feature_category: :team_plannin
expect(subscription_button).to have_css("button:not(.is-checked)")
# Toggle subscription.
- find('[data-testid="subscription-toggle"]').click
+ subscription_button.find('button').click
wait_for_requests
# Check we're subscribed.
diff --git a/spec/features/issues/user_views_issue_spec.rb b/spec/features/issues/user_views_issue_spec.rb
index 17ff3e0c702..00aa7685e9d 100644
--- a/spec/features/issues/user_views_issue_spec.rb
+++ b/spec/features/issues/user_views_issue_spec.rb
@@ -39,42 +39,4 @@ RSpec.describe "User views issue", feature_category: :team_planning do
expect(page).not_to have_link('Close issue')
end
end
-
- describe 'user status' do
- subject { visit(project_issue_path(project, issue)) }
-
- context 'when showing status of the author of the issue' do
- it_behaves_like 'showing user status' do
- let(:user_with_status) { user }
- end
- end
-
- context 'when showing status of a user who commented on an issue', :js do
- it_behaves_like 'showing user status' do
- let(:user_with_status) { user }
- end
- end
-
- context 'when status message has an emoji', :js do
- let_it_be(:message) { 'My status with an emoji' }
- let_it_be(:message_emoji) { 'basketball' }
- let_it_be(:status) { create(:user_status, user: user, emoji: 'smirk', message: "#{message} :#{message_emoji}:") }
-
- it 'correctly renders the emoji' do
- wait_for_requests
-
- tooltip_span = page.first(".user-status-emoji[title^='#{message}']")
-
- tooltip_span.hover
-
- wait_for_requests
-
- tooltip = page.find('.tooltip .tooltip-inner')
-
- page.within(tooltip) do
- expect(page).to have_emoji(message_emoji)
- end
- end
- end
- end
end
diff --git a/spec/features/markdown/gitlab_flavored_markdown_spec.rb b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
index 36b02b17924..cd011315ed0 100644
--- a/spec/features/markdown/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
@@ -57,16 +57,21 @@ RSpec.describe "GitLab Flavored Markdown", feature_category: :team_planning do
describe "for issues", :js do
before do
- @other_issue = create(:issue,
- author: user,
- assignees: [user],
- project: project)
- @issue = create(:issue,
- author: user,
- assignees: [user],
- project: project,
- title: "fix #{@other_issue.to_reference}",
- description: "ask #{fred.to_reference} for details")
+ @other_issue = create(
+ :issue,
+ author: user,
+ assignees: [user],
+ project: project
+ )
+
+ @issue = create(
+ :issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ title: "fix #{@other_issue.to_reference}",
+ description: "ask #{fred.to_reference} for details"
+ )
@note = create(:note_on_issue, noteable: @issue, project: @issue.project, note: "Hello world")
end
@@ -112,10 +117,12 @@ RSpec.describe "GitLab Flavored Markdown", feature_category: :team_planning do
describe "for milestones" do
before do
- @milestone = create(:milestone,
- project: project,
- title: "fix #{issue.to_reference}",
- description: "ask #{fred.to_reference} for details")
+ @milestone = create(
+ :milestone,
+ project: project,
+ title: "fix #{issue.to_reference}",
+ description: "ask #{fred.to_reference} for details"
+ )
end
it "renders title in milestones#index" do
diff --git a/spec/features/merge_request/creating_mr_for_projects_with_different_visibility_spec.rb b/spec/features/merge_request/creating_mr_for_projects_with_different_visibility_spec.rb
new file mode 100644
index 00000000000..3597c2ed1c7
--- /dev/null
+++ b/spec/features/merge_request/creating_mr_for_projects_with_different_visibility_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge Request > Selecting projects with different visibility', feature_category: :source_code_management do
+ include ProjectForksHelper
+
+ let_it_be(:public_project) { create(:project, :public, :small_repo) }
+ let_it_be(:internal_project) { create(:project, :internal, :small_repo) }
+ let_it_be(:private_project) { create(:project, :private, :small_repo) }
+ let(:private_fork_public_project) do
+ fork_project(public_project, nil, target_project: create(:project, :private, :small_repo))
+ end
+
+ let(:private_fork_internal_project) do
+ fork_project(internal_project, nil, target_project: create(:project, :private, :small_repo))
+ end
+
+ let(:internal_fork_public_project) do
+ fork_project(public_project, nil, target_project: create(:project, :internal, :small_repo))
+ end
+
+ let(:user) { source_project.creator }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'warnings for more permissive visibility in target project', :js do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:source_project, :target_project, :warning_message) do
+ ref(:private_fork_internal_project) |
+ ref(:internal_project) |
+ _('This merge request is from a private project to an internal project.')
+
+ ref(:private_fork_public_project) |
+ ref(:public_project) |
+ _('This merge request is from a private project to a public project.')
+
+ ref(:internal_fork_public_project) |
+ ref(:public_project) |
+ _('This merge request is from an internal project to a public project.')
+ end
+
+ with_them do
+ it 'shows a warning message' do
+ visit project_new_merge_request_path(source_project,
+ merge_request: { source_branch: 'master', target_project_id: target_project.id })
+ expect(page).to have_content(warning_message)
+ end
+ end
+
+ describe 'warnings for more permissive repository access level in target project' do
+ let(:source_project) do
+ fork_project(internal_project, nil, target_project: create(:project, :internal, :small_repo))
+ end
+
+ let(:target_project) { internal_project }
+
+ let(:warning_message) do
+ "Project #{source_project.name_with_namespace} has more restricted access settings than " \
+ "#{target_project.name_with_namespace}. To avoid exposing private changes, make sure " \
+ "you're submitting changes to the correct project."
+ end
+
+ context 'when the source repository access level is private' do
+ before do
+ source_access_level = Featurable::PRIVATE
+ source_project.project_feature.update!(
+ repository_access_level: source_access_level,
+ merge_requests_access_level: source_access_level,
+ builds_access_level: source_access_level
+ )
+ end
+
+ it 'shows a warning' do
+ visit project_new_merge_request_path(source_project,
+ merge_request: { source_branch: 'master', target_project_id: target_project.id })
+ expect(page).to have_content(warning_message)
+ end
+
+ context 'when target project is private' do
+ let(:source_project) do
+ fork_project(private_project, nil, target_project: create(:project, :private, :small_repo))
+ end
+
+ let(:target_project) { private_project }
+
+ it 'does not show a warning' do
+ visit project_new_merge_request_path(source_project,
+ merge_request: { source_branch: 'master', target_project_id: target_project.id })
+
+ expect(page).not_to have_content(warning_message)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb
index ab7183775b9..bf237e07ac8 100644
--- a/spec/features/merge_request/user_edits_mr_spec.rb
+++ b/spec/features/merge_request/user_edits_mr_spec.rb
@@ -184,11 +184,6 @@ RSpec.describe 'Merge request > User edits MR', feature_category: :code_review_w
it 'allows to unselect "Remove source branch"', :js do
expect(merge_request.merge_params['force_remove_source_branch']).to be_truthy
- begin
- visit edit_project_merge_request_path(target_project, merge_request)
- rescue Selenium::WebDriver::Error::UnexpectedAlertOpenError
- end
-
uncheck 'Delete source branch when merge request is accepted'
click_button 'Save changes'
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 8c4dbf5ebfd..add8e9f30de 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
@@ -28,12 +28,26 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
let(:expected_detached_mr_tag) { 'merge request' }
before do
+ # rubocop:disable RSpec/AvoidConditionalStatements
+ stub_licensed_features(merge_request_approvers: true) if Gitlab.ee?
+ # rubocop:enable RSpec/AvoidConditionalStatements
+
stub_application_setting(auto_devops_enabled: false)
stub_ci_pipeline_yaml_file(YAML.dump(config))
project.add_maintainer(user)
sign_in(user)
end
+ # rubocop:disable RSpec/AvoidConditionalStatements
+ def mr_widget_title
+ if Gitlab.ee?
+ 'to be merged automatically when all merge checks pass'
+ else
+ 'to be merged automatically when the pipeline succeeds'
+ end
+ end
+ # rubocop:enable RSpec/AvoidConditionalStatements
+
context 'when a user created a merge request in the parent project' do
let!(:merge_request) do
create(
@@ -163,7 +177,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline is pending' do
it 'waits the head pipeline' do
- expect(page).to have_content('to be merged automatically when the pipeline succeeds')
+ expect(page).to have_content mr_widget_title
expect(page).to have_button('Cancel auto-merge')
end
end
@@ -177,7 +191,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
end
it 'waits the head pipeline' do
- expect(page).to have_content('to be merged automatically when the pipeline succeeds')
+ expect(page).to have_content mr_widget_title
expect(page).to have_button('Cancel auto-merge')
end
end
@@ -388,7 +402,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline is pending' do
it 'waits the head pipeline' do
- expect(page).to have_content('to be merged automatically when the pipeline succeeds')
+ expect(page).to have_content mr_widget_title
expect(page).to have_button('Cancel auto-merge')
end
end
@@ -397,7 +411,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
before do
detached_merge_request_pipeline.reload.succeed!
- wait_for_requests
+ refresh
end
it 'merges the merge request' do
@@ -414,7 +428,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
end
it 'waits the head pipeline' do
- expect(page).to have_content('to be merged automatically when the pipeline succeeds')
+ expect(page).to have_content mr_widget_title
expect(page).to have_button('Cancel auto-merge')
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 3cac24838a3..75df93d1a6c 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -197,7 +197,8 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} pending")
+ expect(page).to have_content("Pipeline pending " \
"for #{pipeline.short_sha} " \
"on #{pipeline.ref}")
end
@@ -227,7 +228,8 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
shared_examples 'pipeline widget' do
it 'shows head pipeline information', :sidekiq_might_not_need_inline do
within '.ci-widget-content' do
- expect(page).to have_content("Merge request pipeline ##{pipeline.id} pending for #{pipeline.short_sha}")
+ expect(page).to have_content("Merge request pipeline ##{pipeline.id} pending")
+ expect(page).to have_content("Merge request pipeline pending for #{pipeline.short_sha}")
end
end
end
@@ -266,7 +268,8 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
shared_examples 'pipeline widget' do
it 'shows head pipeline information', :sidekiq_might_not_need_inline do
within '.ci-widget-content' do
- expect(page).to have_content("Merged result pipeline ##{pipeline.id} pending for #{pipeline.short_sha}")
+ expect(page).to have_content("Merged result pipeline ##{pipeline.id} pending")
+ expect(page).to have_content("Merged result pipeline pending for #{pipeline.short_sha}")
end
end
end
diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
index 5756218d20f..9883434eb68 100644
--- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
+++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
@@ -97,8 +97,8 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js, feature_cat
describe 'build list build item' do
let(:build_item) do
- find('.mini-pipeline-graph-dropdown-item')
- first('.mini-pipeline-graph-dropdown-item')
+ find('.pipeline-job-item')
+ first('.pipeline-job-item')
end
it 'visits the build page when clicked' do
diff --git a/spec/features/merge_requests/user_sees_note_updates_in_real_time_spec.rb b/spec/features/merge_requests/user_sees_note_updates_in_real_time_spec.rb
new file mode 100644
index 00000000000..2c7567b1b40
--- /dev/null
+++ b/spec/features/merge_requests/user_sees_note_updates_in_real_time_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge request note updates in real time', :js, feature_category: :code_review_workflow do
+ include NoteInteractionHelpers
+ include ContentEditorHelpers
+
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ before do
+ visit project_merge_request_path(project, merge_request)
+ close_rich_text_promo_popover_if_present
+ end
+
+ describe 'new notes' do
+ it 'displays the new note' do
+ note = create(:note, noteable: merge_request, project: project, note: 'Looks good!')
+
+ expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!')
+ end
+ end
+
+ describe 'updated notes' do
+ let(:note_text) { "Hello World" }
+ let(:updated_text) { "Bye World" }
+ let!(:existing_note) do
+ create(:discussion_note_on_merge_request, noteable: merge_request, project: project, note: note_text)
+ end
+
+ it 'displays the updated note', :aggregate_failures do
+ expect(page).to have_selector("#note_#{existing_note.id}", text: note_text)
+
+ existing_note.update!(note: updated_text)
+ expect(page).to have_selector("#note_#{existing_note.id}", text: updated_text)
+
+ existing_note.resolve!(merge_request.author)
+ expect(page).to have_selector(
+ "#note_#{existing_note.id} .discussion-resolved-text",
+ text: /\AResolved .* by #{merge_request.author.name}\z/
+ )
+ end
+ end
+end
diff --git a/spec/features/nav/top_nav_tooltip_spec.rb b/spec/features/nav/top_nav_tooltip_spec.rb
index 17828778112..1afd1981a86 100644
--- a/spec/features/nav/top_nav_tooltip_spec.rb
+++ b/spec/features/nav/top_nav_tooltip_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'top nav tooltips', :js, feature_category: :navigation do
end
it 'clicking new dropdown hides tooltip', :aggregate_failures,
- quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/382786' do
+ quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/382786' do
btn = '#js-onboarding-new-project-link'
page.find(btn).hover
diff --git a/spec/features/oauth_provider_authorize_spec.rb b/spec/features/oauth_provider_authorize_spec.rb
index 7638563b4a3..310a2e4c2de 100644
--- a/spec/features/oauth_provider_authorize_spec.rb
+++ b/spec/features/oauth_provider_authorize_spec.rb
@@ -9,11 +9,13 @@ RSpec.describe 'OAuth Provider', feature_category: :system_access do
before do
sign_in(user)
- visit oauth_authorization_path(client_id: application.uid,
- redirect_uri: application.redirect_uri.split.first,
- response_type: 'code',
- state: 'my_state',
- scope: 'read_user')
+ visit oauth_authorization_path(
+ client_id: application.uid,
+ redirect_uri: application.redirect_uri.split.first,
+ response_type: 'code',
+ state: 'my_state',
+ scope: 'read_user'
+ )
end
it_behaves_like 'Secure OAuth Authorizations'
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index d8501116134..dbeca601617 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -62,8 +62,7 @@ RSpec.describe 'Member autocomplete', :js, feature_category: :groups_and_project
context 'adding a new note on a Merge Request' do
let(:noteable) do
- create(:merge_request, source_project: project,
- target_project: project, author: author)
+ create(:merge_request, source_project: project, target_project: project, author: author)
end
before do
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index e190dfda937..b6c96555767 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -38,8 +38,7 @@ RSpec.describe 'Profile account page', :js, feature_category: :user_profile do
expect(page).to have_content('Account scheduled for removal')
expect(
- Users::GhostUserMigration.where(user: user,
- initiator_user: user)
+ Users::GhostUserMigration.where(user: user, initiator_user: user)
).to be_exists
end
@@ -71,7 +70,7 @@ RSpec.describe 'Profile account page', :js, feature_category: :user_profile do
previous_token = ''
- within('[data-testid="feed-token-container"]') do
+ within_testid('feed-token-container') do
previous_token = find_field('Feed token').value
click_link('reset this token')
@@ -79,7 +78,7 @@ RSpec.describe 'Profile account page', :js, feature_category: :user_profile do
accept_gl_confirm
- within('[data-testid="feed-token-container"]') do
+ within_testid('feed-token-container') do
click_button('Click to reveal')
expect(find_field('Feed token').value).not_to eq(previous_token)
@@ -93,7 +92,7 @@ RSpec.describe 'Profile account page', :js, feature_category: :user_profile do
previous_token = ''
- within('[data-testid="incoming-email-token-container"]') do
+ within_testid('incoming-email-token-container') do
previous_token = find_field('Incoming email token').value
click_link('reset this token')
@@ -101,7 +100,7 @@ RSpec.describe 'Profile account page', :js, feature_category: :user_profile do
accept_gl_confirm
- within('[data-testid="incoming-email-token-container"]') do
+ within_testid('incoming-email-token-container') do
click_button('Click to reveal')
expect(find_field('Incoming email token').value).not_to eq(previous_token)
diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb
index 0de4ad47f9a..2e800ae88b6 100644
--- a/spec/features/profiles/active_sessions_spec.rb
+++ b/spec/features/profiles/active_sessions_spec.rb
@@ -57,9 +57,7 @@ RSpec.describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state, fe
using_session :session1 do
visit profile_active_sessions_path
- expect(page).to(
- have_selector('ul.list-group li.list-group-item', text: 'Signed in on',
- count: 2))
+ expect(page).to(have_selector('ul.list-group li.list-group-item', text: 'Signed in on', count: 2))
expect(page).to have_content(
'127.0.0.1 ' \
diff --git a/spec/features/profiles/gpg_keys_spec.rb b/spec/features/profiles/gpg_keys_spec.rb
index f39d9ddaf56..38abf9d20b0 100644
--- a/spec/features/profiles/gpg_keys_spec.rb
+++ b/spec/features/profiles/gpg_keys_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe 'Profile > GPG Keys', feature_category: :user_profile do
end
it 'saves the new key' do
+ click_button('Add new key')
fill_in('Key', with: GpgHelpers::User2.public_key)
click_button('Add key')
@@ -24,6 +25,7 @@ RSpec.describe 'Profile > GPG Keys', feature_category: :user_profile do
end
it 'with multiple subkeys' do
+ click_button('Add new key')
fill_in('Key', with: GpgHelpers::User3.public_key)
click_button('Add key')
@@ -52,7 +54,10 @@ RSpec.describe 'Profile > GPG Keys', feature_category: :user_profile do
click_link('Remove')
- expect(page).to have_content('Your GPG keys (0)')
+ expect(page).to have_content('Your GPG keys')
+ page.within('.gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
end
it 'user revokes a key via the key index' do
@@ -63,7 +68,10 @@ RSpec.describe 'Profile > GPG Keys', feature_category: :user_profile do
click_link('Revoke')
- expect(page).to have_content('Your GPG keys (0)')
+ expect(page).to have_content('Your GPG keys')
+ page.within('.gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
expect(gpg_signature.reload).to have_attributes(
verification_status: 'unknown_key',
diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb
index ae61f1cf492..cb270b669d3 100644
--- a/spec/features/profiles/keys_spec.rb
+++ b/spec/features/profiles/keys_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do
end
it 'auto-populates the title', :js do
+ click_button('Add new key')
fill_in('Key', with: attributes_for(:key).fetch(:key))
expect(page).to have_field("Title", with: "dummy@gitlab.com")
@@ -23,11 +24,12 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do
it 'saves the new key' do
attrs = attributes_for(:key)
+ click_button('Add new key')
fill_in('Key', with: attrs[:key])
fill_in('Title', with: attrs[:title])
click_button('Add key')
- expect(page).to have_content("Title: #{attrs[:title]}")
+ expect(page).to have_content(format(s_('Profiles|SSH Key: %{title}'), title: attrs[:title]))
expect(page).to have_content(attrs[:key])
expect(find('[data-testid="breadcrumb-current-link"]')).to have_link(attrs[:title])
end
@@ -35,6 +37,7 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do
it 'shows a confirmable warning if the key begins with an algorithm name that is unsupported' do
attrs = attributes_for(:key)
+ click_button('Add new key')
fill_in('Key', with: 'unsupported-ssh-rsa key')
fill_in('Title', with: attrs[:title])
click_button('Add key')
@@ -60,6 +63,7 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do
it 'shows a validation error' do
attrs = attributes_for(:key)
+ click_button('Add new key')
fill_in('Key', with: attrs[:key])
fill_in('Title', with: attrs[:title])
click_button('Add key')
@@ -79,13 +83,16 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do
def destroy_key(path, action, confirmation_button)
visit path
- page.click_button(action)
+ page.find("button[aria-label=\"#{action}\"]").click
page.within('.modal') do
page.click_button(confirmation_button)
end
- expect(page).to have_content('Your SSH keys (0)')
+ expect(page).to have_content('Your SSH keys')
+ page.within('.gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
end
describe 'User removes a key', :js do
@@ -111,11 +118,13 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do
let!(:commit) { project.commit('ssh-signed-commit') }
let!(:signature) do
- create(:ssh_signature,
- project: project,
- key: key,
- key_fingerprint_sha256: key.fingerprint_sha256,
- commit_sha: commit.sha)
+ create(
+ :ssh_signature,
+ project: project,
+ key: key,
+ key_fingerprint_sha256: key.fingerprint_sha256,
+ commit_sha: commit.sha
+ )
end
before do
diff --git a/spec/features/profiles/list_users_comment_template_spec.rb b/spec/features/profiles/list_users_comment_template_spec.rb
index 85e455ba988..b2faee3ae04 100644
--- a/spec/features/profiles/list_users_comment_template_spec.rb
+++ b/spec/features/profiles/list_users_comment_template_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'Profile > Comment templates > List users comment templates', :js
it 'shows the user a list of their comment templates' do
visit profile_comment_templates_path
- expect(page).to have_content('My comment templates (1)')
+ expect(page).to have_content('My comment templates')
expect(page).to have_content(saved_reply.name)
expect(page).to have_content(saved_reply.content)
end
diff --git a/spec/features/profiles/oauth_applications_spec.rb b/spec/features/profiles/oauth_applications_spec.rb
index d088f73f9df..0b1d67d00c9 100644
--- a/spec/features/profiles/oauth_applications_spec.rb
+++ b/spec/features/profiles/oauth_applications_spec.rb
@@ -25,15 +25,21 @@ RSpec.describe 'Profile > Applications', feature_category: :user_profile do
visit oauth_applications_path
page.within('.oauth-applications') do
- expect(page).to have_content('Your applications (1)')
+ page.within('.gl-new-card-count') do
+ expect(page).to have_content('1')
+ end
click_button 'Destroy'
end
accept_gl_confirm(button_text: 'Destroy')
expect(page).to have_content('The application was deleted successfully')
- expect(page).to have_content('Your applications (0)')
- expect(page).to have_content('Authorized applications (0)')
+ page.within('.oauth-applications .gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
+ page.within('.oauth-authorized-applications .gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
end
end
@@ -57,7 +63,9 @@ RSpec.describe 'Profile > Applications', feature_category: :user_profile do
it 'displays the correct authorized applications' do
visit oauth_applications_path
- expect(page).to have_content('Authorized applications (2)')
+ page.within('.oauth-authorized-applications .gl-new-card-count') do
+ expect(page).to have_content('2')
+ end
page.within('div.oauth-authorized-applications') do
# Ensure the correct user's token details are displayed
@@ -85,7 +93,9 @@ RSpec.describe 'Profile > Applications', feature_category: :user_profile do
accept_gl_confirm(button_text: 'Revoke application')
expect(page).to have_content('The application was revoked access.')
- expect(page).to have_content('Authorized applications (0)')
+ page.within('.oauth-authorized-applications .gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
end
it 'deletes an anonymous authorized application' do
@@ -93,14 +103,18 @@ RSpec.describe 'Profile > Applications', feature_category: :user_profile do
visit oauth_applications_path
page.within('.oauth-authorized-applications') do
- expect(page).to have_content('Authorized applications (1)')
+ page.within('.oauth-authorized-applications .gl-new-card-count') do
+ expect(page).to have_content('1')
+ end
click_button 'Revoke'
end
accept_gl_confirm(button_text: 'Revoke application')
expect(page).to have_content('The application was revoked access.')
- expect(page).to have_content('Authorized applications (0)')
+ page.within('.oauth-authorized-applications .gl-new-card-count') do
+ expect(page).to have_content('0')
+ end
end
end
end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 65fe1330be2..094855393be 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -18,6 +18,8 @@ RSpec.describe 'Profile > Personal Access Tokens', :js, feature_category: :user_
name = 'My PAT'
visit profile_personal_access_tokens_path
+
+ click_button 'Add new token'
fill_in "Token name", with: name
# Set date to 1st of next month
@@ -43,6 +45,8 @@ RSpec.describe 'Profile > Personal Access Tokens', :js, feature_category: :user_
it "displays an error message" do
number_tokens_before = PersonalAccessToken.count
visit profile_personal_access_tokens_path
+
+ click_button 'Add new token'
fill_in "Token name", with: 'My PAT'
click_on "Create personal access token"
@@ -145,6 +149,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js, feature_category: :user_
visit profile_personal_access_tokens_path({ name: name, scopes: scopes })
+ click_button 'Add new token'
expect(page).to have_field("Token name", with: name)
expect(find("#personal_access_token_scopes_api")).to be_checked
expect(find("#personal_access_token_scopes_read_user")).to be_checked
diff --git a/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb b/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb
index 89887cb4772..bdaf6262566 100644
--- a/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb
+++ b/spec/features/profiles/user_changes_notified_of_own_activity_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Profile > Notifications > User changes notified_of_own_activity setting', :js,
-feature_category: :user_profile do
+ feature_category: :user_profile do
let(:user) { create(:user) }
before do
diff --git a/spec/features/profiles/user_creates_comment_template_spec.rb b/spec/features/profiles/user_creates_comment_template_spec.rb
index 44e2b932c00..dcaf47088b0 100644
--- a/spec/features/profiles/user_creates_comment_template_spec.rb
+++ b/spec/features/profiles/user_creates_comment_template_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe 'Profile > Comment templates > User creates comment template', :j
end
it 'shows the user a list of their saved replies' do
+ click_button 'Add new'
find('[data-testid="comment-template-name-input"]').set('test')
find('[data-testid="comment-template-content-input"]').set('Test content')
@@ -22,7 +23,7 @@ RSpec.describe 'Profile > Comment templates > User creates comment template', :j
wait_for_requests
- expect(page).to have_content('My comment templates (1)')
+ expect(page).to have_content('My comment templates')
expect(page).to have_content('test')
expect(page).to have_content('Test content')
end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index de8719630ee..a756c524cbb 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -83,7 +83,7 @@ RSpec.describe 'User edit profile', feature_category: :user_profile do
page.within('.rspec-full-name') do
expect(page).to have_css '.gl-field-error-outline'
expect(find('.gl-field-error')).not_to have_selector('.hidden')
- expect(find('.gl-field-error')).to have_content('Using emojis in names seems fun, but please try to set a status message instead')
+ expect(find('.gl-field-error')).to have_content('Using emoji in names seems fun, but please try to set a status message instead')
end
end
diff --git a/spec/features/profiles/user_manages_emails_spec.rb b/spec/features/profiles/user_manages_emails_spec.rb
index b875dfec217..35f2ccf0f34 100644
--- a/spec/features/profiles/user_manages_emails_spec.rb
+++ b/spec/features/profiles/user_manages_emails_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'User manages emails', feature_category: :user_profile do
it 'adds an email', :aggregate_failures do
fill_in('email_email', with: 'my@email.com')
- click_button('Add')
+ click_button('Add email address')
email = user.emails.find_by(email: 'my@email.com')
@@ -37,7 +37,7 @@ RSpec.describe 'User manages emails', feature_category: :user_profile do
it 'does not add an email that is the primary email of another user', :aggregate_failures do
fill_in('email_email', with: other_user.email)
- click_button('Add')
+ click_button('Add email address')
email = user.emails.find_by(email: other_user.email)
@@ -51,7 +51,7 @@ RSpec.describe 'User manages emails', feature_category: :user_profile do
it 'removes an email', :aggregate_failures do
fill_in('email_email', with: 'my@email.com')
- click_button('Add')
+ click_button('Add email address')
email = user.emails.find_by(email: 'my@email.com')
diff --git a/spec/features/profiles/user_visits_notifications_tab_spec.rb b/spec/features/profiles/user_visits_notifications_tab_spec.rb
index 1295a0b6150..7d858e3c92c 100644
--- a/spec/features/profiles/user_visits_notifications_tab_spec.rb
+++ b/spec/features/profiles/user_visits_notifications_tab_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'User visits the notifications tab', :js, feature_category: :user
end
context 'when project emails are disabled' do
- let(:project) { create(:project, emails_disabled: true) }
+ let_it_be(:project) { create(:project, emails_enabled: false) }
it 'notification button is disabled' do
expect(page).to have_selector('[data-testid="notification-dropdown"] .disabled')
diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb
index c4f78bf4ea3..e2fa924af67 100644
--- a/spec/features/project_variables_spec.rb
+++ b/spec/features/project_variables_spec.rb
@@ -12,6 +12,8 @@ RSpec.describe 'Project variables', :js, feature_category: :secrets_management d
sign_in(user)
project.add_maintainer(user)
project.variables << variable
+
+ stub_feature_flags(ci_variable_drawer: false)
visit page_path
wait_for_requests
end
@@ -49,4 +51,14 @@ RSpec.describe 'Project variables', :js, feature_category: :secrets_management d
expect(find('.js-ci-variable-row:first-child [data-label="Environments"]').text).to eq('review/*')
end
end
+
+ context 'when ci_variable_drawer FF is enabled' do
+ before do
+ stub_feature_flags(ci_variable_drawer: true)
+ visit page_path
+ wait_for_requests
+ end
+
+ it_behaves_like 'variable list drawer'
+ end
end
diff --git a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
index 1990526b5fc..cd7601aa94e 100644
--- a/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
+++ b/spec/features/projects/blobs/user_follows_pipeline_suggest_nudge_spec.rb
@@ -25,8 +25,6 @@ RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled
end
it 'displays suggest_gitlab_ci_yml popover' do
- page.find(:css, '.gitlab-ci-yml-selector').click
-
popover_selector = '.suggest-gitlab-ci-yml'
expect(page).to have_css(popover_selector, visible: true)
diff --git a/spec/features/projects/ci/editor_spec.rb b/spec/features/projects/ci/editor_spec.rb
index 43da57c16d1..b09aa91f4ab 100644
--- a/spec/features/projects/ci/editor_spec.rb
+++ b/spec/features/projects/ci/editor_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe 'Pipeline Editor', :js, feature_category: :pipeline_composition d
let(:default_branch) { 'main' }
let(:other_branch) { 'test' }
let(:branch_with_invalid_ci) { 'despair' }
+ let(:branch_without_ci) { 'empty' }
let(:default_content) { 'Default' }
@@ -45,6 +46,7 @@ RSpec.describe 'Pipeline Editor', :js, feature_category: :pipeline_composition d
project.repository.create_file(user, project.ci_config_path_or_default, default_content, message: 'Create CI file for main', branch_name: default_branch)
project.repository.create_file(user, project.ci_config_path_or_default, valid_content, message: 'Create CI file for test', branch_name: other_branch)
project.repository.create_file(user, project.ci_config_path_or_default, invalid_content, message: 'Create CI file for test', branch_name: branch_with_invalid_ci)
+ project.repository.create_file(user, 'index.js', "file", message: 'New js file', branch_name: branch_without_ci)
visit project_ci_pipeline_editor_path(project)
wait_for_requests
@@ -62,6 +64,31 @@ RSpec.describe 'Pipeline Editor', :js, feature_category: :pipeline_composition d
end
end
+ describe 'when there are no CI config file' do
+ before do
+ visit project_ci_pipeline_editor_path(project, branch_name: branch_without_ci)
+ end
+
+ it 'renders the empty page', :aggregate_failures do
+ expect(page).to have_content 'Optimize your workflow with CI/CD Pipelines'
+ expect(page).to have_selector '[data-testid="create_new_ci_button"]'
+ end
+
+ context 'when clicking on the create new CI button' do
+ before do
+ click_button 'Configure pipeline'
+ end
+
+ it 'renders the source editor with default content', :aggregate_failures do
+ expect(page).to have_selector('#source-editor-')
+
+ page.within('#source-editor-') do
+ expect(page).to have_content('This file is a template, and might need editing before it works on your project.')
+ end
+ end
+ end
+ end
+
describe 'When CI yml has valid syntax' do
before do
visit project_ci_pipeline_editor_path(project, branch_name: other_branch)
@@ -149,15 +176,6 @@ RSpec.describe 'Pipeline Editor', :js, feature_category: :pipeline_composition d
end
shared_examples 'default branch switcher behavior' do
- def switch_to_branch(branch)
- find('[data-testid="branch-selector"]').click
-
- page.within '[data-testid="branch-selector"]' do
- click_button branch
- wait_for_requests
- end
- end
-
it 'displays current branch' do
page.within('[data-testid="branch-selector"]') do
expect(page).to have_content(default_branch)
@@ -195,12 +213,20 @@ RSpec.describe 'Pipeline Editor', :js, feature_category: :pipeline_composition d
end
describe 'Branch Switcher' do
+ def switch_to_branch(branch)
+ # close button for the popover
+ find('[data-testid="close-button"]').click
+ find('[data-testid="branch-selector"]').click
+
+ page.within '[data-testid="branch-selector"]' do
+ click_button branch
+ wait_for_requests
+ end
+ end
+
before do
visit project_ci_pipeline_editor_path(project)
wait_for_requests
-
- # close button for the popover
- find('[data-testid="close-button"]').click
end
it_behaves_like 'default branch switcher behavior'
@@ -262,6 +288,24 @@ RSpec.describe 'Pipeline Editor', :js, feature_category: :pipeline_composition d
end
describe 'Commit Form' do
+ context 'when targetting the main branch' do
+ it 'does not show the option to create a Merge request', :aggregate_failures do
+ expect(page).not_to have_selector('[data-testid="new-mr-checkbox"]')
+ expect(page).not_to have_content('Start a new merge request with these changes')
+ end
+ end
+
+ context 'when targetting any non-main branch' do
+ before do
+ find('#source-branch-field').set('new_branch', clear: :backspace)
+ end
+
+ it 'shows the option to create a Merge request', :aggregate_failures do
+ expect(page).to have_selector('[data-testid="new-mr-checkbox"]')
+ expect(page).to have_content('Start a new merge request with these changes')
+ end
+ end
+
it 'is preserved when changing tabs' do
find('#commit-message').set('message', clear: :backspace)
find('#source-branch-field').set('new_branch', clear: :backspace)
diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
index d2104799e79..5bb3d1af924 100644
--- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb
+++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Mini Pipeline Graph in Commit View', :js, feature_category: :source_code_management do
let(:project) { create(:project, :public, :repository) }
- context 'when commit has pipelines' do
+ context 'when commit has pipelines and feature flag is enabled' do
let(:pipeline) do
create(
:ci_pipeline,
@@ -24,6 +24,33 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js, feature_category: :sou
wait_for_requests
end
+ it 'displays the graphql pipeline stage' do
+ expect(page).to have_selector('[data-testid="pipeline-stage"]')
+
+ build.drop
+ end
+ end
+
+ context 'when commit has pipelines and feature flag is disabled' do
+ let(:pipeline) do
+ create(
+ :ci_pipeline,
+ status: :running,
+ project: project,
+ ref: project.default_branch,
+ sha: project.commit.sha
+ )
+ end
+
+ let(:build) { create(:ci_build, pipeline: pipeline, status: :running) }
+
+ before do
+ stub_feature_flags(ci_graphql_pipeline_mini_graph: false)
+ build.run
+ visit project_commit_path(project, project.commit.id)
+ wait_for_requests
+ end
+
it 'display icon with status' do
expect(page).to have_selector('.ci-status-icon-running')
end
diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb
index 493435d3439..0a77c671fce 100644
--- a/spec/features/projects/container_registry_spec.rb
+++ b/spec/features/projects/container_registry_spec.rb
@@ -67,6 +67,7 @@ RSpec.describe 'Container Registry', :js, feature_category: :groups_and_projects
it 'list page has a list of images' do
visit_container_registry
+ expect(page).to have_content '1 Image repository'
expect(page).to have_content 'my/image'
end
@@ -189,8 +190,7 @@ RSpec.describe 'Container Registry', :js, feature_category: :groups_and_projects
it 'pagination is preserved after navigating back from details' do
visit_next_page
click_link 'my/image'
- breadcrumb = find '.breadcrumbs'
- breadcrumb.click_link 'Container Registry'
+ page.go_back
expect(page).to have_content 'my/image'
end
end
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
index a74cde35be6..55b15ad95d1 100644
--- a/spec/features/projects/files/dockerfile_dropdown_spec.rb
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -12,20 +12,16 @@ RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js, fe
end
it 'user can pick a Dockerfile file from the dropdown' do
- expect(page).to have_css('.dockerfile-selector')
+ click_button 'Apply a template'
- find('.js-dockerfile-selector').click
-
- wait_for_requests
-
- within '.dockerfile-selector' do
- find('.dropdown-input-field').set('HTTPd')
- find('.dropdown-content li', text: 'HTTPd').click
+ within '.gl-new-dropdown-panel' do
+ find('.gl-listbox-search-input').set('HTTPd')
+ find('.gl-new-dropdown-contents li', text: 'HTTPd').click
end
wait_for_requests
- expect(page).to have_css('.dockerfile-selector .dropdown-toggle-text', text: 'Apply a template')
+ expect(page).to have_css('.gl-new-dropdown-button-text', text: 'HTTPd')
expect(find('.monaco-editor')).to have_content('COPY ./ /usr/local/apache2/htdocs/')
end
end
diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb
index 36b02b9b948..b1f7f1c5716 100644
--- a/spec/features/projects/files/gitignore_dropdown_spec.rb
+++ b/spec/features/projects/files/gitignore_dropdown_spec.rb
@@ -12,20 +12,16 @@ RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js, fe
end
it 'user can pick a .gitignore file from the dropdown' do
- expect(page).to have_css('.gitignore-selector')
+ click_button 'Apply a template'
- find('.js-gitignore-selector').click
-
- wait_for_requests
-
- within '.gitignore-selector' do
- find('.dropdown-input-field').set('rails')
- find('.dropdown-content li', text: 'Rails').click
+ within '.gl-new-dropdown-panel' do
+ find('.gl-listbox-search-input').set('rails')
+ find('.gl-new-dropdown-contents li', text: 'Rails').click
end
wait_for_requests
- expect(page).to have_css('.gitignore-selector .dropdown-toggle-text', text: 'Apply a template')
+ expect(page).to have_css('.gl-new-dropdown-button-text', text: 'Rails')
expect(find('.monaco-editor')).to have_content('/.bundle')
expect(find('.monaco-editor')).to have_content('config/initializers/secret_token.rb')
end
diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
index 929554ff0d6..7bfff6b68e8 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -16,20 +16,16 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
end
it 'user can pick a template from the dropdown' do
- expect(page).to have_css('.gitlab-ci-yml-selector')
+ click_button 'Apply a template'
- find('.js-gitlab-ci-yml-selector').click
-
- wait_for_requests
-
- within '.gitlab-ci-yml-selector' do
- find('.dropdown-input-field').set('Jekyll')
- find('.dropdown-content li', text: 'Jekyll').click
+ within '.gl-new-dropdown-panel' do
+ find('.gl-listbox-search-input').set('Jekyll')
+ find('.gl-new-dropdown-contents li', text: 'Jekyll').click
end
wait_for_requests
- expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
+ expect(page).to have_css('.gl-new-dropdown-button-text', text: 'Jekyll')
expect(find('.monaco-editor')).to have_content('This file is a template, and might need editing before it works on your project')
expect(find('.monaco-editor')).to have_content('jekyll build -d test')
end
@@ -40,7 +36,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
it 'uses the given template' do
wait_for_requests
- expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
+ expect(page).to have_css('.gl-new-dropdown-button-text', text: 'Jekyll')
expect(find('.monaco-editor')).to have_content('This file is a template, and might need editing before it works on your project')
expect(find('.monaco-editor')).to have_content('jekyll build -d test')
end
@@ -52,7 +48,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
it 'leaves the editor empty' do
wait_for_requests
- expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
+ expect(page).to have_css('.gl-new-dropdown-button-text', text: 'Apply a template')
expect(find('.monaco-editor')).to have_content('')
end
end
diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
index 8ec9adaeb9a..95e96159744 100644
--- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb
+++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
@@ -20,8 +20,6 @@ RSpec.describe 'Projects > Files > Project owner creates a license file', :js, f
fill_in :file_name, with: 'LICENSE'
- expect(page).to have_selector('.license-selector')
-
select_template('MIT License')
file_content = first('.file-editor')
@@ -44,7 +42,6 @@ RSpec.describe 'Projects > Files > Project owner creates a license file', :js, f
expect(page).to have_current_path(
project_new_blob_path(project, 'master'), ignore_query: true)
expect(find('#file_name').value).to eq('LICENSE')
- expect(page).to have_selector('.license-selector')
select_template('MIT License')
@@ -62,9 +59,9 @@ RSpec.describe 'Projects > Files > Project owner creates a license file', :js, f
end
def select_template(template)
- page.within('.js-license-selector-wrap') do
+ page.within('.gl-new-dropdown') do
click_button 'Apply a template'
- click_link template
+ find('.gl-new-dropdown-contents li', text: template).click
wait_for_requests
end
end
diff --git a/spec/features/projects/files/template_selector_menu_spec.rb b/spec/features/projects/files/template_selector_menu_spec.rb
index 46c4b69bc89..920da6e72ce 100644
--- a/spec/features/projects/files/template_selector_menu_spec.rb
+++ b/spec/features/projects/files/template_selector_menu_spec.rb
@@ -58,7 +58,7 @@ end
def check_template_selector_menu_display(is_visible)
count = is_visible ? 1 : 0
- expect(page).to have_css('.template-selectors-menu', count: count)
+ expect(page).to have_css('[data-testid="template-selector"]', count: count)
end
def create_and_edit_file(file_name)
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index 4b6e6b7282c..d6f9acc68a0 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Projects > Files > Template Undo Button', :js, feature_category:
context 'editing a matching file and applying a template' do
before do
visit project_edit_blob_path(project, File.join(project.default_branch, "LICENSE"))
- select_file_template('.js-license-selector', 'Apache License 2.0')
+ select_file_template('Apache License 2.0')
end
it 'reverts template application' do
@@ -42,8 +42,8 @@ def check_content_reverted(template_content)
expect(page).not_to have_content(template_content)
end
-def select_file_template(template_selector_selector, template_name)
- find(template_selector_selector).click
- find('.dropdown-content li', text: template_name).click
+def select_file_template(template_name)
+ click_button 'Apply a template'
+ find('.gl-new-dropdown-contents li', text: template_name).click
wait_for_requests
end
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index 3b30a620257..e93c9427c91 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe "User browses files", :js, feature_category: :groups_and_projects
click_link("d")
end
- expect(page).to have_link("..", href: project_tree_path(project, "markdown/"))
+ expect(page).to have_link("..", href: project_tree_path(project, "markdown"))
page.within(".tree-table") do
click_link("README.md")
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index 7d734d5d2df..c159b40003c 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -14,23 +14,80 @@ RSpec.describe 'Project fork', feature_category: :groups_and_projects do
end
shared_examples 'fork button on project page' do
- it 'allows user to fork project from the project page' do
- visit project_path(project)
+ context 'when the user has access to only one namespace and has already forked the project', :js do
+ before do
+ fork_project(project, user, repository: true, namespace: user.namespace)
+ end
- expect(page).not_to have_css('a.disabled', text: 'Fork')
- end
+ it 'allows user to go to their fork' do
+ visit project_path(project)
- context 'user has exceeded personal project limit' do
- before do
- user.update!(projects_limit: 0)
+ path = namespace_project_path(user, user.fork_of(project))
+
+ fork_button = find_link 'Fork'
+ expect(fork_button['href']).to include(path)
+ expect(fork_button['class']).not_to include('disabled')
end
+ end
- it 'disables fork button on project page' do
+ shared_examples 'fork button creates new fork' do
+ it 'allows user to fork the project from the project page' do
visit project_path(project)
- expect(page).to have_css('a.disabled', text: 'Fork')
+ path = new_project_fork_path(project)
+
+ fork_button = find_link 'Fork'
+ expect(fork_button['href']).to include(path)
+ expect(fork_button['class']).not_to include('disabled')
+ end
+
+ context 'when the user cannot fork the project' do
+ let(:project) do
+ # Disabling the repository makes sure that the user cannot fork the project
+ create(:project, :public, :repository, :repository_disabled, description: 'some description')
+ end
+
+ it 'disables fork button on project page' do
+ visit project_path(project)
+
+ path = new_project_fork_path(project)
+
+ fork_button = find_link 'Fork'
+ expect(fork_button['href']).to include(path)
+ expect(fork_button['class']).to include('disabled')
+ end
+ end
+
+ context 'user has exceeded personal project limit' do
+ before do
+ user.update!(projects_limit: 0)
+ end
+
+ it 'disables fork button on project page' do
+ visit project_path(project)
+
+ path = new_project_fork_path(project)
+
+ fork_button = find_link 'Fork'
+ expect(fork_button['href']).to include(path)
+ expect(fork_button['class']).to include('disabled')
+ end
end
end
+
+ context 'when the user has not already forked the project', :js do
+ it_behaves_like 'fork button creates new fork'
+ end
+
+ context 'when the user has access to more than one namespace', :js do
+ let(:group) { create(:group) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ it_behaves_like 'fork button creates new fork'
+ end
end
shared_examples 'create fork page' do |fork_page_text|
@@ -42,11 +99,11 @@ RSpec.describe 'Project fork', feature_category: :groups_and_projects do
context 'forking is enabled' do
let(:forking_access_level) { ProjectFeature::ENABLED }
- it 'enables fork button' do
+ it 'enables fork button', :js do
visit project_path(project)
- expect(page).to have_css('a', text: 'Fork')
- expect(page).not_to have_css('a.disabled', text: 'Select')
+ fork_button = find_link 'Fork'
+ expect(fork_button['class']).not_to include('disabled')
end
it 'renders new project fork page' do
@@ -60,11 +117,13 @@ RSpec.describe 'Project fork', feature_category: :groups_and_projects do
context 'forking is disabled' do
let(:forking_access_level) { ProjectFeature::DISABLED }
- it 'render a disabled fork button' do
+ it 'render a disabled fork button', :js do
visit project_path(project)
- expect(page).to have_css('a.disabled', text: 'Fork')
- expect(page).to have_css('a.count', text: '0')
+ fork_button = find_link 'Fork'
+
+ expect(fork_button['class']).to include('disabled')
+ expect(page).to have_selector('[data-testid="forks-count"]')
end
it 'does not render new project fork page' do
@@ -82,11 +141,13 @@ RSpec.describe 'Project fork', feature_category: :groups_and_projects do
end
context 'user is not a team member' do
- it 'render a disabled fork button' do
+ it 'render a disabled fork button', :js do
visit project_path(project)
- expect(page).to have_css('a.disabled', text: 'Fork')
- expect(page).to have_css('a.count', text: '0')
+ fork_button = find_link 'Fork'
+
+ expect(fork_button['class']).to include('disabled')
+ expect(page).to have_selector('[data-testid="forks-count"]')
end
it 'does not render new project fork page' do
@@ -101,12 +162,13 @@ RSpec.describe 'Project fork', feature_category: :groups_and_projects do
project.add_developer(user)
end
- it 'enables fork button' do
+ it 'enables fork button', :js do
visit project_path(project)
- expect(page).to have_css('a', text: 'Fork')
- expect(page).to have_css('a.count', text: '0')
- expect(page).not_to have_css('a.disabled', text: 'Fork')
+ fork_button = find_link 'Fork'
+
+ expect(fork_button['class']).not_to include('disabled')
+ expect(page).to have_selector('[data-testid="forks-count"]')
end
it 'renders new project fork page' do
@@ -185,7 +247,8 @@ RSpec.describe 'Project fork', feature_category: :groups_and_projects do
visit project_path(project)
- expect(page).to have_css('.fork-count', text: 2)
+ forks_count_button = find('[data-testid="forks-count"]')
+ expect(forks_count_button).to have_content("2")
end
end
end
@@ -195,7 +258,9 @@ private
def create_fork(group_obj = group)
visit project_path(project)
- find('.fork-btn').click
+
+ click_link 'Fork'
+
submit_form(group_obj)
wait_for_requests
end
diff --git a/spec/features/projects/labels/user_edits_labels_spec.rb b/spec/features/projects/labels/user_edits_labels_spec.rb
index f90f215f9fc..bf1182cfddd 100644
--- a/spec/features/projects/labels/user_edits_labels_spec.rb
+++ b/spec/features/projects/labels/user_edits_labels_spec.rb
@@ -36,6 +36,6 @@ RSpec.describe "User edits labels", feature_category: :team_planning do
click_link 'Delete label'
end
- expect(page).to have_content('Label was removed')
+ expect(page).to have_content("#{label.title} was removed").and have_no_content("#{label.title}</span>")
end
end
diff --git a/spec/features/projects/labels/user_removes_labels_spec.rb b/spec/features/projects/labels/user_removes_labels_spec.rb
index 55dc52b8ccf..d0175c53951 100644
--- a/spec/features/projects/labels/user_removes_labels_spec.rb
+++ b/spec/features/projects/labels/user_removes_labels_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe "User removes labels", feature_category: :team_planning do
first(:link, "Delete label").click
- expect(page).to have_content("Label was removed").and have_no_content(label.title)
+ expect(page).to have_content("#{label.title} was removed").and have_no_content("#{label.title}</span>")
end
end
diff --git a/spec/features/projects/members/import_project_members_spec.rb b/spec/features/projects/members/import_project_members_spec.rb
new file mode 100644
index 00000000000..20cf42cd135
--- /dev/null
+++ b/spec/features/projects/members/import_project_members_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Projects > Members > Import project members', :js, feature_category: :groups_and_projects do
+ include Features::MembersHelpers
+ include ListboxHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user_mike) { create(:user, name: 'Mike') }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) do
+ create(:project, group: group).tap do |p|
+ p.add_maintainer(user)
+ p.add_developer(create(:user))
+ end
+ end
+
+ let_it_be(:project2) do
+ create(:project).tap do |p|
+ p.add_maintainer(user)
+ p.add_reporter(user_mike)
+ end
+ end
+
+ before do
+ sign_in(user)
+
+ visit(project_project_members_path(project))
+ end
+
+ it 'imports a team from another project' do
+ select_project(project2)
+ submit_import
+
+ expect(find_member_row(user_mike)).to have_content('Reporter')
+ end
+
+ it 'fails to import the other team when source project does not exist' do
+ select_project(project2)
+ submit_import { project2.destroy! }
+
+ within import_project_members_modal_selector do
+ expect(page).to have_content('Unable to import project members')
+ end
+ end
+
+ it 'fails to import some members' do
+ group.add_owner(user_mike)
+
+ select_project(project2)
+ submit_import
+
+ within import_project_members_modal_selector do
+ expect(page).to have_content "The following 1 out of 2 members could not be added"
+ expect(page).to have_content "@#{user_mike.username}: Access level should be greater than or equal to " \
+ "Owner inherited membership from group #{group.name}"
+ end
+ end
+
+ def select_project(source_project)
+ click_on 'Import from a project'
+ click_on 'Select a project'
+ wait_for_requests
+
+ select_listbox_item(source_project.name_with_namespace)
+ end
+
+ def submit_import
+ yield if block_given? # rubocop:disable RSpec/AvoidConditionalStatements
+
+ click_button 'Import project members'
+ wait_for_requests
+ end
+
+ def import_project_members_modal_selector
+ '[data-testid="import-project-members-modal"]'
+ end
+end
diff --git a/spec/features/projects/settings/user_manages_project_members_spec.rb b/spec/features/projects/members/user_manages_project_members_spec.rb
index df571e13979..b1c3132767c 100644
--- a/spec/features/projects/settings/user_manages_project_members_spec.rb
+++ b/spec/features/projects/members/user_manages_project_members_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Projects > Settings > User manages project members', feature_category: :groups_and_projects do
+RSpec.describe 'Projects > Settings > User manages project members', :js, feature_category: :groups_and_projects do
include Features::MembersHelpers
include Spec::Support::Helpers::ModalHelpers
include ListboxHelpers
@@ -20,7 +20,7 @@ RSpec.describe 'Projects > Settings > User manages project members', feature_cat
sign_in(user)
end
- it 'cancels a team member', :js do
+ it 'cancels a team member' do
visit(project_project_members_path(project))
show_actions_for_username(user_dmitriy)
@@ -37,24 +37,7 @@ RSpec.describe 'Projects > Settings > User manages project members', feature_cat
expect(members_table).not_to have_content(user_dmitriy.username)
end
- it 'imports a team from another project', :js do
- project2.add_maintainer(user)
- project2.add_reporter(user_mike)
-
- visit(project_project_members_path(project))
-
- click_on 'Import from a project'
- click_on 'Select a project'
- wait_for_requests
-
- select_listbox_item(project2.name_with_namespace)
- click_button 'Import project members'
- wait_for_requests
-
- expect(find_member_row(user_mike)).to have_content('Reporter')
- end
-
- it 'shows all members of project shared group', :js do
+ it 'shows all members of project shared group' do
group.add_owner(user)
group.add_developer(user_dmitriy)
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index d05b7649f94..6e6d9ff4af9 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -46,7 +46,8 @@ RSpec.describe 'New project', :js, feature_category: :groups_and_projects do
end
it 'shows a message if multiple levels are restricted' do
- Gitlab::CurrentSettings.update!(
+ stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::PUBLIC)
+ stub_application_setting(
restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL]
)
@@ -56,15 +57,21 @@ RSpec.describe 'New project', :js, feature_category: :groups_and_projects do
expect(page).to have_content 'Other visibility settings have been disabled by the administrator.'
end
- it 'shows a message if all levels are restricted' do
- Gitlab::CurrentSettings.update!(
- restricted_visibility_levels: Gitlab::VisibilityLevel.values
- )
+ context 'with prevent_visibility_restriction feature flag off' do
+ before do
+ stub_feature_flags(prevent_visibility_restriction: false)
+ end
- visit new_project_path
- click_link 'Create blank project'
+ it 'shows a message if all levels are restricted' do
+ Gitlab::CurrentSettings.update!(
+ restricted_visibility_levels: Gitlab::VisibilityLevel.values
+ )
- expect(page).to have_content 'Visibility settings have been disabled by the administrator.'
+ visit new_project_path
+ click_link 'Create blank project'
+
+ expect(page).to have_content 'Visibility settings have been disabled by the administrator.'
+ end
end
end
diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb
index ae459197b38..14b01cb63d2 100644
--- a/spec/features/projects/pages/user_adds_domain_spec.rb
+++ b/spec/features/projects/pages/user_adds_domain_spec.rb
@@ -178,7 +178,12 @@ RSpec.describe 'User adds pages domain', :js, feature_category: :pages do
visit project_pages_path(project)
within('#content-body') { click_link 'Edit' }
- expect(page).to have_field :domain_dns, with: "#{domain.domain} ALIAS namespace1.example.com."
+ expect(page).to have_field :domain_dns, with: format(
+ "%{domain} ALIAS %{namespace}.%{pages_host}.",
+ domain: domain.domain,
+ namespace: domain.project.root_namespace.path,
+ pages_host: Settings.pages.host
+ )
end
end
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 25eddf64f99..26fcd8ca3ca 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -559,7 +559,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
find(dropdown_selector).click
within('.js-builds-dropdown-list') do
- build_element = page.find('.mini-pipeline-graph-dropdown-item')
+ build_element = page.find('.pipeline-job-item')
expect(build_element['title']).to eq('build - failed - (unknown failure)')
end
end
@@ -818,7 +818,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
describe 'when the `ios_specific_templates` experiment is enabled and the "Set up a runner" button is clicked' do
before do
stub_experiments(ios_specific_templates: :candidate)
- create(:project_setting, project: project, target_platforms: %w(ios))
+ project.project_setting.update!(target_platforms: %w(ios))
visit project_pipelines_path(project)
click_button 'Set up a runner'
end
diff --git a/spec/features/projects/settings/access_tokens_spec.rb b/spec/features/projects/settings/access_tokens_spec.rb
index 210815f341c..9025bd9052e 100644
--- a/spec/features/projects/settings/access_tokens_spec.rb
+++ b/spec/features/projects/settings/access_tokens_spec.rb
@@ -49,6 +49,7 @@ RSpec.describe 'Project > Settings > Access Tokens', :js, feature_category: :use
it 'shows Owner option' do
visit resource_settings_access_tokens_path
+ click_button 'Add new token'
expect(role_dropdown_options).to include('Owner')
end
end
@@ -63,6 +64,7 @@ RSpec.describe 'Project > Settings > Access Tokens', :js, feature_category: :use
it 'does not show Owner option for a maintainer' do
visit resource_settings_access_tokens_path
+ click_button 'Add new token'
expect(role_dropdown_options).not_to include('Owner')
end
end
@@ -81,6 +83,7 @@ RSpec.describe 'Project > Settings > Access Tokens', :js, feature_category: :use
it 'shows access token creation form and text' do
visit project_settings_access_tokens_path(personal_project)
+ click_button 'Add new token'
expect(page).to have_selector('#js-new-access-token-form')
end
end
diff --git a/spec/features/projects/settings/packages_settings_spec.rb b/spec/features/projects/settings/packages_settings_spec.rb
index 564a71e9a23..5277ede8e52 100644
--- a/spec/features/projects/settings/packages_settings_spec.rb
+++ b/spec/features/projects/settings/packages_settings_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'Projects > Settings > Packages', :js, feature_category: :groups_
let(:packages_enabled) { false }
it 'does not show up in UI' do
- expect(page).not_to have_selector('[data-testid="toggle-label"]', text: 'Packages')
+ expect(page).not_to have_selector('[data-testid="toggle-label"]', text: 'Package registry')
end
end
end
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index ef1c03f4f27..59d9e6d105e 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -65,6 +65,46 @@ RSpec.describe "Projects > Settings > Pipelines settings", feature_category: :gr
expect(checkbox).not_to be_checked
end
+ it 'disables forward deployment rollback allowed when forward deployment enabled is unchecked', :js do
+ visit project_settings_ci_cd_path(project)
+
+ forward_deployment_checkbox = find_field('project_ci_cd_settings_attributes_forward_deployment_enabled')
+ forward_deployment_rollback_checkbox =
+ find_field('project_ci_cd_settings_attributes_forward_deployment_rollback_allowed')
+ expect(forward_deployment_checkbox).to be_checked
+ expect(forward_deployment_rollback_checkbox).not_to be_disabled
+
+ forward_deployment_checkbox.click
+
+ expect(forward_deployment_rollback_checkbox).to be_disabled
+
+ forward_deployment_checkbox.click
+
+ expect(forward_deployment_rollback_checkbox).not_to be_disabled
+ end
+
+ it 'updates forward_deployment_rollback_allowed' do
+ visit project_settings_ci_cd_path(project)
+
+ checkbox = find_field('project_ci_cd_settings_attributes_forward_deployment_rollback_allowed')
+ expect(checkbox).to be_checked
+
+ checkbox.set(false)
+
+ page.within '#js-general-pipeline-settings' do
+ click_on 'Save changes'
+ end
+
+ expect(page.status_code).to eq(200)
+
+ page.within '#js-general-pipeline-settings' do
+ expect(page).to have_button('Save changes', disabled: false)
+ end
+
+ checkbox = find_field('project_ci_cd_settings_attributes_forward_deployment_rollback_allowed')
+ expect(checkbox).not_to be_checked
+ end
+
describe 'Auto DevOps' do
context 'when auto devops is turned on instance-wide' do
before do
diff --git a/spec/features/projects/settings/project_badges_spec.rb b/spec/features/projects/settings/project_badges_spec.rb
index 1f170300155..a66bf5cd3a9 100644
--- a/spec/features/projects/settings/project_badges_spec.rb
+++ b/spec/features/projects/settings/project_badges_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Project Badges', feature_category: :groups_and_projects do
page.within '.badge-settings' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
expect(rows[0]).to have_content group_badge.link_url
expect(rows[1]).to have_content project_badge.link_url
@@ -33,6 +33,7 @@ RSpec.describe 'Project Badges', feature_category: :groups_and_projects do
context 'adding a badge', :js do
it 'user can preview a badge' do
+ click_button 'Add badge'
page.within '.badge-settings form' do
fill_in 'badge-link-url', with: badge_link_url
fill_in 'badge-image-url', with: badge_image_url
@@ -44,6 +45,7 @@ RSpec.describe 'Project Badges', feature_category: :groups_and_projects do
end
it do
+ click_button 'Add badge'
page.within '.badge-settings' do
fill_in 'badge-link-url', with: badge_link_url
fill_in 'badge-image-url', with: badge_image_url
@@ -51,7 +53,7 @@ RSpec.describe 'Project Badges', feature_category: :groups_and_projects do
click_button 'Add badge'
wait_for_requests
- within '.card-body' do
+ within '.gl-card-body' do
expect(find('a')[:href]).to eq badge_link_url
expect(find('a img')[:src]).to eq badge_image_url
end
@@ -63,32 +65,35 @@ RSpec.describe 'Project Badges', feature_category: :groups_and_projects do
it 'form is shown when clicking edit button in list' do
page.within '.badge-settings' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
rows[1].find('[aria-label="Edit"]').click
+ end
- within 'form' do
- expect(find('#badge-link-url').value).to eq project_badge.link_url
- expect(find('#badge-image-url').value).to eq project_badge.image_url
- end
+ page.within '.gl-modal' do
+ expect(find('#badge-link-url').value).to eq project_badge.link_url
+ expect(find('#badge-image-url').value).to eq project_badge.image_url
end
end
it 'updates a badge when submitting the edit form' do
page.within '.badge-settings' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
rows[1].find('[aria-label="Edit"]').click
- within 'form' do
- fill_in 'badge-link-url', with: badge_link_url
- fill_in 'badge-image-url', with: badge_image_url
+ end
- click_button 'Save changes'
- wait_for_requests
- end
+ page.within '.gl-modal' do
+ fill_in 'badge-link-url', with: badge_link_url
+ fill_in 'badge-image-url', with: badge_image_url
- rows = all('.card-body > div')
+ click_button 'Save changes'
+ wait_for_requests
+ end
+
+ page.within '.badge-settings' do
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
expect(rows[1]).to have_content badge_link_url
end
@@ -102,7 +107,7 @@ RSpec.describe 'Project Badges', feature_category: :groups_and_projects do
it 'shows a modal when deleting a badge' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
click_delete_button(rows[1])
@@ -112,14 +117,14 @@ RSpec.describe 'Project Badges', feature_category: :groups_and_projects do
it 'deletes a badge when confirming the modal' do
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 2
click_delete_button(rows[1])
find('.modal .btn-danger').click
wait_for_requests
- rows = all('.card-body > div')
+ rows = all('.gl-card-body tbody tr')
expect(rows.length).to eq 1
expect(rows[0]).to have_content group_badge.link_url
end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index d53aefe5a4e..838ac67ee3d 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -156,6 +156,7 @@ RSpec.describe 'Projects > Settings > Repository settings', feature_category: :g
before do
visit project_settings_repository_path(project)
+ click_button 'Add new'
end
it 'shows push mirror settings', :js do
diff --git a/spec/features/projects/settings/secure_files_spec.rb b/spec/features/projects/settings/secure_files_spec.rb
index 7ff1a5f3568..5f94e215a5f 100644
--- a/spec/features/projects/settings/secure_files_spec.rb
+++ b/spec/features/projects/settings/secure_files_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe 'Secure Files', :js, feature_category: :groups_and_projects do
within '#js-secure-files' do
expect(page).to have_content(file.name)
- find('button.btn-danger-secondary').click
+ find('[data-testid="delete-button"]').click
end
expect(page).to have_content("Delete #{file.name}?")
diff --git a/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
index 0006762a971..4e8f42ae792 100644
--- a/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
+++ b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
@@ -91,6 +91,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :groups
deploy_key_title = attributes_for(:key)[:title]
deploy_key_body = attributes_for(:key)[:key]
+ click_button("Add new key")
fill_in("deploy_key_title", with: deploy_key_title)
fill_in("deploy_key_key", with: deploy_key_body)
@@ -102,6 +103,16 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :groups
expect(page).to have_content(deploy_key_title)
end
end
+
+ it "click on cancel hides the form" do
+ click_button("Add new key")
+
+ expect(page).to have_css('.gl-new-card-add-form')
+
+ click_button("Cancel")
+
+ expect(page).not_to have_css('.gl-new-card-add-form')
+ end
end
context "attaching existing keys" do
diff --git a/spec/features/projects/settings/user_renames_a_project_spec.rb b/spec/features/projects/settings/user_renames_a_project_spec.rb
index 5a58c049601..b7ae595a3a9 100644
--- a/spec/features/projects/settings/user_renames_a_project_spec.rb
+++ b/spec/features/projects/settings/user_renames_a_project_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe 'Projects > Settings > User renames a project', feature_category:
it 'shows error for invalid project name' do
change_name(project, '🧮 foo bar ☁️')
expect(page).to have_field 'Project name', with: '🧮 foo bar ☁️'
- expect(page).not_to have_content "Name can contain only letters, digits, emojis '_', '.', dash and space. It must start with letter, digit, emoji or '_'."
+ expect(page).not_to have_content "Name can contain only letters, digits, emoji '_', '.', dash and space. It must start with letter, digit, emoji or '_'."
end
end
end
diff --git a/spec/features/projects/settings/user_searches_in_settings_spec.rb b/spec/features/projects/settings/user_searches_in_settings_spec.rb
index 978b678c334..1ca4b761788 100644
--- a/spec/features/projects/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/projects/settings/user_searches_in_settings_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe 'User searches project settings', :js, feature_category: :groups_
visit project_settings_access_tokens_path(project)
end
- it_behaves_like 'can highlight results', 'Expiration date'
+ it_behaves_like 'can highlight results', 'Token name'
end
context 'in Repository page' do
diff --git a/spec/features/projects/settings/visibility_settings_spec.rb b/spec/features/projects/settings/visibility_settings_spec.rb
index 7d41b60199c..890f514d3da 100644
--- a/spec/features/projects/settings/visibility_settings_spec.rb
+++ b/spec/features/projects/settings/visibility_settings_spec.rb
@@ -30,11 +30,11 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js, feature_categor
context 'disable email notifications' do
it 'is visible' do
- expect(page).to have_selector('.js-emails-disabled', visible: true)
+ expect(page).to have_selector('.js-emails-enabled', visible: true)
end
it 'accepts the changed state' do
- find('.js-emails-disabled input[type="checkbox"]').click
+ find('.js-emails-enabled input[type="checkbox"]').click
expect { save_permissions_group }.to change { updated_emails_disabled? }.to(true)
end
@@ -59,7 +59,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js, feature_categor
context 'disable email notifications' do
it 'is not available' do
- expect(page).not_to have_selector('.js-emails-disabled', visible: true)
+ expect(page).not_to have_selector('.js-emails-enabled', visible: true)
end
end
end
diff --git a/spec/features/projects/show/user_manages_notifications_spec.rb b/spec/features/projects/show/user_manages_notifications_spec.rb
index 455b931e7f3..bbf31c1e1e1 100644
--- a/spec/features/projects/show/user_manages_notifications_spec.rb
+++ b/spec/features/projects/show/user_manages_notifications_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe 'Projects > Show > User manages notifications', :js, feature_cate
end
context 'when project emails are disabled' do
- let(:project) { create(:project, :public, :repository, emails_disabled: true) }
+ let_it_be(:project) { create(:project, :public, :repository, emails_enabled: false) }
it 'is disabled' do
visit project_path(project)
diff --git a/spec/features/projects/user_changes_project_visibility_spec.rb b/spec/features/projects/user_changes_project_visibility_spec.rb
index f27a659f65f..24f24229f9c 100644
--- a/spec/features/projects/user_changes_project_visibility_spec.rb
+++ b/spec/features/projects/user_changes_project_visibility_spec.rb
@@ -66,8 +66,8 @@ RSpec.describe 'User changes public project visibility', :js, feature_category:
let(:project) { create(:project, :empty_repo, :public) }
it 'saves without confirmation' do
- expect(page).to have_selector('.js-emails-disabled', visible: true)
- find('.js-emails-disabled input[type="checkbox"]').click
+ expect(page).to have_selector('.js-emails-enabled', visible: true)
+ find('.js-emails-enabled input[type="checkbox"]').click
page.within('#js-shared-permissions') do
click_button 'Save changes'
diff --git a/spec/features/projects/work_items/work_item_spec.rb b/spec/features/projects/work_items/work_item_spec.rb
index e996a76b1c5..618d3e2efd0 100644
--- a/spec/features/projects/work_items/work_item_spec.rb
+++ b/spec/features/projects/work_items/work_item_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe 'Work item', :js, feature_category: :team_planning do
end
it_behaves_like 'work items title'
- it_behaves_like 'work items status'
+ it_behaves_like 'work items toggle status button'
it_behaves_like 'work items assignees'
it_behaves_like 'work items labels'
it_behaves_like 'work items comments', :issue
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 9244cafbc0b..ee5d92b7cdb 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -40,6 +40,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
it 'allows to create a protected branch with name containing HTML tags' do
visit project_protected_branches_path(project)
+
+ show_add_form
set_defaults
set_protected_branch_name('foo<b>bar<\b>')
click_on "Protect"
@@ -89,6 +91,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
describe "explicit protected branches" do
it "allows creating explicit protected branches" do
visit project_protected_branches_path(project)
+
+ show_add_form
set_defaults
set_protected_branch_name('some->branch')
click_on "Protect"
@@ -100,6 +104,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
it "shows success alert once protected branch is created" do
visit project_protected_branches_path(project)
+
+ show_add_form
set_defaults
set_protected_branch_name('some->branch')
click_on "Protect"
@@ -112,6 +118,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
project.repository.add_branch(admin, 'some-branch', commit.id)
visit project_protected_branches_path(project)
+
+ show_add_form
set_defaults
set_protected_branch_name('some-branch')
click_on "Protect"
@@ -124,6 +132,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
it "displays an error message if the named branch does not exist" do
visit project_protected_branches_path(project)
+
+ show_add_form
set_defaults
set_protected_branch_name('some-branch')
click_on "Protect"
@@ -135,6 +145,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
describe "wildcard protected branches" do
it "allows creating protected branches with a wildcard" do
visit project_protected_branches_path(project)
+
+ show_add_form
set_defaults
set_protected_branch_name('*-stable')
click_on "Protect"
@@ -149,6 +161,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
project.repository.add_branch(admin, 'staging-stable', 'master')
visit project_protected_branches_path(project)
+
+ show_add_form
set_defaults
set_protected_branch_name('*-stable')
click_on "Protect"
@@ -164,6 +178,8 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem
project.repository.add_branch(admin, 'development', 'master')
visit project_protected_branches_path(project)
+
+ show_add_form
set_protected_branch_name('*-stable')
set_defaults
click_on "Protect"
diff --git a/spec/features/protected_tags_spec.rb b/spec/features/protected_tags_spec.rb
index 45315f53fd6..f5b463d63fa 100644
--- a/spec/features/protected_tags_spec.rb
+++ b/spec/features/protected_tags_spec.rb
@@ -15,6 +15,8 @@ RSpec.describe 'Protected Tags', :js, :with_license, feature_category: :source_c
describe "explicit protected tags" do
it "allows creating explicit protected tags" do
visit project_protected_tags_path(project)
+ click_button('Add tag')
+
set_protected_tag_name('some-tag')
set_allowed_to('create')
click_on_protect
@@ -29,6 +31,7 @@ RSpec.describe 'Protected Tags', :js, :with_license, feature_category: :source_c
project.repository.add_tag(user, 'some-tag', commit.id)
visit project_protected_tags_path(project)
+ click_button('Add tag')
set_protected_tag_name('some-tag')
set_allowed_to('create')
click_on_protect
@@ -38,6 +41,7 @@ RSpec.describe 'Protected Tags', :js, :with_license, feature_category: :source_c
it "displays an error message if the named tag does not exist" do
visit project_protected_tags_path(project)
+ click_button('Add tag')
set_protected_tag_name('some-tag')
set_allowed_to('create')
click_on_protect
@@ -49,6 +53,7 @@ RSpec.describe 'Protected Tags', :js, :with_license, feature_category: :source_c
describe "wildcard protected tags" do
it "allows creating protected tags with a wildcard" do
visit project_protected_tags_path(project)
+ click_button('Add tag')
set_protected_tag_name('*-stable')
set_allowed_to('create')
click_on_protect
@@ -63,12 +68,16 @@ RSpec.describe 'Protected Tags', :js, :with_license, feature_category: :source_c
project.repository.add_tag(user, 'staging-stable', 'master')
visit project_protected_tags_path(project)
+ click_button('Add tag')
set_protected_tag_name('*-stable')
set_allowed_to('create')
click_on_protect
+ within("#js-protected-tags-settings .gl-new-card-count") do
+ expect(page).to have_content("2")
+ end
+
within(".protected-tags-list") do
- expect(page).to have_content("Protected tags (2)")
expect(page).to have_content("2 matching tags")
end
end
@@ -79,11 +88,13 @@ RSpec.describe 'Protected Tags', :js, :with_license, feature_category: :source_c
project.repository.add_tag(user, 'development', 'master')
visit project_protected_tags_path(project)
+ click_button('Add tag')
set_protected_tag_name('*-stable')
set_allowed_to('create')
click_on_protect
visit project_protected_tags_path(project)
+ click_button('Add tag')
click_on "2 matching tags"
within(".protected-tags-list") do
diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb
index 903211ec250..52df4bfece2 100644
--- a/spec/features/triggers_spec.rb
+++ b/spec/features/triggers_spec.rb
@@ -26,16 +26,18 @@ RSpec.describe 'Triggers', :js, feature_category: :continuous_integration do
describe 'triggers page' do
describe 'create trigger workflow' do
it 'prevents adding new trigger with no description' do
+ click_button 'Add new token'
fill_in 'trigger_description', with: ''
- click_button 'Add trigger'
+ click_button 'Create pipeline trigger token'
# See if input has error due to empty value
expect(page.find('form.gl-show-field-errors .gl-field-error')).to be_visible
end
it 'adds new trigger with description' do
+ click_button 'Add new token'
fill_in 'trigger_description', with: 'trigger desc'
- click_button 'Add trigger'
+ click_button 'Create pipeline trigger token'
aggregate_failures 'display creation notice and trigger is created' do
expect(page.find('[data-testid="alert-info"]')).to have_content 'Trigger was created successfully.'
@@ -100,6 +102,7 @@ RSpec.describe 'Triggers', :js, feature_category: :continuous_integration do
describe 'show triggers workflow' do
it 'contains trigger description placeholder' do
+ click_button 'Add new token'
expect(page.find('#trigger_description')['placeholder']).to eq 'Trigger description'
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 cc296259b80..cd181f73473 100644
--- a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
+++ b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
@@ -6,34 +6,63 @@ RSpec.describe 'User uploads avatar to profile', feature_category: :user_profile
let!(:user) { create(:user) }
let(:avatar_file_path) { Rails.root.join('spec', 'fixtures', 'dk.png') }
- before do
- stub_feature_flags(edit_user_profile_vue: false)
- sign_in user
- visit profile_path
- end
+ shared_examples 'upload avatar' do
+ it 'shows the new avatar immediately in the header and setting sidebar', :js do
+ expect(page.find('.avatar-image .gl-avatar')['src']).not_to include(
+ "/uploads/-/system/user/avatar/#{user.id}/avatar.png"
+ )
+ find('.js-user-avatar-input', visible: false).set(avatar_file_path)
+
+ click_button 'Set new profile picture'
+ click_button 'Update profile settings'
- it 'they see their new avatar on their profile' do
- attach_file('user_avatar', avatar_file_path, visible: false)
- click_button 'Update profile settings'
+ wait_for_all_requests
- visit user_path(user)
+ data_uri = find('.avatar-image .gl-avatar')['src']
+ expect(page.find('.header-user-avatar')['src']).to eq data_uri
+ expect(page.find('[data-testid="sidebar-user-avatar"]')['src']).to eq data_uri
+
+ visit profile_path
+
+ expect(page.find('.avatar-image .gl-avatar')['src']).to include(
+ "/uploads/-/system/user/avatar/#{user.id}/avatar.png"
+ )
+ end
+ end
- expect(page).to have_selector(%(img[src$="/uploads/-/system/user/avatar/#{user.id}/dk.png?width=96"]))
+ context 'with "edit_user_profile_vue" turned on' do
+ before do
+ sign_in_and_visit_profile
+ end
- # Cheating here to verify something that isn't user-facing, but is important
- expect(user.reload.avatar.file).to exist
+ it_behaves_like 'upload avatar'
end
- it 'their new avatar is immediately visible in the header and setting sidebar', :js do
- find('.js-user-avatar-input', visible: false).set(avatar_file_path)
+ context 'with "edit_user_profile_vue" turned off' do
+ before do
+ stub_feature_flags(edit_user_profile_vue: false)
+ sign_in_and_visit_profile
+ end
- click_button 'Set new profile picture'
- click_button 'Update profile settings'
+ it 'they see their new avatar on their profile' do
+ attach_file('user_avatar', avatar_file_path, visible: false)
+ click_button 'Update profile settings'
- wait_for_all_requests
+ visit user_path(user)
- data_uri = find('.avatar-image .gl-avatar')['src']
- expect(page.find('.header-user-avatar')['src']).to eq data_uri
- expect(page.find('[data-testid="sidebar-user-avatar"]')['src']).to eq data_uri
+ expect(page).to have_selector(%(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
+ end
+
+ it_behaves_like 'upload avatar'
+ end
+
+ private
+
+ def sign_in_and_visit_profile
+ sign_in user
+ visit profile_path
end
end
diff --git a/spec/features/users/email_verification_on_login_spec.rb b/spec/features/users/email_verification_on_login_spec.rb
index 1854e812b73..7675de28f86 100644
--- a/spec/features/users/email_verification_on_login_spec.rb
+++ b/spec/features/users/email_verification_on_login_spec.rb
@@ -2,10 +2,12 @@
require 'spec_helper'
-RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting, feature_category: :system_access do
+RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting, :js, feature_category: :system_access do
include EmailHelpers
- let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:user) { create(:user) }
+ let_it_be(:another_user) { create(:user) }
+ let_it_be(:new_email) { build_stubbed(:user).email }
let(:require_email_verification_enabled) { user }
@@ -33,7 +35,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
# Expect to see the verification form on the login page
expect(page).to have_current_path(new_user_session_path)
- expect(page).to have_content('Help us protect your account')
+ expect(page).to have_content(s_('IdentityVerification|Help us protect your account'))
# Expect an instructions email to be sent with a code
code = expect_instructions_email_and_extract_code
@@ -41,7 +43,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
# Signing in again prompts for the code and doesn't send a new one
gitlab_sign_in(user)
expect(page).to have_current_path(new_user_session_path)
- expect(page).to have_content('Help us protect your account')
+ expect(page).to have_content(s_('IdentityVerification|Help us protect your account'))
# Verify the code
verify_code(code)
@@ -54,7 +56,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
# Expect a confirmation page with a meta refresh tag for 3 seconds to the root
expect(page).to have_current_path(users_successful_verification_path)
- expect(page).to have_content('Verification successful')
+ expect(page).to have_content(s_('IdentityVerification|Verification successful'))
expect(page).to have_selector("meta[http-equiv='refresh'][content='3; url=#{root_path}']", visible: false)
end
end
@@ -69,7 +71,8 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
code = expect_instructions_email_and_extract_code
# Request a new code
- click_link 'Resend code'
+ click_button s_('IdentityVerification|Resend code')
+ expect(page).to have_content(s_('IdentityVerification|A new code has been sent.'))
expect_log_message('Instructions Sent', 2)
new_code = expect_instructions_email_and_extract_code
@@ -83,22 +86,63 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
gitlab_sign_in(user)
# It shows a resend button
- expect(page).to have_link 'Resend code'
+ expect(page).to have_button s_('IdentityVerification|Resend code')
# Resend more than the rate limited amount of times
10.times do
- click_link 'Resend code'
+ click_button s_('IdentityVerification|Resend code')
end
- # Expect the link to be gone
- expect(page).not_to have_link 'Resend code'
+ # Expect an error alert
+ expect(page).to have_content format(s_("IdentityVerification|You've reached the maximum amount of resends. "\
+ 'Wait %{interval} and try again.'), interval: 'about 1 hour')
+ end
+ end
- # Wait for 1 hour
- travel 1.hour
+ describe 'updating the email address' do
+ it 'offers to update the email address' do
+ perform_enqueued_jobs do
+ # When logging in
+ gitlab_sign_in(user)
- # Now it's visible again
- gitlab_sign_in(user)
- expect(page).to have_link 'Resend code'
+ # Expect an instructions email to be sent with a code
+ code = expect_instructions_email_and_extract_code
+
+ # It shows an update email button
+ expect(page).to have_button s_('IdentityVerification|Update email')
+
+ # Click Update email button
+ click_button s_('IdentityVerification|Update email')
+
+ # Try to update with another user's email address
+ fill_in _('Email'), with: another_user.email
+ click_button s_('IdentityVerification|Update email')
+ expect(page).to have_content('Email has already been taken')
+
+ # Update to a unique email address
+ fill_in _('Email'), with: new_email
+ click_button s_('IdentityVerification|Update email')
+ expect(page).to have_content(s_('IdentityVerification|A new code has been sent to ' \
+ 'your updated email address.'))
+ expect_log_message('Instructions Sent', 2)
+
+ new_code = expect_email_changed_notification_to_old_address_and_instructions_email_to_new_address
+
+ # Verify the old code is different from the new code
+ expect(code).not_to eq(new_code)
+ verify_code(new_code)
+
+ # Expect the user to be unlocked
+ expect_user_to_be_unlocked
+ expect_user_to_be_confirmed
+
+ # When logging in again
+ gitlab_sign_out
+ gitlab_sign_in(user)
+
+ # It does not show an update email button anymore
+ expect(page).not_to have_button s_('IdentityVerification|Update email')
+ end
end
end
@@ -118,8 +162,9 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
# Expect an error message
expect_log_message('Failed Attempt', reason: 'rate_limited')
- expect(page).to have_content("You've reached the maximum amount of tries. "\
- 'Wait 10 minutes or send a new code and try again.')
+ expect(page).to have_content(
+ format(s_("IdentityVerification|You've reached the maximum amount of tries. "\
+ 'Wait %{interval} or send a new code and try again.'), interval: '10 minutes'))
# Wait for 10 minutes
travel 10.minutes
@@ -139,7 +184,8 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
# Expect an error message
expect_log_message('Failed Attempt', reason: 'invalid')
- expect(page).to have_content('The code is incorrect. Enter it again, or send a new code.')
+ expect(page).to have_content(s_('IdentityVerification|The code is incorrect. '\
+ 'Enter it again, or send a new code.'))
end
it 'verifies expired codes' do
@@ -156,7 +202,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
# Expect an error message
expect_log_message('Failed Attempt', reason: 'expired')
- expect(page).to have_content('The code has expired. Send a new code and try again.')
+ expect(page).to have_content(s_('IdentityVerification|The code has expired. Send a new code and try again.'))
end
end
end
@@ -250,7 +296,8 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
it 'shows an error message on on the login page' do
expect(page).to have_current_path(new_user_session_path)
- expect(page).to have_content('Maximum login attempts exceeded. Wait 10 minutes and try again.')
+ expect(page).to have_content(format(s_('IdentityVerification|Maximum login attempts exceeded. '\
+ 'Wait %{interval} and try again.'), interval: '10 minutes'))
end
end
@@ -271,7 +318,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
stub_feature_flags(require_email_verification: false)
# Resending and veryfying the code work as expected
- click_link 'Resend code'
+ click_button s_('IdentityVerification|Resend code')
new_code = expect_instructions_email_and_extract_code
verify_code(code)
@@ -283,7 +330,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
verify_code(new_code)
expect(page).to have_content(s_('IdentityVerification|The code has expired. Send a new code and try again.'))
- click_link 'Resend code'
+ click_button s_('IdentityVerification|Resend code')
another_code = expect_instructions_email_and_extract_code
verify_code(another_code)
@@ -341,6 +388,28 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting,
end
end
+ def expect_user_to_be_confirmed
+ aggregate_failures do
+ expect(user.email).to eq(new_email)
+ expect(user.unconfirmed_email).to be_nil
+ end
+ end
+
+ def expect_email_changed_notification_to_old_address_and_instructions_email_to_new_address
+ changed_email = ActionMailer::Base.deliveries[0]
+ instructions_email = ActionMailer::Base.deliveries[1]
+
+ expect(changed_email.to).to match_array([user.email])
+ expect(changed_email.subject).to eq('Email Changed')
+
+ expect(instructions_email.to).to match_array([new_email])
+ expect(instructions_email.subject).to eq(s_('IdentityVerification|Verify your identity'))
+
+ reset_delivered_emails!
+
+ instructions_email.body.parts.first.to_s[/\d{#{Users::EmailVerification::GenerateTokenService::TOKEN_LENGTH}}/o]
+ end
+
def expect_instructions_email_and_extract_code
mail = find_email_for(user)
expect(mail.to).to match_array([user.email])
diff --git a/spec/features/users/google_syndication_csp_spec.rb b/spec/features/users/google_syndication_csp_spec.rb
new file mode 100644
index 00000000000..e71539f87c8
--- /dev/null
+++ b/spec/features/users/google_syndication_csp_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Google Syndication content security policy', feature_category: :purchase do
+ include ContentSecurityPolicyHelpers
+
+ let_it_be(:connect_src) { 'https://other-cdn.test' }
+
+ let_it_be(:google_analytics_src) do
+ 'localhost https://cdn.cookielaw.org https://*.onetrust.com *.google-analytics.com ' \
+ '*.analytics.google.com *.googletagmanager.com'
+ end
+
+ let_it_be(:allowed_src) do
+ '*.google.com/pagead/landing pagead2.googlesyndication.com/pagead/landing'
+ end
+
+ let(:extra) { { google_tag_manager_nonce_id: 'google_tag_manager_nonce_id' } }
+
+ let(:csp) do
+ ActionDispatch::ContentSecurityPolicy.new do |p|
+ p.connect_src(*connect_src.split)
+ end
+ end
+
+ subject { response_headers['Content-Security-Policy'] }
+
+ before do
+ setup_csp_for_controller(SessionsController, csp, any_time: true)
+ stub_config(extra: extra)
+ visit new_user_session_path
+ end
+
+ context 'when self-hosted' do
+ context 'when there is no CSP config' do
+ let(:extra) { {} }
+ let(:csp) { ActionDispatch::ContentSecurityPolicy.new }
+
+ it { is_expected.to be_blank }
+ end
+
+ context 'when connect-src CSP config exists' do
+ it { is_expected.to include("connect-src #{connect_src} #{google_analytics_src}") }
+ it { is_expected.not_to include(allowed_src) }
+ end
+ end
+
+ context 'when SaaS', :saas do
+ context 'when connect-src CSP config exists' do
+ it { is_expected.to include("connect-src #{connect_src} #{google_analytics_src} #{allowed_src}") }
+ end
+ end
+end
diff --git a/spec/features/users/rss_spec.rb b/spec/features/users/rss_spec.rb
index 39b6d049e43..2db58ce04a1 100644
--- a/spec/features/users/rss_spec.rb
+++ b/spec/features/users/rss_spec.rb
@@ -6,28 +6,53 @@ RSpec.describe 'User RSS', feature_category: :user_profile do
let(:user) { create(:user) }
let(:path) { user_path(create(:user)) }
- before do
- stub_feature_flags(user_profile_overflow_menu_vue: false)
- end
-
- context 'when signed in' do
+ describe 'with "user_profile_overflow_menu_vue" feature flag off' do
before do
- sign_in(user)
- visit path
+ stub_feature_flags(user_profile_overflow_menu_vue: false)
end
- it_behaves_like "it has an RSS button with current_user's feed token"
- end
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ visit path
+ end
- context 'when signed out' do
- before do
- visit path
+ it_behaves_like "it has an RSS button with current_user's feed token"
end
- it_behaves_like "it has an RSS button without a feed token"
+ context 'when signed out' do
+ before do
+ visit path
+ end
+
+ it_behaves_like "it has an RSS button without a feed token"
+ end
end
- # TODO: implement tests before the FF "user_profile_overflow_menu_vue" is turned on
- # See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122971
- # Related Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/416974
+ describe 'with "user_profile_overflow_menu_vue" feature flag on', :js do
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ visit path
+ end
+
+ it 'shows the RSS link with overflow menu' do
+ find('[data-testid="base-dropdown-toggle"').click
+
+ expect(page).to have_link 'Subscribe', href: /feed_token=glft-.*-#{user.id}/
+ end
+ end
+
+ context 'when signed out' do
+ before do
+ visit path
+ end
+
+ it 'has an RSS without a feed token' do
+ find('[data-testid="base-dropdown-toggle"').click
+
+ expect(page).not_to have_link 'Subscribe', href: /feed_token=glft-.*-#{user.id}/
+ end
+ end
+ end
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 850dd0bbc5d..450b9fa46b1 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -36,7 +36,7 @@ RSpec.shared_examples 'Signup name validation' do |field, max_length, label|
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 emoji")
end
end
end
@@ -176,7 +176,7 @@ RSpec.describe 'Signup', :js, feature_category: :user_profile do
it 'shows an error message if the username contains emojis' do
simulate_input('#new_user_username', 'ehsan😀')
- expect(page).to have_content("Invalid input, please avoid emojis")
+ expect(page).to have_content("Invalid input, please avoid emoji")
end
it 'shows a pending message if the username availability is being fetched',