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