112 lines
3.9 KiB
Go
112 lines
3.9 KiB
Go
package commandkit
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
internalcobra "gitea.maximumdirect.net/eric/CommandKit/internal/cobra"
|
|
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
|
|
)
|
|
|
|
func TestAppParseUsesRegisteredBindingsWithTheAdapter(t *testing.T) {
|
|
type input struct {
|
|
scope Supplied[string]
|
|
id Supplied[string]
|
|
}
|
|
show := NewCommand(CommandSpec[input]{
|
|
Name: "show",
|
|
Flags: []Flag[input]{ValueFlag(FlagMeta{Name: "scope"}, (*string)(nil), func(value string) (string, error) {
|
|
return value, nil
|
|
}, func(value *input, supplied Supplied[string]) { value.scope = supplied })},
|
|
Arguments: []Argument[input]{ValueArgument(ArgumentMeta{Name: "id"}, true, func(value string) (string, error) {
|
|
return value, nil
|
|
}, func(value *input, supplied Supplied[string]) { value.id = supplied })},
|
|
Run: func(Invocation, input) Outcome { return Success() },
|
|
})
|
|
config := Group("config", "configuration", show)
|
|
var err error
|
|
app, err := New(Identity{Name: "example"}, config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
options := commandmeta.ParseOptions{Context: context.Background()}
|
|
result := app.parse([]string{"config", "show", "one", "--scope", "app"}, options)
|
|
if result.Failure != nil {
|
|
t.Fatalf("parse failed: %s", result.Failure.Message)
|
|
}
|
|
if !reflect.DeepEqual(result.Path, []string{"config", "show"}) || !reflect.DeepEqual(result.FlagValues, [][]string{{"app"}}) || !reflect.DeepEqual(result.Operands, []string{"one"}) {
|
|
t.Fatalf("parse result = %#v", result)
|
|
}
|
|
result = app.parse([]string{"config", "--scope", "app", "show"}, options)
|
|
if result.Failure == nil {
|
|
t.Fatal("accepted a child flag before the complete command path")
|
|
}
|
|
}
|
|
|
|
func TestRoutingSnapshotPairsParsedKeyWithItsRunner(t *testing.T) {
|
|
command := NewCommand(CommandSpec[struct{}]{Name: "run", Run: func(Invocation, struct{}) Outcome { return Success() }})
|
|
app, err := New(Identity{Name: "example"}, command)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
snapshot := app.routeSnapshot()
|
|
session := internalcobra.Prepare(snapshot.metadata, commandmeta.ParseOptions{Context: context.Background()})
|
|
parsed := session.Parse([]string{"run"})
|
|
if parsed.Failure != nil {
|
|
t.Fatalf("parse failed: %s", parsed.Failure.Message)
|
|
}
|
|
if parsed.Key == 0 || snapshot.runners[parsed.Key] == nil || !snapshot.runners[parsed.Key].hasRun() {
|
|
t.Fatalf("parsed key %d has no matching runner in its snapshot", parsed.Key)
|
|
}
|
|
if app.routeSnapshot() != snapshot {
|
|
t.Fatal("unchanged registry rebuilt its routing snapshot")
|
|
}
|
|
if err := app.Register(NewCommand(CommandSpec[struct{}]{Name: "late"})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if app.routeSnapshot() == snapshot {
|
|
t.Fatal("successful registration kept stale routing metadata")
|
|
}
|
|
}
|
|
|
|
func TestExecutionRefreshesHelpMetadataAfterRegistration(t *testing.T) {
|
|
first := NewCommand(CommandSpec[struct{}]{
|
|
Name: "first",
|
|
Run: func(Invocation, struct{}) Outcome { return Success() },
|
|
})
|
|
app, err := New(Identity{Name: "example"}, first)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var output bytes.Buffer
|
|
current := newExecution(app, context.Background(), Streams{Out: &output, Err: io.Discard})
|
|
parsed := current.parse([]string{"first"})
|
|
if parsed.Failure != nil {
|
|
t.Fatalf("initial parse failed: %s", parsed.Failure.Message)
|
|
}
|
|
|
|
late := NewCommand(CommandSpec[struct{}]{
|
|
Name: "late",
|
|
Summary: "registered during execution",
|
|
Run: func(Invocation, struct{}) Outcome { return Success() },
|
|
})
|
|
if err := app.Register(late); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if got := current.renderHelp([]string{"late"}); got.Kind != OutcomeSuccess {
|
|
t.Fatalf("help after registration = %#v", got)
|
|
}
|
|
if !strings.Contains(output.String(), "registered during execution") {
|
|
t.Fatalf("help did not use registered metadata: %q", output.String())
|
|
}
|
|
if got := current.usageLine([]string{"late"}); !strings.HasPrefix(got, "Usage: example late") {
|
|
t.Fatalf("usage after registration = %q", got)
|
|
}
|
|
}
|