@@ -2465,7 +2465,7 @@ func TestDefaultCompletionCmd(t *testing.T) {
2465
2465
Run : emptyRun ,
2466
2466
}
2467
2467
2468
- // Test that no completion command is created if there are not other sub-commands
2468
+ // Test that when there are no sub-commands, the completion command is not created if it is not called directly.
2469
2469
assertNoErr (t , rootCmd .Execute ())
2470
2470
for _ , cmd := range rootCmd .commands {
2471
2471
if cmd .Name () == compCmdName {
@@ -2474,6 +2474,17 @@ func TestDefaultCompletionCmd(t *testing.T) {
2474
2474
}
2475
2475
}
2476
2476
2477
+ // Test that when there are no sub-commands, the completion command is created when it is called directly.
2478
+ _ , err := executeCommand (rootCmd , compCmdName )
2479
+ if err != nil {
2480
+ t .Errorf ("Unexpected error: %v" , err )
2481
+ }
2482
+ // Reset the arguments
2483
+ rootCmd .args = nil
2484
+ // Remove completion command for the next test
2485
+ removeCompCmd (rootCmd )
2486
+
2487
+ // Add a sub-command
2477
2488
subCmd := & Command {
2478
2489
Use : "sub" ,
2479
2490
Run : emptyRun ,
@@ -2595,19 +2606,55 @@ func TestDefaultCompletionCmd(t *testing.T) {
2595
2606
2596
2607
func TestCompleteCompletion (t * testing.T ) {
2597
2608
rootCmd := & Command {Use : "root" , Args : NoArgs , Run : emptyRun }
2609
+
2610
+ // Test that when there are no sub-commands, the 'completion' command is not completed
2611
+ // (because it is not created).
2612
+ output , err := executeCommand (rootCmd , ShellCompNoDescRequestCmd , "completion" )
2613
+ if err != nil {
2614
+ t .Errorf ("Unexpected error: %v" , err )
2615
+ }
2616
+
2617
+ expected := strings .Join ([]string {
2618
+ ":0" ,
2619
+ "Completion ended with directive: ShellCompDirectiveDefault" , "" }, "\n " )
2620
+
2621
+ if output != expected {
2622
+ t .Errorf ("expected: %q, got: %q" , expected , output )
2623
+ }
2624
+
2625
+ // Test that when there are no sub-commands, completion can be triggered for the default
2626
+ // 'completion' command
2627
+ output , err = executeCommand (rootCmd , ShellCompNoDescRequestCmd , "completion" , "" )
2628
+ if err != nil {
2629
+ t .Errorf ("Unexpected error: %v" , err )
2630
+ }
2631
+
2632
+ expected = strings .Join ([]string {
2633
+ "bash" ,
2634
+ "fish" ,
2635
+ "powershell" ,
2636
+ "zsh" ,
2637
+ ":4" ,
2638
+ "Completion ended with directive: ShellCompDirectiveNoFileComp" , "" }, "\n " )
2639
+
2640
+ if output != expected {
2641
+ t .Errorf ("expected: %q, got: %q" , expected , output )
2642
+ }
2643
+
2644
+ // Add a sub-command
2598
2645
subCmd := & Command {
2599
2646
Use : "sub" ,
2600
2647
Run : emptyRun ,
2601
2648
}
2602
2649
rootCmd .AddCommand (subCmd )
2603
2650
2604
2651
// Test sub-commands of the completion command
2605
- output , err : = executeCommand (rootCmd , ShellCompNoDescRequestCmd , "completion" , "" )
2652
+ output , err = executeCommand (rootCmd , ShellCompNoDescRequestCmd , "completion" , "" )
2606
2653
if err != nil {
2607
2654
t .Errorf ("Unexpected error: %v" , err )
2608
2655
}
2609
2656
2610
- expected : = strings .Join ([]string {
2657
+ expected = strings .Join ([]string {
2611
2658
"bash" ,
2612
2659
"fish" ,
2613
2660
"powershell" ,
@@ -3792,3 +3839,94 @@ func TestDisableDescriptions(t *testing.T) {
3792
3839
})
3793
3840
}
3794
3841
}
3842
+
3843
+ // A test to make sure the InitDefaultCompletionCmd function works as expected
3844
+ // in case a project calls it directly.
3845
+ func TestInitDefaultCompletionCmd (t * testing.T ) {
3846
+
3847
+ testCases := []struct {
3848
+ desc string
3849
+ hasChildCmd bool
3850
+ args []string
3851
+ expectCompCmd bool
3852
+ }{
3853
+ {
3854
+ desc : "no child command and not calling the completion command" ,
3855
+ hasChildCmd : false ,
3856
+ args : []string {"somearg" },
3857
+ expectCompCmd : false ,
3858
+ },
3859
+ {
3860
+ desc : "no child command but calling the completion command" ,
3861
+ hasChildCmd : false ,
3862
+ args : []string {"completion" },
3863
+ expectCompCmd : true ,
3864
+ },
3865
+ {
3866
+ desc : "no child command but calling __complete on the root command" ,
3867
+ hasChildCmd : false ,
3868
+ args : []string {"__complete" , "" },
3869
+ expectCompCmd : false ,
3870
+ },
3871
+ {
3872
+ desc : "no child command but calling __complete on the completion command" ,
3873
+ hasChildCmd : false ,
3874
+ args : []string {"__complete" , "completion" , "" },
3875
+ expectCompCmd : true ,
3876
+ },
3877
+ {
3878
+ desc : "with child command" ,
3879
+ hasChildCmd : true ,
3880
+ args : []string {"child" },
3881
+ expectCompCmd : true ,
3882
+ },
3883
+ {
3884
+ desc : "no child command not passing args" ,
3885
+ hasChildCmd : false ,
3886
+ args : nil ,
3887
+ expectCompCmd : false ,
3888
+ },
3889
+ {
3890
+ desc : "with child command not passing args" ,
3891
+ hasChildCmd : true ,
3892
+ args : nil ,
3893
+ expectCompCmd : true ,
3894
+ },
3895
+ }
3896
+
3897
+ for _ , tc := range testCases {
3898
+ t .Run (tc .desc , func (t * testing.T ) {
3899
+ rootCmd := & Command {Use : "root" , Run : emptyRun }
3900
+ childCmd := & Command {Use : "child" , Run : emptyRun }
3901
+
3902
+ expectedNumSubCommands := 0
3903
+ if tc .hasChildCmd {
3904
+ rootCmd .AddCommand (childCmd )
3905
+ expectedNumSubCommands ++
3906
+ }
3907
+
3908
+ if tc .expectCompCmd {
3909
+ expectedNumSubCommands ++
3910
+ }
3911
+
3912
+ if len (tc .args ) > 0 && tc .args [0 ] == "__complete" {
3913
+ expectedNumSubCommands ++
3914
+ }
3915
+
3916
+ // Setup the __complete command to mimic real world scenarios
3917
+ rootCmd .initCompleteCmd (tc .args )
3918
+
3919
+ // Call the InitDefaultCompletionCmd function directly
3920
+ if tc .args == nil {
3921
+ rootCmd .InitDefaultCompletionCmd ()
3922
+ } else {
3923
+ rootCmd .InitDefaultCompletionCmd (tc .args ... )
3924
+ }
3925
+
3926
+ // Check if the completion command was added
3927
+ if len (rootCmd .Commands ()) != expectedNumSubCommands {
3928
+ t .Errorf ("Expected %d subcommands, got %d" , expectedNumSubCommands , len (rootCmd .Commands ()))
3929
+ }
3930
+ })
3931
+ }
3932
+ }
0 commit comments