github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+incompatible/command/common/help_command_test.go (about)

     1  package common_test
     2  
     3  import (
     4  	"regexp"
     5  
     6  	"code.cloudfoundry.org/cli/actor/actionerror"
     7  	"code.cloudfoundry.org/cli/actor/sharedaction"
     8  	"code.cloudfoundry.org/cli/command/commandfakes"
     9  	. "code.cloudfoundry.org/cli/command/common"
    10  	"code.cloudfoundry.org/cli/command/common/commonfakes"
    11  	"code.cloudfoundry.org/cli/command/flag"
    12  	"code.cloudfoundry.org/cli/util/configv3"
    13  	"code.cloudfoundry.org/cli/util/ui"
    14  
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/gomega"
    17  	. "github.com/onsi/gomega/gbytes"
    18  )
    19  
    20  var _ = Describe("help Command", func() {
    21  	var (
    22  		testUI     *ui.UI
    23  		fakeActor  *commonfakes.FakeHelpActor
    24  		cmd        HelpCommand
    25  		fakeConfig *commandfakes.FakeConfig
    26  	)
    27  
    28  	BeforeEach(func() {
    29  		testUI = ui.NewTestUI(NewBuffer(), NewBuffer(), NewBuffer())
    30  		fakeActor = new(commonfakes.FakeHelpActor)
    31  		fakeConfig = new(commandfakes.FakeConfig)
    32  		fakeConfig.BinaryNameReturns("faceman")
    33  		fakeConfig.BinaryVersionReturns("face2.0-yesterday")
    34  
    35  		cmd = HelpCommand{
    36  			UI:     testUI,
    37  			Actor:  fakeActor,
    38  			Config: fakeConfig,
    39  		}
    40  	})
    41  
    42  	Describe("providing help for a specific command", func() {
    43  		Describe("built-in command", func() {
    44  			BeforeEach(func() {
    45  				cmd.OptionalArgs = flag.CommandName{
    46  					CommandName: "help",
    47  				}
    48  
    49  				commandInfo := sharedaction.CommandInfo{
    50  					Name:        "help",
    51  					Description: "Show help",
    52  					Usage:       "CF_NAME help [COMMAND]",
    53  					Alias:       "h",
    54  				}
    55  				fakeActor.CommandInfoByNameReturns(commandInfo, nil)
    56  			})
    57  
    58  			It("displays the name for help", func() {
    59  				err := cmd.Execute(nil)
    60  				Expect(err).ToNot(HaveOccurred())
    61  
    62  				Expect(testUI.Out).To(Say("NAME:"))
    63  				Expect(testUI.Out).To(Say("   help - Show help"))
    64  
    65  				Expect(fakeActor.CommandInfoByNameCallCount()).To(Equal(1))
    66  				_, commandName := fakeActor.CommandInfoByNameArgsForCall(0)
    67  				Expect(commandName).To(Equal("help"))
    68  			})
    69  
    70  			It("displays the usage for help", func() {
    71  				err := cmd.Execute(nil)
    72  				Expect(err).ToNot(HaveOccurred())
    73  
    74  				Expect(testUI.Out).To(Say("NAME:"))
    75  				Expect(testUI.Out).To(Say("USAGE:"))
    76  				Expect(testUI.Out).To(Say(`   faceman help \[COMMAND\]`))
    77  			})
    78  
    79  			Describe("related commands", func() {
    80  				When("the command has related commands", func() {
    81  					BeforeEach(func() {
    82  						commandInfo := sharedaction.CommandInfo{
    83  							Name:            "app",
    84  							RelatedCommands: []string{"broccoli", "tomato"},
    85  						}
    86  						fakeActor.CommandInfoByNameReturns(commandInfo, nil)
    87  					})
    88  
    89  					It("displays the related commands for help", func() {
    90  						err := cmd.Execute(nil)
    91  						Expect(err).ToNot(HaveOccurred())
    92  
    93  						Expect(testUI.Out).To(Say("NAME:"))
    94  						Expect(testUI.Out).To(Say("SEE ALSO:"))
    95  						Expect(testUI.Out).To(Say("   broccoli, tomato"))
    96  					})
    97  				})
    98  
    99  				When("the command does not have related commands", func() {
   100  					It("displays the related commands for help", func() {
   101  						err := cmd.Execute(nil)
   102  						Expect(err).ToNot(HaveOccurred())
   103  
   104  						Expect(testUI.Out).To(Say("NAME:"))
   105  						Expect(testUI.Out).NotTo(Say("SEE ALSO:"))
   106  					})
   107  				})
   108  			})
   109  
   110  			Describe("aliases", func() {
   111  				When("the command has an alias", func() {
   112  					It("displays the alias for help", func() {
   113  						err := cmd.Execute(nil)
   114  						Expect(err).ToNot(HaveOccurred())
   115  
   116  						Expect(testUI.Out).To(Say("USAGE:"))
   117  						Expect(testUI.Out).To(Say("ALIAS:"))
   118  						Expect(testUI.Out).To(Say("   h"))
   119  					})
   120  				})
   121  
   122  				When("the command does not have an alias", func() {
   123  					BeforeEach(func() {
   124  						cmd.OptionalArgs = flag.CommandName{
   125  							CommandName: "app",
   126  						}
   127  
   128  						commandInfo := sharedaction.CommandInfo{
   129  							Name: "app",
   130  						}
   131  						fakeActor.CommandInfoByNameReturns(commandInfo, nil)
   132  					})
   133  
   134  					It("no alias is displayed", func() {
   135  						err := cmd.Execute(nil)
   136  						Expect(err).ToNot(HaveOccurred())
   137  
   138  						Expect(testUI.Out).ToNot(Say("ALIAS:"))
   139  					})
   140  				})
   141  			})
   142  
   143  			Describe("options", func() {
   144  				When("the command has options", func() {
   145  					BeforeEach(func() {
   146  						cmd.OptionalArgs = flag.CommandName{
   147  							CommandName: "push",
   148  						}
   149  						commandInfo := sharedaction.CommandInfo{
   150  							Name: "push",
   151  							Flags: []sharedaction.CommandFlag{
   152  								{
   153  									Long:        "no-hostname",
   154  									Description: "Map the root domain to this app",
   155  								},
   156  								{
   157  									Short:       "b",
   158  									Description: "Custom buildpack by name (e.g. my-buildpack) or Git URL (e.g. 'https://github.com/cloudfoundry/java-buildpack.git') or Git URL with a branch or tag (e.g. 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0' for 'v3.3.0' tag). To use built-in buildpacks only, specify 'default' or 'null'",
   159  								},
   160  								{
   161  									Long:        "hostname",
   162  									Short:       "n",
   163  									Description: "Hostname (e.g. my-subdomain)",
   164  								},
   165  								{
   166  									Long:        "force",
   167  									Short:       "f",
   168  									Description: "do it",
   169  									Default:     "yes",
   170  								},
   171  							},
   172  						}
   173  						fakeActor.CommandInfoByNameReturns(commandInfo, nil)
   174  					})
   175  
   176  					Context("only has a long option", func() {
   177  						It("displays the options for app", func() {
   178  							err := cmd.Execute(nil)
   179  							Expect(err).ToNot(HaveOccurred())
   180  
   181  							Expect(testUI.Out).To(Say("USAGE:"))
   182  							Expect(testUI.Out).To(Say("OPTIONS:"))
   183  							Expect(testUI.Out).To(Say(`--no-hostname\s+Map the root domain to this app`))
   184  						})
   185  					})
   186  
   187  					Context("only has a short option", func() {
   188  						It("displays the options for app", func() {
   189  							err := cmd.Execute(nil)
   190  							Expect(err).ToNot(HaveOccurred())
   191  
   192  							Expect(testUI.Out).To(Say("USAGE:"))
   193  							Expect(testUI.Out).To(Say("OPTIONS:"))
   194  							Expect(testUI.Out).To(Say(`-b\s+Custom buildpack by name \(e.g. my-buildpack\) or Git URL \(e.g. 'https://github.com/cloudfoundry/java-buildpack.git'\) or Git URL with a branch or tag \(e.g. 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0' for 'v3.3.0' tag\). To use built-in buildpacks only, specify 'default' or 'null'`))
   195  						})
   196  					})
   197  
   198  					Context("has long and short options", func() {
   199  						It("displays the options for app", func() {
   200  							err := cmd.Execute(nil)
   201  							Expect(err).ToNot(HaveOccurred())
   202  
   203  							Expect(testUI.Out).To(Say("USAGE:"))
   204  							Expect(testUI.Out).To(Say("OPTIONS:"))
   205  							Expect(testUI.Out).To(Say(`--hostname, -n\s+Hostname \(e.g. my-subdomain\)`))
   206  						})
   207  					})
   208  
   209  					Context("has a default for an option", func() {
   210  						It("displays the default", func() {
   211  							err := cmd.Execute(nil)
   212  							Expect(err).ToNot(HaveOccurred())
   213  
   214  							Expect(testUI.Out).To(Say(`do it \(Default: yes\)`))
   215  						})
   216  					})
   217  				})
   218  			})
   219  		})
   220  
   221  		Describe("Environment", func() {
   222  			Context("has environment variables", func() {
   223  				var envVars []sharedaction.EnvironmentVariable
   224  
   225  				BeforeEach(func() {
   226  					cmd.OptionalArgs = flag.CommandName{
   227  						CommandName: "push",
   228  					}
   229  					envVars = []sharedaction.EnvironmentVariable{
   230  						sharedaction.EnvironmentVariable{
   231  							Name:         "CF_STAGING_TIMEOUT",
   232  							Description:  "Max wait time for buildpack staging, in minutes",
   233  							DefaultValue: "15",
   234  						},
   235  						sharedaction.EnvironmentVariable{
   236  							Name:         "CF_STARTUP_TIMEOUT",
   237  							Description:  "Max wait time for app instance startup, in minutes",
   238  							DefaultValue: "5",
   239  						},
   240  					}
   241  					commandInfo := sharedaction.CommandInfo{
   242  						Name:        "push",
   243  						Environment: envVars,
   244  					}
   245  
   246  					fakeActor.CommandInfoByNameReturns(commandInfo, nil)
   247  				})
   248  
   249  				It("displays the timeouts under environment", func() {
   250  					err := cmd.Execute(nil)
   251  					Expect(err).ToNot(HaveOccurred())
   252  
   253  					Expect(testUI.Out).To(Say("ENVIRONMENT:"))
   254  					Expect(testUI.Out).To(Say(`
   255     CF_STAGING_TIMEOUT=15        Max wait time for buildpack staging, in minutes
   256     CF_STARTUP_TIMEOUT=5         Max wait time for app instance startup, in minutes
   257  `))
   258  				})
   259  			})
   260  
   261  			Context("does not have any associated environment variables", func() {
   262  				BeforeEach(func() {
   263  					cmd.OptionalArgs = flag.CommandName{
   264  						CommandName: "app",
   265  					}
   266  					commandInfo := sharedaction.CommandInfo{
   267  						Name: "app",
   268  					}
   269  
   270  					fakeActor.CommandInfoByNameReturns(commandInfo, nil)
   271  				})
   272  
   273  				It("does not show the environment section", func() {
   274  					err := cmd.Execute(nil)
   275  					Expect(err).ToNot(HaveOccurred())
   276  					Expect(testUI.Out).ToNot(Say("ENVIRONMENT:"))
   277  				})
   278  			})
   279  		})
   280  
   281  		Describe("plug-in command", func() {
   282  			BeforeEach(func() {
   283  				cmd.OptionalArgs = flag.CommandName{
   284  					CommandName: "enable-diego",
   285  				}
   286  
   287  				fakeConfig.PluginsReturns([]configv3.Plugin{
   288  					{Name: "Diego-Enabler",
   289  						Commands: []configv3.PluginCommand{
   290  							{
   291  								Name:     "enable-diego",
   292  								Alias:    "ed",
   293  								HelpText: "enable Diego support for an app",
   294  								UsageDetails: configv3.PluginUsageDetails{
   295  									Usage: "faceman diego-enabler this and that and a little stuff",
   296  									Options: map[string]string{
   297  										"--first":        "foobar",
   298  										"--second-third": "baz",
   299  									},
   300  								},
   301  							},
   302  						},
   303  					},
   304  				})
   305  
   306  				fakeActor.CommandInfoByNameReturns(sharedaction.CommandInfo{},
   307  					actionerror.InvalidCommandError{CommandName: "enable-diego"})
   308  			})
   309  
   310  			It("displays the plugin's help", func() {
   311  				err := cmd.Execute(nil)
   312  				Expect(err).ToNot(HaveOccurred())
   313  
   314  				Expect(testUI.Out).To(Say("enable-diego - enable Diego support for an app"))
   315  				Expect(testUI.Out).To(Say("faceman diego-enabler this and that and a little stuff"))
   316  				Expect(testUI.Out).To(Say("ALIAS:"))
   317  				Expect(testUI.Out).To(Say("ed"))
   318  				Expect(testUI.Out).To(Say(`--first\s+foobar`))
   319  				Expect(testUI.Out).To(Say(`--second-third\s+baz`))
   320  			})
   321  		})
   322  
   323  		Describe("plug-in alias", func() {
   324  			BeforeEach(func() {
   325  				cmd.OptionalArgs = flag.CommandName{
   326  					CommandName: "ed",
   327  				}
   328  
   329  				fakeConfig.PluginsReturns([]configv3.Plugin{
   330  					{
   331  						Name: "Diego-Enabler",
   332  						Commands: []configv3.PluginCommand{
   333  							{
   334  								Name:     "enable-diego",
   335  								Alias:    "ed",
   336  								HelpText: "enable Diego support for an app",
   337  								UsageDetails: configv3.PluginUsageDetails{
   338  									Usage: "faceman diego-enabler this and that and a little stuff",
   339  									Options: map[string]string{
   340  										"--first":        "foobar",
   341  										"--second-third": "baz",
   342  									},
   343  								},
   344  							},
   345  						},
   346  					},
   347  				})
   348  
   349  				fakeActor.CommandInfoByNameReturns(sharedaction.CommandInfo{},
   350  					actionerror.InvalidCommandError{CommandName: "enable-diego"})
   351  			})
   352  
   353  			It("displays the plugin's help", func() {
   354  				err := cmd.Execute(nil)
   355  				Expect(err).ToNot(HaveOccurred())
   356  
   357  				Expect(testUI.Out).To(Say("enable-diego - enable Diego support for an app"))
   358  				Expect(testUI.Out).To(Say("faceman diego-enabler this and that and a little stuff"))
   359  				Expect(testUI.Out).To(Say("ALIAS:"))
   360  				Expect(testUI.Out).To(Say("ed"))
   361  				Expect(testUI.Out).To(Say(`--first\s+foobar`))
   362  				Expect(testUI.Out).To(Say(`--second-third\s+baz`))
   363  			})
   364  		})
   365  	})
   366  
   367  	Describe("help for common commands", func() {
   368  		BeforeEach(func() {
   369  			cmd.OptionalArgs = flag.CommandName{
   370  				CommandName: "",
   371  			}
   372  			cmd.AllCommands = false
   373  			cmd.Actor = sharedaction.NewActor(nil)
   374  		})
   375  
   376  		It("returns a list of only the common commands", func() {
   377  			err := cmd.Execute(nil)
   378  			Expect(err).ToNot(HaveOccurred())
   379  
   380  			Expect(testUI.Out).To(Say("faceman version face2.0-yesterday, Cloud Foundry command line tool"))
   381  			Expect(testUI.Out).To(Say(regexp.QuoteMeta("Usage: faceman [global options] command [arguments...] [command options]")))
   382  
   383  			Expect(testUI.Out).To(Say("Before getting started:"))
   384  			Expect(testUI.Out).To(Say(`  config\s+login,l\s+target,t`))
   385  			Expect(testUI.Out).To(Say(`  help,h\s+logout,lo`))
   386  
   387  			Expect(testUI.Out).To(Say("Application lifecycle:"))
   388  			Expect(testUI.Out).To(Say(`  apps,a\s+run-task,rt\s+events`))
   389  			Expect(testUI.Out).To(Say(`  push,p\s+logs\s+set-env,se`))
   390  			Expect(testUI.Out).To(Say(`  start,st\s+ssh\s+create-app-manifest`))
   391  			Expect(testUI.Out).To(Say(`  stop,sp\s+app\s+delete,d`))
   392  			Expect(testUI.Out).To(Say(`  restart,rs\s+env,e`))
   393  			Expect(testUI.Out).To(Say(`  restage,rg\s+scale`))
   394  
   395  			Expect(testUI.Out).To(Say("Services integration:"))
   396  			Expect(testUI.Out).To(Say(`  marketplace,m\s+create-user-provided-service,cups`))
   397  			Expect(testUI.Out).To(Say(`  services,s\s+update-user-provided-service,uups`))
   398  			Expect(testUI.Out).To(Say(`  create-service,cs\s+create-service-key,csk`))
   399  			Expect(testUI.Out).To(Say(`  update-service\s+delete-service-key,dsk`))
   400  			Expect(testUI.Out).To(Say(`  delete-service,ds\s+service-keys,sk`))
   401  			Expect(testUI.Out).To(Say(`  service\s+service-key`))
   402  			Expect(testUI.Out).To(Say(`  bind-service,bs\s+bind-route-service,brs`))
   403  			Expect(testUI.Out).To(Say(`  unbind-service,us\s+unbind-route-service,urs`))
   404  
   405  			Expect(testUI.Out).To(Say("Route and domain management:"))
   406  			Expect(testUI.Out).To(Say(`  routes,r\s+delete-route\s+create-domain`))
   407  			Expect(testUI.Out).To(Say(`  domains\s+map-route`))
   408  			Expect(testUI.Out).To(Say(`  create-route\s+unmap-route`))
   409  
   410  			Expect(testUI.Out).To(Say("Space management:"))
   411  			Expect(testUI.Out).To(Say(`  spaces\s+create-space\s+set-space-role`))
   412  			Expect(testUI.Out).To(Say(`  space-users\s+delete-space\s+unset-space-role`))
   413  
   414  			Expect(testUI.Out).To(Say("Org management:"))
   415  			Expect(testUI.Out).To(Say(`  orgs,o\s+set-org-role`))
   416  			Expect(testUI.Out).To(Say(`  org-users\s+unset-org-role`))
   417  
   418  			Expect(testUI.Out).To(Say("CLI plugin management:"))
   419  			Expect(testUI.Out).To(Say(`  plugins\s+add-plugin-repo\s+repo-plugins`))
   420  			Expect(testUI.Out).To(Say(`  install-plugin\s+list-plugin-repos`))
   421  
   422  			Expect(testUI.Out).To(Say("Global options:"))
   423  			Expect(testUI.Out).To(Say(`  --help, -h\s+Show help`))
   424  			Expect(testUI.Out).To(Say(`  -v\s+Print API request diagnostics to stdout`))
   425  
   426  			Expect(testUI.Out).To(Say(`Use 'cf help -a' to see all commands\.`))
   427  		})
   428  
   429  		When("there are multiple installed plugins", func() {
   430  			BeforeEach(func() {
   431  				fakeConfig.PluginsReturns([]configv3.Plugin{
   432  					{
   433  						Name: "Some-other-plugin",
   434  						Commands: []configv3.PluginCommand{
   435  							{
   436  								Name:     "some-other-plugin-command",
   437  								HelpText: "does some other thing",
   438  							},
   439  						},
   440  					},
   441  					{
   442  						Name: "some-plugin",
   443  						Commands: []configv3.PluginCommand{
   444  							{
   445  								Name:     "enable",
   446  								HelpText: "enable command",
   447  							},
   448  							{
   449  								Name:     "disable",
   450  								HelpText: "disable command",
   451  							},
   452  							{
   453  								Name:     "some-other-command",
   454  								HelpText: "does something",
   455  							},
   456  						},
   457  					},
   458  					{
   459  						Name: "the-last-plugin",
   460  						Commands: []configv3.PluginCommand{
   461  							{
   462  								Name:     "last-plugin-command",
   463  								HelpText: "does the last thing",
   464  							},
   465  						},
   466  					},
   467  				})
   468  			})
   469  
   470  			It("returns the plugin commands organized by plugin and sorted in alphabetical order", func() {
   471  				err := cmd.Execute(nil)
   472  				Expect(err).ToNot(HaveOccurred())
   473  
   474  				Expect(testUI.Out).To(Say("Commands offered by installed plugins:"))
   475  				Expect(testUI.Out).To(Say(`some-other-plugin-command\s+enable\s+last-plugin-command`))
   476  				Expect(testUI.Out).To(Say(`disable\s+some-other-command`))
   477  
   478  			})
   479  		})
   480  	})
   481  
   482  	Describe("providing help for all commands", func() {
   483  		When("a command is not provided", func() {
   484  			BeforeEach(func() {
   485  				cmd.OptionalArgs = flag.CommandName{
   486  					CommandName: "",
   487  				}
   488  				cmd.AllCommands = true
   489  
   490  				cmd.Actor = sharedaction.NewActor(nil)
   491  				fakeConfig.PluginsReturns([]configv3.Plugin{
   492  					{
   493  						Name: "Diego-Enabler",
   494  						Commands: []configv3.PluginCommand{
   495  							{
   496  								Name:     "enable-diego",
   497  								HelpText: "enable Diego support for an app",
   498  							},
   499  						},
   500  					},
   501  				})
   502  			})
   503  
   504  			It("returns a list of all commands", func() {
   505  				Expect(cmd.Execute(nil)).ToNot(HaveOccurred())
   506  
   507  				Expect(testUI.Out).To(Say("NAME:"))
   508  				Expect(testUI.Out).To(Say("   faceman - A command line tool to interact with Cloud Foundry"))
   509  				Expect(testUI.Out).To(Say("USAGE:"))
   510  				Expect(testUI.Out).To(Say(`   faceman \[global options\] command \[arguments...\] \[command options\]`))
   511  				Expect(testUI.Out).To(Say("VERSION:"))
   512  				Expect(testUI.Out).To(Say("   face2.0-yesterday"))
   513  				Expect(testUI.Out).To(Say(""))
   514  				Expect(testUI.Out).To(Say("GETTING STARTED:"))
   515  				Expect(testUI.Out).To(Say(`   help\s+Show help`))
   516  				Expect(testUI.Out).To(Say(`   api\s+Set or view target api url`))
   517  				Expect(testUI.Out).To(Say(""))
   518  				Expect(testUI.Out).To(Say("APPS:"))
   519  				Expect(testUI.Out).To(Say(`   apps\s+List all apps in the target space`))
   520  				Expect(testUI.Out).To(Say(`   restart-app-instance\s+Terminate, then restart an app instance`))
   521  				Expect(testUI.Out).To(Say(`   ssh-enabled\s+Reports whether SSH is enabled on an application container instance`))
   522  				Expect(testUI.Out).To(Say(""))
   523  				Expect(testUI.Out).To(Say("SERVICES:"))
   524  				Expect(testUI.Out).To(Say(`   marketplace\s+List available offerings in the marketplace`))
   525  				Expect(testUI.Out).To(Say(`   create-service\s+Create a service instance`))
   526  				Expect(testUI.Out).To(Say(`   share-service\s+Share a service instance with another space`))
   527  				Expect(testUI.Out).To(Say(`   unshare-service\s+Unshare a shared service instance from a space`))
   528  				Expect(testUI.Out).To(Say(""))
   529  				Expect(testUI.Out).To(Say("ORGS:"))
   530  				Expect(testUI.Out).To(Say(`   orgs\s+List all orgs`))
   531  				Expect(testUI.Out).To(Say(`   delete-org\s+Delete an org`))
   532  				Expect(testUI.Out).To(Say(""))
   533  				Expect(testUI.Out).To(Say("SPACES:"))
   534  				Expect(testUI.Out).To(Say(`   spaces\s+List all spaces in an org`))
   535  				Expect(testUI.Out).To(Say(`   allow-space-ssh\s+Allow SSH access for the space`))
   536  				Expect(testUI.Out).To(Say(""))
   537  				Expect(testUI.Out).To(Say("DOMAINS:"))
   538  				Expect(testUI.Out).To(Say(`   domains\s+List domains in the target org`))
   539  				Expect(testUI.Out).To(Say(`   router-groups\s+List router groups`))
   540  				Expect(testUI.Out).To(Say(""))
   541  				Expect(testUI.Out).To(Say("ROUTES:"))
   542  				Expect(testUI.Out).To(Say(`   routes\s+List all routes in the current space or the current organization`))
   543  				Expect(testUI.Out).To(Say(`   unmap-route\s+Remove a url route from an app`))
   544  				Expect(testUI.Out).To(Say(""))
   545  				Expect(testUI.Out).To(Say("NETWORK POLICIES:"))
   546  				Expect(testUI.Out).To(Say(`   network-policies\s+List direct network traffic policies`))
   547  				Expect(testUI.Out).To(Say(`   add-network-policy\s+Create policy to allow direct network traffic from one app to another`))
   548  				Expect(testUI.Out).To(Say(`   remove-network-policy\s+Remove network traffic policy of an app`))
   549  				Expect(testUI.Out).To(Say(""))
   550  				Expect(testUI.Out).To(Say("BUILDPACKS:"))
   551  				Expect(testUI.Out).To(Say(`   buildpacks\s+List all buildpacks`))
   552  				Expect(testUI.Out).To(Say(`   delete-buildpack\s+Delete a buildpack`))
   553  				Expect(testUI.Out).To(Say(""))
   554  				Expect(testUI.Out).To(Say("USER ADMIN:"))
   555  				Expect(testUI.Out).To(Say(`   create-user\s+Create a new user`))
   556  				Expect(testUI.Out).To(Say(`   space-users\s+Show space users by role`))
   557  				Expect(testUI.Out).To(Say(""))
   558  				Expect(testUI.Out).To(Say("ORG ADMIN:"))
   559  				Expect(testUI.Out).To(Say(`   quotas\s+List available usage quotas`))
   560  				Expect(testUI.Out).To(Say(`   delete-quota\s+Delete a quota`))
   561  				Expect(testUI.Out).To(Say(""))
   562  				Expect(testUI.Out).To(Say("SPACE ADMIN:"))
   563  				Expect(testUI.Out).To(Say(`   space-quotas\s+List available space resource quotas`))
   564  				Expect(testUI.Out).To(Say(`   set-space-quota\s+Assign a space quota definition to a space`))
   565  				Expect(testUI.Out).To(Say(""))
   566  				Expect(testUI.Out).To(Say("SERVICE ADMIN:"))
   567  				Expect(testUI.Out).To(Say(`   service-auth-tokens\s+List service auth tokens`))
   568  				Expect(testUI.Out).To(Say(`   service-access\s+List service access settings`))
   569  				Expect(testUI.Out).To(Say(""))
   570  				Expect(testUI.Out).To(Say("SECURITY GROUP:"))
   571  				Expect(testUI.Out).To(Say(`   security-group\s+Show a single security group`))
   572  				Expect(testUI.Out).To(Say(`   staging-security-groups\s+List security groups in the staging set for applications`))
   573  				Expect(testUI.Out).To(Say(""))
   574  				Expect(testUI.Out).To(Say("ENVIRONMENT VARIABLE GROUPS:"))
   575  				Expect(testUI.Out).To(Say(`   running-environment-variable-group\s+Retrieve the contents of the running environment variable group`))
   576  				Expect(testUI.Out).To(Say("   set-running-environment-variable-group Pass parameters as JSON to create a running environment variable group"))
   577  				Expect(testUI.Out).To(Say(""))
   578  				Expect(testUI.Out).To(Say("ISOLATION SEGMENTS:"))
   579  				Expect(testUI.Out).To(Say(`   isolation-segments\s+List all isolation segments`))
   580  				Expect(testUI.Out).To(Say(`   create-isolation-segment\s+Create an isolation segment`))
   581  				Expect(testUI.Out).To(Say(`   delete-isolation-segment\s+Delete an isolation segment`))
   582  				Expect(testUI.Out).To(Say(`   enable-org-isolation\s+Entitle an organization to an isolation segment`))
   583  				Expect(testUI.Out).To(Say(`   disable-org-isolation\s+Revoke an organization's entitlement to an isolation segment`))
   584  				Expect(testUI.Out).To(Say(`   set-org-default-isolation-segment\s+Set the default isolation segment used for apps in spaces in an org`))
   585  				Expect(testUI.Out).To(Say(`   reset-org-default-isolation-segment\s+Reset the default isolation segment used for apps in spaces of an org`))
   586  				Expect(testUI.Out).To(Say("   set-space-isolation-segment"))
   587  				Expect(testUI.Out).To(Say("   reset-space-isolation-segment"))
   588  				Expect(testUI.Out).To(Say(""))
   589  				Expect(testUI.Out).To(Say("FEATURE FLAGS:"))
   590  				Expect(testUI.Out).To(Say(`   feature-flags\s+Retrieve list of feature flags with status`))
   591  				Expect(testUI.Out).To(Say("   disable-feature-flag"))
   592  				Expect(testUI.Out).To(Say(""))
   593  				Expect(testUI.Out).To(Say("ADVANCED:"))
   594  				Expect(testUI.Out).To(Say(`   curl\s+Executes a request to the targeted API endpoint`))
   595  				Expect(testUI.Out).To(Say(`   ssh-code\s+Get a one time password for ssh clients`))
   596  				Expect(testUI.Out).To(Say(""))
   597  				Expect(testUI.Out).To(Say("ADD/REMOVE PLUGIN REPOSITORY:"))
   598  				Expect(testUI.Out).To(Say(`   add-plugin-repo\s+Add a new plugin repository`))
   599  				Expect(testUI.Out).To(Say(`   repo-plugins\s+List all available plugins in specified repository or in all added repositories`))
   600  				Expect(testUI.Out).To(Say(""))
   601  				Expect(testUI.Out).To(Say("ADD/REMOVE PLUGIN:"))
   602  				Expect(testUI.Out).To(Say(`   plugins\s+List commands of installed plugins`))
   603  				Expect(testUI.Out).To(Say(`   uninstall-plugin\s+Uninstall CLI plugin`))
   604  				Expect(testUI.Out).To(Say(""))
   605  				Expect(testUI.Out).To(Say("INSTALLED PLUGIN COMMANDS:"))
   606  				Expect(testUI.Out).To(Say(`   enable-diego\s+enable Diego support for an app`))
   607  				Expect(testUI.Out).To(Say(""))
   608  				Expect(testUI.Out).To(Say("ENVIRONMENT VARIABLES:"))
   609  				Expect(testUI.Out).To(Say("   CF_COLOR=false                     Do not colorize output"))
   610  				Expect(testUI.Out).To(Say("   CF_DIAL_TIMEOUT=5                  Max wait time to establish a connection, including name resolution, in seconds"))
   611  				Expect(testUI.Out).To(Say("   CF_HOME=path/to/dir/               Override path to default config directory"))
   612  				Expect(testUI.Out).To(Say("   CF_PLUGIN_HOME=path/to/dir/        Override path to default plugin config directory"))
   613  				Expect(testUI.Out).To(Say("   CF_TRACE=true                      Print API request diagnostics to stdout"))
   614  				Expect(testUI.Out).To(Say("   CF_TRACE=path/to/trace.log         Append API request diagnostics to a log file"))
   615  				Expect(testUI.Out).To(Say("   all_proxy=proxy.example.com:8080   Specify a proxy server to enable proxying for all requests"))
   616  				Expect(testUI.Out).To(Say("   https_proxy=proxy.example.com:8080 Enable proxying for HTTP requests"))
   617  				Expect(testUI.Out).To(Say(""))
   618  				Expect(testUI.Out).To(Say("GLOBAL OPTIONS:"))
   619  				Expect(testUI.Out).To(Say("   --help, -h                         Show help"))
   620  				Expect(testUI.Out).To(Say("   -v                                 Print API request diagnostics to stdout"))
   621  				Expect(testUI.Out).To(Say(""))
   622  				Expect(testUI.Out).To(Say(`APPS \(experimental\):`))
   623  				Expect(testUI.Out).To(Say(`   v3-apps\s+List all apps in the target space`))
   624  				Expect(testUI.Out).To(Say(`   v3-create-app\s+Create a V3 App`))
   625  				Expect(testUI.Out).To(Say(`   v3-push\s+Push a new app or sync changes to an existing app`))
   626  				Expect(testUI.Out).To(Say(`   v3-scale\s+Change or view the instance count, disk space limit, and memory limit for an app`))
   627  				Expect(testUI.Out).To(Say(`   v3-delete\s+Delete a V3 App`))
   628  				Expect(testUI.Out).To(Say(`   v3-start\s+Start an app`))
   629  				Expect(testUI.Out).To(Say(`   v3-stop\s+Stop an app`))
   630  				Expect(testUI.Out).To(Say(`   v3-restart\s+Stop all instances of the app, then start them again. This causes downtime.`))
   631  				Expect(testUI.Out).To(Say(`   v3-stage\s+Create a new droplet for an app`))
   632  				Expect(testUI.Out).To(Say(`   v3-restart-app-instance\s+Terminate, then instantiate an app instance`))
   633  				Expect(testUI.Out).To(Say(`   v3-apply-manifest\s+Applies manifest properties to an application`))
   634  				Expect(testUI.Out).To(Say(`   v3-droplets\s+List droplets of an app`))
   635  				Expect(testUI.Out).To(Say(`   v3-set-droplet\s+Set the droplet used to run an app`))
   636  				Expect(testUI.Out).To(Say(`   v3-env\s+Show all env variables for an app`))
   637  				Expect(testUI.Out).To(Say(`   v3-set-env\s+Set an env variable for an app`))
   638  				Expect(testUI.Out).To(Say(`   v3-unset-env\s+Remove an env variable from an app`))
   639  				Expect(testUI.Out).To(Say(`   v3-get-health-check\s+Show the type of health check performed on an app`))
   640  				Expect(testUI.Out).To(Say(`   v3-set-health-check\s+Change type of health check performed on an app's process`))
   641  				Expect(testUI.Out).To(Say(`   v3-packages\s+List packages of an app`))
   642  				Expect(testUI.Out).To(Say(`   v3-create-package\s+Uploads a V3 Package`))
   643  				Expect(testUI.Out).To(Say(`   v3-ssh\s+SSH to an application container instance`))
   644  			})
   645  
   646  			When("there are multiple installed plugins", func() {
   647  				BeforeEach(func() {
   648  					fakeConfig.PluginsReturns([]configv3.Plugin{
   649  						{
   650  							Name: "Some-other-plugin",
   651  							Commands: []configv3.PluginCommand{
   652  								{
   653  									Name:     "some-other-plugin-command",
   654  									HelpText: "does some other thing",
   655  								},
   656  							},
   657  						},
   658  						{
   659  							Name: "some-plugin",
   660  							Commands: []configv3.PluginCommand{
   661  								{
   662  									Name:     "enable",
   663  									HelpText: "enable command",
   664  								},
   665  								{
   666  									Name:     "disable",
   667  									HelpText: "disable command",
   668  								},
   669  								{
   670  									Name:     "some-other-command",
   671  									HelpText: "does something",
   672  								},
   673  							},
   674  						},
   675  						{
   676  							Name: "the-last-plugin",
   677  							Commands: []configv3.PluginCommand{
   678  								{
   679  									Name:     "last-plugin-command",
   680  									HelpText: "does the last thing",
   681  								},
   682  							},
   683  						},
   684  					})
   685  				})
   686  
   687  				It("returns the plugin commands organized by plugin and sorted in alphabetical order", func() {
   688  					err := cmd.Execute(nil)
   689  					Expect(err).ToNot(HaveOccurred())
   690  
   691  					Expect(testUI.Out).To(Say(`INSTALLED PLUGIN COMMANDS:.*
   692  \s+some-other-plugin-command\s+does some other thing.*
   693  \s+disable\s+disable command.*
   694  \s+enable\s+enable command.*
   695  \s+some-other-command\s+does something.*
   696  \s+last-plugin-command\s+does the last thing`))
   697  				})
   698  			})
   699  		})
   700  	})
   701  })