diff --git a/app.go b/app.go index 6fc0a42..c286327 100644 --- a/app.go +++ b/app.go @@ -339,13 +339,6 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { return nerr } - cerr := checkRequiredFlags(a.Flags, set) - if cerr != nil { - showFlagError(a.Writer, cerr) - ShowSubcommandHelp(context) - return cerr - } - if checkCompletions(context) { return nil } @@ -371,6 +364,13 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } } + cerr := checkRequiredFlags(a.Flags, set) + if cerr != nil { + showFlagError(a.Writer, cerr) + ShowSubcommandHelp(context) + return cerr + } + if a.After != nil { defer func() { afterErr := a.After(context) diff --git a/app_test.go b/app_test.go index 660d238..cd4b1ef 100644 --- a/app_test.go +++ b/app_test.go @@ -877,54 +877,38 @@ func TestAppNoHelpFlag(t *testing.T) { } } -// TestRequiredFlagAppRunBehavior tests the app-wide behavior of required flags -// and how they interact with the error response and help messages. -// A different test (`TestCheckRequiredFlags`) exists for the more fine grain -// behavior of required flags. func TestRequiredFlagAppRunBehavior(t *testing.T) { tdata := []struct { - testCase string - flags []Flag - appRunInput []string - expectedHelpPrinter bool - expectedAnError bool - expectedFlagErrorPrinter bool + testCase string + flags []Flag + appRunInput []string + expectedAnError bool }{ { // expectations: // - empty input, when a required flag is present, shows the help message - // - empty input, when a required flag is present, errors - // - empty input, when a required flag is present, show the flag error message - testCase: "empty_input_with_required_flag", - appRunInput: []string{"command"}, - flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}}, - expectedHelpPrinter: true, - expectedAnError: true, - expectedFlagErrorPrinter: true, + // - empty input, when a required flag is present, errors and shows the flag error message + testCase: "empty_input_with_required_flag", + appRunInput: []string{"command"}, + flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}}, + expectedAnError: true, }, { // expectations: // - inputing --help, when a required flag is present, shows the help message - // - inputing --help, when a required flag is present, explicitly does not error - // - inputing --help, when a required flag is present, explicitly does not show the flag error message - testCase: "help_input_with_required_flag", - appRunInput: []string{"command", "--help"}, - flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}}, - expectedHelpPrinter: true, - expectedAnError: false, // explicit false for readability (this is the default value) - expectedFlagErrorPrinter: false, // explicit false for readability (this is the default value) + // - inputing --help, when a required flag is present, does not error + testCase: "help_input_with_required_flag", + appRunInput: []string{"command", "--help"}, + flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}}, }, { // expectations: // - giving optional input, when a required flag is present, shows the help message - // - giving optional input, when a required flag is present, errors - // - giving optional input, when a required flag is present, shows the flag error message - testCase: "optional_input_with_required_flag", - appRunInput: []string{"command", "--optional", "cats"}, - flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}, StringFlag{Name: "optional"}}, - expectedHelpPrinter: true, - expectedAnError: true, - expectedFlagErrorPrinter: true, + // - giving optional input, when a required flag is present, errors and shows the flag error message + testCase: "optional_input_with_required_flag", + appRunInput: []string{"command", "--optional", "cats"}, + flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}, StringFlag{Name: "optional"}}, + expectedAnError: true, }, } for _, test := range tdata { @@ -935,9 +919,9 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) { showFlagError = oldShowError }() // setup - mock showFlagError - var showErrorWasCalled = false + var showFlagErrorWasCalled = false showFlagError = func(writer io.Writer, err ...interface{}) (int, error) { - showErrorWasCalled = true + showFlagErrorWasCalled = true return 0, nil } // setup - undo HelpPrinter mock when finished @@ -953,26 +937,20 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) { // setup - app app := NewApp() app.Flags = test.flags - app.Commands = []Command{ - Command{ - Name: "command", - Flags: test.flags, - }, - } // logic under test err := app.Run(test.appRunInput) // assertions - if test.expectedHelpPrinter && helpPrinterWasCalled == false { + if helpPrinterWasCalled == false { t.Errorf("HelpPrinter expected to be called, but was not") } - if test.expectedFlagErrorPrinter && showErrorWasCalled == false { - t.Errorf("showFlagError expected to be called, but was not") - } if test.expectedAnError && err == nil { t.Errorf("expected an error, but there was none") } + if test.expectedAnError && showFlagErrorWasCalled == false { + t.Errorf("showFlagError expected to be called, but was not") + } if !test.expectedAnError && err != nil { t.Errorf("did not expected an error, but there was one: %s", err) } diff --git a/command.go b/command.go index 3d44404..a6b19b5 100644 --- a/command.go +++ b/command.go @@ -135,6 +135,13 @@ func (c Command) Run(ctx *Context) (err error) { return nil } + cerr := checkRequiredFlags(c.Flags, set) + if cerr != nil { + showFlagError(context.App.Writer, cerr) + ShowCommandHelp(context, c.Name) + return cerr + } + if c.After != nil { defer func() { afterErr := c.After(context)