summaryrefslogtreecommitdiff
path: root/spec/features
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-20 23:50:22 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-20 23:50:22 +0000
commit9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch)
tree70467ae3692a0e35e5ea56bcb803eb512a10bedb /spec/features
parent4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff)
downloadgitlab-ce-d01dcc7e6779d5b18a2967c572865b84f63f16aa.tar.gz
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'spec/features')
-rw-r--r--spec/features/admin/admin_abuse_reports_spec.rb2
-rw-r--r--spec/features/admin/admin_appearance_spec.rb2
-rw-r--r--spec/features/admin/admin_groups_spec.rb45
-rw-r--r--spec/features/admin/admin_labels_spec.rb6
-rw-r--r--spec/features/admin/admin_mode/login_spec.rb2
-rw-r--r--spec/features/admin/admin_mode/logout_spec.rb2
-rw-r--r--spec/features/admin/admin_mode_spec.rb8
-rw-r--r--spec/features/admin/admin_runners_spec.rb30
-rw-r--r--spec/features/admin/admin_search_settings_spec.rb6
-rw-r--r--spec/features/admin/admin_sees_project_statistics_spec.rb2
-rw-r--r--spec/features/admin/admin_sees_projects_statistics_spec.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb18
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb2
-rw-r--r--spec/features/admin/services/admin_activates_prometheus_spec.rb24
-rw-r--r--spec/features/admin/services/admin_visits_service_templates_spec.rb44
-rw-r--r--spec/features/alerts_settings/user_views_alerts_settings_spec.rb2
-rw-r--r--spec/features/boards/add_issues_modal_spec.rb270
-rw-r--r--spec/features/boards/boards_spec.rb94
-rw-r--r--spec/features/boards/focus_mode_spec.rb4
-rw-r--r--spec/features/boards/modal_filter_spec.rb228
-rw-r--r--spec/features/boards/multi_select_spec.rb4
-rw-r--r--spec/features/boards/multiple_boards_spec.rb1
-rw-r--r--spec/features/boards/new_issue_spec.rb34
-rw-r--r--spec/features/boards/reload_boards_on_browser_back_spec.rb4
-rw-r--r--spec/features/boards/sidebar_assignee_spec.rb122
-rw-r--r--spec/features/boards/sidebar_due_date_spec.rb46
-rw-r--r--spec/features/boards/sidebar_labels_spec.rb166
-rw-r--r--spec/features/boards/sidebar_milestones_spec.rb65
-rw-r--r--spec/features/boards/sidebar_spec.rb403
-rw-r--r--spec/features/boards/sub_group_project_spec.rb3
-rw-r--r--spec/features/boards/user_adds_lists_to_board_spec.rb11
-rw-r--r--spec/features/calendar_spec.rb4
-rw-r--r--spec/features/callouts/service_templates_deprecation_spec.rb59
-rw-r--r--spec/features/clusters/cluster_detail_page_spec.rb6
-rw-r--r--spec/features/clusters/cluster_health_dashboard_spec.rb2
-rw-r--r--spec/features/commits_spec.rb2
-rw-r--r--spec/features/dashboard/active_tab_spec.rb2
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb2
-rw-r--r--spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb2
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb4
-rw-r--r--spec/features/dashboard/milestones_spec.rb2
-rw-r--r--spec/features/dashboard/project_member_activity_index_spec.rb2
-rw-r--r--spec/features/dashboard/projects_spec.rb23
-rw-r--r--spec/features/dashboard/shortcuts_spec.rb6
-rw-r--r--spec/features/discussion_comments/merge_request_spec.rb2
-rw-r--r--spec/features/error_pages_spec.rb9
-rw-r--r--spec/features/error_tracking/user_filters_errors_by_status_spec.rb1
-rw-r--r--spec/features/error_tracking/user_searches_sentry_errors_spec.rb1
-rw-r--r--spec/features/error_tracking/user_sees_error_index_spec.rb3
-rw-r--r--spec/features/file_uploads/attachment_spec.rb44
-rw-r--r--spec/features/file_uploads/maven_package_spec.rb21
-rw-r--r--spec/features/file_uploads/nuget_package_spec.rb4
-rw-r--r--spec/features/file_uploads/rubygem_package_spec.rb45
-rw-r--r--spec/features/frequently_visited_projects_and_groups_spec.rb2
-rw-r--r--spec/features/gitlab_experiments_spec.rb44
-rw-r--r--spec/features/groups/board_spec.rb2
-rw-r--r--spec/features/groups/clusters/user_spec.rb2
-rw-r--r--spec/features/groups/group_page_with_external_authorization_service_spec.rb4
-rw-r--r--spec/features/groups/group_settings_spec.rb2
-rw-r--r--spec/features/groups/issues_spec.rb2
-rw-r--r--spec/features/groups/labels/index_spec.rb2
-rw-r--r--spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb1
-rw-r--r--spec/features/groups/members/request_access_spec.rb2
-rw-r--r--spec/features/groups/merge_requests_spec.rb2
-rw-r--r--spec/features/groups/milestone_spec.rb6
-rw-r--r--spec/features/groups/navbar_spec.rb6
-rw-r--r--spec/features/groups/settings/user_searches_in_settings_spec.rb23
-rw-r--r--spec/features/groups_spec.rb66
-rw-r--r--spec/features/ide/clientside_preview_csp_spec.rb10
-rw-r--r--spec/features/import/manifest_import_spec.rb11
-rw-r--r--spec/features/invites_spec.rb17
-rw-r--r--spec/features/issues/bulk_assignment_labels_spec.rb4
-rw-r--r--spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb6
-rw-r--r--spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb6
-rw-r--r--spec/features/issues/form_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb984
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb215
-rw-r--r--spec/features/issues/markdown_toolbar_spec.rb28
-rw-r--r--spec/features/issues/note_polling_spec.rb2
-rw-r--r--spec/features/issues/spam_issues_spec.rb22
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb18
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb2
-rw-r--r--spec/features/issues/user_creates_confidential_merge_request_spec.rb2
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb10
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb198
-rw-r--r--spec/features/issues/user_filters_issues_spec.rb2
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb4
-rw-r--r--spec/features/issues/user_invites_from_a_comment_spec.rb25
-rw-r--r--spec/features/issues/user_sees_live_update_spec.rb2
-rw-r--r--spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb5
-rw-r--r--spec/features/issues/user_sorts_issues_spec.rb46
-rw-r--r--spec/features/markdown/markdown_spec.rb11
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb120
-rw-r--r--spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb2
-rw-r--r--spec/features/merge_request/user_awards_emoji_spec.rb29
-rw-r--r--spec/features/merge_request/user_creates_merge_request_spec.rb6
-rw-r--r--spec/features/merge_request/user_invites_from_a_comment_spec.rb25
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb8
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb32
-rw-r--r--spec/features/merge_request/user_sees_breadcrumb_links_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb38
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb6
-rw-r--r--spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb12
-rw-r--r--spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb4
-rw-r--r--spec/features/merge_request/user_squashes_merge_request_spec.rb4
-rw-r--r--spec/features/merge_request/user_views_open_merge_request_spec.rb2
-rw-r--r--spec/features/milestones/user_creates_milestone_spec.rb2
-rw-r--r--spec/features/milestones/user_views_milestone_spec.rb4
-rw-r--r--spec/features/milestones/user_views_milestones_spec.rb3
-rw-r--r--spec/features/participants_autocomplete_spec.rb44
-rw-r--r--spec/features/profiles/emails_spec.rb8
-rw-r--r--spec/features/profiles/password_spec.rb2
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb2
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb8
-rw-r--r--spec/features/profiles/user_search_settings_spec.rb6
-rw-r--r--spec/features/projects/active_tabs_spec.rb2
-rw-r--r--spec/features/projects/blobs/blob_line_permalink_updater_spec.rb22
-rw-r--r--spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb42
-rw-r--r--spec/features/projects/branches/user_creates_branch_spec.rb4
-rw-r--r--spec/features/projects/branches/user_deletes_branch_spec.rb9
-rw-r--r--spec/features/projects/branches_spec.rb29
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb2
-rw-r--r--spec/features/projects/clusters/user_spec.rb2
-rw-r--r--spec/features/projects/clusters_spec.rb4
-rw-r--r--spec/features/projects/commit/cherry_pick_spec.rb13
-rw-r--r--spec/features/projects/commit/comments/user_edits_comments_spec.rb2
-rw-r--r--spec/features/projects/commit/mini_pipeline_graph_spec.rb50
-rw-r--r--spec/features/projects/commit/user_reverts_commit_spec.rb17
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb9
-rw-r--r--spec/features/projects/features_visibility_spec.rb2
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb42
-rw-r--r--spec/features/projects/files/user_creates_directory_spec.rb2
-rw-r--r--spec/features/projects/files/user_uploads_files_spec.rb35
-rw-r--r--spec/features/projects/fork_spec.rb48
-rw-r--r--spec/features/projects/jobs/permissions_spec.rb2
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb9
-rw-r--r--spec/features/projects/jobs_spec.rb5
-rw-r--r--spec/features/projects/labels/user_removes_labels_spec.rb10
-rw-r--r--spec/features/projects/members/list_spec.rb2
-rw-r--r--spec/features/projects/members/user_requests_access_spec.rb2
-rw-r--r--spec/features/projects/merge_request_button_spec.rb4
-rw-r--r--spec/features/projects/navbar_spec.rb4
-rw-r--r--spec/features/projects/new_project_spec.rb66
-rw-r--r--spec/features/projects/pages/user_edits_settings_spec.rb1
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb10
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb89
-rw-r--r--spec/features/projects/releases/user_views_edit_release_spec.rb2
-rw-r--r--spec/features/projects/releases/user_views_release_spec.rb43
-rw-r--r--spec/features/projects/remote_mirror_spec.rb4
-rw-r--r--spec/features/projects/services/disable_triggers_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_asana_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb11
-rw-r--r--spec/features/projects/services/user_activates_hipchat_spec.rb40
-rw-r--r--spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb6
-rw-r--r--spec/features/projects/services/user_activates_jira_spec.rb71
-rw-r--r--spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_pushover_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_slack_notifications_spec.rb2
-rw-r--r--spec/features/projects/services/user_views_services_spec.rb4
-rw-r--r--spec/features/projects/settings/access_tokens_spec.rb106
-rw-r--r--spec/features/projects/settings/forked_project_settings_spec.rb5
-rw-r--r--spec/features/projects/settings/operations_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb4
-rw-r--r--spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb34
-rw-r--r--spec/features/projects/settings/user_searches_in_settings_spec.rb44
-rw-r--r--spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb8
-rw-r--r--spec/features/projects/show/user_sees_deletion_failure_message_spec.rb2
-rw-r--r--spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb5
-rw-r--r--spec/features/projects/show/user_uploads_files_spec.rb12
-rw-r--r--spec/features/projects/snippets/user_comments_on_snippet_spec.rb1
-rw-r--r--spec/features/projects/sub_group_issuables_spec.rb10
-rw-r--r--spec/features/projects/user_sees_sidebar_spec.rb2
-rw-r--r--spec/features/projects/user_sees_user_popover_spec.rb2
-rw-r--r--spec/features/projects/user_uses_shortcuts_spec.rb2
-rw-r--r--spec/features/projects_spec.rb20
-rw-r--r--spec/features/protected_branches_spec.rb12
-rw-r--r--spec/features/registrations/welcome_spec.rb21
-rw-r--r--spec/features/runners_spec.rb16
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb2
-rw-r--r--spec/features/security/project/internal_access_spec.rb12
-rw-r--r--spec/features/security/project/private_access_spec.rb14
-rw-r--r--spec/features/security/project/public_access_spec.rb12
-rw-r--r--spec/features/snippets/notes_on_personal_snippets_spec.rb3
-rw-r--r--spec/features/users/anonymous_sessions_spec.rb2
-rw-r--r--spec/features/users/login_spec.rb6
-rw-r--r--spec/features/users/show_spec.rb6
-rw-r--r--spec/features/users/terms_spec.rb2
-rw-r--r--spec/features/whats_new_spec.rb62
190 files changed, 2882 insertions, 2351 deletions
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
index 192182adddc..3a02ce89aa9 100644
--- a/spec/features/admin/admin_abuse_reports_spec.rb
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe "Admin::AbuseReports", :js do
describe 'filtering by user' do
let!(:user2) { create(:user) }
- let!(:abuse_report) { create(:abuse_report, user: 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
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index cd136af8d69..61e7efbc56c 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe 'Admin Appearance' do
context 'when system header and footer messages are not empty' do
before do
- appearance.update(header_message: 'Foo', footer_message: 'Bar')
+ appearance.update!(header_message: 'Foo', footer_message: 'Bar')
end
it 'shows custom system header and footer fields' do
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index bbdf2f7f4a9..e7634f4e020 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_field('group_path')
expect(page).to have_field('group_visibility_level_0')
expect(page).to have_field('description')
+ expect(page).to have_field('group_admin_note_attributes_note')
end
end
@@ -47,10 +48,12 @@ RSpec.describe 'Admin Groups' do
path_component = 'gitlab'
group_name = 'GitLab group name'
group_description = 'Description of group for GitLab'
+ group_admin_note = 'A note about this group by an admin'
fill_in 'group_path', with: path_component
fill_in 'group_name', with: group_name
fill_in 'group_description', with: group_description
+ fill_in 'group_admin_note_attributes_note', with: group_admin_note
click_button "Create group"
expect(current_path).to eq admin_group_path(Group.find_by(path: path_component))
@@ -61,6 +64,8 @@ RSpec.describe 'Admin Groups' do
expect(li_texts).to match group_name
expect(li_texts).to match path_component
expect(li_texts).to match group_description
+ p_texts = content.all('p').collect(&:text).join('/n')
+ expect(p_texts).to match group_admin_note
end
it 'shows the visibility level radio populated with the default value' do
@@ -116,6 +121,16 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_link(group.name, href: group_path(group))
end
+
+ it 'has a note if one is available' do
+ group = create(:group, :private)
+ note_text = 'A group administrator note'
+ group.update!(admin_note_attributes: { note: note_text })
+
+ visit admin_group_path(group)
+
+ expect(page).to have_text(note_text)
+ end
end
describe 'group edit' do
@@ -145,6 +160,36 @@ RSpec.describe 'Admin Groups' do
expect(name_field.value).to eq original_name
end
+
+ it 'adding an admin note to group without one' do
+ group = create(:group, :private)
+ expect(group.admin_note).to be_nil
+
+ visit admin_group_edit_path(group)
+ admin_note_text = 'A note by an administrator'
+
+ fill_in 'group_admin_note_attributes_note', with: admin_note_text
+ click_button 'Save changes'
+
+ expect(page).to have_content(admin_note_text)
+ end
+
+ it 'editing an existing group admin note' do
+ admin_note_text = 'A note by an administrator'
+ new_admin_note_text = 'A new note by an administrator'
+ group = create(:group, :private)
+ group.create_admin_note(note: admin_note_text)
+
+ visit admin_group_edit_path(group)
+
+ admin_note_field = find('#group_admin_note_attributes_note')
+ expect(admin_note_field.value).to eq(admin_note_text)
+
+ fill_in 'group_admin_note_attributes_note', with: new_admin_note_text
+ click_button 'Save changes'
+
+ expect(page).to have_content(new_admin_note_text)
+ end
end
describe 'add user into a group', :js do
diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb
index 815a73b1450..43fb1f31a0f 100644
--- a/spec/features/admin/admin_labels_spec.rb
+++ b/spec/features/admin/admin_labels_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe 'admin issues labels' do
- let!(:bug_label) { Label.create(title: 'bug', template: true) }
- let!(:feature_label) { Label.create(title: 'feature', template: true) }
+ let!(:bug_label) { Label.create!(title: 'bug', template: true) }
+ let!(:feature_label) { Label.create!(title: 'feature', template: true) }
before do
admin = create(:admin)
@@ -36,7 +36,7 @@ RSpec.describe 'admin issues labels' do
it 'deletes all labels', :js do
page.within '.labels' do
- page.all('.remove-row').each do |remove|
+ page.all('.js-remove-row').each do |remove|
accept_confirm { remove.click }
wait_for_requests
end
diff --git a/spec/features/admin/admin_mode/login_spec.rb b/spec/features/admin/admin_mode/login_spec.rb
index f1dee075925..5b2dfdb2941 100644
--- a/spec/features/admin/admin_mode/login_spec.rb
+++ b/spec/features/admin/admin_mode/login_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Admin Mode Login' do
expect(codes.size).to eq 10
# Ensure the generated codes get saved
- user.save
+ user.save!
end
context 'with valid code' do
diff --git a/spec/features/admin/admin_mode/logout_spec.rb b/spec/features/admin/admin_mode/logout_spec.rb
index b7fa59bbfb7..8cfac5d8b99 100644
--- a/spec/features/admin/admin_mode/logout_spec.rb
+++ b/spec/features/admin/admin_mode/logout_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe 'Admin Mode Logout', :js do
let(:user) { create(:admin) }
before do
+ stub_feature_flags(combined_menu: false)
+
gitlab_sign_in(user)
gitlab_enable_admin_mode_sign_in(user)
visit admin_root_path
diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb
index 8169b3a20db..633de20c82d 100644
--- a/spec/features/admin/admin_mode_spec.rb
+++ b/spec/features/admin/admin_mode_spec.rb
@@ -9,10 +9,12 @@ RSpec.describe 'Admin mode' do
let(:admin) { create(:admin) }
before do
+ stub_feature_flags(combined_menu: false)
+
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
end
- context 'feature flag :user_mode_in_session is enabled', :request_store do
+ context 'application setting :admin_mode is enabled', :request_store do
before do
sign_in(admin)
end
@@ -155,9 +157,9 @@ RSpec.describe 'Admin mode' do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
sign_in(admin)
end
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 4f135b81bdf..4e0dcbdf075 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -201,21 +201,21 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
- within '.runners-content .gl-responsive-table-row:nth-child(2)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(2)' do
expect(page).to have_content 'runner-2'
end
- within '.runners-content .gl-responsive-table-row:nth-child(3)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(3)' do
expect(page).to have_content 'runner-1'
end
sorting_by 'Last Contact'
- within '.runners-content .gl-responsive-table-row:nth-child(2)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(2)' do
expect(page).to have_content 'runner-1'
end
- within '.runners-content .gl-responsive-table-row:nth-child(3)' do
+ within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(3)' do
expect(page).to have_content 'runner-2'
end
end
@@ -285,8 +285,16 @@ RSpec.describe "Admin Runners" do
end
describe 'runner page breadcrumbs' do
- it 'contains the current runner’s short sha' do
- expect(page.find('h2')).to have_content(runner.short_sha)
+ it 'contains the current runner token' do
+ page.within '[data-testid="breadcrumb-links"]' do
+ expect(page.find('h2')).to have_content(runner.short_sha)
+ end
+ end
+ end
+
+ describe 'runner page title', :js do
+ it 'contains the runner id' do
+ expect(find('.page-title')).to have_content("Runner ##{runner.id}")
end
end
@@ -313,11 +321,11 @@ RSpec.describe "Admin Runners" do
describe 'enable/create' do
shared_examples 'assignable runner' do
it 'enables a runner for a project' do
- within '.unassigned-projects' do
+ within '[data-testid="unassigned-projects"]' do
click_on 'Enable'
end
- assigned_project = page.find('.assigned-projects')
+ assigned_project = page.find('[data-testid="assigned-projects"]')
expect(assigned_project).to have_content(@project2.path)
end
@@ -347,7 +355,7 @@ RSpec.describe "Admin Runners" do
let(:runner) { create(:ci_runner, :instance) }
before do
- @project1.destroy
+ @project1.destroy!
visit admin_runner_path(runner)
end
@@ -363,11 +371,11 @@ RSpec.describe "Admin Runners" do
end
it 'enables specific runner for project' do
- within '.assigned-projects' do
+ within '[data-testid="assigned-projects"]' do
click_on 'Disable'
end
- new_runner_project = page.find('.unassigned-projects')
+ new_runner_project = page.find('[data-testid="unassigned-projects"]')
expect(new_runner_project).to have_content(@project1.path)
end
diff --git a/spec/features/admin/admin_search_settings_spec.rb b/spec/features/admin/admin_search_settings_spec.rb
index a78d17a6651..cd61a1db6f3 100644
--- a/spec/features/admin/admin_search_settings_spec.rb
+++ b/spec/features/admin/admin_search_settings_spec.rb
@@ -20,8 +20,10 @@ RSpec.describe 'Admin searches application settings', :js do
end
context 'in ci/cd settings page' do
- let(:visit_path) { ci_cd_admin_application_settings_path }
+ before do
+ visit(ci_cd_admin_application_settings_path)
+ end
- it_behaves_like 'can search settings with feature flag check', 'Variables', 'Package Registry'
+ it_behaves_like 'can search settings', 'Variables', 'Package Registry'
end
end
diff --git a/spec/features/admin/admin_sees_project_statistics_spec.rb b/spec/features/admin/admin_sees_project_statistics_spec.rb
index be781730924..3433cc01b8e 100644
--- a/spec/features/admin/admin_sees_project_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_project_statistics_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe "Admin > Admin sees project statistics" do
end
context 'when project has no statistics' do
- let(:project) { create(:project, :repository) { |project| project.statistics.destroy } }
+ let(:project) { create(:project, :repository) { |project| project.statistics.destroy! } }
it "shows 'Storage: Unknown'" do
expect(page).to have_content("Storage: Unknown")
diff --git a/spec/features/admin/admin_sees_projects_statistics_spec.rb b/spec/features/admin/admin_sees_projects_statistics_spec.rb
index 2e96814d1e9..d340eb47f34 100644
--- a/spec/features/admin/admin_sees_projects_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_projects_statistics_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "Admin > Admin sees projects statistics" do
before do
create(:project, :repository)
- create(:project, :repository) { |project| project.statistics.destroy }
+ create(:project, :repository) { |project| project.statistics.destroy! }
sign_in(current_user)
gitlab_enable_admin_mode_sign_in(current_user)
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 249621f5835..9a2e2eb2f6f 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Admin updates settings' do
let(:admin) { create(:admin) }
- context 'feature flag :user_mode_in_session is enabled', :request_store do
+ context 'application setting :admin_mode is enabled', :request_store do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
@@ -129,7 +129,7 @@ RSpec.describe 'Admin updates settings' do
context 'Change Sign-up restrictions' do
context 'Require Admin approval for new signup setting' do
- it 'changes the setting' do
+ it 'changes the setting', :js do
page.within('.as-signup') do
check 'Require admin approval for new sign-ups'
click_button 'Save changes'
@@ -249,6 +249,14 @@ RSpec.describe 'Admin updates settings' do
expect(page).to have_content "Application settings saved successfully"
expect(current_settings.hide_third_party_offers).to be true
end
+ end
+
+ context 'when the Slack Notifications Service template is active' do
+ before do
+ create(:service, :template, type: 'SlackService', active: true)
+
+ visit general_admin_application_settings_path
+ end
it 'change Slack Notifications Service template settings', :js do
first(:link, 'Service Templates').click
@@ -588,7 +596,7 @@ RSpec.describe 'Admin updates settings' do
context 'Nav bar' do
it 'shows default help links in nav' do
- default_support_url = 'https://about.gitlab.com/getting-help/'
+ default_support_url = "https://#{ApplicationHelper.promo_host}/getting-help/"
visit root_dashboard_path
@@ -615,9 +623,9 @@ RSpec.describe 'Admin updates settings' do
end
end
- context 'feature flag :user_mode_in_session is disabled' do
+ context 'application setting :admin_mode is disabled' do
before do
- stub_feature_flags(user_mode_in_session: false)
+ stub_application_setting(admin_mode: false)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index cae190e76b0..dc528dd92d4 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js do
end
it "removes expired tokens from 'active' section" do
- impersonation_token.update(expires_at: 5.days.ago)
+ impersonation_token.update!(expires_at: 5.days.ago)
visit admin_user_impersonation_tokens_path(user_id: user.username)
diff --git a/spec/features/admin/services/admin_activates_prometheus_spec.rb b/spec/features/admin/services/admin_activates_prometheus_spec.rb
deleted file mode 100644
index a225de365c8..00000000000
--- a/spec/features/admin/services/admin_activates_prometheus_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Admin activates Prometheus', :js do
- let(:admin) { create(:user, :admin) }
-
- before do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
-
- visit(admin_application_settings_services_path)
-
- click_link('Prometheus')
- end
-
- it 'activates service' do
- check('Active')
- fill_in('API URL', with: 'http://prometheus.example.com')
- click_button('Save changes')
-
- expect(page).to have_content('Application settings saved successfully')
- end
-end
diff --git a/spec/features/admin/services/admin_visits_service_templates_spec.rb b/spec/features/admin/services/admin_visits_service_templates_spec.rb
index 563bca8b32f..1fd8c8316e3 100644
--- a/spec/features/admin/services/admin_visits_service_templates_spec.rb
+++ b/spec/features/admin/services/admin_visits_service_templates_spec.rb
@@ -9,23 +9,45 @@ RSpec.describe 'Admin visits service templates' do
before do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
-
- visit(admin_application_settings_services_path)
end
- context 'without instance-level integration' do
- it 'shows a link to service template' do
- expect(page).to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
- expect(page).not_to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ context 'without an active service template' do
+ before do
+ visit(admin_application_settings_services_path)
+ end
+
+ it 'does not show service template content' do
+ expect(page).not_to have_content('Service template allows you to set default values for integrations')
end
end
- context 'with instance-level integration' do
- let_it_be(:slack_instance_integration) { create(:slack_service, instance: true, project: nil) }
+ context 'with an active service template' do
+ before do
+ create(:slack_service, :template, active: true)
+ visit(admin_application_settings_services_path)
+ end
+
+ it 'shows service template content' do
+ expect(page).to have_content('Service template allows you to set default values for integrations')
+ end
+
+ context 'without instance-level integration' do
+ it 'shows a link to service template' do
+ expect(page).to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
+ expect(page).not_to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ end
+ end
+
+ context 'with instance-level integration' do
+ before do
+ create(:slack_service, instance: true, project: nil)
+ visit(admin_application_settings_services_path)
+ end
- it 'shows a link to instance-level integration' do
- expect(page).not_to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
- expect(page).to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ it 'shows a link to instance-level integration' do
+ expect(page).not_to have_link('Slack', href: edit_admin_application_settings_service_path(slack_service.id))
+ expect(page).to have_link('Slack', href: edit_admin_application_settings_integration_path(slack_service))
+ end
end
end
end
diff --git a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
index 60f2f776595..6675abd6b42 100644
--- a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
+++ b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Alert integrations settings form', :js do
it 'shows the alerts setting form title' do
page.within('#js-alert-management-settings') do
- expect(find('h4')).to have_content('Alerts')
+ expect(find('h4')).to have_content('Alert integrations')
end
end
diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb
deleted file mode 100644
index 8d0fa3e023b..00000000000
--- a/spec/features/boards/add_issues_modal_spec.rb
+++ /dev/null
@@ -1,270 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Issue Boards add issue modal', :js do
- let(:project) { create(:project, :public) }
- let(:board) { create(:board, project: project) }
- let(:user) { create(:user) }
- let!(:planning) { create(:label, project: project, name: 'Planning') }
- let!(:label) { create(:label, project: project) }
- let!(:list1) { create(:list, board: board, label: planning, position: 0) }
- let!(:list2) { create(:list, board: board, label: label, position: 1) }
- let!(:issue) { create(:issue, project: project, title: 'abc', description: 'def') }
- let!(:issue2) { create(:issue, project: project, title: 'hij', description: 'klm') }
-
- before do
- project.add_maintainer(user)
-
- sign_in(user)
-
- visit project_board_path(project, board)
- wait_for_requests
- end
-
- it 'resets filtered search state' do
- visit project_board_path(project, board, search: 'testing')
-
- wait_for_requests
-
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- expect(find('.form-control').value).to eq('')
- expect(page).to have_selector('.clear-search', visible: false)
- expect(find('.form-control')[:placeholder]).to eq('Search or filter results...')
- end
- end
-
- context 'modal interaction' do
- before do
- stub_feature_flags(add_issues_button: true)
- end
-
- it 'opens modal' do
- click_button('Add issues')
-
- expect(page).to have_selector('.add-issues-modal')
- end
-
- it 'closes modal' do
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- find('.close').click
- end
-
- expect(page).not_to have_selector('.add-issues-modal')
- end
-
- it 'closes modal if cancel button clicked' do
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- click_button 'Cancel'
- end
-
- expect(page).not_to have_selector('.add-issues-modal')
- end
-
- it 'does not show tooltip on add issues button' do
- button = page.find('.filter-dropdown-container button', text: 'Add issues')
-
- expect(button[:title]).not_to eq("Please add a list to your board first")
- end
- end
-
- context 'issues list' do
- before do
- stub_feature_flags(add_issues_button: true)
- click_button('Add issues')
-
- wait_for_requests
- end
-
- it 'loads issues' do
- page.within('.add-issues-modal') do
- page.within('.gl-tabs') do
- expect(page).to have_content('2')
- end
-
- expect(page).to have_selector('.board-card', count: 2)
- end
- end
-
- it 'shows selected issues tab and empty state message' do
- page.within('.add-issues-modal') do
- click_link 'Selected issues'
-
- expect(page).not_to have_selector('.board-card')
- expect(page).to have_content("Go back to Open issues and select some issues to add to your board.")
- end
- end
-
- context 'list dropdown' do
- it 'resets after deleting list' do
- page.within('.add-issues-modal') do
- expect(find('.add-issues-footer')).to have_button(planning.title)
-
- click_button 'Cancel'
- end
-
- page.within(find('.board:nth-child(2)')) do
- find('button[title="List settings"]').click
- end
-
- page.within(find('.js-board-settings-sidebar')) do
- accept_confirm { find('[data-testid="remove-list"]').click }
- end
-
- click_button('Add issues')
-
- wait_for_requests
-
- page.within('.add-issues-modal') do
- expect(find('.add-issues-footer')).not_to have_button(planning.title)
- expect(find('.add-issues-footer')).to have_button(label.title)
- end
- end
- end
-
- context 'search' do
- it 'returns issues' do
- page.within('.add-issues-modal') do
- find('.form-control').native.send_keys(issue.title)
- find('.form-control').native.send_keys(:enter)
-
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'returns no issues' do
- page.within('.add-issues-modal') do
- find('.form-control').native.send_keys('testing search')
- find('.form-control').native.send_keys(:enter)
-
- wait_for_requests
-
- expect(page).not_to have_selector('.board-card')
- expect(page).not_to have_content("You haven't added any issues to your project yet")
- end
- end
- end
-
- context 'selecting issues' do
- it 'selects single issue' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- page.within('.gl-tabs') do
- expect(page).to have_content('Selected issues 1')
- end
- end
- end
-
- it 'changes button text' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- expect(first('.add-issues-footer .btn')).to have_content('Add 1 issue')
- end
- end
-
- it 'changes button text with plural' do
- page.within('.add-issues-modal') do
- all('.board-card .js-board-card-number-container').each do |el|
- el.click
- end
-
- expect(first('.add-issues-footer .btn')).to have_content('Add 2 issues')
- end
- end
-
- it 'shows only selected issues on selected tab' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_link 'Selected issues'
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'selects all issues' do
- page.within('.add-issues-modal') do
- click_button 'Select all'
-
- expect(page).to have_selector('.is-active', count: 2)
- end
- end
-
- it 'deselects all issues' do
- page.within('.add-issues-modal') do
- click_button 'Select all'
-
- expect(page).to have_selector('.is-active', count: 2)
-
- click_button 'Deselect all'
-
- expect(page).not_to have_selector('.is-active')
- end
- end
-
- it "selects all that aren't already selected" do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- expect(page).to have_selector('.is-active', count: 1)
-
- click_button 'Select all'
-
- expect(page).to have_selector('.is-active', count: 2)
- end
- end
-
- it 'unselects from selected tab' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_link 'Selected issues'
-
- first('.board-card .board-card-number').click
-
- expect(page).not_to have_selector('.is-active')
- end
- end
- end
-
- context 'adding issues' do
- it 'adds to board' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_button 'Add 1 issue'
- end
-
- page.within(find('.board:nth-child(2)')) do
- expect(page).to have_selector('.board-card')
- end
- end
-
- it 'adds to second list' do
- page.within('.add-issues-modal') do
- first('.board-card .board-card-number').click
-
- click_button planning.title
-
- click_link label.title
-
- click_button 'Add 1 issue'
- end
-
- page.within(find('.board:nth-child(3)')) do
- expect(page).to have_selector('.board-card')
- end
- end
- end
- end
-end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index 2392f9d2f8a..ab544022bff 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Issue Boards', :js do
+RSpec.describe 'Project issue boards', :js do
include DragTo
include MobileHelpers
@@ -23,7 +23,7 @@ RSpec.describe 'Issue Boards', :js do
context 'no lists' do
before do
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
end
it 'creates default lists' do
@@ -52,6 +52,7 @@ RSpec.describe 'Issue Boards', :js do
let_it_be(:a_plus) { create(:label, project: project, name: 'A+') }
let_it_be(:list1) { create(:list, board: board, label: planning, position: 0) }
let_it_be(:list2) { create(:list, board: board, label: development, position: 1) }
+ let_it_be(:backlog_list) { create(:backlog_list, board: board) }
let_it_be(:confidential_issue) { create(:labeled_issue, :confidential, project: project, author: user, labels: [planning], relative_position: 9) }
let_it_be(:issue1) { create(:labeled_issue, project: project, title: 'aaa', description: '111', assignees: [user], labels: [planning], relative_position: 8) }
@@ -68,7 +69,7 @@ RSpec.describe 'Issue Boards', :js do
before do
stub_feature_flags(board_new_list: false)
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
wait_for_requests
@@ -121,7 +122,8 @@ RSpec.describe 'Issue Boards', :js do
context 'with the NOT queries feature flag disabled' do
before do
stub_feature_flags(not_issuable_queries: false)
- visit project_board_path(project, board)
+
+ visit_project_board_path_without_query_limit(project, board)
end
it 'does not have the != option' do
@@ -141,7 +143,8 @@ RSpec.describe 'Issue Boards', :js do
context 'with the NOT queries feature flag enabled' do
before do
stub_feature_flags(not_issuable_queries: true)
- visit project_board_path(project, board)
+
+ visit_project_board_path_without_query_limit(project, board)
end
it 'does not have the != option' do
@@ -171,8 +174,7 @@ RSpec.describe 'Issue Boards', :js do
it 'infinite scrolls list' do
create_list(:labeled_issue, 50, project: project, labels: [planning])
- visit project_board_path(project, board)
- wait_for_requests
+ visit_project_board_path_without_query_limit(project, board)
page.within(find('.board:nth-child(2)')) do
expect(page.find('.board-header')).to have_content('58')
@@ -180,15 +182,19 @@ RSpec.describe 'Issue Boards', :js do
expect(page).to have_content('Showing 20 of 58 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
- wait_for_requests
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 40)
expect(page).to have_content('Showing 40 of 58 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
- wait_for_requests
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 58)
expect(page).to have_content('Showing all issues')
@@ -236,13 +242,13 @@ RSpec.describe 'Issue Boards', :js do
wait_for_board_cards(4, 1)
expect(find('.board:nth-child(2)')).to have_content(development.title)
- expect(find('.board:nth-child(2)')).to have_content(planning.title)
+ expect(find('.board:nth-child(3)')).to have_content(planning.title)
# Make sure list positions are preserved after a reload
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
expect(find('.board:nth-child(2)')).to have_content(development.title)
- expect(find('.board:nth-child(2)')).to have_content(planning.title)
+ expect(find('.board:nth-child(3)')).to have_content(planning.title)
end
it 'dragging does not duplicate list' do
@@ -254,7 +260,8 @@ RSpec.describe 'Issue Boards', :js do
expect(page).to have_selector(selector, text: development.title, count: 1)
end
- it 'issue moves between lists and does not show the "Development" label since the card is in the "Development" list label' do
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/323551
+ xit 'issue moves between lists and does not show the "Development" label since the card is in the "Development" list label' do
drag(list_from_index: 1, from_index: 1, list_to_index: 2)
wait_for_board_cards(2, 7)
@@ -467,14 +474,16 @@ RSpec.describe 'Issue Boards', :js do
end
it 'removes filtered labels' do
- set_filter("label", testing.title)
- click_filter_link(testing.title)
- submit_filter
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ set_filter("label", testing.title)
+ click_filter_link(testing.title)
+ submit_filter
- wait_for_board_cards(2, 1)
+ wait_for_board_cards(2, 1)
- find('.clear-search').click
- submit_filter
+ find('.clear-search').click
+ submit_filter
+ end
wait_for_board_cards(2, 8)
end
@@ -484,7 +493,9 @@ RSpec.describe 'Issue Boards', :js do
set_filter("label", testing.title)
click_filter_link(testing.title)
- submit_filter
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ submit_filter
+ end
wait_for_requests
@@ -494,13 +505,18 @@ RSpec.describe 'Issue Boards', :js do
expect(page).to have_content('Showing 20 of 51 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 40)
expect(page).to have_content('Showing 40 of 51 issues')
find('.board .board-list')
- evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
+ end
expect(page).to have_selector('.board-card', count: 51)
expect(page).to have_content('Showing all issues')
@@ -569,7 +585,7 @@ RSpec.describe 'Issue Boards', :js do
context 'keyboard shortcuts' do
before do
- visit project_board_path(project, board)
+ visit_project_board_path_without_query_limit(project, board)
wait_for_requests
end
@@ -617,15 +633,19 @@ RSpec.describe 'Issue Boards', :js do
def drag(selector: '.board-list', list_from_index: 0, from_index: 0, to_index: 0, list_to_index: 0, perform_drop: true)
# ensure there is enough horizontal space for four boards
- resize_window(2000, 800)
-
- drag_to(selector: selector,
- scrollable: '#board-app',
- list_from_index: list_from_index,
- from_index: from_index,
- to_index: to_index,
- list_to_index: list_to_index,
- perform_drop: perform_drop)
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ resize_window(2000, 800)
+
+ drag_to(selector: selector,
+ scrollable: '#board-app',
+ list_from_index: list_from_index,
+ from_index: from_index,
+ to_index: to_index,
+ list_to_index: list_to_index,
+ perform_drop: perform_drop)
+ end
+
+ wait_for_requests
end
def wait_for_board_cards(board_number, expected_cards)
@@ -666,4 +686,10 @@ RSpec.describe 'Issue Boards', :js do
accept_confirm { find('[data-testid="remove-list"]').click }
end
end
+
+ def visit_project_board_path_without_query_limit(project, board)
+ inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ visit project_board_path(project, board)
+ end
+ end
end
diff --git a/spec/features/boards/focus_mode_spec.rb b/spec/features/boards/focus_mode_spec.rb
index b1684ad69a6..2bd1e625236 100644
--- a/spec/features/boards/focus_mode_spec.rb
+++ b/spec/features/boards/focus_mode_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Issue Boards focus mode', :js do
wait_for_requests
end
- it 'shows focus mode button to guest users' do
- expect(page).to have_selector('.board-extra-actions .js-focus-mode-btn')
+ it 'shows focus mode button to anonymous users' do
+ expect(page).to have_selector('.js-focus-mode-btn')
end
end
diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb
deleted file mode 100644
index 5aeb9eb5e50..00000000000
--- a/spec/features/boards/modal_filter_spec.rb
+++ /dev/null
@@ -1,228 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Issue Boards add issue modal filtering', :js do
- let(:project) { create(:project, :public) }
- let(:board) { create(:board, project: project) }
- let(:planning) { create(:label, project: project, name: 'Planning') }
- let!(:list1) { create(:list, board: board, label: planning, position: 0) }
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let!(:issue1) { create(:issue, project: project) }
-
- before do
- project.add_maintainer(user)
-
- sign_in(user)
- end
-
- it 'shows empty state when no results found' do
- visit_board
-
- page.within('.add-issues-modal') do
- find('.form-control').native.send_keys('testing empty state')
- find('.form-control').native.send_keys(:enter)
-
- wait_for_requests
-
- expect(page).to have_content('There are no issues to show.')
- end
- end
-
- it 'restores filters when closing' do
- visit_board
-
- set_filter('milestone')
- click_filter_link('Upcoming')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 0)
-
- click_button 'Cancel'
- end
-
- click_button('Add issues')
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'resotres filters after clicking clear button' do
- visit_board
-
- set_filter('milestone')
- click_filter_link('Upcoming')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 0)
-
- find('.clear-search').click
-
- wait_for_requests
-
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- context 'author' do
- let!(:issue) { create(:issue, project: project, author: user2) }
-
- before do
- project.add_developer(user2)
-
- visit_board
- end
-
- it 'filters by selected user' do
- set_filter('author')
- click_filter_link(user2.name)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: user2.name)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- context 'assignee' do
- let!(:issue) { create(:issue, project: project, assignees: [user2]) }
-
- before do
- project.add_developer(user2)
-
- visit_board
- end
-
- it 'filters by unassigned' do
- set_filter('assignee')
- click_filter_link('None')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: 'None')
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'filters by selected user' do
- set_filter('assignee')
- click_filter_link(user2.name)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: user2.name)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- context 'milestone' do
- let(:milestone) { create(:milestone, project: project) }
- let!(:issue) { create(:issue, project: project, milestone: milestone) }
-
- before do
- visit_board
- end
-
- it 'filters by upcoming milestone' do
- set_filter('milestone')
- click_filter_link('Upcoming')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: 'Upcoming')
- expect(page).to have_selector('.board-card', count: 0)
- end
- end
-
- it 'filters by selected milestone' do
- set_filter('milestone')
- click_filter_link(milestone.name)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: milestone.name)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- context 'label' do
- let(:label) { create(:label, project: project) }
- let!(:issue) { create(:labeled_issue, project: project, labels: [label]) }
-
- before do
- visit_board
- end
-
- it 'filters by no label' do
- set_filter('label')
- click_filter_link('None')
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: 'None')
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
-
- it 'filters by label' do
- set_filter('label')
- click_filter_link(label.title)
- submit_filter
-
- page.within('.add-issues-modal') do
- wait_for_requests
-
- expect(page).to have_selector('.js-visual-token', text: label.title)
- expect(page).to have_selector('.board-card', count: 1)
- end
- end
- end
-
- def visit_board
- visit project_board_path(project, board)
- wait_for_requests
-
- click_button('Add issues')
- end
-
- def set_filter(type, text = '')
- find('.add-issues-modal .filtered-search').native.send_keys("#{type}:=#{text}")
- end
-
- def submit_filter
- find('.add-issues-modal .filtered-search').native.send_keys(:enter)
- end
-
- def click_filter_link(link_text)
- page.within('.add-issues-modal .filtered-search-box') do
- expect(page).to have_button(link_text)
-
- click_button(link_text)
- end
- end
-end
diff --git a/spec/features/boards/multi_select_spec.rb b/spec/features/boards/multi_select_spec.rb
index 162455f75e6..ca322355b8f 100644
--- a/spec/features/boards/multi_select_spec.rb
+++ b/spec/features/boards/multi_select_spec.rb
@@ -41,6 +41,10 @@ RSpec.describe 'Multi Select Issue', :js do
before do
project.add_maintainer(user)
+ # multi-drag disabled with feature flag for now
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/289797
+ stub_feature_flags(graphql_board_lists: false)
+
sign_in(user)
end
diff --git a/spec/features/boards/multiple_boards_spec.rb b/spec/features/boards/multiple_boards_spec.rb
index 2894d5c7666..219f24f60d7 100644
--- a/spec/features/boards/multiple_boards_spec.rb
+++ b/spec/features/boards/multiple_boards_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'Multiple Issue Boards', :js do
let_it_be(:planning) { create(:label, project: project, name: 'Planning') }
let_it_be(:board) { create(:board, name: 'board1', project: project) }
let_it_be(:board2) { create(:board, name: 'board2', project: project) }
+
let(:parent) { project }
let(:boards_path) { project_boards_path(project) }
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index f434ea0c66f..20ae569322c 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -3,10 +3,12 @@
require 'spec_helper'
RSpec.describe 'Issue Boards new issue', :js do
- let(:project) { create(:project, :public) }
- let(:board) { create(:board, project: project) }
- let!(:list) { create(:list, board: board, position: 0) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:backlog_list) { create(:backlog_list, board: board) }
+ let_it_be(:label) { create(:label, project: project, name: 'Label 1') }
+ let_it_be(:list) { create(:list, board: board, label: label, position: 0) }
+ let_it_be(:user) { create(:user) }
context 'authorized user' do
before do
@@ -15,6 +17,7 @@ RSpec.describe 'Issue Boards new issue', :js do
sign_in(user)
visit project_board_path(project, board)
+
wait_for_requests
expect(page).to have_selector('.board', count: 3)
@@ -57,7 +60,7 @@ RSpec.describe 'Issue Boards new issue', :js do
page.within(first('.board-new-issue-form')) do
find('.form-control').set('bug')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
@@ -70,23 +73,24 @@ RSpec.describe 'Issue Boards new issue', :js do
issue = project.issues.find_by_title('bug')
expect(page).to have_content(issue.to_reference)
- expect(page).to have_link(issue.title, href: issue_path(issue))
+ expect(page).to have_link(issue.title, href: /#{issue_path(issue)}/)
end
end
- it 'shows sidebar when creating new issue' do
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/323446
+ xit 'shows sidebar when creating new issue' do
page.within(first('.board')) do
find('.issue-count-badge-add-button').click
end
page.within(first('.board-new-issue-form')) do
find('.form-control').set('bug')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
- expect(page).to have_selector('.issue-boards-sidebar')
+ expect(page).to have_selector('[data-testid="issue-boards-sidebar"]')
end
it 'successfuly loads labels to be added to newly created issue' do
@@ -96,17 +100,21 @@ RSpec.describe 'Issue Boards new issue', :js do
page.within(first('.board-new-issue-form')) do
find('.form-control').set('new issue')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
- page.within(first('.issue-boards-sidebar')) do
- find('.labels .edit-link').click
+ page.within(first('.board')) do
+ find('.board-card').click
+ end
+
+ page.within(first('[data-testid="issue-boards-sidebar"]')) do
+ find('.labels [data-testid="edit-button"]').click
wait_for_requests
- expect(page).to have_selector('.labels .dropdown-content li a')
+ expect(page).to have_selector('.labels-select-contents-list .dropdown-content li a')
end
end
end
diff --git a/spec/features/boards/reload_boards_on_browser_back_spec.rb b/spec/features/boards/reload_boards_on_browser_back_spec.rb
index 181cbcc9811..36682036d48 100644
--- a/spec/features/boards/reload_boards_on_browser_back_spec.rb
+++ b/spec/features/boards/reload_boards_on_browser_back_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
fill_in 'issue_title', with: 'issue should be shown'
- click_button 'Submit issue'
+ click_button 'Create issue'
page.go_back
wait_for_requests
@@ -43,7 +43,7 @@ RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
issue = project.issues.find_by_title('issue should be shown')
expect(page).to have_content(issue.to_reference)
- expect(page).to have_link(issue.title, href: issue_path(issue))
+ expect(page).to have_link(issue.title, href: /#{issue_path(issue)}/)
end
end
end
diff --git a/spec/features/boards/sidebar_assignee_spec.rb b/spec/features/boards/sidebar_assignee_spec.rb
new file mode 100644
index 00000000000..e938612163f
--- /dev/null
+++ b/spec/features/boards/sidebar_assignee_spec.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar assignee', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:development) { create(:label, project: project, name: 'Development') }
+ let_it_be(:regression) { create(:label, project: project, name: 'Regression') }
+ let_it_be(:stretch) { create(:label, project: project, name: 'Stretch') }
+
+ let!(:issue1) { create(:labeled_issue, project: project, assignees: [user], labels: [development], relative_position: 2) }
+ let!(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
+ let(:board) { create(:board, project: project) }
+ let!(:list) { create(:list, board: board, label: development, position: 0) }
+ let(:card) { find('.board:nth-child(2)').first('.board-card') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'assignee' do
+ it 'updates the issues assignee' do
+ click_card(card)
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ wait_for_requests
+
+ assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
+
+ page.within('.dropdown-menu-user') do
+ first('.gl-avatar-labeled').click
+ end
+
+ click_button('Apply')
+ wait_for_requests
+
+ expect(page).to have_content(assignee)
+ end
+
+ expect(card).to have_selector('.avatar')
+ end
+
+ it 'removes the assignee' do
+ card_two = find('.board:nth-child(2)').find('.board-card:nth-child(2)')
+ click_card(card_two)
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ wait_for_requests
+
+ page.within('.dropdown-menu-user') do
+ find('[data-testid="unassign"]').click
+ end
+
+ click_button('Apply')
+ wait_for_requests
+
+ expect(page).to have_content('None')
+ end
+
+ expect(card_two).not_to have_selector('.avatar')
+ end
+
+ it 'assignees to current user' do
+ click_card(card)
+
+ page.within(find('.assignee')) do
+ expect(page).to have_content('None')
+
+ click_button 'assign yourself'
+
+ wait_for_requests
+
+ expect(page).to have_content(user.name)
+ end
+
+ expect(card).to have_selector('.avatar')
+ end
+
+ it 'updates assignee dropdown' do
+ click_card(card)
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ wait_for_requests
+
+ assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
+
+ page.within('.dropdown-menu-user') do
+ first('.gl-avatar-labeled').click
+ end
+
+ click_button('Apply')
+ wait_for_requests
+
+ expect(page).to have_content(assignee)
+ end
+
+ page.within(find('.board:nth-child(2)')) do
+ find('.board-card:nth-child(2)').click
+ end
+
+ page.within('.assignee') do
+ click_button('Edit')
+
+ expect(find('.dropdown-menu')).to have_selector('.gl-new-dropdown-item-check-icon')
+ end
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_due_date_spec.rb b/spec/features/boards/sidebar_due_date_spec.rb
new file mode 100644
index 00000000000..141c574ffec
--- /dev/null
+++ b/spec/features/boards/sidebar_due_date_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar due date', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project, relative_position: 1) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
+
+ let(:card) { find('.board:nth-child(1)').first('.board-card') }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'due date' do
+ it 'updates due date' do
+ click_card(card)
+
+ page.within('[data-testid="sidebar-due-date"]') do
+ today = Date.today.day
+
+ click_button 'Edit'
+
+ click_button today.to_s
+
+ wait_for_requests
+
+ expect(page).to have_content(today.to_s(:medium))
+ end
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_labels_spec.rb b/spec/features/boards/sidebar_labels_spec.rb
new file mode 100644
index 00000000000..2f0230c61d8
--- /dev/null
+++ b/spec/features/boards/sidebar_labels_spec.rb
@@ -0,0 +1,166 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar labels', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:development) { create(:label, project: project, name: 'Development') }
+ let_it_be(:bug) { create(:label, project: project, name: 'Bug') }
+ let_it_be(:regression) { create(:label, project: project, name: 'Regression') }
+ let_it_be(:stretch) { create(:label, project: project, name: 'Stretch') }
+ let_it_be(:issue1) { create(:labeled_issue, project: project, labels: [development], relative_position: 2) }
+ let_it_be(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, label: development, position: 0) }
+
+ let(:card) { find('.board:nth-child(2)').first('.board-card') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'labels' do
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/322725
+ xit 'shows current labels when editing' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_link 'Edit'
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 2)
+ expect(page).to have_content(development.title)
+ expect(page).to have_content(stretch.title)
+ end
+ end
+ end
+
+ it 'adds a single label' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_link bug.title
+
+ find('[data-testid="close-icon"]').click
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 3)
+ expect(page).to have_content(bug.title)
+ end
+ end
+
+ # 'Development' label does not show since the card is in a 'Development' list label
+ expect(card).to have_selector('.gl-label', count: 2)
+ expect(card).to have_content(bug.title)
+ end
+
+ it 'adds a multiple labels' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_link bug.title
+
+ click_link regression.title
+
+ find('[data-testid="close-icon"]').click
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 4)
+ expect(page).to have_content(bug.title)
+ expect(page).to have_content(regression.title)
+ end
+ end
+
+ # 'Development' label does not show since the card is in a 'Development' list label
+ expect(card).to have_selector('.gl-label', count: 3)
+ expect(card).to have_content(bug.title)
+ expect(card).to have_content(regression.title)
+ end
+
+ it 'removes a label' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_link stretch.title
+
+ find('[data-testid="close-icon"]').click
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_selector('.gl-label-text', count: 1)
+ expect(page).not_to have_content(stretch.title)
+ end
+ end
+
+ # 'Development' label does not show since the card is in a 'Development' list label
+ expect(card).to have_selector('.gl-label-text', count: 0)
+ expect(card).not_to have_content(stretch.title)
+ end
+
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/324290
+ xit 'creates project label' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_link 'Edit'
+ wait_for_requests
+
+ click_link 'Create project label'
+ fill_in 'new_label_name', with: 'test label'
+ first('.suggest-colors-dropdown a').click
+ click_button 'Create'
+ wait_for_requests
+
+ expect(page).to have_link 'test label'
+ end
+ expect(page).to have_selector('.board', count: 3)
+ end
+
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/324290
+ xit 'creates project label and list' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_link 'Edit'
+ wait_for_requests
+
+ click_link 'Create project label'
+ fill_in 'new_label_name', with: 'test label'
+ first('.suggest-colors-dropdown a').click
+ first('.js-add-list').click
+ click_button 'Create'
+ wait_for_requests
+
+ expect(page).to have_link 'test label'
+ end
+ expect(page).to have_selector('.board', count: 4)
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_milestones_spec.rb b/spec/features/boards/sidebar_milestones_spec.rb
new file mode 100644
index 00000000000..54182781a30
--- /dev/null
+++ b/spec/features/boards/sidebar_milestones_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project issue boards sidebar milestones', :js do
+ include BoardHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:issue1) { create(:issue, project: project, relative_position: 1) }
+ let_it_be(:issue2) { create(:issue, project: project, milestone: milestone, relative_position: 2) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
+
+ let(:card1) { find('.board:nth-child(1) .board-card:nth-of-type(1)') }
+ let(:card2) { find('.board:nth-child(1) .board-card:nth-of-type(2)') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+
+ context 'milestone' do
+ it 'adds a milestone' do
+ click_card(card1)
+
+ page.within('[data-testid="sidebar-milestones"]') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_button milestone.title
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).to have_content(milestone.title)
+ end
+ end
+ end
+
+ it 'removes a milestone' do
+ click_card(card2)
+
+ page.within('[data-testid="sidebar-milestones"]') do
+ click_button 'Edit'
+
+ wait_for_requests
+
+ click_button "No milestone"
+
+ wait_for_requests
+
+ page.within('.value') do
+ expect(page).not_to have_content(milestone.title)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index c79bf2abff1..977147c3c6b 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -2,412 +2,33 @@
require 'spec_helper'
-RSpec.describe 'Issue Boards', :js do
+RSpec.describe 'Project issue boards sidebar', :js do
include BoardHelpers
- include FilteredSearchHelpers
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let(:project) { create(:project, :public) }
- let!(:milestone) { create(:milestone, project: project) }
- let!(:development) { create(:label, project: project, name: 'Development') }
- let!(:bug) { create(:label, project: project, name: 'Bug') }
- let!(:regression) { create(:label, project: project, name: 'Regression') }
- let!(:stretch) { create(:label, project: project, name: 'Stretch') }
- let!(:issue1) { create(:labeled_issue, project: project, assignees: [user], milestone: milestone, labels: [development], relative_position: 2) }
- let!(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
- let(:board) { create(:board, project: project) }
- let!(:list) { create(:list, board: board, label: development, position: 0) }
- let(:card) { find('.board:nth-child(2)').first('.board-card') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:list) { create(:list, board: board, position: 0) }
- let(:application_settings) { {} }
-
- around do |example|
- freeze_time { example.run }
- end
+ let_it_be(:issue, reload: true) { create(:issue, project: project, relative_position: 1) }
before do
project.add_maintainer(user)
sign_in(user)
- stub_application_setting(application_settings)
-
visit project_board_path(project, board)
- wait_for_requests
- end
-
- it 'shows sidebar when clicking issue' do
- click_card(card)
-
- expect(page).to have_selector('.issue-boards-sidebar')
- end
-
- it 'closes sidebar when clicking issue' do
- click_card(card)
-
- expect(page).to have_selector('.issue-boards-sidebar')
-
- click_card(card)
-
- expect(page).not_to have_selector('.issue-boards-sidebar')
- end
-
- it 'closes sidebar when clicking close button' do
- click_card(card)
-
- expect(page).to have_selector('.issue-boards-sidebar')
-
- find('.gutter-toggle').click
-
- expect(page).not_to have_selector('.issue-boards-sidebar')
- end
-
- it 'shows issue details when sidebar is open' do
- click_card(card)
-
- page.within('.issue-boards-sidebar') do
- expect(page).to have_content(issue2.title)
- expect(page).to have_content(issue2.to_reference)
- end
- end
-
- context 'assignee' do
- it 'updates the issues assignee' do
- click_card(card)
-
- page.within('.assignee') do
- click_button('Edit')
-
- wait_for_requests
-
- assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
-
- page.within('.dropdown-menu-user') do
- first('.gl-avatar-labeled').click
- end
-
- click_button('Edit')
- wait_for_requests
-
- expect(page).to have_content(assignee)
- end
-
- expect(card).to have_selector('.avatar')
- end
-
- it 'removes the assignee' do
- card_two = find('.board:nth-child(2)').find('.board-card:nth-child(2)')
- click_card(card_two)
-
- page.within('.assignee') do
- click_button('Edit')
-
- wait_for_requests
-
- page.within('.dropdown-menu-user') do
- find('[data-testid="unassign"]').click
- end
-
- click_button('Edit')
- wait_for_requests
-
- expect(page).to have_content('None')
- end
-
- expect(card_two).not_to have_selector('.avatar')
- end
-
- it 'assignees to current user' do
- click_card(card)
-
- page.within(find('.assignee')) do
- expect(page).to have_content('None')
-
- click_button 'assign yourself'
-
- wait_for_requests
-
- expect(page).to have_content(user.name)
- end
-
- expect(card).to have_selector('.avatar')
- end
-
- it 'updates assignee dropdown' do
- click_card(card)
-
- page.within('.assignee') do
- click_button('Edit')
-
- wait_for_requests
-
- assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
-
- page.within('.dropdown-menu-user') do
- first('.gl-avatar-labeled').click
- end
-
- click_button('Edit')
- wait_for_requests
-
- expect(page).to have_content(assignee)
- end
-
- page.within(find('.board:nth-child(2)')) do
- find('.board-card:nth-child(2)').click
- end
-
- page.within('.assignee') do
- click_button('Edit')
-
- expect(find('.dropdown-menu')).to have_selector('.gl-new-dropdown-item-check-icon')
- end
- end
- end
-
- context 'milestone' do
- it 'adds a milestone' do
- click_card(card)
-
- page.within('.milestone') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link milestone.title
-
- wait_for_requests
-
- page.within('.value') do
- expect(page).to have_content(milestone.title)
- end
- end
- end
-
- it 'removes a milestone' do
- click_card(card)
- page.within('.milestone') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link "No milestone"
-
- wait_for_requests
-
- page.within('.value') do
- expect(page).not_to have_content(milestone.title)
- end
- end
- end
- end
-
- context 'time tracking' do
- let(:compare_meter_tooltip) { find('.time-tracking .time-tracking-content .compare-meter')['title'] }
-
- before do
- issue2.timelogs.create(time_spent: 14400, user: user)
- issue2.update!(time_estimate: 128800)
-
- click_card(card)
- end
-
- it 'shows time tracking progress bar' do
- expect(compare_meter_tooltip).to eq('Time remaining: 3d 7h 46m')
- end
-
- context 'when time_tracking_limit_to_hours is true' do
- let(:application_settings) { { time_tracking_limit_to_hours: true } }
-
- it 'shows time tracking progress bar' do
- expect(compare_meter_tooltip).to eq('Time remaining: 31h 46m')
- end
- end
- end
-
- context 'due date' do
- it 'updates due date' do
- click_card(card)
-
- page.within('.due_date') do
- click_link 'Edit'
-
- click_button Date.today.day
-
- wait_for_requests
-
- expect(page).to have_content(Date.today.to_s(:medium))
- end
- end
+ wait_for_requests
end
- context 'labels' do
- it 'shows current labels when editing' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 2)
- expect(page).to have_content(development.title)
- expect(page).to have_content(stretch.title)
- end
- end
- end
-
- it 'adds a single label' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link bug.title
-
- wait_for_requests
-
- find('.dropdown-menu-close-icon').click
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 3)
- expect(page).to have_content(bug.title)
- end
- end
-
- # 'Development' label does not show since the card is in a 'Development' list label
- expect(card).to have_selector('.gl-label', count: 2)
- expect(card).to have_content(bug.title)
- end
-
- it 'adds a multiple labels' do
- click_card(card)
+ it_behaves_like 'issue boards sidebar'
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- click_link bug.title
-
- wait_for_requests
-
- click_link regression.title
-
- wait_for_requests
-
- find('.dropdown-menu-close-icon').click
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 4)
- expect(page).to have_content(bug.title)
- expect(page).to have_content(regression.title)
- end
- end
-
- # 'Development' label does not show since the card is in a 'Development' list label
- expect(card).to have_selector('.gl-label', count: 3)
- expect(card).to have_content(bug.title)
- expect(card).to have_content(regression.title)
- end
-
- it 'removes a label' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
-
- wait_for_requests
-
- within('.dropdown-menu-labels') do
- click_link stretch.title
- end
-
- wait_for_requests
-
- find('.dropdown-menu-close-icon').click
-
- page.within('.value') do
- expect(page).to have_selector('.gl-label-text', count: 1)
- expect(page).not_to have_content(stretch.title)
- end
- end
-
- # 'Development' label does not show since the card is in a 'Development' list label
- expect(card).to have_selector('.gl-label-text', count: 0)
- expect(card).not_to have_content(stretch.title)
- end
-
- it 'creates project label' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
- wait_for_requests
-
- click_link 'Create project label'
- fill_in 'new_label_name', with: 'test label'
- first('.suggest-colors-dropdown a').click
- click_button 'Create'
- wait_for_requests
-
- expect(page).to have_link 'test label'
- end
- expect(page).to have_selector('.board', count: 3)
- end
-
- it 'creates project label and list' do
- click_card(card)
-
- page.within('.labels') do
- click_link 'Edit'
- wait_for_requests
-
- click_link 'Create project label'
- fill_in 'new_label_name', with: 'test label'
- first('.suggest-colors-dropdown a').click
- first('.js-add-list').click
- click_button 'Create'
- wait_for_requests
-
- expect(page).to have_link 'test label'
- end
- expect(page).to have_selector('.board', count: 4)
- end
+ def first_card
+ find('.board:nth-child(1)').first("[data-testid='board_card']")
end
- context 'subscription' do
- it 'changes issue subscription' do
- click_card(card)
- wait_for_requests
-
- page.within('.subscriptions') do
- find('[data-testid="subscription-toggle"] button:not(.is-checked)').click
- wait_for_requests
-
- expect(page).to have_css('[data-testid="subscription-toggle"] button.is-checked')
- end
- end
-
- it 'has checked subscription toggle when already subscribed' do
- create(:subscription, user: user, project: project, subscribable: issue2, subscribed: true)
- visit project_board_path(project, board)
- wait_for_requests
-
- click_card(card)
- wait_for_requests
-
- page.within('.subscriptions') do
- find('[data-testid="subscription-toggle"] button.is-checked').click
- wait_for_requests
-
- expect(page).to have_css('[data-testid="subscription-toggle"] button:not(.is-checked)')
- end
- end
+ def click_first_issue_card
+ click_card(first_card)
end
end
diff --git a/spec/features/boards/sub_group_project_spec.rb b/spec/features/boards/sub_group_project_spec.rb
index cd3d61726f6..bde5f061a67 100644
--- a/spec/features/boards/sub_group_project_spec.rb
+++ b/spec/features/boards/sub_group_project_spec.rb
@@ -21,7 +21,8 @@ RSpec.describe 'Sub-group project issue boards', :js do
wait_for_requests
end
- it 'creates new label from sidebar' do
+ # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/324290
+ xit 'creates new label from sidebar' do
find('.board-card').click
page.within '.labels' do
diff --git a/spec/features/boards/user_adds_lists_to_board_spec.rb b/spec/features/boards/user_adds_lists_to_board_spec.rb
index b9945207bb2..5128fc4004e 100644
--- a/spec/features/boards/user_adds_lists_to_board_spec.rb
+++ b/spec/features/boards/user_adds_lists_to_board_spec.rb
@@ -71,10 +71,13 @@ RSpec.describe 'User adds lists', :js do
def select_label(board_new_list_enabled, label)
if board_new_list_enabled
- page.within('.board-add-new-list') do
- find('label', text: label.title).click
- click_button 'Add'
- end
+ click_button 'Select a label'
+
+ find('label', text: label.title).click
+
+ click_button 'Add to board'
+
+ wait_for_all_requests
else
page.within('.dropdown-menu-issues-board-new') do
click_link label.title
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index ee156bdcab4..0b73226268d 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe 'Contributions Calendar', :js do
"#{contributions} #{'contribution'.pluralize(contributions)}"
end
- "#{get_cell_color_selector(contributions)}[title='#{contribution_text}<br />#{date}']"
+ "#{get_cell_color_selector(contributions)}[title='#{contribution_text}<br /><span class=\"gl-text-gray-300\">#{date}</span>']"
end
def push_code_contribution
@@ -64,7 +64,7 @@ RSpec.describe 'Contributions Calendar', :js do
author_id: user.id
}
- Event.create(note_comment_params)
+ Event.create!(note_comment_params)
end
def selected_day_activities(visible: true)
diff --git a/spec/features/callouts/service_templates_deprecation_spec.rb b/spec/features/callouts/service_templates_deprecation_spec.rb
new file mode 100644
index 00000000000..b6403b54e29
--- /dev/null
+++ b/spec/features/callouts/service_templates_deprecation_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Service templates deprecation callout' do
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:non_admin) { create(:user) }
+ let_it_be(:callout_content) { 'Service templates are deprecated and will be removed in GitLab 14.0.' }
+
+ context 'when a non-admin is logged in' do
+ before do
+ sign_in(non_admin)
+ visit root_dashboard_path
+ end
+
+ it 'does not display callout' do
+ expect(page).not_to have_content callout_content
+ end
+ end
+
+ context 'when an admin is logged in' do
+ before do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+
+ visit root_dashboard_path
+ end
+
+ context 'with no active service templates' do
+ it 'does not display callout' do
+ expect(page).not_to have_content callout_content
+ end
+ end
+
+ context 'with active service template' do
+ before do
+ create(:service, :template, type: 'MattermostService', active: true)
+ visit root_dashboard_path
+ end
+
+ it 'displays callout' do
+ expect(page).to have_content callout_content
+ expect(page).to have_link 'See affected service templates', href: admin_application_settings_services_path
+ end
+
+ context 'when callout is dismissed', :js do
+ before do
+ find('[data-testid="close-service-templates-deprecated-callout"]').click
+
+ visit root_dashboard_path
+ end
+
+ it 'does not display callout' do
+ expect(page).not_to have_content callout_content
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb
index 6fe6c099d80..84a18a45d35 100644
--- a/spec/features/clusters/cluster_detail_page_spec.rb
+++ b/spec/features/clusters/cluster_detail_page_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'Clusterable > Show page' do
it 'allow the user to set domain', :js do
visit cluster_path
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
fill_in('cluster_base_domain', with: 'test.com')
click_on 'Save changes'
end
@@ -39,7 +39,7 @@ RSpec.describe 'Clusterable > Show page' do
end
it 'shows help text with the domain as an alternative to custom domain', :js do
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
expect(find(cluster_ingress_help_text_selector).text).to include('192.168.1.100')
end
end
@@ -49,7 +49,7 @@ RSpec.describe 'Clusterable > Show page' do
it 'alternative to custom domain is not shown' do
visit cluster_path
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
expect(page).not_to have_selector(cluster_ingress_help_text_selector)
end
end
diff --git a/spec/features/clusters/cluster_health_dashboard_spec.rb b/spec/features/clusters/cluster_health_dashboard_spec.rb
index e9e3b48e9c0..862f34768c4 100644
--- a/spec/features/clusters/cluster_health_dashboard_spec.rb
+++ b/spec/features/clusters/cluster_health_dashboard_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Cluster Health board', :js, :kubeclient, :use_clean_rails_memory
click_link 'Health'
- expect(page).to have_text('you must first install Prometheus in the Applications tab')
+ expect(page).to have_text('you must first enable Prometheus in the Integrations tab')
end
end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 1622979812d..2dafaedd262 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe 'Commits' do
context 'when accessing internal project with disallowed access', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/299575' do
before do
- project.update(
+ project.update!(
visibility_level: Gitlab::VisibilityLevel::INTERNAL,
public_builds: false)
create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
diff --git a/spec/features/dashboard/active_tab_spec.rb b/spec/features/dashboard/active_tab_spec.rb
index ee85c136190..3a532cb4161 100644
--- a/spec/features/dashboard/active_tab_spec.rb
+++ b/spec/features/dashboard/active_tab_spec.rb
@@ -4,6 +4,8 @@ require 'spec_helper'
RSpec.describe 'Dashboard Active Tab', :js do
before do
+ stub_feature_flags(combined_menu: false)
+
sign_in(create(:user))
end
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index c14a6001a3e..442b8904974 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Tooltips on .timeago dates', :js do
context 'on the activity tab' do
before do
- Event.create( project: project, author_id: user.id, action: :joined,
+ Event.create!( project: project, author_id: user.id, action: :joined,
updated_at: created_date, created_at: created_date)
sign_in user
diff --git a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
index c2a3b90b6f4..179d9d09905 100644
--- a/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
+++ b/spec/features/dashboard/group_dashboard_with_external_authorization_service_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'The group dashboard' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(combined_menu: false)
+
sign_in user
end
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index 3cb7140d253..d4c6b6faa79 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
before do
issue.assignees = [user]
- merge_request.update(assignees: [user])
+ merge_request.update!(assignees: [user])
sign_in(user)
end
@@ -35,7 +35,7 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
expect_counters('merge_requests', '1')
- merge_request.update(assignees: [])
+ merge_request.update!(assignees: [])
user.invalidate_cache_counts
diff --git a/spec/features/dashboard/milestones_spec.rb b/spec/features/dashboard/milestones_spec.rb
index 308432b7a1b..992ed2f2ce6 100644
--- a/spec/features/dashboard/milestones_spec.rb
+++ b/spec/features/dashboard/milestones_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Dashboard > Milestones' do
expect(current_path).to eq dashboard_milestones_path
expect(page).to have_content(milestone.title)
expect(page).to have_content(group.name)
- expect(first('.milestone')).to have_content('Merge Requests')
+ expect(first('.milestone')).to have_content('Merge requests')
end
describe 'new milestones dropdown', :js do
diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb
index 6e6e466294f..c26a1a0b486 100644
--- a/spec/features/dashboard/project_member_activity_index_spec.rb
+++ b/spec/features/dashboard/project_member_activity_index_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Project member activity', :js do
end
def visit_activities_and_wait_with_event(event_type)
- Event.create(project: project, author_id: user.id, action: event_type)
+ Event.create!(project: project, author_id: user.id, action: event_type)
visit activity_project_path(project)
wait_for_requests
end
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index d7330b5267b..20c753b1cdb 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Dashboard Projects' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, name: 'awesome stuff') }
- let(:project2) { create(:project, :public, name: 'Community project') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
+ let_it_be(:project2) { create(:project, :public) }
before do
project.add_developer(user)
@@ -18,17 +18,10 @@ RSpec.describe 'Dashboard Projects' do
end
end
- it 'shows the project the user in a member of in the list' do
- visit dashboard_projects_path
- expect(page).to have_content('awesome stuff')
- end
-
- it 'shows "New project" button' do
+ it 'shows the customize banner', :js do
visit dashboard_projects_path
- page.within '#content-body' do
- expect(page).to have_link('New project')
- end
+ expect(page).to have_content('Do you want to customize this page?')
end
context 'when user has access to the project' do
@@ -48,7 +41,7 @@ RSpec.describe 'Dashboard Projects' do
expect(page).to have_content('Developer')
end
- project.members.last.update(access_level: 40)
+ project.members.last.update!(access_level: 40)
visit dashboard_projects_path
@@ -153,7 +146,7 @@ RSpec.describe 'Dashboard Projects' do
end
describe 'with a pipeline', :clean_gitlab_redis_shared_state do
- let(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha, ref: project.default_branch) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha, ref: project.default_branch) }
before do
# Since the cache isn't updated when a new pipeline is created
@@ -190,7 +183,7 @@ RSpec.describe 'Dashboard Projects' do
let(:guest_user) { create(:user) }
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
project.add_guest(guest_user)
sign_in(guest_user)
end
diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb
index b2fda28f0ec..e96a60b2ab2 100644
--- a/spec/features/dashboard/shortcuts_spec.rb
+++ b/spec/features/dashboard/shortcuts_spec.rb
@@ -3,6 +3,10 @@
require 'spec_helper'
RSpec.describe 'Dashboard shortcuts', :js do
+ before do
+ stub_feature_flags(combined_menu: false)
+ end
+
context 'logged in' do
let(:user) { create(:user) }
let(:project) { create(:project) }
@@ -20,7 +24,7 @@ RSpec.describe 'Dashboard shortcuts', :js do
find('body').send_keys([:shift, 'M'])
- check_page_title('Merge Requests')
+ check_page_title('Merge requests')
find('body').send_keys([:shift, 'T'])
diff --git a/spec/features/discussion_comments/merge_request_spec.rb b/spec/features/discussion_comments/merge_request_spec.rb
index f60d7da6a30..a90ff3721d3 100644
--- a/spec/features/discussion_comments/merge_request_spec.rb
+++ b/spec/features/discussion_comments/merge_request_spec.rb
@@ -8,8 +8,6 @@ RSpec.describe 'Thread Comments Merge Request', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
before do
- stub_feature_flags(remove_resolve_note: false)
-
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/error_pages_spec.rb b/spec/features/error_pages_spec.rb
index 77f8aa87237..8dc9e5ade46 100644
--- a/spec/features/error_pages_spec.rb
+++ b/spec/features/error_pages_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Error Pages' do
+RSpec.describe 'Error Pages', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
@@ -14,7 +14,12 @@ RSpec.describe 'Error Pages' do
it 'shows nav links' do
expect(page).to have_link("Home", href: root_path)
expect(page).to have_link("Help", href: help_path)
- expect(page).to have_link(nil, href: destroy_user_session_path)
+ end
+
+ it 'allows user to sign out' do
+ click_link 'Sign out and sign in with a different account'
+
+ expect(page).to have_current_path(new_user_session_path)
end
end
diff --git a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
index a0d93b791d9..6846d8f6ade 100644
--- a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
+++ b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'When a user filters Sentry errors by status', :js, :use_clean_ra
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:filtered_errors_by_status_response) { Gitlab::Json.parse(issues_response_body).filter { |error| error['status'] == 'ignored' }.to_json }
+
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_filter) { "#{sentry_api_urls.issues_url}?limit=20&query=is:ignored" }
let(:auth_token) {{ 'Authorization' => 'Bearer access_token_123' }}
diff --git a/spec/features/error_tracking/user_searches_sentry_errors_spec.rb b/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
index 025a6261957..c16c9d3fb1f 100644
--- a/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
+++ b/spec/features/error_tracking/user_searches_sentry_errors_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'When a user searches for Sentry errors', :js, :use_clean_rails_m
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:error_search_response_body) { fixture_file('sentry/error_list_search_response.json') }
+
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_search) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved%20NotFound" }
diff --git a/spec/features/error_tracking/user_sees_error_index_spec.rb b/spec/features/error_tracking/user_sees_error_index_spec.rb
index a4b15432ef3..bc6709c659d 100644
--- a/spec/features/error_tracking/user_sees_error_index_spec.rb
+++ b/spec/features/error_tracking/user_sees_error_index_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:issues_response) { Gitlab::Json.parse(issues_response_body) }
+
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
before do
@@ -41,7 +42,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
context 'with error tracking settings disabled' do
before do
- project_error_tracking_settings.update(enabled: false)
+ project_error_tracking_settings.update!(enabled: false)
sign_in(project.owner)
visit project_error_tracking_index_path(project)
diff --git a/spec/features/file_uploads/attachment_spec.rb b/spec/features/file_uploads/attachment_spec.rb
new file mode 100644
index 00000000000..9ad404ce869
--- /dev/null
+++ b/spec/features/file_uploads/attachment_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload an attachment', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ let(:api_path) { "/projects/#{project_id}/uploads" }
+ let(:url) { capybara_url(api(api_path)) }
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ subject do
+ HTTParty.post(
+ url,
+ headers: { 'PRIVATE-TOKEN' => personal_access_token.token },
+ body: { file: file }
+ )
+ end
+
+ shared_examples 'for an attachment' do
+ it 'creates files' do
+ expect { subject }
+ .to change { Upload.count }.by(1)
+ end
+
+ it { expect(subject.code).to eq(201) }
+ end
+
+ context 'with an integer project ID' do
+ let(:project_id) { project.id }
+
+ it_behaves_like 'handling file uploads', 'for an attachment'
+ end
+
+ context 'with an encoded project ID' do
+ let(:project_id) { "#{project.namespace.path}%2F#{project.path}" }
+
+ it_behaves_like 'handling file uploads', 'for an attachment'
+ end
+end
diff --git a/spec/features/file_uploads/maven_package_spec.rb b/spec/features/file_uploads/maven_package_spec.rb
index e87eec58618..ab9f023bd8f 100644
--- a/spec/features/file_uploads/maven_package_spec.rb
+++ b/spec/features/file_uploads/maven_package_spec.rb
@@ -6,16 +6,17 @@ RSpec.describe 'Upload a maven package', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:user) { project.owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
- let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar" }
+ let(:project_id) { project.id }
+ let(:api_path) { "/projects/#{project_id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar" }
let(:url) { capybara_url(api(api_path, personal_access_token: personal_access_token)) }
let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
subject { HTTParty.put(url, body: file.read) }
- RSpec.shared_examples 'for a maven package' do
+ shared_examples 'for a maven package' do
it 'creates package files' do
expect { subject }
.to change { Packages::Package.maven.count }.by(1)
@@ -25,9 +26,9 @@ RSpec.describe 'Upload a maven package', :api, :js do
it { expect(subject.code).to eq(200) }
end
- RSpec.shared_examples 'for a maven sha1' do
+ shared_examples 'for a maven sha1' do
let(:dummy_package) { double(Packages::Package) }
- let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.sha1" }
+ let(:api_path) { "/projects/#{project_id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.sha1" }
before do
# The sha verification done by the maven api is between:
@@ -42,8 +43,8 @@ RSpec.describe 'Upload a maven package', :api, :js do
it { expect(subject.code).to eq(204) }
end
- RSpec.shared_examples 'for a maven md5' do
- let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.md5" }
+ shared_examples 'for a maven md5' do
+ let(:api_path) { "/projects/#{project_id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar.md5" }
let(:file) { StringIO.new('dummy_package') }
it { expect(subject.code).to eq(200) }
@@ -52,4 +53,10 @@ RSpec.describe 'Upload a maven package', :api, :js do
it_behaves_like 'handling file uploads', 'for a maven package'
it_behaves_like 'handling file uploads', 'for a maven sha1'
it_behaves_like 'handling file uploads', 'for a maven md5'
+
+ context 'with an encoded project ID' do
+ let(:project_id) { "#{project.namespace.path}%2F#{project.path}" }
+
+ it_behaves_like 'handling file uploads', 'for a maven package'
+ end
end
diff --git a/spec/features/file_uploads/nuget_package_spec.rb b/spec/features/file_uploads/nuget_package_spec.rb
index 6e05e5d1a6e..871c0274445 100644
--- a/spec/features/file_uploads/nuget_package_spec.rb
+++ b/spec/features/file_uploads/nuget_package_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Upload a nuget package', :api, :js do
include_context 'file upload requests helpers'
let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:user) { project.owner }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:api_path) { "/projects/#{project.id}/packages/nuget/" }
@@ -21,7 +21,7 @@ RSpec.describe 'Upload a nuget package', :api, :js do
)
end
- RSpec.shared_examples 'for a nuget package' do
+ shared_examples 'for a nuget package' do
it 'creates package files' do
expect { subject }
.to change { Packages::Package.nuget.count }.by(1)
diff --git a/spec/features/file_uploads/rubygem_package_spec.rb b/spec/features/file_uploads/rubygem_package_spec.rb
new file mode 100644
index 00000000000..4a5891fdfed
--- /dev/null
+++ b/spec/features/file_uploads/rubygem_package_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a RubyGems package', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ let(:api_path) { "/projects/#{project_id}/packages/rubygems/api/v1/gems" }
+ let(:url) { capybara_url(api(api_path)) }
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ subject do
+ HTTParty.post(
+ url,
+ headers: { 'Authorization' => personal_access_token.token },
+ body: { file: file }
+ )
+ end
+
+ shared_examples 'for a Rubygems package' do
+ it 'creates package files' do
+ expect { subject }
+ .to change { Packages::Package.rubygems.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ end
+
+ it { expect(subject.code).to eq(201) }
+ end
+
+ context 'with an integer project ID' do
+ let(:project_id) { project.id }
+
+ it_behaves_like 'handling file uploads', 'for a Rubygems package'
+ end
+
+ context 'with an encoded project ID' do
+ let(:project_id) { "#{project.namespace.path}%2F#{project.path}" }
+
+ it_behaves_like 'handling file uploads', 'for a Rubygems package'
+ end
+end
diff --git a/spec/features/frequently_visited_projects_and_groups_spec.rb b/spec/features/frequently_visited_projects_and_groups_spec.rb
index b8797d9c139..6c25afdf6d4 100644
--- a/spec/features/frequently_visited_projects_and_groups_spec.rb
+++ b/spec/features/frequently_visited_projects_and_groups_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe 'Frequently visited items', :js do
let_it_be(:user) { create(:user) }
before do
+ stub_feature_flags(combined_menu: false)
+
sign_in(user)
end
diff --git a/spec/features/gitlab_experiments_spec.rb b/spec/features/gitlab_experiments_spec.rb
new file mode 100644
index 00000000000..76b418adcea
--- /dev/null
+++ b/spec/features/gitlab_experiments_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Gitlab::Experiment", :js do
+ # This is part of a set of tests that ensure that tracking remains
+ # consistent at the front end layer. Since we don't want to actually
+ # introduce an experiment in real code, we're going to simulate it
+ # here.
+ let(:user) { create(:user) }
+
+ before do
+ admin = create(:admin)
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ stub_experiments(null_hypothesis: :candidate)
+ end
+
+ describe 'with event tracking' do
+ it 'publishes the experiments that have been run to the client', :experiment do
+ allow_next_instance_of(Admin::AbuseReportsController) do |instance|
+ allow(instance).to receive(:index).and_wrap_original do |original|
+ instance.experiment(:null_hypothesis, user: instance.current_user) do |e|
+ e.use { original.call }
+ e.try { original.call }
+ end
+ end
+ end
+
+ visit admin_abuse_reports_path
+
+ expect(page).to have_content('Abuse Reports')
+
+ published_experiments = page.evaluate_script('window.gon.experiment')
+ expect(published_experiments).to include({
+ 'null_hypothesis' => {
+ 'experiment' => 'null_hypothesis',
+ 'key' => anything,
+ 'variant' => 'candidate'
+ }
+ })
+ end
+ end
+end
diff --git a/spec/features/groups/board_spec.rb b/spec/features/groups/board_spec.rb
index aab3f5e68d5..b4c60ff4fa3 100644
--- a/spec/features/groups/board_spec.rb
+++ b/spec/features/groups/board_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Group Boards' do
find('.gl-new-dropdown-item button').click
end
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).to have_content(issue_title)
end
diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb
index 97f8864aab2..2a7ededa39b 100644
--- a/spec/features/groups/clusters/user_spec.rb
+++ b/spec/features/groups/clusters/user_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe 'User Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
- page.within('.js-cluster-integration-form') { click_button 'Save changes' }
+ page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do
diff --git a/spec/features/groups/group_page_with_external_authorization_service_spec.rb b/spec/features/groups/group_page_with_external_authorization_service_spec.rb
index 8ef1b60d8ca..187d878472e 100644
--- a/spec/features/groups/group_page_with_external_authorization_service_spec.rb
+++ b/spec/features/groups/group_page_with_external_authorization_service_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'The group page' do
expect(page).to have_link('Details')
expect(page).to have_link('Activity')
expect(page).to have_link('Issues')
- expect(page).to have_link('Merge Requests')
+ expect(page).to have_link('Merge requests')
expect(page).to have_link('Members')
end
end
@@ -50,7 +50,7 @@ RSpec.describe 'The group page' do
expect(page).not_to have_link('Contribution')
expect(page).not_to have_link('Issues')
- expect(page).not_to have_link('Merge Requests')
+ expect(page).not_to have_link('Merge requests')
expect(page).to have_link('Members')
end
end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 60cd1ebbbd7..00ad1006037 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe 'Edit group settings' do
end
def updated_emails_disabled?
- group.reload.clear_memoization(:emails_disabled)
+ group.reload.clear_memoization(:emails_disabled_memoized)
group.emails_disabled?
end
end
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index 8ecd2beba68..b0d2f90145f 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -108,7 +108,7 @@ RSpec.describe 'Group issues page' do
it 'shows projects only with issues feature enabled', :js do
find('.empty-state .js-lazy-loaded')
- find('.new-project-item-link').click
+ find('.empty-state .new-project-item-link').click
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
diff --git a/spec/features/groups/labels/index_spec.rb b/spec/features/groups/labels/index_spec.rb
index 3de29231f5c..68f03368989 100644
--- a/spec/features/groups/labels/index_spec.rb
+++ b/spec/features/groups/labels/index_spec.rb
@@ -24,6 +24,6 @@ RSpec.describe 'Group labels' do
end
it 'shows an edit label button', :js do
- expect(page).to have_selector('.label-action.edit')
+ expect(page).to have_selector('.edit')
end
end
diff --git a/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb
index 38deee547a3..d31a7977f66 100644
--- a/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb
+++ b/spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
let_it_be(:user1) { create(:user, name: 'John Doe') }
let_it_be(:group) { create(:group) }
+
let(:new_member) { create(:user, name: 'Mary Jane') }
before do
diff --git a/spec/features/groups/members/request_access_spec.rb b/spec/features/groups/members/request_access_spec.rb
index 307cb63ec8e..827962fee61 100644
--- a/spec/features/groups/members/request_access_spec.rb
+++ b/spec/features/groups/members/request_access_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Groups > Members > Request access' do
end
it 'request access feature is disabled' do
- group.update(request_access_enabled: false)
+ group.update!(request_access_enabled: false)
visit group_path(group)
expect(page).not_to have_content 'Request Access'
diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb
index 43d4b6b23e0..f79c93157dc 100644
--- a/spec/features/groups/merge_requests_spec.rb
+++ b/spec/features/groups/merge_requests_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Group merge requests page' do
end
it 'ignores archived merge request count badges in navbar' do
- expect(first(:link, text: 'Merge Requests').find('.badge').text).to eq("1")
+ expect(first(:link, text: 'Merge requests').find('.badge').text).to eq("1")
end
it 'ignores archived merge request count badges in state-filters' do
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 8d1008b98a6..1d9ac5ee1e9 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -133,7 +133,7 @@ RSpec.describe 'Group milestones' do
href: project_issues_path(project, milestone_title: 'v1.0')
)
expect(page).to have_link(
- '0 Merge Requests',
+ '0 Merge requests',
href: project_merge_requests_path(project, milestone_title: 'v1.0')
)
expect(page).to have_link(
@@ -145,7 +145,7 @@ RSpec.describe 'Group milestones' do
href: issues_group_path(group, milestone_title: 'GL-113')
)
expect(page).to have_link(
- '0 Merge Requests',
+ '0 Merge requests',
href: merge_requests_group_path(group, milestone_title: 'GL-113')
)
end
@@ -179,7 +179,7 @@ RSpec.describe 'Group milestones' do
it 'renders the merge requests tab' do
within('.js-milestone-tabs') do
- click_link('Merge Requests')
+ click_link('Merge requests')
end
within('#tab-merge-requests') do
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index 7025874a4ff..021b1af54d4 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Group navbar' do
]
},
{
- nav_item: _('Merge Requests'),
+ nav_item: _('Merge requests'),
nav_sub_items: []
},
(security_and_compliance_nav_item if Gitlab.ee?),
@@ -68,7 +68,7 @@ RSpec.describe 'Group navbar' do
before do
stub_config(registry: { enabled: true })
- insert_container_nav(_('Kubernetes'))
+ insert_container_nav
visit group_path(group)
end
@@ -80,7 +80,7 @@ RSpec.describe 'Group navbar' do
before do
stub_config(dependency_proxy: { enabled: true })
- insert_dependency_proxy_nav(_('Dependency Proxy'))
+ insert_dependency_proxy_nav
visit group_path(group)
end
diff --git a/spec/features/groups/settings/user_searches_in_settings_spec.rb b/spec/features/groups/settings/user_searches_in_settings_spec.rb
index 819d0c4faba..6d7a3871bb1 100644
--- a/spec/features/groups/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/groups/settings/user_searches_in_settings_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe 'User searches group settings', :js do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, :repository, namespace: group) }
before do
group.add_owner(user)
@@ -13,9 +12,19 @@ RSpec.describe 'User searches group settings', :js do
end
context 'in general settings page' do
- let(:visit_path) { edit_group_path(group) }
+ before do
+ visit edit_group_path(group)
+ end
+
+ it_behaves_like 'can search settings', 'Naming', 'Permissions'
+ end
+
+ context 'in Integrations page' do
+ before do
+ visit group_settings_integrations_path(group)
+ end
- it_behaves_like 'can search settings with feature flag check', 'Naming', 'Permissions'
+ it_behaves_like 'can highlight results', 'set default configuration'
end
context 'in Repository page' do
@@ -33,4 +42,12 @@ RSpec.describe 'User searches group settings', :js do
it_behaves_like 'can search settings', 'Variables', 'Runners'
end
+
+ context 'in Packages & Registries page' do
+ before do
+ visit group_settings_packages_and_registries_path(group)
+ end
+
+ it_behaves_like 'can highlight results', 'GitLab Packages'
+ end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index 28b22860f0a..33d2ac50628 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -141,6 +141,30 @@ RSpec.describe 'Group' do
end
end
end
+
+ describe 'showing recaptcha on group creation when it is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ allow(Gitlab::Recaptcha).to receive(:load_configurations!)
+ visit new_group_path
+ end
+
+ it 'renders recaptcha' do
+ expect(page).to have_css('.recaptcha')
+ end
+ end
+
+ describe 'not showing recaptcha on group creation when it is disabled' do
+ before do
+ stub_feature_flags(recaptcha_on_top_level_group_creation: false)
+ stub_application_setting(recaptcha_enabled: true)
+ visit new_group_path
+ end
+
+ it 'does not render recaptcha' do
+ expect(page).not_to have_css('.recaptcha')
+ end
+ end
end
describe 'create a nested group' do
@@ -189,6 +213,46 @@ RSpec.describe 'Group' do
expect(page).to have_content("Group 'bar' was successfully created.")
end
end
+
+ context 'when recaptcha is enabled' do
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ allow(Gitlab::Recaptcha).to receive(:load_configurations!)
+ end
+
+ context 'when creating subgroup' do
+ let(:path) { new_group_path(group, parent_id: group.id) }
+
+ it 'does not render recaptcha' do
+ visit path
+
+ expect(page).not_to have_css('.recaptcha')
+ end
+ end
+ end
+
+ describe 'real-time group url validation', :js do
+ let_it_be(:subgroup) { create(:group, path: 'sub', parent: group) }
+
+ before do
+ group.add_owner(user)
+ visit new_group_path(parent_id: group.id)
+ end
+
+ it 'shows a message if group url is available' do
+ fill_in 'Group URL', with: group.path
+ wait_for_requests
+
+ expect(page).to have_content('Group path is available')
+ end
+
+ it 'shows an error if group url is taken' do
+ fill_in 'Group URL', with: subgroup.path
+ wait_for_requests
+
+ expect(page).to have_content('Group path is already taken')
+ end
+ end
end
it 'checks permissions to avoid exposing groups by parent_id' do
@@ -203,6 +267,7 @@ RSpec.describe 'Group' do
describe 'group edit', :js do
let_it_be(:group) { create(:group, :public) }
+
let(:path) { edit_group_path(group) }
let(:new_name) { 'new-name' }
@@ -248,6 +313,7 @@ RSpec.describe 'Group' do
describe 'group page with markdown description' do
let_it_be(:group) { create(:group) }
+
let(:path) { group_path(group) }
before do
diff --git a/spec/features/ide/clientside_preview_csp_spec.rb b/spec/features/ide/clientside_preview_csp_spec.rb
index eadcb9cd008..559edb8bf53 100644
--- a/spec/features/ide/clientside_preview_csp_spec.rb
+++ b/spec/features/ide/clientside_preview_csp_spec.rb
@@ -7,9 +7,7 @@ RSpec.describe 'IDE Clientside Preview CSP' do
shared_context 'disable feature' do
before do
- allow_next_instance_of(ApplicationSetting) do |instance|
- allow(instance).to receive(:web_ide_clientside_preview_enabled?).and_return(false)
- end
+ stub_application_setting(web_ide_clientside_preview_enabled: false)
end
end
@@ -24,10 +22,8 @@ RSpec.describe 'IDE Clientside Preview CSP' do
end
before do
- allow_next_instance_of(ApplicationSetting) do |instance|
- allow(instance).to receive(:web_ide_clientside_preview_enabled?).and_return(true)
- allow(instance).to receive(:web_ide_clientside_preview_bundler_url).and_return(whitelisted_url)
- end
+ stub_application_setting(web_ide_clientside_preview_enabled: true)
+ stub_application_setting(web_ide_clientside_preview_bundler_url: whitelisted_url)
sign_in(user)
end
diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb
index dfd6211a683..520cf850da2 100644
--- a/spec/features/import/manifest_import_spec.rb
+++ b/spec/features/import/manifest_import_spec.rb
@@ -37,11 +37,20 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
wait_for_requests
page.within(second_row) do
- expect(page).to have_content 'Done'
+ expect(page).to have_content 'Complete'
expect(page).to have_content("#{group.full_path}/build/blueprint")
end
end
+ it 'renders an error if the remote url scheme starts with javascript' do
+ visit new_import_manifest_path
+
+ attach_file('manifest', Rails.root.join('spec/fixtures/unsafe_javascript.xml'))
+ click_on 'List available repositories'
+
+ expect(page).to have_content 'Make sure the url does not start with javascript'
+ end
+
it 'renders an error if invalid file was provided' do
visit new_import_manifest_path
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 2ceffa896eb..e9960802378 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -50,21 +50,23 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
it 'renders sign in page with sign in notice' do
- expect(current_path).to eq(new_user_session_path)
- expect(page).to have_content('To accept this invitation, sign in')
+ expect(current_path).to eq(new_user_registration_path)
+ expect(page).to have_content('To accept this invitation, create an account or sign in')
end
it 'pre-fills the "Username or email" field on the sign in box with the invite_email from the invite' do
+ click_link 'Sign in'
+
expect(find_field('Username or email').value).to eq(group_invite.invite_email)
end
it 'pre-fills the Email field on the sign up box with the invite_email from the invite' do
- click_link 'Register now'
-
expect(find_field('Email').value).to eq(group_invite.invite_email)
end
it 'sign in, grants access and redirects to group page' do
+ click_link 'Sign in'
+
fill_in_sign_in_form(user)
expect(current_path).to eq(group_path(group))
@@ -85,20 +87,19 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
end
- context 'when inviting a user' do
+ context 'when inviting an unregistered user' do
let(:new_user) { build_stubbed(:user) }
let(:invite_email) { new_user.email }
let(:group_invite) { create(:group_member, :invited, group: group, invite_email: invite_email, created_by: owner) }
let!(:project_invite) { create(:project_member, :invited, project: project, invite_email: invite_email) }
- context 'when user has not signed in yet' do
+ context 'when registering using invitation email' do
before do
stub_application_setting(send_user_confirmation_email: send_email_confirmation)
visit invite_path(group_invite.raw_invite_token)
- click_link 'Register now'
end
- context 'with admin appoval required enabled' do
+ context 'with admin approval required enabled' do
before do
stub_application_setting(require_admin_approval_after_user_signup: true)
end
diff --git a/spec/features/issues/bulk_assignment_labels_spec.rb b/spec/features/issues/bulk_assignment_labels_spec.rb
index aa61aff3b05..80bf964e2ee 100644
--- a/spec/features/issues/bulk_assignment_labels_spec.rb
+++ b/spec/features/issues/bulk_assignment_labels_spec.rb
@@ -295,8 +295,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do
before do
issue1.milestone = milestone
issue2.milestone = milestone
- issue1.save
- issue2.save
+ issue1.save!
+ issue2.save!
issue1.labels << bug
issue2.labels << feature
diff --git a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb
index a4e9df604a9..34d78880991 100644
--- a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb
+++ b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb
@@ -18,10 +18,6 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j
end
end
- before do
- stub_feature_flags(remove_resolve_note: false)
- end
-
describe 'as a user with access to the project' do
before do
project.add_maintainer(user)
@@ -37,7 +33,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j
context 'resolving the thread' do
before do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
it 'hides the link for creating a new issue' do
diff --git a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb
index 99dc71f0559..ac3471e8401 100644
--- a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb
+++ b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb
@@ -14,10 +14,6 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue',
"a[title=\"#{title}\"][href=\"#{url}\"]"
end
- before do
- stub_feature_flags(remove_resolve_note: false)
- end
-
describe 'As a user with access to the project' do
before do
project.add_maintainer(user)
@@ -39,7 +35,7 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue',
context 'resolving the thread' do
before do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
it 'hides the link for creating a new issue' do
diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb
index dac066856c0..5ca20028485 100644
--- a/spec/features/issues/form_spec.rb
+++ b/spec/features/issues/form_spec.rb
@@ -156,7 +156,7 @@ RSpec.describe 'New/edit issue', :js do
expect(page.all('input[name="issue[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s)
expect(page.all('input[name="issue[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s)
- click_button 'Submit issue'
+ click_button 'Create issue'
page.within '.issuable-sidebar' do
page.within '.assignee' do
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index e6ebc37ba59..0cefbae4d37 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -3,16 +3,23 @@
require 'spec_helper'
RSpec.describe 'GFM autocomplete', :js do
- let_it_be(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
- let_it_be(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let_it_be(:user2) { create(:user, name: 'Marge Simpson', username: 'msimpson') }
+
let_it_be(:group) { create(:group, name: 'Ancestor') }
let_it_be(:child_group) { create(:group, parent: group, name: 'My group') }
let_it_be(:project) { create(:project, group: child_group) }
+
+ let_it_be(:issue) { create(:issue, project: project, assignees: [user]) }
let_it_be(:label) { create(:label, project: project, title: 'special+') }
+ let_it_be(:label_scoped) { create(:label, project: project, title: 'scoped::label') }
+ let_it_be(:label_with_spaces) { create(:label, project: project, title: 'Accepting merge requests') }
+ let_it_be(:snippet) { create(:project_snippet, project: project, title: 'code snippet') }
- let(:issue) { create(:issue, project: project) }
+ let_it_be(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+ let_it_be(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
+ let_it_be(:label_xss_title) { 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a' }
+ let_it_be(:label_xss) { create(:label, project: project, title: label_xss_title) }
before_all do
project.add_maintainer(user)
@@ -21,418 +28,366 @@ RSpec.describe 'GFM autocomplete', :js do
end
describe 'when tribute_autocomplete feature flag is off' do
- before do
- stub_feature_flags(tribute_autocomplete: false)
-
- sign_in(user)
- visit project_issue_path(project, issue)
-
- wait_for_requests
- end
-
- it 'updates issue description with GFM reference' do
- click_button 'Edit title and description'
-
- wait_for_requests
-
- fill_in 'Description', with: "@#{user.name[0...3]}"
-
- wait_for_requests
-
- find_highlighted_autocomplete_item.click
-
- click_button 'Save changes'
-
- wait_for_requests
-
- expect(find('.description')).to have_text(user.to_reference)
- end
-
- it 'opens quick action autocomplete when updating description' do
- click_button 'Edit title and description'
-
- fill_in 'Description', with: '/'
-
- expect(find_autocomplete_menu).to be_visible
- end
-
- it 'opens autocomplete menu when field starts with text' do
- fill_in 'Comment', with: '@'
-
- expect(find_autocomplete_menu).to be_visible
- end
-
- it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
- issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
- create(:issue, project: project, title: issue_xss_title)
-
- fill_in 'Comment', with: '#'
-
- wait_for_requests
+ describe 'new issue page' do
+ before do
+ stub_feature_flags(tribute_autocomplete: false)
- expect(find_autocomplete_menu).to have_text(issue_xss_title)
- end
+ sign_in(user)
+ visit new_project_issue_path(project)
- it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '@ev'
+ wait_for_requests
+ end
- wait_for_requests
+ it 'allows quick actions' do
+ fill_in 'Description', with: '/'
- expect(find_highlighted_autocomplete_item).to have_text(user_xss.username)
+ expect(find_autocomplete_menu).to be_visible
+ end
end
- it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
- milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:milestone, project: project, title: milestone_xss_title)
+ describe 'issue description' do
+ let(:issue_to_edit) { create(:issue, project: project) }
- fill_in 'Comment', with: '%'
+ before do
+ stub_feature_flags(tribute_autocomplete: false)
- wait_for_requests
+ sign_in(user)
+ visit project_issue_path(project, issue_to_edit)
- expect(find_autocomplete_menu).to have_text('alert milestone')
- end
+ wait_for_requests
+ end
- it 'doesnt open autocomplete menu character is prefixed with text' do
- fill_in 'Comment', with: 'testing@'
+ it 'updates with GFM reference' do
+ click_button 'Edit title and description'
- expect(page).not_to have_css('.atwho-view')
- end
+ wait_for_requests
- it 'doesnt select the first item for non-assignee dropdowns' do
- fill_in 'Comment', with: ':'
+ fill_in 'Description', with: "@#{user.name[0...3]}"
- wait_for_requests
+ wait_for_requests
- expect(find_autocomplete_menu).not_to have_css('.cur')
- end
+ find_highlighted_autocomplete_item.click
- it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do
- # Number.
- fill_in 'Comment', with: '7:'
- expect(page).not_to have_css('.atwho-view')
+ click_button 'Save changes'
- # ASCII letter.
- fill_in 'Comment', with: 'w:'
- expect(page).not_to have_css('.atwho-view')
+ wait_for_requests
- # Non-ASCII letter.
- fill_in 'Comment', with: 'Ё:'
- expect(page).not_to have_css('.atwho-view')
- end
+ expect(find('.description')).to have_text(user.to_reference)
+ end
- it 'selects the first item for assignee dropdowns' do
- fill_in 'Comment', with: '@'
+ it 'allows quick actions' do
+ click_button 'Edit title and description'
- wait_for_requests
+ fill_in 'Description', with: '/'
- expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
+ expect(find_autocomplete_menu).to be_visible
+ end
end
- it 'includes items for assignee dropdowns with non-ASCII characters in name' do
- fill_in 'Comment', with: "@#{user.name[0...8]}"
+ describe 'issue comment' do
+ before do
+ stub_feature_flags(tribute_autocomplete: false)
- wait_for_requests
+ sign_in(user)
+ visit project_issue_path(project, issue)
- expect(find_autocomplete_menu).to have_text(user.name)
- end
+ wait_for_requests
+ end
- it 'searches across full name for assignees' do
- fill_in 'Comment', with: '@speciąlsome'
+ describe 'triggering autocomplete' do
+ it 'only opens autocomplete menu when trigger character is after whitespace', :aggregate_failures do
+ fill_in 'Comment', with: 'testing@'
+ expect(page).not_to have_css('.atwho-view')
- wait_for_requests
+ fill_in 'Comment', with: '@@'
+ expect(page).not_to have_css('.atwho-view')
- expect(find_highlighted_autocomplete_item).to have_text(user.name)
- end
+ fill_in 'Comment', with: "@#{user.username[0..2]}!"
+ expect(page).not_to have_css('.atwho-view')
- it 'shows names that start with the query as the top result' do
- fill_in 'Comment', with: '@mar'
+ fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ expect(page).not_to have_css('.atwho-view')
- wait_for_requests
+ fill_in 'Comment', with: '7:'
+ expect(page).not_to have_css('.atwho-view')
- expect(find_highlighted_autocomplete_item).to have_text(user2.name)
- end
-
- it 'shows usernames that start with the query as the top result' do
- fill_in 'Comment', with: '@msi'
+ fill_in 'Comment', with: 'w:'
+ expect(page).not_to have_css('.atwho-view')
- wait_for_requests
+ fill_in 'Comment', with: 'Ё:'
+ expect(page).not_to have_css('.atwho-view')
- expect(find_highlighted_autocomplete_item).to have_text(user2.name)
- end
+ fill_in 'Comment', with: "test\n\n@"
+ expect(find_autocomplete_menu).to be_visible
+ end
+ end
- # Regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/321925
- it 'shows username when pasting then pressing Enter' do
- fill_in 'Comment', with: "@#{user.username}\n"
+ context 'xss checks' do
+ it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
+ issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
+ create(:issue, project: project, title: issue_xss_title)
- expect(find_field('Comment').value).to have_text "@#{user.username}"
- end
+ fill_in 'Comment', with: '#'
- it 'does not show `@undefined` when pressing `@` then Enter' do
- fill_in 'Comment', with: "@\n"
+ wait_for_requests
- expect(find_field('Comment').value).to have_text '@'
- expect(find_field('Comment').value).not_to have_text '@undefined'
- end
+ expect(find_autocomplete_menu).to have_text(issue_xss_title)
+ end
- it 'selects the first item for non-assignee dropdowns if a query is entered' do
- fill_in 'Comment', with: ':1'
+ it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '@ev'
- wait_for_requests
+ wait_for_requests
- expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
- end
+ expect(find_highlighted_autocomplete_item).to have_text(user_xss.username)
+ end
- context 'if a selected value has special characters' do
- it 'wraps the result in double quotes' do
- fill_in 'Comment', with: "~#{label.title[0]}"
+ it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
+ milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
+ create(:milestone, project: project, title: milestone_xss_title)
- find_highlighted_autocomplete_item.click
+ fill_in 'Comment', with: '%'
- expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
- end
+ wait_for_requests
- it "shows dropdown after a new line" do
- fill_in 'Comment', with: "test\n\n@"
+ expect(find_autocomplete_menu).to have_text('alert milestone')
+ end
- expect(find_autocomplete_menu).to be_visible
- end
+ it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '~'
- it "does not show dropdown when preceded with a special character" do
- fill_in 'Comment', with: '@@'
+ wait_for_requests
- expect(page).not_to have_css('.atwho-view')
+ expect(find_autocomplete_menu).to have_text('alert label')
+ end
end
- it 'doesn\'t wrap for assignee values' do
- fill_in 'Comment', with: "@#{user.username[0]}"
+ describe 'autocomplete highlighting' do
+ it 'auto-selects the first item when there is a query, and only for assignees with no query', :aggregate_failures do
+ fill_in 'Comment', with: ':'
+ wait_for_requests
+ expect(find_autocomplete_menu).not_to have_css('.cur')
- find_highlighted_autocomplete_item.click
+ fill_in 'Comment', with: ':1'
+ wait_for_requests
+ expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
- expect(find_field('Comment').value).to have_text("@#{user.username}")
+ fill_in 'Comment', with: '@'
+ wait_for_requests
+ expect(find_autocomplete_menu).to have_css('.cur:first-of-type')
+ end
end
- it 'doesn\'t wrap for emoji values' do
- fill_in 'Comment', with: ':cartwheel_'
-
- find_highlighted_autocomplete_item.click
+ describe 'assignees' do
+ it 'does not wrap with quotes for assignee values' do
+ fill_in 'Comment', with: "@#{user.username[0]}"
- expect(find_field('Comment').value).to have_text('cartwheel_tone1')
- end
+ find_highlighted_autocomplete_item.click
- it 'doesn\'t open autocomplete after non-word character' do
- fill_in 'Comment', with: "@#{user.username[0..2]}!"
+ expect(find_field('Comment').value).to have_text("@#{user.username}")
+ end
- expect(page).not_to have_css('.atwho-view')
- end
+ it 'includes items for assignee dropdowns with non-ASCII characters in name' do
+ fill_in 'Comment', with: "@#{user.name[0...8]}"
- it 'doesn\'t open autocomplete if there is no space before' do
- fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ wait_for_requests
- expect(page).not_to have_css('.atwho-view')
- end
+ expect(find_autocomplete_menu).to have_text(user.name)
+ end
- it 'triggers autocomplete after selecting a quick action' do
- fill_in 'Comment', with: '/as'
+ it 'searches across full name for assignees' do
+ fill_in 'Comment', with: '@speciąlsome'
- find_highlighted_autocomplete_item.click
+ wait_for_requests
- expect(find_autocomplete_menu).to have_text(user.username)
- end
+ expect(find_highlighted_autocomplete_item).to have_text(user.name)
+ end
- it 'does not limit quick actions autocomplete list to 5' do
- fill_in 'Comment', with: '/'
+ it 'shows names that start with the query as the top result' do
+ fill_in 'Comment', with: '@mar'
- expect(find_autocomplete_menu).to have_css('li', minimum: 6)
- end
- end
+ wait_for_requests
- context 'assignees' do
- let(:issue_assignee) { create(:issue, project: project) }
- let(:unassigned_user) { create(:user) }
+ expect(find_highlighted_autocomplete_item).to have_text(user2.name)
+ end
- before do
- issue_assignee.update(assignees: [user])
+ it 'shows usernames that start with the query as the top result' do
+ fill_in 'Comment', with: '@msi'
- project.add_maintainer(unassigned_user)
- end
+ wait_for_requests
- it 'lists users who are currently not assigned to the issue when using /assign' do
- visit project_issue_path(project, issue_assignee)
+ expect(find_highlighted_autocomplete_item).to have_text(user2.name)
+ end
- fill_in 'Comment', with: '/as'
+ # Regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/321925
+ it 'shows username when pasting then pressing Enter' do
+ fill_in 'Comment', with: "@#{user.username}\n"
- find_highlighted_autocomplete_item.click
+ expect(find_field('Comment').value).to have_text "@#{user.username}"
+ end
- expect(find_autocomplete_menu).not_to have_text(user.username)
- expect(find_autocomplete_menu).to have_text(unassigned_user.username)
- end
+ it 'does not show `@undefined` when pressing `@` then Enter' do
+ fill_in 'Comment', with: "@\n"
- it 'shows dropdown on new issue form' do
- visit new_project_issue_path(project)
+ expect(find_field('Comment').value).to have_text '@'
+ expect(find_field('Comment').value).not_to have_text '@undefined'
+ end
- fill_in 'Description', with: '/ass'
+ context 'when /assign quick action is selected' do
+ it 'triggers user autocomplete and lists users who are currently not assigned to the issue' do
+ fill_in 'Comment', with: '/as'
- find_highlighted_autocomplete_item.click
+ find_highlighted_autocomplete_item.click
- expect(find_autocomplete_menu).to have_text(unassigned_user.username)
- expect(find_autocomplete_menu).to have_text(user.username)
+ expect(find_autocomplete_menu).not_to have_text(user.username)
+ expect(find_autocomplete_menu).to have_text(user2.username)
+ end
+ end
end
- end
-
- context 'labels' do
- it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
- label_xss_title = 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:label, project: project, title: label_xss_title)
- fill_in 'Comment', with: '~'
-
- wait_for_requests
+ context 'if a selected value has special characters' do
+ it 'wraps the result in double quotes' do
+ fill_in 'Comment', with: "~#{label.title[0..2]}"
- expect(find_autocomplete_menu).to have_text('alert label')
- end
+ find_highlighted_autocomplete_item.click
- it 'allows colons when autocompleting scoped labels' do
- create(:label, project: project, title: 'scoped:label')
+ expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
+ end
- fill_in 'Comment', with: '~scoped:'
+ it 'doesn\'t wrap for emoji values' do
+ fill_in 'Comment', with: ':cartwheel_'
- wait_for_requests
+ find_highlighted_autocomplete_item.click
- expect(find_autocomplete_menu).to have_text('scoped:label')
+ expect(find_field('Comment').value).to have_text('cartwheel_tone1')
+ end
end
- it 'allows colons when autocompleting scoped labels with double colons' do
- create(:label, project: project, title: 'scoped::label')
+ context 'quick actions' do
+ it 'does not limit quick actions autocomplete list to 5' do
+ fill_in 'Comment', with: '/'
- fill_in 'Comment', with: '~scoped::'
-
- wait_for_requests
-
- expect(find_autocomplete_menu).to have_text('scoped::label')
+ expect(find_autocomplete_menu).to have_css('li', minimum: 6)
+ end
end
- it 'allows spaces when autocompleting multi-word labels' do
- create(:label, project: project, title: 'Accepting merge requests')
+ context 'labels' do
+ it 'allows colons when autocompleting scoped labels' do
+ fill_in 'Comment', with: '~scoped:'
- fill_in 'Comment', with: '~Accepting merge'
+ wait_for_requests
- wait_for_requests
+ expect(find_autocomplete_menu).to have_text('scoped::label')
+ end
- expect(find_autocomplete_menu).to have_text('Accepting merge requests')
- end
+ it 'allows spaces when autocompleting multi-word labels' do
+ fill_in 'Comment', with: '~Accepting merge'
- it 'only autocompletes the latest label' do
- create(:label, project: project, title: 'Accepting merge requests')
- create(:label, project: project, title: 'Accepting job applicants')
+ wait_for_requests
- fill_in 'Comment', with: '~Accepting merge requests foo bar ~Accepting job'
+ expect(find_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- wait_for_requests
+ it 'only autocompletes the last label' do
+ fill_in 'Comment', with: '~scoped:: foo bar ~Accepting merge'
- expect(find_autocomplete_menu).to have_text('Accepting job applicants')
- end
+ wait_for_requests
- it 'does not autocomplete labels if no tilde is typed' do
- create(:label, project: project, title: 'Accepting merge requests')
+ expect(find_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- fill_in 'Comment', with: 'Accepting merge'
+ it 'does not autocomplete labels if no tilde is typed' do
+ fill_in 'Comment', with: 'Accepting merge'
- wait_for_requests
+ wait_for_requests
- expect(page).not_to have_css('.atwho-view')
+ expect(page).not_to have_css('.atwho-view')
+ end
end
- end
- context 'when other notes are destroyed' do
- let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
+ context 'when other notes are destroyed' do
+ let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
- # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
- it 'keeps autocomplete key listeners' do
- visit project_issue_path(project, issue)
- note = find_field('Comment')
+ # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
+ it 'keeps autocomplete key listeners' do
+ note = find_field('Comment')
- start_comment_with_emoji(note, '.atwho-view li')
+ start_comment_with_emoji(note, '.atwho-view li')
- start_and_cancel_discussion
+ start_and_cancel_discussion
- note.fill_in(with: '')
- start_comment_with_emoji(note, '.atwho-view li')
- note.native.send_keys(:enter)
+ note.fill_in(with: '')
+ start_comment_with_emoji(note, '.atwho-view li')
+ note.native.send_keys(:enter)
- expect(note.value).to eql('Hello :100: ')
+ expect(note.value).to eql('Hello :100: ')
+ end
end
- end
- shared_examples 'autocomplete suggestions' do
- it 'suggests objects correctly' do
- fill_in 'Comment', with: object.class.reference_prefix
+ shared_examples 'autocomplete suggestions' do
+ it 'suggests objects correctly' do
+ fill_in 'Comment', with: object.class.reference_prefix
- find_autocomplete_menu.find('li').click
+ find_autocomplete_menu.find('li').click
- expect(find_field('Comment').value).to have_text(expected_body)
+ expect(find_field('Comment').value).to have_text(expected_body)
+ end
end
- end
- context 'issues' do
- let(:object) { issue }
- let(:expected_body) { object.to_reference }
+ context 'issues' do
+ let(:object) { issue }
+ let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
- end
-
- context 'merge requests' do
- let(:object) { create(:merge_request, source_project: project) }
- let(:expected_body) { object.to_reference }
-
- it_behaves_like 'autocomplete suggestions'
- end
+ it_behaves_like 'autocomplete suggestions'
+ end
- context 'project snippets' do
- let!(:object) { create(:project_snippet, project: project, title: 'code snippet') }
- let(:expected_body) { object.to_reference }
+ context 'merge requests' do
+ let(:object) { create(:merge_request, source_project: project) }
+ let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
- end
+ it_behaves_like 'autocomplete suggestions'
+ end
- context 'label' do
- let!(:object) { label }
- let(:expected_body) { object.title }
+ context 'project snippets' do
+ let!(:object) { snippet }
+ let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
- end
+ it_behaves_like 'autocomplete suggestions'
+ end
- context 'milestone' do
- let_it_be(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) }
- let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') }
- let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) }
- let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) }
- let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
+ context 'milestone' do
+ let_it_be(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) }
+ let_it_be(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') }
+ let_it_be(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) }
+ let_it_be(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) }
+ let_it_be(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
- before do
- fill_in 'Comment', with: '/milestone %'
+ before do
+ fill_in 'Comment', with: '/milestone %'
- wait_for_requests
- end
+ wait_for_requests
+ end
- it 'shows milestons list in the autocomplete menu' do
- page.within(find_autocomplete_menu) do
- expect(page).to have_selector('li', count: 5)
+ it 'shows milestons list in the autocomplete menu' do
+ page.within(find_autocomplete_menu) do
+ expect(page).to have_selector('li', count: 5)
+ end
end
- end
- it 'shows expired milestone at the bottom of the list' do
- page.within(find_autocomplete_menu) do
- expect(page.find('li:last-child')).to have_content milestone_expired.title
+ it 'shows expired milestone at the bottom of the list' do
+ page.within(find_autocomplete_menu) do
+ expect(page.find('li:last-child')).to have_content milestone_expired.title
+ end
end
- end
- it 'shows milestone due earliest at the top of the list' do
- page.within(find_autocomplete_menu) do
- aggregate_failures do
- expect(page.all('li')[0]).to have_content milestone3.title
- expect(page.all('li')[1]).to have_content milestone2.title
- expect(page.all('li')[2]).to have_content milestone1.title
- expect(page.all('li')[3]).to have_content milestone_no_duedate.title
+ it 'shows milestone due earliest at the top of the list' do
+ page.within(find_autocomplete_menu) do
+ aggregate_failures do
+ expect(page.all('li')[0]).to have_content milestone3.title
+ expect(page.all('li')[1]).to have_content milestone2.title
+ expect(page.all('li')[2]).to have_content milestone1.title
+ expect(page.all('li')[3]).to have_content milestone_no_duedate.title
+ end
end
end
end
@@ -440,346 +395,303 @@ RSpec.describe 'GFM autocomplete', :js do
end
describe 'when tribute_autocomplete feature flag is on' do
- before do
- stub_feature_flags(tribute_autocomplete: true)
-
- sign_in(user)
- visit project_issue_path(project, issue)
-
- wait_for_requests
- end
+ describe 'issue description' do
+ let(:issue_to_edit) { create(:issue, project: project) }
- it 'updates issue description with GFM reference' do
- click_button 'Edit title and description'
-
- wait_for_requests
-
- fill_in 'Description', with: "@#{user.name[0...3]}"
-
- wait_for_requests
+ before do
+ stub_feature_flags(tribute_autocomplete: true)
- find_highlighted_tribute_autocomplete_menu.click
+ sign_in(user)
+ visit project_issue_path(project, issue_to_edit)
- click_button 'Save changes'
+ wait_for_requests
+ end
- wait_for_requests
+ it 'updates with GFM reference' do
+ click_button 'Edit title and description'
- expect(find('.description')).to have_text(user.to_reference)
- end
+ wait_for_requests
- it 'opens autocomplete menu when field starts with text' do
- fill_in 'Comment', with: '@'
+ fill_in 'Description', with: "@#{user.name[0...3]}"
- expect(find_tribute_autocomplete_menu).to be_visible
- end
+ wait_for_requests
- it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
- issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
- create(:issue, project: project, title: issue_xss_title)
+ find_highlighted_tribute_autocomplete_menu.click
- fill_in 'Comment', with: '#'
+ click_button 'Save changes'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_text(issue_xss_title)
+ expect(find('.description')).to have_text(user.to_reference)
+ end
end
- it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
- fill_in 'Comment', with: '@ev'
-
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text(user_xss.username)
- end
+ describe 'issue comment' do
+ before do
+ stub_feature_flags(tribute_autocomplete: true)
- it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
- milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:milestone, project: project, title: milestone_xss_title)
+ sign_in(user)
+ visit project_issue_path(project, issue)
- fill_in 'Comment', with: '%'
+ wait_for_requests
+ end
- wait_for_requests
+ describe 'triggering autocomplete' do
+ it 'only opens autocomplete menu when trigger character is after whitespace', :aggregate_failures do
+ fill_in 'Comment', with: 'testing@'
+ expect(page).not_to have_css('.tribute-container')
- expect(find_tribute_autocomplete_menu).to have_text('alert milestone')
- end
+ fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ expect(page).not_to have_css('.tribute-container')
- it 'does not open autocomplete menu when trigger character is prefixed with text' do
- fill_in 'Comment', with: 'testing@'
+ fill_in 'Comment', with: '7:'
+ expect(page).not_to have_css('.tribute-container')
- expect(page).not_to have_css('.tribute-container')
- end
+ fill_in 'Comment', with: 'w:'
+ expect(page).not_to have_css('.tribute-container')
- it 'does not open autocomplete menu when ":" is prefixed by a number and letters' do
- # Number.
- fill_in 'Comment', with: '7:'
- expect(page).not_to have_css('.tribute-container')
+ fill_in 'Comment', with: 'Ё:'
+ expect(page).not_to have_css('.tribute-container')
- # ASCII letter.
- fill_in 'Comment', with: 'w:'
- expect(page).not_to have_css('.tribute-container')
+ fill_in 'Comment', with: "test\n\n@"
+ expect(find_tribute_autocomplete_menu).to be_visible
+ end
+ end
- # Non-ASCII letter.
- fill_in 'Comment', with: 'Ё:'
- expect(page).not_to have_css('.tribute-container')
- end
+ context 'xss checks' do
+ it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
+ issue_xss_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
+ create(:issue, project: project, title: issue_xss_title)
- it 'selects the first item for assignee dropdowns' do
- fill_in 'Comment', with: '@'
+ fill_in 'Comment', with: '#'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
- end
+ expect(find_tribute_autocomplete_menu).to have_text(issue_xss_title)
+ end
- it 'includes items for assignee dropdowns with non-ASCII characters in name' do
- fill_in 'Comment', with: "@#{user.name[0...8]}"
+ it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '@ev'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_text(user.name)
- end
+ expect(find_tribute_autocomplete_menu).to have_text(user_xss.username)
+ end
- it 'selects the first item for non-assignee dropdowns if a query is entered' do
- fill_in 'Comment', with: ':1'
+ it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
+ milestone_xss_title = 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a'
+ create(:milestone, project: project, title: milestone_xss_title)
- wait_for_requests
+ fill_in 'Comment', with: '%'
- expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
- end
+ wait_for_requests
- context 'when autocompleting for groups' do
- it 'shows the group when searching for the name of the group' do
- fill_in 'Comment', with: '@mygroup'
+ expect(find_tribute_autocomplete_menu).to have_text('alert milestone')
+ end
- expect(find_tribute_autocomplete_menu).to have_text('My group')
- end
+ it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
+ fill_in 'Comment', with: '~'
- it 'does not show the group when searching for the name of the parent of the group' do
- fill_in 'Comment', with: '@ancestor'
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).not_to have_text('My group')
+ expect(find_tribute_autocomplete_menu).to have_text('alert label')
+ end
end
- end
- context 'if a selected value has special characters' do
- it 'wraps the result in double quotes' do
- fill_in 'Comment', with: "~#{label.title[0]}"
+ describe 'autocomplete highlighting' do
+ it 'auto-selects the first item with query', :aggregate_failures do
+ fill_in 'Comment', with: ':1'
+ wait_for_requests
+ expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
- find_highlighted_tribute_autocomplete_menu.click
-
- expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
+ fill_in 'Comment', with: '@'
+ wait_for_requests
+ expect(find_tribute_autocomplete_menu).to have_css('.highlight:first-of-type')
+ end
end
- it "shows dropdown after a new line" do
- fill_in 'Comment', with: "test\n\n@"
-
- expect(find_tribute_autocomplete_menu).to be_visible
- end
+ describe 'assignees' do
+ it 'does not wrap with quotes for assignee values' do
+ fill_in 'Comment', with: "@#{user.username[0..2]}"
- it 'doesn\'t wrap for assignee values' do
- fill_in 'Comment', with: "@#{user.username[0..2]}"
+ find_highlighted_tribute_autocomplete_menu.click
- find_highlighted_tribute_autocomplete_menu.click
+ expect(find_field('Comment').value).to have_text("@#{user.username}")
+ end
- expect(find_field('Comment').value).to have_text("@#{user.username}")
- end
+ it 'includes items for assignee dropdowns with non-ASCII characters in name' do
+ fill_in 'Comment', with: "@#{user.name[0...8]}"
- it 'does not wrap for emoji values' do
- fill_in 'Comment', with: ':cartwheel_'
+ wait_for_requests
- find_highlighted_tribute_autocomplete_menu.click
+ expect(find_tribute_autocomplete_menu).to have_text(user.name)
+ end
- expect(find_field('Comment').value).to have_text('cartwheel_tone1')
- end
+ context 'when autocompleting for groups' do
+ it 'shows the group when searching for the name of the group' do
+ fill_in 'Comment', with: '@mygroup'
- it 'does not open autocomplete if there is no space before' do
- fill_in 'Comment', with: "hello:#{user.username[0..2]}"
+ expect(find_tribute_autocomplete_menu).to have_text('My group')
+ end
- expect(page).not_to have_css('.tribute-container')
- end
+ it 'does not show the group when searching for the name of the parent of the group' do
+ fill_in 'Comment', with: '@ancestor'
- it 'autocompletes for quick actions' do
- fill_in 'Comment', with: '/as'
+ expect(find_tribute_autocomplete_menu).not_to have_text('My group')
+ end
+ end
- find_highlighted_tribute_autocomplete_menu.click
+ context 'when /assign quick action is selected' do
+ it 'lists users who are currently not assigned to the issue' do
+ note = find_field('Comment')
+ note.native.send_keys('/assign ')
+ # The `/assign` ajax response might replace the one by `@` below causing a failed test
+ # so we need to wait for the `/assign` ajax request to finish first
+ wait_for_requests
+ note.native.send_keys('@')
+ wait_for_requests
+
+ expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
+ expect(find_tribute_autocomplete_menu).to have_text(user2.username)
+ end
- expect(find_field('Comment').value).to have_text('/assign')
+ it 'lists users who are currently not assigned to the issue when using /assign on the second line' do
+ note = find_field('Comment')
+ note.native.send_keys('/assign @user2')
+ note.native.send_keys(:enter)
+ note.native.send_keys('/assign ')
+ # The `/assign` ajax response might replace the one by `@` below causing a failed test
+ # so we need to wait for the `/assign` ajax request to finish first
+ wait_for_requests
+ note.native.send_keys('@')
+ wait_for_requests
+
+ expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
+ expect(find_tribute_autocomplete_menu).to have_text(user2.username)
+ end
+ end
end
- end
- context 'assignees' do
- let(:issue_assignee) { create(:issue, project: project) }
- let(:unassigned_user) { create(:user) }
+ context 'if a selected value has special characters' do
+ it 'wraps the result in double quotes' do
+ fill_in 'Comment', with: "~#{label.title[0..2]}"
- before do
- issue_assignee.update(assignees: [user])
+ find_highlighted_tribute_autocomplete_menu.click
- project.add_maintainer(unassigned_user)
- end
+ expect(find_field('Comment').value).to have_text("~\"#{label.title}\"")
+ end
- it 'lists users who are currently not assigned to the issue when using /assign' do
- visit project_issue_path(project, issue_assignee)
+ it 'does not wrap for emoji values' do
+ fill_in 'Comment', with: ':cartwheel_'
- note = find_field('Comment')
- note.native.send_keys('/assign ')
- # The `/assign` ajax response might replace the one by `@` below causing a failed test
- # so we need to wait for the `/assign` ajax request to finish first
- wait_for_requests
- note.native.send_keys('@')
- wait_for_requests
+ find_highlighted_tribute_autocomplete_menu.click
- expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
- expect(find_tribute_autocomplete_menu).to have_text(unassigned_user.username)
+ expect(find_field('Comment').value).to have_text('cartwheel_tone1')
+ end
end
- it 'lists users who are currently not assigned to the issue when using /assign on the second line' do
- visit project_issue_path(project, issue_assignee)
+ context 'quick actions' do
+ it 'autocompletes for quick actions' do
+ fill_in 'Comment', with: '/as'
- note = find_field('Comment')
- note.native.send_keys('/assign @user2')
- note.native.send_keys(:enter)
- note.native.send_keys('/assign ')
- # The `/assign` ajax response might replace the one by `@` below causing a failed test
- # so we need to wait for the `/assign` ajax request to finish first
- wait_for_requests
- note.native.send_keys('@')
- wait_for_requests
+ find_highlighted_tribute_autocomplete_menu.click
- expect(find_tribute_autocomplete_menu).not_to have_text(user.username)
- expect(find_tribute_autocomplete_menu).to have_text(unassigned_user.username)
+ expect(find_field('Comment').value).to have_text('/assign')
+ end
end
- end
- context 'labels' do
- it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
- label_xss_title = 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a'
- create(:label, project: project, title: label_xss_title)
+ context 'labels' do
+ it 'allows colons when autocompleting scoped labels' do
+ fill_in 'Comment', with: '~scoped:'
- fill_in 'Comment', with: '~'
+ wait_for_requests
- wait_for_requests
+ expect(find_tribute_autocomplete_menu).to have_text('scoped::label')
+ end
- expect(find_tribute_autocomplete_menu).to have_text('alert label')
- end
+ it 'autocompletes multi-word labels' do
+ fill_in 'Comment', with: '~Acceptingmerge'
- it 'allows colons when autocompleting scoped labels' do
- create(:label, project: project, title: 'scoped:label')
+ wait_for_requests
- fill_in 'Comment', with: '~scoped:'
+ expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- wait_for_requests
+ it 'only autocompletes the last label' do
+ fill_in 'Comment', with: '~scoped:: foo bar ~Acceptingmerge'
+ # Invoke autocompletion
+ find_field('Comment').native.send_keys(:right)
- expect(find_tribute_autocomplete_menu).to have_text('scoped:label')
- end
+ wait_for_requests
- it 'allows colons when autocompleting scoped labels with double colons' do
- create(:label, project: project, title: 'scoped::label')
+ expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
+ end
- fill_in 'Comment', with: '~scoped::'
+ it 'does not autocomplete labels if no tilde is typed' do
+ fill_in 'Comment', with: 'Accepting'
- wait_for_requests
+ wait_for_requests
- expect(find_tribute_autocomplete_menu).to have_text('scoped::label')
+ expect(page).not_to have_css('.tribute-container')
+ end
end
- it 'autocompletes multi-word labels' do
- create(:label, project: project, title: 'Accepting merge requests')
+ context 'when other notes are destroyed' do
+ let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
- fill_in 'Comment', with: '~Acceptingmerge'
+ # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
+ it 'keeps autocomplete key listeners' do
+ note = find_field('Comment')
- wait_for_requests
-
- expect(find_tribute_autocomplete_menu).to have_text('Accepting merge requests')
- end
-
- it 'only autocompletes the latest label' do
- create(:label, project: project, title: 'documentation')
- create(:label, project: project, title: 'feature')
+ start_comment_with_emoji(note, '.tribute-container li')
- fill_in 'Comment', with: '~documentation foo bar ~feat'
- # Invoke autocompletion
- find_field('Comment').native.send_keys(:right)
+ start_and_cancel_discussion
- wait_for_requests
+ note.fill_in(with: '')
+ start_comment_with_emoji(note, '.tribute-container li')
+ note.native.send_keys(:enter)
- expect(find_tribute_autocomplete_menu).to have_text('feature')
- expect(find_tribute_autocomplete_menu).not_to have_text('documentation')
+ expect(note.value).to eql('Hello :100: ')
+ end
end
- it 'does not autocomplete labels if no tilde is typed' do
- create(:label, project: project, title: 'documentation')
+ shared_examples 'autocomplete suggestions' do
+ it 'suggests objects correctly' do
+ fill_in 'Comment', with: object.class.reference_prefix
- fill_in 'Comment', with: 'document'
-
- wait_for_requests
+ find_tribute_autocomplete_menu.find('li').click
- expect(page).not_to have_css('.tribute-container')
+ expect(find_field('Comment').value).to have_text(expected_body)
+ end
end
- end
-
- context 'when other notes are destroyed' do
- let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
-
- # This is meant to protect against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/228729
- it 'keeps autocomplete key listeners' do
- visit project_issue_path(project, issue)
- note = find_field('Comment')
-
- start_comment_with_emoji(note, '.tribute-container li')
-
- start_and_cancel_discussion
- note.fill_in(with: '')
- start_comment_with_emoji(note, '.tribute-container li')
- note.native.send_keys(:enter)
+ context 'issues' do
+ let(:object) { issue }
+ let(:expected_body) { object.to_reference }
- expect(note.value).to eql('Hello :100: ')
+ it_behaves_like 'autocomplete suggestions'
end
- end
-
- shared_examples 'autocomplete suggestions' do
- it 'suggests objects correctly' do
- fill_in 'Comment', with: object.class.reference_prefix
- find_tribute_autocomplete_menu.find('li').click
+ context 'merge requests' do
+ let(:object) { create(:merge_request, source_project: project) }
+ let(:expected_body) { object.to_reference }
- expect(find_field('Comment').value).to have_text(expected_body)
+ it_behaves_like 'autocomplete suggestions'
end
- end
-
- context 'issues' do
- let(:object) { issue }
- let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
- end
-
- context 'merge requests' do
- let(:object) { create(:merge_request, source_project: project) }
- let(:expected_body) { object.to_reference }
-
- it_behaves_like 'autocomplete suggestions'
- end
+ context 'project snippets' do
+ let!(:object) { snippet }
+ let(:expected_body) { object.to_reference }
- context 'project snippets' do
- let!(:object) { create(:project_snippet, project: project, title: 'code snippet') }
- let(:expected_body) { object.to_reference }
-
- it_behaves_like 'autocomplete suggestions'
- end
-
- context 'label' do
- let!(:object) { label }
- let(:expected_body) { object.title }
-
- it_behaves_like 'autocomplete suggestions'
- end
+ it_behaves_like 'autocomplete suggestions'
+ end
- context 'milestone' do
- let!(:object) { create(:milestone, project: project) }
- let(:expected_body) { object.to_reference }
+ context 'milestone' do
+ let!(:object) { create(:milestone, project: project) }
+ let(:expected_body) { object.to_reference }
- it_behaves_like 'autocomplete suggestions'
+ it_behaves_like 'autocomplete suggestions'
+ end
end
end
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index ca44978d223..04b4caa52fe 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -30,79 +30,199 @@ RSpec.describe 'Issue Sidebar' do
let(:user2) { create(:user) }
let(:issue2) { create(:issue, project: project, author: user2) }
- include_examples 'issuable invite members experiments' do
- let(:issuable_path) { project_issue_path(project, issue2) }
- end
-
- context 'when user is a developer' do
+ context 'when GraphQL assignees widget feature flag is disabled' do
before do
- project.add_developer(user)
- visit_issue(project, issue2)
-
- find('.block.assignee .edit-link').click
+ stub_feature_flags(issue_assignees_widget: false)
+ end
- wait_for_requests
+ include_examples 'issuable invite members experiments' do
+ let(:issuable_path) { project_issue_path(project, issue2) }
end
- it 'shows author in assignee dropdown' do
- page.within '.dropdown-menu-user' do
- expect(page).to have_content(user2.name)
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ visit_issue(project, issue2)
+
+ find('.block.assignee .edit-link').click
+ wait_for_requests
+ end
+
+ it 'shows author in assignee dropdown' do
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'shows author when filtering assignee dropdown' do
+ page.within '.dropdown-menu-user' do
+ find('.dropdown-input-field').set(user2.name)
+
+ wait_for_requests
+
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'assigns yourself' do
+ find('.block.assignee .dropdown-menu-toggle').click
+
+ click_button 'assign yourself'
+
+ wait_for_requests
+
+ find('.block.assignee .edit-link').click
+
+ page.within '.dropdown-menu-user' do
+ expect(page.find('.dropdown-header')).to be_visible
+ expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name)
+ end
end
- end
- it 'shows author when filtering assignee dropdown' do
- page.within '.dropdown-menu-user' do
+ it 'keeps your filtered term after filtering and dismissing the dropdown' do
find('.dropdown-input-field').set(user2.name)
wait_for_requests
- expect(page).to have_content(user2.name)
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_content 'Unassigned'
+ click_link user2.name
+ end
+
+ find('.js-right-sidebar').click
+ find('.block.assignee .edit-link').click
+
+ expect(page.all('.dropdown-menu-user li').length).to eq(1)
+ expect(find('.dropdown-input-field').value).to eq(user2.name)
+ end
+
+ it 'shows label text as "Apply" when assignees are changed' do
+ project.add_developer(user)
+ visit_issue(project, issue2)
+
+ find('.block.assignee .edit-link').click
+ wait_for_requests
+
+ click_on 'Unassigned'
+
+ expect(page).to have_link('Apply')
end
end
+ end
- it 'assigns yourself' do
- find('.block.assignee .dropdown-menu-toggle').click
+ context 'when GraphQL assignees widget feature flag is enabled' do
+ context 'when a privileged user can invite' do
+ it 'shows a link for inviting members and launches invite modal' do
+ project.add_maintainer(user)
+ visit_issue(project, issue2)
- click_button 'assign yourself'
+ open_assignees_dropdown
- wait_for_requests
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_link('Invite members')
+ expect(page).to have_selector('[data-track-event="click_invite_members"]')
+ expect(page).to have_selector('[data-track-label="edit_assignee"]')
+ end
- find('.block.assignee .edit-link').click
+ click_link 'Invite members'
- page.within '.dropdown-menu-user' do
- expect(page.find('.dropdown-header')).to be_visible
- expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name)
+ expect(page).to have_content("You're inviting members to the")
end
end
- it 'keeps your filtered term after filtering and dismissing the dropdown' do
- find('.dropdown-input-field').set(user2.name)
+ context 'when invite_members_version_b experiment is enabled' do
+ before do
+ stub_experiment_for_subject(invite_members_version_b: true)
+ end
+
+ it 'shows a link for inviting members and follows through to modal' do
+ project.add_developer(user)
+ visit_issue(project, issue2)
- wait_for_requests
+ open_assignees_dropdown
- page.within '.dropdown-menu-user' do
- expect(page).not_to have_content 'Unassigned'
- click_link user2.name
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_link('Invite members', href: '#')
+ expect(page).to have_selector('[data-track-event="click_invite_members_version_b"]')
+ expect(page).to have_selector('[data-track-label="edit_assignee"]')
+ end
+
+ click_link 'Invite members'
+
+ expect(page).to have_content("Oops, this feature isn't ready yet")
end
+ end
+
+ context 'when invite_members_version_b experiment is disabled' do
+ it 'shows author in assignee dropdown and no invite link' do
+ project.add_developer(user)
+ visit_issue(project, issue2)
- find('.js-right-sidebar').click
- find('.block.assignee .edit-link').click
+ open_assignees_dropdown
- expect(page.all('.dropdown-menu-user li').length).to eq(1)
- expect(find('.dropdown-input-field').value).to eq(user2.name)
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_link('Invite members')
+ end
+ end
end
- end
- it 'shows label text as "Apply" when assignees are changed' do
- project.add_developer(user)
- visit_issue(project, issue2)
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ visit_issue(project, issue2)
+ end
+
+ it 'shows author in assignee dropdown' do
+ open_assignees_dropdown
+
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'shows author when filtering assignee dropdown' do
+ open_assignees_dropdown
+
+ page.within '.dropdown-menu-user' do
+ find('.js-dropdown-input-field').find('input').set(user2.name)
+
+ wait_for_requests
+
+ expect(page).to have_content(user2.name)
+ end
+ end
+
+ it 'assigns yourself' do
+ click_button 'assign yourself'
+ wait_for_requests
+
+ page.within '.assignee' do
+ expect(page).to have_content(user.name)
+ end
+ end
- find('.block.assignee .edit-link').click
- wait_for_requests
+ it 'keeps your filtered term after filtering and dismissing the dropdown' do
+ open_assignees_dropdown
- click_on 'Unassigned'
+ find('.js-dropdown-input-field').find('input').set(user2.name)
+ wait_for_requests
+
+ page.within '.dropdown-menu-user' do
+ expect(page).not_to have_content 'Unassigned'
+ click_link user2.name
+ end
- expect(page).to have_link('Apply')
+ find('.js-right-sidebar').click
+
+ open_assignees_dropdown
+
+ page.within('.assignee') do
+ expect(page.all('[data-testid="selected-participant"]').length).to eq(1)
+ end
+
+ expect(find('.js-dropdown-input-field').find('input').value).to eq(user2.name)
+ end
+ end
end
end
@@ -171,7 +291,7 @@ RSpec.describe 'Issue Sidebar' do
context 'editing issue labels', :js do
before do
- issue.update(labels: [label])
+ issue.update!(labels: [label])
page.within('.block.labels') do
click_on 'Edit'
end
@@ -334,4 +454,11 @@ RSpec.describe 'Issue Sidebar' do
find('aside.right-sidebar.right-sidebar-collapsed .js-sidebar-toggle').click
find('aside.right-sidebar.right-sidebar-expanded')
end
+
+ def open_assignees_dropdown
+ page.within('.assignee') do
+ click_button('Edit')
+ wait_for_requests
+ end
+ end
end
diff --git a/spec/features/issues/markdown_toolbar_spec.rb b/spec/features/issues/markdown_toolbar_spec.rb
index 6dc1cbfb2d7..aad5d319bc4 100644
--- a/spec/features/issues/markdown_toolbar_spec.rb
+++ b/spec/features/issues/markdown_toolbar_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Issue markdown toolbar', :js do
- let(:project) { create(:project, :public) }
- let(:issue) { create(:issue, project: project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
@@ -14,28 +14,22 @@ RSpec.describe 'Issue markdown toolbar', :js do
end
it "doesn't include first new line when adding bold" do
- find('#note-body').native.send_keys('test')
- find('#note-body').native.send_key(:enter)
- find('#note-body').native.send_keys('bold')
+ fill_in 'Comment', with: "test\nbold"
- find('.js-main-target-form #note-body')
- page.evaluate_script('document.querySelectorAll(".js-main-target-form #note-body")[0].setSelectionRange(4, 9)')
+ page.evaluate_script('document.getElementById("note-body").setSelectionRange(4, 9)')
- first('.toolbar-btn').click
+ click_button 'Add bold text'
- expect(find('#note-body')[:value]).to eq("test\n**bold**\n")
+ expect(find_field('Comment').value).to eq("test\n**bold**\n")
end
it "doesn't include first new line when adding underline" do
- find('#note-body').native.send_keys('test')
- find('#note-body').native.send_key(:enter)
- find('#note-body').native.send_keys('underline')
+ fill_in 'Comment', with: "test\nunderline"
- find('.js-main-target-form #note-body')
- page.evaluate_script('document.querySelectorAll(".js-main-target-form #note-body")[0].setSelectionRange(4, 50)')
+ page.evaluate_script('document.getElementById("note-body").setSelectionRange(4, 50)')
- all('.toolbar-btn')[1].click
+ click_button 'Add italic text'
- expect(find('#note-body')[:value]).to eq("test\n_underline_\n")
+ expect(find_field('Comment').value).to eq("test\n_underline_\n")
end
end
diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb
index bc4c67fdd79..5e02d5ad038 100644
--- a/spec/features/issues/note_polling_spec.rb
+++ b/spec/features/issues/note_polling_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe 'Issue notes polling', :js do
end
def update_note(note, new_text)
- note.update(note: new_text)
+ note.update!(note: new_text)
wait_for_requests
end
diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb
index aec806c566d..461030d3176 100644
--- a/spec/features/issues/spam_issues_spec.rb
+++ b/spec/features/issues/spam_issues_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'New issue', :js do
end
it 'rejects issue creation' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).to have_content('discarded')
expect(page).not_to have_content('potential spam')
@@ -51,7 +51,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -63,14 +63,14 @@ RSpec.describe 'New issue', :js do
end
it 'allows issue creation' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page.find('.issue-details h2.title')).to have_content('issue title')
expect(page.find('.issue-details .description')).to have_content('issue description')
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -101,14 +101,14 @@ RSpec.describe 'New issue', :js do
fill_in 'issue_title', with: 'issue title'
fill_in 'issue_description', with: 'issue description'
- click_button 'Submit issue'
+ click_button 'Create issue'
# it is impossible to test reCAPTCHA automatically and there is no possibility to fill in recaptcha
# reCAPTCHA verification is skipped in test environment and it always returns true
expect(page).not_to have_content('issue title')
expect(page).to have_css('.recaptcha')
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page.find('.issue-details h2.title')).to have_content('issue title')
expect(page.find('.issue-details .description')).to have_content('issue description')
@@ -122,7 +122,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates an issue without a need to solve reCAPTCHA' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).not_to have_css('.recaptcha')
expect(page.find('.issue-details h2.title')).to have_content('issue title')
@@ -130,7 +130,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -148,7 +148,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates an issue without a need to solve reCaptcha' do
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).not_to have_css('.recaptcha')
expect(page.find('.issue-details h2.title')).to have_content('issue title')
@@ -156,7 +156,7 @@ RSpec.describe 'New issue', :js do
end
it 'creates a spam log record' do
- expect { click_button 'Submit issue' }
+ expect { click_button 'Create issue' }
.to log_spam(title: 'issue title', description: 'issue description', user_id: user.id, noteable_type: 'Issue')
end
end
@@ -178,7 +178,7 @@ RSpec.describe 'New issue', :js do
fill_in 'issue_title', with: 'issue title'
fill_in 'issue_description', with: 'issue description'
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page.find('.issue-details h2.title')).to have_content('issue title')
expect(page.find('.issue-details .description')).to have_content('issue description')
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index 004488f2f64..09d3ad15641 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -57,17 +57,9 @@ RSpec.describe "User comments on issue", :js do
project.add_maintainer(user)
create(:label, project: project, title: 'label')
- page.within '.timeline-content-form' do
- find('#note-body').native.send_keys('/l')
- end
-
- wait_for_requests
-
- expect(page).to have_selector('.atwho-container')
+ fill_in 'Comment', with: '/l'
- page.within '.atwho-container #at-view-commands' do
- expect(find('li', match: :first)).to have_content('/label')
- end
+ expect(find_highlighted_autocomplete_item).to have_content('/label')
end
end
@@ -110,4 +102,10 @@ RSpec.describe "User comments on issue", :js do
end
end
end
+
+ private
+
+ def find_highlighted_autocomplete_item
+ find('.atwho-view li.cur', visible: true)
+ end
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 e225a45481d..6e8b3e4fb7c 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
@@ -150,7 +150,7 @@ RSpec.describe 'User creates branch and merge request on issue page', :js do
context 'when merge requests are disabled' do
before do
- project.project_feature.update(merge_requests_access_level: 0)
+ project.project_feature.update!(merge_requests_access_level: 0)
visit project_issue_path(project, issue)
end
diff --git a/spec/features/issues/user_creates_confidential_merge_request_spec.rb b/spec/features/issues/user_creates_confidential_merge_request_spec.rb
index ea96165d7b7..6b4526cd624 100644
--- a/spec/features/issues/user_creates_confidential_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_confidential_merge_request_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe 'User creates confidential merge request on issue page', :js do
let(:forked_project) { fork_project(project, user, repository: true) }
before do
- forked_project.update(visibility: Gitlab::VisibilityLevel::PRIVATE)
+ forked_project.update!(visibility: Gitlab::VisibilityLevel::PRIVATE)
visit_confidential_issue
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 98f9ed6c6a2..e2e204f03db 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe "User creates issue" do
.and have_no_content("Milestone")
expect(page.find('#issue_title')['placeholder']).to eq 'Title'
- expect(page.find('#issue_description')['placeholder']).to eq 'Write a comment or drag your files here…'
+ expect(page.find('#issue_description')['placeholder']).to eq 'Write a description or drag your files here…'
end
issue_title = "500 error on profile"
@@ -54,7 +54,7 @@ RSpec.describe "User creates issue" do
first('.js-md').click
first('.rspec-issuable-form-description').native.send_keys('Description')
- click_button("Submit issue")
+ click_button("Create issue")
expect(page).to have_content(issue_title)
.and have_content(user.name)
@@ -112,7 +112,7 @@ RSpec.describe "User creates issue" do
fill_in("Title", with: issue_title)
click_button("Label")
click_link(label_titles.first)
- click_button("Submit issue")
+ click_button("Create issue")
expect(page).to have_content(issue_title)
.and have_content(user.name)
@@ -135,7 +135,7 @@ RSpec.describe "User creates issue" do
expect(find('#issuable-due-date').value).to eq date.to_s
- click_button 'Submit issue'
+ click_button 'Create issue'
page.within '.issuable-sidebar' do
expect(page).to have_content date.to_s(:medium)
@@ -259,7 +259,7 @@ RSpec.describe "User creates issue" do
fill_in 'issue_title', with: 'bug 345'
fill_in 'issue_description', with: 'bug description'
- click_button 'Submit issue'
+ click_button 'Create issue'
end
end
end
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 9d4a6cdb522..1bbb96ff479 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -78,7 +78,7 @@ RSpec.describe "Issues > User edits issue", :js do
end
it 'warns about version conflict' do
- issue.update(title: "New title")
+ issue.update!(title: "New title")
fill_in 'issue_title', with: 'bug 345'
fill_in 'issue_description', with: 'bug description'
@@ -142,10 +142,8 @@ RSpec.describe "Issues > User edits issue", :js do
it 'can remove label without removing label added via quick action', :aggregate_failures do
# Add `syzygy` label with a quick action
- note = find('#note-body')
- page.within '.timeline-content-form' do
- note.native.send_keys('/label ~syzygy')
- end
+ fill_in 'Comment', with: '/label ~syzygy'
+
click_button 'Comment'
wait_for_requests
@@ -169,80 +167,165 @@ RSpec.describe "Issues > User edits issue", :js do
end
describe 'update assignee' do
- context 'by authorized user' do
- def close_dropdown_menu_if_visible
- find('.dropdown-menu-toggle', visible: :all).tap do |toggle|
- toggle.click if toggle.visible?
- end
+ context 'when GraphQL assignees widget feature flag is disabled' do
+ before do
+ stub_feature_flags(issue_assignees_widget: false)
end
- it 'allows user to select unassigned' do
- visit project_issue_path(project, issue)
+ context 'by authorized user' do
+ def close_dropdown_menu_if_visible
+ find('.dropdown-menu-toggle', visible: :all).tap do |toggle|
+ toggle.click if toggle.visible?
+ end
+ end
- page.within('.assignee') do
- expect(page).to have_content "#{user.name}"
+ it 'allows user to select unassigned' do
+ visit project_issue_path(project, issue)
- click_link 'Edit'
- click_link 'Unassigned'
- first('.title').click
- expect(page).to have_content 'None - assign yourself'
+ page.within('.assignee') do
+ expect(page).to have_content "#{user.name}"
+
+ click_link 'Edit'
+ click_link 'Unassigned'
+ first('.title').click
+
+ expect(page).to have_content 'None - assign yourself'
+ end
end
- end
- it 'allows user to select an assignee' do
- issue2 = create(:issue, project: project, author: user)
- visit project_issue_path(project, issue2)
+ it 'allows user to select an assignee' do
+ issue2 = create(:issue, project: project, author: user)
+ visit project_issue_path(project, issue2)
- page.within('.assignee') do
- expect(page).to have_content "None"
+ page.within('.assignee') do
+ expect(page).to have_content "None"
+ end
+
+ page.within '.assignee' do
+ click_link 'Edit'
+ end
+
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
+
+ page.within('.assignee') do
+ expect(page).to have_content user.name
+ end
end
- page.within '.assignee' do
- click_link 'Edit'
+ it 'allows user to unselect themselves' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
+
+ visit project_issue_path(project, issue2)
+
+ page.within '.assignee' do
+ expect(page).to have_content user.name
+
+ click_link 'Edit'
+ click_link user.name
+
+ close_dropdown_menu_if_visible
+
+ page.within '.value .assign-yourself' do
+ expect(page).to have_content "None"
+ end
+ end
end
+ end
+
+ context 'by unauthorized user' do
+ let(:guest) { create(:user) }
- page.within '.dropdown-menu-user' do
- click_link user.name
+ before do
+ project.add_guest(guest)
end
- page.within('.assignee') do
- expect(page).to have_content user.name
+ it 'shows assignee text' do
+ sign_out(:user)
+ sign_in(guest)
+
+ visit project_issue_path(project, issue)
+ expect(page).to have_content issue.assignees.first.name
end
end
+ end
- it 'allows user to unselect themselves' do
- issue2 = create(:issue, project: project, author: user, assignees: [user])
+ context 'when GraphQL assignees widget feature flag is enabled' do
+ context 'by authorized user' do
+ it 'allows user to select unassigned' do
+ visit project_issue_path(project, issue)
- visit project_issue_path(project, issue2)
+ page.within('.assignee') do
+ expect(page).to have_content "#{user.name}"
- page.within '.assignee' do
- expect(page).to have_content user.name
+ click_button('Edit')
+ wait_for_requests
- click_link 'Edit'
- click_link user.name
+ find('[data-testid="unassign"]').click
+ find('[data-testid="title"]').click
+ wait_for_requests
+
+ expect(page).to have_content 'None - assign yourself'
+ end
+ end
- close_dropdown_menu_if_visible
+ it 'allows user to select an assignee' do
+ issue2 = create(:issue, project: project, author: user)
+ visit project_issue_path(project, issue2)
- page.within '.value .assign-yourself' do
+ page.within('.assignee') do
expect(page).to have_content "None"
+ click_button('Edit')
+ wait_for_requests
+ end
+
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
+
+ page.within('.assignee') do
+ find('[data-testid="title"]').click
+ wait_for_requests
+
+ expect(page).to have_content user.name
end
end
- end
- end
- context 'by unauthorized user' do
- let(:guest) { create(:user) }
+ it 'allows user to unselect themselves' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
- before do
- project.add_guest(guest)
+ visit project_issue_path(project, issue2)
+
+ page.within '.assignee' do
+ expect(page).to have_content user.name
+
+ click_button('Edit')
+ wait_for_requests
+ click_link user.name
+
+ find('[data-testid="title"]').click
+ wait_for_requests
+
+ expect(page).to have_content "None"
+ end
+ end
end
- it 'shows assignee text' do
- sign_out(:user)
- sign_in(guest)
+ context 'by unauthorized user' do
+ let(:guest) { create(:user) }
- visit project_issue_path(project, issue)
- expect(page).to have_content issue.assignees.first.name
+ before do
+ project.add_guest(guest)
+ end
+
+ it 'shows assignee text' do
+ sign_out(:user)
+ sign_in(guest)
+
+ visit project_issue_path(project, issue)
+ expect(page).to have_content issue.assignees.first.name
+ end
end
end
end
@@ -309,7 +392,7 @@ RSpec.describe "Issues > User edits issue", :js do
before do
project.add_guest(guest)
issue.milestone = milestone
- issue.save
+ issue.save!
end
it 'shows milestone text' do
@@ -326,24 +409,23 @@ RSpec.describe "Issues > User edits issue", :js do
it 'adds due date to issue' do
date = Date.today.at_beginning_of_month + 2.days
- page.within '.due_date' do
- click_link 'Edit'
-
+ page.within '[data-testid="due-date"]' do
+ click_button 'Edit'
page.within '.pika-single' do
click_button date.day
end
wait_for_requests
- expect(find('.value').text).to have_content date.strftime('%b %-d, %Y')
+ expect(find('[data-testid="sidebar-duedate-value"]').text).to have_content date.strftime('%b %-d, %Y')
end
end
it 'removes due date from issue' do
date = Date.today.at_beginning_of_month + 2.days
- page.within '.due_date' do
- click_link 'Edit'
+ page.within '[data-testid="due-date"]' do
+ click_button 'Edit'
page.within '.pika-single' do
click_button date.day
@@ -353,7 +435,7 @@ RSpec.describe "Issues > User edits issue", :js do
expect(page).to have_no_content 'None'
- click_link 'remove due date'
+ click_button 'remove due date'
expect(page).to have_content 'None'
end
end
diff --git a/spec/features/issues/user_filters_issues_spec.rb b/spec/features/issues/user_filters_issues_spec.rb
index 1b246181523..5d05df6aaf0 100644
--- a/spec/features/issues/user_filters_issues_spec.rb
+++ b/spec/features/issues/user_filters_issues_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'User filters issues', :js do
@issue = Issue.find_by(title: 'foobar')
@issue.milestone = create(:milestone, project: project)
@issue.assignees = []
- @issue.save
+ @issue.save!
end
let(:issue) { @issue }
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 1c7bc5f239f..e862f7030c0 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe 'User interacts with awards' do
let(:user) { create(:user) }
+ before do
+ stub_feature_flags(improved_emoji_picker: false)
+ end
+
describe 'User interacts with awards in an issue', :js do
let(:issue) { create(:issue, project: project)}
let(:project) { create(:project) }
diff --git a/spec/features/issues/user_invites_from_a_comment_spec.rb b/spec/features/issues/user_invites_from_a_comment_spec.rb
new file mode 100644
index 00000000000..82061f6ed79
--- /dev/null
+++ b/spec/features/issues/user_invites_from_a_comment_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "User invites from a comment", :js do
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:user) { project.owner }
+
+ before do
+ sign_in(user)
+ end
+
+ it "launches the invite modal from invite link on a comment" do
+ stub_experiments(invite_members_in_comment: :invite_member_link)
+
+ visit project_issue_path(project, issue)
+
+ page.within(".new-note") do
+ click_button 'Invite Member'
+ end
+
+ expect(page).to have_content("You're inviting members to the")
+ end
+end
diff --git a/spec/features/issues/user_sees_live_update_spec.rb b/spec/features/issues/user_sees_live_update_spec.rb
index 79c6978cbc0..7e4880f209e 100644
--- a/spec/features/issues/user_sees_live_update_spec.rb
+++ b/spec/features/issues/user_sees_live_update_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'Issues > User sees live update', :js do
expect(page).to have_text("new title")
- issue.update(title: "updated title")
+ issue.update!(title: "updated title")
wait_for_requests
expect(page).to have_text("updated title")
diff --git a/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb b/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb
index 7a2b637e48e..6473fe01052 100644
--- a/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb
+++ b/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb
@@ -19,11 +19,14 @@ RSpec.describe 'Issues > Real-time sidebar', :js do
expect(page.find('.assignee')).to have_content 'None'
end
- gitlab_sign_in(user)
+ sign_in(user)
+
visit project_issue_path(project, issue)
expect(page.find('.assignee')).to have_content 'None'
click_button 'assign yourself'
+ wait_for_requests
+ expect(page.find('.assignee')).to have_content user.name
using_session :other_session do
expect(page.find('.assignee')).to have_content user.name
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index f0bb055c6f2..c161e1deb83 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe "User sorts issues" do
it 'sorts by most recently updated', :js do
issue3.updated_at = Time.now + 100
- issue3.save
+ issue3.save!
visit project_issues_path(project, sort: sort_value_recently_updated)
expect(first_issue).to include('baz')
@@ -85,8 +85,8 @@ RSpec.describe "User sorts issues" do
describe 'sorting by due date', :js do
before do
- issue1.update(due_date: 1.day.from_now)
- issue2.update(due_date: 6.days.from_now)
+ issue1.update!(due_date: 1.day.from_now)
+ issue2.update!(due_date: 6.days.from_now)
end
it 'sorts by due date' do
@@ -96,7 +96,7 @@ RSpec.describe "User sorts issues" do
end
it 'sorts by due date by excluding nil due dates' do
- issue2.update(due_date: nil)
+ issue2.update!(due_date: nil)
visit project_issues_path(project, sort: sort_value_due_date)
@@ -111,7 +111,7 @@ RSpec.describe "User sorts issues" do
end
it 'sorts by least recently due date by excluding nil due dates' do
- issue2.update(due_date: nil)
+ issue2.update!(due_date: nil)
visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later)
@@ -122,8 +122,8 @@ RSpec.describe "User sorts issues" do
describe 'filtering by due date', :js do
before do
- issue1.update(due_date: 1.day.from_now)
- issue2.update(due_date: 6.days.from_now)
+ issue1.update!(due_date: 1.day.from_now)
+ issue2.update!(due_date: 6.days.from_now)
end
it 'filters by none' do
@@ -147,9 +147,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by due this week' do
- issue1.update(due_date: Date.today.beginning_of_week + 2.days)
- issue2.update(due_date: Date.today.end_of_week)
- issue3.update(due_date: Date.today - 8.days)
+ issue1.update!(due_date: Date.today.beginning_of_week + 2.days)
+ issue2.update!(due_date: Date.today.end_of_week)
+ issue3.update!(due_date: Date.today - 8.days)
visit project_issues_path(project, due_date: Issue::DueThisWeek.name)
@@ -161,9 +161,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by due this month' do
- issue1.update(due_date: Date.today.beginning_of_month + 2.days)
- issue2.update(due_date: Date.today.end_of_month)
- issue3.update(due_date: Date.today - 50.days)
+ issue1.update!(due_date: Date.today.beginning_of_month + 2.days)
+ issue2.update!(due_date: Date.today.end_of_month)
+ issue3.update!(due_date: Date.today - 50.days)
visit project_issues_path(project, due_date: Issue::DueThisMonth.name)
@@ -175,9 +175,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by overdue' do
- issue1.update(due_date: Date.today + 2.days)
- issue2.update(due_date: Date.today + 20.days)
- issue3.update(due_date: Date.yesterday)
+ issue1.update!(due_date: Date.today + 2.days)
+ issue2.update!(due_date: Date.today + 20.days)
+ issue3.update!(due_date: Date.yesterday)
visit project_issues_path(project, due_date: Issue::Overdue.name)
@@ -189,9 +189,9 @@ RSpec.describe "User sorts issues" do
end
it 'filters by due next month and previous two weeks' do
- issue1.update(due_date: Date.today - 4.weeks)
- issue2.update(due_date: (Date.today + 2.months).beginning_of_month)
- issue3.update(due_date: Date.yesterday)
+ issue1.update!(due_date: Date.today - 4.weeks)
+ issue2.update!(due_date: (Date.today + 2.months).beginning_of_month)
+ issue3.update!(due_date: Date.yesterday)
visit project_issues_path(project, due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name)
@@ -206,9 +206,9 @@ RSpec.describe "User sorts issues" do
describe 'sorting by milestone', :js do
before do
issue1.milestone = newer_due_milestone
- issue1.save
+ issue1.save!
issue2.milestone = later_due_milestone
- issue2.save
+ issue2.save!
end
it 'sorts by milestone' do
@@ -224,9 +224,9 @@ RSpec.describe "User sorts issues" do
before do
issue1.assignees << user2
- issue1.save
+ issue1.save!
issue2.assignees << user2
- issue2.save
+ issue2.save!
end
it 'sorts with a filter applied' do
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index e84b300a748..3208ad82c03 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -63,8 +63,8 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
end
aggregate_failures 'parses fenced code blocks' do
- expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.c')
- expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.python')
+ expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.language-c')
+ expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.language-python')
end
aggregate_failures 'parses mermaid code block' do
@@ -288,9 +288,10 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
@wiki = @feat.wiki
@wiki_page = @feat.wiki_page
- path = 'images/example.jpg'
- gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
- expect(@wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
+ name = 'example.jpg'
+ path = "images/#{name}"
+ blob = double(name: name, path: path, mime_type: 'image/jpeg', data: nil)
+ expect(@wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(blob))
allow(@wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
@html = markdown(@feat.raw_markdown, { pipeline: :wiki, wiki: @wiki, page_slug: @wiki_page.slug })
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index 25f2707146d..19680a827bf 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'adds draft note' do
- write_comment
+ write_diff_comment
expect(find('.draft-note-component')).to have_content('Line is wrong')
@@ -38,7 +38,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'publishes review' do
- write_comment
+ write_diff_comment
page.within('.review-bar-content') do
click_button 'Submit review'
@@ -52,7 +52,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'publishes single comment' do
- write_comment
+ write_diff_comment
click_button 'Add comment now'
@@ -64,7 +64,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'deletes draft note' do
- write_comment
+ write_diff_comment
accept_alert { find('.js-note-delete').click }
@@ -74,21 +74,70 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'edits draft note' do
- write_comment
+ write_diff_comment
find('.js-note-edit').click
# make sure comment form is in view
execute_script("window.scrollBy(0, 200)")
- page.within('.js-discussion-note-form') do
- fill_in('note_note', with: 'Testing update')
- click_button('Save comment')
+ write_comment(text: 'Testing update', button_text: 'Save comment')
+
+ expect(page).to have_selector('.draft-note-component', text: 'Testing update')
+ end
+
+ context 'with image and file draft note' do
+ let(:merge_request) { create(:merge_request_with_diffs, :with_image_diffs, source_project: project) }
+ let!(:draft_on_text) { create(:draft_note_on_text_diff, merge_request: merge_request, author: user, path: 'README.md', note: 'Lorem ipsum on text...') }
+ let!(:draft_on_image) { create(:draft_note_on_image_diff, merge_request: merge_request, author: user, path: 'files/images/ee_repo_logo.png', note: 'Lorem ipsum on an image...') }
+
+ it 'does not show in overview' do
+ visit_overview
+
+ expect(page).to have_no_text(draft_on_text.note)
+ expect(page).to have_no_text(draft_on_image.note)
end
+ end
- wait_for_requests
+ context 'adding single comment to review' do
+ before do
+ visit_overview
+ end
- expect(page).to have_selector('.draft-note-component', text: 'Testing update')
+ it 'at first does not show `Add to review` and `Add comment now` buttons' do
+ expect(page).to have_no_button('Add to review')
+ expect(page).to have_no_button('Add comment now')
+ end
+
+ context 'when review has started' do
+ before do
+ visit_diffs
+
+ write_diff_comment
+
+ visit_overview
+ end
+
+ it 'can add comment to review' do
+ write_comment(selector: '.js-main-target-form', field: 'note-body', text: 'Its a draft comment', button_text: 'Add to review')
+
+ expect(page).to have_selector('.draft-note-component', text: 'Its a draft comment')
+
+ click_button('Pending comments')
+
+ expect(page).to have_text('2 pending comments')
+ end
+
+ it 'can add comment right away' do
+ write_comment(selector: '.js-main-target-form', field: 'note-body', text: 'Its a regular comment', button_text: 'Add comment now')
+
+ expect(page).to have_selector('.note:not(.draft-note)', text: 'Its a regular comment')
+
+ click_button('Pending comments')
+
+ expect(page).to have_text('1 pending comment')
+ end
+ end
end
context 'in parallel diff' do
@@ -197,46 +246,51 @@ RSpec.describe 'Merge request > Batch comments', :js do
wait_for_requests
end
- def write_comment(button_text: 'Start a review', text: 'Line is wrong')
- click_diff_line(find("[id='#{sample_compare.changes[0][:line_code]}']"))
-
- page.within('.js-discussion-note-form') do
- fill_in('note_note', with: text)
- click_button(button_text)
- end
+ def visit_overview
+ visit project_merge_request_path(merge_request.project, merge_request)
wait_for_requests
end
- def write_parallel_comment(line, button_text: 'Start a review', text: 'Line is wrong')
+ def write_diff_comment(**params)
+ click_diff_line(find("[id='#{sample_compare.changes[0][:line_code]}']"))
+
+ write_comment(**params)
+ end
+
+ def write_parallel_comment(line, **params)
find("td[id='#{line}']").hover
find(".is-over button").click
- page.within("form[data-line-code='#{line}']") do
- fill_in('note_note', with: text)
+ write_comment(selector: "form[data-line-code='#{line}']", **params)
+ end
+
+ def write_comment(selector: '.js-discussion-note-form', field: 'note_note', button_text: 'Start a review', text: 'Line is wrong')
+ page.within(selector) do
+ fill_in(field, with: text)
click_button(button_text)
end
wait_for_requests
end
-end
-def write_reply_to_discussion(button_text: 'Start a review', text: 'Line is wrong', resolve: false, unresolve: false)
- page.within(first('.diff-files-holder .discussion-reply-holder')) do
- find_field('Reply…', match: :first).click
+ def write_reply_to_discussion(button_text: 'Start a review', text: 'Line is wrong', resolve: false, unresolve: false)
+ page.within(first('.diff-files-holder .discussion-reply-holder')) do
+ find_field('Reply…', match: :first).click
- fill_in('note_note', with: text)
+ fill_in('note_note', with: text)
- if resolve
- page.check('Resolve thread')
- end
+ if resolve
+ page.check('Resolve thread')
+ end
+
+ if unresolve
+ page.check('Unresolve thread')
+ end
- if unresolve
- page.check('Unresolve thread')
+ click_button(button_text)
end
- click_button(button_text)
+ wait_for_requests
end
-
- wait_for_requests
end
diff --git a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
index fd13083c185..d36abf86518 100644
--- a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
+++ b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'create a merge request, allowing commits from members who can me
check 'Allow commits from members who can merge to the target branch'
- click_button 'Submit merge request'
+ click_button 'Create merge request'
wait_for_requests
diff --git a/spec/features/merge_request/user_awards_emoji_spec.rb b/spec/features/merge_request/user_awards_emoji_spec.rb
index 62e4209f386..6f46cc20cba 100644
--- a/spec/features/merge_request/user_awards_emoji_spec.rb
+++ b/spec/features/merge_request/user_awards_emoji_spec.rb
@@ -17,33 +17,28 @@ RSpec.describe 'Merge request > User awards emoji', :js do
end
it 'adds award to merge request' do
- first('.js-emoji-btn').click
- expect(page).to have_selector('.js-emoji-btn.active')
- expect(first('.js-emoji-btn')).to have_content '1'
+ first('[data-testid="award-button"]').click
+ expect(page).to have_selector('[data-testid="award-button"].is-active')
+ expect(first('[data-testid="award-button"]')).to have_content '1'
visit project_merge_request_path(project, merge_request)
- expect(first('.js-emoji-btn')).to have_content '1'
+ expect(first('[data-testid="award-button"]')).to have_content '1'
end
it 'removes award from merge request' do
- first('.js-emoji-btn').click
- find('.js-emoji-btn.active').click
- expect(first('.js-emoji-btn')).to have_content '0'
+ first('[data-testid="award-button"]').click
+ find('[data-testid="award-button"].is-active').click
+ expect(first('[data-testid="award-button"]')).to have_content '0'
visit project_merge_request_path(project, merge_request)
- expect(first('.js-emoji-btn')).to have_content '0'
- end
-
- it 'has only one menu on the page' do
- first('.js-add-award').click
- expect(page).to have_selector('.emoji-menu')
-
- expect(page).to have_selector('.emoji-menu', count: 1)
+ expect(first('[data-testid="award-button"]')).to have_content '0'
end
it 'adds awards to note' do
- first('.js-note-emoji').click
- first('.emoji-menu .js-emoji-btn').click
+ page.within('.note-actions') do
+ first('.note-emoji-button').click
+ find('gl-emoji[data-name="8ball"]').click
+ end
wait_for_requests
diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb
index 37d329d4d5d..119cf31098c 100644
--- a/spec/features/merge_request/user_creates_merge_request_spec.rb
+++ b/spec/features/merge_request/user_creates_merge_request_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe "User creates a merge request", :js do
end
fill_in("Title", with: title)
- click_button("Submit merge request")
+ click_button("Create merge request")
page.within(".merge-request") do
expect(page).to have_content(title)
@@ -87,7 +87,7 @@ RSpec.describe "User creates a merge request", :js do
click_button("Compare branches and continue")
- expect(page).to have_css("h3.page-title", text: "New Merge Request")
+ expect(page).to have_css("h3.page-title", text: "New merge request")
page.within("form#new_merge_request") do
fill_in("Title", with: title)
@@ -103,7 +103,7 @@ RSpec.describe "User creates a merge request", :js do
end
find('.js-assignee-search').click
- click_button("Submit merge request")
+ click_button("Create merge request")
expect(page).to have_content(title).and have_content("Request to merge #{user.namespace.path}:#{source_branch} into master")
end
diff --git a/spec/features/merge_request/user_invites_from_a_comment_spec.rb b/spec/features/merge_request/user_invites_from_a_comment_spec.rb
new file mode 100644
index 00000000000..79865094fd0
--- /dev/null
+++ b/spec/features/merge_request/user_invites_from_a_comment_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "User invites from a comment", :js do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+ let_it_be(:user) { project.owner }
+
+ before do
+ sign_in(user)
+ end
+
+ it "launches the invite modal from invite link on a comment" do
+ stub_experiments(invite_members_in_comment: :invite_member_link)
+
+ visit project_merge_request_path(project, merge_request)
+
+ page.within(".new-note") do
+ click_button 'Invite Member'
+ end
+
+ expect(page).to have_content("You're inviting members to the")
+ end
+end
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index 3099a893dc2..a6dfae72912 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -173,7 +173,7 @@ RSpec.describe 'Merge request > User posts notes', :js do
it 'allows using markdown buttons after saving a note and then trying to edit it again' do
page.within('.current-note-edit-form') do
fill_in 'note[note]', with: 'This is the new content'
- find('.btn-success').click
+ find('.btn-confirm').click
end
find('.note').hover
@@ -182,16 +182,16 @@ RSpec.describe 'Merge request > User posts notes', :js do
find('.js-note-edit').click
page.within('.current-note-edit-form') do
- expect(find('#note_note').value).to include('This is the new content')
+ expect(find_field('note[note]').value).to include('This is the new content')
first('.js-md').click
- expect(find('#note_note').value).to include('This is the new content****')
+ expect(find_field('note[note]').value).to include('This is the new content****')
end
end
it 'appends the edited at time to the note' do
page.within('.current-note-edit-form') do
fill_in 'note[note]', with: 'Some new content'
- find('.btn-success').click
+ find('.btn-confirm').click
end
page.within("#note_#{note.id}") do
diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
index caa04059469..9a3f97a0943 100644
--- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
+++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
@@ -15,10 +15,6 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
diff_refs: merge_request.diff_refs)
end
- before do
- stub_feature_flags(remove_resolve_note: false)
- end
-
context 'no threads' do
before do
project.add_maintainer(user)
@@ -67,7 +63,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark thread as resolved' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
expect(page).to have_selector('.discussion-body', visible: false)
@@ -84,7 +80,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to unresolve thread' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
click_button 'Unresolve thread'
end
@@ -96,7 +92,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
describe 'resolved thread' do
before do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
visit_merge_request
@@ -197,7 +193,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to resolve from reply form without a comment' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
page.within '.line-resolve-all-container' do
@@ -234,7 +230,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'hides jump to next button when all resolved' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
expect(page).to have_selector('.discussion-next-btn', visible: false)
@@ -264,7 +260,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
visit_merge_request
end
- it 'does not mark thread as resolved when resolving single note' do
+ it 'marks thread as resolved when resolving single note' do
page.within("#note_#{note.id}") do
first('.line-resolve-btn').click
@@ -273,15 +269,13 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
expect(first('.line-resolve-btn')['aria-label']).to eq("Resolved by #{user.name}")
end
- expect(page).to have_content('Last updated')
-
page.within '.line-resolve-all-container' do
- expect(page).to have_content('1 unresolved thread')
+ expect(page).to have_content('All threads resolved')
end
end
it 'resolves thread' do
- resolve_buttons = page.all('.note .line-resolve-btn', count: 2)
+ resolve_buttons = page.all('.note .line-resolve-btn', count: 1)
resolve_buttons.each do |button|
button.click
end
@@ -332,7 +326,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark all threads as resolved' do
page.all('.discussion-reply-holder', count: 2).each do |reply_holder|
page.within reply_holder do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
end
@@ -344,7 +338,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to quickly scroll to next unresolved thread' do
page.within('.discussion-reply-holder', match: :first) do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
page.within '.line-resolve-all-container' do
@@ -416,7 +410,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark thread as resolved' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
end
page.within '.diff-content .note' do
@@ -431,7 +425,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to unresolve thread' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
click_button 'Unresolve thread'
end
@@ -459,7 +453,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to comment & unresolve thread' do
page.within '.diff-content' do
- click_button 'Resolve thread'
+ find('button[data-qa-selector="resolve_discussion_button"]').click
find_field('Reply…').click
diff --git a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
index 95e435a333e..d8b258bac47 100644
--- a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
+++ b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'New merge request breadcrumb' do
it 'displays link to project merge requests and new merge request' do
page.within '.breadcrumbs' do
- expect(find_link('Merge Requests')[:href]).to end_with(project_merge_requests_path(project))
+ expect(find_link('Merge requests')[:href]).to end_with(project_merge_requests_path(project))
expect(find_link('New')[:href]).to end_with(project_new_merge_request_path(project))
end
end
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 ad0e9b48903..733b5a97fea 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
@@ -26,7 +26,6 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
end
before do
- stub_feature_flags(new_pipelines_table: false)
stub_application_setting(auto_devops_enabled: false)
stub_ci_pipeline_yaml_file(YAML.dump(config))
project.add_maintainer(user)
@@ -62,7 +61,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees branch pipelines and detached merge request pipelines in correct order' do
page.within('.ci-table') do
- expect(page).to have_selector('.ci-pending', count: 2)
+ expect(page).to have_selector('.ci-created', count: 2)
expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
end
end
@@ -154,7 +153,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline succeeds' do
before do
- detached_merge_request_pipeline.succeed!
+ detached_merge_request_pipeline.reload.succeed!
wait_for_requests
end
@@ -168,7 +167,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when branch pipeline succeeds' do
before do
click_link 'Overview'
- push_pipeline.succeed!
+ push_pipeline.reload.succeed!
wait_for_requests
end
@@ -197,7 +196,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'sees a branch pipeline in pipeline tab' do
page.within('.ci-table') do
- expect(page).to have_selector('.ci-pending', count: 1)
+ expect(page).to have_selector('.ci-created', count: 1)
expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{push_pipeline.id}")
end
end
@@ -333,6 +332,31 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
end
end
+ context 'when the latest pipeline is running in the parent project' do
+ before do
+ Ci::CreatePipelineService.new(project, user, ref: 'feature')
+ .execute(:merge_request_event, merge_request: merge_request)
+ end
+
+ context 'when the previous pipeline failed in the fork project' do
+ before do
+ detached_merge_request_pipeline.reload.drop!
+ end
+
+ context 'when the parent project enables pipeline must succeed' do
+ before do
+ project.update!(only_allow_merge_if_pipeline_succeeds: true)
+ end
+
+ it 'shows MWPS button' do
+ visit project_merge_request_path(project, merge_request)
+
+ expect(page).to have_button('Merge when pipeline succeeds')
+ end
+ end
+ end
+ end
+
context 'when a user merges a merge request from a forked project to the parent project' do
before do
click_link("Overview")
@@ -351,7 +375,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline succeeds' do
before do
- detached_merge_request_pipeline.succeed!
+ detached_merge_request_pipeline.reload.succeed!
wait_for_requests
end
@@ -364,7 +388,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when branch pipeline succeeds' do
before do
- push_pipeline.succeed!
+ push_pipeline.reload.succeed!
wait_for_requests
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 05fa5459e06..0cb4107c21d 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
end
it 'shows widget status after creating new merge request' do
- click_button 'Submit merge request'
+ click_button 'Create merge request'
wait_for_requests
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 c0dc2ec3baf..e5592ae9535 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
@@ -23,7 +23,7 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
end
it 'displays a mini pipeline graph' do
- expect(page).to have_selector('.mr-widget-pipeline-graph')
+ expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
end
context 'as json' do
@@ -57,6 +57,10 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
first(dropdown_selector)
end
+ before do
+ wait_for_requests
+ end
+
# Status icon button styles should update as described in
# https://gitlab.com/gitlab-org/gitlab-foss/issues/42769
it 'has unique styles for default, :hover, :active, and :focus states' do
diff --git a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
index ea46ae06329..b8b7fc2009f 100644
--- a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
@@ -28,8 +28,8 @@ RSpec.describe 'Merge request > User sees notes from forked project', :js do
page.within('.discussion-notes') do
find_field('Reply…').click
- scroll_to(page.find('#note_note', visible: false))
- find('#note_note').send_keys('A reply comment')
+ scroll_to(find_field('note[note]', visible: false))
+ fill_in 'note[note]', with: 'A reply comment'
find('.js-comment-button').click
end
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 77d2cb77ae3..a5047c8d550 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
context 'with a detached merge request pipeline' do
let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- it 'displays the Run Pipeline button' do
+ it 'displays the "Run pipeline" button' do
visit project_merge_request_path(project, merge_request)
page.within('.merge-request-tabs') do
@@ -50,14 +50,14 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
wait_for_requests
- expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run Pipeline')
+ expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run pipeline')
end
end
context 'with a merged results pipeline' do
let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) }
- it 'displays the Run Pipeline button' do
+ it 'displays the "Run pipeline" button' do
visit project_merge_request_path(project, merge_request)
page.within('.merge-request-tabs') do
@@ -66,7 +66,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
wait_for_requests
- expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run Pipeline')
+ expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run pipeline')
end
end
end
@@ -131,7 +131,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
visit project_merge_request_path(parent_project, merge_request)
create_merge_request_pipeline
- act_on_security_warning(action: 'Run Pipeline')
+ act_on_security_warning(action: 'Run pipeline')
check_pipeline(expected_project: parent_project)
check_head_pipeline(expected_project: parent_project)
@@ -175,7 +175,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
def create_merge_request_pipeline
page.within('.merge-request-tabs') { click_link('Pipelines') }
- click_button('Run Pipeline')
+ click_button('Run pipeline')
end
def check_pipeline(expected_project:)
diff --git a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb
index 9850ca3f173..275a87ca391 100644
--- a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb
+++ b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe 'Merge request > User selects branches for new MR', :js do
expect(page).to have_content "wm.png"
fill_in "merge_request_title", with: "Orphaned MR test"
- click_button "Submit merge request"
+ click_button "Create merge request"
click_button "Check out branch"
@@ -200,7 +200,7 @@ RSpec.describe 'Merge request > User selects branches for new MR', :js do
click_button "Compare branches"
- expect(page).to have_button("Submit merge request")
+ expect(page).to have_button("Create merge request")
end
end
end
diff --git a/spec/features/merge_request/user_squashes_merge_request_spec.rb b/spec/features/merge_request/user_squashes_merge_request_spec.rb
index 84964bd0637..15f59c0d7bc 100644
--- a/spec/features/merge_request/user_squashes_merge_request_spec.rb
+++ b/spec/features/merge_request/user_squashes_merge_request_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe 'User squashes a merge request', :js do
before do
visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch })
check 'merge_request[squash]'
- click_on 'Submit merge request'
+ click_on 'Create merge request'
wait_for_requests
end
@@ -121,7 +121,7 @@ RSpec.describe 'User squashes a merge request', :js do
context 'when squash is not enabled on merge request creation', :sidekiq_might_not_need_inline do
before do
visit project_new_merge_request_path(project, merge_request: { target_branch: 'master', source_branch: source_branch })
- click_on 'Submit merge request'
+ click_on 'Create merge request'
wait_for_requests
end
diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb
index 5f99d762ecb..f1b44010f63 100644
--- a/spec/features/merge_request/user_views_open_merge_request_spec.rb
+++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb
@@ -125,7 +125,7 @@ RSpec.describe 'User views an open merge request' do
end
it 'encodes branch name' do
- expect(find('cite.ref-name')[:title]).to eq(source_branch)
+ expect(find("[data-testid='ref-name']")[:title]).to eq(source_branch)
end
end
end
diff --git a/spec/features/milestones/user_creates_milestone_spec.rb b/spec/features/milestones/user_creates_milestone_spec.rb
index d80796b8f9a..dd377aa4a26 100644
--- a/spec/features/milestones/user_creates_milestone_spec.rb
+++ b/spec/features/milestones/user_creates_milestone_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe "User creates milestone", :js do
end
it "creates milestone" do
- title = "v2.3".freeze
+ title = "v2.3"
fill_in("Title", with: title)
fill_in("Description", with: "# Description header")
diff --git a/spec/features/milestones/user_views_milestone_spec.rb b/spec/features/milestones/user_views_milestone_spec.rb
index 9c19f842427..8674d59afdf 100644
--- a/spec/features/milestones/user_views_milestone_spec.rb
+++ b/spec/features/milestones/user_views_milestone_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe "User views milestone" do
visit(project_milestone_path(project, milestone))
within('.js-milestone-tabs') do
- click_link('Merge Requests')
+ click_link('Merge requests')
end
wait_for_requests
@@ -116,7 +116,7 @@ RSpec.describe "User views milestone" do
visit(group_milestone_path(group, group_milestone))
within('.js-milestone-tabs') do
- click_link('Merge Requests')
+ click_link('Merge requests')
end
expect(page.find('#tab-merge-requests')).to have_text(project.name)
diff --git a/spec/features/milestones/user_views_milestones_spec.rb b/spec/features/milestones/user_views_milestones_spec.rb
index f8b4b802a60..58439df92ba 100644
--- a/spec/features/milestones/user_views_milestones_spec.rb
+++ b/spec/features/milestones/user_views_milestones_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "User views milestones" do
expect(page).to have_content(milestone.title)
.and have_content(milestone.expires_at)
.and have_content("Issues")
- .and have_content("Merge Requests")
+ .and have_content("Merge requests")
end
context "with issues", :js do
@@ -80,7 +80,6 @@ RSpec.describe "User views milestones with no MR" do
expect(page).to have_content(milestone.title)
.and have_content(milestone.expires_at)
.and have_content("Issues")
- .and have_no_content("Merge Requests")
end
it "opens milestone" do
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index b22778012a8..2781cfffbaf 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Member autocomplete', :js do
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
- let(:author) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:author) { create(:user) }
let(:note) { create(:note, noteable: noteable, project: noteable.project) }
before do
@@ -15,20 +15,16 @@ RSpec.describe 'Member autocomplete', :js do
shared_examples "open suggestions when typing @" do |resource_name|
before do
- page.within('.new-note') do
- if resource_name == 'commit'
- find('#note_note').send_keys('@')
- else
- find('#note-body').send_keys('@')
- end
+ if resource_name == 'commit'
+ fill_in 'note[note]', with: '@'
+ else
+ fill_in 'Comment', with: '@'
end
end
it 'suggests noteable author and note author' do
- page.within('.atwho-view', visible: true) do
- expect(page).to have_content(author.username)
- expect(page).to have_content(note.author.username)
- end
+ expect(find_autocomplete_menu).to have_text(author.username)
+ expect(find_autocomplete_menu).to have_text(note.author.username)
end
end
@@ -51,22 +47,17 @@ RSpec.describe 'Member autocomplete', :js do
stub_feature_flags(tribute_autocomplete: true)
visit project_issue_path(project, noteable)
- page.within('.new-note') do
- find('#note-body').send_keys('@')
- end
+ fill_in 'Comment', with: '@'
end
it 'suggests noteable author and note author' do
- page.within('.tribute-container', visible: true) do
- expect(page).to have_content(author.username)
- expect(page).to have_content(note.author.username)
- end
+ expect(find_tribute_autocomplete_menu).to have_content(author.username)
+ expect(find_tribute_autocomplete_menu).to have_content(note.author.username)
end
end
end
context 'adding a new note on a Merge Request' do
- let(:project) { create(:project, :public, :repository) }
let(:noteable) do
create(:merge_request, source_project: project,
target_project: project, author: author)
@@ -80,7 +71,6 @@ RSpec.describe 'Member autocomplete', :js do
end
context 'adding a new note on a Commit' do
- let(:project) { create(:project, :public, :repository) }
let(:noteable) { project.commit }
let(:note) { create(:note_on_commit, project: project, commit_id: project.commit.id) }
@@ -94,4 +84,14 @@ RSpec.describe 'Member autocomplete', :js do
include_examples "open suggestions when typing @", 'commit'
end
+
+ private
+
+ def find_autocomplete_menu
+ find('.atwho-view ul', visible: true)
+ end
+
+ def find_tribute_autocomplete_menu
+ find('.tribute-container ul', visible: true)
+ end
end
diff --git a/spec/features/profiles/emails_spec.rb b/spec/features/profiles/emails_spec.rb
index bdf1f8b022a..6b6f628e2d5 100644
--- a/spec/features/profiles/emails_spec.rb
+++ b/spec/features/profiles/emails_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user removes email' do
- user.emails.create(email: 'my@email.com')
+ user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect(page).to have_content("my@email.com")
@@ -52,7 +52,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user confirms email' do
- email = user.emails.create(email: 'my@email.com')
+ email = user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect(page).to have_content("#{email.email} Unverified")
@@ -64,7 +64,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'user re-sends confirmation email' do
- email = user.emails.create(email: 'my@email.com')
+ email = user.emails.create!(email: 'my@email.com')
visit profile_emails_path
expect { click_link("Resend confirmation email") }.to have_enqueued_job.on_queue('mailers')
@@ -72,7 +72,7 @@ RSpec.describe 'Profile > Emails' do
end
it 'old unconfirmed emails show Send Confirmation button' do
- email = user.emails.create(email: 'my@email.com')
+ email = user.emails.create!(email: 'my@email.com')
email.update_attribute(:confirmation_sent_at, nil)
visit profile_emails_path
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 039966080d8..c9059395377 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe 'Profile > Password' do
before do
sign_in(user)
- user.update(password_expires_at: 1.hour.ago)
+ user.update!(password_expires_at: 1.hour.ago)
user.identities.delete
expect(user.ldap_user?).to eq false
end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 9e56ef087ae..c85657c89d5 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -95,7 +95,7 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
end
it "removes expired tokens from 'active' section" do
- personal_access_token.update(expires_at: 5.days.ago)
+ personal_access_token.update!(expires_at: 5.days.ago)
visit profile_personal_access_tokens_path
expect(page).to have_selector(".settings-message")
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index bd4917824d1..57f7c7878e3 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -212,8 +212,10 @@ RSpec.describe 'User edit profile' do
end
it 'shows author as busy in the assignee dropdown' do
- find('.block.assignee .edit-link').click
- wait_for_requests
+ page.within('.assignee') do
+ click_button('Edit')
+ wait_for_requests
+ end
page.within '.dropdown-menu-user' do
expect(page).to have_content("#{user.name} (Busy)")
@@ -227,7 +229,7 @@ RSpec.describe 'User edit profile' do
visit project_issue_path(project, issue)
wait_for_requests
- expect(page.find('[data-testid="expanded-assignee"]')).to have_text("#{user.name} (Busy)")
+ expect(page.find('.issuable-assignees')).to have_content("#{user.name} (Busy)")
end
end
diff --git a/spec/features/profiles/user_search_settings_spec.rb b/spec/features/profiles/user_search_settings_spec.rb
index 60df0d7532b..64a8556e349 100644
--- a/spec/features/profiles/user_search_settings_spec.rb
+++ b/spec/features/profiles/user_search_settings_spec.rb
@@ -10,9 +10,11 @@ RSpec.describe 'User searches their settings', :js do
end
context 'in profile page' do
- let(:visit_path) { profile_path }
+ before do
+ visit profile_path
+ end
- it_behaves_like 'can search settings with feature flag check', 'Public Avatar', 'Main settings'
+ it_behaves_like 'can search settings', 'Public Avatar', 'Main settings'
end
context 'in preferences page' do
diff --git a/spec/features/projects/active_tabs_spec.rb b/spec/features/projects/active_tabs_spec.rb
index 86fe59f003f..9de43e7d18c 100644
--- a/spec/features/projects/active_tabs_spec.rb
+++ b/spec/features/projects/active_tabs_spec.rb
@@ -79,7 +79,7 @@ RSpec.describe 'Project active tab' do
visit project_merge_requests_path(project)
end
- it_behaves_like 'page has active tab', 'Merge Requests'
+ it_behaves_like 'page has active tab', 'Merge requests'
end
context 'on project Wiki' do
diff --git a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
index a65a82fab43..1a368676a5e 100644
--- a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
+++ b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
@@ -44,17 +44,6 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do
expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
end
- it 'changes fragment hash if icon inside line number link is clicked' do
- ending_fragment = "L7"
-
- visit_blob
-
- find("##{ending_fragment}").hover
- find("##{ending_fragment} svg").click
-
- expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
- end
-
it 'with initial fragment hash, changes fragment hash if line number clicked' do
fragment = "L1"
ending_fragment = "L5"
@@ -94,17 +83,6 @@ RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do
expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
end
- it 'changes fragment hash if icon inside line number link is clicked' do
- ending_fragment = "L7"
-
- visit_blob
-
- find("##{ending_fragment}").hover
- find("##{ending_fragment} svg").click
-
- expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
- end
-
it 'with initial fragment hash, changes fragment hash if line number clicked' do
fragment = "L1"
ending_fragment = "L5"
diff --git a/spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb b/spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb
new file mode 100644
index 00000000000..b872fa701c8
--- /dev/null
+++ b/spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User views pipeline editor button on root ci config file', :js do
+ include BlobSpecHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+
+ context "when the ci config is the root file" do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ end
+
+ it 'shows the button to the Pipeline Editor' do
+ project.update!(ci_config_path: '.my-config.yml')
+ project.repository.create_file(user, project.ci_config_path_or_default, 'test', message: 'testing', branch_name: 'master')
+ visit project_blob_path(project, File.join('master', '.my-config.yml'))
+
+ expect(page).to have_content('Pipeline Editor')
+ end
+
+ it 'does not shows the Pipeline Editor button' do
+ project.repository.create_file(user, '.my-sub-config.yml', 'test', message: 'testing', branch_name: 'master')
+ visit project_blob_path(project, File.join('master', '.my-sub-config.yml'))
+
+ expect(page).not_to have_content('Pipeline Editor')
+ end
+ end
+
+ context "when user cannot collaborate" do
+ before do
+ sign_in(user)
+ end
+ it 'does not shows the Pipeline Editor button' do
+ visit project_blob_path(project, File.join('master', '.my-config.yml'))
+ expect(page).not_to have_content('Pipeline Editor')
+ end
+ end
+end
diff --git a/spec/features/projects/branches/user_creates_branch_spec.rb b/spec/features/projects/branches/user_creates_branch_spec.rb
index 52c860bfe36..18d083f7d88 100644
--- a/spec/features/projects/branches/user_creates_branch_spec.rb
+++ b/spec/features/projects/branches/user_creates_branch_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe "User creates branch", :js do
end
it "creates new branch" do
- branch_name = "deploy_keys".freeze
+ branch_name = "deploy_keys"
create_branch(branch_name)
@@ -25,7 +25,7 @@ RSpec.describe "User creates branch", :js do
context "when branch name is invalid" do
it "does not create new branch" do
- invalid_branch_name = "1.0 stable".freeze
+ invalid_branch_name = "1.0 stable"
fill_in("branch_name", with: invalid_branch_name)
page.find("body").click # defocus the branch_name input
diff --git a/spec/features/projects/branches/user_deletes_branch_spec.rb b/spec/features/projects/branches/user_deletes_branch_spec.rb
index c480c41709c..bebb4bb679b 100644
--- a/spec/features/projects/branches/user_deletes_branch_spec.rb
+++ b/spec/features/projects/branches/user_deletes_branch_spec.rb
@@ -9,12 +9,15 @@ RSpec.describe "User deletes branch", :js do
before do
project.add_developer(user)
sign_in(user)
-
- visit(project_branches_path(project))
end
it "deletes branch" do
- fill_in("branch-search", with: "improve/awesome").native.send_keys(:enter)
+ visit(project_branches_path(project))
+
+ branch_search = find('input[data-testid="branch-search"]')
+
+ branch_search.set('improve/awesome')
+ branch_search.native.send_keys(:enter)
page.within(".js-branch-improve\\/awesome") do
accept_alert { find(".btn-danger").click }
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 4bfe8852291..f805416b03d 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -88,8 +88,10 @@ RSpec.describe 'Branches' do
it 'shows filtered branches', :js do
visit project_branches_path(project)
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ branch_search = find('input[data-testid="branch-search"]')
+
+ branch_search.set('fix')
+ branch_search.native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -114,20 +116,24 @@ RSpec.describe 'Branches' do
expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :updated_desc))
end
- it 'sorts the branches by name' do
+ it 'sorts the branches by name', :js do
visit project_branches_filtered_path(project, state: 'all')
click_button "Last updated" # Open sorting dropdown
- click_link "Name"
+ within '[data-testid="branches-dropdown"]' do
+ find('p', text: 'Name').click
+ end
expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :name))
end
- it 'sorts the branches by oldest updated' do
+ it 'sorts the branches by oldest updated', :js do
visit project_branches_filtered_path(project, state: 'all')
click_button "Last updated" # Open sorting dropdown
- click_link "Oldest updated"
+ within '[data-testid="branches-dropdown"]' do
+ find('p', text: 'Oldest updated').click
+ end
expect(page).to have_content(sorted_branches(repository, count: 20, sort_by: :updated_asc))
end
@@ -145,8 +151,10 @@ RSpec.describe 'Branches' do
it 'shows filtered branches', :js do
visit project_branches_filtered_path(project, state: 'all')
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ branch_search = find('input[data-testid="branch-search"]')
+
+ branch_search.set('fix')
+ branch_search.native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -157,9 +165,10 @@ RSpec.describe 'Branches' do
it 'removes branch after confirmation', :js do
visit project_branches_filtered_path(project, state: 'all')
- fill_in 'branch-search', with: 'fix'
+ branch_search = find('input[data-testid="branch-search"]')
- find('#branch-search').native.send_keys(:enter)
+ branch_search.set('fix')
+ branch_search.native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index d34dde6a8f2..8c497cded8e 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe 'Gcp Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
- page.within('.js-cluster-integration-form') { click_button 'Save changes' }
+ page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 748eba558aa..5b60edbcf87 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe 'User Cluster', :js do
context 'when user disables the cluster' do
before do
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
- page.within('.js-cluster-integration-form') { click_button 'Save changes' }
+ page.within('.js-cluster-details-form') { click_button 'Save changes' }
end
it 'user sees the successful message' do
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index 6da66989b09..6b03301aa74 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -58,7 +58,7 @@ RSpec.describe 'Clusters', :js do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
- within '.js-cluster-integration-form' do
+ within '.js-cluster-details-form' do
click_button 'Save changes'
end
end
@@ -149,7 +149,7 @@ RSpec.describe 'Clusters', :js do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
- within ".js-cluster-integration-form" do
+ within ".js-cluster-details-form" do
click_button 'Save changes'
end
end
diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb
index 489a90cc8fc..cd944436228 100644
--- a/spec/features/projects/commit/cherry_pick_spec.rb
+++ b/spec/features/projects/commit/cherry_pick_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe 'Cherry-pick Commits', :js do
context 'when the project is archived' do
let(:project) { create(:project, :repository, :archived, namespace: user.namespace) }
- it 'does not show the cherry-pick link' do
+ it 'does not show the cherry-pick button' do
open_dropdown
expect(page).not_to have_text("Cherry-pick")
@@ -106,12 +106,15 @@ RSpec.describe 'Cherry-pick Commits', :js do
end
def open_dropdown
- find('.header-action-buttons .dropdown').click
+ find(dropdown_selector).click
end
def open_modal
open_dropdown
- find('[data-testid="cherry-pick-commit-link"]').click
+
+ page.within(dropdown_selector) do
+ click_button 'Cherry-pick'
+ end
end
def submit_cherry_pick(create_merge_request: false)
@@ -121,6 +124,10 @@ RSpec.describe 'Cherry-pick Commits', :js do
end
end
+ def dropdown_selector
+ '[data-testid="commit-options-dropdown"]'
+ end
+
def modal_selector
'[data-testid="modal-commit"]'
end
diff --git a/spec/features/projects/commit/comments/user_edits_comments_spec.rb b/spec/features/projects/commit/comments/user_edits_comments_spec.rb
index 787d8cdb02b..8ac15c9cb7f 100644
--- a/spec/features/projects/commit/comments/user_edits_comments_spec.rb
+++ b/spec/features/projects/commit/comments/user_edits_comments_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe "User edits a comment on a commit", :js do
end
it "edits comment" do
- new_comment_text = "+1 Awesome!".freeze
+ new_comment_text = "+1 Awesome!"
page.within(".main-notes-list") do
note = find(".note")
diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
index 7d206f76031..6de02556175 100644
--- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb
+++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
@@ -16,46 +16,28 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
let(:build) { create(:ci_build, pipeline: pipeline, status: :running) }
- shared_examples 'shows ci icon and mini pipeline' do
- before do
- build.run
- visit project_commit_path(project, project.commit.id)
- end
-
- it 'display icon with status' do
- expect(page).to have_selector('.ci-status-icon-running')
- end
-
- it 'displays a mini pipeline graph' do
- expect(page).to have_selector('.mr-widget-pipeline-graph')
-
- first('.mini-pipeline-graph-dropdown-toggle').click
-
- wait_for_requests
-
- page.within '.js-builds-dropdown-list' do
- expect(page).to have_selector('.ci-status-icon-running')
- expect(page).to have_content(build.stage)
- end
+ before do
+ build.run
+ visit project_commit_path(project, project.commit.id)
+ end
- build.drop
- end
+ it 'display icon with status' do
+ expect(page).to have_selector('.ci-status-icon-running')
end
- context 'when ci_commit_pipeline_mini_graph_vue is disabled' do
- before do
- stub_feature_flags(ci_commit_pipeline_mini_graph_vue: false)
- end
+ it 'displays a mini pipeline graph' do
+ expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
- it_behaves_like 'shows ci icon and mini pipeline'
- end
+ first('.mini-pipeline-graph-dropdown-toggle').click
- context 'when ci_commit_pipeline_mini_graph_vue is enabled' do
- before do
- stub_feature_flags(ci_commit_pipeline_mini_graph_vue: true)
+ wait_for_requests
+
+ page.within '.js-builds-dropdown-list' do
+ expect(page).to have_selector('.ci-status-icon-running')
+ expect(page).to have_content(build.stage)
end
- it_behaves_like 'shows ci icon and mini pipeline'
+ build.drop
end
end
@@ -65,7 +47,7 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
end
it 'does not display a mini pipeline graph' do
- expect(page).not_to have_selector('.mr-widget-pipeline-graph')
+ expect(page).not_to have_selector('[data-testid="pipeline-mini-graph"]')
end
end
end
diff --git a/spec/features/projects/commit/user_reverts_commit_spec.rb b/spec/features/projects/commit/user_reverts_commit_spec.rb
index 72c639a027e..ad327b86aa7 100644
--- a/spec/features/projects/commit/user_reverts_commit_spec.rb
+++ b/spec/features/projects/commit/user_reverts_commit_spec.rb
@@ -62,10 +62,10 @@ RSpec.describe 'User reverts a commit', :js do
context 'when the project is archived' do
let(:project) { create(:project, :repository, :archived, namespace: user.namespace) }
- it 'does not show the revert link' do
+ it 'does not show the revert button' do
open_dropdown
- expect(page).not_to have_link('Revert')
+ expect(page).not_to have_button('Revert')
end
end
end
@@ -75,17 +75,24 @@ RSpec.describe 'User reverts a commit', :js do
page.within(modal_selector) do
uncheck('create_merge_request') unless create_merge_request
- click_button('Revert')
+ click_button 'Revert'
end
end
def open_dropdown
- find('.header-action-buttons .dropdown').click
+ find(dropdown_selector).click
end
def open_modal
open_dropdown
- find('[data-testid="revert-commit-link"]').click
+
+ page.within(dropdown_selector) do
+ click_button 'Revert'
+ end
+ end
+
+ def dropdown_selector
+ '[data-testid="commit-options-dropdown"]'
end
def modal_selector
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 4894e2b7f3e..76162fb800a 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -20,9 +20,14 @@ RSpec.describe 'User browses commits' do
.and have_content('Side-by-side')
end
- it 'fill commit sha when click new tag from commit page' do
+ it 'fill commit sha when click new tag from commit page', :js do
+ dropdown_selector = '[data-testid="commit-options-dropdown"]'
visit project_commit_path(project, sample_commit.id)
- click_link 'Tag'
+ find(dropdown_selector).click
+
+ page.within(dropdown_selector) do
+ click_link 'Tag'
+ end
expect(page).to have_selector("input[value='#{sample_commit.id}']", visible: false)
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index c94247f65d2..ab82a4750d3 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -134,7 +134,7 @@ RSpec.describe 'Edit Project Settings' do
it 'renders 200 if user is member of group' do
group = create(:group)
project.group = group
- project.save
+ project.save!
group.add_owner(member)
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 55b9f38d8e7..b0ccb5fca94 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -5,10 +5,14 @@ require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js do
include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+ let(:params) { {} }
+ let(:filename) { '.gitlab-ci.yml' }
+
+ let_it_be(:project) { create(:project, :repository) }
+
before do
- project = create(:project, :repository)
sign_in project.owner
- visit project_new_blob_path(project, 'master', file_name: '.gitlab-ci.yml')
+ visit project_new_blob_path(project, 'master', file_name: filename, **params)
end
it 'user can pick a template from the dropdown' do
@@ -29,4 +33,38 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js
expect(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project')
expect(editor_get_value).to have_content('jekyll build -d test')
end
+
+ context 'when template param is provided' do
+ let(:params) { { template: 'Jekyll' } }
+
+ 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(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project')
+ expect(editor_get_value).to have_content('jekyll build -d test')
+ end
+ end
+
+ context 'when provided template param is not a valid template name' do
+ let(:params) { { template: 'non-existing-template' } }
+
+ 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(editor_get_value).to have_content('')
+ end
+ end
+
+ context 'when template is not available for the given file' do
+ let(:filename) { 'Dockerfile' }
+ let(:params) { { template: 'Jekyll' } }
+
+ it 'leaves the editor empty' do
+ wait_for_requests
+
+ expect(editor_get_value).to have_content('')
+ end
+ end
end
diff --git a/spec/features/projects/files/user_creates_directory_spec.rb b/spec/features/projects/files/user_creates_directory_spec.rb
index f2074c78dba..46b93d738e1 100644
--- a/spec/features/projects/files/user_creates_directory_spec.rb
+++ b/spec/features/projects/files/user_creates_directory_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe 'Projects > Files > User creates a directory', :js do
it 'creates the directory in the new branch and redirect to the merge request' do
expect(page).to have_content('new-feature')
expect(page).to have_content('The directory has been successfully created')
- expect(page).to have_content('New Merge Request')
+ expect(page).to have_content('New merge request')
expect(page).to have_content('From new-feature into master')
expect(page).to have_content('Add new directory')
diff --git a/spec/features/projects/files/user_uploads_files_spec.rb b/spec/features/projects/files/user_uploads_files_spec.rb
index 944d08df3f3..54e816d3d13 100644
--- a/spec/features/projects/files/user_uploads_files_spec.rb
+++ b/spec/features/projects/files/user_uploads_files_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User uploads files' do
- include DropzoneHelper
-
let(:user) { create(:user) }
let(:project) { create(:project, :repository, name: 'Shop', creator: user) }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
@@ -17,36 +15,17 @@ RSpec.describe 'Projects > Files > User uploads files' do
context 'when a user has write access' do
before do
visit(project_tree_path(project))
- end
-
- include_examples 'it uploads and commit a new text file'
-
- include_examples 'it uploads and commit a new image file'
- it 'uploads a file to a sub-directory', :js do
- click_link 'files'
-
- page.within('.repo-breadcrumb') do
- expect(page).to have_content('files')
- end
-
- find('.add-to-tree').click
- click_link('Upload file')
- drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ wait_for_requests
+ end
- page.within('#modal-upload-blob') do
- fill_in(:commit_message, with: 'New commit message')
- end
+ include_examples 'it uploads and commits a new text file'
- click_button('Upload file')
+ include_examples 'it uploads and commits a new image file'
- expect(page).to have_content('New commit message')
+ include_examples 'it uploads and commits a new pdf file'
- page.within('.repo-breadcrumb') do
- expect(page).to have_content('files')
- expect(page).to have_content('doc_sample.txt')
- end
- end
+ include_examples 'it uploads a file to a sub-directory'
end
context 'when a user does not have write access' do
@@ -56,6 +35,6 @@ RSpec.describe 'Projects > Files > User uploads files' do
visit(project_tree_path(project2))
end
- include_examples 'it uploads and commit a new file to a forked project'
+ include_examples 'it uploads and commits a new file to a forked project'
end
end
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index 7abbd207b24..2b7ea70fe5a 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe 'Project fork' do
let(:forking_access_level) { ProjectFeature::PRIVATE }
before do
- project.update(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end
context 'user is not a team member' do
@@ -118,6 +118,50 @@ RSpec.describe 'Project fork' do
it_behaves_like 'fork button on project page'
it_behaves_like 'create fork page', 'Fork project'
+ context 'fork form', :js do
+ let(:group) { create(:group) }
+ let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
+
+ def submit_form
+ select(group.name)
+ click_button 'Fork project'
+ end
+
+ it 'forks the project', :sidekiq_might_not_need_inline do
+ visit new_project_fork_path(project)
+ submit_form
+
+ expect(page).to have_content 'Forked from'
+ end
+
+ it 'shows the new forked project on the forks page' do
+ visit new_project_fork_path(project)
+ submit_form
+ wait_for_requests
+
+ visit project_forks_path(project)
+
+ page.within('.js-projects-list-holder') do
+ expect(page).to have_content("#{group.name} / #{project.name}")
+ end
+ end
+
+ it 'shows the filled in info forked project on the forks page' do
+ fork_name = 'some-name'
+ visit new_project_fork_path(project)
+ fill_in('fork-name', with: fork_name, fill_options: { clear: :backspace })
+ fill_in('fork-slug', with: fork_name, fill_options: { clear: :backspace })
+ submit_form
+ wait_for_requests
+
+ visit project_forks_path(project)
+
+ page.within('.js-projects-list-holder') do
+ expect(page).to have_content("#{group.name} / #{fork_name}")
+ end
+ end
+ end
+
context 'with fork_project_form feature flag disabled' do
before do
stub_feature_flags(fork_project_form: false)
@@ -164,7 +208,7 @@ RSpec.describe 'Project fork' do
expect(page).to have_content(/new merge request/i)
page.within '.nav-sidebar' do
- first(:link, 'Merge Requests').click
+ first(:link, 'Merge requests').click
end
expect(page).to have_content(/new merge request/i)
diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb
index e87880d74b1..140d5dee270 100644
--- a/spec/features/projects/jobs/permissions_spec.rb
+++ b/spec/features/projects/jobs/permissions_spec.rb
@@ -12,6 +12,8 @@ RSpec.describe 'Project Jobs Permissions' do
let_it_be(:job) { create(:ci_build, :running, :coverage, :trace_artifact, pipeline: pipeline) }
before do
+ stub_feature_flags(jobs_table_vue: false)
+
sign_in(user)
project.enable_ci
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index 5abebf2320e..dbcd7b5caf5 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'User browses jobs' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(jobs_table_vue: false)
project.add_maintainer(user)
project.enable_ci
project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/)
@@ -24,14 +25,6 @@ RSpec.describe 'User browses jobs' do
end
end
- it 'shows the "CI Lint" button' do
- page.within('.nav-controls') do
- ci_lint_tool_link = page.find_link('CI Lint')
-
- expect(ci_lint_tool_link[:href]).to end_with(project_ci_lint_path(project))
- end
- end
-
context 'with a failed job' do
let!(:build) { create(:ci_build, :coverage, :failed, pipeline: pipeline) }
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 7811394b541..18a6ad12240 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
end
before do
+ stub_feature_flags(jobs_table_vue: false)
project.add_role(user, user_access_level)
sign_in(user)
end
@@ -32,7 +33,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows the empty state page' do
expect(page).to have_content('Use jobs to automate your tasks')
- expect(page).to have_link('Create CI/CD configuration file', href: project.present(current_user: user).add_ci_yml_path)
+ expect(page).to have_link('Create CI/CD configuration file', href: project_ci_pipeline_editor_path(project))
end
end
@@ -1057,7 +1058,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
before do
job.run!
job.cancel!
- project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
sign_out(:user)
sign_in(create(:user))
diff --git a/spec/features/projects/labels/user_removes_labels_spec.rb b/spec/features/projects/labels/user_removes_labels_spec.rb
index 217f86b92cf..11d73a56965 100644
--- a/spec/features/projects/labels/user_removes_labels_spec.rb
+++ b/spec/features/projects/labels/user_removes_labels_spec.rb
@@ -18,17 +18,17 @@ RSpec.describe "User removes labels" do
visit(project_labels_path(project))
end
- it "removes label" do
+ it "removes label", :js do
page.within(".other-labels") do
page.first(".label-list-item") do
first('.js-label-options-dropdown').click
- first(".remove-row").click
+ first('.js-delete-label-modal-button').click
end
+ end
- expect(page).to have_content("#{label.title} will be permanently deleted from #{project.name}. This cannot be undone.")
+ expect(page).to have_content("#{label.title} will be permanently deleted from #{project.name}. This cannot be undone.")
- first(:link, "Delete label").click
- end
+ first(:link, "Delete label").click
expect(page).to have_content("Label was removed").and have_no_content(label.title)
end
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index 0830585da9b..384b8ae9929 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe 'Project members list', :js do
click_on 'Invite members'
page.within '#invite-members-modal' do
- fill_in 'Search for members to invite', with: id
+ fill_in 'Select members or type email addresses', with: id
wait_for_requests
click_button id
diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb
index a339130ee3c..7073741a92d 100644
--- a/spec/features/projects/members/user_requests_access_spec.rb
+++ b/spec/features/projects/members/user_requests_access_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Projects > Members > User requests access', :js do
end
it 'request access feature is disabled' do
- project.update(request_access_enabled: false)
+ project.update!(request_access_enabled: false)
visit project_path(project)
expect(page).not_to have_content 'Request Access'
diff --git a/spec/features/projects/merge_request_button_spec.rb b/spec/features/projects/merge_request_button_spec.rb
index 9547ba8a390..93bbabcc3f8 100644
--- a/spec/features/projects/merge_request_button_spec.rb
+++ b/spec/features/projects/merge_request_button_spec.rb
@@ -14,7 +14,9 @@ RSpec.describe 'Merge Request button' do
it 'does not show Create merge request button' do
visit url
- expect(page).not_to have_link(label)
+ within '.content-wrapper' do
+ expect(page).not_to have_link(label)
+ end
end
end
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index 4ff3827b240..7dc3ee63669 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe 'Project navbar' do
before do
insert_package_nav(_('Operations'))
+ insert_infrastructure_registry_nav
+ stub_config(registry: { enabled: false })
project.add_maintainer(user)
sign_in(user)
@@ -60,7 +62,7 @@ RSpec.describe 'Project navbar' do
before do
stub_config(registry: { enabled: true })
- insert_container_nav(_('Operations'))
+ insert_container_nav
visit project_path(project)
end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index ec34640bd00..7119039d5ff 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -12,6 +12,72 @@ RSpec.describe 'New project', :js do
sign_in(user)
end
+ context 'new repo experiment', :experiment do
+ it 'when in control renders "project"' do
+ stub_experiments(new_repo: :control)
+
+ visit new_project_path
+
+ find('li.header-new.dropdown').click
+
+ page.within('li.header-new.dropdown') do
+ expect(page).to have_selector('a', text: 'New project')
+ expect(page).to have_no_selector('a', text: 'New project/repository')
+ end
+
+ expect(page).to have_selector('.blank-state-title', text: 'Create blank project')
+ expect(page).to have_no_selector('.blank-state-title', text: 'Create blank project/repository')
+ end
+
+ it 'when in candidate renders "project/repository"' do
+ stub_experiments(new_repo: :candidate)
+
+ visit new_project_path
+
+ find('li.header-new.dropdown').click
+
+ page.within('li.header-new.dropdown') do
+ expect(page).to have_selector('a', text: 'New project/repository')
+ end
+
+ expect(page).to have_selector('.blank-state-title', text: 'Create blank project/repository')
+ end
+
+ context 'with combined_menu feature disabled' do
+ before do
+ stub_feature_flags(combined_menu: false)
+ end
+
+ it 'when in control it renders "project" in the new projects dropdown' do
+ stub_experiments(new_repo: :control)
+
+ visit new_project_path
+
+ find('#nav-projects-dropdown').click
+
+ page.within('#nav-projects-dropdown') do
+ expect(page).to have_selector('a', text: 'Create blank project')
+ expect(page).to have_selector('a', text: 'Import project')
+ expect(page).to have_no_selector('a', text: 'Create blank project/repository')
+ expect(page).to have_no_selector('a', text: 'Import project/repository')
+ end
+ end
+
+ it 'when in candidate it renders "project/repository" in the new projects dropdown' do
+ stub_experiments(new_repo: :candidate)
+
+ visit new_project_path
+
+ find('#nav-projects-dropdown').click
+
+ page.within('#nav-projects-dropdown') do
+ expect(page).to have_selector('a', text: 'Create blank project/repository')
+ expect(page).to have_selector('a', text: 'Import project/repository')
+ end
+ end
+ end
+ end
+
it 'shows a message if multiple levels are restricted' do
Gitlab::CurrentSettings.update!(
restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL]
diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb
index 6156b5243de..412ba17cf20 100644
--- a/spec/features/projects/pages/user_edits_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_settings_spec.rb
@@ -175,7 +175,6 @@ RSpec.describe 'Pages edits pages settings', :js do
expect(page).not_to have_field(:project_pages_https_only)
expect(page).not_to have_content('Force HTTPS (requires valid certificates)')
- expect(page).to have_button('Save')
end
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 94800717677..4a0581bb5cf 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -566,7 +566,7 @@ RSpec.describe 'Pipeline', :js do
end
before do
- pipeline.update(user: user)
+ pipeline.update!(user: user)
end
it 'shows the pipeline information' do
@@ -628,7 +628,7 @@ RSpec.describe 'Pipeline', :js do
context 'when user does not have access to read jobs' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
describe 'GET /:project/-/pipelines/:id' do
@@ -709,9 +709,9 @@ RSpec.describe 'Pipeline', :js do
end
end
- it 'displays the PipelineSchedule in an active state' do
+ it 'displays the PipelineSchedule in an inactive state' do
visit project_pipeline_schedules_path(project)
- page.click_link('Active')
+ page.click_link('Inactive')
expect(page).to have_selector('table.ci-table > tbody > tr > td', text: 'blocked user schedule')
end
@@ -1185,7 +1185,7 @@ RSpec.describe 'Pipeline', :js do
let(:role) { :guest }
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
context 'when accessing failed jobs page' do
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 9037aa5c9a8..e375bc10dbf 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe 'Pipelines', :js do
sign_in(user)
stub_feature_flags(graphql_pipeline_details: false)
stub_feature_flags(graphql_pipeline_details_users: false)
- stub_feature_flags(new_pipelines_table: false)
project.add_developer(user)
project.update!(auto_devops_attributes: { enabled: false })
@@ -94,12 +93,12 @@ RSpec.describe 'Pipelines', :js do
wait_for_requests
end
- it 'renders run pipeline link' do
- expect(page).to have_link('Run Pipeline')
+ it 'renders "CI lint" link' do
+ expect(page).to have_link('CI lint')
end
- it 'renders ci lint link' do
- expect(page).to have_link('CI Lint')
+ it 'renders "Run pipeline" link' do
+ expect(page).to have_link('Run pipeline')
end
end
@@ -534,7 +533,7 @@ RSpec.describe 'Pipelines', :js do
end
it 'renders a mini pipeline graph' do
- expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]')
+ expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
expect(page).to have_selector(dropdown_selector)
end
@@ -677,7 +676,7 @@ RSpec.describe 'Pipelines', :js do
end
it 'creates a new pipeline' do
- expect { click_on 'Run Pipeline' }
+ expect { click_on 'Run pipeline' }
.to change { Ci::Pipeline.count }.by(1)
expect(Ci::Pipeline.last).to be_web
@@ -690,7 +689,7 @@ RSpec.describe 'Pipelines', :js do
fill_in "Input variable value", with: "value"
end
- expect { click_on 'Run Pipeline' }
+ expect { click_on 'Run pipeline' }
.to change { Ci::Pipeline.count }.by(1)
expect(Ci::Pipeline.last.variables.map { |var| var.slice(:key, :secret_value) })
@@ -701,7 +700,7 @@ RSpec.describe 'Pipelines', :js do
context 'without gitlab-ci.yml' do
before do
- click_on 'Run Pipeline'
+ click_on 'Run pipeline'
end
it { expect(page).to have_content('Missing CI config file') }
@@ -714,44 +713,13 @@ RSpec.describe 'Pipelines', :js do
click_link 'master'
end
- expect { click_on 'Run Pipeline' }
+ expect { click_on 'Run pipeline' }
.to change { Ci::Pipeline.count }.by(1)
end
end
end
end
- describe 'Run Pipelines' do
- let(:project) { create(:project, :repository) }
-
- before do
- stub_feature_flags(new_pipeline_form: false)
- visit new_project_pipeline_path(project)
- end
-
- describe 'new pipeline page' do
- it 'has field to add a new pipeline' do
- expect(page).to have_selector('.js-branch-select')
- expect(find('.js-branch-select')).to have_content project.default_branch
- expect(page).to have_content('Run for')
- end
- end
-
- describe 'find pipelines' do
- it 'shows filtered pipelines', :js do
- click_button project.default_branch
-
- page.within '.dropdown-menu' do
- find('.dropdown-input-field').native.send_keys('fix')
-
- page.within '.dropdown-content' do
- expect(page).to have_content('fix')
- end
- end
- end
- end
- end
-
describe 'Reset runner caches' do
let(:project) { create(:project, :repository) }
@@ -762,17 +730,17 @@ RSpec.describe 'Pipelines', :js do
end
it 'has a clear caches button' do
- expect(page).to have_button 'Clear Runner Caches'
+ expect(page).to have_button 'Clear runner caches'
end
describe 'user clicks the button' do
context 'when project already has jobs_cache_index' do
before do
- project.update(jobs_cache_index: 1)
+ project.update!(jobs_cache_index: 1)
end
it 'increments jobs_cache_index' do
- click_button 'Clear Runner Caches'
+ click_button 'Clear runner caches'
wait_for_requests
expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
end
@@ -780,7 +748,7 @@ RSpec.describe 'Pipelines', :js do
context 'when project does not have jobs_cache_index' do
it 'sets jobs_cache_index to 1' do
- click_button 'Clear Runner Caches'
+ click_button 'Clear runner caches'
wait_for_requests
expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
end
@@ -788,6 +756,37 @@ RSpec.describe 'Pipelines', :js do
end
end
+ describe 'Run Pipelines' do
+ let(:project) { create(:project, :repository) }
+
+ before do
+ stub_feature_flags(new_pipeline_form: false)
+ visit new_project_pipeline_path(project)
+ end
+
+ describe 'new pipeline page' do
+ it 'has field to add a new pipeline' do
+ expect(page).to have_selector('.js-branch-select')
+ expect(find('.js-branch-select')).to have_content project.default_branch
+ expect(page).to have_content('Run for')
+ end
+ end
+
+ describe 'find pipelines' do
+ it 'shows filtered pipelines', :js do
+ click_button project.default_branch
+
+ page.within '.dropdown-menu' do
+ find('.dropdown-input-field').native.send_keys('fix')
+
+ page.within '.dropdown-content' do
+ expect(page).to have_content('fix')
+ end
+ end
+ end
+ end
+ end
+
describe 'Empty State' do
let(:project) { create(:project, :repository) }
diff --git a/spec/features/projects/releases/user_views_edit_release_spec.rb b/spec/features/projects/releases/user_views_edit_release_spec.rb
index bb54b6be9c4..024c0a227c5 100644
--- a/spec/features/projects/releases/user_views_edit_release_spec.rb
+++ b/spec/features/projects/releases/user_views_edit_release_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe 'User edits Release', :js do
end
it 'renders the edit Release form' do
- expect(page).to have_content('Releases are based on Git tags. We recommend tags that use semantic versioning, for example v1.0, v2.0-pre.')
+ expect(page).to have_content('Releases are based on Git tags. We recommend tags that use semantic versioning, for example v1.0.0, v2.1.0-pre.')
expect(find_field('Tag name', disabled: true).value).to eq(release.tag)
expect(find_field('Release title').value).to eq(release.name)
diff --git a/spec/features/projects/releases/user_views_release_spec.rb b/spec/features/projects/releases/user_views_release_spec.rb
index 186122536ce..4410f345e56 100644
--- a/spec/features/projects/releases/user_views_release_spec.rb
+++ b/spec/features/projects/releases/user_views_release_spec.rb
@@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe 'User views Release', :js do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
- let(:graphql_feature_flag) { true }
let(:release) do
create(:release,
@@ -15,8 +14,6 @@ RSpec.describe 'User views Release', :js do
end
before do
- stub_feature_flags(graphql_individual_release_page: graphql_feature_flag)
-
project.add_developer(user)
sign_in(user)
@@ -26,35 +23,23 @@ RSpec.describe 'User views Release', :js do
it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet'
- shared_examples 'release page' do
- it 'renders the breadcrumbs' do
- within('.breadcrumbs') do
- expect(page).to have_content("#{project.creator.name} #{project.name} Releases #{release.name}")
-
- expect(page).to have_link(project.creator.name, href: user_path(project.creator))
- expect(page).to have_link(project.name, href: project_path(project))
- expect(page).to have_link('Releases', href: project_releases_path(project))
- expect(page).to have_link(release.name, href: project_release_path(project, release))
- end
- end
+ it 'renders the breadcrumbs' do
+ within('.breadcrumbs') do
+ expect(page).to have_content("#{project.creator.name} #{project.name} Releases #{release.name}")
- it 'renders the release details' do
- within('.release-block') do
- expect(page).to have_content(release.name)
- expect(page).to have_content(release.tag)
- expect(page).to have_content(release.commit.short_id)
- expect(page).to have_content('Lorem ipsum dolor sit amet')
- end
+ expect(page).to have_link(project.creator.name, href: user_path(project.creator))
+ expect(page).to have_link(project.name, href: project_path(project))
+ expect(page).to have_link('Releases', href: project_releases_path(project))
+ expect(page).to have_link(release.name, href: project_release_path(project, release))
end
end
- describe 'when the graphql_individual_release_page feature flag is enabled' do
- it_behaves_like 'release page'
- end
-
- describe 'when the graphql_individual_release_page feature flag is disabled' do
- let(:graphql_feature_flag) { false }
-
- it_behaves_like 'release page'
+ it 'renders the release details' do
+ within('.release-block') do
+ expect(page).to have_content(release.name)
+ expect(page).to have_content(release.tag)
+ expect(page).to have_content(release.commit.short_id)
+ expect(page).to have_content('Lorem ipsum dolor sit amet')
+ end
end
end
diff --git a/spec/features/projects/remote_mirror_spec.rb b/spec/features/projects/remote_mirror_spec.rb
index 26d27c914cc..7bbffe627f6 100644
--- a/spec/features/projects/remote_mirror_spec.rb
+++ b/spec/features/projects/remote_mirror_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Project remote mirror', :feature do
context 'when last_error is present but last_update_at is not' do
it 'renders error message without timstamp' do
- remote_mirror.update(last_error: 'Some new error', last_update_at: nil)
+ remote_mirror.update!(last_error: 'Some new error', last_update_at: nil)
visit project_mirror_path(project)
@@ -25,7 +25,7 @@ RSpec.describe 'Project remote mirror', :feature do
context 'when last_error and last_update_at are present' do
it 'renders error message with timestamp' do
- remote_mirror.update(last_error: 'Some new error', last_update_at: Time.now - 5.minutes)
+ remote_mirror.update!(last_error: 'Some new error', last_update_at: Time.now - 5.minutes)
visit project_mirror_path(project)
diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/services/disable_triggers_spec.rb
index b3a3d7f0622..d9e200cf563 100644
--- a/spec/features/projects/services/disable_triggers_spec.rb
+++ b/spec/features/projects/services/disable_triggers_spec.rb
@@ -12,10 +12,10 @@ RSpec.describe 'Disable individual triggers', :js do
end
context 'service has multiple supported events' do
- let(:service_name) { 'HipChat' }
+ let(:service_name) { 'Jenkins' }
it 'shows trigger checkboxes' do
- event_count = HipchatService.supported_events.count
+ event_count = JenkinsService.supported_events.count
expect(page).to have_content "Trigger"
expect(page).to have_css(checkbox_selector, visible: :all, count: event_count)
diff --git a/spec/features/projects/services/user_activates_asana_spec.rb b/spec/features/projects/services/user_activates_asana_spec.rb
index e95e7e89fc2..cf2290383e8 100644
--- a/spec/features/projects/services/user_activates_asana_spec.rb
+++ b/spec/features/projects/services/user_activates_asana_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'User activates Asana' do
it 'activates service', :js do
visit_project_integration('Asana')
- fill_in('Api key', with: 'verySecret')
+ fill_in('API key', with: 'verySecret')
fill_in('Restrict to branch', with: 'verySecret')
click_test_then_save_integration
diff --git a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
index a9d91454670..91db375be3a 100644
--- a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
+++ b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
@@ -10,19 +10,20 @@ RSpec.describe 'User activates Atlassian Bamboo CI' do
end
it 'activates service', :js do
- visit_project_integration('Atlassian Bamboo CI')
- fill_in('Bamboo url', with: 'http://bamboo.example.com')
+ visit_project_integration('Atlassian Bamboo')
+ fill_in('Bamboo URL', with: 'http://bamboo.example.com')
fill_in('Build key', with: 'KEY')
fill_in('Username', with: 'user')
fill_in('Password', with: 'verySecret')
click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Atlassian Bamboo CI settings saved and active.')
+ expect(page).to have_content('Atlassian Bamboo settings saved and active.')
# Password field should not be filled in.
- click_link('Atlassian Bamboo CI')
+ click_link('Atlassian Bamboo')
- expect(find_field('Enter new Password').value).to be_blank
+ expect(find_field('Enter new password').value).to be_blank
+ expect(page).to have_content('Leave blank to use your current password')
end
end
diff --git a/spec/features/projects/services/user_activates_hipchat_spec.rb b/spec/features/projects/services/user_activates_hipchat_spec.rb
deleted file mode 100644
index cffb780e05d..00000000000
--- a/spec/features/projects/services/user_activates_hipchat_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'User activates HipChat', :js do
- include_context 'project service activation'
-
- context 'with standard settings' do
- before do
- stub_request(:post, /.*api.hipchat.com.*/)
- end
-
- it 'activates service' do
- visit_project_integration('HipChat')
- fill_in('Room', with: 'gitlab')
- fill_in('Token', with: 'verySecret')
-
- click_test_then_save_integration(expect_test_to_fail: false)
-
- expect(page).to have_content('HipChat settings saved and active.')
- end
- end
-
- context 'with custom settings' do
- before do
- stub_request(:post, /.*chat.example.com.*/)
- end
-
- it 'activates service' do
- visit_project_integration('HipChat')
- fill_in('Room', with: 'gitlab_custom')
- fill_in('Token', with: 'secretCustom')
- fill_in('Server', with: 'https://chat.example.com')
-
- click_test_then_save_integration(expect_test_to_fail: false)
-
- expect(page).to have_content('HipChat settings saved and active.')
- end
- end
-end
diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
index 72881054c6c..17bfe8fc1e2 100644
--- a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
+++ b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
@@ -10,16 +10,16 @@ RSpec.describe 'User activates JetBrains TeamCity CI' do
end
it 'activates service', :js do
- visit_project_integration('JetBrains TeamCity CI')
+ visit_project_integration('JetBrains TeamCity')
check('Push')
check('Merge Request')
- fill_in('Teamcity url', with: 'http://teamcity.example.com')
+ fill_in('TeamCity server URL', with: 'http://teamcity.example.com')
fill_in('Build type', with: 'GitlabTest_Build')
fill_in('Username', with: 'user')
fill_in('Password', with: 'verySecret')
click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('JetBrains TeamCity CI settings saved and active.')
+ expect(page).to have_content('JetBrains TeamCity settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_jira_spec.rb b/spec/features/projects/services/user_activates_jira_spec.rb
index 85afc54be48..10f84aae93f 100644
--- a/spec/features/projects/services/user_activates_jira_spec.rb
+++ b/spec/features/projects/services/user_activates_jira_spec.rb
@@ -6,12 +6,13 @@ RSpec.describe 'User activates Jira', :js do
include_context 'project service activation'
include_context 'project service Jira context'
+ before do
+ stub_request(:get, test_url).to_return(body: { key: 'value' }.to_json)
+ end
+
describe 'user tests Jira Service' do
context 'when Jira connection test succeeds' do
before do
- server_info = { key: 'value' }.to_json
- stub_request(:get, test_url).with(basic_auth: %w(username password)).to_return(body: server_info)
-
visit_project_integration('Jira')
fill_form
click_test_then_save_integration(expect_test_to_fail: false)
@@ -81,4 +82,68 @@ RSpec.describe 'User activates Jira', :js do
end
end
end
+
+ describe 'issue transition settings' do
+ it 'using custom transitions' do
+ visit_project_integration('Jira')
+
+ expect(page).to have_field('Enable Jira transitions', checked: false)
+
+ check 'Enable Jira transitions'
+
+ expect(page).to have_field('Move to Done', checked: true)
+
+ fill_form
+ choose 'Use custom transitions'
+ click_save_integration
+
+ within '[data-testid="issue-transition-mode"]' do
+ expect(page).to have_content('This field is required.')
+ end
+
+ fill_in 'service[jira_issue_transition_id]', with: '1, 2, 3'
+ click_save_integration
+
+ expect(page).to have_content('Jira settings saved and active.')
+ expect(project.reload.jira_service.data_fields).to have_attributes(
+ jira_issue_transition_automatic: false,
+ jira_issue_transition_id: '1, 2, 3'
+ )
+ end
+
+ it 'using automatic transitions' do
+ create(:jira_service, project: project, jira_issue_transition_automatic: false, jira_issue_transition_id: '1, 2, 3')
+ visit_project_integration('Jira')
+
+ expect(page).to have_field('Enable Jira transitions', checked: true)
+ expect(page).to have_field('Use custom transitions', checked: true)
+ expect(page).to have_field('service[jira_issue_transition_id]', with: '1, 2, 3')
+
+ choose 'Move to Done'
+ click_save_integration
+
+ expect(page).to have_content('Jira settings saved and active.')
+ expect(project.reload.jira_service.data_fields).to have_attributes(
+ jira_issue_transition_automatic: true,
+ jira_issue_transition_id: ''
+ )
+ end
+
+ it 'disabling issue transitions' do
+ create(:jira_service, project: project, jira_issue_transition_automatic: true, jira_issue_transition_id: '1, 2, 3')
+ visit_project_integration('Jira')
+
+ expect(page).to have_field('Enable Jira transitions', checked: true)
+ expect(page).to have_field('Move to Done', checked: true)
+
+ uncheck 'Enable Jira transitions'
+ click_save_integration
+
+ expect(page).to have_content('Jira settings saved and active.')
+ expect(project.reload.jira_service.data_fields).to have_attributes(
+ jira_issue_transition_automatic: false,
+ jira_issue_transition_id: ''
+ )
+ end
+ end
end
diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
index 88812fc188b..54a501e89a2 100644
--- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
let(:mattermost_enabled) { true }
it 'shows a help message' do
- expect(page).to have_content("This service allows users to perform common")
+ expect(page).to have_content("Use this service to perform common")
end
it 'shows a token placeholder' do
diff --git a/spec/features/projects/services/user_activates_pushover_spec.rb b/spec/features/projects/services/user_activates_pushover_spec.rb
index 3cfd069032a..97003ab7c2a 100644
--- a/spec/features/projects/services/user_activates_pushover_spec.rb
+++ b/spec/features/projects/services/user_activates_pushover_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'User activates Pushover' do
it 'activates service', :js do
visit_project_integration('Pushover')
- fill_in('Api key', with: 'verySecret')
+ fill_in('API key', with: 'verySecret')
fill_in('User key', with: 'verySecret')
fill_in('Device', with: 'myDevice')
select('High Priority', from: 'Priority')
diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
index 2a880e05e0f..0cba1ee1c4c 100644
--- a/spec/features/projects/services/user_activates_slack_notifications_spec.rb
+++ b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'User activates Slack notifications', :js do
before do
service.fields
- service.update(
+ service.update!(
push_channel: 1,
issue_channel: 2,
merge_request_channel: 3,
diff --git a/spec/features/projects/services/user_views_services_spec.rb b/spec/features/projects/services/user_views_services_spec.rb
index fef6b7bd991..b936a7f38f6 100644
--- a/spec/features/projects/services/user_views_services_spec.rb
+++ b/spec/features/projects/services/user_views_services_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'User views services' do
+RSpec.describe 'User views services', :js do
include_context 'project service activation'
it 'shows the list of available services' do
@@ -10,7 +10,7 @@ RSpec.describe 'User views services' do
expect(page).to have_content('Integrations')
expect(page).to have_content('Campfire')
- expect(page).to have_content('HipChat')
+ expect(page).to have_content('Jira')
expect(page).to have_content('Assembla')
expect(page).to have_content('Pushover')
expect(page).to have_content('Atlassian Bamboo')
diff --git a/spec/features/projects/settings/access_tokens_spec.rb b/spec/features/projects/settings/access_tokens_spec.rb
index 45fe19deb8e..8083c851bb7 100644
--- a/spec/features/projects/settings/access_tokens_spec.rb
+++ b/spec/features/projects/settings/access_tokens_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe 'Project > Settings > Access Tokens', :js do
let_it_be(:user) { create(:user) }
let_it_be(:bot_user) { create(:user, :project_bot) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
before_all do
project.add_maintainer(user)
@@ -33,6 +34,18 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
find('#created-personal-access-token').value
end
+ context 'when user is not a project maintainer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'does not show project access token page' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).to have_content("Page Not Found")
+ end
+ end
+
describe 'token creation' do
it 'allows creation of a project access token' do
name = 'My project access token'
@@ -57,6 +70,81 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
expect(active_project_access_tokens).to have_text('read_api')
expect(created_project_access_token).not_to be_empty
end
+
+ context 'when token creation is not allowed' do
+ before do
+ group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
+ end
+
+ it 'does not show project access token creation form' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).not_to have_selector('#new_project_access_token')
+ end
+
+ it 'shows project access token creation disabled text' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).to have_text('Project access token creation is disabled in this group. You can still use and manage existing tokens.')
+ end
+
+ context 'with a project in a personal namespace' do
+ let(:personal_project) { create(:project) }
+
+ before do
+ personal_project.add_maintainer(user)
+ end
+
+ it 'shows project access token creation form and text' do
+ visit project_settings_access_tokens_path(personal_project)
+
+ expect(page).to have_selector('#new_project_access_token')
+ expect(page).to have_text('You can generate an access token scoped to this project for each application to use the GitLab API.')
+ end
+ end
+
+ context 'group settings link' do
+ context 'when user is not a group owner' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'does not show group settings link' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).not_to have_link('group settings', href: edit_group_path(group))
+ end
+ end
+
+ context 'with nested groups' do
+ let(:subgroup) { create(:group, parent: group) }
+
+ context 'when user is not a top level group owner' do
+ before do
+ subgroup.add_owner(user)
+ end
+
+ it 'does not show group settings link' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).not_to have_link('group settings', href: edit_group_path(group))
+ end
+ end
+ end
+
+ context 'when user is a group owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'shows group settings link' do
+ visit project_settings_access_tokens_path(project)
+
+ expect(page).to have_link('group settings', href: edit_group_path(group))
+ end
+ end
+ end
+ end
end
describe 'active tokens' do
@@ -83,11 +171,25 @@ RSpec.describe 'Project > Settings > Access Tokens', :js do
end
it 'removes expired tokens from active section' do
- project_access_token.update(expires_at: 5.days.ago)
+ project_access_token.update!(expires_at: 5.days.ago)
visit project_settings_access_tokens_path(project)
expect(page).to have_selector('.settings-message')
expect(no_project_access_tokens_message).to have_text(no_active_tokens_text)
end
+
+ context 'when resource access token creation is not allowed' do
+ before do
+ group.namespace_settings.update_column(:resource_access_token_creation_allowed, false)
+ end
+
+ it 'allows revocation of an active token' do
+ visit project_settings_access_tokens_path(project)
+ accept_confirm { click_on 'Revoke' }
+
+ expect(page).to have_selector('.settings-message')
+ expect(no_project_access_tokens_message).to have_text(no_active_tokens_text)
+ end
+ end
end
end
diff --git a/spec/features/projects/settings/forked_project_settings_spec.rb b/spec/features/projects/settings/forked_project_settings_spec.rb
index f6c25d483ad..a84516e19f9 100644
--- a/spec/features/projects/settings/forked_project_settings_spec.rb
+++ b/spec/features/projects/settings/forked_project_settings_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
end
shared_examples 'project settings for a forked projects' do
- it 'allows deleting the link to the forked project' do
+ it 'allows deleting the link to the forked project', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/327817' do
visit edit_project_path(forked_project)
click_button 'Remove fork relationship'
@@ -25,7 +25,8 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
fill_in('confirm_name_input', with: forked_project.name)
click_button('Confirm')
- expect(page).to have_content('The fork relationship has been removed.')
+ wait_for_requests
+
expect(forked_project.reload.forked?).to be_falsy
end
end
diff --git a/spec/features/projects/settings/operations_settings_spec.rb b/spec/features/projects/settings/operations_settings_spec.rb
index fe0ee52e4fa..ca976997142 100644
--- a/spec/features/projects/settings/operations_settings_spec.rb
+++ b/spec/features/projects/settings/operations_settings_spec.rb
@@ -146,7 +146,7 @@ RSpec.describe 'Projects > Settings > For a forked project', :js do
click_button('Connect')
- assert_text('Connection has failed. Re-check Auth Token and try again.')
+ assert_text('Connection failed. Check Auth Token and try again.')
end
end
end
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 6e4082d1391..bc60cdd2f8e 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
select('7 days', from: 'Remove tags older than:')
fill_in('Remove tags matching:', with: '.*-production')
- submit_button = find('.btn.gl-button.btn-success')
+ submit_button = find('[data-testid="save-button"')
expect(submit_button).not_to be_disabled
submit_button.click
end
@@ -53,7 +53,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
within '#js-registry-policies' do
fill_in('Remove tags matching:', with: '*-production')
- submit_button = find('.btn.gl-button.btn-success')
+ submit_button = find('[data-testid="save-button"')
expect(submit_button).not_to be_disabled
submit_button.click
end
diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
index 397c334a2b8..ebda5c9ff59 100644
--- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
+++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
@@ -2,6 +2,8 @@
require 'spec_helper'
RSpec.describe 'Projects > Settings > User manages merge request settings' do
+ include ProjectForksHelper
+
let(:user) { create(:user) }
let(:project) { create(:project, :public, namespace: user.namespace, path: 'gitlab', name: 'sample') }
@@ -198,4 +200,36 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(project.reload.project_setting.squash_option).to eq('never')
end
end
+
+ describe 'target project settings' do
+ context 'when project is a fork' do
+ let_it_be(:upstream) { create(:project, :public) }
+
+ let(:project) { fork_project(upstream, user) }
+
+ it 'allows to change merge request target project behavior' do
+ expect(page).to have_content 'The default target project for merge requests'
+
+ radio = find_field('project_project_setting_attributes_mr_default_target_self_false')
+ expect(radio).to be_checked
+
+ choose('project_project_setting_attributes_mr_default_target_self_true')
+
+ within('.merge-request-settings-form') do
+ find('.rspec-save-merge-request-changes')
+ click_on('Save changes')
+ end
+
+ find('.flash-notice')
+ radio = find_field('project_project_setting_attributes_mr_default_target_self_true')
+
+ expect(radio).to be_checked
+ expect(project.reload.project_setting.mr_default_target_self).to be_truthy
+ end
+ end
+
+ it 'does not show target project section' do
+ expect(page).not_to have_content 'The default target project for merge requests'
+ end
+ end
end
diff --git a/spec/features/projects/settings/user_searches_in_settings_spec.rb b/spec/features/projects/settings/user_searches_in_settings_spec.rb
index 4c5b39d5282..9b09958bae5 100644
--- a/spec/features/projects/settings/user_searches_in_settings_spec.rb
+++ b/spec/features/projects/settings/user_searches_in_settings_spec.rb
@@ -4,16 +4,42 @@ require 'spec_helper'
RSpec.describe 'User searches project settings', :js do
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:project) { create(:project, :repository, namespace: user.namespace, pages_https_only: false) }
before do
sign_in(user)
end
context 'in general settings page' do
- let(:visit_path) { edit_project_path(project) }
+ before do
+ visit edit_project_path(project)
+ end
+
+ it_behaves_like 'can search settings', 'Naming', 'Visibility'
+ end
+
+ context 'in Integrations page' do
+ before do
+ visit project_settings_integrations_path(project)
+ end
+
+ it_behaves_like 'can highlight results', 'third-party applications'
+ end
+
+ context 'in Webhooks page' do
+ before do
+ visit project_hooks_path(project)
+ end
- it_behaves_like 'can search settings with feature flag check', 'Naming', 'Visibility'
+ it_behaves_like 'can highlight results', 'Secret token'
+ end
+
+ context 'in Access Tokens page' do
+ before do
+ visit project_settings_access_tokens_path(project)
+ end
+
+ it_behaves_like 'can highlight results', 'Expires at'
end
context 'in Repository page' do
@@ -37,6 +63,16 @@ RSpec.describe 'User searches project settings', :js do
visit project_settings_operations_path(project)
end
- it_behaves_like 'can search settings', 'Alerts', 'Error tracking'
+ it_behaves_like 'can search settings', 'Alert integrations', 'Error tracking'
+ end
+
+ context 'in Pages page' do
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+
+ visit project_pages_path(project)
+ end
+
+ it_behaves_like 'can highlight results', 'static website'
end
end
diff --git a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
index d0f297d2067..eed3494ef5b 100644
--- a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
+++ b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb
@@ -13,16 +13,10 @@ RSpec.describe 'Repository Settings > User sees revoke deploy token modal', :js
sign_in(user)
stub_feature_flags(ajax_new_deploy_token: project)
visit(project_settings_repository_path(project))
- click_link('Revoke')
+ click_button('Revoke')
end
it 'shows the revoke deploy token modal' do
expect(page).to have_content('You are about to revoke')
end
-
- it 'closes the revoke deploy token modal with escape keypress' do
- find('.modal.show').send_keys(:escape)
-
- expect(page).not_to have_content('You are about to revoke')
- end
end
diff --git a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
index 5e878411f6a..b7af0c29b33 100644
--- a/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
+++ b/spec/features/projects/show/user_sees_deletion_failure_message_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Projects > Show > User sees a deletion failure message' do
end
it 'shows error message if deletion for project fails' do
- project.update(delete_error: "Something went wrong", pending_delete: false)
+ project.update!(delete_error: "Something went wrong", pending_delete: false)
visit project_path(project)
diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
index 9b51e867156..dc551158895 100644
--- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
@@ -226,11 +226,11 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do
expect(project.repository.gitlab_ci_yml).to be_nil
page.within('.project-buttons') do
- expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_path)
+ expect(page).to have_link('Set up CI/CD', href: project_ci_pipeline_editor_path(project))
end
end
- it 'no "Set up CI/CD" button if the project already has a .gitlab-ci.yml' do
+ it '"Set up CI/CD" button is renamed if the project already has a .gitlab-ci.yml' do
Files::CreateService.new(
project,
project.creator,
@@ -247,6 +247,7 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do
page.within('.project-buttons') do
expect(page).not_to have_link('Set up CI/CD')
+ expect(page).to have_link('CI/CD configuration')
end
end
end
diff --git a/spec/features/projects/show/user_uploads_files_spec.rb b/spec/features/projects/show/user_uploads_files_spec.rb
index 2030c4d998a..eb230082bfa 100644
--- a/spec/features/projects/show/user_uploads_files_spec.rb
+++ b/spec/features/projects/show/user_uploads_files_spec.rb
@@ -17,11 +17,17 @@ RSpec.describe 'Projects > Show > User uploads files' do
context 'when a user has write access' do
before do
visit(project_path(project))
+
+ wait_for_requests
end
- include_examples 'it uploads and commit a new text file'
+ include_examples 'it uploads and commits a new text file'
+
+ include_examples 'it uploads and commits a new image file'
+
+ include_examples 'it uploads and commits a new pdf file'
- include_examples 'it uploads and commit a new image file'
+ include_examples 'it uploads a file to a sub-directory'
end
context 'when a user does not have write access' do
@@ -31,7 +37,7 @@ RSpec.describe 'Projects > Show > User uploads files' do
visit(project_path(project2))
end
- include_examples 'it uploads and commit a new file to a forked project'
+ include_examples 'it uploads and commits a new file to a forked project'
end
context 'when in the empty_repo_upload experiment' do
diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
index b37d40c0eed..3ccb73c88ef 100644
--- a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
@@ -29,7 +29,6 @@ RSpec.describe 'Projects > Snippets > User comments on a snippet', :js do
end
it 'has autocomplete' do
- find('#note_note').native.send_keys('')
fill_in 'note[note]', with: '@'
expect(page).to have_selector('.atwho-view')
diff --git a/spec/features/projects/sub_group_issuables_spec.rb b/spec/features/projects/sub_group_issuables_spec.rb
index 8c1d88276df..d7614201740 100644
--- a/spec/features/projects/sub_group_issuables_spec.rb
+++ b/spec/features/projects/sub_group_issuables_spec.rb
@@ -16,18 +16,18 @@ RSpec.describe 'Subgroup Issuables', :js do
it 'shows the full subgroup title when issues index page is empty' do
visit project_issues_path(project)
- expect_to_have_full_subgroup_title
+ expect_to_have_breadcrumb_links
end
it 'shows the full subgroup title when merge requests index page is empty' do
visit project_merge_requests_path(project)
- expect_to_have_full_subgroup_title
+ expect_to_have_breadcrumb_links
end
- def expect_to_have_full_subgroup_title
- title = find('.breadcrumbs-links')
+ def expect_to_have_breadcrumb_links
+ links = find('[data-testid="breadcrumb-links"]')
- expect(title).to have_content 'group subgroup project'
+ expect(links).to have_content 'group subgroup project'
end
end
diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb
index e5ba6b503cc..ff6217d02a7 100644
--- a/spec/features/projects/user_sees_sidebar_spec.rb
+++ b/spec/features/projects/user_sees_sidebar_spec.rb
@@ -208,7 +208,7 @@ RSpec.describe 'Projects > User sees sidebar' do
it 'shows build tab if builds are public' do
project.public_builds = true
- project.save
+ project.save!
visit project_path(project)
diff --git a/spec/features/projects/user_sees_user_popover_spec.rb b/spec/features/projects/user_sees_user_popover_spec.rb
index 52e65deae3b..e357824a533 100644
--- a/spec/features/projects/user_sees_user_popover_spec.rb
+++ b/spec/features/projects/user_sees_user_popover_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'User sees user popover', :js do
end
end
- it "displays user popover in system note" do
+ it 'displays user popover in system note', :sidekiq_inline do
add_note("/assign @#{user.username}")
find('.system-note-message .js-user-link').hover
diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb
index f97c8d820e3..b6fde19e0d4 100644
--- a/spec/features/projects/user_uses_shortcuts_spec.rb
+++ b/spec/features/projects/user_uses_shortcuts_spec.rb
@@ -151,7 +151,7 @@ RSpec.describe 'User uses shortcuts', :js do
find('body').native.send_key('g')
find('body').native.send_key('m')
- expect(page).to have_active_navigation('Merge Requests')
+ expect(page).to have_active_navigation('Merge requests')
end
end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 4730679feb8..c18b0f2688b 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -174,26 +174,6 @@ RSpec.describe 'Project' do
end
end
- describe 'remove forked relationship', :js do
- let(:user) { create(:user) }
- let(:project) { fork_project(create(:project, :public), user, namespace: user.namespace) }
-
- before do
- sign_in user
- visit edit_project_path(project)
- end
-
- it 'removes fork' do
- expect(page).to have_content 'Remove fork relationship'
-
- remove_with_confirm('Remove fork relationship', project.path)
-
- expect(page).to have_content 'The fork relationship has been removed.'
- expect(project.reload.forked?).to be_falsey
- expect(page).not_to have_content 'Remove fork relationship'
- end
- end
-
describe 'showing information about source of a project fork' do
let(:user) { create(:user) }
let(:base_project) { create(:project, :public, :repository) }
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index eb099359df9..207b74c990a 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -24,8 +24,8 @@ RSpec.describe 'Protected Branches', :js do
it 'does not allow developer to removes protected branch' do
visit project_branches_path(project)
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_css('.btn-danger.disabled')
end
@@ -47,8 +47,8 @@ RSpec.describe 'Protected Branches', :js do
it 'removes branch after modal confirmation' do
visit project_branches_path(project)
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
@@ -58,8 +58,8 @@ RSpec.describe 'Protected Branches', :js do
fill_in 'delete_branch_input', with: 'fix'
click_link 'Delete protected branch'
- fill_in 'branch-search', with: 'fix'
- find('#branch-search').native.send_keys(:enter)
+ find('input[data-testid="branch-search"]').set('fix')
+ find('input[data-testid="branch-search"]').native.send_keys(:enter)
expect(page).to have_content('No branches to show')
end
diff --git a/spec/features/registrations/welcome_spec.rb b/spec/features/registrations/welcome_spec.rb
new file mode 100644
index 00000000000..74320b69f19
--- /dev/null
+++ b/spec/features/registrations/welcome_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Welcome screen' do
+ let(:user) { create(:user) }
+
+ before do
+ gitlab_sign_in(user)
+
+ visit users_sign_up_welcome_path
+ end
+
+ it 'shows the email opt in' do
+ select 'Software Developer', from: 'user_role'
+ check 'user_email_opted_in'
+ click_button 'Get started!'
+
+ expect(user.reload.email_opted_in).to eq(true)
+ end
+end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index cc024ab8f35..acfb7c2602a 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -49,19 +49,19 @@ RSpec.describe 'Runners' do
visit project_runners_path(project)
within '.activated-specific-runners' do
- expect(page).to have_content('Pause')
+ expect(page).to have_link('Pause')
end
click_on 'Pause'
within '.activated-specific-runners' do
- expect(page).to have_content('Resume')
+ expect(page).to have_link('Resume')
end
click_on 'Resume'
within '.activated-specific-runners' do
- expect(page).to have_content('Pause')
+ expect(page).to have_link('Pause')
end
end
@@ -79,7 +79,7 @@ RSpec.describe 'Runners' do
visit project_runners_path(project)
within '.activated-specific-runners' do
- first('.edit-runner > a').click
+ first('[data-testid="edit-runner-link"]').click
end
expect(page.find_field('runner[access_level]')).not_to be_checked
@@ -92,14 +92,14 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
- specific_runner.update(tag_list: ['tag'])
+ specific_runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
visit project_runners_path(project)
within '.activated-specific-runners' do
- first('.edit-runner > a').click
+ first('[data-testid="edit-runner-link"]').click
end
expect(page.find_field('runner[run_untagged]')).to be_checked
@@ -370,7 +370,7 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
- runner.update(tag_list: ['tag'])
+ runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
@@ -450,7 +450,7 @@ RSpec.describe 'Runners' do
context 'when a runner has a tag' do
before do
- runner.update(tag_list: ['tag'])
+ runner.update!(tag_list: ['tag'])
end
it 'user edits runner not to run untagged jobs' do
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index 9296a3f33d4..4c42800cf05 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe 'User uses header search field', :js do
fill_in_search('Merge')
within(dashboard_search_options_popup_menu) do
- expect(page).to have_text('Merge Requests')
+ expect(page).to have_text('Merge requests')
end
end
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index 2440b738db3..9dcef13757a 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -356,7 +356,7 @@ RSpec.describe "Internal Project Access" do
context "when allowed for public and internal" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -372,7 +372,7 @@ RSpec.describe "Internal Project Access" do
context "when disallowed for public and internal" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -396,7 +396,7 @@ RSpec.describe "Internal Project Access" do
context "when allowed for public and internal" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -412,7 +412,7 @@ RSpec.describe "Internal Project Access" do
context "when disallowed for public and internal" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -436,7 +436,7 @@ RSpec.describe "Internal Project Access" do
context 'when allowed for public and internal' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -452,7 +452,7 @@ RSpec.describe "Internal Project Access" do
context 'when disallowed for public and internal' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
index 9d3109b92e6..5a200bea80a 100644
--- a/spec/features/security/project/private_access_spec.rb
+++ b/spec/features/security/project/private_access_spec.rb
@@ -319,7 +319,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -348,7 +348,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -375,7 +375,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -405,7 +405,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -414,7 +414,7 @@ RSpec.describe "Private Project Access" do
context 'when public buils are disabled' do
before do
project.public_builds = false
- project.save
+ project.save!
end
it { is_expected.to be_denied_for(:guest).of(project) }
@@ -440,7 +440,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is enabled' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:guest).of(project) }
@@ -448,7 +448,7 @@ RSpec.describe "Private Project Access" do
context 'when public builds is disabled' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it { is_expected.to be_denied_for(:guest).of(project) }
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
index 28a1f1cda7f..8ceb6920e77 100644
--- a/spec/features/security/project/public_access_spec.rb
+++ b/spec/features/security/project/public_access_spec.rb
@@ -164,7 +164,7 @@ RSpec.describe "Public Project Access" do
context "when allowed for public" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -180,7 +180,7 @@ RSpec.describe "Public Project Access" do
context "when disallowed for public" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -204,7 +204,7 @@ RSpec.describe "Public Project Access" do
context "when allowed for public" do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -220,7 +220,7 @@ RSpec.describe "Public Project Access" do
context "when disallowed for public" do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
@@ -244,7 +244,7 @@ RSpec.describe "Public Project Access" do
context 'when allowed for public' do
before do
- project.update(public_builds: true)
+ project.update!(public_builds: true)
end
it { is_expected.to be_allowed_for(:admin) }
@@ -260,7 +260,7 @@ RSpec.describe "Public Project Access" do
context 'when disallowed for public' do
before do
- project.update(public_builds: false)
+ project.update!(public_builds: false)
end
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb
index ce9a2d1461e..47dad9bd88e 100644
--- a/spec/features/snippets/notes_on_personal_snippets_spec.rb
+++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb
@@ -108,9 +108,6 @@ RSpec.describe 'Comments on personal snippets', :js do
end
it 'does not have autocomplete' do
- wait_for_requests
-
- find('#note_note').native.send_keys('')
fill_in 'note[note]', with: '@'
wait_for_requests
diff --git a/spec/features/users/anonymous_sessions_spec.rb b/spec/features/users/anonymous_sessions_spec.rb
index 420fb225f94..273d3aa346f 100644
--- a/spec/features/users/anonymous_sessions_spec.rb
+++ b/spec/features/users/anonymous_sessions_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Session TTLs', :clean_gitlab_redis_shared_state do
fill_in 'user_password', with: '12345678'
click_button 'Sign in'
- expect(page).to have_content('Invalid Login or password')
+ expect(page).to have_content('Invalid login or password')
expect_single_session_with_expiration(Settings.gitlab['unauthenticated_session_expire_delay'])
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 1d1120709b5..e60d9d6ab69 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -138,7 +138,7 @@ RSpec.describe 'Login' do
gitlab_sign_in(User.ghost)
- expect(page).to have_content('Invalid Login or password.')
+ expect(page).to have_content('Invalid login or password.')
end
it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do
@@ -239,7 +239,7 @@ RSpec.describe 'Login' do
expect(codes.size).to eq 10
# Ensure the generated codes get saved
- user.save(touch: false)
+ user.save!(touch: false)
end
context 'with valid code' do
@@ -406,7 +406,7 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
- expect(page).to have_content('Invalid Login or password.')
+ expect(page).to have_content('Invalid login or password.')
end
end
end
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index a8372800700..56d2aaea203 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'User page' do
context 'work information' do
it 'shows job title and organization details' do
- user.update(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
+ user.update!(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
subject
@@ -41,7 +41,7 @@ RSpec.describe 'User page' do
end
it 'shows job title' do
- user.update(organization: nil, job_title: 'Frontend Engineer - work info test')
+ user.update!(organization: nil, job_title: 'Frontend Engineer - work info test')
subject
@@ -49,7 +49,7 @@ RSpec.describe 'User page' do
end
it 'shows organization details' do
- user.update(organization: 'GitLab - work info test', job_title: '')
+ user.update!(organization: 'GitLab - work info test', job_title: '')
subject
diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb
index 7500f2fe59a..8ba79d77c22 100644
--- a/spec/features/users/terms_spec.rb
+++ b/spec/features/users/terms_spec.rb
@@ -121,7 +121,7 @@ RSpec.describe 'Users > Terms' do
enforce_terms
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(current_path).to eq(terms_path)
diff --git a/spec/features/whats_new_spec.rb b/spec/features/whats_new_spec.rb
index 7c5625486f5..55b96361f03 100644
--- a/spec/features/whats_new_spec.rb
+++ b/spec/features/whats_new_spec.rb
@@ -2,34 +2,60 @@
require "spec_helper"
-RSpec.describe "renders a `whats new` dropdown item", :js do
+RSpec.describe "renders a `whats new` dropdown item" do
let_it_be(:user) { create(:user) }
- before do
- sign_in(user)
- end
+ context 'when not logged in' do
+ it 'and on .com it renders' do
+ allow(Gitlab).to receive(:com?).and_return(true)
- it 'shows notification dot and count and removes it once viewed' do
- visit root_dashboard_path
+ visit user_path(user)
- page.within '.header-help' do
- expect(page).to have_selector('.notification-dot', visible: true)
+ page.within '.header-help' do
+ find('.header-help-dropdown-toggle').click
- find('.header-help-dropdown-toggle').click
+ expect(page).to have_button(text: "What's new")
+ end
+ end
+
+ it "doesn't render what's new" do
+ visit user_path(user)
- expect(page).to have_button(text: "What's new")
- expect(page).to have_selector('.js-whats-new-notification-count')
+ page.within '.header-help' do
+ find('.header-help-dropdown-toggle').click
+
+ expect(page).not_to have_button(text: "What's new")
+ end
+ end
+ end
- find('button', text: "What's new").click
+ context 'when logged in', :js do
+ before do
+ sign_in(user)
end
- find('.whats-new-drawer .gl-drawer-close-button').click
- find('.header-help-dropdown-toggle').click
+ it 'shows notification dot and count and removes it once viewed' do
+ visit root_dashboard_path
+
+ page.within '.header-help' do
+ expect(page).to have_selector('.notification-dot', visible: true)
+
+ find('.header-help-dropdown-toggle').click
+
+ expect(page).to have_button(text: "What's new")
+ expect(page).to have_selector('.js-whats-new-notification-count')
+
+ find('button', text: "What's new").click
+ end
+
+ find('.whats-new-drawer .gl-drawer-close-button').click
+ find('.header-help-dropdown-toggle').click
- page.within '.header-help' do
- expect(page).not_to have_selector('.notification-dot', visible: true)
- expect(page).to have_button(text: "What's new")
- expect(page).not_to have_selector('.js-whats-new-notification-count')
+ page.within '.header-help' do
+ expect(page).not_to have_selector('.notification-dot', visible: true)
+ expect(page).to have_button(text: "What's new")
+ expect(page).not_to have_selector('.js-whats-new-notification-count')
+ end
end
end
end