diff --git a/pkg/app/run_test.go b/pkg/app/run_test.go index 5edca1b92..af08e1ddd 100644 --- a/pkg/app/run_test.go +++ b/pkg/app/run_test.go @@ -310,6 +310,57 @@ func TestShortHelpFlag(t *testing.T) { } } +// TestHelpSubcommandFlags verifies that `fastly help ` displays the command's +// specific flags (Required / Optional flags) consistently with ` --help`. +func TestHelpSubcommandFlags(t *testing.T) { + cases := []struct { + name string + args string + wantFlags []string + }{ + { + name: "help service create includes optional flags", + args: "help service create", + wantFlags: []string{"OPTIONAL FLAGS", "--comment", "--name", "--type", "GLOBAL FLAGS"}, + }, + { + name: "help service alert create includes required and optional flags", + args: "help service alert create", + wantFlags: []string{"REQUIRED FLAGS", "--description", "--metric", "--name", "OPTIONAL FLAGS", "GLOBAL FLAGS"}, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + var stdout bytes.Buffer + args := testutil.SplitArgs(tc.args) + app.Init = func(_ []string, _ io.Reader) (*global.Data, error) { + return testutil.MockGlobalData(args, &stdout), nil + } + err := app.Run(args, nil) + var output string + if err != nil { + var re errors.RemediationError + var se errors.SkipExitError + if ok := stderrors.As(err, &re); ok { + output = re.Prefix + } else if ok := stderrors.As(err, &se); ok { + if re, ok := se.Err.(errors.RemediationError); ok { + output = re.Prefix + } + } + } + output += stdout.String() + + for _, want := range tc.wantFlags { + if !strings.Contains(output, want) { + t.Errorf("expected %q in output for %q, got:\n%s", want, tc.args, output) + } + } + }) + } +} + // stripTrailingSpace removes any trailing spaces from the multiline str. func stripTrailingSpace(str string) string { buf := bytes.NewBuffer(nil) diff --git a/pkg/app/usage.go b/pkg/app/usage.go index 4b522bb87..708a2a696 100644 --- a/pkg/app/usage.go +++ b/pkg/app/usage.go @@ -210,11 +210,22 @@ const VerboseUsageTemplate = `{{define "FormatCommands" -}} {{if .Context.SelectedCommand -}} {{T "USAGE"|Bold}} {{.App.Name}} {{.App.FlagSummary}} {{.Context.SelectedCommand.CmdSummary}} +{{if .Context.SelectedCommand.Help}} +{{.Context.SelectedCommand.Help|Wrap 0}} +{{end -}} {{else}} {{- T "USAGE"|Bold}} {{template "FormatUsage" .App -}} {{end -}} -{{if .Context.Flags|GlobalFlags }} +{{if .Context.Flags|RequiredFlags -}} +{{T "REQUIRED FLAGS"|Bold}} +{{.Context.Flags|RequiredFlags|FlagsToTwoColumns|FormatTwoColumns}} +{{end -}} +{{if .Context.Flags|OptionalFlags -}} +{{T "OPTIONAL FLAGS"|Bold}} +{{.Context.Flags|OptionalFlags|FlagsToTwoColumns|FormatTwoColumns}} +{{end -}} +{{if .Context.Flags|GlobalFlags -}} {{T "GLOBAL FLAGS"|Bold}} {{.Context.Flags|GlobalFlags|FlagsToTwoColumns|FormatTwoColumns}} {{end -}}