Commit 517c97eb authored by Toon Claes's avatar Toon Claes

/reassign should only work when multiple assignees are available

Only if the issuable allows multiple assignees the `/reassign` command
should be enabled.

While at it, put all EE-specific Quick Action in a separate file.

Also, port back the original CE specs of QuickActionsServices and put
the differences in a separate EE-only file.
parent 941d6b1e
module EE
module QuickActions
module InterpretService
include ::Gitlab::QuickActions::Dsl
desc 'Change assignee(s)'
explanation do
'Change assignee(s)'
end
params '@user1 @user2'
condition do
issuable.allows_multiple_assignees? &&
issuable.persisted? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", project)
end
command :reassign do |unassign_param|
@updates[:assignee_ids] = extract_users(unassign_param).map(&:id)
end
desc 'Set weight'
explanation do |weight|
"Sets weight to #{weight}." if weight
end
params ::Issue::WEIGHT_RANGE.to_s.squeeze('.').tr('.', '-')
condition do
issuable.supports_weight? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
parse_params do |weight|
weight.to_i if ::Issue.weight_filter_options.include?(weight.to_i)
end
command :weight do |weight|
@updates[:weight] = weight if weight
end
desc 'Clear weight'
explanation 'Clears weight.'
condition do
issuable.persisted? &&
issuable.supports_weight? &&
issuable.weight? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
command :clear_weight do
@updates[:weight] = nil
end
end
end
end
module QuickActions
class InterpretService < BaseService
include Gitlab::QuickActions::Dsl
prepend EE::QuickActions::InterpretService
attr_reader :issuable
......@@ -146,32 +147,6 @@ module QuickActions
end
end
desc do
"Change assignee#{'(s)' if issuable.allows_multiple_assignees?}"
end
explanation do |users|
users = issuable.allows_multiple_assignees? ? users : users.take(1)
"Change #{'assignee'.pluralize(users.size)} to #{users.map(&:to_reference).to_sentence}."
end
params do
issuable.allows_multiple_assignees? ? '@user1 @user2' : '@user'
end
condition do
issuable.persisted? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", project)
end
parse_params do |assignee_param|
extract_users(assignee_param)
end
command :reassign do |users|
@updates[:assignee_ids] =
if issuable.allows_multiple_assignees?
users.map(&:id)
else
[users.last.id]
end
end
desc 'Set milestone'
explanation do |milestone|
"Sets the milestone to #{milestone.to_reference}." if milestone
......@@ -471,34 +446,6 @@ module QuickActions
@updates[:target_branch] = branch_name if project.repository.branch_names.include?(branch_name)
end
desc 'Set weight'
explanation do |weight|
"Sets weight to #{weight}." if weight
end
params Issue::WEIGHT_RANGE.to_s.squeeze('.').tr('.', '-')
condition do
issuable.supports_weight? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
parse_params do |weight|
weight.to_i if Issue.weight_filter_options.include?(weight.to_i)
end
command :weight do |weight|
@updates[:weight] = weight if weight
end
desc 'Clear weight'
explanation 'Clears weight.'
condition do
issuable.persisted? &&
issuable.supports_weight? &&
issuable.weight? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
command :clear_weight do
@updates[:weight] = nil
end
desc 'Move issue from one column of the board to another'
explanation do |target_list_name|
label = find_label_references(target_list_name).first
......
require 'spec_helper'
describe QuickActions::InterpretService, services: true do # rubocop:disable RSpec/FilePath
let(:user) { create(:user) }
let(:developer) { create(:user) }
let(:developer2) { create(:user) }
let(:project) { create(:empty_project, :public) }
let(:issue) { create(:issue, project: project) }
let(:service) { described_class.new(project, developer) }
before do
stub_licensed_features(multiple_issue_assignees: true)
project.add_developer(developer)
end
describe '#execute' do
context 'assign command' do
let(:content) { "/assign @#{developer.username}" }
context 'Issue' do
it 'fetches assignees and populates them if content contains /assign' do
issue.assignees << user
_, updates = service.execute(content, issue)
expect(updates[:assignee_ids]).to match_array([developer.id, user.id])
end
context 'assign command with multiple assignees' do
let(:content) { "/assign @#{developer.username} @#{developer2.username}" }
before do
project.add_developer(developer2)
end
it 'fetches assignee and populates assignee_ids if content contains /assign' do
_, updates = service.execute(content, issue)
expect(updates[:assignee_ids]).to match_array([developer.id, developer2.id])
end
end
end
end
context 'unassign command' do
let(:content) { '/unassign' }
context 'Issue' do
it 'unassigns user if content contains /unassign @user' do
issue.update(assignee_ids: [developer.id, developer2.id])
_, updates = service.execute("/unassign @#{developer2.username}", issue)
expect(updates).to eq(assignee_ids: [developer.id])
end
it 'unassigns both users if content contains /unassign @user @user1' do
user = create(:user)
issue.update(assignee_ids: [developer.id, developer2.id, user.id])
_, updates = service.execute("/unassign @#{developer2.username} @#{developer.username}", issue)
expect(updates).to eq(assignee_ids: [user.id])
end
it 'unassigns all the users if content contains /unassign' do
issue.update(assignee_ids: [developer.id, developer2.id])
_, updates = service.execute('/unassign', issue)
expect(updates[:assignee_ids]).to be_empty
end
end
end
context 'reassign command' do
let(:content) { "/reassign @#{user.username}" }
context 'Merge Request' do
let(:merge_request) { create(:merge_request, source_project: project) }
it 'does not recognize /reassign @user' do
_, updates = service.execute(content, merge_request)
expect(updates).to be_empty
end
end
context 'Issue' do
let(:content) { "/reassign @#{user.username}" }
before do
issue.update(assignee_ids: [developer.id])
end
context 'unlicensed' do
before do
stub_licensed_features(multiple_issue_assignees: false)
end
it 'does not recognize /reassign @user' do
_, updates = service.execute(content, issue)
expect(updates).to be_empty
end
end
it 'reassigns user if content contains /reassign @user' do
_, updates = service.execute("/reassign @#{user.username}", issue)
expect(updates).to eq(assignee_ids: [user.id])
end
end
end
end
end
......@@ -11,6 +11,8 @@ describe QuickActions::InterpretService, services: true do
let(:note) { build(:note, commit_id: merge_request.diff_head_sha) }
before do
stub_licensed_features(multiple_issue_assignees: false)
project.team << [developer, :developer]
end
......@@ -399,13 +401,10 @@ describe QuickActions::InterpretService, services: true do
let(:content) { "/assign @#{developer.username}" }
context 'Issue' do
it 'fetches assignees and populates them if content contains /assign' do
user = create(:user)
issue.assignees << user
it 'fetches assignee and populates assignee_ids if content contains /assign' do
_, updates = service.execute(content, issue)
expect(updates[:assignee_ids]).to match_array([developer.id, user.id])
expect(updates[:assignee_ids]).to match_array([developer.id])
end
end
......@@ -429,7 +428,7 @@ describe QuickActions::InterpretService, services: true do
it 'fetches assignee and populates assignee_ids if content contains /assign' do
_, updates = service.execute(content, issue)
expect(updates[:assignee_ids]).to match_array([developer.id, developer2.id])
expect(updates[:assignee_ids]).to match_array([developer.id])
end
end
......@@ -456,30 +455,11 @@ describe QuickActions::InterpretService, services: true do
let(:content) { '/unassign' }
context 'Issue' do
it 'unassigns user if content contains /unassign @user' do
issue.update(assignee_ids: [developer.id, developer2.id])
_, updates = service.execute("/unassign @#{developer2.username}", issue)
expect(updates).to eq(assignee_ids: [developer.id])
end
it 'unassigns both users if content contains /unassign @user @user1' do
user = create(:user)
issue.update(assignee_ids: [developer.id, developer2.id, user.id])
_, updates = service.execute("/unassign @#{developer2.username} @#{developer.username}", issue)
expect(updates).to eq(assignee_ids: [user.id])
end
it 'unassigns all the users if content contains /unassign' do
issue.update(assignee_ids: [developer.id, developer2.id])
_, updates = service.execute('/unassign', issue)
it 'populates assignee_ids: [] if content contains /unassign' do
issue.update(assignee_ids: [developer.id])
_, updates = service.execute(content, issue)
expect(updates[:assignee_ids]).to be_empty
expect(updates).to eq(assignee_ids: [])
end
end
......@@ -493,22 +473,6 @@ describe QuickActions::InterpretService, services: true do
end
end
context 'reassign command' do
let(:content) { '/reassign' }
context 'Issue' do
it 'reassigns user if content contains /reassign @user' do
user = create(:user)
issue.update(assignee_ids: [developer.id])
_, updates = service.execute("/reassign @#{user.username}", issue)
expect(updates).to eq(assignee_ids: [user.id])
end
end
end
it_behaves_like 'milestone command' do
let(:content) { "/milestone %#{milestone.title}" }
let(:issuable) { issue }
......@@ -997,7 +961,7 @@ describe QuickActions::InterpretService, services: true do
it 'includes current assignee reference' do
_, explanations = service.explain(content, issue)
expect(explanations).to eq(["Removes assignee #{developer.to_reference}."])
expect(explanations).to eq(["Removes assignee @#{developer.username}."])
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment