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
029b7d2e
Commit
029b7d2e
authored
Aug 13, 2016
by
Douwe Maan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed specs and fixes based on failing specs
parent
b2b1b4a4
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
365 additions
and
428 deletions
+365
-428
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+1
-7
app/services/notes/create_service.rb
app/services/notes/create_service.rb
+16
-7
app/services/notes/slash_commands_service.rb
app/services/notes/slash_commands_service.rb
+14
-5
app/services/slash_commands/interpret_service.rb
app/services/slash_commands/interpret_service.rb
+43
-36
lib/gitlab/slash_commands/command_definition.rb
lib/gitlab/slash_commands/command_definition.rb
+2
-9
lib/gitlab/slash_commands/dsl.rb
lib/gitlab/slash_commands/dsl.rb
+1
-4
lib/gitlab/slash_commands/extractor.rb
lib/gitlab/slash_commands/extractor.rb
+9
-3
spec/lib/gitlab/slash_commands/command_definition_spec.rb
spec/lib/gitlab/slash_commands/command_definition_spec.rb
+143
-0
spec/lib/gitlab/slash_commands/dsl_spec.rb
spec/lib/gitlab/slash_commands/dsl_spec.rb
+46
-154
spec/lib/gitlab/slash_commands/extractor_spec.rb
spec/lib/gitlab/slash_commands/extractor_spec.rb
+33
-22
spec/services/notes/create_service_spec.rb
spec/services/notes/create_service_spec.rb
+1
-1
spec/services/notes/slash_commands_service_spec.rb
spec/services/notes/slash_commands_service_spec.rb
+22
-11
spec/services/slash_commands/interpret_service_spec.rb
spec/services/slash_commands/interpret_service_spec.rb
+34
-169
No files found.
app/controllers/projects/issues_controller.rb
View file @
029b7d2e
...
@@ -176,12 +176,7 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -176,12 +176,7 @@ class Projects::IssuesController < Projects::ApplicationController
protected
protected
def
issue
def
issue
@noteable
=
@issue
||=
@noteable
=
@issue
||=
@project
.
issues
.
find_by
(
iid:
params
[
:id
])
||
redirect_old
begin
@project
.
issues
.
find_by!
(
iid:
params
[
:id
])
rescue
ActiveRecord
::
RecordNotFound
redirect_old
end
end
end
alias_method
:subscribable_resource
,
:issue
alias_method
:subscribable_resource
,
:issue
alias_method
:issuable
,
:issue
alias_method
:issuable
,
:issue
...
@@ -225,7 +220,6 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -225,7 +220,6 @@ class Projects::IssuesController < Projects::ApplicationController
if
issue
if
issue
redirect_to
issue_path
(
issue
)
redirect_to
issue_path
(
issue
)
return
else
else
raise
ActiveRecord
::
RecordNotFound
.
new
raise
ActiveRecord
::
RecordNotFound
.
new
end
end
...
...
app/services/notes/create_service.rb
View file @
029b7d2e
...
@@ -15,21 +15,30 @@ module Notes
...
@@ -15,21 +15,30 @@ module Notes
# **before** we save the note because if the note consists of commands
# **before** we save the note because if the note consists of commands
# only, there is no need be create a note!
# only, there is no need be create a note!
slash_commands_service
=
SlashCommandsService
.
new
(
project
,
current_user
)
slash_commands_service
=
SlashCommandsService
.
new
(
project
,
current_user
)
if
slash_commands_service
.
supported?
(
note
)
content
,
command_params
=
slash_commands_service
.
extract_commands
(
note
)
content
,
command_params
=
slash_commands_service
.
extract_commands
(
note
)
only_commands
=
content
.
empty?
note
.
note
=
content
note
.
note
=
content
end
if
note
.
save
if
!
only_commands
&&
note
.
save
# Finish the harder work in the background
# Finish the harder work in the background
NewNoteWorker
.
perform_in
(
2
.
seconds
,
note
.
id
,
params
)
NewNoteWorker
.
perform_in
(
2
.
seconds
,
note
.
id
,
params
)
todo_service
.
new_note
(
note
,
current_user
)
todo_service
.
new_note
(
note
,
current_user
)
end
end
if
command_params
&&
command_params
.
any?
slash_commands_service
.
execute
(
command_params
,
note
)
# We must add the error after we call #save because errors are reset
# We must add the error after we call #save because errors are reset
# when #save is called
# when #save is called
if
slash_commands_service
.
execute
(
command_params
,
note
)
&&
note
.
note
.
blank?
if
only_commands
note
.
errors
.
add
(
:commands_only
,
'Your commands have been executed!'
)
note
.
errors
.
add
(
:commands_only
,
'Your commands have been executed!'
)
end
end
end
note
note
end
end
...
...
app/services/notes/slash_commands_service.rb
View file @
029b7d2e
...
@@ -5,10 +5,13 @@ module Notes
...
@@ -5,10 +5,13 @@ module Notes
'MergeRequest'
=>
MergeRequests
::
UpdateService
'MergeRequest'
=>
MergeRequests
::
UpdateService
}
}
def
supported?
(
note
)
noteable_update_service
(
note
)
&&
can?
(
current_user
,
:"update_
#{
note
.
noteable_type
.
underscore
}
"
,
note
.
noteable
)
end
def
extract_commands
(
note
)
def
extract_commands
(
note
)
@noteable_update_service
=
UPDATE_SERVICES
[
note
.
noteable_type
]
return
[
note
.
note
,
{}]
unless
supported?
(
note
)
return
[]
unless
@noteable_update_service
return
[]
unless
can?
(
current_user
,
:"update_
#{
note
.
noteable_type
.
underscore
}
"
,
note
.
noteable
)
SlashCommands
::
InterpretService
.
new
(
project
,
current_user
).
SlashCommands
::
InterpretService
.
new
(
project
,
current_user
).
execute
(
note
.
note
,
note
.
noteable
)
execute
(
note
.
note
,
note
.
noteable
)
...
@@ -16,9 +19,15 @@ module Notes
...
@@ -16,9 +19,15 @@ module Notes
def
execute
(
command_params
,
note
)
def
execute
(
command_params
,
note
)
return
if
command_params
.
empty?
return
if
command_params
.
empty?
return
unless
supported?
(
note
)
noteable_update_service
(
note
).
new
(
project
,
current_user
,
command_params
).
execute
(
note
.
noteable
)
end
private
@noteable_update_service
.
new
(
project
,
current_user
,
command_params
).
def
noteable_update_service
(
note
)
execute
(
note
.
noteable
)
UPDATE_SERVICES
[
note
.
noteable_type
]
end
end
end
end
end
end
app/services/slash_commands/interpret_service.rb
View file @
029b7d2e
...
@@ -2,16 +2,16 @@ module SlashCommands
...
@@ -2,16 +2,16 @@ module SlashCommands
class
InterpretService
<
BaseService
class
InterpretService
<
BaseService
include
Gitlab
::
SlashCommands
::
Dsl
include
Gitlab
::
SlashCommands
::
Dsl
attr_reader
:
note
able
attr_reader
:
issu
able
# Takes a text and interpret the commands that are extracted from it.
# Takes a text and interpret the commands that are extracted from it.
# Returns a hash of changes to be applied to a record.
# Returns a hash of changes to be applied to a record.
def
execute
(
content
,
note
able
)
def
execute
(
content
,
issu
able
)
@
noteable
=
note
able
@
issuable
=
issu
able
@updates
=
{}
@updates
=
{}
opts
=
{
opts
=
{
noteable:
note
able
,
issuable:
issu
able
,
current_user:
current_user
,
current_user:
current_user
,
project:
project
project:
project
}
}
...
@@ -35,23 +35,24 @@ module SlashCommands
...
@@ -35,23 +35,24 @@ module SlashCommands
end
end
desc
do
desc
do
"Close this
#{
note
able
.
to_ability_name
.
humanize
(
capitalize:
false
)
}
"
"Close this
#{
issu
able
.
to_ability_name
.
humanize
(
capitalize:
false
)
}
"
end
end
condition
do
condition
do
note
able
.
persisted?
&&
issu
able
.
persisted?
&&
note
able
.
open?
&&
issu
able
.
open?
&&
current_user
.
can?
(
:"update_
#{
noteable
.
to_ability_name
}
"
,
note
able
)
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issu
able
)
end
end
command
:close
do
command
:close
do
@updates
[
:state_event
]
=
'close'
@updates
[
:state_event
]
=
'close'
end
end
desc
do
desc
do
"Reopen this
#{
note
able
.
to_ability_name
.
humanize
(
capitalize:
false
)
}
"
"Reopen this
#{
issu
able
.
to_ability_name
.
humanize
(
capitalize:
false
)
}
"
end
end
condition
do
condition
do
noteable
.
closed?
&&
issuable
.
persisted?
&&
current_user
.
can?
(
:"update_
#{
noteable
.
to_ability_name
}
"
,
noteable
)
issuable
.
closed?
&&
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
end
command
:reopen
,
:open
do
command
:reopen
,
:open
do
@updates
[
:state_event
]
=
'reopen'
@updates
[
:state_event
]
=
'reopen'
...
@@ -60,8 +61,8 @@ module SlashCommands
...
@@ -60,8 +61,8 @@ module SlashCommands
desc
'Change title'
desc
'Change title'
params
'<New title>'
params
'<New title>'
condition
do
condition
do
note
able
.
persisted?
&&
issu
able
.
persisted?
&&
current_user
.
can?
(
:"update_
#{
noteable
.
to_ability_name
}
"
,
note
able
)
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issu
able
)
end
end
command
:title
do
|
title_param
|
command
:title
do
|
title_param
|
@updates
[
:title
]
=
title_param
@updates
[
:title
]
=
title_param
...
@@ -70,7 +71,7 @@ module SlashCommands
...
@@ -70,7 +71,7 @@ module SlashCommands
desc
'Assign'
desc
'Assign'
params
'@user'
params
'@user'
condition
do
condition
do
current_user
.
can?
(
:"admin_
#{
note
able
.
to_ability_name
}
"
,
project
)
current_user
.
can?
(
:"admin_
#{
issu
able
.
to_ability_name
}
"
,
project
)
end
end
command
:assign
do
|
assignee_param
|
command
:assign
do
|
assignee_param
|
user
=
extract_references
(
assignee_param
,
:user
).
first
user
=
extract_references
(
assignee_param
,
:user
).
first
...
@@ -82,8 +83,9 @@ module SlashCommands
...
@@ -82,8 +83,9 @@ module SlashCommands
desc
'Remove assignee'
desc
'Remove assignee'
condition
do
condition
do
noteable
.
assignee_id?
&&
issuable
.
persisted?
&&
current_user
.
can?
(
:"admin_
#{
noteable
.
to_ability_name
}
"
,
project
)
issuable
.
assignee_id?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
end
command
:unassign
,
:remove_assignee
do
command
:unassign
,
:remove_assignee
do
@updates
[
:assignee_id
]
=
nil
@updates
[
:assignee_id
]
=
nil
...
@@ -92,7 +94,7 @@ module SlashCommands
...
@@ -92,7 +94,7 @@ module SlashCommands
desc
'Set milestone'
desc
'Set milestone'
params
'%"milestone"'
params
'%"milestone"'
condition
do
condition
do
current_user
.
can?
(
:"admin_
#{
note
able
.
to_ability_name
}
"
,
project
)
&&
current_user
.
can?
(
:"admin_
#{
issu
able
.
to_ability_name
}
"
,
project
)
&&
project
.
milestones
.
active
.
any?
project
.
milestones
.
active
.
any?
end
end
command
:milestone
do
|
milestone_param
|
command
:milestone
do
|
milestone_param
|
...
@@ -104,8 +106,9 @@ module SlashCommands
...
@@ -104,8 +106,9 @@ module SlashCommands
desc
'Remove milestone'
desc
'Remove milestone'
condition
do
condition
do
noteable
.
milestone_id?
&&
issuable
.
persisted?
&&
current_user
.
can?
(
:"admin_
#{
noteable
.
to_ability_name
}
"
,
project
)
issuable
.
milestone_id?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
end
command
:clear_milestone
,
:remove_milestone
do
command
:clear_milestone
,
:remove_milestone
do
@updates
[
:milestone_id
]
=
nil
@updates
[
:milestone_id
]
=
nil
...
@@ -114,7 +117,7 @@ module SlashCommands
...
@@ -114,7 +117,7 @@ module SlashCommands
desc
'Add label(s)'
desc
'Add label(s)'
params
'~label1 ~"label 2"'
params
'~label1 ~"label 2"'
condition
do
condition
do
current_user
.
can?
(
:"admin_
#{
note
able
.
to_ability_name
}
"
,
project
)
&&
current_user
.
can?
(
:"admin_
#{
issu
able
.
to_ability_name
}
"
,
project
)
&&
project
.
labels
.
any?
project
.
labels
.
any?
end
end
command
:label
,
:labels
do
|
labels_param
|
command
:label
,
:labels
do
|
labels_param
|
...
@@ -126,8 +129,9 @@ module SlashCommands
...
@@ -126,8 +129,9 @@ module SlashCommands
desc
'Remove label(s)'
desc
'Remove label(s)'
params
'~label1 ~"label 2"'
params
'~label1 ~"label 2"'
condition
do
condition
do
noteable
.
labels
.
any?
&&
issuable
.
persisted?
&&
current_user
.
can?
(
:"admin_
#{
noteable
.
to_ability_name
}
"
,
project
)
issuable
.
labels
.
any?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
end
command
:unlabel
,
:remove_label
,
:remove_labels
do
|
labels_param
|
command
:unlabel
,
:remove_label
,
:remove_labels
do
|
labels_param
|
label_ids
=
find_label_ids
(
labels_param
)
label_ids
=
find_label_ids
(
labels_param
)
...
@@ -137,8 +141,9 @@ module SlashCommands
...
@@ -137,8 +141,9 @@ module SlashCommands
desc
'Remove all labels'
desc
'Remove all labels'
condition
do
condition
do
noteable
.
labels
.
any?
&&
issuable
.
persisted?
&&
current_user
.
can?
(
:"admin_
#{
noteable
.
to_ability_name
}
"
,
project
)
issuable
.
labels
.
any?
&&
current_user
.
can?
(
:"admin_
#{
issuable
.
to_ability_name
}
"
,
project
)
end
end
command
:clear_labels
,
:clear_label
do
command
:clear_labels
,
:clear_label
do
@updates
[
:label_ids
]
=
[]
@updates
[
:label_ids
]
=
[]
...
@@ -146,8 +151,8 @@ module SlashCommands
...
@@ -146,8 +151,8 @@ module SlashCommands
desc
'Add a todo'
desc
'Add a todo'
condition
do
condition
do
note
able
.
persisted?
&&
issu
able
.
persisted?
&&
!
TodoService
.
new
.
todo_exist?
(
note
able
,
current_user
)
!
TodoService
.
new
.
todo_exist?
(
issu
able
,
current_user
)
end
end
command
:todo
do
command
:todo
do
@updates
[
:todo_event
]
=
'add'
@updates
[
:todo_event
]
=
'add'
...
@@ -155,7 +160,8 @@ module SlashCommands
...
@@ -155,7 +160,8 @@ module SlashCommands
desc
'Mark todo as done'
desc
'Mark todo as done'
condition
do
condition
do
TodoService
.
new
.
todo_exist?
(
noteable
,
current_user
)
issuable
.
persisted?
&&
TodoService
.
new
.
todo_exist?
(
issuable
,
current_user
)
end
end
command
:done
do
command
:done
do
@updates
[
:todo_event
]
=
'done'
@updates
[
:todo_event
]
=
'done'
...
@@ -163,8 +169,8 @@ module SlashCommands
...
@@ -163,8 +169,8 @@ module SlashCommands
desc
'Subscribe'
desc
'Subscribe'
condition
do
condition
do
note
able
.
persisted?
&&
issu
able
.
persisted?
&&
!
note
able
.
subscribed?
(
current_user
)
!
issu
able
.
subscribed?
(
current_user
)
end
end
command
:subscribe
do
command
:subscribe
do
@updates
[
:subscription_event
]
=
'subscribe'
@updates
[
:subscription_event
]
=
'subscribe'
...
@@ -172,8 +178,8 @@ module SlashCommands
...
@@ -172,8 +178,8 @@ module SlashCommands
desc
'Unsubscribe'
desc
'Unsubscribe'
condition
do
condition
do
note
able
.
persisted?
&&
issu
able
.
persisted?
&&
note
able
.
subscribed?
(
current_user
)
issu
able
.
subscribed?
(
current_user
)
end
end
command
:unsubscribe
do
command
:unsubscribe
do
@updates
[
:subscription_event
]
=
'unsubscribe'
@updates
[
:subscription_event
]
=
'unsubscribe'
...
@@ -182,8 +188,8 @@ module SlashCommands
...
@@ -182,8 +188,8 @@ module SlashCommands
desc
'Set due date'
desc
'Set due date'
params
'<in 2 days; this Friday; December 31st>'
params
'<in 2 days; this Friday; December 31st>'
condition
do
condition
do
note
able
.
respond_to?
(
:due_date
)
&&
issu
able
.
respond_to?
(
:due_date
)
&&
current_user
.
can?
(
:"update_
#{
noteable
.
to_ability_name
}
"
,
note
able
)
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issu
able
)
end
end
command
:due
,
:due_date
do
|
due_date_param
|
command
:due
,
:due_date
do
|
due_date_param
|
due_date
=
Chronic
.
parse
(
due_date_param
).
try
(
:to_date
)
due_date
=
Chronic
.
parse
(
due_date_param
).
try
(
:to_date
)
...
@@ -193,9 +199,10 @@ module SlashCommands
...
@@ -193,9 +199,10 @@ module SlashCommands
desc
'Remove due date'
desc
'Remove due date'
condition
do
condition
do
noteable
.
respond_to?
(
:due_date
)
&&
issuable
.
persisted?
&&
noteable
.
due_date?
&&
issuable
.
respond_to?
(
:due_date
)
&&
current_user
.
can?
(
:"update_
#{
noteable
.
to_ability_name
}
"
,
noteable
)
issuable
.
due_date?
&&
current_user
.
can?
(
:"update_
#{
issuable
.
to_ability_name
}
"
,
issuable
)
end
end
command
:clear_due_date
do
command
:clear_due_date
do
@updates
[
:due_date
]
=
nil
@updates
[
:due_date
]
=
nil
...
...
lib/gitlab/slash_commands/command_definition.rb
View file @
029b7d2e
...
@@ -3,8 +3,8 @@ module Gitlab
...
@@ -3,8 +3,8 @@ module Gitlab
class
CommandDefinition
class
CommandDefinition
attr_accessor
:name
,
:aliases
,
:description
,
:params
,
:condition_block
,
:action_block
attr_accessor
:name
,
:aliases
,
:description
,
:params
,
:condition_block
,
:action_block
def
valid?
def
initialize
(
name
)
name
.
present?
@name
=
name
end
end
def
all_names
def
all_names
...
@@ -22,13 +22,6 @@ module Gitlab
...
@@ -22,13 +22,6 @@ module Gitlab
context
.
instance_exec
(
&
condition_block
)
context
.
instance_exec
(
&
condition_block
)
end
end
def
to_description
(
opts
)
return
description
unless
description
.
respond_to?
(
:call
)
context
=
OpenStruct
.
new
(
opts
)
context
.
instance_exec
(
&
description
)
rescue
''
end
def
execute
(
context
,
opts
,
*
args
)
def
execute
(
context
,
opts
,
*
args
)
return
if
noop?
||
!
available?
(
opts
)
return
if
noop?
||
!
available?
(
opts
)
...
...
lib/gitlab/slash_commands/dsl.rb
View file @
029b7d2e
...
@@ -73,16 +73,13 @@ module Gitlab
...
@@ -73,16 +73,13 @@ module Gitlab
def
command
(
*
command_names
,
&
block
)
def
command
(
*
command_names
,
&
block
)
name
,
*
aliases
=
command_names
name
,
*
aliases
=
command_names
definition
=
CommandDefinition
.
new
definition
=
CommandDefinition
.
new
(
name
)
definition
.
name
=
name
definition
.
aliases
=
aliases
definition
.
aliases
=
aliases
definition
.
description
=
@description
||
''
definition
.
description
=
@description
||
''
definition
.
params
=
@params
||
[]
definition
.
params
=
@params
||
[]
definition
.
condition_block
=
@condition_block
definition
.
condition_block
=
@condition_block
definition
.
action_block
=
block
definition
.
action_block
=
block
return
unless
definition
.
valid?
self
.
command_definitions
<<
definition
self
.
command_definitions
<<
definition
definition
.
all_names
.
each
do
|
name
|
definition
.
all_names
.
each
do
|
name
|
...
...
lib/gitlab/slash_commands/extractor.rb
View file @
029b7d2e
...
@@ -29,8 +29,8 @@ module Gitlab
...
@@ -29,8 +29,8 @@ module Gitlab
# commands = extractor.extract_commands(msg) #=> [['labels', '~foo ~"bar baz"']]
# commands = extractor.extract_commands(msg) #=> [['labels', '~foo ~"bar baz"']]
# msg #=> "hello\nworld"
# msg #=> "hello\nworld"
# ```
# ```
def
extract_commands
(
content
,
opts
)
def
extract_commands
(
content
,
opts
=
{}
)
return
[]
unless
content
return
[
content
,
[]
]
unless
content
content
=
content
.
dup
content
=
content
.
dup
...
@@ -107,7 +107,13 @@ module Gitlab
...
@@ -107,7 +107,13 @@ module Gitlab
# Command not in a blockquote, blockcode, or HTML tag:
# Command not in a blockquote, blockcode, or HTML tag:
# /close
# /close
^
\/
(?<cmd>
#{
Regexp
.
union
(
names
)
}
)(?:$|
\
(?<args>[^
\/\n
]*)$)
^
\/
(?<cmd>
#{
Regexp
.
union
(
names
)
}
)
(?:
[ ]
(?<args>[^
\/\n
]*)
)?
(?:
\n
|$)
)
)
}mx
}mx
end
end
...
...
spec/lib/gitlab/slash_commands/command_definition_spec.rb
0 → 100644
View file @
029b7d2e
require
'spec_helper'
describe
Gitlab
::
SlashCommands
::
CommandDefinition
do
subject
{
described_class
.
new
(
:command
)
}
describe
"#all_names"
do
context
"when the command has aliases"
do
before
do
subject
.
aliases
=
[
:alias1
,
:alias2
]
end
it
"returns an array with the name and aliases"
do
expect
(
subject
.
all_names
).
to
eq
([
:command
,
:alias1
,
:alias2
])
end
end
context
"when the command doesn't have aliases"
do
it
"returns an array with the name"
do
expect
(
subject
.
all_names
).
to
eq
([
:command
])
end
end
end
describe
"#noop?"
do
context
"when the command has an action block"
do
before
do
subject
.
action_block
=
->
{
}
end
it
"returns false"
do
expect
(
subject
.
noop?
).
to
be
false
end
end
context
"when the command doesn't have an action block"
do
it
"returns true"
do
expect
(
subject
.
noop?
).
to
be
true
end
end
end
describe
"#available?"
do
let
(
:opts
)
{
{
go:
false
}
}
context
"when the command has a condition block"
do
before
do
subject
.
condition_block
=
->
{
go
}
end
context
"when the condition block returns true"
do
before
do
opts
[
:go
]
=
true
end
it
"returns true"
do
expect
(
subject
.
available?
(
opts
)).
to
be
true
end
end
context
"when the condition block returns false"
do
it
"returns false"
do
expect
(
subject
.
available?
(
opts
)).
to
be
false
end
end
end
context
"when the command doesn't have a condition block"
do
it
"returns true"
do
expect
(
subject
.
available?
(
opts
)).
to
be
true
end
end
end
describe
"#execute"
do
let
(
:context
)
{
OpenStruct
.
new
(
run:
false
)
}
context
"when the command is a noop"
do
it
"doesn't execute the command"
do
expect
(
context
).
not_to
receive
(
:instance_exec
)
subject
.
execute
(
context
,
{})
expect
(
context
.
run
).
to
be
false
end
end
context
"when the command is not a noop"
do
before
do
subject
.
action_block
=
->
{
self
.
run
=
true
}
end
context
"when the command is not available"
do
before
do
subject
.
condition_block
=
->
{
false
}
end
it
"doesn't execute the command"
do
subject
.
execute
(
context
,
{})
expect
(
context
.
run
).
to
be
false
end
end
context
"when the command is available"
do
context
"when the command has an exact number of arguments"
do
before
do
subject
.
action_block
=
->
(
arg
)
{
self
.
run
=
arg
}
end
context
"when the command is provided a wrong number of arguments"
do
it
"doesn't execute the command"
do
subject
.
execute
(
context
,
{},
true
,
true
)
expect
(
context
.
run
).
to
be
false
end
end
context
"when the command is provided the right number of arguments"
do
it
"executes the command"
do
subject
.
execute
(
context
,
{},
true
)
expect
(
context
.
run
).
to
be
true
end
end
end
context
"when the command has a variable number of arguments"
do
before
do
subject
.
action_block
=
->
(
*
args
)
{
self
.
run
=
args
.
first
}
end
context
"when the command is provided any number of arguments"
do
it
"executes the command"
do
subject
.
execute
(
context
,
{},
true
,
true
)
expect
(
context
.
run
).
to
be
true
end
end
end
end
end
end
end
spec/lib/gitlab/slash_commands/dsl_spec.rb
View file @
029b7d2e
...
@@ -10,9 +10,9 @@ describe Gitlab::SlashCommands::Dsl do
...
@@ -10,9 +10,9 @@ describe Gitlab::SlashCommands::Dsl do
"Hello World!"
"Hello World!"
end
end
desc
'A command returning a value'
desc
{
"A command with
#{
something
}
"
}
command
:returning
do
command
:returning
do
return
42
42
end
end
params
'The first argument'
params
'The first argument'
...
@@ -28,7 +28,7 @@ describe Gitlab::SlashCommands::Dsl do
...
@@ -28,7 +28,7 @@ describe Gitlab::SlashCommands::Dsl do
[
arg1
,
arg2
]
[
arg1
,
arg2
]
end
end
command
:cc
,
noop:
true
command
:cc
condition
do
condition
do
project
==
'foo'
project
==
'foo'
...
@@ -49,182 +49,74 @@ describe Gitlab::SlashCommands::Dsl do
...
@@ -49,182 +49,74 @@ describe Gitlab::SlashCommands::Dsl do
{
{
name: :no_args
,
aliases:
[
:none
],
name: :no_args
,
aliases:
[
:none
],
description:
'A command with no args'
,
params:
[],
description:
'A command with no args'
,
params:
[],
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
),
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
)
opts:
{}
},
},
{
{
name: :returning
,
aliases:
[],
name: :returning
,
aliases:
[],
description:
'A command returning a value'
,
params:
[],
description:
'A command returning a value'
,
params:
[],
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
),
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
)
opts:
{}
},
},
{
{
name: :one_arg
,
aliases:
[
:once
,
:first
],
name: :one_arg
,
aliases:
[
:once
,
:first
],
description:
''
,
params:
[
'The first argument'
],
description:
''
,
params:
[
'The first argument'
],
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
),
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
)
opts:
{}
},
},
{
{
name: :two_args
,
aliases:
[],
name: :two_args
,
aliases:
[],
description:
''
,
params:
[
'The first argument'
,
'The second argument'
],
description:
''
,
params:
[
'The first argument'
,
'The second argument'
],
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
),
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
)
opts:
{}
},
},
{
{
name: :cc
,
aliases:
[],
name: :cc
,
aliases:
[],
description:
''
,
params:
[],
description:
''
,
params:
[],
condition_block:
nil
,
action_block:
nil
,
condition_block:
nil
,
action_block:
nil
opts:
{
noop:
true
}
},
},
{
{
name: :wildcard
,
aliases:
[],
name: :wildcard
,
aliases:
[],
description:
''
,
params:
[],
description:
''
,
params:
[],
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
),
condition_block:
nil
,
action_block:
a_kind_of
(
Proc
)
opts:
{}
}
}
]
]
end
end
it
'returns an array with commands definitions'
do
it
'returns an array with commands definitions'
do
expect
(
DummyClass
.
command_definitions
).
to
match_array
base_expected
no_args_def
,
returning_def
,
one_arg_def
,
two_args_def
,
cc_def
,
cond_action_def
,
wildcard_def
=
DummyClass
.
command_definitions
end
expect
(
no_args_def
.
name
).
to
eq
(
:no_args
)
context
'with options passed'
do
expect
(
no_args_def
.
aliases
).
to
eq
([
:none
])
context
'when condition is met'
do
expect
(
no_args_def
.
description
).
to
eq
(
'A command with no args'
)
let
(
:expected
)
do
expect
(
no_args_def
.
params
).
to
eq
([])
base_expected
<<
{
expect
(
no_args_def
.
condition_block
).
to
be_nil
name: :cond_action
,
aliases:
[],
expect
(
no_args_def
.
action_block
).
to
be_a_kind_of
(
Proc
)
description:
''
,
params:
[],
condition_block:
a_kind_of
(
Proc
),
action_block:
a_kind_of
(
Proc
),
expect
(
returning_def
.
name
).
to
eq
(
:returning
)
opts:
{}
expect
(
returning_def
.
aliases
).
to
eq
([])
}
expect
(
returning_def
.
description
).
to
be_a_kind_of
(
Proc
)
end
expect
(
returning_def
.
to_h
(
something:
"a block description"
)[
:description
]).
to
eq
(
'A command with a block description'
)
expect
(
returning_def
.
params
).
to
eq
([])
it
'returns an array with commands definitions'
do
expect
(
returning_def
.
condition_block
).
to
be_nil
expect
(
DummyClass
.
command_definitions
(
project:
'foo'
)).
to
match_array
expected
expect
(
returning_def
.
action_block
).
to
be_a_kind_of
(
Proc
)
end
end
expect
(
one_arg_def
.
name
).
to
eq
(
:one_arg
)
expect
(
one_arg_def
.
aliases
).
to
eq
([
:once
,
:first
])
context
'when condition is not met'
do
expect
(
one_arg_def
.
description
).
to
eq
(
''
)
it
'returns an array with commands definitions without actions that did not met conditions'
do
expect
(
one_arg_def
.
params
).
to
eq
([
'The first argument'
])
expect
(
DummyClass
.
command_definitions
(
project:
'bar'
)).
to
match_array
base_expected
expect
(
one_arg_def
.
condition_block
).
to
be_nil
end
expect
(
one_arg_def
.
action_block
).
to
be_a_kind_of
(
Proc
)
end
expect
(
cc_def
.
name
).
to
eq
(
:cc
)
context
'when description can be generated dynamically'
do
expect
(
cc_def
.
aliases
).
to
eq
([])
it
'returns an array with commands definitions with dynamic descriptions'
do
expect
(
cc_def
.
description
).
to
eq
(
''
)
base_expected
[
3
][
:description
]
=
'A dynamic description for MERGE REQUEST'
expect
(
cc_def
.
params
).
to
eq
([])
expect
(
cc_def
.
condition_block
).
to
be_nil
expect
(
DummyClass
.
command_definitions
(
noteable:
'merge request'
)).
to
match_array
base_expected
expect
(
cc_def
.
action_block
).
to
be_nil
end
end
expect
(
wildcard_def
.
name
).
to
eq
(
:wildcard
)
end
expect
(
wildcard_def
.
aliases
).
to
eq
([])
end
expect
(
wildcard_def
.
description
).
to
eq
(
''
)
expect
(
wildcard_def
.
params
).
to
eq
([])
describe
'.command_names'
do
expect
(
wildcard_def
.
condition_block
).
to
be_nil
let
(
:base_expected
)
do
expect
(
wildcard_def
.
action_block
).
to
be_a_kind_of
(
Proc
)
[
:no_args
,
:none
,
:returning
,
:one_arg
,
:once
,
:first
,
:two_args
,
:wildcard
]
end
it
'returns an array with commands definitions'
do
expect
(
DummyClass
.
command_names
).
to
eq
base_expected
end
context
'with options passed'
do
context
'when condition is met'
do
let
(
:expected
)
{
base_expected
<<
:cond_action
}
it
'returns an array with commands definitions'
do
expect
(
DummyClass
.
command_names
(
project:
'foo'
)).
to
match_array
expected
end
end
context
'when condition is not met'
do
it
'returns an array with commands definitions without action that did not met conditions'
do
expect
(
DummyClass
.
command_names
(
project:
'bar'
)).
to
match_array
base_expected
end
end
end
end
let
(
:dummy
)
{
DummyClass
.
new
(
nil
)
}
describe
'#execute_command'
do
describe
'command with no args'
do
context
'called with no args'
do
it
'succeeds'
do
expect
(
dummy
.
execute_command
(
:no_args
)).
to
eq
'Hello World!'
end
end
end
describe
'command with an explicit return'
do
context
'called with no args'
do
it
'succeeds'
do
expect
{
dummy
.
execute_command
(
:returning
)
}.
to
raise_error
(
LocalJumpError
)
end
end
end
describe
'command with one arg'
do
context
'called with one arg'
do
it
'succeeds'
do
expect
(
dummy
.
execute_command
(
:one_arg
,
42
)).
to
eq
42
end
end
end
describe
'command with two args'
do
context
'called with two args'
do
it
'succeeds'
do
expect
(
dummy
.
execute_command
(
:two_args
,
42
,
'foo'
)).
to
eq
[
42
,
'foo'
]
end
end
end
describe
'noop command'
do
it
'returns nil'
do
expect
(
dummy
.
execute_command
(
:cc
)).
to
be_nil
end
end
describe
'command with condition'
do
context
'when condition is not met'
do
it
'returns nil'
do
expect
(
dummy
.
execute_command
(
:cond_action
)).
to
be_nil
end
end
context
'when condition is met'
do
let
(
:dummy
)
{
DummyClass
.
new
(
'foo'
)
}
it
'succeeds'
do
expect
(
dummy
.
execute_command
(
:cond_action
,
42
)).
to
eq
42
end
end
end
describe
'command with wildcard'
do
context
'called with no args'
do
it
'succeeds'
do
expect
(
dummy
.
execute_command
(
:wildcard
)).
to
eq
[]
end
end
context
'called with one arg'
do
it
'succeeds'
do
expect
(
dummy
.
execute_command
(
:wildcard
,
42
)).
to
eq
[
42
]
end
end
context
'called with two args'
do
it
'succeeds'
do
expect
(
dummy
.
execute_command
(
:wildcard
,
42
,
'foo'
)).
to
eq
[
42
,
'foo'
]
end
end
end
end
end
end
end
end
spec/lib/gitlab/slash_commands/extractor_spec.rb
View file @
029b7d2e
require
'spec_helper'
require
'spec_helper'
describe
Gitlab
::
SlashCommands
::
Extractor
do
describe
Gitlab
::
SlashCommands
::
Extractor
do
let
(
:extractor
)
{
described_class
.
new
([
:open
,
:assign
,
:labels
,
:power
])
}
let
(
:definitions
)
do
Class
.
new
do
include
Gitlab
::
SlashCommands
::
Dsl
command
(
:reopen
,
:open
)
{
}
command
(
:assign
)
{
}
command
(
:labels
)
{
}
command
(
:power
)
{
}
end
.
command_definitions
end
let
(
:extractor
)
{
described_class
.
new
(
definitions
)
}
shared_examples
'command with no argument'
do
shared_examples
'command with no argument'
do
it
'extracts command'
do
it
'extracts command'
do
commands
=
extractor
.
extract_commands
(
original_msg
)
msg
,
commands
=
extractor
.
extract_commands
(
original_msg
)
expect
(
commands
).
to
eq
[[
'open'
]]
expect
(
commands
).
to
eq
[[
'open'
]]
expect
(
original_
msg
).
to
eq
final_msg
expect
(
msg
).
to
eq
final_msg
end
end
end
end
shared_examples
'command with a single argument'
do
shared_examples
'command with a single argument'
do
it
'extracts command'
do
it
'extracts command'
do
commands
=
extractor
.
extract_commands
(
original_msg
)
msg
,
commands
=
extractor
.
extract_commands
(
original_msg
)
expect
(
commands
).
to
eq
[[
'assign'
,
'@joe'
]]
expect
(
commands
).
to
eq
[[
'assign'
,
'@joe'
]]
expect
(
original_
msg
).
to
eq
final_msg
expect
(
msg
).
to
eq
final_msg
end
end
end
end
shared_examples
'command with multiple arguments'
do
shared_examples
'command with multiple arguments'
do
it
'extracts command'
do
it
'extracts command'
do
commands
=
extractor
.
extract_commands
(
original_msg
)
msg
,
commands
=
extractor
.
extract_commands
(
original_msg
)
expect
(
commands
).
to
eq
[[
'labels'
,
'~foo ~"bar baz" label'
]]
expect
(
commands
).
to
eq
[[
'labels'
,
'~foo ~"bar baz" label'
]]
expect
(
original_
msg
).
to
eq
final_msg
expect
(
msg
).
to
eq
final_msg
end
end
end
end
...
@@ -49,7 +60,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -49,7 +60,7 @@ describe Gitlab::SlashCommands::Extractor do
context
'in the middle of a line'
do
context
'in the middle of a line'
do
it
'does not extract command'
do
it
'does not extract command'
do
msg
=
"hello
\n
world /open"
msg
=
"hello
\n
world /open"
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
"hello
\n
world /open"
expect
(
msg
).
to
eq
"hello
\n
world /open"
...
@@ -59,7 +70,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -59,7 +70,7 @@ describe Gitlab::SlashCommands::Extractor do
context
'at the end of content'
do
context
'at the end of content'
do
it_behaves_like
'command with no argument'
do
it_behaves_like
'command with no argument'
do
let
(
:original_msg
)
{
"hello
\n
/open"
}
let
(
:original_msg
)
{
"hello
\n
/open"
}
let
(
:final_msg
)
{
"hello
\n
"
}
let
(
:final_msg
)
{
"hello"
}
end
end
end
end
end
end
...
@@ -82,7 +93,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -82,7 +93,7 @@ describe Gitlab::SlashCommands::Extractor do
context
'in the middle of a line'
do
context
'in the middle of a line'
do
it
'does not extract command'
do
it
'does not extract command'
do
msg
=
"hello
\n
world /assign @joe"
msg
=
"hello
\n
world /assign @joe"
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
"hello
\n
world /assign @joe"
expect
(
msg
).
to
eq
"hello
\n
world /assign @joe"
...
@@ -92,14 +103,14 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -92,14 +103,14 @@ describe Gitlab::SlashCommands::Extractor do
context
'at the end of content'
do
context
'at the end of content'
do
it_behaves_like
'command with a single argument'
do
it_behaves_like
'command with a single argument'
do
let
(
:original_msg
)
{
"hello
\n
/assign @joe"
}
let
(
:original_msg
)
{
"hello
\n
/assign @joe"
}
let
(
:final_msg
)
{
"hello
\n
"
}
let
(
:final_msg
)
{
"hello"
}
end
end
end
end
context
'when argument is not separated with a space'
do
context
'when argument is not separated with a space'
do
it
'does not extract command'
do
it
'does not extract command'
do
msg
=
"hello
\n
/assign@joe
\n
world"
msg
=
"hello
\n
/assign@joe
\n
world"
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
"hello
\n
/assign@joe
\n
world"
expect
(
msg
).
to
eq
"hello
\n
/assign@joe
\n
world"
...
@@ -125,7 +136,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -125,7 +136,7 @@ describe Gitlab::SlashCommands::Extractor do
context
'in the middle of a line'
do
context
'in the middle of a line'
do
it
'does not extract command'
do
it
'does not extract command'
do
msg
=
%(hello\nworld /labels ~foo ~"bar baz" label)
msg
=
%(hello\nworld /labels ~foo ~"bar baz" label)
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
%(hello\nworld /labels ~foo ~"bar baz" label)
expect
(
msg
).
to
eq
%(hello\nworld /labels ~foo ~"bar baz" label)
...
@@ -135,14 +146,14 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -135,14 +146,14 @@ describe Gitlab::SlashCommands::Extractor do
context
'at the end of content'
do
context
'at the end of content'
do
it_behaves_like
'command with multiple arguments'
do
it_behaves_like
'command with multiple arguments'
do
let
(
:original_msg
)
{
%(hello\n/labels ~foo ~"bar baz" label)
}
let
(
:original_msg
)
{
%(hello\n/labels ~foo ~"bar baz" label)
}
let
(
:final_msg
)
{
"hello
\n
"
}
let
(
:final_msg
)
{
"hello"
}
end
end
end
end
context
'when argument is not separated with a space'
do
context
'when argument is not separated with a space'
do
it
'does not extract command'
do
it
'does not extract command'
do
msg
=
%(hello\n/labels~foo ~"bar baz" label\nworld)
msg
=
%(hello\n/labels~foo ~"bar baz" label\nworld)
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
%(hello\n/labels~foo ~"bar baz" label\nworld)
expect
(
msg
).
to
eq
%(hello\n/labels~foo ~"bar baz" label\nworld)
...
@@ -152,7 +163,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -152,7 +163,7 @@ describe Gitlab::SlashCommands::Extractor do
it
'extracts command with multiple arguments and various prefixes'
do
it
'extracts command with multiple arguments and various prefixes'
do
msg
=
%(hello\n/power @user.name %9.10 ~"bar baz.2"\nworld)
msg
=
%(hello\n/power @user.name %9.10 ~"bar baz.2"\nworld)
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
eq
[[
'power'
,
'@user.name %9.10 ~"bar baz.2"'
]]
expect
(
commands
).
to
eq
[[
'power'
,
'@user.name %9.10 ~"bar baz.2"'
]]
expect
(
msg
).
to
eq
"hello
\n
world"
expect
(
msg
).
to
eq
"hello
\n
world"
...
@@ -160,15 +171,15 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -160,15 +171,15 @@ describe Gitlab::SlashCommands::Extractor do
it
'extracts multiple commands'
do
it
'extracts multiple commands'
do
msg
=
%(hello\n/power @user.name %9.10 ~"bar baz.2" label\nworld\n/open)
msg
=
%(hello\n/power @user.name %9.10 ~"bar baz.2" label\nworld\n/open)
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
eq
[[
'power'
,
'@user.name %9.10 ~"bar baz.2" label'
],
[
'open'
]]
expect
(
commands
).
to
eq
[[
'power'
,
'@user.name %9.10 ~"bar baz.2" label'
],
[
'open'
]]
expect
(
msg
).
to
eq
"hello
\n
world
\n
"
expect
(
msg
).
to
eq
"hello
\n
world"
end
end
it
'does not alter original content if no command is found'
do
it
'does not alter original content if no command is found'
do
msg
=
'Fixes #123'
msg
=
'Fixes #123'
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
'Fixes #123'
expect
(
msg
).
to
eq
'Fixes #123'
...
@@ -177,7 +188,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -177,7 +188,7 @@ describe Gitlab::SlashCommands::Extractor do
it
'does not extract commands inside a blockcode'
do
it
'does not extract commands inside a blockcode'
do
msg
=
"Hello
\r\n
```
\r\n
This is some text
\r\n
/close
\r\n
/assign @user
\r\n
```
\r\n\r\n
World"
msg
=
"Hello
\r\n
```
\r\n
This is some text
\r\n
/close
\r\n
/assign @user
\r\n
```
\r\n\r\n
World"
expected
=
msg
.
delete
(
"
\r
"
)
expected
=
msg
.
delete
(
"
\r
"
)
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
expected
expect
(
msg
).
to
eq
expected
...
@@ -186,7 +197,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -186,7 +197,7 @@ describe Gitlab::SlashCommands::Extractor do
it
'does not extract commands inside a blockquote'
do
it
'does not extract commands inside a blockquote'
do
msg
=
"Hello
\r\n
>>>
\r\n
This is some text
\r\n
/close
\r\n
/assign @user
\r\n
>>>
\r\n\r\n
World"
msg
=
"Hello
\r\n
>>>
\r\n
This is some text
\r\n
/close
\r\n
/assign @user
\r\n
>>>
\r\n\r\n
World"
expected
=
msg
.
delete
(
"
\r
"
)
expected
=
msg
.
delete
(
"
\r
"
)
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
expected
expect
(
msg
).
to
eq
expected
...
@@ -195,7 +206,7 @@ describe Gitlab::SlashCommands::Extractor do
...
@@ -195,7 +206,7 @@ describe Gitlab::SlashCommands::Extractor do
it
'does not extract commands inside a HTML tag'
do
it
'does not extract commands inside a HTML tag'
do
msg
=
"Hello
\r\n
<div>
\r\n
This is some text
\r\n
/close
\r\n
/assign @user
\r\n
</div>
\r\n\r\n
World"
msg
=
"Hello
\r\n
<div>
\r\n
This is some text
\r\n
/close
\r\n
/assign @user
\r\n
</div>
\r\n\r\n
World"
expected
=
msg
.
delete
(
"
\r
"
)
expected
=
msg
.
delete
(
"
\r
"
)
commands
=
extractor
.
extract_commands
(
msg
)
msg
,
commands
=
extractor
.
extract_commands
(
msg
)
expect
(
commands
).
to
be_empty
expect
(
commands
).
to
be_empty
expect
(
msg
).
to
eq
expected
expect
(
msg
).
to
eq
expected
...
...
spec/services/notes/create_service_spec.rb
View file @
029b7d2e
...
@@ -56,7 +56,7 @@ describe Notes::CreateService, services: true do
...
@@ -56,7 +56,7 @@ describe Notes::CreateService, services: true do
it
"creates regular note if emoji name is invalid"
do
it
"creates regular note if emoji name is invalid"
do
opts
=
{
opts
=
{
note:
':smile: moretext:
'
,
note:
':smile: moretext:'
,
noteable_type:
'Issue'
,
noteable_type:
'Issue'
,
noteable_id:
issue
.
id
noteable_id:
issue
.
id
}
}
...
...
spec/services/notes/slash_commands_service_spec.rb
View file @
029b7d2e
...
@@ -12,7 +12,6 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -12,7 +12,6 @@ describe Notes::SlashCommandsService, services: true do
before
do
before
do
note
.
note
=
note_text
note
.
note
=
note_text
described_class
.
new
(
project
,
master
).
execute
(
note
)
end
end
describe
'note with only command'
do
describe
'note with only command'
do
...
@@ -20,7 +19,10 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -20,7 +19,10 @@ describe Notes::SlashCommandsService, services: true do
let
(
:note_text
)
{
%(/close\n/assign @#{assignee.username}")
}
let
(
:note_text
)
{
%(/close\n/assign @#{assignee.username}")
}
it
'saves the note and does not alter the note text'
do
it
'saves the note and does not alter the note text'
do
expect
(
note
.
note
).
to
eq
note_text
content
,
command_params
=
service
.
extract_commands
(
note
)
expect
(
content
).
to
eq
note_text
expect
(
command_params
).
to
be_empty
end
end
end
end
end
end
...
@@ -30,7 +32,10 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -30,7 +32,10 @@ describe Notes::SlashCommandsService, services: true do
let
(
:note_text
)
{
%(HELLO\n/close\n/assign @#{assignee.username}\nWORLD)
}
let
(
:note_text
)
{
%(HELLO\n/close\n/assign @#{assignee.username}\nWORLD)
}
it
'saves the note and does not alter the note text'
do
it
'saves the note and does not alter the note text'
do
expect
(
note
.
note
).
to
eq
note_text
content
,
command_params
=
service
.
extract_commands
(
note
)
expect
(
content
).
to
eq
note_text
expect
(
command_params
).
to
be_empty
end
end
end
end
end
end
...
@@ -53,9 +58,10 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -53,9 +58,10 @@ describe Notes::SlashCommandsService, services: true do
end
end
it
'closes noteable, sets labels, assigns, and sets milestone to noteable, and leave no note'
do
it
'closes noteable, sets labels, assigns, and sets milestone to noteable, and leave no note'
do
described_class
.
new
(
project
,
master
).
execute
(
note
)
content
,
command_params
=
service
.
extract_commands
(
note
)
service
.
execute
(
command_params
,
note
)
expect
(
note
.
note
).
to
eq
''
expect
(
content
).
to
eq
''
expect
(
note
.
noteable
).
to
be_closed
expect
(
note
.
noteable
).
to
be_closed
expect
(
note
.
noteable
.
labels
).
to
match_array
(
labels
)
expect
(
note
.
noteable
.
labels
).
to
match_array
(
labels
)
expect
(
note
.
noteable
.
assignee
).
to
eq
(
assignee
)
expect
(
note
.
noteable
.
assignee
).
to
eq
(
assignee
)
...
@@ -71,9 +77,10 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -71,9 +77,10 @@ describe Notes::SlashCommandsService, services: true do
let
(
:note_text
)
{
'/open'
}
let
(
:note_text
)
{
'/open'
}
it
'opens the noteable, and leave no note'
do
it
'opens the noteable, and leave no note'
do
described_class
.
new
(
project
,
master
).
execute
(
note
)
content
,
command_params
=
service
.
extract_commands
(
note
)
service
.
execute
(
command_params
,
note
)
expect
(
note
.
note
).
to
eq
''
expect
(
content
).
to
eq
''
expect
(
note
.
noteable
).
to
be_open
expect
(
note
.
noteable
).
to
be_open
end
end
end
end
...
@@ -86,9 +93,10 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -86,9 +93,10 @@ describe Notes::SlashCommandsService, services: true do
end
end
it
'closes noteable, sets labels, assigns, and sets milestone to noteable'
do
it
'closes noteable, sets labels, assigns, and sets milestone to noteable'
do
described_class
.
new
(
project
,
master
).
execute
(
note
)
content
,
command_params
=
service
.
extract_commands
(
note
)
service
.
execute
(
command_params
,
note
)
expect
(
note
.
note
).
to
eq
"HELLO
\n
WORLD"
expect
(
content
).
to
eq
"HELLO
\n
WORLD"
expect
(
note
.
noteable
).
to
be_closed
expect
(
note
.
noteable
).
to
be_closed
expect
(
note
.
noteable
.
labels
).
to
match_array
(
labels
)
expect
(
note
.
noteable
.
labels
).
to
match_array
(
labels
)
expect
(
note
.
noteable
.
assignee
).
to
eq
(
assignee
)
expect
(
note
.
noteable
.
assignee
).
to
eq
(
assignee
)
...
@@ -104,9 +112,10 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -104,9 +112,10 @@ describe Notes::SlashCommandsService, services: true do
let
(
:note_text
)
{
"HELLO
\n
/open
\n
WORLD"
}
let
(
:note_text
)
{
"HELLO
\n
/open
\n
WORLD"
}
it
'opens the noteable'
do
it
'opens the noteable'
do
described_class
.
new
(
project
,
master
).
execute
(
note
)
content
,
command_params
=
service
.
extract_commands
(
note
)
service
.
execute
(
command_params
,
note
)
expect
(
note
.
note
).
to
eq
"HELLO
\n
WORLD"
expect
(
content
).
to
eq
"HELLO
\n
WORLD"
expect
(
note
.
noteable
).
to
be_open
expect
(
note
.
noteable
).
to
be_open
end
end
end
end
...
@@ -114,6 +123,8 @@ describe Notes::SlashCommandsService, services: true do
...
@@ -114,6 +123,8 @@ describe Notes::SlashCommandsService, services: true do
end
end
describe
'#execute'
do
describe
'#execute'
do
let
(
:service
)
{
described_class
.
new
(
project
,
master
)
}
it_behaves_like
'note on noteable that supports slash commands'
do
it_behaves_like
'note on noteable that supports slash commands'
do
let
(
:note
)
{
build
(
:note_on_issue
,
project:
project
)
}
let
(
:note
)
{
build
(
:note_on_issue
,
project:
project
)
}
end
end
...
...
spec/services/slash_commands/interpret_service_spec.rb
View file @
029b7d2e
...
@@ -12,141 +12,6 @@ describe SlashCommands::InterpretService, services: true do
...
@@ -12,141 +12,6 @@ describe SlashCommands::InterpretService, services: true do
project
.
team
<<
[
user
,
:developer
]
project
.
team
<<
[
user
,
:developer
]
end
end
describe
'#command_names'
do
subject
do
described_class
.
command_names
(
project:
project
,
noteable:
issue
,
current_user:
user
)
end
it
'returns the basic known commands'
do
is_expected
.
to
match_array
([
:close
,
:title
,
:assign
,
:reassign
,
:todo
,
:subscribe
,
:due_date
,
:due
])
end
context
'when noteable is open'
do
it
'includes the :close command'
do
is_expected
.
to
include
(
*
[
:close
])
end
end
context
'when noteable is closed'
do
before
do
issue
.
close!
end
it
'includes the :open, :reopen commands'
do
is_expected
.
to
include
(
*
[
:open
,
:reopen
])
end
end
context
'when noteable has an assignee'
do
before
do
issue
.
update
(
assignee_id:
user
.
id
)
end
it
'includes the :unassign, :remove_assignee commands'
do
is_expected
.
to
include
(
*
[
:unassign
,
:remove_assignee
])
end
end
context
'when noteable has a milestone'
do
before
do
issue
.
update
(
milestone:
milestone
)
end
it
'includes the :clear_milestone, :remove_milestone commands'
do
is_expected
.
to
include
(
*
[
:milestone
,
:clear_milestone
,
:remove_milestone
])
end
end
context
'when project has a milestone'
do
before
do
milestone
end
it
'includes the :milestone command'
do
is_expected
.
to
include
(
*
[
:milestone
])
end
end
context
'when noteable has a label'
do
before
do
issue
.
update
(
label_ids:
[
bug
.
id
])
end
it
'includes the :unlabel, :remove_labels, :remove_label, :clear_labels, :clear_label commands'
do
is_expected
.
to
include
(
*
[
:unlabel
,
:remove_labels
,
:remove_label
,
:clear_labels
,
:clear_label
])
end
end
context
'when project has a label'
do
before
do
inprogress
end
it
'includes the :labels, :label commands'
do
is_expected
.
to
include
(
*
[
:labels
,
:label
])
end
end
context
'when user has no todo'
do
it
'includes the :todo command'
do
is_expected
.
to
include
(
*
[
:todo
])
end
end
context
'when user has a todo'
do
before
do
TodoService
.
new
.
mark_todo
(
issue
,
user
)
end
it
'includes the :done command'
do
is_expected
.
to
include
(
*
[
:done
])
end
end
context
'when user is not subscribed'
do
it
'includes the :subscribe command'
do
is_expected
.
to
include
(
*
[
:subscribe
])
end
end
context
'when user is subscribed'
do
before
do
issue
.
subscribe
(
user
)
end
it
'includes the :unsubscribe command'
do
is_expected
.
to
include
(
*
[
:unsubscribe
])
end
end
context
'when noteable has a no due date'
do
it
'includes the :due_date, :due commands'
do
is_expected
.
to
include
(
*
[
:due_date
,
:due
])
end
end
context
'when noteable has a due date'
do
before
do
issue
.
update
(
due_date:
Date
.
today
)
end
it
'includes the :clear_due_date command'
do
is_expected
.
to
include
(
*
[
:due_date
,
:due
,
:clear_due_date
])
end
end
end
describe
'#execute'
do
describe
'#execute'
do
let
(
:service
)
{
described_class
.
new
(
project
,
user
)
}
let
(
:service
)
{
described_class
.
new
(
project
,
user
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
)
}
...
@@ -154,60 +19,60 @@ describe SlashCommands::InterpretService, services: true do
...
@@ -154,60 +19,60 @@ describe SlashCommands::InterpretService, services: true do
shared_examples
'open command'
do
shared_examples
'open command'
do
it
'returns state_event: "open" if content contains /open'
do
it
'returns state_event: "open" if content contains /open'
do
issuable
.
close!
issuable
.
close!
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
state_event:
'reopen'
)
expect
(
updat
es
).
to
eq
(
state_event:
'reopen'
)
end
end
end
end
shared_examples
'close command'
do
shared_examples
'close command'
do
it
'returns state_event: "close" if content contains /open'
do
it
'returns state_event: "close" if content contains /open'
do
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
state_event:
'close'
)
expect
(
updat
es
).
to
eq
(
state_event:
'close'
)
end
end
end
end
shared_examples
'title command'
do
shared_examples
'title command'
do
it
'populates title: "A brand new title" if content contains /title A brand new title'
do
it
'populates title: "A brand new title" if content contains /title A brand new title'
do
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
title:
'A brand new title'
)
expect
(
updat
es
).
to
eq
(
title:
'A brand new title'
)
end
end
end
end
shared_examples
'assign command'
do
shared_examples
'assign command'
do
it
'fetches assignee and populates assignee_id if content contains /assign'
do
it
'fetches assignee and populates assignee_id if content contains /assign'
do
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
assignee_id:
user
.
id
)
expect
(
updat
es
).
to
eq
(
assignee_id:
user
.
id
)
end
end
end
end
shared_examples
'unassign command'
do
shared_examples
'unassign command'
do
it
'populates assignee_id: nil if content contains /unassign'
do
it
'populates assignee_id: nil if content contains /unassign'
do
issuable
.
update
(
assignee_id:
user
.
id
)
issuable
.
update
(
assignee_id:
user
.
id
)
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
assignee_id:
nil
)
expect
(
updat
es
).
to
eq
(
assignee_id:
nil
)
end
end
end
end
shared_examples
'milestone command'
do
shared_examples
'milestone command'
do
it
'fetches milestone and populates milestone_id if content contains /milestone'
do
it
'fetches milestone and populates milestone_id if content contains /milestone'
do
milestone
# populate the milestone
milestone
# populate the milestone
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
milestone_id:
milestone
.
id
)
expect
(
updat
es
).
to
eq
(
milestone_id:
milestone
.
id
)
end
end
end
end
shared_examples
'clear_milestone command'
do
shared_examples
'clear_milestone command'
do
it
'populates milestone_id: nil if content contains /clear_milestone'
do
it
'populates milestone_id: nil if content contains /clear_milestone'
do
issuable
.
update
(
milestone_id:
milestone
.
id
)
issuable
.
update
(
milestone_id:
milestone
.
id
)
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
milestone_id:
nil
)
expect
(
updat
es
).
to
eq
(
milestone_id:
nil
)
end
end
end
end
...
@@ -215,86 +80,86 @@ describe SlashCommands::InterpretService, services: true do
...
@@ -215,86 +80,86 @@ describe SlashCommands::InterpretService, services: true do
it
'fetches label ids and populates add_label_ids if content contains /label'
do
it
'fetches label ids and populates add_label_ids if content contains /label'
do
bug
# populate the label
bug
# populate the label
inprogress
# populate the label
inprogress
# populate the label
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
add_label_ids:
[
bug
.
id
,
inprogress
.
id
])
expect
(
updat
es
).
to
eq
(
add_label_ids:
[
bug
.
id
,
inprogress
.
id
])
end
end
end
end
shared_examples
'unlabel command'
do
shared_examples
'unlabel command'
do
it
'fetches label ids and populates remove_label_ids if content contains /unlabel'
do
it
'fetches label ids and populates remove_label_ids if content contains /unlabel'
do
issuable
.
update
(
label_ids:
[
inprogress
.
id
])
# populate the label
issuable
.
update
(
label_ids:
[
inprogress
.
id
])
# populate the label
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
remove_label_ids:
[
inprogress
.
id
])
expect
(
updat
es
).
to
eq
(
remove_label_ids:
[
inprogress
.
id
])
end
end
end
end
shared_examples
'clear_labels command'
do
shared_examples
'clear_labels command'
do
it
'populates label_ids: [] if content contains /clear_labels'
do
it
'populates label_ids: [] if content contains /clear_labels'
do
issuable
.
update
(
label_ids:
[
inprogress
.
id
])
# populate the label
issuable
.
update
(
label_ids:
[
inprogress
.
id
])
# populate the label
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
label_ids:
[])
expect
(
updat
es
).
to
eq
(
label_ids:
[])
end
end
end
end
shared_examples
'todo command'
do
shared_examples
'todo command'
do
it
'populates todo_event: "add" if content contains /todo'
do
it
'populates todo_event: "add" if content contains /todo'
do
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
todo_event:
'add'
)
expect
(
updat
es
).
to
eq
(
todo_event:
'add'
)
end
end
end
end
shared_examples
'done command'
do
shared_examples
'done command'
do
it
'populates todo_event: "done" if content contains /done'
do
it
'populates todo_event: "done" if content contains /done'
do
TodoService
.
new
.
mark_todo
(
issuable
,
user
)
TodoService
.
new
.
mark_todo
(
issuable
,
user
)
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
todo_event:
'done'
)
expect
(
updat
es
).
to
eq
(
todo_event:
'done'
)
end
end
end
end
shared_examples
'subscribe command'
do
shared_examples
'subscribe command'
do
it
'populates subscription_event: "subscribe" if content contains /subscribe'
do
it
'populates subscription_event: "subscribe" if content contains /subscribe'
do
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
subscription_event:
'subscribe'
)
expect
(
updat
es
).
to
eq
(
subscription_event:
'subscribe'
)
end
end
end
end
shared_examples
'unsubscribe command'
do
shared_examples
'unsubscribe command'
do
it
'populates subscription_event: "unsubscribe" if content contains /unsubscribe'
do
it
'populates subscription_event: "unsubscribe" if content contains /unsubscribe'
do
issuable
.
subscribe
(
user
)
issuable
.
subscribe
(
user
)
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
subscription_event:
'unsubscribe'
)
expect
(
updat
es
).
to
eq
(
subscription_event:
'unsubscribe'
)
end
end
end
end
shared_examples
'due_date command'
do
shared_examples
'due_date command'
do
it
'populates due_date: Date.new(2016, 8, 28) if content contains /due_date 2016-08-28'
do
it
'populates due_date: Date.new(2016, 8, 28) if content contains /due_date 2016-08-28'
do
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
due_date:
defined?
(
expected_date
)
?
expected_date
:
Date
.
new
(
2016
,
8
,
28
))
expect
(
updat
es
).
to
eq
(
due_date:
defined?
(
expected_date
)
?
expected_date
:
Date
.
new
(
2016
,
8
,
28
))
end
end
end
end
shared_examples
'clear_due_date command'
do
shared_examples
'clear_due_date command'
do
it
'populates due_date: nil if content contains /clear_due_date'
do
it
'populates due_date: nil if content contains /clear_due_date'
do
issuable
.
update
(
due_date:
Date
.
today
)
issuable
.
update
(
due_date:
Date
.
today
)
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
eq
(
due_date:
nil
)
expect
(
updat
es
).
to
eq
(
due_date:
nil
)
end
end
end
end
shared_examples
'empty command'
do
shared_examples
'empty command'
do
it
'populates {} if content contains an unsupported command'
do
it
'populates {} if content contains an unsupported command'
do
chang
es
=
service
.
execute
(
content
,
issuable
)
_
,
updat
es
=
service
.
execute
(
content
,
issuable
)
expect
(
chang
es
).
to
be_empty
expect
(
updat
es
).
to
be_empty
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