401 lines
12 KiB
Go
401 lines
12 KiB
Go
|
// Copyright 2013-2023 The Cobra Authors
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package cobra
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
activeHelpMessage = "This is an activeHelp message"
|
||
|
activeHelpMessage2 = "This is the rest of the activeHelp message"
|
||
|
)
|
||
|
|
||
|
func TestActiveHelpAlone(t *testing.T) {
|
||
|
rootCmd := &Command{
|
||
|
Use: "root",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
|
||
|
activeHelpFunc := func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
comps := AppendActiveHelp(nil, activeHelpMessage)
|
||
|
return comps, ShellCompDirectiveDefault
|
||
|
}
|
||
|
|
||
|
// Test that activeHelp can be added to a root command
|
||
|
rootCmd.ValidArgsFunction = activeHelpFunc
|
||
|
|
||
|
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected := strings.Join([]string{
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
":0",
|
||
|
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
|
||
|
rootCmd.ValidArgsFunction = nil
|
||
|
|
||
|
// Test that activeHelp can be added to a child command
|
||
|
childCmd := &Command{
|
||
|
Use: "thechild",
|
||
|
Short: "The child command",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
rootCmd.AddCommand(childCmd)
|
||
|
|
||
|
childCmd.ValidArgsFunction = activeHelpFunc
|
||
|
|
||
|
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected = strings.Join([]string{
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
":0",
|
||
|
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestActiveHelpWithComps(t *testing.T) {
|
||
|
rootCmd := &Command{
|
||
|
Use: "root",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
|
||
|
childCmd := &Command{
|
||
|
Use: "thechild",
|
||
|
Short: "The child command",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
rootCmd.AddCommand(childCmd)
|
||
|
|
||
|
// Test that activeHelp can be added following other completions
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
comps := []string{"first", "second"}
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage)
|
||
|
return comps, ShellCompDirectiveDefault
|
||
|
}
|
||
|
|
||
|
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected := strings.Join([]string{
|
||
|
"first",
|
||
|
"second",
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
":0",
|
||
|
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
|
||
|
// Test that activeHelp can be added preceding other completions
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
var comps []string
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage)
|
||
|
comps = append(comps, []string{"first", "second"}...)
|
||
|
return comps, ShellCompDirectiveDefault
|
||
|
}
|
||
|
|
||
|
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected = strings.Join([]string{
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
"first",
|
||
|
"second",
|
||
|
":0",
|
||
|
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
|
||
|
// Test that activeHelp can be added interleaved with other completions
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
comps := []string{"first"}
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage)
|
||
|
comps = append(comps, "second")
|
||
|
return comps, ShellCompDirectiveDefault
|
||
|
}
|
||
|
|
||
|
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected = strings.Join([]string{
|
||
|
"first",
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
"second",
|
||
|
":0",
|
||
|
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestMultiActiveHelp(t *testing.T) {
|
||
|
rootCmd := &Command{
|
||
|
Use: "root",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
|
||
|
childCmd := &Command{
|
||
|
Use: "thechild",
|
||
|
Short: "The child command",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
rootCmd.AddCommand(childCmd)
|
||
|
|
||
|
// Test that multiple activeHelp message can be added
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
comps := AppendActiveHelp(nil, activeHelpMessage)
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage2)
|
||
|
return comps, ShellCompDirectiveNoFileComp
|
||
|
}
|
||
|
|
||
|
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected := strings.Join([]string{
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage2),
|
||
|
":4",
|
||
|
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
|
||
|
// Test that multiple activeHelp messages can be used along with completions
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
comps := []string{"first"}
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage)
|
||
|
comps = append(comps, "second")
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage2)
|
||
|
return comps, ShellCompDirectiveNoFileComp
|
||
|
}
|
||
|
|
||
|
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected = strings.Join([]string{
|
||
|
"first",
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
"second",
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage2),
|
||
|
":4",
|
||
|
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestActiveHelpForFlag(t *testing.T) {
|
||
|
rootCmd := &Command{
|
||
|
Use: "root",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
flagname := "flag"
|
||
|
rootCmd.Flags().String(flagname, "", "A flag")
|
||
|
|
||
|
// Test that multiple activeHelp message can be added
|
||
|
_ = rootCmd.RegisterFlagCompletionFunc(flagname, func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
comps := []string{"first"}
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage)
|
||
|
comps = append(comps, "second")
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage2)
|
||
|
return comps, ShellCompDirectiveNoFileComp
|
||
|
})
|
||
|
|
||
|
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--flag", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
expected := strings.Join([]string{
|
||
|
"first",
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
|
||
|
"second",
|
||
|
fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage2),
|
||
|
":4",
|
||
|
"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestConfigActiveHelp(t *testing.T) {
|
||
|
rootCmd := &Command{
|
||
|
Use: "root",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
|
||
|
childCmd := &Command{
|
||
|
Use: "thechild",
|
||
|
Short: "The child command",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
rootCmd.AddCommand(childCmd)
|
||
|
|
||
|
activeHelpCfg := "someconfig,anotherconfig"
|
||
|
// Set the variable that the user would be setting
|
||
|
os.Setenv(activeHelpEnvVar(rootCmd.Name()), activeHelpCfg)
|
||
|
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
receivedActiveHelpCfg := GetActiveHelpConfig(cmd)
|
||
|
if receivedActiveHelpCfg != activeHelpCfg {
|
||
|
t.Errorf("expected activeHelpConfig: %q, but got: %q", activeHelpCfg, receivedActiveHelpCfg)
|
||
|
}
|
||
|
return nil, ShellCompDirectiveDefault
|
||
|
}
|
||
|
|
||
|
_, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
// Test active help config for a flag
|
||
|
activeHelpCfg = "a config for a flag"
|
||
|
// Set the variable that the completions scripts will be setting
|
||
|
os.Setenv(activeHelpEnvVar(rootCmd.Name()), activeHelpCfg)
|
||
|
|
||
|
flagname := "flag"
|
||
|
childCmd.Flags().String(flagname, "", "A flag")
|
||
|
|
||
|
// Test that multiple activeHelp message can be added
|
||
|
_ = childCmd.RegisterFlagCompletionFunc(flagname, func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
receivedActiveHelpCfg := GetActiveHelpConfig(cmd)
|
||
|
if receivedActiveHelpCfg != activeHelpCfg {
|
||
|
t.Errorf("expected activeHelpConfig: %q, but got: %q", activeHelpCfg, receivedActiveHelpCfg)
|
||
|
}
|
||
|
return nil, ShellCompDirectiveDefault
|
||
|
})
|
||
|
|
||
|
_, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "--flag", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDisableActiveHelp(t *testing.T) {
|
||
|
rootCmd := &Command{
|
||
|
Use: "root",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
|
||
|
childCmd := &Command{
|
||
|
Use: "thechild",
|
||
|
Short: "The child command",
|
||
|
Run: emptyRun,
|
||
|
}
|
||
|
rootCmd.AddCommand(childCmd)
|
||
|
|
||
|
// Test the disabling of activeHelp using the specific program
|
||
|
// environment variable that the completions scripts will be setting.
|
||
|
// Make sure the disabling value is "0" by hard-coding it in the tests;
|
||
|
// this is for backwards-compatibility as programs will be using this value.
|
||
|
os.Setenv(activeHelpEnvVar(rootCmd.Name()), "0")
|
||
|
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
comps := []string{"first"}
|
||
|
comps = AppendActiveHelp(comps, activeHelpMessage)
|
||
|
return comps, ShellCompDirectiveDefault
|
||
|
}
|
||
|
|
||
|
output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
os.Unsetenv(activeHelpEnvVar(rootCmd.Name()))
|
||
|
|
||
|
// Make sure there is no ActiveHelp in the output
|
||
|
expected := strings.Join([]string{
|
||
|
"first",
|
||
|
":0",
|
||
|
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
|
||
|
// Now test the global disabling of ActiveHelp
|
||
|
os.Setenv(activeHelpGlobalEnvVar, "0")
|
||
|
// Set the specific variable, to make sure it is ignored when the global env
|
||
|
// var is set properly
|
||
|
os.Setenv(activeHelpEnvVar(rootCmd.Name()), "1")
|
||
|
|
||
|
output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
|
||
|
// Make sure there is no ActiveHelp in the output
|
||
|
expected = strings.Join([]string{
|
||
|
"first",
|
||
|
":0",
|
||
|
"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
|
||
|
|
||
|
if output != expected {
|
||
|
t.Errorf("expected: %q, got: %q", expected, output)
|
||
|
}
|
||
|
|
||
|
// Make sure that if the global env variable is set to anything else than
|
||
|
// the disable value it is ignored
|
||
|
os.Setenv(activeHelpGlobalEnvVar, "on")
|
||
|
// Set the specific variable, to make sure it is used (while ignoring the global env var)
|
||
|
activeHelpCfg := "1"
|
||
|
os.Setenv(activeHelpEnvVar(rootCmd.Name()), activeHelpCfg)
|
||
|
|
||
|
childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
|
||
|
receivedActiveHelpCfg := GetActiveHelpConfig(cmd)
|
||
|
if receivedActiveHelpCfg != activeHelpCfg {
|
||
|
t.Errorf("expected activeHelpConfig: %q, but got: %q", activeHelpCfg, receivedActiveHelpCfg)
|
||
|
}
|
||
|
return nil, ShellCompDirectiveDefault
|
||
|
}
|
||
|
|
||
|
_, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
|
||
|
if err != nil {
|
||
|
t.Errorf("Unexpected error: %v", err)
|
||
|
}
|
||
|
}
|