Add focused CLI argument helpers
This commit is contained in:
@@ -13,14 +13,10 @@ func inspectCommand(ctx context.Context, args []string, stdout, stderr io.Writer
|
|||||||
printInspectHelp(stdout)
|
printInspectHelp(stdout)
|
||||||
return exitOK
|
return exitOK
|
||||||
}
|
}
|
||||||
if len(args) > 1 {
|
path, ok := parseOptionalPathArg(stderr, "inspect", args)
|
||||||
fmt.Fprintf(stderr, "%s: inspect accepts at most one path\n", app.Name)
|
if !ok {
|
||||||
return exitUsage
|
return exitUsage
|
||||||
}
|
}
|
||||||
var path string
|
|
||||||
if len(args) == 1 {
|
|
||||||
path = args[0]
|
|
||||||
}
|
|
||||||
if err := app.Inspect(ctx, app.InspectOptions{Path: path, Stdout: stdout}); err != nil {
|
if err := app.Inspect(ctx, app.InspectOptions{Path: path, Stdout: stdout}); err != nil {
|
||||||
return fail(stderr, err)
|
return fail(stderr, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,3 +82,22 @@ func rejectExtraArgs(stderr io.Writer, command string, args []string) bool {
|
|||||||
fmt.Fprintf(stderr, "%s: %s does not accept arguments: %s\n", app.Name, command, strings.Join(args, " "))
|
fmt.Fprintf(stderr, "%s: %s does not accept arguments: %s\n", app.Name, command, strings.Join(args, " "))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseOptionalPathArg(stderr io.Writer, command string, args []string) (string, bool) {
|
||||||
|
if len(args) > 1 {
|
||||||
|
fmt.Fprintf(stderr, "%s: %s accepts at most one path\n", app.Name, command)
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if len(args) == 0 {
|
||||||
|
return "", true
|
||||||
|
}
|
||||||
|
return args[0], true
|
||||||
|
}
|
||||||
|
|
||||||
|
func rejectPositionalArgs(stderr io.Writer, command string, args []string) bool {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fmt.Fprintf(stderr, "%s: %s does not accept positional arguments: %v\n", app.Name, command, args)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,6 +56,51 @@ func TestExecuteValidate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExecuteValidateArgs(t *testing.T) {
|
||||||
|
validPath := filepath.Join("..", "bundle", "testdata", "valid_bundle")
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
wantCode int
|
||||||
|
wantStdout string
|
||||||
|
wantStderr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "zero args",
|
||||||
|
args: []string{"validate"},
|
||||||
|
wantCode: exitError,
|
||||||
|
wantStderr: "requires a path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "one arg",
|
||||||
|
args: []string{"validate", validPath},
|
||||||
|
wantCode: exitOK,
|
||||||
|
wantStdout: "Validated 1 bundle(s)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "two args",
|
||||||
|
args: []string{"validate", validPath, validPath},
|
||||||
|
wantCode: exitUsage,
|
||||||
|
wantStderr: "accepts at most one path",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
code := Execute(context.Background(), tt.args, &stdout, &stderr)
|
||||||
|
if code != tt.wantCode {
|
||||||
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, tt.wantCode, stderr.String())
|
||||||
|
}
|
||||||
|
if tt.wantStdout != "" && !strings.Contains(stdout.String(), tt.wantStdout) {
|
||||||
|
t.Fatalf("stdout = %q, want substring %q", stdout.String(), tt.wantStdout)
|
||||||
|
}
|
||||||
|
if tt.wantStderr != "" && !strings.Contains(stderr.String(), tt.wantStderr) {
|
||||||
|
t.Fatalf("stderr = %q, want substring %q", stderr.String(), tt.wantStderr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExecuteInspect(t *testing.T) {
|
func TestExecuteInspect(t *testing.T) {
|
||||||
var stdout, stderr bytes.Buffer
|
var stdout, stderr bytes.Buffer
|
||||||
|
|
||||||
@@ -69,6 +114,51 @@ func TestExecuteInspect(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExecuteInspectArgs(t *testing.T) {
|
||||||
|
validPath := filepath.Join("..", "bundle", "testdata", "valid_bundle")
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
wantCode int
|
||||||
|
wantStdout string
|
||||||
|
wantStderr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "zero args",
|
||||||
|
args: []string{"inspect"},
|
||||||
|
wantCode: exitError,
|
||||||
|
wantStderr: "requires a path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "one arg",
|
||||||
|
args: []string{"inspect", validPath},
|
||||||
|
wantCode: exitOK,
|
||||||
|
wantStdout: "id=weather.daily.brentwood.2026-05-30",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "two args",
|
||||||
|
args: []string{"inspect", validPath, validPath},
|
||||||
|
wantCode: exitUsage,
|
||||||
|
wantStderr: "accepts at most one path",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
code := Execute(context.Background(), tt.args, &stdout, &stderr)
|
||||||
|
if code != tt.wantCode {
|
||||||
|
t.Fatalf("exit code = %d, want %d; stderr = %q", code, tt.wantCode, stderr.String())
|
||||||
|
}
|
||||||
|
if tt.wantStdout != "" && !strings.Contains(stdout.String(), tt.wantStdout) {
|
||||||
|
t.Fatalf("stdout = %q, want substring %q", stdout.String(), tt.wantStdout)
|
||||||
|
}
|
||||||
|
if tt.wantStderr != "" && !strings.Contains(stderr.String(), tt.wantStderr) {
|
||||||
|
t.Fatalf("stderr = %q, want substring %q", stderr.String(), tt.wantStderr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExecuteRunDryRun(t *testing.T) {
|
func TestExecuteRunDryRun(t *testing.T) {
|
||||||
sourceRoot := t.TempDir()
|
sourceRoot := t.TempDir()
|
||||||
writeCLIBundle(t, sourceRoot)
|
writeCLIBundle(t, sourceRoot)
|
||||||
@@ -103,6 +193,19 @@ pipelines:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExecuteRunRejectsExtraPositionalArgs(t *testing.T) {
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
|
||||||
|
code := Execute(context.Background(), []string{"run", "--config", "config.yml", "extra"}, &stdout, &stderr)
|
||||||
|
|
||||||
|
if code != exitUsage {
|
||||||
|
t.Fatalf("exit code = %d, want %d", code, exitUsage)
|
||||||
|
}
|
||||||
|
if !strings.Contains(stderr.String(), "does not accept positional arguments") {
|
||||||
|
t.Fatalf("stderr = %q, want positional argument error", stderr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExecuteRunPublishes(t *testing.T) {
|
func TestExecuteRunPublishes(t *testing.T) {
|
||||||
sourceRoot := t.TempDir()
|
sourceRoot := t.TempDir()
|
||||||
destinationRoot := t.TempDir()
|
destinationRoot := t.TempDir()
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ func runCommand(ctx context.Context, args []string, stdout, stderr io.Writer) in
|
|||||||
if err := flags.Parse(args); err != nil {
|
if err := flags.Parse(args); err != nil {
|
||||||
return exitUsage
|
return exitUsage
|
||||||
}
|
}
|
||||||
if flags.NArg() > 0 {
|
if rejectPositionalArgs(stderr, "run", flags.Args()) {
|
||||||
fmt.Fprintf(stderr, "%s: run does not accept positional arguments: %v\n", app.Name, flags.Args())
|
|
||||||
return exitUsage
|
return exitUsage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,14 +13,10 @@ func validateCommand(ctx context.Context, args []string, stdout, stderr io.Write
|
|||||||
printValidateHelp(stdout)
|
printValidateHelp(stdout)
|
||||||
return exitOK
|
return exitOK
|
||||||
}
|
}
|
||||||
if len(args) > 1 {
|
path, ok := parseOptionalPathArg(stderr, "validate", args)
|
||||||
fmt.Fprintf(stderr, "%s: validate accepts at most one path\n", app.Name)
|
if !ok {
|
||||||
return exitUsage
|
return exitUsage
|
||||||
}
|
}
|
||||||
var path string
|
|
||||||
if len(args) == 1 {
|
|
||||||
path = args[0]
|
|
||||||
}
|
|
||||||
if err := app.Validate(ctx, app.ValidateOptions{Path: path, Stdout: stdout}); err != nil {
|
if err := app.Validate(ctx, app.ValidateOptions{Path: path, Stdout: stdout}); err != nil {
|
||||||
return fail(stderr, err)
|
return fail(stderr, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user