Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/components/console/spec/commands/complete_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ struct CompleteCommandTest < ASPEC::TestCase
end
end

def test_completes_command_name_with_loader : Nil
@application.command_loader = ACON::Loader::Factory.new({
"foo:bar1" => ->{ Foo1Command.new.as ACON::Command },
})

self.execute({"--current" => "0", "--input" => [] of String})
@tester.display.should eq "#{["help", "list", "completion", "hello", "ahoy", "foo:bar1", "afoobar1"].join("\n")}#{ACON::System::EOL}"
end

def test_additional_shell_support : Nil
@command = ACON::Commands::Complete.new({"supported" => ACON::Completion::Output::Bash} of String => ACON::Completion::Output::Interface.class)
@command.application = @application
Expand Down
17 changes: 17 additions & 0 deletions src/components/console/spec/commands/dump_completion_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require "../spec_helper"

struct DumpCompletionCommandTest < ASPEC::TestCase
@[DataProvider("complete_provider")]
def test_complete(input : Array(String), expected_suggestions : Array(String)) : Nil
tester = ACON::Spec::CommandCompletionTester.new ACON::Commands::DumpCompletion.new
suggestions = tester.complete input

suggestions.should eq expected_suggestions
end

def complete_provider : Hash
{
"shell" => {[] of String, ["bash"]},
}
end
end
88 changes: 52 additions & 36 deletions src/components/console/spec/commands/help_spec.cr
Original file line number Diff line number Diff line change
@@ -1,40 +1,56 @@
require "../spec_helper"

describe ACON::Commands::Help do
describe "#execute" do
it "with command alias" do
command = ACON::Commands::Help.new
command.application = ACON::Application.new "foo"

tester = ACON::Spec::CommandTester.new command
tester.execute command_name: "li", decorated: false

tester.display.should contain "list [options] [--] [<namespace>]"
tester.display.should contain "format=FORMAT"
tester.display.should contain "raw"
end

it "executes" do
command = ACON::Commands::Help.new

tester = ACON::Spec::CommandTester.new command
command.command = ACON::Commands::List.new

tester.execute decorated: false

tester.display.should contain "list [options] [--] [<namespace>]"
tester.display.should contain "format=FORMAT"
tester.display.should contain "raw"
end

it "with application command" do
app = ACON::Application.new "foo"
tester = ACON::Spec::CommandTester.new app.get "help"
tester.execute command_name: "list"

tester.display.should contain "list [options] [--] [<namespace>]"
tester.display.should contain "format=FORMAT"
tester.display.should contain "raw"
end
struct HelpCommandTest < ASPEC::TestCase
def test_execute_alias : Nil
command = ACON::Commands::Help.new
command.application = ACON::Application.new "foo"

tester = ACON::Spec::CommandTester.new command
tester.execute command_name: "li", decorated: false

tester.display.should contain "list [options] [--] [<namespace>]"
tester.display.should contain "format=FORMAT"
tester.display.should contain "raw"
end

def test_execute : Nil
command = ACON::Commands::Help.new
command.application = ACON::Application.new "foo"

tester = ACON::Spec::CommandTester.new command
tester.execute command_name: "li", decorated: false

tester.display.should contain "list [options] [--] [<namespace>]"
tester.display.should contain "format=FORMAT"
tester.display.should contain "raw"
end

def test_execute_application_command : Nil
app = ACON::Application.new "foo"
tester = ACON::Spec::CommandTester.new app.get "help"
tester.execute command_name: "list"

tester.display.should contain "list [options] [--] [<namespace>]"
tester.display.should contain "format=FORMAT"
tester.display.should contain "raw"
end

@[DataProvider("complete_provider")]
def test_complete(input : Array(String), expected_suggestions : Array(String)) : Nil
app = ACON::Application.new "foo"
app.add FooCommand.new

tester = ACON::Spec::CommandCompletionTester.new app.get "help"
suggestions = tester.complete input

suggestions.should eq expected_suggestions
end

def complete_provider : Hash
{
"long option" => {["--format"], ["txt"]},
"nothing" => {[] of String, ["completion", "help", "list", "foo:bar"]},
"command name" => {["f"], ["completion", "help", "list", "foo:bar"]},
}
end
end
89 changes: 53 additions & 36 deletions src/components/console/spec/commands/list_spec.cr
Original file line number Diff line number Diff line change
@@ -1,41 +1,40 @@
require "../spec_helper"

describe ACON::Commands::List do
describe "#execute" do
it "executes" do
app = ACON::Application.new "foo"
tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", decorated: false
struct ListCommandTest < ASPEC::TestCase
def test_execute_lists_commands : Nil
app = ACON::Application.new "foo"
tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", decorated: false

tester.display.should match /help\s{2,}Display help for a command/
end
tester.display.should match /help\s{2,}Display help for a command/
end

it "with raw option" do
app = ACON::Application.new "foo"
tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", "--raw": true
def test_with_raw_option : Nil
app = ACON::Application.new "foo"
tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", "--raw": true

tester.display.should eq "completion Dump the shell completion script\nhelp Display help for a command\nlist List commands\n"
end
tester.display.should eq "completion Dump the shell completion script\nhelp Display help for a command\nlist List available commands\n"
end

it "with namespace argument" do
app = ACON::Application.new "foo"
app.add FooCommand.new
def test_with_namespace_argument : Nil
app = ACON::Application.new "foo"
app.add FooCommand.new

tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", namespace: "foo", "--raw": true
tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", namespace: "foo", "--raw": true

tester.display.should eq "foo:bar The foo:bar command\n"
end
tester.display.should eq "foo:bar The foo:bar command\n"
end

it "lists commands order" do
app = ACON::Application.new "foo"
app.add Foo6Command.new
def test_lists_command_in_expected_order : Nil
app = ACON::Application.new "foo"
app.add Foo6Command.new

tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", decorated: false
tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", decorated: false

tester.display.should eq <<-OUTPUT
tester.display.should eq <<-OUTPUT
foo 0.1.0

Usage:
Expand All @@ -52,20 +51,38 @@ describe ACON::Commands::List do
Available commands:
completion Dump the shell completion script
help Display help for a command
list List commands
list List available commands
0foo
0foo:bar 0foo:bar command\n
OUTPUT
end
end

def test_lists_commands_in_expected_order_in_raw_mode : Nil
app = ACON::Application.new "foo"
app.add Foo6Command.new

it "lists commands order with raw option" do
app = ACON::Application.new "foo"
app.add Foo6Command.new
tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", "--raw": true

tester = ACON::Spec::CommandTester.new app.get("list")
tester.execute command: "list", "--raw": true
tester.display.should eq "completion Dump the shell completion script\nhelp Display help for a command\nlist List available commands\n0foo:bar 0foo:bar command\n"
end

@[DataProvider("complete_provider")]
def test_complete(input : Array(String), expected_suggestions : Array(String)) : Nil
app = ACON::Application.new "foo"
app.add FooCommand.new

tester = ACON::Spec::CommandCompletionTester.new app.get "list"
suggestions = tester.complete input

suggestions.should eq expected_suggestions
end

tester.display.should eq "completion Dump the shell completion script\nhelp Display help for a command\nlist List commands\n0foo:bar 0foo:bar command\n"
end
def complete_provider : Hash
{
"--format option" => {["--format"], ["txt"]},
"empty namespace" => {[] of String, ["_global", "foo"]},
"partial namespace" => {["f"], ["_global", "foo"]},
}
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ foo <info>0.1.0</info>
<comment>Available commands:</comment>
<info>completion</info> Dump the shell completion script
<info>help</info> Display help for a command
<info>list</info> List commands
<info>list</info> List available commands
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ My Athena application <info>1.0.0</info>
<comment>Available commands:</comment>
<info>completion</info> Dump the shell completion script
<info>help</info> Display help for a command
<info>list</info> List commands
<info>list</info> List available commands
<comment>descriptor</comment>
<info>descriptor:command1</info> [alias1|alias2] command 1 description
<info>descriptor:command2</info> command 2 description
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ Options:
Available commands:
completion Dump the shell completion script
help Display help for a command
list List commands
list List available commands
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Description:
List commands
List available commands

Usage:
list \[options\] \[--\] \[<namespace>\]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Description:
List commands
List available commands

Usage:
list \[options\] \[--\] \[<namespace>\]
Expand Down
2 changes: 1 addition & 1 deletion src/components/console/src/application.cr
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ class Athena::Console::Application
# By default this handles completing commands and options, but can be overridden if needed.
def complete(input : ACON::Completion::Input, suggestions : ACON::Completion::Suggestions) : Nil
if input.completion_type.argument_value? && "command" == input.completion_name
@commands.each do |name, command|
self.commands.each do |name, command|
next if command.hidden? || command.name != name

suggestions.suggest_value name, command.description
Expand Down
10 changes: 4 additions & 6 deletions src/components/console/src/commands/help.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Displays information for a given command.
@[Athena::Console::Annotations::AsCommand("help", description: "Display help for a command")]
class Athena::Console::Commands::Help < Athena::Console::Command
# :nodoc:
setter command : ACON::Command? = nil
Expand All @@ -8,12 +9,9 @@ class Athena::Console::Commands::Help < Athena::Console::Command

self
.name("help")
.definition(
ACON::Input::Argument.new("command_name", :optional, "The command name", "help"),
ACON::Input::Option.new("format", nil, :required, "The output format (txt)", "txt"),
ACON::Input::Option.new("raw", nil, :none, "To output raw command help"),
)
.description("Display help for a command")
.argument("command_name", description: "The command name", default: "help") { ACON::Descriptor::Application.new(self.application).commands.keys }
.option("format", value_mode: :required, description: "The output format (txt)", default: "txt") { ACON::Helper::Descriptor.new.formats }
.option("raw", value_mode: :none, description: "To output raw command help")
.help(
<<-HELP
The <info>%command.name%</info> command displays help for a given command:
Expand Down
13 changes: 5 additions & 8 deletions src/components/console/src/commands/list.cr
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
# Lists the available commands, optionally only including those in a specific namespace.
@[Athena::Console::Annotations::AsCommand("list", description: "List available commands")]
class Athena::Console::Commands::List < Athena::Console::Command
protected def configure : Nil
self
.name("list")
.description("List commands")
.definition(
ACON::Input::Argument.new("namespace", :optional, "Only list commands in this namespace"),
ACON::Input::Option.new("raw", nil, :none, "To output raw command list"),
ACON::Input::Option.new("format", nil, :required, "The output format (txt)", "txt"),
ACON::Input::Option.new("short", nil, :none, "To skip describing command's arguments"),
)
.argument("namespace", description: "Only list commands in this namespace") { ACON::Descriptor::Application.new(self.application).namespaces.keys }
.option("raw", value_mode: :none, description: "To output raw command list")
.option("format", value_mode: :required, description: "The output format (txt)", default: "txt") { ACON::Helper::Descriptor.new.formats }
.option("short", value_mode: :none, description: "To skip describing command's arguments")
.help(
<<-HELP
The <info>%command.name%</info> command lists all commands:
Expand Down
4 changes: 4 additions & 0 deletions src/components/console/src/helper/descriptor_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ class Athena::Console::Helper::Descriptor < Athena::Console::Helper

self
end

def formats : Array(String)
@descriptors.keys
end
end
24 changes: 24 additions & 0 deletions src/components/console/src/spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,28 @@ module Athena::Console::Spec
@status = @command.run self.input, self.output
end
end

struct CommandCompletionTester
def initialize(@command : ACON::Command); end

def complete(*input : String) : Array(String)
self.complete input
end

def complete(input : Enumerable(String)) : Array(String)
completion_input = ACON::Completion::Input.from_tokens input, (input.size - 1).clamp(0, nil)
completion_input.bind @command.definition
suggestions = ACON::Completion::Suggestions.new

@command.complete completion_input, suggestions

options = [] of String

suggestions.suggested_options.each do |option|
options << "--#{option.name}"
end

options.concat suggestions.suggested_values.map(&.to_s)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,27 @@ struct DebugEventDispatcherCommandTest < ASPEC::TestCase
tester.display.should contain "#1 generic-event 0"
end

@[DataProvider("complete_provider")]
def test_complete(input : Array(String), expected_suggestions : Array(String)) : Nil
tester = ACON::Spec::CommandCompletionTester.new self.command
suggestions = tester.complete input

suggestions.should eq expected_suggestions
end

def complete_provider : Hash
{
"nothing" => {[] of String, ["Athena::EventDispatcher::GenericEvent(String, String)", "MyEvent", "MyOtherEvent"]},
"format" => {["--format"], ["txt"]},
}
end

private def command : ATH::Commands::DebugEventDispatcher
ATH::Commands::DebugEventDispatcher.new self.dispatcher
end

private def command_tester : ACON::Spec::CommandTester
ACON::Spec::CommandTester.new ATH::Commands::DebugEventDispatcher.new self.dispatcher
ACON::Spec::CommandTester.new self.command
end

private def dispatcher : AED::EventDispatcherInterface
Expand Down
Loading