summaryrefslogtreecommitdiff
path: root/spec/features/issues/user_bulk_edits_issues_labels_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/features/issues/user_bulk_edits_issues_labels_spec.rb')
-rw-r--r--spec/features/issues/user_bulk_edits_issues_labels_spec.rb468
1 files changed, 468 insertions, 0 deletions
diff --git a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb
new file mode 100644
index 00000000000..97df2d0208b
--- /dev/null
+++ b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb
@@ -0,0 +1,468 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Issues > Labels bulk assignment' do
+ let(:user) { create(:user) }
+ let!(:project) { create(:project) }
+ let!(:bug) { create(:label, project: project, title: 'bug') }
+ let!(:feature) { create(:label, project: project, title: 'feature') }
+ let!(:frontend) { create(:label, project: project, title: 'frontend') }
+ let!(:wontfix) { create(:label, project: project, title: 'wontfix') }
+ let!(:issue1) { create(:issue, project: project, title: "Issue 1", labels: [frontend]) }
+ let!(:issue2) { create(:issue, project: project, title: "Issue 2") }
+
+ context 'as an allowed user', :js do
+ before do
+ project.add_maintainer(user)
+
+ sign_in user
+ end
+
+ context 'sidebar' do
+ it 'is present when bulk edit is enabled' do
+ enable_bulk_update
+ expect(page).to have_css 'aside[aria-label="Bulk update"]'
+ end
+
+ it 'is not present when bulk edit is disabled' do
+ expect(page).not_to have_css 'aside[aria-label="Bulk update"]'
+ end
+ end
+
+ context 'can bulk assign' do
+ before do
+ enable_bulk_update
+ end
+
+ context 'a label' do
+ context 'to all issues' do
+ before do
+ check 'Select all'
+ open_labels_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
+ expect(find("#issue_#{issue2.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ end
+ end
+
+ context 'to some issues' do
+ before do
+ check issue1.title
+ check issue2.title
+ open_labels_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
+ expect(find("#issue_#{issue2.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ end
+ end
+
+ context 'to an issue' do
+ before do
+ check issue1.title
+ open_labels_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ end
+ end
+
+ context 'to an issue by selecting the label first' do
+ before do
+ open_labels_dropdown ['bug']
+ check issue1.title
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ end
+ end
+ end
+
+ context 'multiple labels' do
+ context 'to all issues' do
+ before do
+ check 'Select all'
+ open_labels_dropdown %w(bug feature)
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ end
+ end
+
+ context 'to a issue' do
+ before do
+ check issue1.title
+ open_labels_dropdown %w(bug feature)
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
+ end
+ end
+ end
+ end
+
+ context 'can assign a label to all issues when label is present' do
+ before do
+ issue2.labels << bug
+ issue2.labels << feature
+
+ enable_bulk_update
+ check 'Select all'
+
+ open_labels_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'bug'
+ end
+ end
+
+ context 'can bulk un-assign' do
+ context 'all labels to all issues' do
+ before do
+ issue1.labels << bug
+ issue1.labels << feature
+ issue2.labels << bug
+ issue2.labels << feature
+
+ enable_bulk_update
+ check 'Select all'
+ unmark_labels_in_dropdown %w(bug feature)
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
+ end
+ end
+
+ context 'a label to a issue' do
+ before do
+ issue1.labels << bug
+ issue2.labels << feature
+
+ enable_bulk_update
+ check_issue issue1
+ unmark_labels_in_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ end
+ end
+
+ context 'a label and keep the others label' do
+ before do
+ issue1.labels << bug
+ issue1.labels << feature
+ issue2.labels << bug
+ issue2.labels << feature
+
+ enable_bulk_update
+ check_issue issue1
+ check_issue issue2
+ unmark_labels_in_dropdown ['bug']
+ update_issues
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ end
+ end
+ end
+
+ context 'toggling a milestone' do
+ let!(:milestone) { create(:milestone, project: project, title: 'First Release') }
+
+ context 'setting a milestone' do
+ before do
+ issue1.labels << bug
+ issue2.labels << feature
+ enable_bulk_update
+ end
+
+ it 'keeps labels' do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+
+ check 'Select all'
+
+ open_milestone_dropdown(['First Release'])
+ update_issues
+
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+ end
+ end
+
+ context 'setting a milestone and adding another label' do
+ before do
+ issue1.labels << bug
+ enable_bulk_update
+ end
+
+ it 'keeps existing label and new label is present' do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+
+ check 'Select all'
+ open_milestone_dropdown ['First Release']
+ open_labels_dropdown ['feature']
+ update_issues
+
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+ end
+ end
+
+ context 'setting a milestone and removing existing label' do
+ before do
+ issue1.labels << bug
+ issue1.labels << feature
+ issue2.labels << feature
+
+ enable_bulk_update
+ end
+
+ it 'keeps existing label and new label is present' do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+
+ check 'Select all'
+
+ open_milestone_dropdown ['First Release']
+ unmark_labels_in_dropdown ['feature']
+ update_issues
+
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'feature'
+ expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+ end
+ end
+
+ context 'unsetting a milestone' do
+ before do
+ issue1.milestone = milestone
+ issue2.milestone = milestone
+ issue1.save!
+ issue2.save!
+ issue1.labels << bug
+ issue2.labels << feature
+
+ enable_bulk_update
+ end
+
+ it 'keeps labels' do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+
+ check 'Select all'
+ open_milestone_dropdown(['No milestone'])
+ update_issues
+
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).not_to have_content 'First Release'
+ expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find("#issue_#{issue2.id}")).not_to have_content 'First Release'
+ end
+ end
+ end
+
+ context 'toggling checked issues' do
+ before do
+ issue1.labels << bug
+ enable_bulk_update
+ end
+
+ it do
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+
+ check_issue issue1
+ open_labels_dropdown ['feature']
+ uncheck_issue issue1
+ check_issue issue1
+ update_issues
+ sleep 1 # needed
+
+ expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ end
+ end
+
+ context 'mark previously toggled label' do
+ before do
+ enable_bulk_update
+ end
+
+ it do
+ open_labels_dropdown ['feature']
+
+ check_issue issue1
+
+ update_issues
+
+ expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ end
+ end
+
+ # Special case https://gitlab.com/gitlab-org/gitlab-foss/issues/24877
+ context 'unmarking common label' do
+ before do
+ issue1.labels << bug
+ issue1.labels << feature
+ issue2.labels << bug
+
+ enable_bulk_update
+ end
+
+ it 'applies label from filtered results' do
+ check 'Select all'
+
+ within('aside[aria-label="Bulk update"]') do
+ click_button 'Select labels'
+ wait_for_requests
+
+ expect(page).to have_link 'bug', class: 'is-active'
+ expect(page).to have_link 'feature', class: 'is-indeterminate'
+
+ click_link 'bug'
+ fill_in 'Search', with: 'wontfix'
+ click_link 'wontfix'
+ end
+
+ update_issues
+
+ first_issue = find("#issue_#{issue1.id}")
+ expect(first_issue).not_to have_content 'bug'
+ expect(first_issue).to have_content 'feature'
+ expect(first_issue).to have_content 'wontfix'
+
+ second_issue = find("#issue_#{issue2.id}")
+ expect(second_issue).not_to have_content 'bug'
+ expect(second_issue).not_to have_content 'feature'
+ expect(second_issue).to have_content 'wontfix'
+ end
+ end
+ end
+
+ context 'as a guest' do
+ before do
+ sign_in user
+
+ visit project_issues_path(project)
+ end
+
+ context 'cannot bulk assign labels' do
+ it do
+ expect(page).not_to have_button 'Edit issues'
+ expect(page).not_to have_unchecked_field 'Select all'
+ expect(page).not_to have_unchecked_field issue1.title
+ end
+ end
+ end
+
+ def open_milestone_dropdown(items = [])
+ click_button 'Select milestone'
+ wait_for_requests
+ items.map do |item|
+ click_link item
+ end
+ end
+
+ def open_labels_dropdown(items = [], unmark = false)
+ within('aside[aria-label="Bulk update"]') do
+ click_button 'Select labels'
+ wait_for_requests
+ items.map do |item|
+ click_link item
+ end
+
+ if unmark
+ items.map do |item|
+ # Make sure we are unmarking the item no matter the state it has currently
+ click_link item until find('a', text: item)[:class].include? 'label-item'
+ end
+ end
+ end
+ end
+
+ def unmark_labels_in_dropdown(items = [])
+ open_labels_dropdown(items, true)
+ end
+
+ def check_issue(issue, uncheck = false)
+ if uncheck
+ uncheck issue.title
+ else
+ check issue.title
+ end
+ end
+
+ def uncheck_issue(issue)
+ check_issue(issue, true)
+ end
+
+ def update_issues
+ click_button 'Update all'
+ wait_for_requests
+ end
+
+ def enable_bulk_update
+ visit project_issues_path(project)
+ wait_for_requests
+ click_button 'Edit issues'
+ end
+
+ def disable_bulk_update
+ click_button 'Cancel'
+ end
+end