package cobra import ( "context" "io" "reflect" "strings" "testing" ) func TestParseRoutesBeforeOptionsAndKeepsFlagsLocal(t *testing.T) { tree := &Command{Name: "app", Children: []*Command{ {Name: "config", Children: []*Command{ {Name: "show", Runnable: true, Flags: []Flag{{Name: "scope"}}}, }}, }} result := Parse(tree, []string{"config", "show", "--scope", "app"}, ParseOptions{}) 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"}}) { t.Fatalf("selected result = %#v", result) } result = Parse(tree, []string{"config", "--scope", "app", "show"}, ParseOptions{}) if result.Failure == nil { t.Fatal("accepted a child flag before the complete command path") } } func TestParseInterspersedOperandsBooleanFlagsAndTerminator(t *testing.T) { tree := &Command{Name: "app", Children: []*Command{ {Name: "restore", Runnable: true, Flags: []Flag{ {Name: "enabled", Boolean: true}, {Name: "tag", Repeated: true}, }}, }} result := Parse(tree, []string{"restore", "before", "--enabled", "--tag", "a,b", "--tag=c", "--", "--literal"}, ParseOptions{}) if result.Failure != nil { t.Fatalf("parse failed: %s", result.Failure.Message) } if !reflect.DeepEqual(result.FlagValues, [][]string{{"true"}, {"a,b", "c"}}) { t.Fatalf("flag values = %#v", result.FlagValues) } if !reflect.DeepEqual(result.Operands, []string{"before", "--literal"}) { t.Fatalf("operands = %#v", result.Operands) } result = Parse(tree, []string{"restore", "--enabled=false"}, ParseOptions{}) if result.Failure != nil || !reflect.DeepEqual(result.FlagValues[0], []string{"false"}) { t.Fatalf("explicit false = %#v", result) } } func TestParseHelpIsLocalAndFalseDoesNotRequestHelp(t *testing.T) { tree := &Command{Name: "app", Children: []*Command{ {Name: "run", Runnable: true, Flags: []Flag{{Name: "required", Required: true}}}, }} result := Parse(tree, []string{"run", "--help"}, ParseOptions{}) if result.Failure != nil || !result.HelpRequested { t.Fatalf("help parse = %#v", result) } result = Parse(tree, []string{"run", "--help=false"}, ParseOptions{}) if result.Failure != nil || result.HelpRequested { t.Fatalf("false help parse = %#v", result) } result = Parse(tree, []string{"run", "--help=1"}, ParseOptions{}) if result.Failure != nil || !result.HelpRequested { t.Fatalf("strconv boolean help parse = %#v", result) } result = Parse(tree, []string{"run", "--help=invalid", "--help"}, ParseOptions{}) if result.Failure == nil { t.Fatal("accepted an invalid earlier help occurrence") } } func TestParseRunnableParentAndGroupUnknownCommand(t *testing.T) { tree := &Command{Name: "app", Children: []*Command{ {Name: "deploy", Runnable: true, Flags: []Flag{{Name: "scope"}}, Children: []*Command{{Name: "now", Runnable: true}}}, {Name: "config", Children: []*Command{{Name: "show", Runnable: true}}}, }} result := Parse(tree, []string{"deploy", "target"}, ParseOptions{}) if result.Failure != nil || !reflect.DeepEqual(result.Path, []string{"deploy"}) || !reflect.DeepEqual(result.Operands, []string{"target"}) { t.Fatalf("runnable parent result = %#v", result) } result = Parse(tree, []string{"deploy", "--scope", "local"}, ParseOptions{}) if result.Failure != nil || !reflect.DeepEqual(result.FlagValues, [][]string{{"local"}}) { t.Fatalf("runnable parent local flag = %#v", result) } result = Parse(tree, []string{"deploy", "now"}, ParseOptions{}) if result.Failure != nil || !reflect.DeepEqual(result.Path, []string{"deploy", "now"}) { t.Fatalf("nested runnable child = %#v", result) } result = Parse(tree, []string{"config", "mystery"}, ParseOptions{}) if result.Failure == nil { t.Fatal("accepted an unknown trailing command beneath a group") } } func TestParseReturnsNeutralFailuresAndFreshState(t *testing.T) { tree := &Command{Name: "app", Children: []*Command{ {Name: "run", Runnable: true, Flags: []Flag{{Name: "value"}}}, }} options := ParseOptions{Context: context.Background(), In: strings.NewReader("unused"), Out: io.Discard, Err: io.Discard} first := Parse(tree, []string{"run", "--value=old"}, options) second := Parse(tree, []string{"run"}, options) if first.Failure != nil || second.Failure != nil { t.Fatalf("parse results = %#v, %#v", first, second) } if !reflect.DeepEqual(first.FlagValues, [][]string{{"old"}}) || !reflect.DeepEqual(second.FlagValues, [][]string{nil}) { t.Fatalf("state leaked between parses: %#v then %#v", first.FlagValues, second.FlagValues) } failed := Parse(tree, []string{"run", "--unknown"}, options) if failed.Failure == nil || failed.Failure.Message == "" { t.Fatalf("unknown flag failure = %#v", failed.Failure) } }