Expect(outputBuffer).To(test_helpers.SayLine("Error submitting build of droplet-name: failed"))
				Expect(fakeDropletRunner.UploadBitsCallCount()).To(Equal(1))
				Expect(fakeDropletRunner.BuildDropletCallCount()).To(Equal(1))
				Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.CommandFailed}))
			})
		})

		Describe("waiting for the build to finish", func() {
			It("polls for the build to complete, outputting logs while the build runs", func() {
				fakeTaskExaminer.TaskStatusReturns(task_examiner.TaskInfo{State: "PENDING"}, nil)

				args := []string{
					"droplet-name",
					"http://some.url/for/buildpack",
				}
				doneChan := test_helpers.AsyncExecuteCommandWithArgs(buildDropletCommand, args)

				Eventually(outputBuffer).Should(test_helpers.SayLine("Submitted build of droplet-name"))

				Eventually(fakeTailedLogsOutputter.OutputTailedLogsCallCount).Should(Equal(1))
				Expect(fakeTailedLogsOutputter.OutputTailedLogsArgsForCall(0)).To(Equal("build-droplet-droplet-name"))

				Eventually(fakeTaskExaminer.TaskStatusCallCount).Should(Equal(1))
				Expect(fakeTaskExaminer.TaskStatusArgsForCall(0)).To(Equal("build-droplet-droplet-name"))

				fakeClock.IncrementBySeconds(1)
				Expect(doneChan).NotTo(BeClosed())
				Expect(fakeTailedLogsOutputter.StopOutputtingCallCount()).To(Equal(0))

				fakeTaskExaminer.TaskStatusReturns(task_examiner.TaskInfo{State: "RUNNING"}, nil)
			})
		})

		Describe("polling for the app to start after desiring the app", func() {
			It("polls for the app to start with correct number of instances, outputting logs while the app starts", func() {
				fakeDockerMetadataFetcher.FetchMetadataReturns(&docker_metadata_fetcher.ImageMetadata{}, nil)
				fakeAppExaminer.RunningAppInstancesInfoReturns(0, false, nil)

				args := []string{
					"--instances=10",
					"cool-web-app",
					"superfun/app",
					"--",
					"/start-me-please",
				}
				doneChan := test_helpers.AsyncExecuteCommandWithArgs(createCommand, args)

				Eventually(outputBuffer).Should(test_helpers.SayLine("Creating App: cool-web-app"))

				Expect(fakeTailedLogsOutputter.OutputTailedLogsCallCount()).To(Equal(1))
				Expect(fakeTailedLogsOutputter.OutputTailedLogsArgsForCall(0)).To(Equal("cool-web-app"))

				Expect(fakeAppExaminer.RunningAppInstancesInfoCallCount()).To(Equal(1))
				Expect(fakeAppExaminer.RunningAppInstancesInfoArgsForCall(0)).To(Equal("cool-web-app"))

				fakeClock.IncrementBySeconds(1)
				Expect(fakeTailedLogsOutputter.StopOutputtingCallCount()).To(Equal(0))

				fakeAppExaminer.RunningAppInstancesInfoReturns(9, false, nil)
				fakeClock.IncrementBySeconds(1)
				Expect(doneChan).ShouldNot(BeClosed())
		It("should ssh to instance index specified", func() {
			test_helpers.ExecuteCommandWithArgs(sshCommand, []string{"--instance", "2", "app-name"})

			Expect(outputBuffer).To(test_helpers.SayLine("Connecting to app-name/2 at %s", config.Target()))

			Expect(fakeSecureShell.ConnectToShellCallCount()).To(Equal(1))
			appName, instanceIndex, command, actualConfig := fakeSecureShell.ConnectToShellArgsForCall(0)
			Expect(appName).To(Equal("app-name"))
			Expect(instanceIndex).To(Equal(2))
			Expect(command).To(BeEmpty())
			Expect(actualConfig).To(Equal(config))
		})

		It("should run a command remotely instead of the login shell", func() {
			doneChan := test_helpers.AsyncExecuteCommandWithArgs(sshCommand, []string{"app-name", "echo", "1", "2", "3"})

			Eventually(doneChan).Should(BeClosed())
			Expect(outputBuffer).NotTo(test_helpers.Say("Connecting to app-name"))

			Expect(fakeSecureShell.ConnectToShellCallCount()).To(Equal(1))
			appName, instanceIndex, command, actualConfig := fakeSecureShell.ConnectToShellArgsForCall(0)
			Expect(appName).To(Equal("app-name"))
			Expect(instanceIndex).To(Equal(0))
			Expect(command).To(Equal("echo 1 2 3"))
			Expect(actualConfig).To(Equal(config))
		})

		It("should support -- delimiter for args", func() {
			doneChan := test_helpers.AsyncExecuteCommandWithArgs(sshCommand, []string{"app-name", "--", "/bin/ls", "-l"})
			It("alerts the user if no target is set", func() {
				config.SetBlobTarget("", 0, "", "", "")
				config.Save()

				test_helpers.ExecuteCommandWithArgs(targetBlobCommand, []string{})

				Expect(outputBuffer).To(test_helpers.SayLine("Blob target not set"))
			})
		})

		Context("setting the blob target", func() {
			It("sets the blob target and credentials", func() {
				fakeTargetVerifier.VerifyBlobTargetReturns(true, nil)

				commandFinishChan := test_helpers.AsyncExecuteCommandWithArgs(targetBlobCommand, []string{"192.168.11.11:8980"})

				Eventually(outputBuffer).Should(test_helpers.Say("Access Key: "))
				stdinWriter.Write([]byte("yaykey\n"))
				Eventually(outputBuffer).Should(test_helpers.Say("Secret Key: "))
				stdinWriter.Write([]byte("superserial\n"))
				Eventually(outputBuffer).Should(test_helpers.Say("Bucket Name [condenser-bucket]: "))
				stdinWriter.Write([]byte("bhuket\n"))

				Eventually(commandFinishChan).Should(BeClosed())

				Expect(fakeTargetVerifier.VerifyBlobTargetCallCount()).To(Equal(1))
				host, port, accessKey, secretKey, bucketName := fakeTargetVerifier.VerifyBlobTargetArgsForCall(0)
				Expect(host).To(Equal("192.168.11.11"))
				Expect(port).To(Equal(uint16(8980)))
				Expect(accessKey).To(Equal("yaykey"))
	)

	BeforeEach(func() {
		commandRan = false

		cliCommand = cli.Command{
			Name: "exec",
			Action: func(*cli.Context) {
				commandRan = true
			},
		}
	})

	Describe("ExecuteCommandWithArgs", func() {
		It("executes the command", func() {
			test_helpers.ExecuteCommandWithArgs(cliCommand, []string{})

			Expect(commandRan).To(BeTrue())
		})
	})

	Describe("AsyncExecuteCommandWithArgs", func() {
		It("executes the command", func() {
			doneChan := test_helpers.AsyncExecuteCommandWithArgs(cliCommand, []string{})

			Eventually(doneChan, 3).Should(BeClosed())
			Expect(commandRan).To(BeTrue())
		})
	})
})
					Eventually(outputBuffer).Should(test_helpers.SayLine("some error"))
					verifyOldTargetStillSet()
					Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.FileSystemError}))
				})
			})
		})

		Context("when the receptor requires authentication", func() {
			BeforeEach(func() {
				fakeTargetVerifier.VerifyTargetReturns(true, false, nil)
				fakeBlobStoreVerifier.VerifyReturns(true, nil)
				fakePasswordReader.PromptForPasswordReturns("testpassword")
			})

			It("prompts for credentials and stores them in the config", func() {
				doneChan := test_helpers.AsyncExecuteCommandWithArgs(targetCommand, []string{"myapi.com"})

				Eventually(outputBuffer).Should(test_helpers.Say("Username: "******"testusername\n"))

				Eventually(doneChan, 3).Should(BeClosed())

				Expect(config.Target()).To(Equal("myapi.com"))
				Expect(config.Receptor()).To(Equal("http://*****:*****@receptor.myapi.com"))
				Expect(outputBuffer).To(test_helpers.SayLine("API location set."))

				Expect(fakePasswordReader.PromptForPasswordCallCount()).To(Equal(1))
				Expect(fakePasswordReader.PromptForPasswordArgsForCall(0)).To(Equal("Password"))

				Expect(fakeTargetVerifier.VerifyTargetCallCount()).To(Equal(2))
				Expect(fakeDropletRunner.UploadBitsCallCount()).To(Equal(1))
				Expect(fakeDropletRunner.BuildDropletCallCount()).To(Equal(1))
				Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.CommandFailed}))
			})
		})

		Describe("waiting for the build to finish", func() {
			It("polls for the build to complete, outputting logs while the build runs", func() {
				args := []string{
					"droplet-name",
					"http://some.url/for/buildpack",
				}

				fakeTaskExaminer.TaskStatusReturns(task_examiner.TaskInfo{State: "PENDING"}, nil)

				commandFinishChan := test_helpers.AsyncExecuteCommandWithArgs(buildDropletCommand, args)

				Eventually(outputBuffer).Should(test_helpers.Say("Submitted build of droplet-name"))

				Expect(fakeTailedLogsOutputter.OutputTailedLogsCallCount()).To(Equal(1))
				Expect(fakeTailedLogsOutputter.OutputTailedLogsArgsForCall(0)).To(Equal("build-droplet-droplet-name"))

				Expect(fakeTaskExaminer.TaskStatusCallCount()).To(Equal(1))
				Expect(fakeTaskExaminer.TaskStatusArgsForCall(0)).To(Equal("build-droplet-droplet-name"))

				fakeClock.IncrementBySeconds(1)
				Expect(commandFinishChan).ShouldNot(BeClosed())
				Expect(fakeTailedLogsOutputter.StopOutputtingCallCount()).To(Equal(0))

				fakeTaskExaminer.TaskStatusReturns(task_examiner.TaskInfo{State: "RUNNING"}, nil)
		Context("when a rate flag is provided", func() {
			var closeChan chan struct{}

			AfterEach(func() {
				go fakeExitHandler.Exit(exit_codes.SigInt)
				Eventually(closeChan).Should(BeClosed())
			})

			It("dynamically displays the visualization", func() {
				setNumberOfRunningInstances := func(count int) {
					fakeAppExaminer.ListCellsReturns([]app_examiner.CellInfo{app_examiner.CellInfo{CellID: "cell-0", RunningInstances: count}, app_examiner.CellInfo{CellID: "cell-1", RunningInstances: count, Missing: true}}, nil)
				}
				setNumberOfRunningInstances(0)

				closeChan = test_helpers.AsyncExecuteCommandWithArgs(visualizeCommand, []string{"--rate", "2s"})

				Eventually(outputBuffer).Should(test_helpers.SayLine("cell-0: " + colors.Red("empty") + cursor.ClearToEndOfLine()))
				Eventually(outputBuffer).Should(test_helpers.SayLine("cell-1" + colors.Red("[MISSING]") + ": " + cursor.ClearToEndOfLine()))

				setNumberOfRunningInstances(2)

				fakeClock.IncrementBySeconds(1)

				Consistently(outputBuffer).ShouldNot(test_helpers.Say("cell: \n")) // TODO: how would this happen

				fakeClock.IncrementBySeconds(1)

				Eventually(outputBuffer).Should(test_helpers.Say(cursor.Hide()))
				Eventually(outputBuffer).Should(test_helpers.Say(cursor.Up(2)))
				Eventually(outputBuffer).Should(test_helpers.SayLine("cell-0: " + colors.Green("••") + cursor.ClearToEndOfLine()))
			It("alerts the user if no target is set", func() {
				config.SetTarget("")
				test_helpers.ExecuteCommandWithArgs(targetCommand, []string{})

				Expect(outputBuffer).To(test_helpers.Say("Target not set."))
			})
		})

		Context("setting target without auth", func() {
			BeforeEach(func() {
				fakeTargetVerifier.VerifyTargetReturns(true, true, nil)
			})

			It("saves the new target", func() {
				commandFinishChan := test_helpers.AsyncExecuteCommandWithArgs(targetCommand, []string{"myapi.com"})

				Eventually(commandFinishChan).Should(BeClosed())

				Expect(fakeTargetVerifier.VerifyTargetCallCount()).To(Equal(1))
				Expect(fakeTargetVerifier.VerifyTargetArgsForCall(0)).To(Equal("http://receptor.myapi.com"))

				Expect(config.Receptor()).To(Equal("http://receptor.myapi.com"))
			})

			It("clears out existing saved target credentials", func() {
				test_helpers.ExecuteCommandWithArgs(targetCommand, []string{"myapi.com"})

				Expect(fakeTargetVerifier.VerifyTargetCallCount()).To(Equal(1))
				Expect(fakeTargetVerifier.VerifyTargetArgsForCall(0)).To(Equal("http://receptor.myapi.com"))
			})
		signalChan = make(chan os.Signal)
		fakeExitHandler = &fake_exit_handler.FakeExitHandler{}
	})

	Describe("LogsCommand", func() {
		var logsCommand cli.Command

		BeforeEach(func() {
			commandFactory := command_factory.NewLogsCommandFactory(appExaminer, taskExaminer, terminalUI, fakeTailedLogsOutputter, fakeExitHandler)
			logsCommand = commandFactory.MakeLogsCommand()
		})

		It("tails logs", func() {
			appExaminer.AppExistsReturns(true, nil)

			doneChan := test_helpers.AsyncExecuteCommandWithArgs(logsCommand, []string{"my-app-guid"})

			Eventually(fakeTailedLogsOutputter.OutputTailedLogsCallCount).Should(Equal(1))
			Expect(fakeTailedLogsOutputter.OutputTailedLogsArgsForCall(0)).To(Equal("my-app-guid"))

			Consistently(doneChan).ShouldNot(BeClosed())
		})

		It("handles invalid appguids", func() {
			test_helpers.ExecuteCommandWithArgs(logsCommand, []string{})

			Expect(outputBuffer).To(test_helpers.SayIncorrectUsage())
			Expect(fakeExitHandler.ExitCalledWith).To(Equal([]int{exit_codes.InvalidSyntax}))
		})

		It("handles non existent application", func() {
			Expect(fakeAppRunner.ScaleAppCallCount()).To(Equal(1))
			name, instances := fakeAppRunner.ScaleAppArgsForCall(0)
			Expect(name).To(Equal("cool-web-app"))
			Expect(instances).To(Equal(22))
		})

		It("polls until the required number of instances are running", func() {
			args := []string{
				"cool-web-app",
				"22",
			}

			fakeAppExaminer.RunningAppInstancesInfoReturns(1, false, nil)

			commandFinishChan := test_helpers.AsyncExecuteCommandWithArgs(scaleCommand, args)

			Eventually(outputBuffer).Should(test_helpers.Say("Scaling cool-web-app to 22 instances"))

			Expect(fakeAppExaminer.RunningAppInstancesInfoCallCount()).To(Equal(1))
			Expect(fakeAppExaminer.RunningAppInstancesInfoArgsForCall(0)).To(Equal("cool-web-app"))

			fakeClock.IncrementBySeconds(1)
			Eventually(outputBuffer).Should(test_helpers.Say("."))
			fakeClock.IncrementBySeconds(1)
			Eventually(outputBuffer).Should(test_helpers.Say("."))

			fakeAppExaminer.RunningAppInstancesInfoReturns(22, false, nil)
			fakeClock.IncrementBySeconds(1)

			Eventually(commandFinishChan).Should(BeClosed())