package cobra import ( "bytes" "strings" "testing" ) func validArgsFunc(cmd *Command, args []string, toComplete string) ([]string, BashCompDirective) { if len(args) != 0 { return nil, BashCompDirectiveNoFileComp } var completions []string for _, comp := range []string{"one", "two"} { if strings.HasPrefix(comp, toComplete) { completions = append(completions, comp) } } return completions, BashCompDirectiveDefault } func validArgsFunc2(cmd *Command, args []string, toComplete string) ([]string, BashCompDirective) { if len(args) != 0 { return nil, BashCompDirectiveNoFileComp } var completions []string for _, comp := range []string{"three", "four"} { if strings.HasPrefix(comp, toComplete) { completions = append(completions, comp) } } return completions, BashCompDirectiveDefault } func TestValidArgsFuncSingleCmd(t *testing.T) { rootCmd := &Command{ Use: "root", ValidArgsFunction: validArgsFunc, Run: emptyRun, } // Test completing an empty string output, err := executeCommand(rootCmd, CompRequestCmd, "") if err != nil { t.Errorf("Unexpected error: %v", err) } expected := strings.Join([]string{ "one", "two", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Check completing with a prefix output, err = executeCommand(rootCmd, CompRequestCmd, "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "two", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } } func TestValidArgsFuncSingleCmdInvalidArg(t *testing.T) { rootCmd := &Command{ Use: "root", // If we don't specify a value for Args, this test fails. // This is only true for a root command without any subcommands, and is caused // by the fact that the __complete command becomes a subcommand when there should not be one. // The problem is in the implementation of legacyArgs(). Args: MinimumNArgs(1), ValidArgsFunction: validArgsFunc, Run: emptyRun, } // Check completing with wrong number of args output, err := executeCommand(rootCmd, CompRequestCmd, "unexpectedArg", "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected := strings.Join([]string{ ":4", "Completion ended with directive: BashCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } } func TestValidArgsFuncChildCmds(t *testing.T) { rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} child1Cmd := &Command{ Use: "child1", ValidArgsFunction: validArgsFunc, Run: emptyRun, } child2Cmd := &Command{ Use: "child2", ValidArgsFunction: validArgsFunc2, Run: emptyRun, } rootCmd.AddCommand(child1Cmd, child2Cmd) // Test completion of first sub-command with empty argument output, err := executeCommand(rootCmd, CompRequestCmd, "child1", "") if err != nil { t.Errorf("Unexpected error: %v", err) } expected := strings.Join([]string{ "one", "two", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Test completion of first sub-command with a prefix to complete output, err = executeCommand(rootCmd, CompRequestCmd, "child1", "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "two", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Check completing with wrong number of args output, err = executeCommand(rootCmd, CompRequestCmd, "child1", "unexpectedArg", "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ ":4", "Completion ended with directive: BashCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Test completion of second sub-command with empty argument output, err = executeCommand(rootCmd, CompRequestCmd, "child2", "") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "three", "four", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } output, err = executeCommand(rootCmd, CompRequestCmd, "child2", "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "three", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Check completing with wrong number of args output, err = executeCommand(rootCmd, CompRequestCmd, "child2", "unexpectedArg", "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ ":4", "Completion ended with directive: BashCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } } func TestValidArgsFuncAliases(t *testing.T) { rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} child := &Command{ Use: "child", Aliases: []string{"son", "daughter"}, ValidArgsFunction: validArgsFunc, Run: emptyRun, } rootCmd.AddCommand(child) // Test completion of first sub-command with empty argument output, err := executeCommand(rootCmd, CompRequestCmd, "son", "") if err != nil { t.Errorf("Unexpected error: %v", err) } expected := strings.Join([]string{ "one", "two", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Test completion of first sub-command with a prefix to complete output, err = executeCommand(rootCmd, CompRequestCmd, "daughter", "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "two", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Check completing with wrong number of args output, err = executeCommand(rootCmd, CompRequestCmd, "son", "unexpectedArg", "t") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ ":4", "Completion ended with directive: BashCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } } func TestValidArgsFuncInScript(t *testing.T) { rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} child := &Command{ Use: "child", ValidArgsFunction: validArgsFunc, Run: emptyRun, } rootCmd.AddCommand(child) buf := new(bytes.Buffer) rootCmd.GenBashCompletion(buf) output := buf.String() check(t, output, "has_completion_function=1") } func TestNoValidArgsFuncInScript(t *testing.T) { rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun} child := &Command{ Use: "child", Run: emptyRun, } rootCmd.AddCommand(child) buf := new(bytes.Buffer) rootCmd.GenBashCompletion(buf) output := buf.String() checkOmit(t, output, "has_completion_function=1") } func TestFlagCompletionInGo(t *testing.T) { rootCmd := &Command{ Use: "root", Run: emptyRun, } rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot") rootCmd.RegisterFlagCompletionFunc("introot", func(cmd *Command, args []string, toComplete string) ([]string, BashCompDirective) { completions := []string{} for _, comp := range []string{"1", "2", "10"} { if strings.HasPrefix(comp, toComplete) { completions = append(completions, comp) } } return completions, BashCompDirectiveDefault }) rootCmd.Flags().String("filename", "", "Enter a filename") rootCmd.RegisterFlagCompletionFunc("filename", func(cmd *Command, args []string, toComplete string) ([]string, BashCompDirective) { completions := []string{} for _, comp := range []string{"file.yaml", "myfile.json", "file.xml"} { if strings.HasPrefix(comp, toComplete) { completions = append(completions, comp) } } return completions, BashCompDirectiveNoSpace | BashCompDirectiveNoFileComp }) // Test completing an empty string output, err := executeCommand(rootCmd, CompRequestCmd, "--introot", "") if err != nil { t.Errorf("Unexpected error: %v", err) } expected := strings.Join([]string{ "1", "2", "10", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Check completing with a prefix output, err = executeCommand(rootCmd, CompRequestCmd, "--introot", "1") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "1", "10", ":0", "Completion ended with directive: BashCompDirectiveDefault", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Test completing an empty string output, err = executeCommand(rootCmd, CompRequestCmd, "--filename", "") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "file.yaml", "myfile.json", "file.xml", ":6", "Completion ended with directive: BashCompDirectiveNoSpace, BashCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } // Check completing with a prefix output, err = executeCommand(rootCmd, CompRequestCmd, "--filename", "f") if err != nil { t.Errorf("Unexpected error: %v", err) } expected = strings.Join([]string{ "file.yaml", "file.xml", ":6", "Completion ended with directive: BashCompDirectiveNoSpace, BashCompDirectiveNoFileComp", ""}, "\n") if output != expected { t.Errorf("expected: %q, got: %q", expected, output) } }