Fix behavior around commands with optional arguments
This commit is contained in:
parent
6f2f2a6baa
commit
2703330a19
5 changed files with 67 additions and 46 deletions
|
@ -18,11 +18,11 @@ module SlashCommands
|
|||
|
||||
content, commands = extractor.extract_commands(content, opts)
|
||||
|
||||
commands.each do |name, args|
|
||||
commands.each do |name, arg|
|
||||
definition = self.class.command_definitions_by_name[name.to_sym]
|
||||
next unless definition
|
||||
|
||||
definition.execute(self, opts, args)
|
||||
definition.execute(self, opts, arg)
|
||||
end
|
||||
|
||||
[content, @updates]
|
||||
|
|
|
@ -28,13 +28,14 @@ module Gitlab
|
|||
context.instance_exec(&condition_block)
|
||||
end
|
||||
|
||||
def execute(context, opts, args)
|
||||
def execute(context, opts, arg)
|
||||
return if noop? || !available?(opts)
|
||||
|
||||
block_arity = action_block.arity
|
||||
return unless (args.present? && block_arity == 1) || (args.blank? && block_arity <= 0)
|
||||
|
||||
context.instance_exec(args, &action_block)
|
||||
if arg.present?
|
||||
context.instance_exec(arg, &action_block)
|
||||
elsif action_block.arity == 0
|
||||
context.instance_exec(&action_block)
|
||||
end
|
||||
end
|
||||
|
||||
def to_h(opts)
|
||||
|
|
|
@ -39,7 +39,7 @@ module Gitlab
|
|||
content.delete!("\r")
|
||||
content.gsub!(commands_regex(opts)) do
|
||||
if $~[:cmd]
|
||||
commands << [$~[:cmd], $~[:args]].reject(&:blank?)
|
||||
commands << [$~[:cmd], $~[:arg]].reject(&:blank?)
|
||||
''
|
||||
else
|
||||
$~[0]
|
||||
|
@ -50,13 +50,14 @@ module Gitlab
|
|||
end
|
||||
|
||||
private
|
||||
|
||||
# Builds a regular expression to match known commands.
|
||||
# First match group captures the command name and
|
||||
# second match group captures its arguments.
|
||||
#
|
||||
# It looks something like:
|
||||
#
|
||||
# /^\/(?<cmd>close|reopen|...)(?:( |$))(?<args>[^\/\n]*)(?:\n|$)/
|
||||
# /^\/(?<cmd>close|reopen|...)(?:( |$))(?<arg>[^\/\n]*)(?:\n|$)/
|
||||
def commands_regex(opts)
|
||||
names = command_names(opts).map(&:to_s)
|
||||
|
||||
|
@ -64,7 +65,7 @@ module Gitlab
|
|||
(?<code>
|
||||
# Code blocks:
|
||||
# ```
|
||||
# Anything, including `/cmd args` which are ignored by this filter
|
||||
# Anything, including `/cmd arg` which are ignored by this filter
|
||||
# ```
|
||||
|
||||
^```
|
||||
|
@ -75,7 +76,7 @@ module Gitlab
|
|||
(?<html>
|
||||
# HTML block:
|
||||
# <tag>
|
||||
# Anything, including `/cmd args` which are ignored by this filter
|
||||
# Anything, including `/cmd arg` which are ignored by this filter
|
||||
# </tag>
|
||||
|
||||
^<[^>]+?>\n
|
||||
|
@ -86,7 +87,7 @@ module Gitlab
|
|||
(?<html>
|
||||
# Quote block:
|
||||
# >>>
|
||||
# Anything, including `/cmd args` which are ignored by this filter
|
||||
# Anything, including `/cmd arg` which are ignored by this filter
|
||||
# >>>
|
||||
|
||||
^>>>
|
||||
|
@ -102,7 +103,7 @@ module Gitlab
|
|||
(?<cmd>#{Regexp.union(names)})
|
||||
(?:
|
||||
[ ]
|
||||
(?<args>[^\/\n]*)
|
||||
(?<arg>[^\/\n]*)
|
||||
)?
|
||||
(?:\n|$)
|
||||
)
|
||||
|
|
|
@ -24,7 +24,7 @@ describe Gitlab::SlashCommands::CommandDefinition do
|
|||
describe "#noop?" do
|
||||
context "when the command has an action block" do
|
||||
before do
|
||||
subject.action_block = -> { }
|
||||
subject.action_block = proc { }
|
||||
end
|
||||
|
||||
it "returns false" do
|
||||
|
@ -44,7 +44,7 @@ describe Gitlab::SlashCommands::CommandDefinition do
|
|||
|
||||
context "when the command has a condition block" do
|
||||
before do
|
||||
subject.condition_block = -> { go }
|
||||
subject.condition_block = proc { go }
|
||||
end
|
||||
|
||||
context "when the condition block returns true" do
|
||||
|
@ -78,7 +78,7 @@ describe Gitlab::SlashCommands::CommandDefinition do
|
|||
it "doesn't execute the command" do
|
||||
expect(context).not_to receive(:instance_exec)
|
||||
|
||||
subject.execute(context, {})
|
||||
subject.execute(context, {}, nil)
|
||||
|
||||
expect(context.run).to be false
|
||||
end
|
||||
|
@ -86,52 +86,82 @@ describe Gitlab::SlashCommands::CommandDefinition do
|
|||
|
||||
context "when the command is not a noop" do
|
||||
before do
|
||||
subject.action_block = -> { self.run = true }
|
||||
subject.action_block = proc { self.run = true }
|
||||
end
|
||||
|
||||
context "when the command is not available" do
|
||||
before do
|
||||
subject.condition_block = -> { false }
|
||||
subject.condition_block = proc { false }
|
||||
end
|
||||
|
||||
it "doesn't execute the command" do
|
||||
subject.execute(context, {})
|
||||
subject.execute(context, {}, nil)
|
||||
|
||||
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
|
||||
context "when the commnd has no arguments" do
|
||||
before do
|
||||
subject.action_block = ->(arg) { self.run = arg }
|
||||
subject.action_block = proc { self.run = true }
|
||||
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
|
||||
context "when the command is provided an argument" 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
|
||||
context "when the command is not provided an argument" do
|
||||
it "executes the command" do
|
||||
subject.execute(context, {}, true, true)
|
||||
subject.execute(context, {}, nil)
|
||||
|
||||
expect(context.run).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when the command has 1 required argument" do
|
||||
before do
|
||||
subject.action_block = ->(arg) { self.run = arg }
|
||||
end
|
||||
|
||||
context "when the command is provided an argument" do
|
||||
it "executes the command" do
|
||||
subject.execute(context, {}, true)
|
||||
|
||||
expect(context.run).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context "when the command is not provided an argument" do
|
||||
it "doesn't execute the command" do
|
||||
subject.execute(context, {}, nil)
|
||||
|
||||
expect(context.run).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when the command has 1 optional argument" do
|
||||
before do
|
||||
subject.action_block = proc { |arg = nil| self.run = arg || true }
|
||||
end
|
||||
|
||||
context "when the command is provided an argument" do
|
||||
it "executes the command" do
|
||||
subject.execute(context, {}, true)
|
||||
|
||||
expect(context.run).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context "when the command is not provided an argument" do
|
||||
it "executes the command" do
|
||||
subject.execute(context, {}, nil)
|
||||
|
||||
expect(context.run).to be true
|
||||
end
|
||||
|
|
|
@ -31,16 +31,12 @@ describe Gitlab::SlashCommands::Dsl do
|
|||
command :cond_action do |arg|
|
||||
arg
|
||||
end
|
||||
|
||||
command :wildcard do |*args|
|
||||
args
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.command_definitions' do
|
||||
it 'returns an array with commands definitions' do
|
||||
no_args_def, one_arg_def, two_args_def, cc_def, cond_action_def, wildcard_def = DummyClass.command_definitions
|
||||
no_args_def, one_arg_def, two_args_def, cc_def, cond_action_def = DummyClass.command_definitions
|
||||
|
||||
expect(no_args_def.name).to eq(:no_args)
|
||||
expect(no_args_def.aliases).to eq([:none])
|
||||
|
@ -76,13 +72,6 @@ describe Gitlab::SlashCommands::Dsl do
|
|||
expect(cond_action_def.params).to eq([])
|
||||
expect(cond_action_def.condition_block).to be_a_kind_of(Proc)
|
||||
expect(cond_action_def.action_block).to be_a_kind_of(Proc)
|
||||
|
||||
expect(wildcard_def.name).to eq(:wildcard)
|
||||
expect(wildcard_def.aliases).to eq([])
|
||||
expect(wildcard_def.description).to eq('')
|
||||
expect(wildcard_def.params).to eq([])
|
||||
expect(wildcard_def.condition_block).to be_nil
|
||||
expect(wildcard_def.action_block).to be_a_kind_of(Proc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue