git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/cobra/active_help_test.go (about)

     1  // Copyright 2013-2022 The Cobra Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cobra
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"strings"
    21  	"testing"
    22  )
    23  
    24  const (
    25  	activeHelpMessage  = "This is an activeHelp message"
    26  	activeHelpMessage2 = "This is the rest of the activeHelp message"
    27  )
    28  
    29  func TestActiveHelpAlone(t *testing.T) {
    30  	rootCmd := &Command{
    31  		Use: "root",
    32  		Run: emptyRun,
    33  	}
    34  
    35  	activeHelpFunc := func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
    36  		comps := AppendActiveHelp(nil, activeHelpMessage)
    37  		return comps, ShellCompDirectiveDefault
    38  	}
    39  
    40  	// Test that activeHelp can be added to a root command
    41  	rootCmd.ValidArgsFunction = activeHelpFunc
    42  
    43  	output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "")
    44  	if err != nil {
    45  		t.Errorf("Unexpected error: %v", err)
    46  	}
    47  
    48  	expected := strings.Join([]string{
    49  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
    50  		":0",
    51  		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
    52  
    53  	if output != expected {
    54  		t.Errorf("expected: %q, got: %q", expected, output)
    55  	}
    56  
    57  	rootCmd.ValidArgsFunction = nil
    58  
    59  	// Test that activeHelp can be added to a child command
    60  	childCmd := &Command{
    61  		Use:   "thechild",
    62  		Short: "The child command",
    63  		Run:   emptyRun,
    64  	}
    65  	rootCmd.AddCommand(childCmd)
    66  
    67  	childCmd.ValidArgsFunction = activeHelpFunc
    68  
    69  	output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
    70  	if err != nil {
    71  		t.Errorf("Unexpected error: %v", err)
    72  	}
    73  
    74  	expected = strings.Join([]string{
    75  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
    76  		":0",
    77  		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
    78  
    79  	if output != expected {
    80  		t.Errorf("expected: %q, got: %q", expected, output)
    81  	}
    82  }
    83  
    84  func TestActiveHelpWithComps(t *testing.T) {
    85  	rootCmd := &Command{
    86  		Use: "root",
    87  		Run: emptyRun,
    88  	}
    89  
    90  	childCmd := &Command{
    91  		Use:   "thechild",
    92  		Short: "The child command",
    93  		Run:   emptyRun,
    94  	}
    95  	rootCmd.AddCommand(childCmd)
    96  
    97  	// Test that activeHelp can be added following other completions
    98  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
    99  		comps := []string{"first", "second"}
   100  		comps = AppendActiveHelp(comps, activeHelpMessage)
   101  		return comps, ShellCompDirectiveDefault
   102  	}
   103  
   104  	output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   105  	if err != nil {
   106  		t.Errorf("Unexpected error: %v", err)
   107  	}
   108  
   109  	expected := strings.Join([]string{
   110  		"first",
   111  		"second",
   112  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
   113  		":0",
   114  		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
   115  
   116  	if output != expected {
   117  		t.Errorf("expected: %q, got: %q", expected, output)
   118  	}
   119  
   120  	// Test that activeHelp can be added preceding other completions
   121  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   122  		var comps []string
   123  		comps = AppendActiveHelp(comps, activeHelpMessage)
   124  		comps = append(comps, []string{"first", "second"}...)
   125  		return comps, ShellCompDirectiveDefault
   126  	}
   127  
   128  	output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   129  	if err != nil {
   130  		t.Errorf("Unexpected error: %v", err)
   131  	}
   132  
   133  	expected = strings.Join([]string{
   134  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
   135  		"first",
   136  		"second",
   137  		":0",
   138  		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
   139  
   140  	if output != expected {
   141  		t.Errorf("expected: %q, got: %q", expected, output)
   142  	}
   143  
   144  	// Test that activeHelp can be added interleaved with other completions
   145  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   146  		comps := []string{"first"}
   147  		comps = AppendActiveHelp(comps, activeHelpMessage)
   148  		comps = append(comps, "second")
   149  		return comps, ShellCompDirectiveDefault
   150  	}
   151  
   152  	output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   153  	if err != nil {
   154  		t.Errorf("Unexpected error: %v", err)
   155  	}
   156  
   157  	expected = strings.Join([]string{
   158  		"first",
   159  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
   160  		"second",
   161  		":0",
   162  		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
   163  
   164  	if output != expected {
   165  		t.Errorf("expected: %q, got: %q", expected, output)
   166  	}
   167  }
   168  
   169  func TestMultiActiveHelp(t *testing.T) {
   170  	rootCmd := &Command{
   171  		Use: "root",
   172  		Run: emptyRun,
   173  	}
   174  
   175  	childCmd := &Command{
   176  		Use:   "thechild",
   177  		Short: "The child command",
   178  		Run:   emptyRun,
   179  	}
   180  	rootCmd.AddCommand(childCmd)
   181  
   182  	// Test that multiple activeHelp message can be added
   183  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   184  		comps := AppendActiveHelp(nil, activeHelpMessage)
   185  		comps = AppendActiveHelp(comps, activeHelpMessage2)
   186  		return comps, ShellCompDirectiveNoFileComp
   187  	}
   188  
   189  	output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   190  	if err != nil {
   191  		t.Errorf("Unexpected error: %v", err)
   192  	}
   193  
   194  	expected := strings.Join([]string{
   195  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
   196  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage2),
   197  		":4",
   198  		"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
   199  
   200  	if output != expected {
   201  		t.Errorf("expected: %q, got: %q", expected, output)
   202  	}
   203  
   204  	// Test that multiple activeHelp messages can be used along with completions
   205  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   206  		comps := []string{"first"}
   207  		comps = AppendActiveHelp(comps, activeHelpMessage)
   208  		comps = append(comps, "second")
   209  		comps = AppendActiveHelp(comps, activeHelpMessage2)
   210  		return comps, ShellCompDirectiveNoFileComp
   211  	}
   212  
   213  	output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   214  	if err != nil {
   215  		t.Errorf("Unexpected error: %v", err)
   216  	}
   217  
   218  	expected = strings.Join([]string{
   219  		"first",
   220  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
   221  		"second",
   222  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage2),
   223  		":4",
   224  		"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
   225  
   226  	if output != expected {
   227  		t.Errorf("expected: %q, got: %q", expected, output)
   228  	}
   229  }
   230  
   231  func TestActiveHelpForFlag(t *testing.T) {
   232  	rootCmd := &Command{
   233  		Use: "root",
   234  		Run: emptyRun,
   235  	}
   236  	flagname := "flag"
   237  	rootCmd.Flags().String(flagname, "", "A flag")
   238  
   239  	// Test that multiple activeHelp message can be added
   240  	_ = rootCmd.RegisterFlagCompletionFunc(flagname, func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   241  		comps := []string{"first"}
   242  		comps = AppendActiveHelp(comps, activeHelpMessage)
   243  		comps = append(comps, "second")
   244  		comps = AppendActiveHelp(comps, activeHelpMessage2)
   245  		return comps, ShellCompDirectiveNoFileComp
   246  	})
   247  
   248  	output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "--flag", "")
   249  	if err != nil {
   250  		t.Errorf("Unexpected error: %v", err)
   251  	}
   252  
   253  	expected := strings.Join([]string{
   254  		"first",
   255  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage),
   256  		"second",
   257  		fmt.Sprintf("%s%s", activeHelpMarker, activeHelpMessage2),
   258  		":4",
   259  		"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
   260  
   261  	if output != expected {
   262  		t.Errorf("expected: %q, got: %q", expected, output)
   263  	}
   264  }
   265  
   266  func TestConfigActiveHelp(t *testing.T) {
   267  	rootCmd := &Command{
   268  		Use: "root",
   269  		Run: emptyRun,
   270  	}
   271  
   272  	childCmd := &Command{
   273  		Use:   "thechild",
   274  		Short: "The child command",
   275  		Run:   emptyRun,
   276  	}
   277  	rootCmd.AddCommand(childCmd)
   278  
   279  	activeHelpCfg := "someconfig,anotherconfig"
   280  	// Set the variable that the user would be setting
   281  	os.Setenv(activeHelpEnvVar(rootCmd.Name()), activeHelpCfg)
   282  
   283  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   284  		receivedActiveHelpCfg := GetActiveHelpConfig(cmd)
   285  		if receivedActiveHelpCfg != activeHelpCfg {
   286  			t.Errorf("expected activeHelpConfig: %q, but got: %q", activeHelpCfg, receivedActiveHelpCfg)
   287  		}
   288  		return nil, ShellCompDirectiveDefault
   289  	}
   290  
   291  	_, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   292  	if err != nil {
   293  		t.Errorf("Unexpected error: %v", err)
   294  	}
   295  
   296  	// Test active help config for a flag
   297  	activeHelpCfg = "a config for a flag"
   298  	// Set the variable that the completions scripts will be setting
   299  	os.Setenv(activeHelpEnvVar(rootCmd.Name()), activeHelpCfg)
   300  
   301  	flagname := "flag"
   302  	childCmd.Flags().String(flagname, "", "A flag")
   303  
   304  	// Test that multiple activeHelp message can be added
   305  	_ = childCmd.RegisterFlagCompletionFunc(flagname, func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   306  		receivedActiveHelpCfg := GetActiveHelpConfig(cmd)
   307  		if receivedActiveHelpCfg != activeHelpCfg {
   308  			t.Errorf("expected activeHelpConfig: %q, but got: %q", activeHelpCfg, receivedActiveHelpCfg)
   309  		}
   310  		return nil, ShellCompDirectiveDefault
   311  	})
   312  
   313  	_, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "--flag", "")
   314  	if err != nil {
   315  		t.Errorf("Unexpected error: %v", err)
   316  	}
   317  }
   318  
   319  func TestDisableActiveHelp(t *testing.T) {
   320  	rootCmd := &Command{
   321  		Use: "root",
   322  		Run: emptyRun,
   323  	}
   324  
   325  	childCmd := &Command{
   326  		Use:   "thechild",
   327  		Short: "The child command",
   328  		Run:   emptyRun,
   329  	}
   330  	rootCmd.AddCommand(childCmd)
   331  
   332  	// Test the disabling of activeHelp using the specific program
   333  	// environment variable that the completions scripts will be setting.
   334  	// Make sure the disabling value is "0" by hard-coding it in the tests;
   335  	// this is for backwards-compatibility as programs will be using this value.
   336  	os.Setenv(activeHelpEnvVar(rootCmd.Name()), "0")
   337  
   338  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   339  		comps := []string{"first"}
   340  		comps = AppendActiveHelp(comps, activeHelpMessage)
   341  		return comps, ShellCompDirectiveDefault
   342  	}
   343  
   344  	output, err := executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   345  	if err != nil {
   346  		t.Errorf("Unexpected error: %v", err)
   347  	}
   348  	os.Unsetenv(activeHelpEnvVar(rootCmd.Name()))
   349  
   350  	// Make sure there is no ActiveHelp in the output
   351  	expected := strings.Join([]string{
   352  		"first",
   353  		":0",
   354  		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
   355  
   356  	if output != expected {
   357  		t.Errorf("expected: %q, got: %q", expected, output)
   358  	}
   359  
   360  	// Now test the global disabling of ActiveHelp
   361  	os.Setenv(activeHelpGlobalEnvVar, "0")
   362  	// Set the specific variable, to make sure it is ignored when the global env
   363  	// var is set properly
   364  	os.Setenv(activeHelpEnvVar(rootCmd.Name()), "1")
   365  
   366  	output, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   367  	if err != nil {
   368  		t.Errorf("Unexpected error: %v", err)
   369  	}
   370  
   371  	// Make sure there is no ActiveHelp in the output
   372  	expected = strings.Join([]string{
   373  		"first",
   374  		":0",
   375  		"Completion ended with directive: ShellCompDirectiveDefault", ""}, "\n")
   376  
   377  	if output != expected {
   378  		t.Errorf("expected: %q, got: %q", expected, output)
   379  	}
   380  
   381  	// Make sure that if the global env variable is set to anything else than
   382  	// the disable value it is ignored
   383  	os.Setenv(activeHelpGlobalEnvVar, "on")
   384  	// Set the specific variable, to make sure it is used (while ignoring the global env var)
   385  	activeHelpCfg := "1"
   386  	os.Setenv(activeHelpEnvVar(rootCmd.Name()), activeHelpCfg)
   387  
   388  	childCmd.ValidArgsFunction = func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
   389  		receivedActiveHelpCfg := GetActiveHelpConfig(cmd)
   390  		if receivedActiveHelpCfg != activeHelpCfg {
   391  			t.Errorf("expected activeHelpConfig: %q, but got: %q", activeHelpCfg, receivedActiveHelpCfg)
   392  		}
   393  		return nil, ShellCompDirectiveDefault
   394  	}
   395  
   396  	_, err = executeCommand(rootCmd, ShellCompNoDescRequestCmd, "thechild", "")
   397  	if err != nil {
   398  		t.Errorf("Unexpected error: %v", err)
   399  	}
   400  }