github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/command/v2/app_command_test.go (about) 1 package v2_test 2 3 import ( 4 "errors" 5 "time" 6 7 "code.cloudfoundry.org/cli/actor/sharedaction" 8 "code.cloudfoundry.org/cli/actor/v2action" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2" 10 "code.cloudfoundry.org/cli/command" 11 "code.cloudfoundry.org/cli/command/commandfakes" 12 "code.cloudfoundry.org/cli/command/v2" 13 "code.cloudfoundry.org/cli/command/v2/v2fakes" 14 "code.cloudfoundry.org/cli/util/configv3" 15 "code.cloudfoundry.org/cli/util/ui" 16 "github.com/cloudfoundry/bytefmt" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 . "github.com/onsi/gomega/gbytes" 20 ) 21 22 var _ = Describe("App Command", func() { 23 var ( 24 cmd v2.AppCommand 25 testUI *ui.UI 26 fakeConfig *commandfakes.FakeConfig 27 fakeSharedActor *commandfakes.FakeSharedActor 28 fakeActor *v2fakes.FakeAppActor 29 binaryName string 30 executeErr error 31 ) 32 33 BeforeEach(func() { 34 testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) 35 fakeConfig = new(commandfakes.FakeConfig) 36 fakeSharedActor = new(commandfakes.FakeSharedActor) 37 fakeActor = new(v2fakes.FakeAppActor) 38 39 cmd = v2.AppCommand{ 40 UI: testUI, 41 Config: fakeConfig, 42 SharedActor: fakeSharedActor, 43 Actor: fakeActor, 44 } 45 46 cmd.RequiredArgs.AppName = "some-app" 47 48 binaryName = "faceman" 49 fakeConfig.BinaryNameReturns(binaryName) 50 51 // TODO: remove when experimental flag is removed 52 fakeConfig.ExperimentalReturns(true) 53 }) 54 55 JustBeforeEach(func() { 56 executeErr = cmd.Execute(nil) 57 }) 58 59 // TODO: remove when experimental flag is removed 60 It("Displays the experimental warning message", func() { 61 Expect(testUI.Out).To(Say(command.ExperimentalWarning)) 62 }) 63 64 Context("when checking target fails", func() { 65 BeforeEach(func() { 66 fakeSharedActor.CheckTargetReturns(sharedaction.NotLoggedInError{BinaryName: binaryName}) 67 }) 68 69 It("returns an error if the check fails", func() { 70 Expect(executeErr).To(MatchError(command.NotLoggedInError{BinaryName: "faceman"})) 71 72 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 73 _, checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) 74 Expect(checkTargetedOrg).To(BeTrue()) 75 Expect(checkTargetedSpace).To(BeTrue()) 76 }) 77 }) 78 79 Context("when the user is logged in, and org and space are targeted", func() { 80 BeforeEach(func() { 81 fakeConfig.HasTargetedOrganizationReturns(true) 82 fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: "some-org"}) 83 fakeConfig.HasTargetedSpaceReturns(true) 84 fakeConfig.TargetedSpaceReturns(configv3.Space{ 85 GUID: "some-space-guid", 86 Name: "some-space"}) 87 fakeConfig.CurrentUserReturns( 88 configv3.User{Name: "some-user"}, 89 nil) 90 }) 91 92 Context("when getting the current user returns an error", func() { 93 var expectedErr error 94 95 BeforeEach(func() { 96 expectedErr = errors.New("getting current user error") 97 fakeConfig.CurrentUserReturns( 98 configv3.User{}, 99 expectedErr) 100 }) 101 102 It("returns the error", func() { 103 Expect(executeErr).To(MatchError(expectedErr)) 104 }) 105 }) 106 107 It("displays flavor text", func() { 108 Expect(testUI.Out).To(Say("Showing health and status for app some-app in org some-org / space some-space as some-user...")) 109 }) 110 111 Context("when the --guid flag is provided", func() { 112 BeforeEach(func() { 113 cmd.GUID = true 114 }) 115 116 Context("when no errors occur", func() { 117 BeforeEach(func() { 118 fakeActor.GetApplicationByNameAndSpaceReturns( 119 v2action.Application{GUID: "some-guid"}, 120 v2action.Warnings{"warning-1", "warning-2"}, 121 nil) 122 }) 123 124 It("displays the application guid and all warnings", func() { 125 Expect(executeErr).ToNot(HaveOccurred()) 126 127 Expect(testUI.Out).To(Say("some-guid")) 128 Expect(testUI.Err).To(Say("warning-1")) 129 Expect(testUI.Err).To(Say("warning-2")) 130 }) 131 }) 132 133 Context("when an error is encountered getting the app", func() { 134 Context("when the error is translatable", func() { 135 BeforeEach(func() { 136 fakeActor.GetApplicationByNameAndSpaceReturns( 137 v2action.Application{}, 138 v2action.Warnings{"warning-1", "warning-2"}, 139 v2action.ApplicationNotFoundError{Name: "some-app"}) 140 }) 141 142 It("returns a translatable error and all warnings", func() { 143 Expect(executeErr).To(MatchError(command.ApplicationNotFoundError{Name: "some-app"})) 144 145 Expect(testUI.Err).To(Say("warning-1")) 146 Expect(testUI.Err).To(Say("warning-2")) 147 }) 148 }) 149 150 Context("when the error is not translatable", func() { 151 var expectedErr error 152 153 BeforeEach(func() { 154 expectedErr = errors.New("get app summary error") 155 fakeActor.GetApplicationByNameAndSpaceReturns( 156 v2action.Application{}, 157 v2action.Warnings{"warning-1", "warning-2"}, 158 expectedErr) 159 }) 160 161 It("returns the error and all warnings", func() { 162 Expect(executeErr).To(MatchError(expectedErr)) 163 164 Expect(testUI.Err).To(Say("warning-1")) 165 Expect(testUI.Err).To(Say("warning-2")) 166 }) 167 }) 168 }) 169 }) 170 171 Context("when the --guid flag is not provided", func() { 172 Context("when no errors occur", func() { 173 var ( 174 applicationSummary v2action.ApplicationSummary 175 warnings []string 176 ) 177 178 BeforeEach(func() { 179 applicationSummary = v2action.ApplicationSummary{ 180 Application: v2action.Application{ 181 Name: "some-app", 182 GUID: "some-app-guid", 183 Instances: 3, 184 Memory: 128, 185 PackageUpdatedAt: time.Unix(0, 0), 186 DetectedBuildpack: "some-buildpack", 187 State: "STARTED", 188 }, 189 Stack: v2action.Stack{ 190 Name: "potatos", 191 }, 192 Routes: []v2action.Route{ 193 { 194 Host: "banana", 195 Domain: "fruit.com", 196 Path: "/hi", 197 }, 198 { 199 Domain: "foobar.com", 200 Port: 13, 201 }, 202 }, 203 } 204 warnings = []string{"app-summary-warning"} 205 }) 206 207 Context("when the app does not have running instances", func() { 208 BeforeEach(func() { 209 applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{} 210 fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil) 211 }) 212 213 It("displays the app summary, 'no running instances' message, and all warnings", func() { 214 Expect(testUI.Out).To(Say("Showing health and status for app some-app in org some-org / space some-space as some-user...")) 215 Expect(testUI.Out).To(Say("")) 216 Expect(testUI.Out).To(Say("Name:\\s+some-app")) 217 Expect(testUI.Out).To(Say("Requested state:\\s+started")) 218 Expect(testUI.Out).To(Say("Instances:\\s+0\\/3")) 219 Expect(testUI.Out).To(Say("Usage:\\s+128M x 3 instances")) 220 Expect(testUI.Out).To(Say("Routes:\\s+banana.fruit.com/hi, foobar.com:13")) 221 Expect(testUI.Out).To(Say("Last uploaded:\\s+1970-01-01T00:00:00Z")) 222 Expect(testUI.Out).To(Say("Stack:\\s+potatos")) 223 Expect(testUI.Out).To(Say("Buildpack:\\s+some-buildpack")) 224 Expect(testUI.Out).To(Say("")) 225 Expect(testUI.Out).To(Say("There are no running instances of this app")) 226 227 Expect(testUI.Err).To(Say("app-summary-warning")) 228 }) 229 230 It("should not display the instance table", func() { 231 Expect(testUI.Out).NotTo(Say("State\\s+Since\\s+CPU\\s+Memory\\s+Disk")) 232 }) 233 }) 234 235 Context("when the app has running instances", func() { 236 BeforeEach(func() { 237 applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{ 238 { 239 ID: 0, 240 State: v2action.ApplicationInstanceState(ccv2.ApplicationInstanceRunning), 241 Since: 1403140717.984577, 242 CPU: 0.73, 243 Disk: 50 * bytefmt.MEGABYTE, 244 DiskQuota: 2048 * bytefmt.MEGABYTE, 245 Memory: 100 * bytefmt.MEGABYTE, 246 MemoryQuota: 128 * bytefmt.MEGABYTE, 247 Details: "info from the backend", 248 }, 249 { 250 ID: 1, 251 State: v2action.ApplicationInstanceState(ccv2.ApplicationInstanceCrashed), 252 Since: 1403100000.900000, 253 CPU: 0.37, 254 Disk: 50 * bytefmt.MEGABYTE, 255 DiskQuota: 2048 * bytefmt.MEGABYTE, 256 Memory: 100 * bytefmt.MEGABYTE, 257 MemoryQuota: 128 * bytefmt.MEGABYTE, 258 Details: "potato", 259 }, 260 } 261 fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil) 262 }) 263 264 It("displays app summary, instance table, and all warnings", func() { 265 Expect(testUI.Out).To(Say("Showing health and status for app some-app in org some-org / space some-space as some-user...")) 266 Expect(testUI.Out).To(Say("")) 267 Expect(testUI.Out).To(Say("Name:\\s+some-app")) 268 Expect(testUI.Out).To(Say("Requested state:\\s+started")) 269 Expect(testUI.Out).To(Say("Instances:\\s+2\\/3")) 270 Expect(testUI.Out).To(Say("Usage:\\s+128M x 3 instances")) 271 Expect(testUI.Out).To(Say("Routes:\\s+banana.fruit.com/hi, foobar.com:13")) 272 Expect(testUI.Out).To(Say("Last uploaded:\\s+1970-01-01T00:00:00Z")) 273 Expect(testUI.Out).To(Say("Stack:\\s+potatos")) 274 Expect(testUI.Out).To(Say("Buildpack:\\s+some-buildpack")) 275 Expect(testUI.Out).To(Say("")) 276 Expect(testUI.Out).To(Say("State\\s+Since\\s+CPU\\s+Memory\\s+Disk\\s+Details")) 277 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`)) 278 Expect(testUI.Out).To(Say(`#1\s+crashed\s+2014-06-18T14:00:00Z\s+37.0%\s+100M of 128M\s+50M of 2G\s+potato`)) 279 280 Expect(testUI.Err).To(Say("app-summary-warning")) 281 282 Expect(fakeActor.GetApplicationSummaryByNameAndSpaceCallCount()).To(Equal(1)) 283 appName, spaceGUID := fakeActor.GetApplicationSummaryByNameAndSpaceArgsForCall(0) 284 Expect(appName).To(Equal("some-app")) 285 Expect(spaceGUID).To(Equal("some-space-guid")) 286 }) 287 }) 288 }) 289 290 Context("when an error is encountered getting app summary", func() { 291 Context("when the error is not translatable", func() { 292 var expectedErr error 293 294 BeforeEach(func() { 295 expectedErr = errors.New("get app summary error") 296 fakeActor.GetApplicationSummaryByNameAndSpaceReturns( 297 v2action.ApplicationSummary{}, 298 nil, 299 expectedErr) 300 }) 301 302 It("returns the error", func() { 303 Expect(executeErr).To(MatchError(expectedErr)) 304 }) 305 }) 306 307 Context("when the error is translatable", func() { 308 BeforeEach(func() { 309 fakeActor.GetApplicationSummaryByNameAndSpaceReturns( 310 v2action.ApplicationSummary{}, 311 nil, 312 v2action.ApplicationNotFoundError{Name: "some-app"}) 313 }) 314 315 It("returns a translatable error", func() { 316 Expect(executeErr).To(MatchError(command.ApplicationNotFoundError{Name: "some-app"})) 317 }) 318 }) 319 }) 320 }) 321 }) 322 })