github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/command/common/help_command_test.go (about)

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