Resolve command context for completion
This commit is contained in:
75
completion_context_test.go
Normal file
75
completion_context_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package commandkit
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
|
||||
)
|
||||
|
||||
func TestCompletionCommandContext(t *testing.T) {
|
||||
parse := func(value string) (string, error) { return value, nil }
|
||||
mixed := NewCommand(CommandSpec[struct{}]{
|
||||
Name: "mixed", Children: []Command{simpleRunnable("child")},
|
||||
Arguments: []Argument[struct{}]{ValueArgument(ArgumentMeta{Name: "item"}, false, parse, func(*struct{}, Supplied[string]) {})},
|
||||
Run: func(Invocation, struct{}) Outcome { return Success() },
|
||||
})
|
||||
app, err := New(Identity{Name: "example"},
|
||||
Group("workspace", "", Group("list", "", simpleRunnable("shadow"), simpleRunnable("show"))),
|
||||
simpleRunnable("other"), mixed, Completion("example"),
|
||||
Alias("ws", "workspace"), Alias("w", "ws"), Alias("ws list shadow", "other"),
|
||||
Alias("legacy inspect", "workspace list"), FlagAlias("--silent", "--quiet"),
|
||||
FlagAliasFor("workspace list", "--detail", "--verbose"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
snapshot := app.routeSnapshot()
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
completed []string
|
||||
current string
|
||||
path string
|
||||
position bool
|
||||
choices []string
|
||||
kind routeKind
|
||||
}{
|
||||
{"root", nil, "work", "", true, []string{"workspace"}, routeCanonical},
|
||||
{"group", []string{"workspace"}, "li", "workspace", true, []string{"list"}, routeCanonical},
|
||||
{"entered alias", []string{"ws", "list"}, "sh", "workspace list", true, []string{"show"}, routeCanonical},
|
||||
{"alias chain", []string{"w", "list"}, "sh", "workspace list", true, []string{"show"}, routeCanonical},
|
||||
{"discovery", []string{"legacy"}, "in", "", false, nil, routeDiscovery},
|
||||
{"complete alias", []string{"legacy", "inspect"}, "sh", "workspace list", true, []string{"shadow", "show"}, routeCanonical},
|
||||
{"runnable child", []string{"mixed"}, "ch", "mixed", true, []string{"child"}, routeCanonical},
|
||||
{"unmatched child", []string{"mixed"}, "other", "mixed", true, nil, routeCanonical},
|
||||
{"runnable operand", []string{"mixed", "value"}, "ch", "mixed", false, nil, routeCanonical},
|
||||
{"flag ends path", []string{"mixed", "--quiet"}, "ch", "mixed", false, nil, routeCanonical},
|
||||
{"flag before child", []string{"workspace", "--quiet"}, "li", "workspace", false, nil, routeCanonical},
|
||||
{"unknown", []string{"missing"}, "x", "", false, nil, routeUnknown},
|
||||
{"hidden endpoint", nil, "__comp", "", true, nil, routeCanonical},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
original := append([]string(nil), tc.completed...)
|
||||
context := resolveCompletionContext(snapshot, tc.completed, tc.current)
|
||||
if context.route.kind != tc.kind || context.route.canonicalPath.String() != tc.path || context.commandPosition != tc.position || !reflect.DeepEqual(tc.completed, original) {
|
||||
t.Fatalf("context=%#v completed=%q", context, tc.completed)
|
||||
}
|
||||
var names []string
|
||||
for _, choice := range completionChildren(snapshot, context) {
|
||||
names = append(names, choice.Value)
|
||||
}
|
||||
if !reflect.DeepEqual(names, tc.choices) {
|
||||
t.Fatalf("children=%q, want %q", names, tc.choices)
|
||||
}
|
||||
if tc.kind == routeDiscovery && !reflect.DeepEqual(context.aliases, []commandmeta.FlagAlias{{Source: "--silent", Target: "--quiet"}}) {
|
||||
t.Fatalf("discovery aliases=%#v", context.aliases)
|
||||
}
|
||||
if (tc.name == "runnable child" || tc.name == "unmatched child") && (context.command == nil || len(context.command.Arguments) != 1) {
|
||||
t.Fatalf("runnable operand metadata missing: %#v", context.command)
|
||||
}
|
||||
if tc.name == "entered alias" && !reflect.DeepEqual(context.aliases, []commandmeta.FlagAlias{{Source: "--detail", Target: "--verbose"}, {Source: "--silent", Target: "--quiet"}}) {
|
||||
t.Fatalf("canonical aliases=%#v", context.aliases)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user