github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/command/v2/start_command_test.go (about)

     1  package v2_test
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"github.com/cloudfoundry/bytefmt"
     8  	"github.com/liamawhite/cli-with-i18n/actor/actionerror"
     9  	"github.com/liamawhite/cli-with-i18n/actor/sharedaction"
    10  	"github.com/liamawhite/cli-with-i18n/actor/v2action"
    11  	"github.com/liamawhite/cli-with-i18n/api/cloudcontroller/ccv2"
    12  	"github.com/liamawhite/cli-with-i18n/command/commandfakes"
    13  	"github.com/liamawhite/cli-with-i18n/command/translatableerror"
    14  	. "github.com/liamawhite/cli-with-i18n/command/v2"
    15  	"github.com/liamawhite/cli-with-i18n/command/v2/v2fakes"
    16  	"github.com/liamawhite/cli-with-i18n/types"
    17  	"github.com/liamawhite/cli-with-i18n/util/configv3"
    18  	"github.com/liamawhite/cli-with-i18n/util/ui"
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  	. "github.com/onsi/gomega/gbytes"
    22  )
    23  
    24  var _ = Describe("Start Command", func() {
    25  	var (
    26  		cmd             StartCommand
    27  		testUI          *ui.UI
    28  		fakeConfig      *commandfakes.FakeConfig
    29  		fakeSharedActor *commandfakes.FakeSharedActor
    30  		fakeActor       *v2fakes.FakeStartActor
    31  		binaryName      string
    32  		executeErr      error
    33  	)
    34  
    35  	BeforeEach(func() {
    36  		testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer())
    37  		fakeConfig = new(commandfakes.FakeConfig)
    38  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    39  		fakeActor = new(v2fakes.FakeStartActor)
    40  
    41  		cmd = StartCommand{
    42  			UI:          testUI,
    43  			Config:      fakeConfig,
    44  			SharedActor: fakeSharedActor,
    45  			Actor:       fakeActor,
    46  		}
    47  
    48  		cmd.RequiredArgs.AppName = "some-app"
    49  
    50  		binaryName = "faceman"
    51  		fakeConfig.BinaryNameReturns(binaryName)
    52  
    53  		var err error
    54  		testUI.TimezoneLocation, err = time.LoadLocation("America/Los_Angeles")
    55  		Expect(err).NotTo(HaveOccurred())
    56  
    57  		fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
    58  			messages := make(chan *v2action.LogMessage)
    59  			logErrs := make(chan error)
    60  			appState := make(chan v2action.ApplicationStateChange)
    61  			warnings := make(chan string)
    62  			errs := make(chan error)
    63  
    64  			go func() {
    65  				close(messages)
    66  				close(logErrs)
    67  				close(appState)
    68  				close(warnings)
    69  				close(errs)
    70  			}()
    71  
    72  			return messages, logErrs, appState, warnings, errs
    73  		}
    74  	})
    75  
    76  	JustBeforeEach(func() {
    77  		executeErr = cmd.Execute(nil)
    78  	})
    79  
    80  	Context("when checking target fails", func() {
    81  		BeforeEach(func() {
    82  			fakeSharedActor.CheckTargetReturns(sharedaction.NotLoggedInError{BinaryName: binaryName})
    83  		})
    84  
    85  		It("returns an error if the check fails", func() {
    86  			Expect(executeErr).To(MatchError(translatableerror.NotLoggedInError{BinaryName: "faceman"}))
    87  
    88  			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
    89  			_, checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
    90  			Expect(checkTargetedOrg).To(BeTrue())
    91  			Expect(checkTargetedSpace).To(BeTrue())
    92  		})
    93  	})
    94  
    95  	Context("when the user is logged in, and org and space are targeted", func() {
    96  		BeforeEach(func() {
    97  			fakeConfig.HasTargetedOrganizationReturns(true)
    98  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: "some-org"})
    99  			fakeConfig.HasTargetedSpaceReturns(true)
   100  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   101  				GUID: "some-space-guid",
   102  				Name: "some-space"})
   103  			fakeConfig.CurrentUserReturns(
   104  				configv3.User{Name: "some-user"},
   105  				nil)
   106  		})
   107  
   108  		Context("when getting the current user returns an error", func() {
   109  			var expectedErr error
   110  
   111  			BeforeEach(func() {
   112  				expectedErr = errors.New("getting current user error")
   113  				fakeConfig.CurrentUserReturns(
   114  					configv3.User{},
   115  					expectedErr)
   116  			})
   117  
   118  			It("returns the error", func() {
   119  				Expect(executeErr).To(MatchError(expectedErr))
   120  			})
   121  		})
   122  
   123  		It("displays flavor text", func() {
   124  			Expect(testUI.Out).To(Say("Starting app some-app in org some-org / space some-space as some-user..."))
   125  		})
   126  
   127  		Context("when the app exists", func() {
   128  			Context("when the app is already started", func() {
   129  				BeforeEach(func() {
   130  					fakeActor.GetApplicationByNameAndSpaceReturns(
   131  						v2action.Application{State: ccv2.ApplicationStarted},
   132  						v2action.Warnings{"warning-1", "warning-2"},
   133  						nil,
   134  					)
   135  				})
   136  
   137  				It("short circuits and displays message", func() {
   138  					Expect(executeErr).ToNot(HaveOccurred())
   139  
   140  					Expect(testUI.Out).To(Say("App some-app is already started"))
   141  
   142  					Expect(testUI.Err).To(Say("warning-1"))
   143  					Expect(testUI.Err).To(Say("warning-2"))
   144  
   145  					Expect(fakeActor.StartApplicationCallCount()).To(Equal(0))
   146  				})
   147  			})
   148  
   149  			Context("when the app is not already started", func() {
   150  				BeforeEach(func() {
   151  					fakeActor.GetApplicationByNameAndSpaceReturns(
   152  						v2action.Application{GUID: "app-guid", State: ccv2.ApplicationStopped},
   153  						v2action.Warnings{"warning-1", "warning-2"},
   154  						nil,
   155  					)
   156  				})
   157  
   158  				It("starts the app", func() {
   159  					Expect(executeErr).ToNot(HaveOccurred())
   160  
   161  					Expect(testUI.Err).To(Say("warning-1"))
   162  					Expect(testUI.Err).To(Say("warning-2"))
   163  
   164  					Expect(fakeActor.StartApplicationCallCount()).To(Equal(1))
   165  					app, _, config := fakeActor.StartApplicationArgsForCall(0)
   166  					Expect(app.GUID).To(Equal("app-guid"))
   167  					Expect(config).To(Equal(fakeConfig))
   168  				})
   169  
   170  				Context("when passed an ApplicationStateStarting message", func() {
   171  					BeforeEach(func() {
   172  						fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   173  							messages := make(chan *v2action.LogMessage)
   174  							logErrs := make(chan error)
   175  							appState := make(chan v2action.ApplicationStateChange)
   176  							warnings := make(chan string)
   177  							errs := make(chan error)
   178  
   179  							go func() {
   180  								messages <- v2action.NewLogMessage("log message 1", 1, time.Unix(0, 0), "STG", "1")
   181  								messages <- v2action.NewLogMessage("log message 2", 1, time.Unix(0, 0), "STG", "1")
   182  								appState <- v2action.ApplicationStateStarting
   183  								close(messages)
   184  								close(logErrs)
   185  								close(appState)
   186  								close(warnings)
   187  								close(errs)
   188  							}()
   189  
   190  							return messages, logErrs, appState, warnings, errs
   191  						}
   192  					})
   193  
   194  					It("displays the log", func() {
   195  						Expect(executeErr).ToNot(HaveOccurred())
   196  						Expect(testUI.Out).To(Say("log message 1"))
   197  						Expect(testUI.Out).To(Say("log message 2"))
   198  						Expect(testUI.Out).To(Say("Waiting for app to start..."))
   199  					})
   200  				})
   201  
   202  				Context("when passed a log message", func() {
   203  					BeforeEach(func() {
   204  						fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   205  							messages := make(chan *v2action.LogMessage)
   206  							logErrs := make(chan error)
   207  							appState := make(chan v2action.ApplicationStateChange)
   208  							warnings := make(chan string)
   209  							errs := make(chan error)
   210  
   211  							go func() {
   212  								messages <- v2action.NewLogMessage("log message 1", 1, time.Unix(0, 0), "STG", "1")
   213  								messages <- v2action.NewLogMessage("log message 2", 1, time.Unix(0, 0), "STG", "1")
   214  								messages <- v2action.NewLogMessage("log message 3", 1, time.Unix(0, 0), "Something else", "1")
   215  								close(messages)
   216  								close(logErrs)
   217  								close(appState)
   218  								close(warnings)
   219  								close(errs)
   220  							}()
   221  
   222  							return messages, logErrs, appState, warnings, errs
   223  						}
   224  					})
   225  
   226  					It("displays the log", func() {
   227  						Expect(executeErr).ToNot(HaveOccurred())
   228  						Expect(testUI.Out).To(Say("log message 1"))
   229  						Expect(testUI.Out).To(Say("log message 2"))
   230  						Expect(testUI.Out).ToNot(Say("log message 3"))
   231  					})
   232  				})
   233  
   234  				Context("when passed an log err", func() {
   235  					Context("NOAA connection times out/closes", func() {
   236  						BeforeEach(func() {
   237  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   238  								messages := make(chan *v2action.LogMessage)
   239  								logErrs := make(chan error)
   240  								appState := make(chan v2action.ApplicationStateChange)
   241  								warnings := make(chan string)
   242  								errs := make(chan error)
   243  
   244  								go func() {
   245  									messages <- v2action.NewLogMessage("log message 1", 1, time.Unix(0, 0), "STG", "1")
   246  									messages <- v2action.NewLogMessage("log message 2", 1, time.Unix(0, 0), "STG", "1")
   247  									messages <- v2action.NewLogMessage("log message 3", 1, time.Unix(0, 0), "STG", "1")
   248  									logErrs <- v2action.NOAATimeoutError{}
   249  									close(messages)
   250  									close(logErrs)
   251  									close(appState)
   252  									close(warnings)
   253  									close(errs)
   254  								}()
   255  
   256  								return messages, logErrs, appState, warnings, errs
   257  							}
   258  
   259  							applicationSummary := v2action.ApplicationSummary{
   260  								Application: v2action.Application{
   261  									Name:                 "some-app",
   262  									GUID:                 "some-app-guid",
   263  									Instances:            types.NullInt{Value: 3, IsSet: true},
   264  									Memory:               128,
   265  									PackageUpdatedAt:     time.Unix(0, 0),
   266  									DetectedBuildpack:    types.FilteredString{IsSet: true, Value: "some-buildpack"},
   267  									State:                "STARTED",
   268  									DetectedStartCommand: types.FilteredString{IsSet: true, Value: "some start command"},
   269  								},
   270  								Stack: v2action.Stack{
   271  									Name: "potatos",
   272  								},
   273  								Routes: []v2action.Route{
   274  									{
   275  										Host: "banana",
   276  										Domain: v2action.Domain{
   277  											Name: "fruit.com",
   278  										},
   279  										Path: "/hi",
   280  									},
   281  									{
   282  										Domain: v2action.Domain{
   283  											Name: "foobar.com",
   284  										},
   285  										Port: types.NullInt{IsSet: true, Value: 13},
   286  									},
   287  								},
   288  							}
   289  							warnings := []string{"app-summary-warning"}
   290  
   291  							applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{}
   292  
   293  							fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   294  						})
   295  
   296  						It("displays a warning and continues until app has started", func() {
   297  							Expect(executeErr).To(BeNil())
   298  							Expect(testUI.Out).To(Say("message 1"))
   299  							Expect(testUI.Out).To(Say("message 2"))
   300  							Expect(testUI.Out).To(Say("message 3"))
   301  							Expect(testUI.Err).To(Say("timeout connecting to log server, no log will be shown"))
   302  							Expect(testUI.Out).To(Say("name:\\s+some-app"))
   303  						})
   304  					})
   305  
   306  					Context("an unexpected error occurs", func() {
   307  						var expectedErr error
   308  
   309  						BeforeEach(func() {
   310  							expectedErr = errors.New("err log message")
   311  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   312  								messages := make(chan *v2action.LogMessage)
   313  								logErrs := make(chan error)
   314  								appState := make(chan v2action.ApplicationStateChange)
   315  								warnings := make(chan string)
   316  								errs := make(chan error)
   317  
   318  								go func() {
   319  									logErrs <- expectedErr
   320  									close(messages)
   321  									close(logErrs)
   322  									close(appState)
   323  									close(warnings)
   324  									close(errs)
   325  								}()
   326  
   327  								return messages, logErrs, appState, warnings, errs
   328  							}
   329  						})
   330  
   331  						It("displays the error and continues to poll", func() {
   332  							Expect(executeErr).NotTo(HaveOccurred())
   333  							Expect(testUI.Err).To(Say(expectedErr.Error()))
   334  						})
   335  					})
   336  				})
   337  
   338  				Context("when passed a warning", func() {
   339  					Context("while NOAA is still logging", func() {
   340  						BeforeEach(func() {
   341  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   342  								messages := make(chan *v2action.LogMessage)
   343  								logErrs := make(chan error)
   344  								appState := make(chan v2action.ApplicationStateChange)
   345  								warnings := make(chan string)
   346  								errs := make(chan error)
   347  
   348  								go func() {
   349  									warnings <- "warning 1"
   350  									warnings <- "warning 2"
   351  									close(messages)
   352  									close(logErrs)
   353  									close(appState)
   354  									close(warnings)
   355  									close(errs)
   356  								}()
   357  
   358  								return messages, logErrs, appState, warnings, errs
   359  							}
   360  						})
   361  
   362  						It("displays the warnings to STDERR", func() {
   363  							Expect(executeErr).ToNot(HaveOccurred())
   364  							Expect(testUI.Err).To(Say("warning 1"))
   365  							Expect(testUI.Err).To(Say("warning 2"))
   366  						})
   367  					})
   368  
   369  					Context("while NOAA is no longer logging", func() {
   370  						BeforeEach(func() {
   371  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   372  								messages := make(chan *v2action.LogMessage)
   373  								logErrs := make(chan error)
   374  								appState := make(chan v2action.ApplicationStateChange)
   375  								warnings := make(chan string)
   376  								errs := make(chan error)
   377  
   378  								go func() {
   379  									warnings <- "warning 1"
   380  									warnings <- "warning 2"
   381  									logErrs <- v2action.NOAATimeoutError{}
   382  									close(messages)
   383  									close(logErrs)
   384  									warnings <- "warning 3"
   385  									warnings <- "warning 4"
   386  									close(appState)
   387  									close(warnings)
   388  									close(errs)
   389  								}()
   390  
   391  								return messages, logErrs, appState, warnings, errs
   392  							}
   393  						})
   394  
   395  						It("displays the warnings to STDERR", func() {
   396  							Expect(executeErr).ToNot(HaveOccurred())
   397  							Expect(testUI.Err).To(Say("warning 1"))
   398  							Expect(testUI.Err).To(Say("warning 2"))
   399  							Expect(testUI.Err).To(Say("timeout connecting to log server, no log will be shown"))
   400  							Expect(testUI.Err).To(Say("warning 3"))
   401  							Expect(testUI.Err).To(Say("warning 4"))
   402  						})
   403  					})
   404  				})
   405  
   406  				Context("when passed an API err", func() {
   407  					var apiErr error
   408  
   409  					BeforeEach(func() {
   410  						fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient, config v2action.Config) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   411  							messages := make(chan *v2action.LogMessage)
   412  							logErrs := make(chan error)
   413  							appState := make(chan v2action.ApplicationStateChange)
   414  							warnings := make(chan string)
   415  							errs := make(chan error)
   416  
   417  							go func() {
   418  								errs <- apiErr
   419  								close(messages)
   420  								close(logErrs)
   421  								close(appState)
   422  								close(warnings)
   423  								close(errs)
   424  							}()
   425  
   426  							return messages, logErrs, appState, warnings, errs
   427  						}
   428  					})
   429  
   430  					Context("an unexpected error", func() {
   431  						BeforeEach(func() {
   432  							apiErr = errors.New("err log message")
   433  						})
   434  
   435  						It("stops logging and returns the error", func() {
   436  							Expect(executeErr).To(MatchError(apiErr))
   437  						})
   438  					})
   439  
   440  					Context("staging failed", func() {
   441  						BeforeEach(func() {
   442  							apiErr = actionerror.StagingFailedError{Reason: "Something, but not nothing"}
   443  						})
   444  
   445  						It("stops logging and returns StagingFailedError", func() {
   446  							Expect(executeErr).To(MatchError(translatableerror.StagingFailedError{Message: "Something, but not nothing"}))
   447  						})
   448  					})
   449  
   450  					Context("staging timed out", func() {
   451  						BeforeEach(func() {
   452  							apiErr = actionerror.StagingTimeoutError{Name: "some-app", Timeout: time.Nanosecond}
   453  						})
   454  
   455  						It("stops logging and returns StagingTimeoutError", func() {
   456  							Expect(executeErr).To(MatchError(translatableerror.StagingTimeoutError{AppName: "some-app", Timeout: time.Nanosecond}))
   457  						})
   458  					})
   459  
   460  					Context("when the app instance crashes", func() {
   461  						BeforeEach(func() {
   462  							apiErr = actionerror.ApplicationInstanceCrashedError{Name: "some-app"}
   463  						})
   464  
   465  						It("stops logging and returns UnsuccessfulStartError", func() {
   466  							Expect(executeErr).To(MatchError(translatableerror.UnsuccessfulStartError{AppName: "some-app", BinaryName: "faceman"}))
   467  						})
   468  					})
   469  
   470  					Context("when the app instance flaps", func() {
   471  						BeforeEach(func() {
   472  							apiErr = actionerror.ApplicationInstanceFlappingError{Name: "some-app"}
   473  						})
   474  
   475  						It("stops logging and returns UnsuccessfulStartError", func() {
   476  							Expect(executeErr).To(MatchError(translatableerror.UnsuccessfulStartError{AppName: "some-app", BinaryName: "faceman"}))
   477  						})
   478  					})
   479  
   480  					Context("starting timeout", func() {
   481  						BeforeEach(func() {
   482  							apiErr = actionerror.StartupTimeoutError{Name: "some-app"}
   483  						})
   484  
   485  						It("stops logging and returns StartupTimeoutError", func() {
   486  							Expect(executeErr).To(MatchError(translatableerror.StartupTimeoutError{AppName: "some-app", BinaryName: "faceman"}))
   487  						})
   488  					})
   489  				})
   490  
   491  				Context("when the app finishes starting", func() {
   492  					var (
   493  						applicationSummary v2action.ApplicationSummary
   494  						warnings           []string
   495  					)
   496  
   497  					BeforeEach(func() {
   498  						applicationSummary = v2action.ApplicationSummary{
   499  							Application: v2action.Application{
   500  								Name:                 "some-app",
   501  								GUID:                 "some-app-guid",
   502  								Instances:            types.NullInt{Value: 3, IsSet: true},
   503  								Memory:               128,
   504  								PackageUpdatedAt:     time.Unix(0, 0),
   505  								DetectedBuildpack:    types.FilteredString{IsSet: true, Value: "some-buildpack"},
   506  								State:                "STARTED",
   507  								DetectedStartCommand: types.FilteredString{IsSet: true, Value: "some start command"},
   508  							},
   509  							IsolationSegment: "some-isolation-segment",
   510  							Stack: v2action.Stack{
   511  								Name: "potatos",
   512  							},
   513  							Routes: []v2action.Route{
   514  								{
   515  									Host: "banana",
   516  									Domain: v2action.Domain{
   517  										Name: "fruit.com",
   518  									},
   519  									Path: "/hi",
   520  								},
   521  								{
   522  									Domain: v2action.Domain{
   523  										Name: "foobar.com",
   524  									},
   525  									Port: types.NullInt{IsSet: true, Value: 13},
   526  								},
   527  							},
   528  						}
   529  						warnings = []string{"app-summary-warning"}
   530  
   531  						applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{
   532  							{
   533  								ID:          0,
   534  								State:       v2action.ApplicationInstanceState(ccv2.ApplicationInstanceRunning),
   535  								Since:       1403140717.984577,
   536  								CPU:         0.73,
   537  								Disk:        50 * bytefmt.MEGABYTE,
   538  								DiskQuota:   2048 * bytefmt.MEGABYTE,
   539  								Memory:      100 * bytefmt.MEGABYTE,
   540  								MemoryQuota: 128 * bytefmt.MEGABYTE,
   541  								Details:     "info from the backend",
   542  							},
   543  						}
   544  					})
   545  
   546  					Context("when the isolation segment is not empty", func() {
   547  						BeforeEach(func() {
   548  							fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   549  						})
   550  
   551  						It("displays the app summary with isolation segments as well as warnings", func() {
   552  							Expect(executeErr).ToNot(HaveOccurred())
   553  							Expect(testUI.Out).To(Say("name:\\s+some-app"))
   554  							Expect(testUI.Out).To(Say("requested state:\\s+started"))
   555  							Expect(testUI.Out).To(Say("instances:\\s+1\\/3"))
   556  							Expect(testUI.Out).To(Say("isolation segment:\\s+some-isolation-segment"))
   557  							Expect(testUI.Out).To(Say("usage:\\s+128M x 3 instances"))
   558  							Expect(testUI.Out).To(Say("routes:\\s+banana.fruit.com/hi, foobar.com:13"))
   559  							Expect(testUI.Out).To(Say("last uploaded:\\s+\\w{3} [0-3]\\d \\w{3} [0-2]\\d:[0-5]\\d:[0-5]\\d \\w+ \\d{4}"))
   560  							Expect(testUI.Out).To(Say("stack:\\s+potatos"))
   561  							Expect(testUI.Out).To(Say("buildpack:\\s+some-buildpack"))
   562  							Expect(testUI.Out).To(Say("start command:\\s+some start command"))
   563  
   564  							Expect(testUI.Err).To(Say("app-summary-warning"))
   565  						})
   566  
   567  						It("should display the instance table", func() {
   568  							Expect(executeErr).ToNot(HaveOccurred())
   569  							Expect(testUI.Out).To(Say("state\\s+since\\s+cpu\\s+memory\\s+disk"))
   570  							Expect(testUI.Out).To(Say(`#0\s+running\s+2014-06-19T01:18:37Z\s+73.0%\s+100M of 128M\s+50M of 2G\s+info from the backend`))
   571  						})
   572  
   573  					})
   574  
   575  					Context("when the isolation segment is empty", func() {
   576  						BeforeEach(func() {
   577  							applicationSummary.IsolationSegment = ""
   578  							fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   579  						})
   580  
   581  						It("displays the app summary without isolation segment as well as warnings", func() {
   582  							Expect(executeErr).ToNot(HaveOccurred())
   583  							Expect(testUI.Out).To(Say("name:\\s+some-app"))
   584  							Expect(testUI.Out).To(Say("requested state:\\s+started"))
   585  							Expect(testUI.Out).To(Say("instances:\\s+1\\/3"))
   586  							Expect(testUI.Out).NotTo(Say("isolation segment:"))
   587  							Expect(testUI.Out).To(Say("usage:\\s+128M x 3 instances"))
   588  							Expect(testUI.Out).To(Say("routes:\\s+banana.fruit.com/hi, foobar.com:13"))
   589  							Expect(testUI.Out).To(Say("last uploaded:\\s+\\w{3} [0-3]\\d \\w{3} [0-2]\\d:[0-5]\\d:[0-5]\\d \\w+ \\d{4}"))
   590  							Expect(testUI.Out).To(Say("stack:\\s+potatos"))
   591  							Expect(testUI.Out).To(Say("buildpack:\\s+some-buildpack"))
   592  							Expect(testUI.Out).To(Say("start command:\\s+some start command"))
   593  
   594  							Expect(testUI.Err).To(Say("app-summary-warning"))
   595  						})
   596  
   597  						It("should display the instance table", func() {
   598  							Expect(executeErr).ToNot(HaveOccurred())
   599  							Expect(testUI.Out).To(Say("state\\s+since\\s+cpu\\s+memory\\s+disk"))
   600  							Expect(testUI.Out).To(Say(`#0\s+running\s+2014-06-19T01:18:37Z\s+73.0%\s+100M of 128M\s+50M of 2G\s+info from the backend`))
   601  						})
   602  					})
   603  				})
   604  			})
   605  		})
   606  
   607  		Context("when the app does *not* exists", func() {
   608  			BeforeEach(func() {
   609  				fakeActor.GetApplicationByNameAndSpaceReturns(
   610  					v2action.Application{},
   611  					v2action.Warnings{"warning-1", "warning-2"},
   612  					actionerror.ApplicationNotFoundError{Name: "some-app"},
   613  				)
   614  			})
   615  
   616  			It("returns back an error", func() {
   617  				Expect(executeErr).To(MatchError(translatableerror.ApplicationNotFoundError{Name: "some-app"}))
   618  
   619  				Expect(testUI.Err).To(Say("warning-1"))
   620  				Expect(testUI.Err).To(Say("warning-2"))
   621  			})
   622  		})
   623  	})
   624  })