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 }