github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/command/v7/start_command_test.go (about)

     1  package v7_test
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
     8  
     9  	"context"
    10  
    11  	"code.cloudfoundry.org/cli/actor/actionerror"
    12  	"code.cloudfoundry.org/cli/actor/v7action"
    13  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    14  	"code.cloudfoundry.org/cli/command/commandfakes"
    15  	"code.cloudfoundry.org/cli/command/flag"
    16  	v7 "code.cloudfoundry.org/cli/command/v7"
    17  	"code.cloudfoundry.org/cli/command/v7/v7fakes"
    18  	"code.cloudfoundry.org/cli/types"
    19  	"code.cloudfoundry.org/cli/util/configv3"
    20  	"code.cloudfoundry.org/cli/util/ui"
    21  	. "github.com/onsi/ginkgo"
    22  	. "github.com/onsi/gomega"
    23  	. "github.com/onsi/gomega/gbytes"
    24  )
    25  
    26  var _ = Describe("start Command", func() {
    27  	var (
    28  		cmd                v7.StartCommand
    29  		testUI             *ui.UI
    30  		fakeConfig         *commandfakes.FakeConfig
    31  		fakeSharedActor    *commandfakes.FakeSharedActor
    32  		fakeActor          *v7fakes.FakeStartActor
    33  		fakeLogCacheClient *v7actionfakes.FakeLogCacheClient
    34  
    35  		binaryName  string
    36  		executeErr  error
    37  		app         string
    38  		packageGUID string
    39  	)
    40  
    41  	BeforeEach(func() {
    42  		testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer())
    43  		fakeConfig = new(commandfakes.FakeConfig)
    44  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    45  		fakeActor = new(v7fakes.FakeStartActor)
    46  		fakeLogCacheClient = new(v7actionfakes.FakeLogCacheClient)
    47  
    48  		binaryName = "faceman"
    49  		fakeConfig.BinaryNameReturns(binaryName)
    50  		app = "some-app"
    51  		packageGUID = "some-package-guid"
    52  
    53  		cmd = v7.StartCommand{
    54  			RequiredArgs: flag.AppName{AppName: app},
    55  
    56  			UI:             testUI,
    57  			Config:         fakeConfig,
    58  			SharedActor:    fakeSharedActor,
    59  			Actor:          fakeActor,
    60  			LogCacheClient: fakeLogCacheClient,
    61  		}
    62  	})
    63  
    64  	JustBeforeEach(func() {
    65  		executeErr = cmd.Execute(nil)
    66  	})
    67  
    68  	It("displays the experimental warning", func() {
    69  		Expect(testUI.Err).NotTo(Say("This command is in EXPERIMENTAL stage and may change without notice"))
    70  	})
    71  
    72  	When("checking target fails", func() {
    73  		BeforeEach(func() {
    74  			fakeSharedActor.CheckTargetReturns(actionerror.NoOrganizationTargetedError{BinaryName: binaryName})
    75  		})
    76  
    77  		It("returns an error", func() {
    78  			Expect(executeErr).To(MatchError(actionerror.NoOrganizationTargetedError{BinaryName: binaryName}))
    79  
    80  			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
    81  			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
    82  			Expect(checkTargetedOrg).To(BeTrue())
    83  			Expect(checkTargetedSpace).To(BeTrue())
    84  		})
    85  	})
    86  
    87  	When("the user is not logged in", func() {
    88  		var expectedErr error
    89  
    90  		BeforeEach(func() {
    91  			expectedErr = errors.New("some current user error")
    92  			fakeConfig.CurrentUserReturns(configv3.User{}, expectedErr)
    93  		})
    94  
    95  		It("return an error", func() {
    96  			Expect(executeErr).To(Equal(expectedErr))
    97  		})
    98  	})
    99  
   100  	When("the actor does not return an error", func() {
   101  		BeforeEach(func() {
   102  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   103  				Name: "some-org",
   104  			})
   105  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   106  				Name: "some-space",
   107  				GUID: "some-space-guid",
   108  			})
   109  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   110  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{GUID: "some-app-guid", State: constant.ApplicationStopped}, v7action.Warnings{"get-warning-1", "get-warning-2"}, nil)
   111  			fakeActor.StartApplicationReturns(v7action.Warnings{"start-warning-1", "start-warning-2"}, nil)
   112  			fakeActor.PollStartReturns(v7action.Warnings{"poll-warning-1", "poll-warning-2"}, nil)
   113  		})
   114  
   115  		It("says that the app was started and outputs warnings", func() {
   116  			Expect(executeErr).ToNot(HaveOccurred())
   117  
   118  			Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as steve\.\.\.`))
   119  			Expect(testUI.Out).To(Say(`Waiting for app to start\.\.\.`))
   120  
   121  			Expect(testUI.Err).To(Say("get-warning-1"))
   122  			Expect(testUI.Err).To(Say("get-warning-2"))
   123  			Expect(testUI.Err).To(Say("start-warning-1"))
   124  			Expect(testUI.Err).To(Say("start-warning-2"))
   125  			Expect(testUI.Err).To(Say("poll-warning-1"))
   126  			Expect(testUI.Err).To(Say("poll-warning-2"))
   127  
   128  			Expect(fakeActor.StartApplicationCallCount()).To(Equal(1))
   129  			appGUID := fakeActor.StartApplicationArgsForCall(0)
   130  			Expect(appGUID).To(Equal("some-app-guid"))
   131  
   132  			Expect(fakeActor.PollStartCallCount()).To(Equal(1))
   133  			appGUID, noWait := fakeActor.PollStartArgsForCall(0)
   134  			Expect(appGUID).To(Equal("some-app-guid"))
   135  			Expect(noWait).To(Equal(false))
   136  		})
   137  	})
   138  
   139  	When("the get app call returns a ApplicationNotFoundError", func() {
   140  		var expectedErr error
   141  
   142  		BeforeEach(func() {
   143  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   144  				Name: "some-org",
   145  			})
   146  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   147  				Name: "some-space",
   148  			})
   149  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   150  			expectedErr = actionerror.ApplicationNotFoundError{Name: app}
   151  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStopped}, v7action.Warnings{"get-warning-1", "get-warning-2"}, expectedErr)
   152  		})
   153  
   154  		It("says that the app failed to start", func() {
   155  			Expect(executeErr).To(Equal(actionerror.ApplicationNotFoundError{Name: app}))
   156  			Expect(testUI.Out).ToNot(Say("Starting"))
   157  
   158  			Expect(testUI.Err).To(Say("get-warning-1"))
   159  			Expect(testUI.Err).To(Say("get-warning-2"))
   160  		})
   161  	})
   162  
   163  	When("the start app call returns a ApplicationNotFoundError (someone else deleted app after we fetched summary)", func() {
   164  		var expectedErr error
   165  
   166  		BeforeEach(func() {
   167  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   168  				Name: "some-org",
   169  			})
   170  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   171  				Name: "some-space",
   172  			})
   173  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   174  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStopped}, v7action.Warnings{"get-warning-1", "get-warning-2"}, nil)
   175  			expectedErr = actionerror.ApplicationNotFoundError{Name: app}
   176  			fakeActor.StartApplicationReturns(v7action.Warnings{"start-warning-1", "start-warning-2"}, expectedErr)
   177  		})
   178  
   179  		It("says that the app failed to start", func() {
   180  			Expect(executeErr).To(Equal(actionerror.ApplicationNotFoundError{Name: app}))
   181  			Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as steve\.\.\.`))
   182  			Expect(testUI.Out).To(Say(`Waiting for app to start\.\.\.`))
   183  
   184  			Expect(testUI.Err).To(Say("get-warning-1"))
   185  			Expect(testUI.Err).To(Say("get-warning-2"))
   186  			Expect(testUI.Err).To(Say("start-warning-1"))
   187  			Expect(testUI.Err).To(Say("start-warning-2"))
   188  		})
   189  	})
   190  
   191  	When("there is an error when polling the app", func() {
   192  		var expectedErr error
   193  
   194  		BeforeEach(func() {
   195  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   196  				Name: "some-org",
   197  			})
   198  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   199  				Name: "some-space",
   200  			})
   201  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   202  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStopped}, v7action.Warnings{"get-warning-1", "get-warning-2"}, nil)
   203  			expectedErr = actionerror.ApplicationNotStartedError{Name: app}
   204  			fakeActor.StartApplicationReturns(v7action.Warnings{"start-warning-1", "start-warning-2"}, nil)
   205  			fakeActor.PollStartReturns(v7action.Warnings{"poll-warning"}, expectedErr)
   206  		})
   207  
   208  		It("says that the app failed to start", func() {
   209  			Expect(executeErr).To(Equal(actionerror.ApplicationNotStartedError{Name: app}))
   210  			Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as steve\.\.\.`))
   211  			Expect(testUI.Out).To(Say(`Waiting for app to start\.\.\.`))
   212  
   213  			Expect(testUI.Err).To(Say("get-warning-1"))
   214  			Expect(testUI.Err).To(Say("get-warning-2"))
   215  			Expect(testUI.Err).To(Say("start-warning-1"))
   216  			Expect(testUI.Err).To(Say("start-warning-2"))
   217  			Expect(testUI.Err).To(Say("poll-warning"))
   218  		})
   219  	})
   220  
   221  	When("the app is already started", func() {
   222  		BeforeEach(func() {
   223  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   224  				Name: "some-org",
   225  			})
   226  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   227  				Name: "some-space",
   228  			})
   229  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   230  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStarted, Name: app}, v7action.Warnings{"get-warning-1", "get-warning-2"}, nil)
   231  		})
   232  
   233  		It("says that the app failed to start", func() {
   234  			Expect(executeErr).ToNot(HaveOccurred())
   235  			Expect(testUI.Out).ToNot(Say("Starting"))
   236  			Expect(testUI.Out).To(Say(`App 'some-app' is already started\.`))
   237  			Expect(testUI.Out).To(Say("OK"))
   238  
   239  			Expect(testUI.Err).To(Say("get-warning-1"))
   240  			Expect(testUI.Err).To(Say("get-warning-2"))
   241  
   242  			Expect(fakeActor.StartApplicationCallCount()).To(BeZero(), "Expected StartApplication to not be called")
   243  		})
   244  	})
   245  
   246  	When("getting attempting to get the unstaged package returns an error", func() {
   247  		var expectedErr error
   248  		BeforeEach(func() {
   249  			expectedErr = errors.New("error getting package")
   250  			app = "some-app"
   251  			fakeActor.GetUnstagedNewestPackageGUIDReturns("", v7action.Warnings{"needs-stage-warnings"}, expectedErr)
   252  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   253  				Name: "some-org",
   254  			})
   255  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   256  				Name: "some-space",
   257  				GUID: "some-space-guid",
   258  			})
   259  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   260  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStopped, LifecycleType: constant.AppLifecycleTypeBuildpack, GUID: "some-app-guid"}, v7action.Warnings{"get-warning-1", "get-warning-2"}, nil)
   261  		})
   262  		It("errors", func() {
   263  			Expect(testUI.Err).To(Say("needs-stage-warnings"))
   264  			Expect(executeErr).To(MatchError(expectedErr))
   265  			Expect(fakeActor.GetUnstagedNewestPackageGUIDCallCount()).To(Equal(1))
   266  			appGUID := fakeActor.GetUnstagedNewestPackageGUIDArgsForCall(0)
   267  			Expect(appGUID).To(Equal("some-app-guid"))
   268  		})
   269  	})
   270  
   271  	When("the app needs staging", func() {
   272  		BeforeEach(func() {
   273  			app = "some-app"
   274  			fakeActor.GetUnstagedNewestPackageGUIDReturns(packageGUID, v7action.Warnings{"needs-stage-warnings"}, nil)
   275  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   276  				Name: "some-org",
   277  			})
   278  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   279  				Name: "some-space",
   280  				GUID: "some-space-guid",
   281  			})
   282  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   283  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStopped, LifecycleType: constant.AppLifecycleTypeBuildpack, GUID: "some-app-guid"}, v7action.Warnings{"get-warning-1", "get-warning-2"}, nil)
   284  		})
   285  
   286  		When("the logging does not error", func() {
   287  			var allLogsWritten chan bool
   288  			var closedTheStreams bool
   289  
   290  			BeforeEach(func() {
   291  				allLogsWritten = make(chan bool)
   292  				fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = func(appName string, spaceGUID string, client v7action.LogCacheClient) (<-chan v7action.LogMessage, <-chan error, context.CancelFunc, v7action.Warnings, error) {
   293  					logStream := make(chan v7action.LogMessage)
   294  					errorStream := make(chan error)
   295  					closedTheStreams = false
   296  
   297  					cancelFunc := func() {
   298  						if closedTheStreams {
   299  							return
   300  						}
   301  						closedTheStreams = true
   302  						close(logStream)
   303  						close(errorStream)
   304  					}
   305  					go func() {
   306  						logStream <- *v7action.NewLogMessage("Here are some staging logs!", "OUT", time.Now(), v7action.StagingLog, "sourceInstance")
   307  						logStream <- *v7action.NewLogMessage("Here are some other staging logs!", "OUT", time.Now(), v7action.StagingLog, "sourceInstance")
   308  						allLogsWritten <- true
   309  					}()
   310  
   311  					return logStream, errorStream, cancelFunc, v7action.Warnings{"steve for all I care"}, nil
   312  				}
   313  			})
   314  
   315  			JustAfterEach(func() {
   316  				Expect(closedTheStreams).To(BeTrue())
   317  			})
   318  
   319  			When("the staging is successful", func() {
   320  				const dropletCreateTime = "2017-08-14T21:16:42Z"
   321  				BeforeEach(func() {
   322  					fakeActor.StagePackageStub = func(packageGUID, appName, spaceGUID string) (<-chan v7action.Droplet, <-chan v7action.Warnings, <-chan error) {
   323  						dropletStream := make(chan v7action.Droplet)
   324  						warningsStream := make(chan v7action.Warnings)
   325  						errorStream := make(chan error)
   326  
   327  						go func() {
   328  							<-allLogsWritten
   329  							defer close(dropletStream)
   330  							defer close(warningsStream)
   331  							defer close(errorStream)
   332  							warningsStream <- v7action.Warnings{"some-warning", "some-other-warning"}
   333  							dropletStream <- v7action.Droplet{
   334  								GUID:      "some-droplet-guid",
   335  								CreatedAt: dropletCreateTime,
   336  								State:     constant.DropletStaged,
   337  							}
   338  						}()
   339  
   340  						return dropletStream, warningsStream, errorStream
   341  					}
   342  					fakeActor.SetApplicationDropletReturns(v7action.Warnings{"some-set-droplet-warning"}, nil)
   343  				})
   344  
   345  				It("stages the package", func() {
   346  					Expect(executeErr).ToNot(HaveOccurred())
   347  					Expect(fakeActor.StagePackageCallCount()).To(Equal(1))
   348  					guidArg, appNameArg, spaceGUIDArg := fakeActor.StagePackageArgsForCall(0)
   349  					Expect(guidArg).To(Equal(packageGUID))
   350  					Expect(appNameArg).To(Equal(app))
   351  					Expect(spaceGUIDArg).To(Equal("some-space-guid"))
   352  				})
   353  
   354  				It("displays staging logs and their warnings", func() {
   355  					Expect(testUI.Out).To(Say("Here are some staging logs!"))
   356  					Expect(testUI.Out).To(Say("Here are some other staging logs!"))
   357  
   358  					Expect(testUI.Err).To(Say("steve for all I care"))
   359  
   360  					Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1))
   361  					appNameArg, spaceGUID, noaaClient := fakeActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(0)
   362  					Expect(appNameArg).To(Equal(app))
   363  					Expect(spaceGUID).To(Equal("some-space-guid"))
   364  					Expect(noaaClient).To(Equal(fakeLogCacheClient))
   365  
   366  					Expect(fakeActor.StagePackageCallCount()).To(Equal(1))
   367  					guidArg, appNameArg, spaceGUIDArg := fakeActor.StagePackageArgsForCall(0)
   368  					Expect(guidArg).To(Equal(packageGUID))
   369  					Expect(appNameArg).To(Equal(app))
   370  					Expect(spaceGUIDArg).To(Equal(spaceGUID))
   371  				})
   372  
   373  				When("Assigning the droplet is successful", func() {
   374  					BeforeEach(func() {
   375  						fakeActor.SetApplicationDropletReturns(v7action.Warnings{"some-set-droplet-warning"}, nil)
   376  					})
   377  					It("displays that the droplet was assigned", func() {
   378  						Expect(executeErr).ToNot(HaveOccurred())
   379  						Expect(testUI.Err).To(Say("warning-1"))
   380  						Expect(testUI.Err).To(Say("warning-2"))
   381  
   382  						Expect(fakeActor.SetApplicationDropletCallCount()).To(Equal(1))
   383  						appGuid, dropletGUID := fakeActor.SetApplicationDropletArgsForCall(0)
   384  						Expect(appGuid).To(Equal("some-app-guid"))
   385  						Expect(dropletGUID).To(Equal("some-droplet-guid"))
   386  
   387  					})
   388  				})
   389  
   390  				When("Assigning the droplet is not successful", func() {
   391  					var expectedErr error
   392  					BeforeEach(func() {
   393  						expectedErr = errors.New("some-error")
   394  						fakeActor.SetApplicationDropletReturns(v7action.Warnings{"some-set-droplet-warning"}, expectedErr)
   395  					})
   396  					It("errors and displays warnings", func() {
   397  						Expect(executeErr).To(HaveOccurred())
   398  						Expect(testUI.Err).To(Say("some-set-droplet-warning"))
   399  					})
   400  				})
   401  			})
   402  
   403  			When("the staging returns an error", func() {
   404  				var expectedErr error
   405  
   406  				BeforeEach(func() {
   407  					expectedErr = errors.New("any gibberish")
   408  					fakeActor.StagePackageStub = func(packageGUID, _, _ string) (<-chan v7action.Droplet, <-chan v7action.Warnings, <-chan error) {
   409  						dropletStream := make(chan v7action.Droplet)
   410  						warningsStream := make(chan v7action.Warnings)
   411  						errorStream := make(chan error)
   412  
   413  						go func() {
   414  							<-allLogsWritten
   415  							defer close(dropletStream)
   416  							defer close(warningsStream)
   417  							defer close(errorStream)
   418  							warningsStream <- v7action.Warnings{"some-warning", "some-other-warning"}
   419  							errorStream <- expectedErr
   420  						}()
   421  
   422  						return dropletStream, warningsStream, errorStream
   423  					}
   424  				})
   425  
   426  				It("returns the error and displays warnings", func() {
   427  					Expect(executeErr).To(Equal(expectedErr))
   428  
   429  					Expect(testUI.Err).To(Say("some-warning"))
   430  					Expect(testUI.Err).To(Say("some-other-warning"))
   431  				})
   432  			})
   433  		})
   434  
   435  		When("the logging stream has errors", func() {
   436  			var (
   437  				expectedErr      error
   438  				allLogsWritten   chan bool
   439  				closedTheStreams bool
   440  			)
   441  
   442  			BeforeEach(func() {
   443  				allLogsWritten = make(chan bool)
   444  				expectedErr = errors.New("banana")
   445  
   446  				fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = func(appName string, spaceGUID string, client v7action.LogCacheClient) (<-chan v7action.LogMessage, <-chan error, context.CancelFunc, v7action.Warnings, error) {
   447  					logStream := make(chan v7action.LogMessage)
   448  					errorStream := make(chan error)
   449  					closedTheStreams = false
   450  
   451  					cancelFunc := func() {
   452  						if closedTheStreams {
   453  							return
   454  						}
   455  						closedTheStreams = true
   456  						close(logStream)
   457  						close(errorStream)
   458  					}
   459  					go func() {
   460  						logStream <- *v7action.NewLogMessage("Here are some staging logs!", "OUT", time.Now(), v7action.StagingLog, "sourceInstance")
   461  						errorStream <- expectedErr
   462  						allLogsWritten <- true
   463  					}()
   464  
   465  					return logStream, errorStream, cancelFunc, v7action.Warnings{"steve for all I care"}, nil
   466  				}
   467  
   468  				fakeActor.StagePackageStub = func(packageGUID, _, _ string) (<-chan v7action.Droplet, <-chan v7action.Warnings, <-chan error) {
   469  					dropletStream := make(chan v7action.Droplet)
   470  					warningsStream := make(chan v7action.Warnings)
   471  					errorStream := make(chan error)
   472  
   473  					go func() {
   474  						<-allLogsWritten
   475  						defer close(dropletStream)
   476  						defer close(warningsStream)
   477  						defer close(errorStream)
   478  						warningsStream <- v7action.Warnings{"some-warning", "some-other-warning"}
   479  						dropletStream <- v7action.Droplet{
   480  							GUID:      "some-droplet-guid",
   481  							CreatedAt: "2017-08-14T21:16:42Z",
   482  							State:     constant.DropletStaged,
   483  						}
   484  					}()
   485  
   486  					return dropletStream, warningsStream, errorStream
   487  				}
   488  			})
   489  
   490  			JustAfterEach(func() {
   491  				Expect(closedTheStreams).To(BeTrue())
   492  			})
   493  
   494  			It("displays the errors and continues staging", func() {
   495  				Expect(executeErr).ToNot(HaveOccurred())
   496  
   497  				Expect(testUI.Err).To(Say("banana"))
   498  				Expect(testUI.Err).To(Say("some-warning"))
   499  				Expect(testUI.Err).To(Say("some-other-warning"))
   500  			})
   501  		})
   502  	})
   503  
   504  	When("the get application returns an unknown error", func() {
   505  		var expectedErr error
   506  
   507  		BeforeEach(func() {
   508  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   509  				Name: "some-org",
   510  			})
   511  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   512  				Name: "some-space",
   513  			})
   514  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   515  			expectedErr = errors.New("some-error")
   516  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStopped}, v7action.Warnings{"get-warning-1", "get-warning-2"}, expectedErr)
   517  		})
   518  
   519  		It("says that the app failed to start", func() {
   520  			Expect(executeErr).To(Equal(expectedErr))
   521  			Expect(testUI.Out).ToNot(Say("Starting"))
   522  
   523  			Expect(testUI.Err).To(Say("get-warning-1"))
   524  			Expect(testUI.Err).To(Say("get-warning-2"))
   525  
   526  			Expect(fakeActor.StartApplicationCallCount()).To(BeZero(), "Expected StartApplication to not be called")
   527  		})
   528  	})
   529  
   530  	When("the start application returns an unknown error", func() {
   531  		var expectedErr error
   532  
   533  		BeforeEach(func() {
   534  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   535  				Name: "some-org",
   536  			})
   537  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   538  				Name: "some-space",
   539  			})
   540  			fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil)
   541  			fakeActor.GetApplicationByNameAndSpaceReturns(v7action.Application{State: constant.ApplicationStopped}, v7action.Warnings{"get-warning-1", "get-warning-2"}, nil)
   542  			expectedErr = errors.New("some-error")
   543  			fakeActor.StartApplicationReturns(v7action.Warnings{"start-warning-1", "start-warning-2"}, expectedErr)
   544  		})
   545  
   546  		It("says that the app failed to start", func() {
   547  			Expect(executeErr).To(Equal(expectedErr))
   548  			Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as steve\.\.\.`))
   549  
   550  			Expect(testUI.Err).To(Say("get-warning-1"))
   551  			Expect(testUI.Err).To(Say("get-warning-2"))
   552  			Expect(testUI.Err).To(Say("start-warning-1"))
   553  			Expect(testUI.Err).To(Say("start-warning-2"))
   554  		})
   555  	})
   556  
   557  	When("getting the application summary returns an error", func() {
   558  		var expectedErr error
   559  
   560  		BeforeEach(func() {
   561  			expectedErr = actionerror.ApplicationNotFoundError{Name: app}
   562  			fakeActor.GetDetailedAppSummaryReturns(v7action.DetailedApplicationSummary{}, v7action.Warnings{"warning-1", "warning-2"}, expectedErr)
   563  		})
   564  
   565  		It("returns the error and prints warnings", func() {
   566  			Expect(executeErr).To(Equal(actionerror.ApplicationNotFoundError{Name: app}))
   567  
   568  			Expect(testUI.Out).To(Say(`Waiting for app to start\.\.\.`))
   569  
   570  			Expect(testUI.Err).To(Say("warning-1"))
   571  			Expect(testUI.Err).To(Say("warning-2"))
   572  		})
   573  	})
   574  
   575  	When("getting the application summary is successful", func() {
   576  		BeforeEach(func() {
   577  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   578  				Name: "some-space",
   579  				GUID: "some-space-guid",
   580  			})
   581  			summary := v7action.DetailedApplicationSummary{
   582  				ApplicationSummary: v7action.ApplicationSummary{
   583  					Application: v7action.Application{
   584  						Name:  "some-app",
   585  						State: constant.ApplicationStarted,
   586  					},
   587  					ProcessSummaries: v7action.ProcessSummaries{
   588  						{
   589  							Process: v7action.Process{
   590  								Type:    constant.ProcessTypeWeb,
   591  								Command: *types.NewFilteredString("some-command-1"),
   592  							},
   593  						},
   594  						{
   595  							Process: v7action.Process{
   596  								Type:    "console",
   597  								Command: *types.NewFilteredString("some-command-2"),
   598  							},
   599  						},
   600  					},
   601  				},
   602  				CurrentDroplet: v7action.Droplet{
   603  					Stack: "cflinuxfs2",
   604  					Buildpacks: []v7action.DropletBuildpack{
   605  						{
   606  							Name:         "ruby_buildpack",
   607  							DetectOutput: "some-detect-output",
   608  						},
   609  						{
   610  							Name:         "some-buildpack",
   611  							DetectOutput: "",
   612  						},
   613  					},
   614  				},
   615  			}
   616  			fakeActor.GetDetailedAppSummaryReturns(summary, v7action.Warnings{"warning-1", "warning-2"}, nil)
   617  		})
   618  
   619  		It("prints the application summary and outputs warnings", func() {
   620  			Expect(executeErr).ToNot(HaveOccurred())
   621  
   622  			Expect(testUI.Out).To(Say(`Waiting for app to start\.\.\.`))
   623  			Expect(testUI.Out).To(Say(`name:\s+some-app`))
   624  			Expect(testUI.Out).To(Say(`requested state:\s+started`))
   625  			Expect(testUI.Out).ToNot(Say("start command:"))
   626  
   627  			Expect(testUI.Err).To(Say("warning-1"))
   628  			Expect(testUI.Err).To(Say("warning-2"))
   629  
   630  			Expect(fakeActor.GetDetailedAppSummaryCallCount()).To(Equal(1))
   631  			appName, spaceGUID, withObfuscatedValues := fakeActor.GetDetailedAppSummaryArgsForCall(0)
   632  			Expect(appName).To(Equal("some-app"))
   633  			Expect(spaceGUID).To(Equal("some-space-guid"))
   634  			Expect(withObfuscatedValues).To(BeFalse())
   635  		})
   636  	})
   637  })