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