Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
gitlab-ce
Commits
6297446d
Commit
6297446d
authored
Mar 01, 2018
by
Oswaldo Ferreira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move wip handling to MergeRequest::BaseService
parent
7b31095e
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
25 additions
and
1044 deletions
+25
-1044
app/services/issuable_base_service.rb
app/services/issuable_base_service.rb
+5
-16
app/services/merge_requests/base_service.rb
app/services/merge_requests/base_service.rb
+11
-0
app/services/merge_requests/create_service.rb
app/services/merge_requests/create_service.rb
+6
-0
app/services/quick_actions/interpret_service.rb
app/services/quick_actions/interpret_service.rb
+3
-3
app/services/slash_commands/interpret_service.rb
app/services/slash_commands/interpret_service.rb
+0
-336
spec/services/slash_commands/interpret_service_spec.rb
spec/services/slash_commands/interpret_service_spec.rb
+0
-689
No files found.
app/services/issuable_base_service.rb
View file @
6297446d
...
...
@@ -109,6 +109,10 @@ class IssuableBaseService < BaseService
@available_labels
||=
LabelsFinder
.
new
(
current_user
,
project_id:
@project
.
id
).
execute
end
def
handle_quick_actions
(
issuable
)
merge_quick_actions_into_params!
(
issuable
)
end
def
merge_quick_actions_into_params!
(
issuable
)
original_description
=
params
.
fetch
(
:description
,
issuable
.
description
)
...
...
@@ -131,8 +135,7 @@ class IssuableBaseService < BaseService
end
def
create
(
issuable
)
merge_quick_actions_into_params!
(
issuable
)
handle_wip_event
(
issuable
)
handle_quick_actions
(
issuable
)
filter_params
(
issuable
)
params
.
delete
(
:state_event
)
...
...
@@ -312,18 +315,4 @@ class IssuableBaseService < BaseService
def
parent
project
end
def
handle_wip_event
(
issuable
)
if
wip_event
=
params
.
delete
(
:wip_event
)
case
issuable
when
MergeRequest
# We update the title that is provided in the params or we use the mr title
title
=
params
[
:title
]
||
issuable
.
title
params
[
:title
]
=
case
wip_event
when
:wip
then
MergeRequest
.
wip_title
(
title
)
when
:unwip
then
MergeRequest
.
wipless_title
(
title
)
end
end
end
end
end
app/services/merge_requests/base_service.rb
View file @
6297446d
...
...
@@ -24,6 +24,17 @@ module MergeRequests
private
def
handle_wip_event
(
merge_request
)
if
wip_event
=
params
.
delete
(
:wip_event
)
# We update the title that is provided in the params or we use the mr title
title
=
params
[
:title
]
||
merge_request
.
title
params
[
:title
]
=
case
wip_event
when
'wip'
then
MergeRequest
.
wip_title
(
title
)
when
'unwip'
then
MergeRequest
.
wipless_title
(
title
)
end
end
end
def
merge_request_metrics_service
(
merge_request
)
MergeRequestMetricsService
.
new
(
merge_request
.
metrics
)
end
...
...
app/services/merge_requests/create_service.rb
View file @
6297446d
...
...
@@ -34,6 +34,12 @@ module MergeRequests
super
end
# Override from IssuableBaseService
def
handle_quick_actions
(
merge_request
)
super
handle_wip_event
(
merge_request
)
end
private
def
update_merge_requests_head_pipeline
(
merge_request
)
...
...
app/services/quick_actions/interpret_service.rb
View file @
6297446d
...
...
@@ -347,9 +347,9 @@ module QuickActions
"
#{
verb
}
this
#{
noun
}
as Work In Progress."
end
condition
do
issuable
.
persisted?
&&
issuable
.
respond_to?
(
:work_in_progress?
)
&&
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
issuable
.
respond_to?
(
:work_in_progress?
)
&&
# Allow it to mark as WIP on MR creation page _or_ through MR notes.
(
issuable
.
new_record?
||
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
)
end
command
:wip
do
@updates
[
:wip_event
]
=
issuable
.
work_in_progress?
?
'unwip'
:
'wip'
...
...
app/services/slash_commands/interpret_service.rb
deleted
100644 → 0
View file @
7b31095e
module
SlashCommands
class
InterpretService
<
BaseService
include
Gitlab
::
SlashCommands
::
Dsl
attr_reader
:issuable
,
:options
# Takes a text and interprets the commands that are extracted from it.
# Returns the content without commands, and hash of changes to be applied to a record.
def
execute
(
content
,
issuable
)
@issuable
=
issuable
@updates
=
{}
opts
=
{
issuable:
issuable
,
current_user:
current_user
,
project:
project
,
params:
params
}
content
,
commands
=
extractor
.
extract_commands
(
content
,
opts
)
commands
.
each
do
|
name
,
arg
|
definition
=
self
.
class
.
command_definitions_by_name
[
name
.
to_sym
]
next
unless
definition
definition
.
execute
(
self
,
opts
,
arg
)
end
[
content
,
@updates
]
end
private
def
extractor
Gitlab
::
SlashCommands
::
Extractor
.
new
(
self
.
class
.
command_definitions
)
end
desc
do
"Close this
#{
issuable
.
to_ability_name
.
humanize
(
capitalize:
false
)
}
"
end
condition
do
issuable
.
persisted?
&&
issuable
.
open?
&&
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
command
:close
do
@updates
[
:state_event
]
=
'close'
end
desc
do
"Reopen this
#{
issuable
.
to_ability_name
.
humanize
(
capitalize:
false
)
}
"
end
condition
do
issuable
.
persisted?
&&
issuable
.
closed?
&&
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
command
:reopen
do
@updates
[
:state_event
]
=
'reopen'
end
desc
'Merge (when build succeeds)'
condition
do
last_diff_sha
=
params
&&
params
[
:merge_request_diff_head_sha
]
issuable
.
is_a?
(
MergeRequest
)
&&
issuable
.
persisted?
&&
issuable
.
mergeable_with_slash_command?
(
current_user
,
autocomplete_precheck:
!
last_diff_sha
,
last_diff_sha:
last_diff_sha
)
end
command
:merge
do
@updates
[
:merge
]
=
params
[
:merge_request_diff_head_sha
]
end
desc
'Change title'
params
'<New title>'
condition
do
issuable
.
persisted?
&&
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
command
:title
do
|
title_param
|
@updates
[
:title
]
=
title_param
end
desc
'Assign'
params
'@user'
condition
do
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:assign
do
|
assignee_param
|
user
=
extract_references
(
assignee_param
,
:user
).
first
user
||=
User
.
find_by
(
username:
assignee_param
)
@updates
[
:assignee_id
]
=
user
.
id
if
user
end
desc
'Remove assignee'
condition
do
issuable
.
persisted?
&&
issuable
.
assignee_id?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:unassign
do
@updates
[
:assignee_id
]
=
nil
end
desc
'Set milestone'
params
'%"milestone"'
condition
do
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
&&
project
.
milestones
.
active
.
any?
end
command
:milestone
do
|
milestone_param
|
milestone
=
extract_references
(
milestone_param
,
:milestone
).
first
milestone
||=
project
.
milestones
.
find_by
(
title:
milestone_param
.
strip
)
@updates
[
:milestone_id
]
=
milestone
.
id
if
milestone
end
desc
'Remove milestone'
condition
do
issuable
.
persisted?
&&
issuable
.
milestone_id?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:remove_milestone
do
@updates
[
:milestone_id
]
=
nil
end
desc
'Add label(s)'
params
'~label1 ~"label 2"'
condition
do
available_labels
=
LabelsFinder
.
new
(
current_user
,
project_id:
project
.
id
).
execute
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
&&
available_labels
.
any?
end
command
:label
do
|
labels_param
|
label_ids
=
find_label_ids
(
labels_param
)
if
label_ids
.
any?
@updates
[
:add_label_ids
]
||=
[]
@updates
[
:add_label_ids
]
+=
label_ids
@updates
[
:add_label_ids
].
uniq!
end
end
desc
'Remove all or specific label(s)'
params
'~label1 ~"label 2"'
condition
do
issuable
.
persisted?
&&
issuable
.
labels
.
any?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:unlabel
do
|
labels_param
=
nil
|
if
labels_param
.
present?
label_ids
=
find_label_ids
(
labels_param
)
if
label_ids
.
any?
@updates
[
:remove_label_ids
]
||=
[]
@updates
[
:remove_label_ids
]
+=
label_ids
@updates
[
:remove_label_ids
].
uniq!
end
else
@updates
[
:label_ids
]
=
[]
end
end
desc
'Replace all label(s)'
params
'~label1 ~"label 2"'
condition
do
issuable
.
persisted?
&&
issuable
.
labels
.
any?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:relabel
do
|
labels_param
|
label_ids
=
find_label_ids
(
labels_param
)
if
label_ids
.
any?
@updates
[
:label_ids
]
||=
[]
@updates
[
:label_ids
]
+=
label_ids
@updates
[
:label_ids
].
uniq!
end
end
desc
'Add a todo'
condition
do
issuable
.
persisted?
&&
!
TodoService
.
new
.
todo_exist?
(
issuable
,
current_user
)
end
command
:todo
do
@updates
[
:todo_event
]
=
'add'
end
desc
'Mark todo as done'
condition
do
issuable
.
persisted?
&&
TodoService
.
new
.
todo_exist?
(
issuable
,
current_user
)
end
command
:done
do
@updates
[
:todo_event
]
=
'done'
end
desc
'Subscribe'
condition
do
issuable
.
persisted?
&&
!
issuable
.
subscribed?
(
current_user
,
project
)
end
command
:subscribe
do
@updates
[
:subscription_event
]
=
'subscribe'
end
desc
'Unsubscribe'
condition
do
issuable
.
persisted?
&&
issuable
.
subscribed?
(
current_user
,
project
)
end
command
:unsubscribe
do
@updates
[
:subscription_event
]
=
'unsubscribe'
end
desc
'Set due date'
params
'<in 2 days | this Friday | December 31st>'
condition
do
issuable
.
respond_to?
(
:due_date
)
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:due
do
|
due_date_param
|
due_date
=
Chronic
.
parse
(
due_date_param
).
try
(
:to_date
)
@updates
[
:due_date
]
=
due_date
if
due_date
end
desc
'Remove due date'
condition
do
issuable
.
persisted?
&&
issuable
.
respond_to?
(
:due_date
)
&&
issuable
.
due_date?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:remove_due_date
do
@updates
[
:due_date
]
=
nil
end
desc
do
"Toggle the Work In Progress status"
end
condition
do
issuable
.
respond_to?
(
:work_in_progress?
)
&&
(
# /wip on comment text on MR page
(
issuable
.
persisted?
&&
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
))
||
# /wip on create MR page
issuable
.
new_record?
)
end
command
:wip
do
@updates
[
:wip_event
]
=
issuable
.
work_in_progress?
?
:unwip
:
:wip
end
desc
'Set time estimate'
params
'<1w 3d 2h 14m>'
condition
do
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:estimate
do
|
raw_duration
|
time_estimate
=
Gitlab
::
TimeTrackingFormatter
.
parse
(
raw_duration
)
if
time_estimate
@updates
[
:time_estimate
]
=
time_estimate
end
end
desc
'Add or substract spent time'
params
'<1h 30m | -1h 30m>'
condition
do
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
command
:spend
do
|
raw_duration
|
time_spent
=
Gitlab
::
TimeTrackingFormatter
.
parse
(
raw_duration
)
if
time_spent
@updates
[
:spend_time
]
=
{
duration:
time_spent
,
user:
current_user
}
end
end
desc
'Remove time estimate'
condition
do
issuable
.
persisted?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:remove_estimate
do
@updates
[
:time_estimate
]
=
0
end
desc
'Remove spent time'
condition
do
issuable
.
persisted?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
command
:remove_time_spent
do
@updates
[
:spend_time
]
=
{
duration: :reset
,
user:
current_user
}
end
# This is a dummy command, so that it appears in the autocomplete commands
desc
'CC'
params
'@user'
command
:cc
desc
'Defines target branch for MR'
params
'<Local branch name>'
condition
do
issuable
.
respond_to?
(
:target_branch
)
&&
(
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
||
issuable
.
new_record?
)
end
command
:target_branch
do
|
target_branch_param
|
branch_name
=
target_branch_param
.
strip
@updates
[
:target_branch
]
=
branch_name
if
project
.
repository
.
branch_names
.
include?
(
branch_name
)
end
def
find_label_ids
(
labels_param
)
label_ids_by_reference
=
extract_references
(
labels_param
,
:label
).
map
(
&
:id
)
labels_ids_by_name
=
LabelsFinder
.
new
(
current_user
,
project_id:
project
.
id
,
name:
labels_param
.
split
).
execute
.
select
(
:id
)
label_ids_by_reference
|
labels_ids_by_name
end
def
extract_references
(
arg
,
type
)
ext
=
Gitlab
::
ReferenceExtractor
.
new
(
project
,
current_user
)
ext
.
analyze
(
arg
,
author:
current_user
)
ext
.
references
(
type
)
end
end
end
spec/services/slash_commands/interpret_service_spec.rb
deleted
100644 → 0
View file @
7b31095e
require
'spec_helper'
describe
SlashCommands
::
InterpretService
,
services:
true
do
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:developer
)
{
create
(
:user
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:milestone
)
{
create
(
:milestone
,
project:
project
,
title:
'9.10'
)
}
let
(
:inprogress
)
{
create
(
:label
,
project:
project
,
title:
'In Progress'
)
}
let
(
:bug
)
{
create
(
:label
,
project:
project
,
title:
'Bug'
)
}
let
(
:note
)
{
build
(
:note
,
commit_id:
merge_request
.
diff_head_sha
)
}
before
do
project
.
team
<<
[
developer
,
:developer
]
end
describe
'#execute'
do
let
(
:service
)
{
described_class
.
new
(
project
,
developer
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
)
}
shared_examples
'reopen command'
do
it
'returns state_event: "reopen" if content contains /reopen'
do
issuable
.
close!
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
state_event:
'reopen'
)
end
end
shared_examples
'close command'
do
it
'returns state_event: "close" if content contains /close'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
state_event:
'close'
)
end
end
shared_examples
'title command'
do
it
'populates title: "A brand new title" if content contains /title A brand new title'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
title:
'A brand new title'
)
end
end
shared_examples
'assign command'
do
it
'fetches assignee and populates assignee_id if content contains /assign'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
assignee_id:
developer
.
id
)
end
end
shared_examples
'unassign command'
do
it
'populates assignee_id: nil if content contains /unassign'
do
issuable
.
update
(
assignee_id:
developer
.
id
)
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
assignee_id:
nil
)
end
end
shared_examples
'milestone command'
do
it
'fetches milestone and populates milestone_id if content contains /milestone'
do
milestone
# populate the milestone
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
milestone_id:
milestone
.
id
)
end
end
shared_examples
'remove_milestone command'
do
it
'populates milestone_id: nil if content contains /remove_milestone'
do
issuable
.
update
(
milestone_id:
milestone
.
id
)
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
milestone_id:
nil
)
end
end
shared_examples
'label command'
do
it
'fetches label ids and populates add_label_ids if content contains /label'
do
bug
# populate the label
inprogress
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
add_label_ids:
[
bug
.
id
,
inprogress
.
id
])
end
end
shared_examples
'multiple label command'
do
it
'fetches label ids and populates add_label_ids if content contains multiple /label'
do
bug
# populate the label
inprogress
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
add_label_ids:
[
inprogress
.
id
,
bug
.
id
])
end
end
shared_examples
'multiple label with same argument'
do
it
'prevents duplicate label ids and populates add_label_ids if content contains multiple /label'
do
inprogress
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
add_label_ids:
[
inprogress
.
id
])
end
end
shared_examples
'unlabel command'
do
it
'fetches label ids and populates remove_label_ids if content contains /unlabel'
do
issuable
.
update
(
label_ids:
[
inprogress
.
id
])
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
remove_label_ids:
[
inprogress
.
id
])
end
end
shared_examples
'multiple unlabel command'
do
it
'fetches label ids and populates remove_label_ids if content contains mutiple /unlabel'
do
issuable
.
update
(
label_ids:
[
inprogress
.
id
,
bug
.
id
])
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
remove_label_ids:
[
inprogress
.
id
,
bug
.
id
])
end
end
shared_examples
'unlabel command with no argument'
do
it
'populates label_ids: [] if content contains /unlabel with no arguments'
do
issuable
.
update
(
label_ids:
[
inprogress
.
id
])
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
label_ids:
[])
end
end
shared_examples
'relabel command'
do
it
'populates label_ids: [] if content contains /relabel'
do
issuable
.
update
(
label_ids:
[
bug
.
id
])
# populate the label
inprogress
# populate the label
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
label_ids:
[
inprogress
.
id
])
end
end
shared_examples
'todo command'
do
it
'populates todo_event: "add" if content contains /todo'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
todo_event:
'add'
)
end
end
shared_examples
'done command'
do
it
'populates todo_event: "done" if content contains /done'
do
TodoService
.
new
.
mark_todo
(
issuable
,
developer
)
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
todo_event:
'done'
)
end
end
shared_examples
'subscribe command'
do
it
'populates subscription_event: "subscribe" if content contains /subscribe'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
subscription_event:
'subscribe'
)
end
end
shared_examples
'unsubscribe command'
do
it
'populates subscription_event: "unsubscribe" if content contains /unsubscribe'
do
issuable
.
subscribe
(
developer
,
project
)
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
subscription_event:
'unsubscribe'
)
end
end
shared_examples
'due command'
do
it
'populates due_date: Date.new(2016, 8, 28) if content contains /due 2016-08-28'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
due_date:
defined?
(
expected_date
)
?
expected_date
:
Date
.
new
(
2016
,
8
,
28
))
end
end
shared_examples
'remove_due_date command'
do
it
'populates due_date: nil if content contains /remove_due_date'
do
issuable
.
update
(
due_date:
Date
.
today
)
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
due_date:
nil
)
end
end
shared_examples
'wip command'
do
it
'returns wip_event: "wip" if content contains /wip'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
wip_event: :wip
)
end
end
shared_examples
'unwip command'
do
it
'returns wip_event: "unwip" if content contains /wip'
do
issuable
.
update
(
title:
issuable
.
wip_title
)
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
wip_event: :unwip
)
end
end
shared_examples
'estimate command'
do
it
'populates time_estimate: 3600 if content contains /estimate 1h'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
time_estimate:
3600
)
end
end
shared_examples
'spend command'
do
it
'populates spend_time: 3600 if content contains /spend 1h'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
spend_time:
{
duration:
3600
,
user:
developer
})
end
end
shared_examples
'spend command with negative time'
do
it
'populates spend_time: -1800 if content contains /spend -30m'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
spend_time:
{
duration:
-
1800
,
user:
developer
})
end
end
shared_examples
'remove_estimate command'
do
it
'populates time_estimate: 0 if content contains /remove_estimate'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
time_estimate:
0
)
end
end
shared_examples
'remove_time_spent command'
do
it
'populates spend_time: :reset if content contains /remove_time_spent'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
spend_time:
{
duration: :reset
,
user:
developer
})
end
end
shared_examples
'empty command'
do
it
'populates {} if content contains an unsupported command'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
be_empty
end
end
shared_examples
'merge command'
do
it
'runs merge command if content contains /merge'
do
_
,
updates
=
service
.
execute
(
content
,
issuable
)
expect
(
updates
).
to
eq
(
merge:
merge_request
.
diff_head_sha
)
end
end
it_behaves_like
'reopen command'
do
let
(
:content
)
{
'/reopen'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'reopen command'
do
let
(
:content
)
{
'/reopen'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'close command'
do
let
(
:content
)
{
'/close'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'close command'
do
let
(
:content
)
{
'/close'
}
let
(
:issuable
)
{
merge_request
}
end
context
'merge command'
do
let
(
:service
)
{
described_class
.
new
(
project
,
developer
,
{
merge_request_diff_head_sha:
merge_request
.
diff_head_sha
})
}
it_behaves_like
'merge command'
do
let
(
:content
)
{
'/merge'
}
let
(
:issuable
)
{
merge_request
}
end
context
'can not be merged when logged user does not have permissions'
do
let
(
:service
)
{
described_class
.
new
(
project
,
create
(
:user
))
}
it_behaves_like
'empty command'
do
let
(
:content
)
{
"/merge"
}
let
(
:issuable
)
{
merge_request
}
end
end
context
'can not be merged when sha does not match'
do
let
(
:service
)
{
described_class
.
new
(
project
,
developer
,
{
merge_request_diff_head_sha:
'othersha'
})
}
it_behaves_like
'empty command'
do
let
(
:content
)
{
"/merge"
}
let
(
:issuable
)
{
merge_request
}
end
end
context
'when sha is missing'
do
let
(
:service
)
{
described_class
.
new
(
project
,
developer
,
{})
}
it
'precheck passes and returns merge command'
do
_
,
updates
=
service
.
execute
(
'/merge'
,
merge_request
)
expect
(
updates
).
to
eq
(
merge:
nil
)
end
end
context
'issue can not be merged'
do
it_behaves_like
'empty command'
do
let
(
:content
)
{
"/merge"
}
let
(
:issuable
)
{
issue
}
end
end
context
'non persisted merge request cant be merged'
do
it_behaves_like
'empty command'
do
let
(
:content
)
{
"/merge"
}
let
(
:issuable
)
{
build
(
:merge_request
)
}
end
end
context
'not persisted merge request can not be merged'
do
it_behaves_like
'empty command'
do
let
(
:content
)
{
"/merge"
}
let
(
:issuable
)
{
build
(
:merge_request
,
source_project:
project
)
}
end
end
end
it_behaves_like
'title command'
do
let
(
:content
)
{
'/title A brand new title'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'title command'
do
let
(
:content
)
{
'/title A brand new title'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/title'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'assign command'
do
let
(
:content
)
{
"/assign @
#{
developer
.
username
}
"
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'assign command'
do
let
(
:content
)
{
"/assign @
#{
developer
.
username
}
"
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/assign @abcd1234'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/assign'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'unassign command'
do
let
(
:content
)
{
'/unassign'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'unassign command'
do
let
(
:content
)
{
'/unassign'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'milestone command'
do
let
(
:content
)
{
"/milestone %
#{
milestone
.
title
}
"
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'milestone command'
do
let
(
:content
)
{
"/milestone %
#{
milestone
.
title
}
"
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'remove_milestone command'
do
let
(
:content
)
{
'/remove_milestone'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'remove_milestone command'
do
let
(
:content
)
{
'/remove_milestone'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'label command'
do
let
(
:content
)
{
%(/label ~"#{inprogress.title}" ~#{bug.title} ~unknown)
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'label command'
do
let
(
:content
)
{
%(/label ~"#{inprogress.title}" ~#{bug.title} ~unknown)
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'multiple label command'
do
let
(
:content
)
{
%(/label ~"#{inprogress.title}" \n/label ~#{bug.title})
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'multiple label with same argument'
do
let
(
:content
)
{
%(/label ~"#{inprogress.title}" \n/label ~#{inprogress.title})
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'unlabel command'
do
let
(
:content
)
{
%(/unlabel ~"#{inprogress.title}")
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'unlabel command'
do
let
(
:content
)
{
%(/unlabel ~"#{inprogress.title}")
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'multiple unlabel command'
do
let
(
:content
)
{
%(/unlabel ~"#{inprogress.title}" \n/unlabel ~#{bug.title})
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'unlabel command with no argument'
do
let
(
:content
)
{
%(/unlabel)
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'unlabel command with no argument'
do
let
(
:content
)
{
%(/unlabel)
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'relabel command'
do
let
(
:content
)
{
%(/relabel ~"#{inprogress.title}")
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'relabel command'
do
let
(
:content
)
{
%(/relabel ~"#{inprogress.title}")
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'todo command'
do
let
(
:content
)
{
'/todo'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'todo command'
do
let
(
:content
)
{
'/todo'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'done command'
do
let
(
:content
)
{
'/done'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'done command'
do
let
(
:content
)
{
'/done'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'subscribe command'
do
let
(
:content
)
{
'/subscribe'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'subscribe command'
do
let
(
:content
)
{
'/subscribe'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'unsubscribe command'
do
let
(
:content
)
{
'/unsubscribe'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'unsubscribe command'
do
let
(
:content
)
{
'/unsubscribe'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'due command'
do
let
(
:content
)
{
'/due 2016-08-28'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'due command'
do
let
(
:content
)
{
'/due tomorrow'
}
let
(
:issuable
)
{
issue
}
let
(
:expected_date
)
{
Date
.
tomorrow
}
end
it_behaves_like
'due command'
do
let
(
:content
)
{
'/due 5 days from now'
}
let
(
:issuable
)
{
issue
}
let
(
:expected_date
)
{
5
.
days
.
from_now
.
to_date
}
end
it_behaves_like
'due command'
do
let
(
:content
)
{
'/due in 2 days'
}
let
(
:issuable
)
{
issue
}
let
(
:expected_date
)
{
2
.
days
.
from_now
.
to_date
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/due foo bar'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/due 2016-08-28'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'remove_due_date command'
do
let
(
:content
)
{
'/remove_due_date'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'wip command'
do
let
(
:content
)
{
'/wip'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'unwip command'
do
let
(
:content
)
{
'/wip'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/remove_due_date'
}
let
(
:issuable
)
{
merge_request
}
end
it_behaves_like
'estimate command'
do
let
(
:content
)
{
'/estimate 1h'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/estimate'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/estimate abc'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'spend command'
do
let
(
:content
)
{
'/spend 1h'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'spend command with negative time'
do
let
(
:content
)
{
'/spend -30m'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/spend'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/spend abc'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'remove_estimate command'
do
let
(
:content
)
{
'/remove_estimate'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'remove_time_spent command'
do
let
(
:content
)
{
'/remove_time_spent'
}
let
(
:issuable
)
{
issue
}
end
context
'when current_user cannot :admin_issue'
do
let
(
:visitor
)
{
create
(
:user
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
,
author:
visitor
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
visitor
)
}
it_behaves_like
'empty command'
do
let
(
:content
)
{
"/assign @
#{
developer
.
username
}
"
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/unassign'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
"/milestone %
#{
milestone
.
title
}
"
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/remove_milestone'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
%(/label ~"#{inprogress.title}" ~#{bug.title} ~unknown)
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
%(/unlabel ~"#{inprogress.title}")
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
%(/relabel ~"#{inprogress.title}")
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/due tomorrow'
}
let
(
:issuable
)
{
issue
}
end
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/remove_due_date'
}
let
(
:issuable
)
{
issue
}
end
end
context
'/target_branch command'
do
let
(
:non_empty_project
)
{
create
(
:project
)
}
let
(
:another_merge_request
)
{
create
(
:merge_request
,
author:
developer
,
source_project:
non_empty_project
)
}
let
(
:service
)
{
described_class
.
new
(
non_empty_project
,
developer
)}
it
'updates target_branch if /target_branch command is executed'
do
_
,
updates
=
service
.
execute
(
'/target_branch merge-test'
,
merge_request
)
expect
(
updates
).
to
eq
(
target_branch:
'merge-test'
)
end
it
'handles blanks around param'
do
_
,
updates
=
service
.
execute
(
'/target_branch merge-test '
,
merge_request
)
expect
(
updates
).
to
eq
(
target_branch:
'merge-test'
)
end
context
'ignores command with no argument'
do
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/target_branch'
}
let
(
:issuable
)
{
another_merge_request
}
end
end
context
'ignores non-existing target branch'
do
it_behaves_like
'empty command'
do
let
(
:content
)
{
'/target_branch totally_non_existing_branch'
}
let
(
:issuable
)
{
another_merge_request
}
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment