summaryrefslogtreecommitdiff
path: root/spec/features
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-01-21 14:21:10 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-21 14:21:10 +0000
commitcb0d23c455b73486fd1015f8ca9479b5b7e3585d (patch)
treed7dc129a407fd74266d2dc561bebf24665197c2f /spec/features
parentc3e911be175c0aabfea1eb030f9e0ef23f5f3887 (diff)
downloadgitlab-ce-cb0d23c455b73486fd1015f8ca9479b5b7e3585d.tar.gz
Add latest changes from gitlab-org/gitlab@12-7-stable-ee
Diffstat (limited to 'spec/features')
-rw-r--r--spec/features/admin/admin_broadcast_messages_spec.rb30
-rw-r--r--spec/features/admin/admin_groups_spec.rb10
-rw-r--r--spec/features/admin/admin_hooks_spec.rb4
-rw-r--r--spec/features/admin/admin_projects_spec.rb4
-rw-r--r--spec/features/admin/admin_runners_spec.rb24
-rw-r--r--spec/features/boards/boards_spec.rb10
-rw-r--r--spec/features/boards/modal_filter_spec.rb2
-rw-r--r--spec/features/boards/sidebar_spec.rb4
-rw-r--r--spec/features/clusters/installing_applications_shared_examples.rb3
-rw-r--r--spec/features/cycle_analytics_spec.rb2
-rw-r--r--spec/features/dashboard/instance_statistics_spec.rb22
-rw-r--r--spec/features/dashboard/issues_filter_spec.rb6
-rw-r--r--spec/features/dashboard/issues_spec.rb2
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb4
-rw-r--r--spec/features/dashboard/projects_spec.rb28
-rw-r--r--spec/features/dashboard/snippets_spec.rb1
-rw-r--r--spec/features/groups/issues_spec.rb2
-rw-r--r--spec/features/groups/members/manage_groups_spec.rb89
-rw-r--r--spec/features/groups/members/manage_members_spec.rb8
-rw-r--r--spec/features/groups/members/search_members_spec.rb2
-rw-r--r--spec/features/groups/merge_requests_spec.rb2
-rw-r--r--spec/features/import/manifest_import_spec.rb10
-rw-r--r--spec/features/instance_statistics/cohorts_spec.rb2
-rw-r--r--spec/features/issuables/issuable_list_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb201
-rw-r--r--spec/features/issues/filtered_search/dropdown_author_spec.rb169
-rw-r--r--spec/features/issues/filtered_search/dropdown_base_spec.rb58
-rw-r--r--spec/features/issues/filtered_search/dropdown_emoji_spec.rb156
-rw-r--r--spec/features/issues/filtered_search/dropdown_hint_spec.rb193
-rw-r--r--spec/features/issues/filtered_search/dropdown_label_spec.rb285
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb253
-rw-r--r--spec/features/issues/filtered_search/dropdown_release_spec.rb30
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb216
-rw-r--r--spec/features/issues/filtered_search/recent_searches_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/search_bar_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/visual_tokens_spec.rb219
-rw-r--r--spec/features/issues/rss_spec.rb37
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb6
-rw-r--r--spec/features/issues/user_creates_issue_by_email_spec.rb46
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb126
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb279
-rw-r--r--spec/features/issues/user_filters_issues_spec.rb39
-rw-r--r--spec/features/issues/user_resets_their_incoming_email_token_spec.rb32
-rw-r--r--spec/features/issues/user_sees_breadcrumb_links_spec.rb20
-rw-r--r--spec/features/issues/user_sees_empty_state_spec.rb51
-rw-r--r--spec/features/issues/user_sees_live_update_spec.rb52
-rw-r--r--spec/features/issues/user_sorts_issues_spec.rb187
-rw-r--r--spec/features/issues_spec.rb828
-rw-r--r--spec/features/labels_hierarchy_spec.rb6
-rw-r--r--spec/features/markdown/markdown_spec.rb18
-rw-r--r--spec/features/merge_request/maintainer_edits_fork_spec.rb2
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb3
-rw-r--r--spec/features/merge_request/user_creates_image_diff_notes_spec.rb3
-rw-r--r--spec/features/merge_request/user_expands_diff_spec.rb3
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb3
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb4
-rw-r--r--spec/features/merge_request/user_resolves_conflicts_spec.rb3
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb3
-rw-r--r--spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb3
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb3
-rw-r--r--spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb3
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb29
-rw-r--r--spec/features/merge_request/user_suggests_changes_on_diff_spec.rb6
-rw-r--r--spec/features/merge_request/user_toggles_whitespace_changes_spec.rb3
-rw-r--r--spec/features/merge_request/user_views_diffs_spec.rb3
-rw-r--r--spec/features/merge_requests/filters_generic_behavior_spec.rb2
-rw-r--r--spec/features/merge_requests/user_filters_by_assignees_spec.rb6
-rw-r--r--spec/features/merge_requests/user_filters_by_labels_spec.rb6
-rw-r--r--spec/features/merge_requests/user_filters_by_milestones_spec.rb10
-rw-r--r--spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb4
-rw-r--r--spec/features/merge_requests/user_filters_by_target_branch_spec.rb6
-rw-r--r--spec/features/profiles/active_sessions_spec.rb27
-rw-r--r--spec/features/profiles/user_visits_profile_preferences_page_spec.rb17
-rw-r--r--spec/features/projects/badges/coverage_spec.rb2
-rw-r--r--spec/features/projects/blobs/edit_spec.rb4
-rw-r--r--spec/features/projects/environments/environment_metrics_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb69
-rw-r--r--spec/features/projects/features_visibility_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb15
-rw-r--r--spec/features/projects/files/user_browses_lfs_files_spec.rb15
-rw-r--r--spec/features/projects/fork_spec.rb83
-rw-r--r--spec/features/projects/jobs_spec.rb15
-rw-r--r--spec/features/projects/members/list_spec.rb4
-rw-r--r--spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb4
-rw-r--r--spec/features/projects/pages_spec.rb6
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb140
-rw-r--r--spec/features/projects/raw/user_interacts_with_raw_endpoint_spec.rb2
-rw-r--r--spec/features/projects/serverless/functions_spec.rb5
-rw-r--r--spec/features/projects/settings/project_settings_spec.rb20
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb37
-rw-r--r--spec/features/projects/settings/user_manages_project_members_spec.rb2
-rw-r--r--spec/features/projects/settings/user_renames_a_project_spec.rb4
-rw-r--r--spec/features/projects/snippets/create_snippet_spec.rb4
-rw-r--r--spec/features/projects/sourcegraph_csp_spec.rb98
-rw-r--r--spec/features/projects/tree/create_directory_spec.rb2
-rw-r--r--spec/features/projects/tree/create_file_spec.rb2
-rw-r--r--spec/features/projects/view_on_env_spec.rb3
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb18
-rw-r--r--spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb79
-rw-r--r--spec/features/task_lists_spec.rb69
-rw-r--r--spec/features/triggers_spec.rb92
-rw-r--r--spec/features/users/signup_spec.rb134
103 files changed, 2155 insertions, 2723 deletions
diff --git a/spec/features/admin/admin_broadcast_messages_spec.rb b/spec/features/admin/admin_broadcast_messages_spec.rb
index c5a302ce78b..bf7f8563e68 100644
--- a/spec/features/admin/admin_broadcast_messages_spec.rb
+++ b/spec/features/admin/admin_broadcast_messages_spec.rb
@@ -13,7 +13,7 @@ describe 'Admin Broadcast Messages' do
expect(page).to have_content 'Migration to new server'
end
- it 'Create a customized broadcast message' do
+ it 'creates a customized broadcast banner message' do
fill_in 'broadcast_message_message', with: 'Application update from **4:00 CST to 5:00 CST**'
fill_in 'broadcast_message_color', with: '#f2dede'
fill_in 'broadcast_message_target_path', with: '*/user_onboarded'
@@ -28,6 +28,20 @@ describe 'Admin Broadcast Messages' do
expect(page).to have_selector %(div[style="background-color: #f2dede; color: #b94a48"])
end
+ it 'creates a customized broadcast notification message' do
+ fill_in 'broadcast_message_message', with: 'Application update from **4:00 CST to 5:00 CST**'
+ fill_in 'broadcast_message_target_path', with: '*/user_onboarded'
+ select 'Notification', from: 'broadcast_message_broadcast_type'
+ select Date.today.next_year.year, from: 'broadcast_message_ends_at_1i'
+ click_button 'Add broadcast message'
+
+ expect(current_path).to eq admin_broadcast_messages_path
+ expect(page).to have_content 'Application update from 4:00 CST to 5:00 CST'
+ expect(page).to have_content '*/user_onboarded'
+ expect(page).to have_content 'Notification'
+ expect(page).to have_selector 'strong', text: '4:00 CST to 5:00 CST'
+ end
+
it 'Edit an existing broadcast message' do
click_link 'Edit'
fill_in 'broadcast_message_message', with: 'Application update RIGHT NOW'
@@ -44,10 +58,20 @@ describe 'Admin Broadcast Messages' do
expect(page).not_to have_content 'Migration to new server'
end
- it 'Live preview a customized broadcast message', :js do
+ it 'updates a preview of a customized broadcast banner message', :js do
+ fill_in 'broadcast_message_message', with: "Live **Markdown** previews. :tada:"
+
+ page.within('.js-broadcast-banner-message-preview') do
+ expect(page).to have_selector('strong', text: 'Markdown')
+ expect(page).to have_emoji('tada')
+ end
+ end
+
+ it 'updates a preview of a customized broadcast notification message', :js do
fill_in 'broadcast_message_message', with: "Live **Markdown** previews. :tada:"
+ select 'Notification', from: 'broadcast_message_broadcast_type'
- page.within('.broadcast-message-preview') do
+ page.within('.js-broadcast-notification-message-preview') do
expect(page).to have_selector('strong', text: 'Markdown')
expect(page).to have_emoji('tada')
end
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 257e5cb8bf0..9a4889a0335 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -167,14 +167,14 @@ describe 'Admin Groups' do
it 'adds admin a to a group as developer', :js do
visit group_group_members_path(group)
- page.within '.users-group-form' do
+ page.within '.invite-users-form' do
select2(current_user.id, from: '#user_ids', multiple: true)
select 'Developer', from: 'access_level'
end
- click_button 'Add to group'
+ click_button 'Invite'
- page.within '.content-list' do
+ page.within '[data-qa-selector="members_list"]' do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end
@@ -187,7 +187,7 @@ describe 'Admin Groups' do
visit group_group_members_path(group)
- page.within '.content-list' do
+ page.within '[data-qa-selector="members_list"]' do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end
@@ -196,7 +196,7 @@ describe 'Admin Groups' do
visit group_group_members_path(group)
- page.within '.content-list' do
+ page.within '[data-qa-selector="members_list"]' do
expect(page).not_to have_content(current_user.name)
expect(page).not_to have_content('Developer')
end
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index b4bcbe9d812..64326f3be32 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -28,11 +28,11 @@ describe 'Admin::Hooks' do
end
it 'renders plugins list as well' do
- allow(Gitlab::Plugin).to receive(:files).and_return(['foo.rb', 'bar.clj'])
+ allow(Gitlab::FileHook).to receive(:files).and_return(['foo.rb', 'bar.clj'])
visit admin_hooks_path
- expect(page).to have_content('Plugins')
+ expect(page).to have_content('File Hooks')
expect(page).to have_content('foo.rb')
expect(page).to have_content('bar.clj')
end
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index 7c40ac5bde3..d1889d3a89a 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -98,12 +98,12 @@ describe "Admin::Projects" do
it 'adds admin a to a project as developer', :js do
visit project_project_members_path(project)
- page.within '.users-project-form' do
+ page.within '.invite-users-form' do
select2(current_user.id, from: '#user_ids', multiple: true)
select 'Developer', from: 'access_level'
end
- click_button 'Add to project'
+ click_button 'Invite'
page.within '.content-list' do
expect(page).to have_content(current_user.name)
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 0d5f5df71b6..6bcadda6523 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -57,7 +57,7 @@ describe "Admin Runners" do
expect(page).to have_content 'runner-active'
expect(page).to have_content 'runner-paused'
- input_filtered_search_keys('status:active')
+ input_filtered_search_keys('status=active')
expect(page).to have_content 'runner-active'
expect(page).not_to have_content 'runner-paused'
end
@@ -68,7 +68,7 @@ describe "Admin Runners" do
visit admin_runners_path
- input_filtered_search_keys('status:offline')
+ input_filtered_search_keys('status=offline')
expect(page).not_to have_content 'runner-active'
expect(page).not_to have_content 'runner-paused'
@@ -83,12 +83,12 @@ describe "Admin Runners" do
visit admin_runners_path
- input_filtered_search_keys('status:active')
+ input_filtered_search_keys('status=active')
expect(page).to have_content 'runner-a-1'
expect(page).to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
- input_filtered_search_keys('status:active runner-a')
+ input_filtered_search_keys('status=active runner-a')
expect(page).to have_content 'runner-a-1'
expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
@@ -105,7 +105,7 @@ describe "Admin Runners" do
expect(page).to have_content 'runner-project'
expect(page).to have_content 'runner-group'
- input_filtered_search_keys('type:project_type')
+ input_filtered_search_keys('type=project_type')
expect(page).to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
end
@@ -116,7 +116,7 @@ describe "Admin Runners" do
visit admin_runners_path
- input_filtered_search_keys('type:instance_type')
+ input_filtered_search_keys('type=instance_type')
expect(page).not_to have_content 'runner-project'
expect(page).not_to have_content 'runner-group'
@@ -131,12 +131,12 @@ describe "Admin Runners" do
visit admin_runners_path
- input_filtered_search_keys('type:project_type')
+ input_filtered_search_keys('type=project_type')
expect(page).to have_content 'runner-a-1'
expect(page).to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
- input_filtered_search_keys('type:project_type runner-a')
+ input_filtered_search_keys('type=project_type runner-a')
expect(page).to have_content 'runner-a-1'
expect(page).not_to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
@@ -153,7 +153,7 @@ describe "Admin Runners" do
expect(page).to have_content 'runner-blue'
expect(page).to have_content 'runner-red'
- input_filtered_search_keys('tag:blue')
+ input_filtered_search_keys('tag=blue')
expect(page).to have_content 'runner-blue'
expect(page).not_to have_content 'runner-red'
@@ -165,7 +165,7 @@ describe "Admin Runners" do
visit admin_runners_path
- input_filtered_search_keys('tag:red')
+ input_filtered_search_keys('tag=red')
expect(page).not_to have_content 'runner-blue'
expect(page).not_to have_content 'runner-blue'
@@ -179,13 +179,13 @@ describe "Admin Runners" do
visit admin_runners_path
- input_filtered_search_keys('tag:blue')
+ input_filtered_search_keys('tag=blue')
expect(page).to have_content 'runner-a-1'
expect(page).to have_content 'runner-b-1'
expect(page).not_to have_content 'runner-a-2'
- input_filtered_search_keys('tag:blue runner-a')
+ input_filtered_search_keys('tag=blue runner-a')
expect(page).to have_content 'runner-a-1'
expect(page).not_to have_content 'runner-b-1'
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index c740e4e26d9..8aad598b843 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -163,9 +163,7 @@ describe 'Issue Boards', :js do
end
it 'infinite scrolls list' do
- 50.times do
- create(:labeled_issue, project: project, labels: [planning])
- end
+ create_list(:labeled_issue, 50, project: project, labels: [planning])
visit project_board_path(project, board)
wait_for_requests
@@ -475,9 +473,7 @@ describe 'Issue Boards', :js do
end
it 'infinite scrolls list with label filter' do
- 50.times do
- create(:labeled_issue, project: project, labels: [planning, testing])
- end
+ create_list(:labeled_issue, 50, project: project, labels: [planning, testing])
set_filter("label", testing.title)
click_filter_link(testing.title)
@@ -628,7 +624,7 @@ describe 'Issue Boards', :js do
end
def set_filter(type, text)
- find('.filtered-search').native.send_keys("#{type}:#{text}")
+ find('.filtered-search').native.send_keys("#{type}=#{text}")
end
def submit_filter
diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb
index 70bc067f79d..d14041ecf3f 100644
--- a/spec/features/boards/modal_filter_spec.rb
+++ b/spec/features/boards/modal_filter_spec.rb
@@ -211,7 +211,7 @@ describe 'Issue Boards add issue modal filtering', :js do
end
def set_filter(type, text = '')
- find('.add-issues-modal .filtered-search').native.send_keys("#{type}:#{text}")
+ find('.add-issues-modal .filtered-search').native.send_keys("#{type}=#{text}")
end
def submit_filter
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index 9143db16b87..c7edb574f19 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -318,7 +318,9 @@ describe 'Issue Boards', :js do
wait_for_requests
click_link bug.title
- within('.dropdown-menu-labels') { expect(page).to have_selector('.is-active', count: 3) }
+
+ wait_for_requests
+
click_link regression.title
wait_for_requests
diff --git a/spec/features/clusters/installing_applications_shared_examples.rb b/spec/features/clusters/installing_applications_shared_examples.rb
index 988cd228c1c..20648ed3d46 100644
--- a/spec/features/clusters/installing_applications_shared_examples.rb
+++ b/spec/features/clusters/installing_applications_shared_examples.rb
@@ -181,11 +181,8 @@ shared_examples "installing applications on a cluster" do
context 'when user installs Elastic Stack' do
before do
allow(ClusterInstallAppWorker).to receive(:perform_async)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
- allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
create(:clusters_applications_helm, :installed, cluster: cluster)
- create(:clusters_applications_ingress, :installed, external_ip: '127.0.0.1', cluster: cluster)
page.within('.js-cluster-application-row-elastic_stack') do
click_button 'Install'
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index e9751aa2e72..0cafdb4e982 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -76,7 +76,7 @@ describe 'Cycle Analytics', :js do
click_stage('Staging')
expect_build_to_be_present
- click_stage('Production')
+ click_stage('Total')
expect_issue_to_be_present
end
diff --git a/spec/features/dashboard/instance_statistics_spec.rb b/spec/features/dashboard/instance_statistics_spec.rb
index 21ee2796bd8..feb568d8ef4 100644
--- a/spec/features/dashboard/instance_statistics_spec.rb
+++ b/spec/features/dashboard/instance_statistics_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe 'Showing instance statistics' do
+describe 'Showing analytics' do
before do
sign_in user if user
end
@@ -13,10 +13,10 @@ describe 'Showing instance statistics' do
context 'for unauthenticated users' do
let(:user) { nil }
- it 'does not show the instance statistics link' do
+ it 'does not show the Analytics link' do
subject
- expect(page).not_to have_link('Instance Statistics')
+ expect(page).not_to have_link('Analytics')
end
end
@@ -28,10 +28,10 @@ describe 'Showing instance statistics' do
stub_application_setting(instance_statistics_visibility_private: false)
end
- it 'shows the instance statistics link' do
+ it 'shows the analytics link' do
subject
- expect(page).to have_link('Instance Statistics')
+ expect(page).to have_link('Analytics')
end
end
@@ -40,10 +40,14 @@ describe 'Showing instance statistics' do
stub_application_setting(instance_statistics_visibility_private: true)
end
- it 'shows the instance statistics link' do
+ it 'does not show the analytics link' do
subject
- expect(page).not_to have_link('Instance Statistics')
+ # Skipping this test on EE as there is an EE specifc spec for this functionality
+ # ee/spec/features/dashboards/analytics_spec.rb
+ skip if Gitlab.ee?
+
+ expect(page).not_to have_link('Analytics')
end
end
end
@@ -51,10 +55,10 @@ describe 'Showing instance statistics' do
context 'for admins' do
let(:user) { create(:admin) }
- it 'shows the instance statistics link' do
+ it 'shows the analytics link' do
subject
- expect(page).to have_link('Instance Statistics')
+ expect(page).to have_link('Analytics')
end
end
end
diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb
index 1352e1bd8fc..8e7fd1f500f 100644
--- a/spec/features/dashboard/issues_filter_spec.rb
+++ b/spec/features/dashboard/issues_filter_spec.rb
@@ -28,14 +28,14 @@ describe 'Dashboard Issues filtering', :js do
context 'filtering by milestone' do
it 'shows all issues with no milestone' do
- input_filtered_search("milestone:none")
+ input_filtered_search("milestone=none")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_selector('.issue', count: 1)
end
it 'shows all issues with the selected milestone' do
- input_filtered_search("milestone:%\"#{milestone.title}\"")
+ input_filtered_search("milestone=%\"#{milestone.title}\"")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_selector('.issue', count: 1)
@@ -63,7 +63,7 @@ describe 'Dashboard Issues filtering', :js do
let!(:label_link) { create(:label_link, label: label, target: issue) }
it 'shows all issues with the selected label' do
- input_filtered_search("label:~#{label.title}")
+ input_filtered_search("label=~#{label.title}")
page.within 'ul.content-list' do
expect(page).to have_content issue.title
diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb
index cb055ff8416..a2ead1b5d33 100644
--- a/spec/features/dashboard/issues_spec.rb
+++ b/spec/features/dashboard/issues_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Dashboard Issues' do
it 'shows issues when current user is author', :js do
reset_filters
- input_filtered_search("author:#{current_user.to_reference}")
+ input_filtered_search("author=#{current_user.to_reference}")
expect(page).to have_content(authored_issue.title)
expect(page).to have_content(authored_issue_on_public_project.title)
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index 0c1e1d5910b..bb515cfae82 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -107,7 +107,7 @@ describe 'Dashboard Merge Requests' do
it 'shows authored merge requests', :js do
reset_filters
- input_filtered_search("author:#{current_user.to_reference}")
+ input_filtered_search("author=#{current_user.to_reference}")
expect(page).to have_content(authored_merge_request.title)
expect(page).to have_content(authored_merge_request_from_fork.title)
@@ -120,7 +120,7 @@ describe 'Dashboard Merge Requests' do
it 'shows labeled merge requests', :js do
reset_filters
- input_filtered_search("label:#{label.name}")
+ input_filtered_search("label=#{label.name}")
expect(page).to have_content(labeled_merge_request.title)
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index f10cdf6da1e..73f759f8a54 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -173,6 +173,19 @@ describe 'Dashboard Projects' do
end
end
+ shared_examples 'hidden pipeline status' do
+ it 'does not show the pipeline status' do
+ visit dashboard_projects_path
+
+ page.within('.controls') do
+ expect(page).not_to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit, ref: pipeline.ref)}']")
+ expect(page).not_to have_css('.ci-status-link')
+ expect(page).not_to have_css('.ci-status-icon-success')
+ expect(page).not_to have_link('Pipeline: passed')
+ end
+ end
+ end
+
context 'guest user of project and project has private pipelines' do
let(:guest_user) { create(:user) }
@@ -182,16 +195,15 @@ describe 'Dashboard Projects' do
sign_in(guest_user)
end
- it 'shows that the last pipeline passed' do
- visit dashboard_projects_path
+ it_behaves_like 'hidden pipeline status'
+ end
- page.within('.controls') do
- expect(page).not_to have_xpath("//a[@href='#{pipelines_project_commit_path(project, project.commit, ref: pipeline.ref)}']")
- expect(page).not_to have_css('.ci-status-link')
- expect(page).not_to have_css('.ci-status-icon-success')
- expect(page).not_to have_link('Pipeline: passed')
- end
+ context 'when dashboard_pipeline_status is disabled' do
+ before do
+ stub_feature_flags(dashboard_pipeline_status: false)
end
+
+ it_behaves_like 'hidden pipeline status'
end
end
diff --git a/spec/features/dashboard/snippets_spec.rb b/spec/features/dashboard/snippets_spec.rb
index ff3eb58931d..94dc8601abb 100644
--- a/spec/features/dashboard/snippets_spec.rb
+++ b/spec/features/dashboard/snippets_spec.rb
@@ -91,6 +91,7 @@ describe 'Dashboard snippets' do
context 'as an external user' do
let(:user) { create(:user, :external) }
+
before do
sign_in(user)
visit dashboard_snippets_path
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index b9b233026fd..a3fa87e3242 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -48,7 +48,7 @@ describe 'Group issues page' do
let(:user2) { user_outside_group }
it 'filters by only group users' do
- filtered_search.set('assignee:')
+ filtered_search.set('assignee=')
expect(find('#js-dropdown-assignee .filter-dropdown')).to have_content(user.name)
expect(find('#js-dropdown-assignee .filter-dropdown')).not_to have_content(user2.name)
diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb
new file mode 100644
index 00000000000..55f9418521f
--- /dev/null
+++ b/spec/features/groups/members/manage_groups_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Groups > Members > Manage groups', :js do
+ include Select2Helper
+ include Spec::Support::Helpers::Features::ListRowsHelpers
+
+ let(:user) { create(:user) }
+ let(:shared_with_group) { create(:group) }
+ let(:shared_group) { create(:group) }
+
+ before do
+ shared_group.add_owner(user)
+ sign_in(user)
+ end
+
+ context 'with share groups with groups feature flag' do
+ before do
+ stub_feature_flags(shared_with_group: true)
+ end
+
+ it 'add group to group' do
+ visit group_group_members_path(shared_group)
+
+ add_group(shared_with_group.id, 'Reporter')
+
+ page.within(first_row) do
+ expect(page).to have_content(shared_with_group.name)
+ expect(page).to have_content('Reporter')
+ end
+ end
+
+ it 'remove user from group' do
+ create(:group_group_link, shared_group: shared_group,
+ shared_with_group: shared_with_group, group_access: ::Gitlab::Access::DEVELOPER)
+
+ visit group_group_members_path(shared_group)
+
+ expect(page).to have_content(shared_with_group.name)
+
+ accept_confirm do
+ find(:css, '#existing_shares li', text: shared_with_group.name).find(:css, 'a.btn-remove').click
+ end
+
+ wait_for_requests
+
+ expect(page).not_to have_content(shared_with_group.name)
+ end
+
+ it 'update group to owner level' do
+ create(:group_group_link, shared_group: shared_group,
+ shared_with_group: shared_with_group, group_access: ::Gitlab::Access::DEVELOPER)
+
+ visit group_group_members_path(shared_group)
+
+ page.within(first_row) do
+ click_button('Developer')
+ click_link('Maintainer')
+
+ wait_for_requests
+
+ expect(page).to have_button('Maintainer')
+ end
+ end
+
+ def add_group(id, role)
+ page.click_link 'Invite group'
+ page.within ".invite-group-form" do
+ select2(id, from: "#shared_with_group_id")
+ select(role, from: "shared_group_access")
+ click_button "Invite"
+ end
+ end
+ end
+
+ context 'without share groups with groups feature flag' do
+ before do
+ stub_feature_flags(share_group_with_group: false)
+ end
+
+ it 'does not render invitation form and tabs' do
+ visit group_group_members_path(shared_group)
+
+ expect(page).not_to have_link('Invite member')
+ expect(page).not_to have_link('Invite group')
+ end
+ end
+end
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index cdd16ae9441..e4ba3022d8b 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -113,7 +113,8 @@ describe 'Groups > Members > Manage members' do
visit group_group_members_path(group)
- expect(page).not_to have_button 'Add to group'
+ expect(page).not_to have_selector '.invite-users-form'
+ expect(page).not_to have_selector '.invite-group-form'
page.within(second_row) do
# Can not modify user2 role
@@ -125,11 +126,10 @@ describe 'Groups > Members > Manage members' do
end
def add_user(id, role)
- page.within ".users-group-form" do
+ page.within ".invite-users-form" do
select2(id, from: "#user_ids", multiple: true)
select(role, from: "access_level")
+ click_button "Invite"
end
-
- click_button "Add to group"
end
end
diff --git a/spec/features/groups/members/search_members_spec.rb b/spec/features/groups/members/search_members_spec.rb
index 9c17aac09e8..fda129ce422 100644
--- a/spec/features/groups/members/search_members_spec.rb
+++ b/spec/features/groups/members/search_members_spec.rb
@@ -24,7 +24,7 @@ describe 'Search group member' do
find('.user-search-btn').click
end
- group_members_list = find(".card .content-list")
+ group_members_list = find('[data-qa-selector="members_list"]')
expect(group_members_list).to have_content(member.name)
expect(group_members_list).not_to have_content(user.name)
end
diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb
index 59230d6891a..0038a8e4892 100644
--- a/spec/features/groups/merge_requests_spec.rb
+++ b/spec/features/groups/merge_requests_spec.rb
@@ -52,7 +52,7 @@ describe 'Group merge requests page' do
let(:user2) { user_outside_group }
it 'filters by assignee only group users' do
- filtered_search.set('assignee:')
+ filtered_search.set('assignee=')
expect(find('#js-dropdown-assignee .filter-dropdown')).to have_content(user.name)
expect(find('#js-dropdown-assignee .filter-dropdown')).not_to have_content(user2.name)
diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb
index 89bf69dea7d..36478128dd1 100644
--- a/spec/features/import/manifest_import_spec.rb
+++ b/spec/features/import/manifest_import_spec.rb
@@ -24,17 +24,17 @@ describe 'Import multiple repositories by uploading a manifest file', :js do
expect(page).to have_content('https://android-review.googlesource.com/platform/build/blueprint')
end
- it 'imports successfully imports a project', :sidekiq_might_not_need_inline do
+ it 'imports successfully imports a project', :sidekiq_inline do
visit new_import_manifest_path
attach_file('manifest', Rails.root.join('spec/fixtures/aosp_manifest.xml'))
click_on 'List available repositories'
- page.within(first_row) do
+ page.within(second_row) do
click_on 'Import'
expect(page).to have_content 'Done'
- expect(page).to have_content("#{group.full_path}/build/make")
+ expect(page).to have_content("#{group.full_path}/build/blueprint")
end
end
@@ -47,7 +47,7 @@ describe 'Import multiple repositories by uploading a manifest file', :js do
expect(page).to have_content 'The uploaded file is not a valid XML file.'
end
- def first_row
- page.all('table.import-jobs tbody tr')[0]
+ def second_row
+ page.all('table.import-jobs tbody tr')[1]
end
end
diff --git a/spec/features/instance_statistics/cohorts_spec.rb b/spec/features/instance_statistics/cohorts_spec.rb
index 3940e8fa389..0bb2e4b997d 100644
--- a/spec/features/instance_statistics/cohorts_spec.rb
+++ b/spec/features/instance_statistics/cohorts_spec.rb
@@ -10,7 +10,7 @@ describe 'Cohorts page' do
end
it 'See users count per month' do
- 2.times { create(:user) }
+ create_list(:user, 2)
visit instance_statistics_cohorts_path
diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb
index 30c516459c5..bcc05d313ad 100644
--- a/spec/features/issuables/issuable_list_spec.rb
+++ b/spec/features/issuables/issuable_list_spec.rb
@@ -83,9 +83,7 @@ describe 'issuable list' do
create(:merge_request, title: FFaker::Lorem.sentence, source_project: project, source_branch: source_branch, head_pipeline: pipeline)
end
- 2.times do
- create(:note_on_issue, noteable: issuable, project: project)
- end
+ create_list(:note_on_issue, 2, noteable: issuable, project: project)
create(:award_emoji, :downvote, awardable: issuable)
create(:award_emoji, :upvote, awardable: issuable)
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index e1177bedd2d..8aa29cddd5f 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -7,24 +7,11 @@ describe 'Dropdown assignee', :js do
let!(:project) { create(:project) }
let!(:user) { create(:user, name: 'administrator', username: 'root') }
- let!(:user_john) { create(:user, name: 'John', username: 'th0mas') }
- let!(:user_jacob) { create(:user, name: 'Jacob', username: 'otter32') }
- let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_assignee) { '#js-dropdown-assignee' }
let(:filter_dropdown) { find("#{js_dropdown_assignee} .filter-dropdown") }
- def dropdown_assignee_size
- filter_dropdown.all('.filter-dropdown-item').size
- end
-
- def click_assignee(text)
- find('#js-dropdown-assignee .filter-dropdown .filter-dropdown-item', text: text).click
- end
-
before do
project.add_maintainer(user)
- project.add_maintainer(user_john)
- project.add_maintainer(user_jacob)
sign_in(user)
create(:issue, project: project)
@@ -32,153 +19,23 @@ describe 'Dropdown assignee', :js do
end
describe 'behavior' do
- it 'opens when the search bar has assignee:' do
- input_filtered_search('assignee:', submit: false, extra_space: false)
-
- expect(page).to have_css(js_dropdown_assignee, visible: true)
- end
-
- it 'closes when the search bar is unfocused' do
- find('body').click
-
- expect(page).to have_css(js_dropdown_assignee, visible: false)
- end
-
- it 'shows loading indicator when opened' do
- slow_requests do
- # We aren't using `input_filtered_search` because we want to see the loading indicator
- filtered_search.set('assignee:')
-
- expect(page).to have_css('#js-dropdown-assignee .filter-dropdown-loading', visible: true)
- end
- end
-
- it 'hides loading indicator when loaded' do
- input_filtered_search('assignee:', submit: false, extra_space: false)
-
- expect(find(js_dropdown_assignee)).not_to have_css('.filter-dropdown-loading')
- end
-
it 'loads all the assignees when opened' do
- input_filtered_search('assignee:', submit: false, extra_space: false)
+ input_filtered_search('assignee=', submit: false, extra_space: false)
- expect(dropdown_assignee_size).to eq(4)
+ expect_filtered_search_dropdown_results(filter_dropdown, 2)
end
it 'shows current user at top of dropdown' do
- input_filtered_search('assignee:', submit: false, extra_space: false)
+ input_filtered_search('assignee=', submit: false, extra_space: false)
expect(filter_dropdown.first('.filter-dropdown-item')).to have_content(user.name)
end
end
- describe 'filtering' do
- before do
- input_filtered_search('assignee:', submit: false, extra_space: false)
-
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_john.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name)
- end
-
- it 'filters by name' do
- input_filtered_search('jac', submit: false, extra_space: false)
-
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user.name)
- end
-
- it 'filters by case insensitive name' do
- input_filtered_search('JAC', submit: false, extra_space: false)
-
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user.name)
- end
-
- it 'filters by username with symbol' do
- input_filtered_search('@ott', submit: false, extra_space: false)
-
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user_john.name)
- end
-
- it 'filters by case insensitive username with symbol' do
- input_filtered_search('@OTT', submit: false, extra_space: false)
-
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user_john.name)
- end
-
- it 'filters by username without symbol' do
- input_filtered_search('ott', submit: false, extra_space: false)
-
- wait_for_requests
-
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user_john.name)
- end
-
- it 'filters by case insensitive username without symbol' do
- input_filtered_search('OTT', submit: false, extra_space: false)
-
- wait_for_requests
-
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name)
- expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user_john.name)
- end
- end
-
- describe 'selecting from dropdown' do
- before do
- input_filtered_search('assignee:', submit: false, extra_space: false)
- end
-
- it 'fills in the assignee username when the assignee has not been filtered' do
- click_assignee(user_jacob.name)
-
- wait_for_requests
-
- expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([assignee_token(user_jacob.name)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the assignee username when the assignee has been filtered' do
- input_filtered_search('roo', submit: false, extra_space: false)
- click_assignee(user.name)
-
- wait_for_requests
-
- expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([assignee_token(user.name)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `None`' do
- find('#js-dropdown-assignee .filter-dropdown-item', text: 'None').click
-
- expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([assignee_token('None')])
- expect_filtered_search_input_empty
- end
-
- it 'selects `Any`' do
- find('#js-dropdown-assignee .filter-dropdown-item', text: 'Any').click
-
- expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([assignee_token('Any')])
- expect_filtered_search_input_empty
- end
- end
-
describe 'selecting from dropdown without Ajax call' do
before do
Gitlab::Testing::RequestBlockerMiddleware.block_requests!
- input_filtered_search('assignee:', submit: false, extra_space: false)
+ input_filtered_search('assignee=', submit: false, extra_space: false)
end
after do
@@ -186,59 +43,11 @@ describe 'Dropdown assignee', :js do
end
it 'selects current user' do
- find('#js-dropdown-assignee .filter-dropdown-item', text: user.username).click
+ find("#{js_dropdown_assignee} .filter-dropdown-item", text: user.username).click
expect(page).to have_css(js_dropdown_assignee, visible: false)
expect_tokens([assignee_token(user.username)])
expect_filtered_search_input_empty
end
end
-
- describe 'input has existing content' do
- it 'opens assignee dropdown with existing search term' do
- input_filtered_search('searchTerm assignee:', submit: false, extra_space: false)
-
- expect(page).to have_css(js_dropdown_assignee, visible: true)
- end
-
- it 'opens assignee dropdown with existing author' do
- input_filtered_search('author:@user assignee:', submit: false, extra_space: false)
-
- expect(page).to have_css(js_dropdown_assignee, visible: true)
- end
-
- it 'opens assignee dropdown with existing label' do
- input_filtered_search('label:~bug assignee:', submit: false, extra_space: false)
-
- expect(page).to have_css(js_dropdown_assignee, visible: true)
- end
-
- it 'opens assignee dropdown with existing milestone' do
- input_filtered_search('milestone:%v1.0 assignee:', submit: false, extra_space: false)
-
- expect(page).to have_css(js_dropdown_assignee, visible: true)
- end
-
- it 'opens assignee dropdown with existing my-reaction' do
- input_filtered_search('my-reaction:star assignee:', submit: false, extra_space: false)
-
- expect(page).to have_css(js_dropdown_assignee, visible: true)
- end
- end
-
- describe 'caching requests' do
- it 'caches requests after the first load' do
- input_filtered_search('assignee:', submit: false, extra_space: false)
- initial_size = dropdown_assignee_size
-
- expect(initial_size).to be > 0
-
- new_user = create(:user)
- project.add_maintainer(new_user)
- find('.filtered-search-box .clear-search').click
- input_filtered_search('assignee:', submit: false, extra_space: false)
-
- expect(dropdown_assignee_size).to eq(initial_size)
- end
- end
end
diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb
index bd22eb1056b..c95bd7071b3 100644
--- a/spec/features/issues/filtered_search/dropdown_author_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb
@@ -7,32 +7,11 @@ describe 'Dropdown author', :js do
let!(:project) { create(:project) }
let!(:user) { create(:user, name: 'administrator', username: 'root') }
- let!(:user_john) { create(:user, name: 'John', username: 'th0mas') }
- let!(:user_jacob) { create(:user, name: 'Jacob', username: 'ooter32') }
- let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_author) { '#js-dropdown-author' }
-
- def send_keys_to_filtered_search(input)
- input.split("").each do |i|
- filtered_search.send_keys(i)
- end
-
- sleep 0.5
- wait_for_requests
- end
-
- def dropdown_author_size
- page.all('#js-dropdown-author .filter-dropdown .filter-dropdown-item').size
- end
-
- def click_author(text)
- find('#js-dropdown-author .filter-dropdown .filter-dropdown-item', text: text).click
- end
+ let(:filter_dropdown) { find("#{js_dropdown_author} .filter-dropdown") }
before do
project.add_maintainer(user)
- project.add_maintainer(user_john)
- project.add_maintainer(user_jacob)
sign_in(user)
create(:issue, project: project)
@@ -40,113 +19,23 @@ describe 'Dropdown author', :js do
end
describe 'behavior' do
- it 'opens when the search bar has author:' do
- filtered_search.set('author:')
-
- expect(page).to have_css(js_dropdown_author, visible: true)
- end
-
- it 'closes when the search bar is unfocused' do
- find('body').click
-
- expect(page).to have_css(js_dropdown_author, visible: false)
- end
-
- it 'shows loading indicator when opened' do
- slow_requests do
- filtered_search.set('author:')
-
- expect(page).to have_css('#js-dropdown-author .filter-dropdown-loading', visible: true)
- end
- end
-
- it 'hides loading indicator when loaded' do
- send_keys_to_filtered_search('author:')
-
- expect(page).not_to have_css('#js-dropdown-author .filter-dropdown-loading')
- end
-
it 'loads all the authors when opened' do
- send_keys_to_filtered_search('author:')
+ input_filtered_search('author=', submit: false, extra_space: false)
- expect(dropdown_author_size).to eq(4)
+ expect_filtered_search_dropdown_results(filter_dropdown, 2)
end
it 'shows current user at top of dropdown' do
- send_keys_to_filtered_search('author:')
+ input_filtered_search('author=', submit: false, extra_space: false)
- expect(first('#js-dropdown-author li')).to have_content(user.name)
- end
- end
-
- describe 'filtering' do
- before do
- filtered_search.set('author')
- send_keys_to_filtered_search(':')
- end
-
- it 'filters by name' do
- send_keys_to_filtered_search('jac')
-
- expect(dropdown_author_size).to eq(1)
- end
-
- it 'filters by case insensitive name' do
- send_keys_to_filtered_search('Jac')
-
- expect(dropdown_author_size).to eq(1)
- end
-
- it 'filters by username with symbol' do
- send_keys_to_filtered_search('@oot')
-
- expect(dropdown_author_size).to eq(2)
- end
-
- it 'filters by username without symbol' do
- send_keys_to_filtered_search('oot')
-
- expect(dropdown_author_size).to eq(2)
- end
-
- it 'filters by case insensitive username without symbol' do
- send_keys_to_filtered_search('OOT')
-
- expect(dropdown_author_size).to eq(2)
- end
- end
-
- describe 'selecting from dropdown' do
- before do
- filtered_search.set('author')
- send_keys_to_filtered_search(':')
- end
-
- it 'fills in the author username when the author has not been filtered' do
- click_author(user_jacob.name)
-
- wait_for_requests
-
- expect(page).to have_css(js_dropdown_author, visible: false)
- expect_tokens([author_token(user_jacob.name)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the author username when the author has been filtered' do
- click_author(user.name)
-
- wait_for_requests
-
- expect(page).to have_css(js_dropdown_author, visible: false)
- expect_tokens([author_token(user.name)])
- expect_filtered_search_input_empty
+ expect(filter_dropdown.first('.filter-dropdown-item')).to have_content(user.name)
end
end
describe 'selecting from dropdown without Ajax call' do
before do
Gitlab::Testing::RequestBlockerMiddleware.block_requests!
- filtered_search.set('author:')
+ input_filtered_search('author=', submit: false, extra_space: false)
end
after do
@@ -154,55 +43,11 @@ describe 'Dropdown author', :js do
end
it 'selects current user' do
- find('#js-dropdown-author .filter-dropdown-item', text: user.username).click
+ find("#{js_dropdown_author} .filter-dropdown-item", text: user.username).click
expect(page).to have_css(js_dropdown_author, visible: false)
expect_tokens([author_token(user.username)])
expect_filtered_search_input_empty
end
end
-
- describe 'input has existing content' do
- it 'opens author dropdown with existing search term' do
- filtered_search.set('searchTerm author:')
-
- expect(page).to have_css(js_dropdown_author, visible: true)
- end
-
- it 'opens author dropdown with existing assignee' do
- filtered_search.set('assignee:@user author:')
-
- expect(page).to have_css(js_dropdown_author, visible: true)
- end
-
- it 'opens author dropdown with existing label' do
- filtered_search.set('label:~bug author:')
-
- expect(page).to have_css(js_dropdown_author, visible: true)
- end
-
- it 'opens author dropdown with existing milestone' do
- filtered_search.set('milestone:%v1.0 author:')
-
- expect(page).to have_css(js_dropdown_author, visible: true)
- end
- end
-
- describe 'caching requests' do
- it 'caches requests after the first load' do
- filtered_search.set('author')
- send_keys_to_filtered_search(':')
- initial_size = dropdown_author_size
-
- expect(initial_size).to be > 0
-
- new_user = create(:user)
- project.add_maintainer(new_user)
- find('.filtered-search-box .clear-search').click
- filtered_search.set('author')
- send_keys_to_filtered_search(':')
-
- expect(dropdown_author_size).to eq(initial_size)
- end
- end
end
diff --git a/spec/features/issues/filtered_search/dropdown_base_spec.rb b/spec/features/issues/filtered_search/dropdown_base_spec.rb
new file mode 100644
index 00000000000..2a800f054a0
--- /dev/null
+++ b/spec/features/issues/filtered_search/dropdown_base_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Dropdown base', :js do
+ include FilteredSearchHelpers
+
+ let!(:project) { create(:project) }
+ let!(:user) { create(:user, name: 'administrator', username: 'root') }
+ let(:filtered_search) { find('.filtered-search') }
+ let(:js_dropdown_assignee) { '#js-dropdown-assignee' }
+ let(:filter_dropdown) { find("#{js_dropdown_assignee} .filter-dropdown") }
+
+ def dropdown_assignee_size
+ filter_dropdown.all('.filter-dropdown-item').size
+ end
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ create(:issue, project: project)
+
+ visit project_issues_path(project)
+ end
+
+ describe 'behavior' do
+ it 'shows loading indicator when opened' do
+ slow_requests do
+ # We aren't using `input_filtered_search` because we want to see the loading indicator
+ filtered_search.set('assignee=')
+
+ expect(page).to have_css("#{js_dropdown_assignee} .filter-dropdown-loading", visible: true)
+ end
+ end
+
+ it 'hides loading indicator when loaded' do
+ input_filtered_search('assignee=', submit: false, extra_space: false)
+
+ expect(find(js_dropdown_assignee)).not_to have_css('.filter-dropdown-loading')
+ end
+ end
+
+ describe 'caching requests' do
+ it 'caches requests after the first load' do
+ input_filtered_search('assignee=', submit: false, extra_space: false)
+ initial_size = dropdown_assignee_size
+
+ expect(initial_size).to be > 0
+
+ new_user = create(:user)
+ project.add_maintainer(new_user)
+ find('.filtered-search-box .clear-search').click
+ input_filtered_search('assignee=', submit: false, extra_space: false)
+
+ expect(dropdown_assignee_size).to eq(initial_size)
+ end
+ end
+end
diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
index 7ec3d215fb1..4c11f83318b 100644
--- a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
@@ -11,30 +11,13 @@ describe 'Dropdown emoji', :js do
let!(:award_emoji_star) { create(:award_emoji, name: 'star', user: user, awardable: issue) }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_emoji) { '#js-dropdown-my-reaction' }
-
- def send_keys_to_filtered_search(input)
- input.split("").each do |i|
- filtered_search.send_keys(i)
- end
-
- sleep 0.5
- wait_for_requests
- end
-
- def dropdown_emoji_size
- all('gl-emoji[data-name]').size
- end
-
- def click_emoji(text)
- find('#js-dropdown-my-reaction .filter-dropdown .filter-dropdown-item', text: text).click
- end
+ let(:filter_dropdown) { find("#{js_dropdown_emoji} .filter-dropdown") }
before do
project.add_maintainer(user)
create_list(:award_emoji, 2, user: user, name: 'thumbsup')
create_list(:award_emoji, 1, user: user, name: 'thumbsdown')
create_list(:award_emoji, 3, user: user, name: 'star')
- create_list(:award_emoji, 1, user: user, name: 'tea')
end
context 'when user not logged in' do
@@ -43,8 +26,8 @@ describe 'Dropdown emoji', :js do
end
describe 'behavior' do
- it 'does not open when the search bar has my-reaction:' do
- filtered_search.set('my-reaction:')
+ it 'does not open when the search bar has my-reaction=' do
+ filtered_search.set('my-reaction=')
expect(page).not_to have_css(js_dropdown_emoji)
end
@@ -59,143 +42,22 @@ describe 'Dropdown emoji', :js do
end
describe 'behavior' do
- it 'opens when the search bar has my-reaction:' do
- filtered_search.set('my-reaction:')
+ it 'opens when the search bar has my-reaction=' do
+ filtered_search.set('my-reaction=')
expect(page).to have_css(js_dropdown_emoji, visible: true)
end
- it 'closes when the search bar is unfocused' do
- find('body').click
-
- expect(page).to have_css(js_dropdown_emoji, visible: false)
- end
-
- it 'shows loading indicator when opened' do
- slow_requests do
- filtered_search.set('my-reaction:')
-
- expect(page).to have_css('#js-dropdown-my-reaction .filter-dropdown-loading', visible: true)
- end
- end
-
- it 'hides loading indicator when loaded' do
- send_keys_to_filtered_search('my-reaction:')
-
- expect(page).not_to have_css('#js-dropdown-my-reaction .filter-dropdown-loading')
- end
-
it 'loads all the emojis when opened' do
- send_keys_to_filtered_search('my-reaction:')
+ input_filtered_search('my-reaction=', submit: false, extra_space: false)
- expect(dropdown_emoji_size).to eq(4)
+ expect_filtered_search_dropdown_results(filter_dropdown, 3)
end
it 'shows the most populated emoji at top of dropdown' do
- send_keys_to_filtered_search('my-reaction:')
-
- expect(first('#js-dropdown-my-reaction .filter-dropdown li')).to have_content(award_emoji_star.name)
- end
- end
-
- describe 'filtering' do
- before do
- filtered_search.set('my-reaction')
- send_keys_to_filtered_search(':')
- end
-
- it 'filters by name' do
- send_keys_to_filtered_search('up')
-
- expect(dropdown_emoji_size).to eq(1)
- end
-
- it 'filters by case insensitive name' do
- send_keys_to_filtered_search('Up')
-
- expect(dropdown_emoji_size).to eq(1)
- end
- end
-
- describe 'selecting from dropdown' do
- before do
- filtered_search.set('my-reaction')
- send_keys_to_filtered_search(':')
- end
-
- it 'selects `None`' do
- find('#js-dropdown-my-reaction .filter-dropdown-item', text: 'None').click
-
- expect(page).to have_css(js_dropdown_emoji, visible: false)
- expect_tokens([reaction_token('None', false)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `Any`' do
- find('#js-dropdown-my-reaction .filter-dropdown-item', text: 'Any').click
-
- expect(page).to have_css(js_dropdown_emoji, visible: false)
- expect_tokens([reaction_token('Any', false)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the my-reaction name' do
- click_emoji('thumbsup')
-
- wait_for_requests
-
- expect(page).to have_css(js_dropdown_emoji, visible: false)
- expect_tokens([reaction_token('thumbsup')])
- expect_filtered_search_input_empty
- end
- end
-
- describe 'input has existing content' do
- it 'opens my-reaction dropdown with existing search term' do
- filtered_search.set('searchTerm my-reaction:')
-
- expect(page).to have_css(js_dropdown_emoji, visible: true)
- end
-
- it 'opens my-reaction dropdown with existing assignee' do
- filtered_search.set('assignee:@user my-reaction:')
-
- expect(page).to have_css(js_dropdown_emoji, visible: true)
- end
-
- it 'opens my-reaction dropdown with existing label' do
- filtered_search.set('label:~bug my-reaction:')
-
- expect(page).to have_css(js_dropdown_emoji, visible: true)
- end
-
- it 'opens my-reaction dropdown with existing milestone' do
- filtered_search.set('milestone:%v1.0 my-reaction:')
-
- expect(page).to have_css(js_dropdown_emoji, visible: true)
- end
-
- it 'opens my-reaction dropdown with existing my-reaction' do
- filtered_search.set('my-reaction:star my-reaction:')
-
- expect(page).to have_css(js_dropdown_emoji, visible: true)
- end
- end
-
- describe 'caching requests' do
- it 'caches requests after the first load' do
- filtered_search.set('my-reaction')
- send_keys_to_filtered_search(':')
- initial_size = dropdown_emoji_size
-
- expect(initial_size).to be > 0
-
- create_list(:award_emoji, 1, user: user, name: 'smile')
- find('.filtered-search-box .clear-search').click
- filtered_search.set('my-reaction')
- send_keys_to_filtered_search(':')
+ input_filtered_search('my-reaction=', submit: false, extra_space: false)
- expect(dropdown_emoji_size).to eq(initial_size)
+ expect(first("#{js_dropdown_emoji} .filter-dropdown li")).to have_content(award_emoji_star.name)
end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
index bb57d69148b..10b092c6957 100644
--- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
@@ -9,11 +9,16 @@ describe 'Dropdown hint', :js do
let!(:user) { create(:user) }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_hint) { '#js-dropdown-hint' }
+ let(:js_dropdown_operator) { '#js-dropdown-operator' }
def click_hint(text)
find('#js-dropdown-hint .filter-dropdown .filter-dropdown-item', text: text).click
end
+ def click_operator(op)
+ find("#js-dropdown-operator .filter-dropdown .filter-dropdown-item[data-value='#{op}']").click
+ end
+
before do
project.add_maintainer(user)
create(:issue, project: project)
@@ -27,7 +32,7 @@ describe 'Dropdown hint', :js do
it 'does not exist my-reaction dropdown item' do
expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).not_to have_content('my-reaction')
+ expect(page).not_to have_content('My-reaction')
end
end
@@ -46,9 +51,7 @@ describe 'Dropdown hint', :js do
it 'opens when the search bar is first focused' do
expect(page).to have_css(js_dropdown_hint, visible: true)
- end
- it 'closes when the search bar is unfocused' do
find('body').click
expect(page).to have_css(js_dropdown_hint, visible: false)
@@ -56,15 +59,6 @@ describe 'Dropdown hint', :js do
end
describe 'filtering' do
- it 'does not filter `Press Enter or click to search`' do
- filtered_search.set('randomtext')
-
- hint_dropdown = find(js_dropdown_hint)
-
- expect(hint_dropdown).to have_content('Press Enter or click to search')
- expect(hint_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 0)
- end
-
it 'filters with text' do
filtered_search.set('a')
@@ -77,189 +71,32 @@ describe 'Dropdown hint', :js do
filtered_search.click
end
- it 'opens the author dropdown when you click on author' do
- click_hint('author')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'Author' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the assignee dropdown when you click on assignee' do
- click_hint('assignee')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'Assignee' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the milestone dropdown when you click on milestone' do
- click_hint('milestone')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'Milestone' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the release dropdown when you click on release' do
- click_hint('release')
+ it 'opens the token dropdown when you click on it' do
+ click_hint('Author')
expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-release', visible: true)
- expect_tokens([{ name: 'Release' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the label dropdown when you click on label' do
- click_hint('label')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'Label' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the emoji dropdown when you click on my-reaction' do
- click_hint('my-reaction')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
- expect_tokens([{ name: 'My-reaction' }])
- expect_filtered_search_input_empty
- end
+ expect(page).to have_css(js_dropdown_operator, visible: true)
- it 'opens the yes-no dropdown when you click on confidential' do
- click_hint('confidential')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-confidential', visible: true)
- expect_tokens([{ name: 'Confidential' }])
- expect_filtered_search_input_empty
- end
- end
-
- describe 'selecting from dropdown with some input' do
- it 'opens the author dropdown when you click on author' do
- filtered_search.set('auth')
- click_hint('author')
+ click_operator('=')
expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css(js_dropdown_operator, visible: false)
expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'Author' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the assignee dropdown when you click on assignee' do
- filtered_search.set('assign')
- click_hint('assignee')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'Assignee' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the milestone dropdown when you click on milestone' do
- filtered_search.set('mile')
- click_hint('milestone')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'Milestone' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the label dropdown when you click on label' do
- filtered_search.set('lab')
- click_hint('label')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'Label' }])
- expect_filtered_search_input_empty
- end
-
- it 'opens the emoji dropdown when you click on my-reaction' do
- filtered_search.set('my')
- click_hint('my-reaction')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
- expect_tokens([{ name: 'My-reaction' }])
+ expect_tokens([{ name: 'Author', operator: '=' }])
expect_filtered_search_input_empty
end
end
describe 'reselecting from dropdown' do
- it 'reuses existing author text' do
- filtered_search.send_keys('author:')
+ it 'reuses existing token text' do
+ filtered_search.send_keys('author')
filtered_search.send_keys(:backspace)
filtered_search.send_keys(:backspace)
- click_hint('author')
+ click_hint('Author')
expect_tokens([{ name: 'Author' }])
expect_filtered_search_input_empty
end
-
- it 'reuses existing assignee text' do
- filtered_search.send_keys('assignee:')
- filtered_search.send_keys(:backspace)
- filtered_search.send_keys(:backspace)
- click_hint('assignee')
-
- expect_tokens([{ name: 'Assignee' }])
- expect_filtered_search_input_empty
- end
-
- it 'reuses existing milestone text' do
- filtered_search.send_keys('milestone:')
- filtered_search.send_keys(:backspace)
- filtered_search.send_keys(:backspace)
- click_hint('milestone')
-
- expect_tokens([{ name: 'Milestone' }])
- expect_filtered_search_input_empty
- end
-
- it 'reuses existing label text' do
- filtered_search.send_keys('label:')
- filtered_search.send_keys(:backspace)
- filtered_search.send_keys(:backspace)
- click_hint('label')
-
- expect_tokens([{ name: 'Label' }])
- expect_filtered_search_input_empty
- end
-
- it 'reuses existing emoji text' do
- filtered_search.send_keys('my-reaction:')
- filtered_search.send_keys(:backspace)
- filtered_search.send_keys(:backspace)
- click_hint('my-reaction')
-
- expect_tokens([{ name: 'My-reaction' }])
- expect_filtered_search_input_empty
- end
- end
- end
-
- context 'merge request page' do
- before do
- sign_in(user)
- visit project_merge_requests_path(project)
- filtered_search.click
- end
-
- it 'shows the WIP menu item and opens the WIP options dropdown' do
- click_hint('wip')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-wip', visible: true)
- expect_tokens([{ name: 'WIP' }])
- expect_filtered_search_input_empty
end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index f7f9f0de4db..1e90efc8d56 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -8,31 +8,7 @@ describe 'Dropdown label', :js do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:filtered_search) { find('.filtered-search') }
- let(:js_dropdown_label) { '#js-dropdown-label' }
- let(:filter_dropdown) { find("#{js_dropdown_label} .filter-dropdown") }
-
- shared_context 'with labels' do
- let!(:bug_label) { create(:label, project: project, title: 'bug-label') }
- let!(:uppercase_label) { create(:label, project: project, title: 'BUG-LABEL') }
- let!(:two_words_label) { create(:label, project: project, title: 'High Priority') }
- let!(:wont_fix_label) { create(:label, project: project, title: 'Won"t Fix') }
- let!(:wont_fix_single_label) { create(:label, project: project, title: 'Won\'t Fix') }
- let!(:special_label) { create(:label, project: project, title: '!@#$%^+&*()') }
- let!(:long_label) { create(:label, project: project, title: 'this is a very long title this is a very long title this is a very long title this is a very long title this is a very long title') }
- end
-
- def search_for_label(label)
- init_label_search
- filtered_search.send_keys(label)
- end
-
- def click_label(text)
- filter_dropdown.find('.filter-dropdown-item', text: text).click
- end
-
- def clear_search_field
- find('.filtered-search-box .clear-search').click
- end
+ let(:filter_dropdown) { find('#js-dropdown-label .filter-dropdown') }
before do
project.add_maintainer(user)
@@ -42,267 +18,12 @@ describe 'Dropdown label', :js do
visit project_issues_path(project)
end
- describe 'keyboard navigation' do
- it 'selects label' do
- bug_label = create(:label, project: project, title: 'bug-label')
- init_label_search
-
- # navigate to the bug_label option and selects it
- filtered_search.native.send_keys(:down, :down, :down, :enter)
-
- expect_tokens([label_token(bug_label.title)])
- expect_filtered_search_input_empty
- end
- end
-
describe 'behavior' do
- it 'opens when the search bar has label:' do
- filtered_search.set('label:')
-
- expect(page).to have_css(js_dropdown_label)
- end
-
- it 'closes when the search bar is unfocused' do
- find('body').click
-
- expect(page).not_to have_css(js_dropdown_label)
- end
-
- it 'shows loading indicator when opened and hides it when loaded' do
- slow_requests do
- filtered_search.set('label:')
-
- expect(page).to have_css("#{js_dropdown_label} .filter-dropdown-loading", visible: true)
- end
- expect(find(js_dropdown_label)).not_to have_css('.filter-dropdown-loading')
- end
-
it 'loads all the labels when opened' do
- bug_label = create(:label, project: project, title: 'bug-label')
- filtered_search.set('label:')
-
- expect(filter_dropdown).to have_content(bug_label.title)
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
- end
- end
-
- describe 'filtering' do
- include_context 'with labels'
-
- before do
- init_label_search
- end
-
- it 'filters by case-insensitive name with or without symbol' do
- filtered_search.send_keys('b')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible
- expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible
-
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 2)
-
- clear_search_field
- init_label_search
-
- filtered_search.send_keys('~bu')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible
- expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 2)
- end
-
- it 'filters by multiple words with or without symbol' do
- filtered_search.send_keys('Hig')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
-
- clear_search_field
- init_label_search
-
- filtered_search.send_keys('~Hig')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
- end
-
- it 'filters by multiple words containing single quotes with or without symbol' do
- filtered_search.send_keys('won\'t')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
-
- clear_search_field
- init_label_search
-
- filtered_search.send_keys('~won\'t')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
- end
-
- it 'filters by multiple words containing double quotes with or without symbol' do
- filtered_search.send_keys('won"t')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
-
- clear_search_field
- init_label_search
-
- filtered_search.send_keys('~won"t')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
- end
-
- it 'filters by special characters with or without symbol' do
- filtered_search.send_keys('^+')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
-
- clear_search_field
- init_label_search
-
- filtered_search.send_keys('~^+')
-
- expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
- end
- end
-
- describe 'selecting from dropdown' do
- include_context 'with labels'
-
- before do
- init_label_search
- end
-
- it 'fills in the label name when the label has not been filled' do
- click_label(bug_label.title)
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token(bug_label.title)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the label name when the label is partially filled' do
- filtered_search.send_keys('bu')
- click_label(bug_label.title)
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token(bug_label.title)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the label name that contains multiple words' do
- click_label(two_words_label.title)
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token("\"#{two_words_label.title}\"")])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the label name that contains multiple words and is very long' do
- click_label(long_label.title)
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token("\"#{long_label.title}\"")])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the label name that contains double quotes' do
- click_label(wont_fix_label.title)
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token("'#{wont_fix_label.title}'")])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the label name with the correct capitalization' do
- click_label(uppercase_label.title)
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token(uppercase_label.title)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the label name with special characters' do
- click_label(special_label.title)
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token(special_label.title)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `no label`' do
- find("#{js_dropdown_label} .filter-dropdown-item", text: 'None').click
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token('None', false)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `any label`' do
- find("#{js_dropdown_label} .filter-dropdown-item", text: 'Any').click
-
- expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([label_token('Any', false)])
- expect_filtered_search_input_empty
- end
- end
-
- describe 'input has existing content' do
- it 'opens label dropdown with existing search term' do
- filtered_search.set('searchTerm label:')
-
- expect(page).to have_css(js_dropdown_label)
- end
-
- it 'opens label dropdown with existing author' do
- filtered_search.set('author:@person label:')
-
- expect(page).to have_css(js_dropdown_label)
- end
-
- it 'opens label dropdown with existing assignee' do
- filtered_search.set('assignee:@person label:')
-
- expect(page).to have_css(js_dropdown_label)
- end
-
- it 'opens label dropdown with existing label' do
- filtered_search.set('label:~urgent label:')
-
- expect(page).to have_css(js_dropdown_label)
- end
-
- it 'opens label dropdown with existing milestone' do
- filtered_search.set('milestone:%v2.0 label:')
-
- expect(page).to have_css(js_dropdown_label)
- end
-
- it 'opens label dropdown with existing my-reaction' do
- filtered_search.set('my-reaction:star label:')
-
- expect(page).to have_css(js_dropdown_label)
- end
- end
-
- describe 'caching requests' do
- it 'caches requests after the first load' do
create(:label, project: project, title: 'bug-label')
- init_label_search
-
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
-
- create(:label, project: project)
- clear_search_field
- init_label_search
+ filtered_search.set('label=')
- expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
+ expect_filtered_search_dropdown_results(filter_dropdown, 1)
end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index 5272a970a60..1f62a8e0c8d 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -9,26 +9,9 @@ describe 'Dropdown milestone', :js do
let!(:user) { create(:user) }
let!(:milestone) { create(:milestone, title: 'v1.0', project: project) }
let!(:uppercase_milestone) { create(:milestone, title: 'CAP_MILESTONE', project: project) }
- let!(:two_words_milestone) { create(:milestone, title: 'Future Plan', project: project) }
- let!(:wont_fix_milestone) { create(:milestone, title: 'Won"t Fix', project: project) }
- let!(:special_milestone) { create(:milestone, title: '!@#$%^&*(+)', project: project) }
- let!(:long_milestone) { create(:milestone, title: 'this is a very long title this is a very long title this is a very long title this is a very long title this is a very long title', project: project) }
let(:filtered_search) { find('.filtered-search') }
- let(:js_dropdown_milestone) { '#js-dropdown-milestone' }
- let(:filter_dropdown) { find("#{js_dropdown_milestone} .filter-dropdown") }
-
- def dropdown_milestone_size
- filter_dropdown.all('.filter-dropdown-item').size
- end
-
- def click_milestone(text)
- find('#js-dropdown-milestone .filter-dropdown .filter-dropdown-item', text: text).click
- end
-
- def click_static_milestone(text)
- find('#js-dropdown-milestone .filter-dropdown-item', text: text).click
- end
+ let(:filter_dropdown) { find('#js-dropdown-milestone .filter-dropdown') }
before do
project.add_maintainer(user)
@@ -39,240 +22,12 @@ describe 'Dropdown milestone', :js do
end
describe 'behavior' do
- context 'filters by "milestone:"' do
- before do
- filtered_search.set('milestone:')
- end
-
- it 'opens when the search bar has milestone:' do
- expect(page).to have_css(js_dropdown_milestone, visible: true)
- end
-
- it 'closes when the search bar is unfocused' do
- find('body').click
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- end
-
- it 'hides loading indicator when loaded' do
- expect(find(js_dropdown_milestone)).not_to have_css('.filter-dropdown-loading')
- end
-
- it 'loads all the milestones when opened' do
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 6)
- end
- end
-
- it 'shows loading indicator when opened' do
- slow_requests do
- filtered_search.set('milestone:')
-
- expect(page).to have_css('#js-dropdown-milestone .filter-dropdown-loading', visible: true)
- end
- end
- end
-
- describe 'filtering' do
before do
- filtered_search.set('milestone:')
-
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(uppercase_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(two_words_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(wont_fix_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(special_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(long_milestone.title)
- end
-
- it 'filters by name' do
- filtered_search.send_keys('v1')
-
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
- end
-
- it 'filters by case insensitive name' do
- filtered_search.send_keys('V1')
-
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
+ filtered_search.set('milestone=')
end
- it 'filters by name with symbol' do
- filtered_search.send_keys('%v1')
-
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
- end
-
- it 'filters by case insensitive name with symbol' do
- filtered_search.send_keys('%V1')
-
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
- end
-
- it 'filters by special characters' do
- filtered_search.send_keys('(+')
-
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
- end
-
- it 'filters by special characters with symbol' do
- filtered_search.send_keys('%(+')
-
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
- end
- end
-
- describe 'selecting from dropdown' do
- before do
- filtered_search.set('milestone:')
-
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(uppercase_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(two_words_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(wont_fix_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(special_milestone.title)
- expect(find("#{js_dropdown_milestone} .filter-dropdown")).to have_content(long_milestone.title)
- end
-
- it 'fills in the milestone name when the milestone has not been filled' do
- click_milestone(milestone.title)
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token(milestone.title)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the milestone name when the milestone is partially filled', :quarantine do
- filtered_search.send_keys('v')
- click_milestone(milestone.title)
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token(milestone.title)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the milestone name that contains multiple words' do
- click_milestone(two_words_milestone.title)
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token("\"#{two_words_milestone.title}\"")])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the milestone name that contains multiple words and is very long' do
- click_milestone(long_milestone.title)
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token("\"#{long_milestone.title}\"")])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the milestone name that contains double quotes' do
- click_milestone(wont_fix_milestone.title)
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token("'#{wont_fix_milestone.title}'")])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the milestone name with the correct capitalization' do
- click_milestone(uppercase_milestone.title)
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token(uppercase_milestone.title)])
- expect_filtered_search_input_empty
- end
-
- it 'fills in the milestone name with special characters' do
- click_milestone(special_milestone.title)
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token(special_milestone.title)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `no milestone`' do
- click_static_milestone('None')
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('None', false)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `any milestone`' do
- click_static_milestone('Any')
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('Any', false)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `upcoming milestone`' do
- click_static_milestone('Upcoming')
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('Upcoming', false)])
- expect_filtered_search_input_empty
- end
-
- it 'selects `started milestones`' do
- click_static_milestone('Started')
-
- expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([milestone_token('Started', false)])
- expect_filtered_search_input_empty
- end
- end
-
- describe 'input has existing content' do
- it 'opens milestone dropdown with existing search term' do
- filtered_search.set('searchTerm milestone:')
-
- expect(page).to have_css(js_dropdown_milestone, visible: true)
- end
-
- it 'opens milestone dropdown with existing author' do
- filtered_search.set('author:@john milestone:')
-
- expect(page).to have_css(js_dropdown_milestone, visible: true)
- end
-
- it 'opens milestone dropdown with existing assignee' do
- filtered_search.set('assignee:@john milestone:')
-
- expect(page).to have_css(js_dropdown_milestone, visible: true)
- end
-
- it 'opens milestone dropdown with existing label' do
- filtered_search.set('label:~important milestone:')
-
- expect(page).to have_css(js_dropdown_milestone, visible: true)
- end
-
- it 'opens milestone dropdown with existing milestone' do
- filtered_search.set('milestone:%100 milestone:')
-
- expect(page).to have_css(js_dropdown_milestone, visible: true)
- end
-
- it 'opens milestone dropdown with existing my-reaction' do
- filtered_search.set('my-reaction:star milestone:')
-
- expect(page).to have_css(js_dropdown_milestone, visible: true)
- end
- end
-
- describe 'caching requests' do
- it 'caches requests after the first load' do
- filtered_search.set('milestone:')
- initial_size = dropdown_milestone_size
-
- expect(initial_size).to be > 0
-
- create(:milestone, project: project)
- find('.filtered-search-box .clear-search').click
- filtered_search.set('milestone:')
-
- expect(dropdown_milestone_size).to eq(initial_size)
+ it 'loads all the milestones when opened' do
+ expect_filtered_search_dropdown_results(filter_dropdown, 2)
end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_release_spec.rb b/spec/features/issues/filtered_search/dropdown_release_spec.rb
index eea7f2d7848..fd0a98f9ddc 100644
--- a/spec/features/issues/filtered_search/dropdown_release_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_release_spec.rb
@@ -10,13 +10,8 @@ describe 'Dropdown release', :js do
let!(:release) { create(:release, tag: 'v1.0', project: project) }
let!(:crazy_release) { create(:release, tag: '☺!/"#%&\'{}+,-.<>;=@]_`{|}🚀', project: project) }
- def filtered_search
- find('.filtered-search')
- end
-
- def filter_dropdown
- find('#js-dropdown-release .filter-dropdown')
- end
+ let(:filtered_search) { find('.filtered-search') }
+ let(:filter_dropdown) { find('#js-dropdown-release .filter-dropdown') }
before do
project.add_maintainer(user)
@@ -28,28 +23,11 @@ describe 'Dropdown release', :js do
describe 'behavior' do
before do
- filtered_search.set('release:')
- end
-
- def expect_results(count)
- expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: count)
+ filtered_search.set('release=')
end
it 'loads all the releases when opened' do
- expect_results(2)
- end
-
- it 'filters by tag name' do
- filtered_search.send_keys("☺")
- expect_results(1)
- end
-
- it 'fills in the release name when the autocomplete hint is clicked' do
- find('#js-dropdown-release .filter-dropdown-item', text: crazy_release.tag).click
-
- expect(page).to have_css('#js-dropdown-release', visible: false)
- expect_tokens([release_token(crazy_release.tag)])
- expect_filtered_search_input_empty
+ expect_filtered_search_dropdown_results(filter_dropdown, 2)
end
end
end
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index 8b5e7934ec1..c99c205d5da 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -67,7 +67,7 @@ describe 'Filter issues', :js do
it 'filters by all available tokens' do
search_term = 'issue'
- input_filtered_search("assignee:@#{user.username} author:@#{user.username} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} #{search_term}")
+ input_filtered_search("assignee=@#{user.username} author=@#{user.username} label=~#{caps_sensitive_label.title} milestone=%#{milestone.title} #{search_term}")
wait_for_requests
@@ -84,7 +84,7 @@ describe 'Filter issues', :js do
describe 'filter issues by author' do
context 'only author' do
it 'filters issues by searched author' do
- input_filtered_search("author:@#{user.username}")
+ input_filtered_search("author=@#{user.username}")
wait_for_requests
@@ -98,7 +98,7 @@ describe 'Filter issues', :js do
describe 'filter issues by assignee' do
context 'only assignee' do
it 'filters issues by searched assignee' do
- input_filtered_search("assignee:@#{user.username}")
+ input_filtered_search("assignee=@#{user.username}")
wait_for_requests
@@ -108,7 +108,7 @@ describe 'Filter issues', :js do
end
it 'filters issues by no assignee' do
- input_filtered_search('assignee:none')
+ input_filtered_search('assignee=none')
expect_tokens([assignee_token('None')])
expect_issues_list_count(3)
@@ -122,7 +122,7 @@ describe 'Filter issues', :js do
it 'filters issues by multiple assignees' do
create(:issue, project: project, author: user, assignees: [user2, user])
- input_filtered_search("assignee:@#{user.username} assignee:@#{user2.username}")
+ input_filtered_search("assignee=@#{user.username} assignee=@#{user2.username}")
expect_tokens([
assignee_token(user.name),
@@ -138,15 +138,31 @@ describe 'Filter issues', :js do
describe 'filter issues by label' do
context 'only label' do
it 'filters issues by searched label' do
- input_filtered_search("label:~#{bug_label.title}")
+ input_filtered_search("label=~#{bug_label.title}")
expect_tokens([label_token(bug_label.title)])
expect_issues_list_count(2)
expect_filtered_search_input_empty
end
+ it 'filters issues not containing searched label' do
+ input_filtered_search("label!=~#{bug_label.title}")
+
+ expect_tokens([label_token(bug_label.title)])
+ expect_issues_list_count(6)
+ expect_filtered_search_input_empty
+ end
+
it 'filters issues by no label' do
- input_filtered_search('label:none')
+ input_filtered_search('label=none')
+
+ expect_tokens([label_token('None', false)])
+ expect_issues_list_count(4)
+ expect_filtered_search_input_empty
+ end
+
+ it 'filters issues by no label' do
+ input_filtered_search('label!=none')
expect_tokens([label_token('None', false)])
expect_issues_list_count(4)
@@ -154,7 +170,18 @@ describe 'Filter issues', :js do
end
it 'filters issues by multiple labels' do
- input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title}")
+ input_filtered_search("label=~#{bug_label.title} label=~#{caps_sensitive_label.title}")
+
+ expect_tokens([
+ label_token(bug_label.title),
+ label_token(caps_sensitive_label.title)
+ ])
+ expect_issues_list_count(1)
+ expect_filtered_search_input_empty
+ end
+
+ it 'filters issues by multiple labels with not operator' do
+ input_filtered_search("label!=~#{bug_label.title} label=~#{caps_sensitive_label.title}")
expect_tokens([
label_token(bug_label.title),
@@ -169,22 +196,42 @@ describe 'Filter issues', :js do
special_issue = create(:issue, title: "Issue with special character label", project: project)
special_issue.labels << special_label
- input_filtered_search("label:~#{special_label.title}")
+ input_filtered_search("label=~#{special_label.title}")
expect_tokens([label_token(special_label.title)])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
+ it 'filters issues by label not containing special characters' do
+ special_label = create(:label, project: project, title: '!@#{$%^&*()-+[]<>?/:{}|\}')
+ special_issue = create(:issue, title: "Issue with special character label", project: project)
+ special_issue.labels << special_label
+
+ input_filtered_search("label!=~#{special_label.title}")
+
+ expect_tokens([label_token(special_label.title)])
+ expect_issues_list_count(8)
+ expect_filtered_search_input_empty
+ end
+
it 'does not show issues for unused labels' do
new_label = create(:label, project: project, title: 'new_label')
- input_filtered_search("label:~#{new_label.title}")
+ input_filtered_search("label=~#{new_label.title}")
expect_tokens([label_token(new_label.title)])
expect_no_issues_list
expect_filtered_search_input_empty
end
+
+ it 'does show issues for bug label' do
+ input_filtered_search("label!=~#{bug_label.title}")
+
+ expect_tokens([label_token(bug_label.title)])
+ expect_issues_list_count(6)
+ expect_filtered_search_input_empty
+ end
end
context 'label with multiple words' do
@@ -193,7 +240,7 @@ describe 'Filter issues', :js do
special_multiple_issue = create(:issue, title: "Issue with special character multiple words label", project: project)
special_multiple_issue.labels << special_multiple_label
- input_filtered_search("label:~'#{special_multiple_label.title}'")
+ input_filtered_search("label=~'#{special_multiple_label.title}'")
# Check for search results (which makes sure that the page has changed)
expect_issues_list_count(1)
@@ -205,7 +252,7 @@ describe 'Filter issues', :js do
end
it 'single quotes' do
- input_filtered_search("label:~'#{multiple_words_label.title}'")
+ input_filtered_search("label=~'#{multiple_words_label.title}'")
expect_issues_list_count(1)
expect_tokens([label_token("\"#{multiple_words_label.title}\"")])
@@ -213,7 +260,7 @@ describe 'Filter issues', :js do
end
it 'double quotes' do
- input_filtered_search("label:~\"#{multiple_words_label.title}\"")
+ input_filtered_search("label=~\"#{multiple_words_label.title}\"")
expect_tokens([label_token("\"#{multiple_words_label.title}\"")])
expect_issues_list_count(1)
@@ -225,7 +272,7 @@ describe 'Filter issues', :js do
double_quotes_label_issue = create(:issue, title: "Issue with double quotes label", project: project)
double_quotes_label_issue.labels << double_quotes_label
- input_filtered_search("label:~'#{double_quotes_label.title}'")
+ input_filtered_search("label=~'#{double_quotes_label.title}'")
expect_tokens([label_token("'#{double_quotes_label.title}'")])
expect_issues_list_count(1)
@@ -237,7 +284,7 @@ describe 'Filter issues', :js do
single_quotes_label_issue = create(:issue, title: "Issue with single quotes label", project: project)
single_quotes_label_issue.labels << single_quotes_label
- input_filtered_search("label:~\"#{single_quotes_label.title}\"")
+ input_filtered_search("label=~\"#{single_quotes_label.title}\"")
expect_tokens([label_token("\"#{single_quotes_label.title}\"")])
expect_issues_list_count(1)
@@ -249,7 +296,7 @@ describe 'Filter issues', :js do
it 'filters issues by searched label, label2, author, assignee, milestone and text' do
search_term = 'bug'
- input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} milestone:%#{milestone.title} #{search_term}")
+ input_filtered_search("label=~#{bug_label.title} label=~#{caps_sensitive_label.title} author=@#{user.username} assignee=@#{user.username} milestone=%#{milestone.title} #{search_term}")
wait_for_requests
@@ -263,6 +310,24 @@ describe 'Filter issues', :js do
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
end
+
+ it 'filters issues by searched label, label2, author, assignee, not included in a milestone' do
+ search_term = 'bug'
+
+ input_filtered_search("label=~#{bug_label.title} label=~#{caps_sensitive_label.title} author=@#{user.username} assignee=@#{user.username} milestone!=%#{milestone.title} #{search_term}")
+
+ wait_for_requests
+
+ expect_tokens([
+ label_token(bug_label.title),
+ label_token(caps_sensitive_label.title),
+ author_token(user.name),
+ assignee_token(user.name),
+ milestone_token(milestone.title, false, '!=')
+ ])
+ expect_issues_list_count(0)
+ expect_filtered_search_input(search_term)
+ end
end
context 'issue label clicked' do
@@ -279,7 +344,7 @@ describe 'Filter issues', :js do
describe 'filter issues by milestone' do
context 'only milestone' do
it 'filters issues by searched milestone' do
- input_filtered_search("milestone:%#{milestone.title}")
+ input_filtered_search("milestone=%#{milestone.title}")
expect_tokens([milestone_token(milestone.title)])
expect_issues_list_count(5)
@@ -287,53 +352,102 @@ describe 'Filter issues', :js do
end
it 'filters issues by no milestone' do
- input_filtered_search("milestone:none")
+ input_filtered_search("milestone=none")
expect_tokens([milestone_token('None', false)])
expect_issues_list_count(3)
expect_filtered_search_input_empty
end
+ it 'filters issues by negation of no milestone' do
+ input_filtered_search("milestone!=none ")
+
+ expect_tokens([milestone_token('None', false, '!=')])
+ expect_issues_list_count(5)
+ expect_filtered_search_input_empty
+ end
+
it 'filters issues by upcoming milestones' do
create(:milestone, project: project, due_date: 1.month.from_now) do |future_milestone|
create(:issue, project: project, milestone: future_milestone, author: user)
end
- input_filtered_search("milestone:upcoming")
+ input_filtered_search("milestone=upcoming")
expect_tokens([milestone_token('Upcoming', false)])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
+ it 'filters issues by negation of upcoming milestones' do
+ create(:milestone, project: project, due_date: 1.month.from_now) do |future_milestone|
+ create(:issue, project: project, milestone: future_milestone, author: user)
+ end
+
+ input_filtered_search("milestone!=upcoming")
+
+ expect_tokens([milestone_token('Upcoming', false, '!=')])
+ expect_issues_list_count(8)
+ expect_filtered_search_input_empty
+ end
+
it 'filters issues by started milestones' do
- input_filtered_search("milestone:started")
+ input_filtered_search("milestone=started")
expect_tokens([milestone_token('Started', false)])
expect_issues_list_count(5)
expect_filtered_search_input_empty
end
+ it 'filters issues by negation of started milestones' do
+ input_filtered_search("milestone!=started")
+
+ expect_tokens([milestone_token('Started', false, '!=')])
+ expect_issues_list_count(3)
+ expect_filtered_search_input_empty
+ end
+
it 'filters issues by milestone containing special characters' do
special_milestone = create(:milestone, title: '!@\#{$%^&*()}', project: project)
create(:issue, project: project, milestone: special_milestone)
- input_filtered_search("milestone:%#{special_milestone.title}")
+ input_filtered_search("milestone=%#{special_milestone.title}")
expect_tokens([milestone_token(special_milestone.title)])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
+ it 'filters issues by milestone not containing special characters' do
+ special_milestone = create(:milestone, title: '!@\#{$%^&*()}', project: project)
+ create(:issue, project: project, milestone: special_milestone)
+
+ input_filtered_search("milestone!=%#{special_milestone.title}")
+
+ expect_tokens([milestone_token(special_milestone.title, false, '!=')])
+ expect_issues_list_count(8)
+ expect_filtered_search_input_empty
+ end
+
it 'does not show issues for unused milestones' do
new_milestone = create(:milestone, title: 'new', project: project)
- input_filtered_search("milestone:%#{new_milestone.title}")
+ input_filtered_search("milestone=%#{new_milestone.title}")
expect_tokens([milestone_token(new_milestone.title)])
expect_no_issues_list
expect_filtered_search_input_empty
end
+
+ it 'show issues for unused milestones' do
+ new_milestone = create(:milestone, title: 'new', project: project)
+
+ input_filtered_search("milestone!=%#{new_milestone.title}")
+
+ expect_tokens([milestone_token(new_milestone.title, false, '!=')])
+ expect_issues_list_count(8)
+ expect_filtered_search_input_empty
+ end
end
end
@@ -407,7 +521,7 @@ describe 'Filter issues', :js do
context 'searched text with other filters' do
it 'filters issues by searched text, author, text, assignee, text, label1, text, label2, text, milestone and text' do
- input_filtered_search("bug author:@#{user.username} report label:~#{bug_label.title} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} foo")
+ input_filtered_search("bug author=@#{user.username} report label=~#{bug_label.title} label=~#{caps_sensitive_label.title} milestone=%#{milestone.title} foo")
expect_issues_list_count(1)
expect_filtered_search_input('bug report foo')
@@ -475,65 +589,13 @@ describe 'Filter issues', :js do
end
end
- describe 'RSS feeds' do
- let(:group) { create(:group) }
- let(:project) { create(:project, group: group) }
-
- before do
- group.add_developer(user)
- end
-
- shared_examples 'updates atom feed link' do |type|
- it "for #{type}" do
- visit path
-
- link = find_link('Subscribe to RSS feed')
- params = CGI.parse(URI.parse(link[:href]).query)
- auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
- auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
-
- expected = {
- 'feed_token' => [user.feed_token],
- 'milestone_title' => [milestone.title],
- 'assignee_id' => [user.id.to_s]
- }
-
- expect(params).to include(expected)
- expect(auto_discovery_params).to include(expected)
- end
- end
-
- it_behaves_like 'updates atom feed link', :project do
- let(:path) { project_issues_path(project, milestone_title: milestone.title, assignee_id: user.id) }
- end
-
- it_behaves_like 'updates atom feed link', :group do
- let(:path) { issues_group_path(group, milestone_title: milestone.title, assignee_id: user.id) }
- end
-
- it 'updates atom feed link for group issues' do
- visit issues_group_path(group, milestone_title: milestone.title, assignee_id: user.id)
- link = find('.nav-controls a[title="Subscribe to RSS feed"]', visible: false)
- params = CGI.parse(URI.parse(link[:href]).query)
- auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
- auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
-
- expect(params).to include('feed_token' => [user.feed_token])
- expect(params).to include('milestone_title' => [milestone.title])
- expect(params).to include('assignee_id' => [user.id.to_s])
- expect(auto_discovery_params).to include('feed_token' => [user.feed_token])
- expect(auto_discovery_params).to include('milestone_title' => [milestone.title])
- expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
- end
- end
-
context 'URL has a trailing slash' do
before do
visit "#{project_issues_path(project)}/"
end
it 'milestone dropdown loads milestones' do
- input_filtered_search("milestone:", submit: false)
+ input_filtered_search("milestone=", submit: false)
within('#js-dropdown-milestone') do
expect(page).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
@@ -541,7 +603,7 @@ describe 'Filter issues', :js do
end
it 'label dropdown load labels' do
- input_filtered_search("label:", submit: false)
+ input_filtered_search("label=", submit: false)
within('#js-dropdown-label') do
expect(page).to have_selector('.filter-dropdown .filter-dropdown-item', count: 3)
diff --git a/spec/features/issues/filtered_search/recent_searches_spec.rb b/spec/features/issues/filtered_search/recent_searches_spec.rb
index c038281d825..e05c7aa3af5 100644
--- a/spec/features/issues/filtered_search/recent_searches_spec.rb
+++ b/spec/features/issues/filtered_search/recent_searches_spec.rb
@@ -41,8 +41,8 @@ describe 'Recent searches', :js do
items = all('.filtered-search-history-dropdown-item', visible: false, count: 2)
- expect(items[0].text).to eq('label: ~qux garply')
- expect(items[1].text).to eq('label: ~foo bar')
+ expect(items[0].text).to eq('label: = ~qux garply')
+ expect(items[1].text).to eq('label: = ~foo bar')
end
it 'saved recent searches are restored last on the list' do
diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb
index e97314e02e6..ad994270218 100644
--- a/spec/features/issues/filtered_search/search_bar_spec.rb
+++ b/spec/features/issues/filtered_search/search_bar_spec.rb
@@ -34,7 +34,7 @@ describe 'Search bar', :js do
it 'selects item' do
filtered_search.native.send_keys(:down, :down, :enter)
- expect_tokens([author_token])
+ expect_tokens([{ name: 'Assignee' }])
expect_filtered_search_input_empty
end
end
@@ -78,7 +78,7 @@ describe 'Search bar', :js do
filtered_search.click
original_size = page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size
- filtered_search.set('author')
+ filtered_search.set('autho')
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb
index f8035ef4b85..2af2e096bcc 100644
--- a/spec/features/issues/filtered_search/visual_tokens_spec.rb
+++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb
@@ -34,17 +34,15 @@ describe 'Visual tokens', :js do
visit project_issues_path(project)
end
- describe 'editing author token' do
+ describe 'editing a single token' do
before do
- input_filtered_search('author:@root assignee:none', submit: false)
+ input_filtered_search('author=@root assignee=none', submit: false)
first('.tokens-container .filtered-search-token').click
+ wait_for_requests
end
it 'opens author dropdown' do
expect(page).to have_css('#js-dropdown-author', visible: true)
- end
-
- it 'makes value editable' do
expect_filtered_search_input('@root')
end
@@ -77,143 +75,10 @@ describe 'Visual tokens', :js do
end
end
- describe 'editing assignee token' do
- before do
- input_filtered_search('assignee:@root author:none', submit: false)
- first('.tokens-container .filtered-search-token').double_click
- end
-
- it 'opens assignee dropdown' do
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- end
-
- it 'makes value editable' do
- expect_filtered_search_input('@root')
- end
-
- it 'filters value' do
- filtered_search.send_keys(:backspace)
-
- expect(page).to have_css('#js-dropdown-assignee .filter-dropdown .filter-dropdown-item', count: 1)
- end
-
- it 'ends editing mode when document is clicked' do
- find('#content-body').click
-
- expect_filtered_search_input_empty
- expect(page).to have_css('#js-dropdown-assignee', visible: false)
- end
-
- describe 'selecting static option from dropdown' do
- before do
- find("#js-dropdown-assignee").find('.filter-dropdown-item', text: 'None').click
- end
-
- it 'changes value in visual token' do
- expect(first('.tokens-container .filtered-search-token .value').text).to eq('None')
- end
-
- it 'moves input to the right' do
- expect(is_input_focused).to eq(true)
- end
- end
- end
-
- describe 'editing milestone token' do
- before do
- input_filtered_search('milestone:%10.0 author:none', submit: false)
- first('.tokens-container .filtered-search-token').click
- first('#js-dropdown-milestone .filter-dropdown .filter-dropdown-item')
- end
-
- it 'opens milestone dropdown' do
- expect(filter_milestone_dropdown.find('.filter-dropdown-item', text: milestone_ten.title)).to be_visible
- expect(filter_milestone_dropdown.find('.filter-dropdown-item', text: milestone_nine.title)).to be_visible
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- end
-
- it 'selects static option from dropdown' do
- find("#js-dropdown-milestone").find('.filter-dropdown-item', text: 'Upcoming').click
-
- expect(first('.tokens-container .filtered-search-token .value').text).to eq('Upcoming')
- expect(is_input_focused).to eq(true)
- end
-
- it 'makes value editable' do
- expect_filtered_search_input('%10.0')
- end
-
- it 'filters value' do
- filtered_search.send_keys(:backspace)
-
- expect(page).to have_css('#js-dropdown-milestone .filter-dropdown .filter-dropdown-item', count: 1)
- end
-
- it 'ends editing mode when document is clicked' do
- find('#content-body').click
-
- expect_filtered_search_input_empty
- expect(page).to have_css('#js-dropdown-milestone', visible: false)
- end
- end
-
- describe 'editing label token' do
- before do
- input_filtered_search("label:~#{label.title} author:none", submit: false)
- first('.tokens-container .filtered-search-token').double_click
- first('#js-dropdown-label .filter-dropdown .filter-dropdown-item')
- end
-
- it 'opens label dropdown' do
- expect(filter_label_dropdown.find('.filter-dropdown-item', text: label.title)).to be_visible
- expect(filter_label_dropdown.find('.filter-dropdown-item', text: cc_label.title)).to be_visible
- expect(page).to have_css('#js-dropdown-label', visible: true)
- end
-
- it 'selects option from dropdown' do
- expect(filter_label_dropdown.find('.filter-dropdown-item', text: label.title)).to be_visible
- expect(filter_label_dropdown.find('.filter-dropdown-item', text: cc_label.title)).to be_visible
-
- find("#js-dropdown-label").find('.filter-dropdown-item', text: cc_label.title).click
-
- expect(first('.tokens-container .filtered-search-token .value').text).to eq("~\"#{cc_label.title}\"")
- expect(is_input_focused).to eq(true)
- end
-
- it 'makes value editable' do
- expect_filtered_search_input("~#{label.title}")
- end
-
- it 'filters value' do
- expect(filter_label_dropdown.find('.filter-dropdown-item', text: label.title)).to be_visible
- expect(filter_label_dropdown.find('.filter-dropdown-item', text: cc_label.title)).to be_visible
-
- filtered_search.send_keys(:backspace)
-
- filter_label_dropdown.find('.filter-dropdown-item')
-
- expect(page.all('#js-dropdown-label .filter-dropdown .filter-dropdown-item').size).to eq(1)
- end
-
- it 'ends editing mode when document is clicked' do
- find('#content-body').click
-
- expect_filtered_search_input_empty
- expect(page).to have_css('#js-dropdown-label', visible: false)
- end
-
- it 'ends editing mode when scroll container is clicked' do
- find('.scroll-container').click
-
- expect_filtered_search_input_empty
- expect(page).to have_css('#js-dropdown-label', visible: false)
- end
- end
-
describe 'editing multiple tokens' do
before do
- input_filtered_search('author:@root assignee:none', submit: false)
- first('.tokens-container .filtered-search-token').double_click
+ input_filtered_search('author=@root assignee=none', submit: false)
+ first('.tokens-container .filtered-search-token').click
end
it 'opens author dropdown' do
@@ -221,31 +86,33 @@ describe 'Visual tokens', :js do
end
it 'opens assignee dropdown' do
- find('.tokens-container .filtered-search-token', text: 'Assignee').double_click
+ find('.tokens-container .filtered-search-token', text: 'Assignee').click
expect(page).to have_css('#js-dropdown-assignee', visible: true)
end
end
describe 'editing a search term while editing another filter token' do
before do
- input_filtered_search('author assignee:', submit: false)
- first('.tokens-container .filtered-search-term').double_click
- end
-
- it 'opens hint dropdown' do
- expect(page).to have_css('#js-dropdown-hint', visible: true)
+ input_filtered_search('foo assignee=', submit: false)
+ first('.tokens-container .filtered-search-term').click
end
it 'opens author dropdown' do
- find('#js-dropdown-hint .filter-dropdown .filter-dropdown-item', text: 'author').click
+ find('#js-dropdown-hint .filter-dropdown .filter-dropdown-item', text: 'Author').click
+
+ expect(page).to have_css('#js-dropdown-operator', visible: true)
+ expect(page).to have_css('#js-dropdown-author', visible: false)
+ find('#js-dropdown-operator .filter-dropdown .filter-dropdown-item[data-value="="]').click
+
+ expect(page).to have_css('#js-dropdown-operator', visible: false)
expect(page).to have_css('#js-dropdown-author', visible: true)
end
end
describe 'add new token after editing existing token' do
before do
- input_filtered_search('author:@root assignee:none', submit: false)
+ input_filtered_search('author=@root assignee=none', submit: false)
first('.tokens-container .filtered-search-token').double_click
filtered_search.send_keys(' ')
end
@@ -255,63 +122,25 @@ describe 'Visual tokens', :js do
expect(page).to have_css('#js-dropdown-hint', visible: true)
end
- it 'opens author dropdown' do
- filtered_search.send_keys('author:')
- expect(page).to have_css('#js-dropdown-author', visible: true)
- end
-
- it 'opens assignee dropdown' do
- filtered_search.send_keys('assignee:')
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- end
-
- it 'opens milestone dropdown' do
- filtered_search.send_keys('milestone:')
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- end
+ it 'opens token dropdown' do
+ filtered_search.send_keys('author=')
- it 'opens label dropdown' do
- filtered_search.send_keys('label:')
- expect(page).to have_css('#js-dropdown-label', visible: true)
+ expect(page).to have_css('#js-dropdown-author', visible: true)
end
end
- describe 'creates visual tokens' do
- it 'creates author token' do
- filtered_search.send_keys('author:@thomas ')
+ describe 'visual tokens' do
+ it 'creates visual token' do
+ filtered_search.send_keys('author=@thomas ')
token = page.all('.tokens-container .filtered-search-token')[1]
expect(token.find('.name').text).to eq('Author')
expect(token.find('.value').text).to eq('@thomas')
end
-
- it 'creates assignee token' do
- filtered_search.send_keys('assignee:@thomas ')
- token = page.all('.tokens-container .filtered-search-token')[1]
-
- expect(token.find('.name').text).to eq('Assignee')
- expect(token.find('.value').text).to eq('@thomas')
- end
-
- it 'creates milestone token' do
- filtered_search.send_keys('milestone:none ')
- token = page.all('.tokens-container .filtered-search-token')[1]
-
- expect(token.find('.name').text).to eq('Milestone')
- expect(token.find('.value').text).to eq('none')
- end
-
- it 'creates label token' do
- filtered_search.send_keys('label:~Backend ')
- token = page.all('.tokens-container .filtered-search-token')[1]
-
- expect(token.find('.name').text).to eq('Label')
- expect(token.find('.value').text).to eq('~Backend')
- end
end
it 'does not tokenize incomplete token' do
- filtered_search.send_keys('author:')
+ filtered_search.send_keys('author=')
find('body').click
token = page.all('.tokens-container .js-visual-token')[1]
@@ -323,7 +152,7 @@ describe 'Visual tokens', :js do
describe 'search using incomplete visual tokens' do
before do
- input_filtered_search('author:@root assignee:none', extra_space: false)
+ input_filtered_search('author=@root assignee=none', extra_space: false)
end
it 'tokenizes the search term to complete visual token' do
diff --git a/spec/features/issues/rss_spec.rb b/spec/features/issues/rss_spec.rb
index d6a406f4f44..7577df3bc7d 100644
--- a/spec/features/issues/rss_spec.rb
+++ b/spec/features/issues/rss_spec.rb
@@ -3,11 +3,14 @@
require 'spec_helper'
describe 'Project Issues RSS' do
- let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
+ let!(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
let(:path) { project_issues_path(project) }
before do
- create(:issue, project: project)
+ create(:issue, project: project, assignees: [user])
+ group.add_developer(user)
end
context 'when signed in' do
@@ -31,4 +34,34 @@ describe 'Project Issues RSS' do
it_behaves_like "it has an RSS button without a feed token"
it_behaves_like "an autodiscoverable RSS feed without a feed token"
end
+
+ describe 'feeds' do
+ shared_examples 'updates atom feed link' do |type|
+ it "for #{type}" do
+ sign_in(user)
+ visit path
+
+ link = find_link('Subscribe to RSS feed')
+ params = CGI.parse(URI.parse(link[:href]).query)
+ auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
+ auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
+
+ expected = {
+ 'feed_token' => [user.feed_token],
+ 'assignee_id' => [user.id.to_s]
+ }
+
+ expect(params).to include(expected)
+ expect(auto_discovery_params).to include(expected)
+ end
+ end
+
+ it_behaves_like 'updates atom feed link', :project do
+ let(:path) { project_issues_path(project, assignee_id: user.id) }
+ end
+
+ it_behaves_like 'updates atom feed link', :group do
+ let(:path) { issues_group_path(group, assignee_id: user.id) }
+ end
+ end
end
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index 829f945c47f..363906b017a 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -43,17 +43,17 @@ describe "User comments on issue", :js do
expect(page.find('pre code').text).to eq code_block_content
end
- it "renders escaped HTML content in Mermaid" do
+ it "renders HTML content as text in Mermaid" do
html_content = "<img onerror=location=`javascript\\u003aalert\\u0028document.domain\\u0029` src=x>"
mermaid_content = "graph LR\n B-->D(#{html_content});"
- escaped_content = CGI.escapeHTML(html_content).gsub('=', "&equals;")
comment = "```mermaid\n#{mermaid_content}\n```"
add_note(comment)
wait_for_requests
- expect(page.find('svg.mermaid')).to have_content escaped_content
+ expect(page.find('svg.mermaid')).to have_content html_content
+ within('svg.mermaid') { expect(page).not_to have_selector('img') }
end
it 'opens autocomplete menu for quick actions and have `/label` first choice' do
diff --git a/spec/features/issues/user_creates_issue_by_email_spec.rb b/spec/features/issues/user_creates_issue_by_email_spec.rb
new file mode 100644
index 00000000000..c73a65849cc
--- /dev/null
+++ b/spec/features/issues/user_creates_issue_by_email_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Issues > User creates issue by email' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+
+ before do
+ sign_in(user)
+
+ project.add_developer(user)
+ end
+
+ describe 'new issue by email' do
+ shared_examples 'show the email in the modal' do
+ let(:issue) { create(:issue, project: project) }
+
+ before do
+ project.issues << issue
+ stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
+
+ visit project_issues_path(project)
+ click_button('Email a new issue')
+ end
+
+ it 'click the button to show modal for the new email' do
+ page.within '#issuable-email-modal' do
+ email = project.new_issuable_address(user, 'issue')
+
+ expect(page).to have_selector("input[value='#{email}']")
+ end
+ end
+ end
+
+ context 'with existing issues' do
+ let!(:issue) { create(:issue, project: project, author: user) }
+
+ it_behaves_like 'show the email in the modal'
+ end
+
+ context 'without existing issues' do
+ it_behaves_like 'show the email in the modal'
+ end
+ end
+end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 39ce3415727..b0a2a734877 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -3,8 +3,32 @@
require "spec_helper"
describe "User creates issue" do
- let(:project) { create(:project_empty_repo, :public) }
- let(:user) { create(:user) }
+ include DropzoneHelper
+
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:user) { create(:user) }
+
+ context "when unauthenticated" do
+ before do
+ sign_out(:user)
+ end
+
+ it "redirects to signin then back to new issue after signin" do
+ create(:issue, project: project)
+
+ visit project_issues_path(project)
+
+ page.within ".nav-controls" do
+ click_link "New issue"
+ end
+
+ expect(current_path).to eq new_user_session_path
+
+ gitlab_sign_in(create(:user))
+
+ expect(current_path).to eq new_project_issue_path(project)
+ end
+ end
context "when signed in as guest" do
before do
@@ -92,6 +116,104 @@ describe "User creates issue" do
.and have_content(label_titles.first)
end
end
+
+ context 'with due date', :js do
+ it 'saves with due date' do
+ date = Date.today.at_beginning_of_month
+
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+ find('#issuable-due-date').click
+
+ page.within '.pika-single' do
+ click_button date.day
+ end
+
+ expect(find('#issuable-due-date').value).to eq date.to_s
+
+ click_button 'Submit issue'
+
+ page.within '.issuable-sidebar' do
+ expect(page).to have_content date.to_s(:medium)
+ end
+ end
+ end
+
+ context 'dropzone upload file', :js do
+ before do
+ visit new_project_issue_path(project)
+ end
+
+ it 'uploads file when dragging into textarea' do
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+
+ expect(page.find_field("issue_description").value).to have_content 'banana_sample'
+ end
+
+ it "doesn't add double newline to end of a single attachment markdown" do
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+
+ expect(page.find_field("issue_description").value).not_to match /\n\n$/
+ end
+
+ it "cancels a file upload correctly" do
+ slow_requests do
+ dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
+
+ click_button 'Cancel'
+ end
+
+ expect(page).to have_button('Attach a file')
+ expect(page).not_to have_button('Cancel')
+ expect(page).not_to have_selector('.uploading-progress-container', visible: true)
+ end
+ end
+
+ context 'form filled by URL parameters' do
+ let(:project) { create(:project, :public, :repository) }
+
+ before do
+ project.repository.create_file(
+ user,
+ '.gitlab/issue_templates/bug.md',
+ 'this is a test "bug" template',
+ message: 'added issue template',
+ branch_name: 'master')
+
+ visit new_project_issue_path(project, issuable_template: 'bug')
+ end
+
+ it 'fills in template' do
+ expect(find('.js-issuable-selector .dropdown-toggle-text')).to have_content('bug')
+ end
+ end
+
+ context 'suggestions', :js do
+ it 'displays list of related issues' do
+ issue = create(:issue, project: project)
+ create(:issue, project: project, title: 'test issue')
+
+ visit new_project_issue_path(project)
+
+ fill_in 'issue_title', with: issue.title
+
+ expect(page).to have_selector('.suggestion-item', count: 1)
+ end
+ end
+
+ it 'clears local storage after creating a new issue', :js do
+ 2.times do
+ visit new_project_issue_path(project)
+ wait_for_requests
+
+ expect(page).to have_field('Title', with: '')
+
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+
+ click_button 'Submit issue'
+ end
+ end
end
context "when signed in as user with special characters in their name" do
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 0afc19d9519..ad984cf07e2 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -2,26 +2,283 @@
require "spec_helper"
-describe "User edits issue", :js do
- set(:project) { create(:project_empty_repo, :public) }
- set(:user) { create(:user) }
- set(:issue) { create(:issue, project: project, author: user) }
+describe "Issues > User edits issue", :js do
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
+ let_it_be(:label) { create(:label, project: project) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
before do
project.add_developer(user)
sign_in(user)
+ end
+
+ context "from edit page" do
+ before do
+ visit edit_project_issue_path(project, issue)
+ end
+
+ it "previews content" do
+ form = first(".gfm-form")
+
+ page.within(form) do
+ fill_in("Description", with: "Bug fixed :smile:")
+ click_button("Preview")
+ end
+
+ expect(form).to have_button("Write")
+ end
+
+ it 'allows user to select unassigned' do
+ visit edit_project_issue_path(project, issue)
+
+ expect(page).to have_content "Assignee #{user.name}"
+
+ first('.js-user-search').click
+ click_link 'Unassigned'
+
+ click_button 'Save changes'
+
+ page.within('.assignee') do
+ expect(page).to have_content 'None - assign yourself'
+ end
+ end
+
+ context 'with due date' do
+ before do
+ visit edit_project_issue_path(project, issue)
+ end
+
+ it 'saves with due date' do
+ date = Date.today.at_beginning_of_month.tomorrow
+
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+ find('#issuable-due-date').click
+
+ page.within '.pika-single' do
+ click_button date.day
+ end
+
+ expect(find('#issuable-due-date').value).to eq date.to_s
+
+ click_button 'Save changes'
- visit(edit_project_issue_path(project, issue))
+ page.within '.issuable-sidebar' do
+ expect(page).to have_content date.to_s(:medium)
+ end
+ end
+
+ it 'warns about version conflict' do
+ issue.update(title: "New title")
+
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+
+ click_button 'Save changes'
+
+ expect(page).to have_content 'Someone edited the issue the same time you did'
+ end
+ end
end
- it "previews content" do
- form = first(".gfm-form")
+ context "from issue#show" do
+ before do
+ visit project_issue_path(project, issue)
+ end
+
+ describe 'update labels' do
+ it 'will not send ajax request when no data is changed' do
+ page.within '.labels' do
+ click_link 'Edit'
- page.within(form) do
- fill_in("Description", with: "Bug fixed :smile:")
- click_button("Preview")
+ find('.dropdown-menu-close', match: :first).click
+
+ expect(page).not_to have_selector('.block-loading')
+ end
+ end
end
- expect(form).to have_button("Write")
+ 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
+ end
+
+ it 'allows user to select unassigned' do
+ visit project_issue_path(project, issue)
+
+ 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
+
+ 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"
+ 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
+
+ it 'allows user to unselect themselves' do
+ issue2 = create(:issue, project: project, author: user)
+
+ visit project_issue_path(project, issue2)
+
+ page.within '.assignee' do
+ click_link 'Edit'
+ click_link user.name
+
+ close_dropdown_menu_if_visible
+
+ page.within '.value .author' do
+ expect(page).to have_content user.name
+ end
+
+ 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) }
+
+ 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
+
+ describe 'update milestone' do
+ context 'by authorized user' do
+ it 'allows user to select unassigned' do
+ visit project_issue_path(project, issue)
+
+ page.within('.milestone') do
+ expect(page).to have_content "None"
+ end
+
+ find('.block.milestone .edit-link').click
+ sleep 2 # wait for ajax stuff to complete
+ first('.dropdown-content li').click
+ sleep 2
+ page.within('.milestone') do
+ expect(page).to have_content 'None'
+ end
+ end
+
+ it 'allows user to de-select milestone' do
+ visit project_issue_path(project, issue)
+
+ page.within('.milestone') do
+ click_link 'Edit'
+ click_link milestone.title
+
+ page.within '.value' do
+ expect(page).to have_content milestone.title
+ end
+
+ click_link 'Edit'
+ click_link milestone.title
+
+ page.within '.value' do
+ expect(page).to have_content 'None'
+ end
+ end
+ end
+ end
+
+ context 'by unauthorized user' do
+ let(:guest) { create(:user) }
+
+ before do
+ project.add_guest(guest)
+ issue.milestone = milestone
+ issue.save
+ end
+
+ it 'shows milestone text' do
+ sign_out(:user)
+ sign_in(guest)
+
+ visit project_issue_path(project, issue)
+ expect(page).to have_content milestone.title
+ end
+ end
+ end
+
+ context 'update due date' 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 '.pika-single' do
+ click_button date.day
+ end
+
+ wait_for_requests
+
+ expect(find('.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 '.pika-single' do
+ click_button date.day
+ end
+
+ wait_for_requests
+
+ expect(page).to have_no_content 'None'
+
+ click_link 'remove due date'
+ expect(page).to have_content 'None'
+ end
+ end
+ end
end
end
diff --git a/spec/features/issues/user_filters_issues_spec.rb b/spec/features/issues/user_filters_issues_spec.rb
new file mode 100644
index 00000000000..714bc972025
--- /dev/null
+++ b/spec/features/issues/user_filters_issues_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'User filters issues' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+
+ before do
+ %w[foobar barbaz].each do |title|
+ create(:issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ title: title)
+ end
+
+ @issue = Issue.find_by(title: 'foobar')
+ @issue.milestone = create(:milestone, project: project)
+ @issue.assignees = []
+ @issue.save
+ end
+
+ let(:issue) { @issue }
+
+ it 'allows filtering by issues with no specified assignee' do
+ visit project_issues_path(project, assignee_id: IssuableFinder::FILTER_NONE)
+
+ expect(page).to have_content 'foobar'
+ expect(page).not_to have_content 'barbaz'
+ end
+
+ it 'allows filtering by a specified assignee' do
+ visit project_issues_path(project, assignee_id: user.id)
+
+ expect(page).not_to have_content 'foobar'
+ expect(page).to have_content 'barbaz'
+ end
+end
diff --git a/spec/features/issues/user_resets_their_incoming_email_token_spec.rb b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
new file mode 100644
index 00000000000..108b6f550db
--- /dev/null
+++ b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Issues > User resets their incoming email token' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, namespace: user.namespace) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ before do
+ stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
+ project.add_maintainer(user)
+ sign_in(user)
+
+ visit namespace_project_issues_path(user.namespace, project)
+ end
+
+ it 'changes incoming email address token', :js do
+ find('.issuable-email-modal-btn').click
+ previous_token = find('input#issuable_email').value
+ find('.incoming-email-token-reset').click
+
+ wait_for_requests
+
+ expect(page).to have_no_field('issuable_email', with: previous_token)
+ new_token = project.new_issuable_address(user.reload, 'issue')
+ expect(page).to have_field(
+ 'issuable_email',
+ with: new_token
+ )
+ end
+end
diff --git a/spec/features/issues/user_sees_breadcrumb_links_spec.rb b/spec/features/issues/user_sees_breadcrumb_links_spec.rb
index f31d730c337..8a120a0a0b2 100644
--- a/spec/features/issues/user_sees_breadcrumb_links_spec.rb
+++ b/spec/features/issues/user_sees_breadcrumb_links_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe 'New issue breadcrumb' do
- let(:project) { create(:project) }
+ let_it_be(:project, reload: true) { create(:project) }
let(:user) { project.creator }
before do
@@ -17,4 +17,22 @@ describe 'New issue breadcrumb' do
expect(find_link('New')[:href]).to end_with(new_project_issue_path(project))
end
end
+
+ it 'links to current issue in breadcrubs' do
+ issue = create(:issue, project: project)
+
+ visit project_issue_path(project, issue)
+
+ expect(find('.breadcrumbs-sub-title a')[:href]).to end_with(issue_path(issue))
+ end
+
+ it 'excludes award_emoji from comment count' do
+ issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar')
+ create(:award_emoji, awardable: issue)
+
+ visit project_issues_path(project, assignee_id: user.id)
+
+ expect(page).to have_content 'foobar'
+ expect(page.all('.no-comments').first.text).to eq "0"
+ end
end
diff --git a/spec/features/issues/user_sees_empty_state_spec.rb b/spec/features/issues/user_sees_empty_state_spec.rb
new file mode 100644
index 00000000000..114d119aca8
--- /dev/null
+++ b/spec/features/issues/user_sees_empty_state_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Issues > User sees empty state' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:user) { project.creator }
+
+ shared_examples_for 'empty state with filters' do
+ it 'user sees empty state with filters' do
+ create(:issue, author: user, project: project)
+
+ visit project_issues_path(project, milestone_title: "1.0")
+
+ expect(page).to have_content('Sorry, your filter produced no results')
+ expect(page).to have_content('To widen your search, change or remove filters above')
+ end
+ end
+
+ describe 'while user is signed out' do
+ describe 'empty state' do
+ it 'user sees empty state' do
+ visit project_issues_path(project)
+
+ expect(page).to have_content('Register / Sign In')
+ expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project.')
+ expect(page).to have_content('You can register or sign in to create issues for this project.')
+ end
+
+ it_behaves_like 'empty state with filters'
+ end
+ end
+
+ describe 'while user is signed in' do
+ before do
+ sign_in(user)
+ end
+
+ describe 'empty state' do
+ it 'user sees empty state' do
+ visit project_issues_path(project)
+
+ expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project')
+ expect(page).to have_content('Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.')
+ expect(page).to have_content('New issue')
+ end
+
+ it_behaves_like 'empty state with filters'
+ end
+ end
+end
diff --git a/spec/features/issues/user_sees_live_update_spec.rb b/spec/features/issues/user_sees_live_update_spec.rb
new file mode 100644
index 00000000000..98c7d289fb0
--- /dev/null
+++ b/spec/features/issues/user_sees_live_update_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Issues > User sees live update', :js do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:user) { project.creator }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'title issue#show' do
+ it 'updates the title' do
+ issue = create(:issue, author: user, assignees: [user], project: project, title: 'new title')
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_text("new title")
+
+ issue.update(title: "updated title")
+
+ wait_for_requests
+ expect(page).to have_text("updated title")
+ end
+ end
+
+ describe 'confidential issue#show' do
+ it 'shows confidential sibebar information as confidential and can be turned off' do
+ issue = create(:issue, :confidential, project: project)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.issuable-note-warning')
+ expect(find('.issuable-sidebar-item.confidentiality')).to have_css('.is-active')
+ expect(find('.issuable-sidebar-item.confidentiality')).not_to have_css('.not-active')
+
+ find('.confidential-edit').click
+ expect(page).to have_css('.sidebar-item-warning-message')
+
+ within('.sidebar-item-warning-message') do
+ find('.btn-close').click
+ end
+
+ wait_for_requests
+
+ visit project_issue_path(project, issue)
+
+ expect(page).not_to have_css('.is-active')
+ end
+ end
+end
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index 79938785633..66110f55435 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -3,12 +3,17 @@
require "spec_helper"
describe "User sorts issues" do
- set(:user) { create(:user) }
- set(:group) { create(:group) }
- set(:project) { create(:project_empty_repo, :public, group: group) }
- set(:issue1) { create(:issue, project: project) }
- set(:issue2) { create(:issue, project: project) }
- set(:issue3) { create(:issue, project: project) }
+ include SortingHelper
+ include IssueHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project_empty_repo, :public, group: group) }
+ let_it_be(:issue1, reload: true) { create(:issue, title: 'foo', created_at: Time.now, project: project) }
+ let_it_be(:issue2, reload: true) { create(:issue, title: 'bar', created_at: Time.now - 60, project: project) }
+ let_it_be(:issue3, reload: true) { create(:issue, title: 'baz', created_at: Time.now - 120, project: project) }
+ let_it_be(:newer_due_milestone) { create(:milestone, project: project, due_date: '2013-12-11') }
+ let_it_be(:later_due_milestone) { create(:milestone, project: project, due_date: '2013-12-12') }
before do
create_list(:award_emoji, 2, :upvote, awardable: issue1)
@@ -62,4 +67,174 @@ describe "User sorts issues" do
end
end
end
+
+ it 'sorts by newest' do
+ visit project_issues_path(project, sort: sort_value_created_date)
+
+ expect(first_issue).to include('foo')
+ expect(last_issue).to include('baz')
+ end
+
+ it 'sorts by most recently updated' do
+ issue3.updated_at = Time.now + 100
+ issue3.save
+ visit project_issues_path(project, sort: sort_value_recently_updated)
+
+ expect(first_issue).to include('baz')
+ end
+
+ describe 'sorting by due date' do
+ before do
+ issue1.update(due_date: 1.day.from_now)
+ issue2.update(due_date: 6.days.from_now)
+ end
+
+ it 'sorts by due date' do
+ visit project_issues_path(project, sort: sort_value_due_date)
+
+ expect(first_issue).to include('foo')
+ end
+
+ it 'sorts by due date by excluding nil due dates' do
+ issue2.update(due_date: nil)
+
+ visit project_issues_path(project, sort: sort_value_due_date)
+
+ expect(first_issue).to include('foo')
+ end
+
+ context 'with a filter on labels' do
+ let(:label) { create(:label, project: project) }
+
+ before do
+ create(:label_link, label: label, target: issue1)
+ end
+
+ it 'sorts by least recently due date by excluding nil due dates' do
+ issue2.update(due_date: nil)
+
+ visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later)
+
+ expect(first_issue).to include('foo')
+ end
+ end
+ end
+
+ describe 'filtering by due date' do
+ before do
+ issue1.update(due_date: 1.day.from_now)
+ issue2.update(due_date: 6.days.from_now)
+ end
+
+ it 'filters by none' do
+ visit project_issues_path(project, due_date: Issue::NoDueDate.name)
+
+ page.within '.issues-holder' do
+ expect(page).not_to have_content('foo')
+ expect(page).not_to have_content('bar')
+ expect(page).to have_content('baz')
+ end
+ end
+
+ it 'filters by any' do
+ visit project_issues_path(project, due_date: Issue::AnyDueDate.name)
+
+ page.within '.issues-holder' do
+ expect(page).to have_content('foo')
+ expect(page).to have_content('bar')
+ expect(page).to have_content('baz')
+ end
+ 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)
+
+ visit project_issues_path(project, due_date: Issue::DueThisWeek.name)
+
+ page.within '.issues-holder' do
+ expect(page).to have_content('foo')
+ expect(page).to have_content('bar')
+ expect(page).not_to have_content('baz')
+ end
+ 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)
+
+ visit project_issues_path(project, due_date: Issue::DueThisMonth.name)
+
+ page.within '.issues-holder' do
+ expect(page).to have_content('foo')
+ expect(page).to have_content('bar')
+ expect(page).not_to have_content('baz')
+ end
+ 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)
+
+ visit project_issues_path(project, due_date: Issue::Overdue.name)
+
+ page.within '.issues-holder' do
+ expect(page).not_to have_content('foo')
+ expect(page).not_to have_content('bar')
+ expect(page).to have_content('baz')
+ end
+ 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)
+
+ visit project_issues_path(project, due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name)
+
+ page.within '.issues-holder' do
+ expect(page).not_to have_content('foo')
+ expect(page).not_to have_content('bar')
+ expect(page).to have_content('baz')
+ end
+ end
+ end
+
+ describe 'sorting by milestone' do
+ before do
+ issue1.milestone = newer_due_milestone
+ issue1.save
+ issue2.milestone = later_due_milestone
+ issue2.save
+ end
+
+ it 'sorts by milestone' do
+ visit project_issues_path(project, sort: sort_value_milestone)
+
+ expect(first_issue).to include('foo')
+ expect(last_issue).to include('baz')
+ end
+ end
+
+ describe 'combine filter and sort' do
+ let(:user2) { create(:user) }
+
+ before do
+ issue1.assignees << user2
+ issue1.save
+ issue2.assignees << user2
+ issue2.save
+ end
+
+ it 'sorts with a filter applied' do
+ visit project_issues_path(project, sort: sort_value_created_date, assignee_id: user2.id)
+
+ expect(first_issue).to include('foo')
+ expect(last_issue).to include('bar')
+ expect(page).not_to have_content('baz')
+ end
+ end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
deleted file mode 100644
index ef9daf70b0c..00000000000
--- a/spec/features/issues_spec.rb
+++ /dev/null
@@ -1,828 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe 'Issues' do
- include DropzoneHelper
- include IssueHelpers
- include SortingHelper
-
- let(:user) { create(:user) }
- let(:project) { create(:project, :public) }
-
- shared_examples_for 'empty state with filters' do
- it 'user sees empty state with filters' do
- create(:issue, author: user, project: project)
-
- visit project_issues_path(project, milestone_title: "1.0")
-
- expect(page).to have_content('Sorry, your filter produced no results')
- expect(page).to have_content('To widen your search, change or remove filters above')
- end
- end
-
- describe 'while user is signed out' do
- describe 'empty state' do
- it 'user sees empty state' do
- visit project_issues_path(project)
-
- expect(page).to have_content('Register / Sign In')
- expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project.')
- expect(page).to have_content('You can register or sign in to create issues for this project.')
- end
-
- it_behaves_like 'empty state with filters'
- end
- end
-
- describe 'while user is signed in' do
- before do
- sign_in(user)
- user2 = create(:user)
-
- project.add_developer(user)
- project.add_developer(user2)
- end
-
- describe 'empty state' do
- it 'user sees empty state' do
- visit project_issues_path(project)
-
- expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project')
- expect(page).to have_content('Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.')
- expect(page).to have_content('New issue')
- end
-
- it_behaves_like 'empty state with filters'
- end
-
- describe 'Edit issue' do
- let!(:issue) do
- create(:issue,
- author: user,
- assignees: [user],
- project: project)
- end
-
- before do
- visit edit_project_issue_path(project, issue)
- find('.js-zen-enter').click
- end
-
- it 'opens new issue popup' do
- expect(page).to have_content("Issue ##{issue.iid}")
- end
- end
-
- describe 'Editing issue assignee' do
- let!(:issue) do
- create(:issue,
- author: user,
- assignees: [user],
- project: project)
- end
-
- it 'allows user to select unassigned', :js do
- visit edit_project_issue_path(project, issue)
-
- expect(page).to have_content "Assignee #{user.name}"
-
- first('.js-user-search').click
- click_link 'Unassigned'
-
- click_button 'Save changes'
-
- page.within('.assignee') do
- expect(page).to have_content 'None - assign yourself'
- end
-
- expect(issue.reload.assignees).to be_empty
- end
- end
-
- describe 'due date', :js do
- context 'on new form' do
- before do
- visit new_project_issue_path(project)
- end
-
- it 'saves with due date' do
- date = Date.today.at_beginning_of_month
-
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
- find('#issuable-due-date').click
-
- page.within '.pika-single' do
- click_button date.day
- end
-
- expect(find('#issuable-due-date').value).to eq date.to_s
-
- click_button 'Submit issue'
-
- page.within '.issuable-sidebar' do
- expect(page).to have_content date.to_s(:medium)
- end
- end
- end
-
- context 'on edit form' do
- let(:issue) { create(:issue, author: user, project: project, due_date: Date.today.at_beginning_of_month.to_s) }
-
- before do
- visit edit_project_issue_path(project, issue)
- end
-
- it 'saves with due date' do
- date = Date.today.at_beginning_of_month
-
- expect(find('#issuable-due-date').value).to eq date.to_s
-
- date = date.tomorrow
-
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
- find('#issuable-due-date').click
-
- page.within '.pika-single' do
- click_button date.day
- end
-
- expect(find('#issuable-due-date').value).to eq date.to_s
-
- click_button 'Save changes'
-
- page.within '.issuable-sidebar' do
- expect(page).to have_content date.to_s(:medium)
- end
- end
-
- it 'warns about version conflict' do
- issue.update(title: "New title")
-
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
-
- click_button 'Save changes'
-
- expect(page).to have_content 'Someone edited the issue the same time you did'
- end
- end
- end
-
- describe 'Issue info' do
- it 'links to current issue in breadcrubs' do
- issue = create(:issue, project: project)
-
- visit project_issue_path(project, issue)
-
- expect(find('.breadcrumbs-sub-title a')[:href]).to end_with(issue_path(issue))
- end
-
- it 'excludes award_emoji from comment count' do
- issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar')
- create(:award_emoji, awardable: issue)
-
- visit project_issues_path(project, assignee_id: user.id)
-
- expect(page).to have_content 'foobar'
- expect(page.all('.no-comments').first.text).to eq "0"
- end
- end
-
- describe 'Filter issue' do
- before do
- %w(foobar barbaz gitlab).each do |title|
- create(:issue,
- author: user,
- assignees: [user],
- project: project,
- title: title)
- end
-
- @issue = Issue.find_by(title: 'foobar')
- @issue.milestone = create(:milestone, project: project)
- @issue.assignees = []
- @issue.save
- end
-
- let(:issue) { @issue }
-
- it 'allows filtering by issues with no specified assignee' do
- visit project_issues_path(project, assignee_id: IssuableFinder::FILTER_NONE)
-
- expect(page).to have_content 'foobar'
- expect(page).not_to have_content 'barbaz'
- expect(page).not_to have_content 'gitlab'
- end
-
- it 'allows filtering by a specified assignee' do
- visit project_issues_path(project, assignee_id: user.id)
-
- expect(page).not_to have_content 'foobar'
- expect(page).to have_content 'barbaz'
- expect(page).to have_content 'gitlab'
- end
- end
-
- describe 'filter issue' do
- titles = %w[foo bar baz]
- titles.each_with_index do |title, index|
- let!(title.to_sym) do
- create(:issue, title: title,
- project: project,
- created_at: Time.now - (index * 60))
- end
- end
- let(:newer_due_milestone) { create(:milestone, project: project, due_date: '2013-12-11') }
- let(:later_due_milestone) { create(:milestone, project: project, due_date: '2013-12-12') }
-
- it 'sorts by newest' do
- visit project_issues_path(project, sort: sort_value_created_date)
-
- expect(first_issue).to include('foo')
- expect(last_issue).to include('baz')
- end
-
- it 'sorts by most recently updated' do
- baz.updated_at = Time.now + 100
- baz.save
- visit project_issues_path(project, sort: sort_value_recently_updated)
-
- expect(first_issue).to include('baz')
- end
-
- describe 'sorting by due date' do
- before do
- foo.update(due_date: 1.day.from_now)
- bar.update(due_date: 6.days.from_now)
- end
-
- it 'sorts by due date' do
- visit project_issues_path(project, sort: sort_value_due_date)
-
- expect(first_issue).to include('foo')
- end
-
- it 'sorts by due date by excluding nil due dates' do
- bar.update(due_date: nil)
-
- visit project_issues_path(project, sort: sort_value_due_date)
-
- expect(first_issue).to include('foo')
- end
-
- context 'with a filter on labels' do
- let(:label) { create(:label, project: project) }
-
- before do
- create(:label_link, label: label, target: foo)
- end
-
- it 'sorts by least recently due date by excluding nil due dates' do
- bar.update(due_date: nil)
-
- visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later)
-
- expect(first_issue).to include('foo')
- end
- end
- end
-
- describe 'filtering by due date' do
- before do
- foo.update(due_date: 1.day.from_now)
- bar.update(due_date: 6.days.from_now)
- end
-
- it 'filters by none' do
- visit project_issues_path(project, due_date: Issue::NoDueDate.name)
-
- page.within '.issues-holder' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
-
- it 'filters by any' do
- visit project_issues_path(project, due_date: Issue::AnyDueDate.name)
-
- page.within '.issues-holder' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
-
- it 'filters by due this week' do
- foo.update(due_date: Date.today.beginning_of_week + 2.days)
- bar.update(due_date: Date.today.end_of_week)
- baz.update(due_date: Date.today - 8.days)
-
- visit project_issues_path(project, due_date: Issue::DueThisWeek.name)
-
- page.within '.issues-holder' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).not_to have_content('baz')
- end
- end
-
- it 'filters by due this month' do
- foo.update(due_date: Date.today.beginning_of_month + 2.days)
- bar.update(due_date: Date.today.end_of_month)
- baz.update(due_date: Date.today - 50.days)
-
- visit project_issues_path(project, due_date: Issue::DueThisMonth.name)
-
- page.within '.issues-holder' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).not_to have_content('baz')
- end
- end
-
- it 'filters by overdue' do
- foo.update(due_date: Date.today + 2.days)
- bar.update(due_date: Date.today + 20.days)
- baz.update(due_date: Date.yesterday)
-
- visit project_issues_path(project, due_date: Issue::Overdue.name)
-
- page.within '.issues-holder' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
-
- it 'filters by due next month and previous two weeks' do
- foo.update(due_date: Date.today - 4.weeks)
- bar.update(due_date: (Date.today + 2.months).beginning_of_month)
- baz.update(due_date: Date.yesterday)
-
- visit project_issues_path(project, due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name)
-
- page.within '.issues-holder' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
- end
- end
- end
-
- describe 'sorting by milestone' do
- before do
- foo.milestone = newer_due_milestone
- foo.save
- bar.milestone = later_due_milestone
- bar.save
- end
-
- it 'sorts by milestone' do
- visit project_issues_path(project, sort: sort_value_milestone)
-
- expect(first_issue).to include('foo')
- expect(last_issue).to include('baz')
- end
- end
-
- describe 'combine filter and sort' do
- let(:user2) { create(:user) }
-
- before do
- foo.assignees << user2
- foo.save
- bar.assignees << user2
- bar.save
- end
-
- it 'sorts with a filter applied' do
- visit project_issues_path(project, sort: sort_value_created_date, assignee_id: user2.id)
-
- expect(first_issue).to include('foo')
- expect(last_issue).to include('bar')
- expect(page).not_to have_content('baz')
- end
- end
- end
-
- describe 'when I want to reset my incoming email token' do
- let(:project1) { create(:project, namespace: user.namespace) }
- let!(:issue) { create(:issue, project: project1) }
-
- before do
- stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
- project1.add_maintainer(user)
- visit namespace_project_issues_path(user.namespace, project1)
- end
-
- it 'changes incoming email address token', :js do
- find('.issuable-email-modal-btn').click
- previous_token = find('input#issuable_email').value
- find('.incoming-email-token-reset').click
-
- wait_for_requests
-
- expect(page).to have_no_field('issuable_email', with: previous_token)
- new_token = project1.new_issuable_address(user.reload, 'issue')
- expect(page).to have_field(
- 'issuable_email',
- with: new_token
- )
- end
- end
-
- describe 'update labels from issue#show', :js do
- let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
- let!(:label) { create(:label, project: project) }
-
- before do
- visit project_issue_path(project, issue)
- end
-
- it 'will not send ajax request when no data is changed' do
- page.within '.labels' do
- click_link 'Edit'
-
- find('.dropdown-menu-close', match: :first).click
-
- expect(page).not_to have_selector('.block-loading')
- end
- end
- end
-
- describe 'update assignee from issue#show' do
- let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
-
- context 'by authorized user' do
- it 'allows user to select unassigned', :js do
- visit project_issue_path(project, issue)
-
- 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'
- end
-
- wait_for_requests
-
- expect(issue.reload.assignees).to be_empty
- end
-
- it 'allows user to select an assignee', :js do
- issue2 = create(:issue, project: project, author: user)
- visit project_issue_path(project, issue2)
-
- 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
-
- it 'allows user to unselect themselves', :js do
- issue2 = create(:issue, project: project, author: user)
-
- visit project_issue_path(project, issue2)
-
- 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
- click_link 'Edit'
- click_link user.name
-
- close_dropdown_menu_if_visible
-
- page.within '.value .author' do
- expect(page).to have_content user.name
- end
-
- 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) }
-
- before do
- project.add_guest(guest)
- end
-
- it 'shows assignee text', :js 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
-
- describe 'update milestone from issue#show' do
- let!(:issue) { create(:issue, project: project, author: user) }
- let!(:milestone) { create(:milestone, project: project) }
-
- context 'by authorized user' do
- it 'allows user to select unassigned', :js do
- visit project_issue_path(project, issue)
-
- page.within('.milestone') do
- expect(page).to have_content "None"
- end
-
- find('.block.milestone .edit-link').click
- sleep 2 # wait for ajax stuff to complete
- first('.dropdown-content li').click
- sleep 2
- page.within('.milestone') do
- expect(page).to have_content 'None'
- end
-
- expect(issue.reload.milestone).to be_nil
- end
-
- it 'allows user to de-select milestone', :js do
- visit project_issue_path(project, issue)
-
- page.within('.milestone') do
- click_link 'Edit'
- click_link milestone.title
-
- page.within '.value' do
- expect(page).to have_content milestone.title
- end
-
- click_link 'Edit'
- click_link milestone.title
-
- page.within '.value' do
- expect(page).to have_content 'None'
- end
- end
- end
- end
-
- context 'by unauthorized user' do
- let(:guest) { create(:user) }
-
- before do
- project.add_guest(guest)
- issue.milestone = milestone
- issue.save
- end
-
- it 'shows milestone text', :js do
- sign_out(:user)
- sign_in(guest)
-
- visit project_issue_path(project, issue)
- expect(page).to have_content milestone.title
- end
- end
- end
-
- describe 'new issue' do
- let!(:issue) { create(:issue, project: project) }
-
- context 'by unauthenticated user' do
- before do
- sign_out(:user)
- end
-
- it 'redirects to signin then back to new issue after signin' do
- visit project_issues_path(project)
-
- page.within '.nav-controls' do
- click_link 'New issue'
- end
-
- expect(current_path).to eq new_user_session_path
-
- gitlab_sign_in(create(:user))
-
- expect(current_path).to eq new_project_issue_path(project)
- end
- end
-
- it 'clears local storage after creating a new issue', :js do
- 2.times do
- visit new_project_issue_path(project)
- wait_for_requests
-
- expect(page).to have_field('Title', with: '')
-
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
-
- click_button 'Submit issue'
- end
- end
-
- context 'dropzone upload file', :js do
- before do
- visit new_project_issue_path(project)
- end
-
- it 'uploads file when dragging into textarea' do
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
-
- expect(page.find_field("issue_description").value).to have_content 'banana_sample'
- end
-
- it "doesn't add double newline to end of a single attachment markdown" do
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
-
- expect(page.find_field("issue_description").value).not_to match /\n\n$/
- end
-
- it "cancels a file upload correctly" do
- slow_requests do
- dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
-
- click_button 'Cancel'
- end
-
- expect(page).to have_button('Attach a file')
- expect(page).not_to have_button('Cancel')
- expect(page).not_to have_selector('.uploading-progress-container', visible: true)
- end
- end
-
- context 'form filled by URL parameters' do
- let(:project) { create(:project, :public, :repository) }
-
- before do
- project.repository.create_file(
- user,
- '.gitlab/issue_templates/bug.md',
- 'this is a test "bug" template',
- message: 'added issue template',
- branch_name: 'master')
-
- visit new_project_issue_path(project, issuable_template: 'bug')
- end
-
- it 'fills in template' do
- expect(find('.js-issuable-selector .dropdown-toggle-text')).to have_content('bug')
- end
- end
-
- context 'suggestions', :js do
- it 'displays list of related issues' do
- create(:issue, project: project, title: 'test issue')
-
- visit new_project_issue_path(project)
-
- fill_in 'issue_title', with: issue.title
-
- expect(page).to have_selector('.suggestion-item', count: 1)
- end
- end
- end
-
- describe 'new issue by email' do
- shared_examples 'show the email in the modal' do
- let(:issue) { create(:issue, project: project) }
-
- before do
- project.issues << issue
- stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
-
- visit project_issues_path(project)
- click_button('Email a new issue')
- end
-
- it 'click the button to show modal for the new email' do
- page.within '#issuable-email-modal' do
- email = project.new_issuable_address(user, 'issue')
-
- expect(page).to have_selector("input[value='#{email}']")
- end
- end
- end
-
- context 'with existing issues' do
- let!(:issue) { create(:issue, project: project, author: user) }
-
- it_behaves_like 'show the email in the modal'
- end
-
- context 'without existing issues' do
- it_behaves_like 'show the email in the modal'
- end
- end
-
- describe 'due date' do
- context 'update due on issue#show', :js do
- let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
-
- before do
- visit project_issue_path(project, issue)
- end
-
- 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 '.pika-single' do
- click_button date.day
- end
-
- wait_for_requests
-
- expect(find('.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 '.pika-single' do
- click_button date.day
- end
-
- wait_for_requests
-
- expect(page).to have_no_content 'None'
-
- click_link 'remove due date'
- expect(page).to have_content 'None'
- end
- end
- end
- end
-
- describe 'title issue#show', :js do
- it 'updates the title', :js do
- issue = create(:issue, author: user, assignees: [user], project: project, title: 'new title')
-
- visit project_issue_path(project, issue)
-
- expect(page).to have_text("new title")
-
- issue.update(title: "updated title")
-
- wait_for_requests
- expect(page).to have_text("updated title")
- end
- end
-
- describe 'confidential issue#show', :js do
- it 'shows confidential sibebar information as confidential and can be turned off' do
- issue = create(:issue, :confidential, project: project)
-
- visit project_issue_path(project, issue)
-
- expect(page).to have_css('.issuable-note-warning')
- expect(find('.issuable-sidebar-item.confidentiality')).to have_css('.is-active')
- expect(find('.issuable-sidebar-item.confidentiality')).not_to have_css('.not-active')
-
- find('.confidential-edit').click
- expect(page).to have_css('.sidebar-item-warning-message')
-
- within('.sidebar-item-warning-message') do
- find('.btn-close').click
- end
-
- wait_for_requests
-
- visit project_issue_path(project, issue)
-
- expect(page).not_to have_css('.is-active')
- end
- end
- end
-end
diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb
index b7a45905845..c1a2e22a0c2 100644
--- a/spec/features/labels_hierarchy_spec.rb
+++ b/spec/features/labels_hierarchy_spec.rb
@@ -70,7 +70,7 @@ describe 'Labels Hierarchy', :js do
end
it 'does not filter by descendant group labels' do
- filtered_search.set("label:")
+ filtered_search.set("label=")
wait_for_requests
@@ -134,7 +134,7 @@ describe 'Labels Hierarchy', :js do
end
it 'does not filter by descendant group project labels' do
- filtered_search.set("label:")
+ filtered_search.set("label=")
wait_for_requests
@@ -227,7 +227,7 @@ describe 'Labels Hierarchy', :js do
it_behaves_like 'filtering by ancestor labels for projects'
it 'does not filter by descendant group labels' do
- filtered_search.set("label:")
+ filtered_search.set("label=")
wait_for_requests
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index a45fa67ce9e..9ebd85acb81 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -208,6 +208,8 @@ describe 'GitLab Markdown', :aggregate_failures do
@group = @feat.group
end
+ let(:project) { @feat.project } # Shadow this so matchers can use it
+
context 'default pipeline' do
before do
@html = markdown(@feat.raw_markdown)
@@ -216,8 +218,12 @@ describe 'GitLab Markdown', :aggregate_failures do
it_behaves_like 'all pipelines'
it 'includes custom filters' do
- aggregate_failures 'RelativeLinkFilter' do
- expect(doc).to parse_relative_links
+ aggregate_failures 'UploadLinkFilter' do
+ expect(doc).to parse_upload_links
+ end
+
+ aggregate_failures 'RepositoryLinkFilter' do
+ expect(doc).to parse_repository_links
end
aggregate_failures 'EmojiFilter' do
@@ -277,8 +283,12 @@ describe 'GitLab Markdown', :aggregate_failures do
it_behaves_like 'all pipelines'
it 'includes custom filters' do
- aggregate_failures 'RelativeLinkFilter' do
- expect(doc).not_to parse_relative_links
+ aggregate_failures 'UploadLinkFilter' do
+ expect(doc).to parse_upload_links
+ end
+
+ aggregate_failures 'RepositoryLinkFilter' do
+ expect(doc).not_to parse_repository_links
end
aggregate_failures 'EmojiFilter' do
diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb
index 4e161d530d3..4f2c5fc73d8 100644
--- a/spec/features/merge_request/maintainer_edits_fork_spec.rb
+++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb
@@ -32,8 +32,6 @@ describe 'a maintainer edits files on a source-branch of an MR from a fork', :js
wait_for_requests
end
- it_behaves_like 'rendering a single diff version'
-
it 'mentions commits will go to the source branch' do
expect(page).to have_content('Your changes can be committed to fix because a merge request is open.')
end
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index 6a23b6cdf60..19b8a7f74b7 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -13,15 +13,12 @@ describe 'User comments on a diff', :js do
let(:user) { create(:user) }
before do
- stub_feature_flags(single_mr_diff_view: false)
project.add_maintainer(user)
sign_in(user)
visit(diffs_project_merge_request_path(project, merge_request))
end
- it_behaves_like 'rendering a single diff version'
-
context 'when viewing comments' do
context 'when toggling inline comments' do
context 'in a single file' do
diff --git a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
index e6634a8ff39..e0724a04ea3 100644
--- a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
@@ -9,7 +9,6 @@ describe 'Merge request > User creates image diff notes', :js do
let(:user) { project.creator }
before do
- stub_feature_flags(single_mr_diff_view: false)
sign_in(user)
# Stub helper to return any blob file as image from public app folder.
@@ -18,8 +17,6 @@ describe 'Merge request > User creates image diff notes', :js do
allow_any_instance_of(DiffHelper).to receive(:diff_file_old_blob_raw_url).and_return('/favicon.png')
end
- it_behaves_like 'rendering a single diff version'
-
context 'create commit diff notes' do
commit_id = '2f63565e7aac07bcdadb654e253078b727143ec4'
diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb
index 9b040271468..9bce5264817 100644
--- a/spec/features/merge_request/user_expands_diff_spec.rb
+++ b/spec/features/merge_request/user_expands_diff_spec.rb
@@ -7,7 +7,6 @@ describe 'User expands diff', :js do
let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) }
before do
- stub_feature_flags(single_mr_diff_view: false)
stub_feature_flags(diffs_batch_load: false)
allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
@@ -18,8 +17,6 @@ describe 'User expands diff', :js do
wait_for_requests
end
- it_behaves_like 'rendering a single diff version'
-
it 'allows user to expand diff' do
page.within find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9"]') do
click_link 'Click to expand it.'
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index 6328c0a5133..8b16760606c 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -14,15 +14,12 @@ describe 'Merge request > User posts diff notes', :js do
let(:test_note_comment) { 'this is a test note!' }
before do
- stub_feature_flags(single_mr_diff_view: false)
set_cookie('sidebar_collapsed', 'true')
project.add_developer(user)
sign_in(user)
end
- it_behaves_like 'rendering a single diff version'
-
context 'when hovering over a parallel view diff file' do
before do
visit diffs_project_merge_request_path(project, merge_request, view: 'parallel')
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index c0655581b18..f24e7090605 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -165,9 +165,9 @@ 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 eq('This is the new content')
+ expect(find('#note_note').value).to include('This is the new content')
first('.js-md').click
- expect(find('#note_note').value).to eq('This is the new content****')
+ expect(find('#note_note').value).to include('This is the new content****')
end
end
diff --git a/spec/features/merge_request/user_resolves_conflicts_spec.rb b/spec/features/merge_request/user_resolves_conflicts_spec.rb
index f0949fefa3b..ce85e81868d 100644
--- a/spec/features/merge_request/user_resolves_conflicts_spec.rb
+++ b/spec/features/merge_request/user_resolves_conflicts_spec.rb
@@ -9,7 +9,6 @@ describe 'Merge request > User resolves conflicts', :js do
before do
# In order to have the diffs collapsed, we need to disable the increase feature
stub_feature_flags(gitlab_git_diff_size_limit_increase: false)
- stub_feature_flags(single_mr_diff_view: false)
end
def create_merge_request(source_branch)
@@ -18,8 +17,6 @@ describe 'Merge request > User resolves conflicts', :js do
end
end
- it_behaves_like 'rendering a single diff version'
-
shared_examples 'conflicts are resolved in Interactive mode' do
it 'conflicts are resolved in Interactive mode' do
within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') 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 9cbea8a8466..eb86b1e33af 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
@@ -20,12 +20,9 @@ describe 'Merge request > User resolves diff notes and threads', :js do
end
before do
- stub_feature_flags(single_mr_diff_view: false)
stub_feature_flags(diffs_batch_load: false)
end
- it_behaves_like 'rendering a single diff version'
-
context 'no threads' do
before do
project.add_maintainer(user)
diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
index 70afe056c64..3e77b9e75d6 100644
--- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
@@ -21,7 +21,6 @@ describe 'Merge request > User sees avatars on diff notes', :js do
let!(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position) }
before do
- stub_feature_flags(single_mr_diff_view: false)
stub_feature_flags(diffs_batch_load: false)
project.add_maintainer(user)
sign_in user
@@ -29,8 +28,6 @@ describe 'Merge request > User sees avatars on diff notes', :js do
set_cookie('sidebar_collapsed', 'true')
end
- it_behaves_like 'rendering a single diff version'
-
context 'discussion tab' do
before do
visit project_merge_request_path(project, merge_request)
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index 3743ef0f25d..99c9e9dc501 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -33,10 +33,10 @@ describe 'Merge request > User sees deployment widget', :js do
end
context 'when a user created a new merge request with the same SHA' do
- let(:pipeline2) { create(:ci_pipeline, sha: sha, project: project, ref: 'new-patch-1') }
+ let(:pipeline2) { create(:ci_pipeline, sha: sha, project: project, ref: 'video') }
let(:build2) { create(:ci_build, :success, pipeline: pipeline2) }
let(:environment2) { create(:environment, project: project) }
- let!(:deployment2) { create(:deployment, environment: environment2, sha: sha, ref: 'new-patch-1', deployable: build2) }
+ let!(:deployment2) { create(:deployment, environment: environment2, sha: sha, ref: 'video', deployable: build2) }
it 'displays one environment which is related to the pipeline' do
visit project_merge_request_path(project, merge_request)
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index de142344c26..2d91d09a486 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -10,12 +10,9 @@ describe 'Merge request > User sees diff', :js do
let(:merge_request) { create(:merge_request, source_project: project) }
before do
- stub_feature_flags(single_mr_diff_view: false)
stub_feature_flags(diffs_batch_load: false)
end
- it_behaves_like 'rendering a single diff version'
-
context 'when linking to note' do
describe 'with unresolved note' do
let(:note) { create :diff_note_on_merge_request, project: project, noteable: merge_request }
diff --git a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
index e28d2ca5536..59e5f5c847d 100644
--- a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
+++ b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb
@@ -11,14 +11,11 @@ describe 'Merge request > User sees MR with deleted source branch', :js do
let(:user) { project.creator }
before do
- stub_feature_flags(single_mr_diff_view: false)
merge_request.update!(source_branch: 'this-branch-does-not-exist')
sign_in(user)
visit project_merge_request_path(project, merge_request)
end
- it_behaves_like 'rendering a single diff version'
-
it 'shows a message about missing source branch' do
expect(page).to have_content('Source branch does not exist.')
end
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index b3aef601c7b..cd62bab412a 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -16,7 +16,6 @@ describe 'Merge request > User sees versions', :js do
let!(:params) { {} }
before do
- stub_feature_flags(single_mr_diff_view: false)
stub_feature_flags(diffs_batch_load: false)
project.add_maintainer(user)
@@ -24,8 +23,6 @@ describe 'Merge request > User sees versions', :js do
visit diffs_project_merge_request_path(project, merge_request, params)
end
- it_behaves_like 'rendering a single diff version'
-
shared_examples 'allows commenting' do |file_id:, line_code:, comment:|
it do
diff_file_selector = ".diff-file[id='#{file_id}']"
@@ -53,7 +50,7 @@ describe 'Merge request > User sees versions', :js do
expect(page).to have_content 'latest version'
end
- expect(page).to have_content '8 Files'
+ expect(page).to have_content '8 files'
end
it_behaves_like 'allows commenting',
@@ -87,7 +84,7 @@ describe 'Merge request > User sees versions', :js do
end
it 'shows comments that were last relevant at that version' do
- expect(page).to have_content '5 Files'
+ expect(page).to have_content '5 files'
position = Gitlab::Diff::Position.new(
old_path: ".gitmodules",
@@ -131,12 +128,10 @@ describe 'Merge request > User sees versions', :js do
diff_id: merge_request_diff3.id,
start_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9'
)
- expect(page).to have_content '4 Files'
+ expect(page).to have_content '4 files'
- additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-addition')
- .ancestor('.diff-stats-group').text
- deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-deletion')
- .ancestor('.diff-stats-group').text
+ additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-addition-line').text
+ deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-deletion-line').text
expect(additions_content).to eq '15'
expect(deletions_content).to eq '6'
@@ -159,12 +154,10 @@ describe 'Merge request > User sees versions', :js do
end
it 'show diff between new and old version' do
- additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-addition')
- .ancestor('.diff-stats-group').text
- deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-deletion')
- .ancestor('.diff-stats-group').text
+ additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-addition-line').text
+ deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-deletion-line').text
- expect(page).to have_content '4 Files'
+ expect(page).to have_content '4 files'
expect(additions_content).to eq '15'
expect(deletions_content).to eq '6'
end
@@ -174,7 +167,7 @@ describe 'Merge request > User sees versions', :js do
page.within '.mr-version-dropdown' do
expect(page).to have_content 'latest version'
end
- expect(page).to have_content '8 Files'
+ expect(page).to have_content '8 files'
end
it_behaves_like 'allows commenting',
@@ -200,7 +193,7 @@ describe 'Merge request > User sees versions', :js do
find('.btn-default').click
click_link 'version 1'
end
- expect(page).to have_content '0 Files'
+ expect(page).to have_content '0 files'
end
end
@@ -226,7 +219,7 @@ describe 'Merge request > User sees versions', :js do
expect(page).to have_content 'version 1'
end
- expect(page).to have_content '0 Files'
+ expect(page).to have_content '0 files'
end
end
diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
index 7fe72e1bc8a..95cb0a2dee3 100644
--- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
+++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
@@ -25,15 +25,12 @@ describe 'User comments on a diff', :js do
let(:user) { create(:user) }
before do
- stub_feature_flags(single_mr_diff_view: false)
project.add_maintainer(user)
sign_in(user)
visit(diffs_project_merge_request_path(project, merge_request))
end
- it_behaves_like 'rendering a single diff version'
-
context 'single suggestion note' do
it 'hides suggestion popover' do
click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
@@ -97,8 +94,7 @@ describe 'User comments on a diff', :js do
end
context 'multiple suggestions in expanded lines' do
- # Report issue: https://gitlab.com/gitlab-org/gitlab/issues/38277
- # Fix issue: https://gitlab.com/gitlab-org/gitlab/issues/39095
+ # https://gitlab.com/gitlab-org/gitlab/issues/38277
it 'suggestions are appliable', :quarantine do
diff_file = merge_request.diffs(paths: ['files/ruby/popen.rb']).diff_files.first
hash = Digest::SHA1.hexdigest(diff_file.file_path)
diff --git a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb
index 5e59bc87e68..4db067a4e41 100644
--- a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb
+++ b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb
@@ -8,7 +8,6 @@ describe 'Merge request > User toggles whitespace changes', :js do
let(:user) { project.creator }
before do
- stub_feature_flags(single_mr_diff_view: false)
project.add_maintainer(user)
sign_in(user)
visit diffs_project_merge_request_path(project, merge_request)
@@ -16,8 +15,6 @@ describe 'Merge request > User toggles whitespace changes', :js do
find('.js-show-diff-settings').click
end
- it_behaves_like 'rendering a single diff version'
-
it 'has a button to toggle whitespace changes' do
expect(page).to have_content 'Show whitespace changes'
end
diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb
index 313f438e23b..e0e4058dd47 100644
--- a/spec/features/merge_request/user_views_diffs_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_spec.rb
@@ -9,7 +9,6 @@ describe 'User views diffs', :js do
let(:project) { create(:project, :public, :repository) }
before do
- stub_feature_flags(single_mr_diff_view: false)
stub_feature_flags(diffs_batch_load: false)
visit(diffs_project_merge_request_path(project, merge_request))
@@ -18,8 +17,6 @@ describe 'User views diffs', :js do
find('.js-toggle-tree-list').click
end
- it_behaves_like 'rendering a single diff version'
-
shared_examples 'unfold diffs' do
it 'unfolds diffs upwards' do
first('.js-unfold').click
diff --git a/spec/features/merge_requests/filters_generic_behavior_spec.rb b/spec/features/merge_requests/filters_generic_behavior_spec.rb
index 58aad1b7e91..c3400acae4f 100644
--- a/spec/features/merge_requests/filters_generic_behavior_spec.rb
+++ b/spec/features/merge_requests/filters_generic_behavior_spec.rb
@@ -23,7 +23,7 @@ describe 'Merge Requests > Filters generic behavior', :js do
context 'when filtered by a label' do
before do
- input_filtered_search('label:~bug')
+ input_filtered_search('label=~bug')
end
describe 'state tabs' do
diff --git a/spec/features/merge_requests/user_filters_by_assignees_spec.rb b/spec/features/merge_requests/user_filters_by_assignees_spec.rb
index 00bd8455ae1..3abee3b656a 100644
--- a/spec/features/merge_requests/user_filters_by_assignees_spec.rb
+++ b/spec/features/merge_requests/user_filters_by_assignees_spec.rb
@@ -18,7 +18,7 @@ describe 'Merge Requests > User filters by assignees', :js do
context 'filtering by assignee:none' do
it 'applies the filter' do
- input_filtered_search('assignee:none')
+ input_filtered_search('assignee=none')
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).not_to have_content 'Bugfix1'
@@ -26,9 +26,9 @@ describe 'Merge Requests > User filters by assignees', :js do
end
end
- context 'filtering by assignee:@username' do
+ context 'filtering by assignee=@username' do
it 'applies the filter' do
- input_filtered_search("assignee:@#{user.username}")
+ input_filtered_search("assignee=@#{user.username}")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_content 'Bugfix1'
diff --git a/spec/features/merge_requests/user_filters_by_labels_spec.rb b/spec/features/merge_requests/user_filters_by_labels_spec.rb
index fd2b4b23f96..7a80ebe9be3 100644
--- a/spec/features/merge_requests/user_filters_by_labels_spec.rb
+++ b/spec/features/merge_requests/user_filters_by_labels_spec.rb
@@ -22,7 +22,7 @@ describe 'Merge Requests > User filters by labels', :js do
context 'filtering by label:none' do
it 'applies the filter' do
- input_filtered_search('label:none')
+ input_filtered_search('label=none')
expect(page).to have_issuable_counts(open: 0, closed: 0, all: 0)
expect(page).not_to have_content 'Bugfix1'
@@ -32,7 +32,7 @@ describe 'Merge Requests > User filters by labels', :js do
context 'filtering by label:~enhancement' do
it 'applies the filter' do
- input_filtered_search('label:~enhancement')
+ input_filtered_search('label=~enhancement')
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_content 'Bugfix2'
@@ -42,7 +42,7 @@ describe 'Merge Requests > User filters by labels', :js do
context 'filtering by label:~enhancement and label:~bug' do
it 'applies the filters' do
- input_filtered_search('label:~bug label:~enhancement')
+ input_filtered_search('label=~bug label=~enhancement')
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_content 'Bugfix2'
diff --git a/spec/features/merge_requests/user_filters_by_milestones_spec.rb b/spec/features/merge_requests/user_filters_by_milestones_spec.rb
index e0ee69d7a5b..8cb686e191e 100644
--- a/spec/features/merge_requests/user_filters_by_milestones_spec.rb
+++ b/spec/features/merge_requests/user_filters_by_milestones_spec.rb
@@ -18,14 +18,14 @@ describe 'Merge Requests > User filters by milestones', :js do
end
it 'filters by no milestone' do
- input_filtered_search('milestone:none')
+ input_filtered_search('milestone=none')
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_css('.merge-request', count: 1)
end
it 'filters by a specific milestone' do
- input_filtered_search("milestone:%'#{milestone.title}'")
+ input_filtered_search("milestone=%'#{milestone.title}'")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_css('.merge-request', count: 1)
@@ -33,7 +33,7 @@ describe 'Merge Requests > User filters by milestones', :js do
describe 'filters by upcoming milestone' do
it 'does not show merge requests with no expiry' do
- input_filtered_search('milestone:upcoming')
+ input_filtered_search('milestone=upcoming')
expect(page).to have_issuable_counts(open: 0, closed: 0, all: 0)
expect(page).to have_css('.merge-request', count: 0)
@@ -43,7 +43,7 @@ describe 'Merge Requests > User filters by milestones', :js do
let(:milestone) { create(:milestone, project: project, due_date: Date.tomorrow) }
it 'shows merge requests' do
- input_filtered_search('milestone:upcoming')
+ input_filtered_search('milestone=upcoming')
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_css('.merge-request', count: 1)
@@ -54,7 +54,7 @@ describe 'Merge Requests > User filters by milestones', :js do
let(:milestone) { create(:milestone, project: project, due_date: Date.yesterday) }
it 'does not show any merge requests' do
- input_filtered_search('milestone:upcoming')
+ input_filtered_search('milestone=upcoming')
expect(page).to have_issuable_counts(open: 0, closed: 0, all: 0)
expect(page).to have_css('.merge-request', count: 0)
diff --git a/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb b/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb
index bc6e2ac5132..5c9d53778d2 100644
--- a/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb
+++ b/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb
@@ -20,7 +20,7 @@ describe 'Merge requests > User filters by multiple criteria', :js do
describe 'filtering by label:~"Won\'t fix" and assignee:~bug' do
it 'applies the filters' do
- input_filtered_search("label:~\"Won't fix\" assignee:@#{user.username}")
+ input_filtered_search("label=~\"Won't fix\" assignee=@#{user.username}")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_content 'Bugfix2'
@@ -30,7 +30,7 @@ describe 'Merge requests > User filters by multiple criteria', :js do
describe 'filtering by text, author, assignee, milestone, and label' do
it 'filters by text, author, assignee, milestone, and label' do
- input_filtered_search_keys("author:@#{user.username} assignee:@#{user.username} milestone:%\"v1.1\" label:~\"Won't fix\" Bug")
+ input_filtered_search_keys("author=@#{user.username} assignee=@#{user.username} milestone=%\"v1.1\" label=~\"Won't fix\" Bug")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_content 'Bugfix2'
diff --git a/spec/features/merge_requests/user_filters_by_target_branch_spec.rb b/spec/features/merge_requests/user_filters_by_target_branch_spec.rb
index 0d03c5eae31..faff7de729d 100644
--- a/spec/features/merge_requests/user_filters_by_target_branch_spec.rb
+++ b/spec/features/merge_requests/user_filters_by_target_branch_spec.rb
@@ -17,7 +17,7 @@ describe 'Merge Requests > User filters by target branch', :js do
context 'filtering by target-branch:master' do
it 'applies the filter' do
- input_filtered_search('target-branch:master')
+ input_filtered_search('target-branch=master')
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_content mr1.title
@@ -27,7 +27,7 @@ describe 'Merge Requests > User filters by target branch', :js do
context 'filtering by target-branch:merged-target' do
it 'applies the filter' do
- input_filtered_search('target-branch:merged-target')
+ input_filtered_search('target-branch=merged-target')
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).not_to have_content mr1.title
@@ -37,7 +37,7 @@ describe 'Merge Requests > User filters by target branch', :js do
context 'filtering by target-branch:feature' do
it 'applies the filter' do
- input_filtered_search('target-branch:feature')
+ input_filtered_search('target-branch=feature')
expect(page).to have_issuable_counts(open: 0, closed: 0, all: 0)
expect(page).not_to have_content mr1.title
diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb
index a5c2d15f598..bab6251a5d4 100644
--- a/spec/features/profiles/active_sessions_spec.rb
+++ b/spec/features/profiles/active_sessions_spec.rb
@@ -84,4 +84,31 @@ describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do
expect(page).not_to have_content('Chrome on Windows')
end
end
+
+ it 'User can revoke a session', :js, :redis_session_store do
+ Capybara::Session.new(:session1)
+ Capybara::Session.new(:session2)
+
+ # set an additional session in another browser
+ using_session :session2 do
+ gitlab_sign_in(user)
+ end
+
+ using_session :session1 do
+ gitlab_sign_in(user)
+ visit profile_active_sessions_path
+
+ expect(page).to have_link('Revoke', count: 1)
+
+ accept_confirm { click_on 'Revoke' }
+
+ expect(page).not_to have_link('Revoke')
+ end
+
+ using_session :session2 do
+ visit profile_active_sessions_path
+
+ expect(page).to have_content('You need to sign in or sign up before continuing.')
+ end
+ end
end
diff --git a/spec/features/profiles/user_visits_profile_preferences_page_spec.rb b/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
index 4dbdea02e27..b18f763a968 100644
--- a/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
+++ b/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
@@ -86,6 +86,23 @@ describe 'User visits the profile preferences page' do
end
end
+ describe 'User changes whitespace in code' do
+ it 'updates their preference' do
+ expect(user.render_whitespace_in_code).to be(false)
+ expect(render_whitespace_field).not_to be_checked
+ render_whitespace_field.click
+
+ click_button 'Save changes'
+
+ expect(user.reload.render_whitespace_in_code).to be(true)
+ expect(render_whitespace_field).to be_checked
+ end
+ end
+
+ def render_whitespace_field
+ find_field('user[render_whitespace_in_code]')
+ end
+
def expect_preferences_saved_message
page.within('.flash-container') do
expect(page).to have_content('Preferences saved.')
diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb
index 46aa104fdd7..dd51eac9be1 100644
--- a/spec/features/projects/badges/coverage_spec.rb
+++ b/spec/features/projects/badges/coverage_spec.rb
@@ -63,7 +63,7 @@ describe 'test coverage badge' do
create(:ci_pipeline, opts).tap do |pipeline|
yield pipeline
- pipeline.update_status
+ pipeline.update_legacy_status
end
end
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index 0a5bc64b429..a1d6a8896c7 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -12,11 +12,9 @@ describe 'Editing file blob', :js do
let(:readme_file_path) { 'README.md' }
before do
- stub_feature_flags(web_ide_default: false, single_mr_diff_view: false)
+ stub_feature_flags(web_ide_default: false)
end
- it_behaves_like 'rendering a single diff version'
-
context 'as a developer' do
let(:user) { create(:user) }
let(:role) { :developer }
diff --git a/spec/features/projects/environments/environment_metrics_spec.rb b/spec/features/projects/environments/environment_metrics_spec.rb
index c027b776d67..d34db5e15cc 100644
--- a/spec/features/projects/environments/environment_metrics_spec.rb
+++ b/spec/features/projects/environments/environment_metrics_spec.rb
@@ -6,7 +6,7 @@ describe 'Environment > Metrics' do
include PrometheusHelpers
let(:user) { create(:user) }
- let(:project) { create(:prometheus_project) }
+ let(:project) { create(:prometheus_project, :repository) }
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:environment) { create(:environment, project: project) }
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 3eab13cb820..bbd33225bb9 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe 'Environment' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
let(:role) { :developer }
@@ -12,11 +12,16 @@ describe 'Environment' do
project.add_role(user, role)
end
+ def auto_stop_button_selector
+ %q{button[title="Prevent environment from auto-stopping"]}
+ end
+
describe 'environment details page' do
let!(:environment) { create(:environment, project: project) }
let!(:permissions) { }
let!(:deployment) { }
let!(:action) { }
+ let!(:cluster) { }
before do
visit_environment(environment)
@@ -26,6 +31,40 @@ describe 'Environment' do
expect(page).to have_content(environment.name)
end
+ context 'without auto-stop' do
+ it 'does not show auto-stop text' do
+ expect(page).not_to have_content('Auto stops')
+ end
+
+ it 'does not show auto-stop button' do
+ expect(page).not_to have_selector(auto_stop_button_selector)
+ end
+ end
+
+ context 'with auto-stop' do
+ let!(:environment) { create(:environment, :will_auto_stop, name: 'staging', project: project) }
+
+ before do
+ visit_environment(environment)
+ end
+
+ it 'shows auto stop info' do
+ expect(page).to have_content('Auto stops')
+ end
+
+ it 'shows auto stop button' do
+ expect(page).to have_selector(auto_stop_button_selector)
+ expect(page.find(auto_stop_button_selector).find(:xpath, '..')['action']).to have_content(cancel_auto_stop_project_environment_path(environment.project, environment))
+ end
+
+ it 'allows user to cancel auto stop', :js do
+ page.find(auto_stop_button_selector).click
+ wait_for_all_requests
+ expect(page).to have_content('Auto stop successfully canceled.')
+ expect(page).not_to have_selector(auto_stop_button_selector)
+ end
+ end
+
context 'without deployments' do
it 'does not show deployments' do
expect(page).to have_content('You don\'t have any deployments right now.')
@@ -94,19 +133,10 @@ describe 'Environment' do
it 'does show build name' do
expect(page).to have_link("#{build.name} (##{build.id})")
- expect(page).not_to have_link('Re-deploy')
- expect(page).not_to have_terminal_button
end
- context 'when user has ability to re-deploy' do
- let(:permissions) do
- create(:protected_branch, :developers_can_merge,
- name: build.ref, project: project)
- end
-
- it 'does show re-deploy' do
- expect(page).to have_link('Re-deploy')
- end
+ it 'shows the re-deploy button' do
+ expect(page).to have_button('Re-deploy to environment')
end
context 'with manual action' do
@@ -141,6 +171,11 @@ describe 'Environment' do
end
context 'when user has no ability to trigger a deployment' do
+ let(:permissions) do
+ create(:protected_branch, :no_one_can_merge,
+ name: action.ref, project: project)
+ end
+
it 'does not show a play button' do
expect(page).not_to have_link(action.name)
end
@@ -158,8 +193,9 @@ describe 'Environment' do
context 'with terminal' do
context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
+ let!(:cluster) do
+ create(:cluster, :project, :provided_by_gcp, projects: [project])
+ end
context 'for project maintainer' do
let(:role) { :maintainer }
@@ -228,6 +264,11 @@ describe 'Environment' do
end
context 'when user has no ability to stop environment' do
+ let(:permissions) do
+ create(:protected_branch, :no_one_can_merge,
+ name: action.ref, project: project)
+ end
+
it 'does not allow to stop environment' do
expect(page).not_to have_button('Stop')
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index a825911b01a..9854335a7ad 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -186,7 +186,7 @@ describe 'Edit Project Settings' do
click_button "Save changes"
end
- expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 2)
+ expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 3)
end
it "shows empty features project homepage" do
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index 10672bbec68..b8efabb0cab 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -41,6 +41,11 @@ describe "User browses files" do
it "shows the `Browse Directory` link" do
click_link("files")
+
+ page.within('.repo-breadcrumb') do
+ expect(page).to have_link('files')
+ end
+
click_link("History")
expect(page).to have_link("Browse Directory").and have_no_link("Browse Code")
@@ -229,6 +234,16 @@ describe "User browses files" do
expect(page).to have_content("*.rb")
.and have_content("Dmitriy Zaporozhets")
.and have_content("Initial commit")
+ .and have_content("Ignore DS files")
+
+ previous_commit_anchor = "//a[@title='Ignore DS files']/parent::span/following-sibling::span/a"
+ find(:xpath, previous_commit_anchor).click
+
+ expect(page).to have_content("*.rb")
+ .and have_content("Dmitriy Zaporozhets")
+ .and have_content("Initial commit")
+
+ expect(page).not_to have_content("Ignore DS files")
end
end
diff --git a/spec/features/projects/files/user_browses_lfs_files_spec.rb b/spec/features/projects/files/user_browses_lfs_files_spec.rb
index 618290416bd..dbeec973865 100644
--- a/spec/features/projects/files/user_browses_lfs_files_spec.rb
+++ b/spec/features/projects/files/user_browses_lfs_files_spec.rb
@@ -19,7 +19,17 @@ describe 'Projects > Files > User browses LFS files' do
it 'is possible to see raw content of LFS pointer' do
click_link 'files'
+
+ page.within('.repo-breadcrumb') do
+ expect(page).to have_link('files')
+ end
+
click_link 'lfs'
+
+ page.within('.repo-breadcrumb') do
+ expect(page).to have_link('lfs')
+ end
+
click_link 'lfs_object.iso'
expect(page).to have_content 'version https://git-lfs.github.com/spec/v1'
@@ -38,6 +48,11 @@ describe 'Projects > Files > User browses LFS files' do
it 'shows an LFS object' do
click_link('files')
+
+ page.within('.repo-breadcrumb') do
+ expect(page).to have_link('files')
+ end
+
click_link('lfs')
click_link('lfs_object.iso')
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index 0f97032eefa..bfab4387688 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -27,6 +27,89 @@ describe 'Project fork' do
expect(page).to have_css('a.disabled', text: 'Fork')
end
+ context 'forking enabled / disabled in project settings' do
+ before do
+ project.project_feature.update_attribute(
+ :forking_access_level, forking_access_level)
+ end
+
+ context 'forking is enabled' do
+ let(:forking_access_level) { ProjectFeature::ENABLED }
+
+ it 'enables fork button' do
+ visit project_path(project)
+
+ expect(page).to have_css('a', text: 'Fork')
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+ end
+
+ it 'renders new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_text(' Select a namespace to fork the project ')
+ end
+ end
+
+ context 'forking is disabled' do
+ let(:forking_access_level) { ProjectFeature::DISABLED }
+
+ it 'does not render fork button' do
+ visit project_path(project)
+
+ expect(page).not_to have_css('a', text: 'Fork')
+ end
+
+ it 'does not render new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(404)
+ end
+ end
+
+ context 'forking is private' do
+ let(:forking_access_level) { ProjectFeature::PRIVATE }
+
+ before do
+ project.update(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ context 'user is not a team member' do
+ it 'does not render fork button' do
+ visit project_path(project)
+
+ expect(page).not_to have_css('a', text: 'Fork')
+ end
+
+ it 'does not render new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(404)
+ end
+ end
+
+ context 'user is a team member' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'enables fork button' do
+ visit project_path(project)
+
+ expect(page).to have_css('a', text: 'Fork')
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+ end
+
+ it 'renders new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_text(' Select a namespace to fork the project ')
+ end
+ end
+ end
+ end
+
it 'forks the project', :sidekiq_might_not_need_inline do
visit project_path(project)
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 26ba7ae7a29..f9ff076a416 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -306,6 +306,21 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
+ context 'when job is waiting for resource', :js do
+ let(:job) { create(:ci_build, :waiting_for_resource, pipeline: pipeline, resource_group: resource_group) }
+ let(:resource_group) { create(:ci_resource_group, project: project) }
+
+ before do
+ visit project_job_path(project, job)
+ wait_for_requests
+ end
+
+ it 'shows correct UI components' do
+ expect(page).to have_content("This job is waiting for resource: #{resource_group.key}")
+ expect(page).to have_link("Cancel this job")
+ end
+ end
+
context "Job from other project" do
before do
visit project_job_path(project, job2)
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index 6d92c777033..84000ef73ce 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -87,12 +87,12 @@ describe 'Project members list' do
end
def add_user(id, role)
- page.within ".users-project-form" do
+ page.within ".invite-users-form" do
select2(id, from: "#user_ids", multiple: true)
select(role, from: "access_level")
end
- click_button "Add to project"
+ click_button "Invite"
end
def visit_members_page
diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
index 501dd05300a..cbcd03b33ce 100644
--- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
+++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
@@ -20,10 +20,10 @@ describe 'Projects > Members > Maintainer adds member with expiration date', :js
date = 4.days.from_now
visit project_project_members_path(project)
- page.within '.users-project-form' do
+ page.within '.invite-users-form' do
select2(new_member.id, from: '#user_ids', multiple: true)
fill_in 'expires_at', with: date.to_s(:medium) + "\n"
- click_on 'Add to project'
+ click_on 'Invite'
end
page.within "#project_member_#{new_member.project_members.first.id}" do
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index 3c4b5b2c4ca..c8da87041f9 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -322,7 +322,7 @@ shared_examples 'pages settings editing' do
before do
allow(Projects::UpdateService).to receive(:new).and_return(service)
- allow(service).to receive(:execute).and_return(status: :error)
+ allow(service).to receive(:execute).and_return(status: :error, message: 'Some error has occured')
end
it 'tries to change the setting' do
@@ -332,7 +332,7 @@ shared_examples 'pages settings editing' do
click_button 'Save'
- expect(page).to have_text('Something went wrong on our end')
+ expect(page).to have_text('Some error has occured')
end
end
@@ -347,7 +347,7 @@ shared_examples 'pages settings editing' do
visit project_pages_path(project)
expect(page).to have_field(:project_pages_https_only, disabled: true)
- expect(page).not_to have_button('Save')
+ expect(page).to have_button('Save')
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 94fac9a2eb5..198af65c361 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -59,7 +59,8 @@ describe 'Pipeline', :js do
describe 'GET /:project/pipelines/:id' do
include_context 'pipeline builds'
- let(:project) { create(:project, :repository) }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :repository, group: group) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id, user: user) }
subject(:visit_pipeline) { visit project_pipeline_path(project, pipeline) }
@@ -329,6 +330,32 @@ describe 'Pipeline', :js do
end
end
+ context 'deleting pipeline' do
+ context 'when user can not delete' do
+ before do
+ visit_pipeline
+ end
+
+ it { expect(page).not_to have_button('Delete') }
+ end
+
+ context 'when deleting' do
+ before do
+ group.add_owner(user)
+
+ visit_pipeline
+
+ click_button 'Delete'
+ click_button 'Delete pipeline'
+ end
+
+ it 'redirects to pipeline overview page', :sidekiq_might_not_need_inline do
+ expect(page).to have_content('The pipeline has been deleted')
+ expect(current_path).to eq(project_pipelines_path(project))
+ end
+ end
+ end
+
context 'when pipeline ref does not exist in repository anymore' do
let(:pipeline) do
create(:ci_empty_pipeline, project: project,
@@ -606,6 +633,117 @@ describe 'Pipeline', :js do
end
end
+ context 'when build requires resource', :sidekiq_inline do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:resource_group) { create(:ci_resource_group, project: project) }
+
+ let!(:test_job) do
+ create(:ci_build, :pending, stage: 'test', name: 'test',
+ stage_idx: 1, pipeline: pipeline, project: project)
+ end
+
+ let!(:deploy_job) do
+ create(:ci_build, :created, stage: 'deploy', name: 'deploy',
+ stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group)
+ end
+
+ describe 'GET /:project/pipelines/:id' do
+ subject { visit project_pipeline_path(project, pipeline) }
+
+ it 'shows deploy job as created' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('pending')
+ end
+
+ within('.pipeline-graph') do
+ within '.stage-column:nth-child(1)' do
+ expect(page).to have_content('test')
+ expect(page).to have_css('.ci-status-icon-pending')
+ end
+
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-created')
+ end
+ end
+ end
+
+ context 'when test job succeeded' do
+ before do
+ test_job.success!
+ end
+
+ it 'shows deploy job as pending' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('running')
+ end
+
+ within('.pipeline-graph') do
+ within '.stage-column:nth-child(1)' do
+ expect(page).to have_content('test')
+ expect(page).to have_css('.ci-status-icon-success')
+ end
+
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-pending')
+ end
+ end
+ end
+ end
+
+ context 'when test job succeeded but there are no available resources' do
+ let(:another_job) { create(:ci_build, :running, project: project, resource_group: resource_group) }
+
+ before do
+ resource_group.assign_resource_to(another_job)
+ test_job.success!
+ end
+
+ it 'shows deploy job as waiting for resource' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('waiting')
+ end
+
+ within('.pipeline-graph') do
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-waiting-for-resource')
+ end
+ end
+ end
+
+ context 'when resource is released from another job' do
+ before do
+ another_job.success!
+ end
+
+ it 'shows deploy job as pending' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('running')
+ end
+
+ within('.pipeline-graph') do
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-pending')
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
describe 'GET /:project/pipelines/:id/builds' do
include_context 'pipeline builds'
diff --git a/spec/features/projects/raw/user_interacts_with_raw_endpoint_spec.rb b/spec/features/projects/raw/user_interacts_with_raw_endpoint_spec.rb
index 6d587053b4f..673766073a2 100644
--- a/spec/features/projects/raw/user_interacts_with_raw_endpoint_spec.rb
+++ b/spec/features/projects/raw/user_interacts_with_raw_endpoint_spec.rb
@@ -31,8 +31,6 @@ describe 'Projects > Raw > User interacts with raw endpoint' do
visit project_raw_url(project, file_path)
end
- expect(source).to have_content('You are being redirected')
- click_link('redirected')
expect(page).to have_content('You cannot access the raw file. Please wait a minute.')
end
end
diff --git a/spec/features/projects/serverless/functions_spec.rb b/spec/features/projects/serverless/functions_spec.rb
index e82e5b81021..c661ceb8eda 100644
--- a/spec/features/projects/serverless/functions_spec.rb
+++ b/spec/features/projects/serverless/functions_spec.rb
@@ -6,7 +6,7 @@ describe 'Functions', :js do
include KubernetesHelpers
include ReactiveCachingHelpers
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
before do
@@ -36,9 +36,8 @@ describe 'Functions', :js do
end
context 'when the user has a cluster and knative installed and visits the serverless page' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp, projects: [project]) }
let(:service) { cluster.platform_kubernetes }
- let(:project) { cluster.project }
let(:environment) { create(:environment, project: project) }
let!(:deployment) { create(:deployment, :success, cluster: cluster, environment: environment) }
let(:knative_services_finder) { environment.knative_services_finder }
diff --git a/spec/features/projects/settings/project_settings_spec.rb b/spec/features/projects/settings/project_settings_spec.rb
index 7afddc0e712..b601866c96b 100644
--- a/spec/features/projects/settings/project_settings_spec.rb
+++ b/spec/features/projects/settings/project_settings_spec.rb
@@ -34,6 +34,26 @@ describe 'Projects settings' do
expect_toggle_state(:expanded)
end
+ context 'forking enabled', :js do
+ it 'toggles forking enabled / disabled' do
+ visit edit_project_path(project)
+
+ forking_enabled_input = find('input[name="project[project_feature_attributes][forking_access_level]"]', visible: :hidden)
+ forking_enabled_button = find('input[name="project[project_feature_attributes][forking_access_level]"] + label > button')
+
+ expect(forking_enabled_input.value).to eq('20')
+
+ # disable by clicking toggle
+ forking_enabled_button.click
+ page.within('.sharing-permissions') do
+ find('input[value="Save changes"]').click
+ end
+ wait_for_requests
+
+ expect(forking_enabled_input.value).to eq('0')
+ end
+ end
+
def expect_toggle_state(state)
is_collapsed = state == :collapsed
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
new file mode 100644
index 00000000000..86da866a927
--- /dev/null
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Project > Settings > CI/CD > Container registry tag expiration policy', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ context 'as owner' do
+ before do
+ sign_in(user)
+ visit project_settings_ci_cd_path(project)
+ end
+
+ it 'section is available' do
+ settings_block = find('#js-registry-policies')
+ expect(settings_block).to have_text 'Container Registry tag expiration policy'
+ end
+
+ it 'Save expiration policy submit the form', :js do
+ within '#js-registry-policies' do
+ within '.card-body' do
+ click_button(class: 'gl-toggle')
+ select('7 days until tags are automatically removed', from: 'expiration-policy-interval')
+ select('Every day', from: 'expiration-policy-schedule')
+ select('50 tags per image name', from: 'expiration-policy-latest')
+ fill_in('expiration-policy-name-matching', with: '*-production')
+ end
+ submit_button = find('.card-footer .btn.btn-success')
+ expect(submit_button).not_to be_disabled
+ submit_button.click
+ end
+ flash_text = find('.flash-text')
+ expect(flash_text).to have_content('Expiration policy successfully saved.')
+ end
+ end
+end
diff --git a/spec/features/projects/settings/user_manages_project_members_spec.rb b/spec/features/projects/settings/user_manages_project_members_spec.rb
index 6d94388a6e2..705c60f15ee 100644
--- a/spec/features/projects/settings/user_manages_project_members_spec.rb
+++ b/spec/features/projects/settings/user_manages_project_members_spec.rb
@@ -37,7 +37,7 @@ describe 'Projects > Settings > User manages project members' do
visit(project_project_members_path(project))
- page.within('.users-project-form') do
+ page.within('.invite-users-form') do
click_link('Import')
end
diff --git a/spec/features/projects/settings/user_renames_a_project_spec.rb b/spec/features/projects/settings/user_renames_a_project_spec.rb
index d2daf8b922d..789c5e31748 100644
--- a/spec/features/projects/settings/user_renames_a_project_spec.rb
+++ b/spec/features/projects/settings/user_renames_a_project_spec.rb
@@ -59,8 +59,8 @@ describe 'Projects > Settings > User renames a project' do
context 'with emojis' do
it 'shows error for invalid project name' do
- change_name(project, '🚀 foo bar ☁️')
- expect(page).to have_field 'Project name', with: '🚀 foo bar ☁️'
+ change_name(project, '🧮 foo bar ☁️')
+ expect(page).to have_field 'Project name', with: '🧮 foo bar ☁️'
expect(page).not_to have_content "Name can contain only letters, digits, emojis '_', '.', dash and space. It must start with letter, digit, emoji or '_'."
end
end
diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb
index ad65e04473c..94af023e804 100644
--- a/spec/features/projects/snippets/create_snippet_spec.rb
+++ b/spec/features/projects/snippets/create_snippet_spec.rb
@@ -50,7 +50,7 @@ describe 'Projects > Snippets > Create Snippet', :js do
wait_for_requests
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
- expect(link).to match(%r{/#{Regexp.escape(project.full_path) }/uploads/\h{32}/banana_sample\.gif\z})
+ expect(link).to match(%r{/#{Regexp.escape(project.full_path)}/uploads/\h{32}/banana_sample\.gif\z})
end
it 'creates a snippet when all required fields are filled in after validation failing' do
@@ -72,7 +72,7 @@ describe 'Projects > Snippets > Create Snippet', :js do
expect(page).to have_selector('strong')
end
link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
- expect(link).to match(%r{/#{Regexp.escape(project.full_path) }/uploads/\h{32}/banana_sample\.gif\z})
+ expect(link).to match(%r{/#{Regexp.escape(project.full_path)}/uploads/\h{32}/banana_sample\.gif\z})
end
end
diff --git a/spec/features/projects/sourcegraph_csp_spec.rb b/spec/features/projects/sourcegraph_csp_spec.rb
new file mode 100644
index 00000000000..57d1e8e3034
--- /dev/null
+++ b/spec/features/projects/sourcegraph_csp_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Sourcegraph Content Security Policy' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:default_csp_values) { "'self' https://some-cdn.test" }
+ let_it_be(:sourcegraph_url) { 'https://sourcegraph.test' }
+ let(:sourcegraph_enabled) { true }
+
+ subject do
+ visit project_blob_path(project, File.join('master', 'README.md'))
+
+ response_headers['Content-Security-Policy']
+ end
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(sourcegraph_url)
+ allow(Gitlab::CurrentSettings).to receive(:sourcegraph_enabled).and_return(sourcegraph_enabled)
+
+ sign_in(user)
+ end
+
+ shared_context 'csp config' do |csp_rule|
+ before do
+ csp = ActionDispatch::ContentSecurityPolicy.new do |p|
+ p.send(csp_rule, default_csp_values) if csp_rule
+ end
+
+ expect_next_instance_of(Projects::BlobController) do |controller|
+ expect(controller).to receive(:current_content_security_policy).and_return(csp)
+ end
+ end
+ end
+
+ context 'when no CSP config' do
+ include_context 'csp config', nil
+
+ it 'does not add CSP directives' do
+ is_expected.to be_blank
+ end
+ end
+
+ describe 'when a CSP config exists for connect-src' do
+ include_context 'csp config', :connect_src
+
+ context 'when sourcegraph enabled' do
+ it 'appends to connect-src' do
+ is_expected.to eql("connect-src #{default_csp_values} #{sourcegraph_url}")
+ end
+ end
+
+ context 'when sourcegraph disabled' do
+ let(:sourcegraph_enabled) { false }
+
+ it 'keeps original connect-src' do
+ is_expected.to eql("connect-src #{default_csp_values}")
+ end
+ end
+ end
+
+ describe 'when a CSP config exists for default-src but not connect-src' do
+ include_context 'csp config', :default_src
+
+ context 'when sourcegraph enabled' do
+ it 'uses default-src values in connect-src' do
+ is_expected.to eql("default-src #{default_csp_values}; connect-src #{default_csp_values} #{sourcegraph_url}")
+ end
+ end
+
+ context 'when sourcegraph disabled' do
+ let(:sourcegraph_enabled) { false }
+
+ it 'does not add connect-src' do
+ is_expected.to eql("default-src #{default_csp_values}")
+ end
+ end
+ end
+
+ describe 'when a CSP config exists for font-src but not connect-src' do
+ include_context 'csp config', :font_src
+
+ context 'when sourcegraph enabled' do
+ it 'uses default-src values in connect-src' do
+ is_expected.to eql("font-src #{default_csp_values}; connect-src #{sourcegraph_url}")
+ end
+ end
+
+ context 'when sourcegraph disabled' do
+ let(:sourcegraph_enabled) { false }
+
+ it 'does not add connect-src' do
+ is_expected.to eql("font-src #{default_csp_values}")
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb
index 99285011405..7e0ee861b18 100644
--- a/spec/features/projects/tree/create_directory_spec.rb
+++ b/spec/features/projects/tree/create_directory_spec.rb
@@ -46,8 +46,6 @@ describe 'Multi-file editor new directory', :js do
find('.js-ide-commit-mode').click
- click_button 'Stage'
-
fill_in('commit-message', with: 'commit message ide')
find(:css, ".js-ide-commit-new-mr input").set(false)
diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb
index 780575a5975..eba33168006 100644
--- a/spec/features/projects/tree/create_file_spec.rb
+++ b/spec/features/projects/tree/create_file_spec.rb
@@ -36,8 +36,6 @@ describe 'Multi-file editor new file', :js do
find('.js-ide-commit-mode').click
- click_button 'Stage'
-
fill_in('commit-message', with: 'commit message ide')
find(:css, ".js-ide-commit-new-mr input").set(false)
diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb
index c2d4cefad12..8b25565c08a 100644
--- a/spec/features/projects/view_on_env_spec.rb
+++ b/spec/features/projects/view_on_env_spec.rb
@@ -9,14 +9,11 @@ describe 'View on environment', :js do
let(:user) { project.creator }
before do
- stub_feature_flags(single_mr_diff_view: false)
stub_feature_flags(diffs_batch_load: false)
project.add_maintainer(user)
end
- it_behaves_like 'rendering a single diff version'
-
context 'when the branch has a route map' do
let(:route_map) do
<<-MAP.strip_heredoc
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index 499c459621a..7503c8aa52e 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -145,6 +145,24 @@ describe "User creates wiki page" do
end
end
+ it 'creates a wiki page with Org markup', :aggregate_failures do
+ org_content = <<~ORG
+ * Heading
+ ** Subheading
+ [[home][Link to Home]]
+ ORG
+
+ page.within('.wiki-form') do
+ find('#wiki_format option[value=org]').select_option
+ fill_in(:wiki_content, with: org_content)
+ click_button('Create page')
+ end
+
+ expect(page).to have_selector('h1', text: 'Heading')
+ expect(page).to have_selector('h2', text: 'Subheading')
+ expect(page).to have_link('Link to Home', href: "/#{project.full_path}/-/wikis/home")
+ end
+
it_behaves_like 'wiki file attachments', :quarantine
end
diff --git a/spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb b/spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb
new file mode 100644
index 00000000000..08eea14c438
--- /dev/null
+++ b/spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'User views AsciiDoc page with includes', :js do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' }
+ let(:project) { create(:project, :public, :wiki_repo) }
+ let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')}
+ let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") }
+
+ def create_wiki_page(title, content:)
+ attrs = {
+ title: title,
+ content: content,
+ format: :asciidoc
+ }
+
+ create(:wiki_page, wiki: project.wiki, attrs: attrs)
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when the file being included exists' do
+ it 'includes the file contents' do
+ visit(project_wiki_path(project, wiki_page))
+
+ page.within(:css, wiki_content_selector) do
+ expect(page).to have_content('Content from the main page. Content from the included page')
+ end
+ end
+
+ context 'when there are multiple versions of the wiki pages' do
+ before do
+ included_wiki_page.update(message: 'updated included file', content: 'Updated content from the included page')
+ wiki_page.update(message: 'updated wiki page', content: "Updated content from the main page.\ninclude::included_page.asciidoc[]")
+ end
+
+ let(:latest_version_id) { wiki_page.versions.first.id }
+ let(:oldest_version_id) { wiki_page.versions.last.id }
+
+ context 'viewing the latest version' do
+ it 'includes the latest content' do
+ visit(project_wiki_path(project, wiki_page, version_id: latest_version_id))
+
+ page.within(:css, wiki_content_selector) do
+ expect(page).to have_content('Updated content from the main page. Updated content from the included page')
+ end
+ end
+ end
+
+ context 'viewing the original version' do
+ it 'includes the content from the original version' do
+ visit(project_wiki_path(project, wiki_page, version_id: oldest_version_id))
+
+ page.within(:css, wiki_content_selector) do
+ expect(page).to have_content('Content from the main page. Content from the included page')
+ end
+ end
+ end
+ end
+ end
+
+ context 'when the file being included does not exist' do
+ before do
+ included_wiki_page.delete
+ end
+
+ it 'outputs an error' do
+ visit(project_wiki_path(project, wiki_page))
+
+ page.within(:css, wiki_content_selector) do
+ expect(page).to have_content('Content from the main page. [ERROR: include::included_page.asciidoc[] - unresolved directive]')
+ end
+ end
+ end
+end
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index 11429f16f42..bcd894a0d20 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -51,6 +51,27 @@ describe 'Task Lists' do
EOT
end
+ let(:commented_tasks_markdown) do
+ <<-EOT.strip_heredoc
+ <!--
+ - [ ] a
+ -->
+
+ - [ ] b
+ EOT
+ end
+
+ let(:summary_no_blank_line_markdown) do
+ <<-EOT.strip_heredoc
+ <details>
+ <summary>No blank line after summary element breaks task list</summary>
+ 1. [ ] People Ops: do such and such
+ </details>
+
+ * [ ] Task 1
+ EOT
+ end
+
before do
Warden.test_mode!
@@ -291,4 +312,52 @@ describe 'Task Lists' do
end
end
end
+
+ describe 'markdown task edge cases' do
+ describe 'commented tasks', :js do
+ let!(:issue) { create(:issue, description: commented_tasks_markdown, author: user, project: project) }
+
+ it 'renders' do
+ visit_issue(project, issue)
+ wait_for_requests
+
+ expect(page).to have_selector('ul.task-list', count: 1)
+ expect(page).to have_selector('li.task-list-item', count: 1)
+ expect(page).to have_selector('ul input[checked]', count: 0)
+
+ find('.task-list-item-checkbox').click
+ wait_for_requests
+
+ visit_issue(project, issue)
+ wait_for_requests
+
+ expect(page).to have_selector('ul.task-list', count: 1)
+ expect(page).to have_selector('li.task-list-item', count: 1)
+ expect(page).to have_selector('ul input[checked]', count: 1)
+ end
+ end
+
+ describe 'summary with no blank line', :js do
+ let!(:issue) { create(:issue, description: summary_no_blank_line_markdown, author: user, project: project) }
+
+ it 'renders' do
+ visit_issue(project, issue)
+ wait_for_requests
+
+ expect(page).to have_selector('ul.task-list', count: 1)
+ expect(page).to have_selector('li.task-list-item', count: 1)
+ expect(page).to have_selector('ul input[checked]', count: 0)
+
+ find('.task-list-item-checkbox').click
+ wait_for_requests
+
+ visit_issue(project, issue)
+ wait_for_requests
+
+ expect(page).to have_selector('ul.task-list', count: 1)
+ expect(page).to have_selector('li.task-list-item', count: 1)
+ expect(page).to have_selector('ul input[checked]', count: 1)
+ end
+ end
+ end
end
diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb
index 19cd21e4161..af406961bbc 100644
--- a/spec/features/triggers_spec.rb
+++ b/spec/features/triggers_spec.rb
@@ -65,22 +65,6 @@ describe 'Triggers', :js do
expect(page.find('.triggers-list')).to have_content new_trigger_title
expect(page.find('.triggers-list .trigger-owner')).to have_content user.name
end
-
- it 'edit "legacy" trigger and save' do
- # Create new trigger without owner association, i.e. Legacy trigger
- create(:ci_trigger, owner: user, project: @project).update_attribute(:owner, nil)
- visit project_settings_ci_cd_path(@project)
-
- # See if the trigger can be edited and description is blank
- find('a[title="Edit"]').send_keys(:return)
- expect(page.find('#trigger_description').value).to have_content ''
-
- # See if trigger can be updated with description and saved successfully
- fill_in 'trigger_description', with: new_trigger_title
- click_button 'Save trigger'
- expect(page.find('.flash-notice')).to have_content 'Trigger was successfully updated.'
- expect(page.find('.triggers-list')).to have_content new_trigger_title
- end
end
describe 'trigger "Revoke" workflow' do
@@ -106,43 +90,18 @@ describe 'Triggers', :js do
end
describe 'show triggers workflow' do
- before do
- stub_feature_flags(use_legacy_pipeline_triggers: false)
- end
-
it 'contains trigger description placeholder' do
expect(page.find('#trigger_description')['placeholder']).to eq 'Trigger description'
end
- it 'show "invalid" badge for legacy trigger' do
- create(:ci_trigger, owner: user, project: @project).update_attribute(:owner, nil)
- visit project_settings_ci_cd_path(@project)
-
- expect(page.find('.triggers-list')).to have_content 'invalid'
- end
-
it 'show "invalid" badge for trigger with owner having insufficient permissions' do
create(:ci_trigger, owner: guest_user, project: @project, description: trigger_title)
visit project_settings_ci_cd_path(@project)
- # See if trigger without owner (i.e. legacy) shows "legacy" badge and is non-editable
expect(page.find('.triggers-list')).to have_content 'invalid'
expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]')
end
- it 'do not show "Edit" or full token for legacy trigger' do
- create(:ci_trigger, owner: user, project: @project, description: trigger_title)
- .update_attribute(:owner, nil)
- visit project_settings_ci_cd_path(@project)
-
- # See if trigger not owned shows only first few token chars and doesn't have copy-to-clipboard button
- expect(page.find('.triggers-list')).to have_content(@project.triggers.first.token[0..3])
- expect(page.find('.triggers-list')).not_to have_selector('button.btn-clipboard')
-
- # See if trigger is non-editable
- expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]')
- end
-
it 'do not show "Edit" or full token for not owned trigger' do
# Create trigger with user different from current_user
create(:ci_trigger, owner: user2, project: @project, description: trigger_title)
@@ -169,56 +128,5 @@ describe 'Triggers', :js do
expect(page.find('.triggers-list .trigger-owner')).to have_content user.name
expect(page.find('.triggers-list')).to have_selector('a[title="Edit"]')
end
-
- context 'when :use_legacy_pipeline_triggers feature flag is enabled' do
- before do
- stub_feature_flags(use_legacy_pipeline_triggers: true)
- end
-
- it 'show "legacy" badge for legacy trigger' do
- create(:ci_trigger, owner: nil, project: @project)
- visit project_settings_ci_cd_path(@project)
-
- # See if trigger without owner (i.e. legacy) shows "legacy" badge and is editable
- expect(page.find('.triggers-list')).to have_content 'legacy'
- expect(page.find('.triggers-list')).to have_selector('a[title="Edit"]')
- end
-
- it 'show "invalid" badge for trigger with owner having insufficient permissions' do
- create(:ci_trigger, owner: guest_user, project: @project, description: trigger_title)
- visit project_settings_ci_cd_path(@project)
-
- # See if trigger without owner (i.e. legacy) shows "legacy" badge and is non-editable
- expect(page.find('.triggers-list')).to have_content 'invalid'
- expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]')
- end
-
- it 'do not show "Edit" or full token for not owned trigger' do
- # Create trigger with user different from current_user
- create(:ci_trigger, owner: user2, project: @project, description: trigger_title)
- visit project_settings_ci_cd_path(@project)
-
- # See if trigger not owned by current_user shows only first few token chars and doesn't have copy-to-clipboard button
- expect(page.find('.triggers-list')).to have_content(@project.triggers.first.token[0..3])
- expect(page.find('.triggers-list')).not_to have_selector('button.btn-clipboard')
-
- # See if trigger owner name doesn't match with current_user and trigger is non-editable
- expect(page.find('.triggers-list .trigger-owner')).not_to have_content user.name
- expect(page.find('.triggers-list')).not_to have_selector('a[title="Edit"]')
- end
-
- it 'show "Edit" and full token for owned trigger' do
- create(:ci_trigger, owner: user, project: @project, description: trigger_title)
- visit project_settings_ci_cd_path(@project)
-
- # See if trigger shows full token and has copy-to-clipboard button
- expect(page.find('.triggers-list')).to have_content @project.triggers.first.token
- expect(page.find('.triggers-list')).to have_selector('button.btn-clipboard')
-
- # See if trigger owner name matches with current_user and is editable
- expect(page.find('.triggers-list .trigger-owner')).to have_content user.name
- expect(page.find('.triggers-list')).to have_selector('a[title="Edit"]')
- end
- end
end
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 3b19bd423a4..30f298b1fc3 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -123,50 +123,6 @@ shared_examples 'Signup' do
end
end
- describe 'user\'s full name validation', :js do
- before do
- if Gitlab::Experimentation.enabled?(:signup_flow)
- user = create(:user, role: nil)
- sign_in(user)
- visit users_sign_up_welcome_path
- @user_name_field = 'user_name'
- else
- visit new_user_registration_path
- @user_name_field = 'new_user_name'
- end
- end
-
- it 'does not show an error border if the user\'s fullname length is not longer than 128 characters' do
- fill_in @user_name_field, with: 'u' * 128
-
- expect(find('.name')).not_to have_css '.gl-field-error-outline'
- end
-
- it 'shows an error border if the user\'s fullname contains an emoji' do
- simulate_input("##{@user_name_field}", 'Ehsan 🦋')
-
- expect(find('.name')).to have_css '.gl-field-error-outline'
- end
-
- it 'shows an error border if the user\'s fullname is longer than 128 characters' do
- fill_in @user_name_field, with: 'n' * 129
-
- expect(find('.name')).to have_css '.gl-field-error-outline'
- end
-
- it 'shows an error message if the user\'s fullname is longer than 128 characters' do
- fill_in @user_name_field, with: 'n' * 129
-
- expect(page).to have_content("Name is too long (maximum is 128 characters).")
- end
-
- it 'shows an error message if the username contains emojis' do
- simulate_input("##{@user_name_field}", 'Ehsan 🦋')
-
- expect(page).to have_content("Invalid input, please avoid emojis")
- end
- end
-
context 'with no errors' do
context 'when sending confirmation email' do
before do
@@ -184,7 +140,10 @@ shared_examples 'Signup' do
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
@@ -209,7 +168,10 @@ shared_examples 'Signup' do
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
@@ -235,7 +197,10 @@ shared_examples 'Signup' do
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email.capitalize
end
@@ -263,7 +228,10 @@ shared_examples 'Signup' do
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
@@ -287,7 +255,10 @@ shared_examples 'Signup' do
visit new_user_registration_path
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
end
@@ -313,7 +284,10 @@ shared_examples 'Signup' do
visit new_user_registration_path
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
end
@@ -338,7 +312,10 @@ shared_examples 'Signup' do
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
@@ -357,7 +334,10 @@ shared_examples 'Signup' do
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
@@ -394,7 +374,10 @@ shared_examples 'Signup' do
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- unless Gitlab::Experimentation.enabled?(:signup_flow)
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
@@ -412,6 +395,44 @@ shared_examples 'Signup' do
end
end
+shared_examples 'Signup name validation' do |field, max_length|
+ before do
+ visit new_user_registration_path
+ end
+
+ describe "#{field} validation", :js do
+ it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do
+ fill_in field, with: 'u' * max_length
+
+ expect(find('.name')).not_to have_css '.gl-field-error-outline'
+ end
+
+ it 'shows an error border if the user\'s fullname contains an emoji' do
+ simulate_input("##{field}", 'Ehsan 🦋')
+
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
+
+ it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do
+ fill_in field, with: 'n' * (max_length + 1)
+
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
+
+ it "shows an error message if the user\'s fullname is longer than #{max_length} characters" do
+ fill_in field, with: 'n' * (max_length + 1)
+
+ expect(page).to have_content("Name is too long (maximum is #{max_length} characters).")
+ end
+
+ it 'shows an error message if the username contains emojis' do
+ simulate_input("##{field}", 'Ehsan 🦋')
+
+ expect(page).to have_content("Invalid input, please avoid emojis")
+ end
+ end
+end
+
describe 'With original flow' do
before do
stub_experiment(signup_flow: false)
@@ -419,6 +440,7 @@ describe 'With original flow' do
end
it_behaves_like 'Signup'
+ it_behaves_like 'Signup name validation', 'new_user_name', 255
end
describe 'With experimental flow' do
@@ -428,11 +450,15 @@ describe 'With experimental flow' do
end
it_behaves_like 'Signup'
+ it_behaves_like 'Signup name validation', 'new_user_first_name', 127
+ it_behaves_like 'Signup name validation', 'new_user_last_name', 127
describe 'when role is required' do
it 'after registering, it redirects to step 2 of the signup process, sets the name and role and then redirects to the original requested url' do
new_user = build_stubbed(:user)
visit new_user_registration_path
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
fill_in 'new_user_password', with: new_user.password
@@ -441,13 +467,11 @@ describe 'With experimental flow' do
expect(page).to have_current_path(users_sign_up_welcome_path)
- fill_in 'user_name', with: 'New name'
select 'Software Developer', from: 'user_role'
choose 'user_setup_for_company_true'
click_button 'Get started!'
new_user = User.find_by_username(new_user.username)
- expect(new_user.name).to eq 'New name'
expect(new_user.software_developer_role?).to be_truthy
expect(new_user.setup_for_company).to be_truthy
expect(page).to have_current_path(new_project_path)