Compose discovery help through group aliases

This commit is contained in:
2026-10-20 00:25:33 +00:00
parent fa09edf8cc
commit c231a41665
4 changed files with 123 additions and 19 deletions

View File

@@ -132,6 +132,88 @@ func TestExplicitHelpRequiresAnExactResolvedTarget(t *testing.T) {
}
}
func TestDiscoveryHelpComposesGroupShortcutsAndOverrides(t *testing.T) {
for _, override := range []bool{false, true} {
t.Run(fmt.Sprint(override), func(t *testing.T) {
initialized := false
inspect := NewCommand(CommandSpec[struct{}]{
Name: "inspect", NewInput: func() struct{} { initialized = true; return struct{}{} },
Flags: []Flag[struct{}]{ValueFlag(FlagMeta{Name: "format"}, (*string)(nil),
func(value string) (string, error) { return value, nil }, func(*struct{}, Supplied[string]) {})},
Run: func(Invocation, struct{}) Outcome { return Success() },
})
declarations := []Declaration{Group("box", "Box"), inspect, simpleRunnable("alternate"),
Alias("pk", "box"), Alias("box admin pick", "inspect"), Alias("box admin other", "inspect"),
FlagAlias("--hlep", "--help"), FlagAliasFor("inspect", "--fmt", "--format")}
wantPick := "pick → inspect"
if override {
declarations = append(declarations, Alias("pk admin pick", "alternate"), Alias("pk admin nested choose", "inspect"))
wantPick = "pick → alternate"
}
app, err := New(Identity{Name: "Demo"}, declarations...)
if err != nil {
t.Fatal(err)
}
for _, args := range [][]string{{"pk", "admin", "--help"}, {"help", "pk", "admin"}, {"pk", "admin", "--hlep"}} {
var output, diagnostics bytes.Buffer
outcome := app.Execute(context.Background(), args, Streams{Out: &output, Err: &diagnostics})
if outcome.Kind != OutcomeSuccess {
t.Fatalf("Execute(%q) = %v, diagnostics %q", args, outcome.Kind, diagnostics.String())
}
for _, fragment := range []string{"Demo pk admin [command]", wantPick, "other → inspect"} {
if !strings.Contains(output.String(), fragment) {
t.Errorf("help %q omits %q", output.String(), fragment)
}
}
if override && strings.Contains(output.String(), "pick → inspect") {
t.Errorf("help displays overridden target: %q", output.String())
}
if strings.Contains(output.String(), "--fmt") {
t.Errorf("discovery inherited a descendant flag: %q", output.String())
}
}
if initialized {
t.Fatal("discovery initialized application input")
}
if override {
var output bytes.Buffer
outcome := app.Execute(context.Background(), []string{"help", "pk", "admin", "nested"}, Streams{Out: &output, Err: io.Discard})
if outcome.Kind != OutcomeSuccess || !strings.Contains(output.String(), "choose → inspect") {
t.Fatalf("entered-only discovery outcome = %v, help %q", outcome.Kind, output.String())
}
}
var diagnostics bytes.Buffer
outcome := app.Execute(context.Background(), []string{"pk", "admin"}, Streams{Out: io.Discard, Err: &diagnostics})
if outcome.Kind != OutcomeUsage || !strings.Contains(diagnostics.String(), "pk admin") {
t.Fatalf("bare discovery = %v, diagnostics %q", outcome.Kind, diagnostics.String())
}
outcome = app.Execute(context.Background(), []string{"pk", "admin", "--fmt=yaml", "--hlep"}, Streams{Out: io.Discard, Err: io.Discard})
if outcome.Kind != OutcomeUsage {
t.Fatal("discovery accepted descendant flag")
}
outcome = app.Execute(context.Background(), []string{"pk", "admin", "other"}, Streams{Out: io.Discard, Err: io.Discard})
if outcome.Kind != OutcomeSuccess || !initialized {
t.Fatal("complete composed route is unavailable")
}
})
}
}
func TestDiscoveryHelpThroughExpandedGroupPath(t *testing.T) {
app, err := New(Identity{Name: "Demo"}, Group("outer", "Outer", Group("box", "Box")),
simpleRunnable("inspect"), Alias("pk", "outer box"), Alias("outer box admin pick", "inspect"))
if err != nil {
t.Fatal(err)
}
for _, args := range [][]string{{"pk", "admin", "--help"}, {"help", "pk", "admin"}} {
var output bytes.Buffer
outcome := app.Execute(context.Background(), args, Streams{Out: &output, Err: io.Discard})
if outcome.Kind != OutcomeSuccess || !strings.Contains(output.String(), "Demo pk admin [command]") || !strings.Contains(output.String(), "pick → inspect") {
t.Fatalf("expanded discovery outcome = %v, help %q", outcome.Kind, output.String())
}
}
}
func routeTestApp(t *testing.T, extra ...Declaration) *App {
t.Helper()
collections := simpleRunnable("collections")