github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/cf/commands/service/unbind_route_service_test.go (about) 1 package service_test 2 3 import ( 4 "net/http" 5 6 "code.cloudfoundry.org/cli/cf/commandregistry" 7 "code.cloudfoundry.org/cli/cf/commands/service" 8 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 9 "code.cloudfoundry.org/cli/cf/errors" 10 "code.cloudfoundry.org/cli/cf/flags" 11 "code.cloudfoundry.org/cli/cf/models" 12 "code.cloudfoundry.org/cli/cf/requirements" 13 "code.cloudfoundry.org/cli/cf/requirements/requirementsfakes" 14 "github.com/blang/semver" 15 16 "code.cloudfoundry.org/cli/cf/api/apifakes" 17 testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration" 18 testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal" 19 20 . "code.cloudfoundry.org/cli/util/testhelpers/matchers" 21 . "github.com/onsi/ginkgo" 22 . "github.com/onsi/gomega" 23 ) 24 25 var _ = Describe("UnbindRouteService", func() { 26 var ( 27 ui *testterm.FakeUI 28 configRepo coreconfig.Repository 29 routeRepo *apifakes.FakeRouteRepository 30 routeServiceBindingRepo *apifakes.FakeRouteServiceBindingRepository 31 32 cmd commandregistry.Command 33 deps commandregistry.Dependency 34 factory *requirementsfakes.FakeFactory 35 flagContext flags.FlagContext 36 37 fakeDomain models.DomainFields 38 39 loginRequirement requirements.Requirement 40 minAPIVersionRequirement requirements.Requirement 41 domainRequirement *requirementsfakes.FakeDomainRequirement 42 serviceInstanceRequirement *requirementsfakes.FakeServiceInstanceRequirement 43 ) 44 45 BeforeEach(func() { 46 ui = &testterm.FakeUI{} 47 48 configRepo = testconfig.NewRepositoryWithDefaults() 49 routeRepo = new(apifakes.FakeRouteRepository) 50 repoLocator := deps.RepoLocator.SetRouteRepository(routeRepo) 51 52 routeServiceBindingRepo = new(apifakes.FakeRouteServiceBindingRepository) 53 repoLocator = repoLocator.SetRouteServiceBindingRepository(routeServiceBindingRepo) 54 55 deps = commandregistry.Dependency{ 56 UI: ui, 57 Config: configRepo, 58 RepoLocator: repoLocator, 59 } 60 61 cmd = &service.UnbindRouteService{} 62 cmd.SetDependency(deps, false) 63 64 flagContext = flags.NewFlagContext(cmd.MetaData().Flags) 65 66 factory = new(requirementsfakes.FakeFactory) 67 68 loginRequirement = &passingRequirement{Name: "login-requirement"} 69 factory.NewLoginRequirementReturns(loginRequirement) 70 71 domainRequirement = new(requirementsfakes.FakeDomainRequirement) 72 factory.NewDomainRequirementReturns(domainRequirement) 73 74 fakeDomain = models.DomainFields{ 75 GUID: "fake-domain-guid", 76 Name: "fake-domain-name", 77 } 78 domainRequirement.GetDomainReturns(fakeDomain) 79 80 serviceInstanceRequirement = new(requirementsfakes.FakeServiceInstanceRequirement) 81 factory.NewServiceInstanceRequirementReturns(serviceInstanceRequirement) 82 83 minAPIVersionRequirement = &passingRequirement{Name: "min-api-version-requirement"} 84 factory.NewMinAPIVersionRequirementReturns(minAPIVersionRequirement) 85 }) 86 87 Describe("Requirements", func() { 88 Context("when not provided exactly two args", func() { 89 BeforeEach(func() { 90 flagContext.Parse("domain-name") 91 }) 92 93 It("fails with usage", func() { 94 _, err := cmd.Requirements(factory, flagContext) 95 Expect(err).To(HaveOccurred()) 96 Expect(ui.Outputs()).To(ContainSubstrings( 97 []string{"FAILED"}, 98 []string{"Incorrect Usage. Requires DOMAIN and SERVICE_INSTANCE as arguments"}, 99 )) 100 }) 101 }) 102 103 Context("when provided exactly two args", func() { 104 BeforeEach(func() { 105 flagContext.Parse("domain-name", "service-instance") 106 }) 107 108 It("returns a LoginRequirement", func() { 109 actualRequirements, err := cmd.Requirements(factory, flagContext) 110 Expect(err).NotTo(HaveOccurred()) 111 Expect(factory.NewLoginRequirementCallCount()).To(Equal(1)) 112 Expect(actualRequirements).To(ContainElement(loginRequirement)) 113 }) 114 115 It("returns a DomainRequirement", func() { 116 actualRequirements, err := cmd.Requirements(factory, flagContext) 117 Expect(err).NotTo(HaveOccurred()) 118 Expect(factory.NewLoginRequirementCallCount()).To(Equal(1)) 119 Expect(actualRequirements).To(ContainElement(loginRequirement)) 120 }) 121 122 It("returns a ServiceInstanceRequirement", func() { 123 actualRequirements, err := cmd.Requirements(factory, flagContext) 124 Expect(err).NotTo(HaveOccurred()) 125 Expect(factory.NewServiceInstanceRequirementCallCount()).To(Equal(1)) 126 Expect(actualRequirements).To(ContainElement(serviceInstanceRequirement)) 127 }) 128 129 It("returns a MinAPIVersionRequirement", func() { 130 actualRequirements, err := cmd.Requirements(factory, flagContext) 131 Expect(err).NotTo(HaveOccurred()) 132 Expect(factory.NewMinAPIVersionRequirementCallCount()).To(Equal(1)) 133 Expect(actualRequirements).To(ContainElement(minAPIVersionRequirement)) 134 135 feature, requiredVersion := factory.NewMinAPIVersionRequirementArgsForCall(0) 136 Expect(feature).To(Equal("unbind-route-service")) 137 expectedRequiredVersion, err := semver.Make("2.51.0") 138 Expect(err).NotTo(HaveOccurred()) 139 Expect(requiredVersion).To(Equal(expectedRequiredVersion)) 140 }) 141 }) 142 }) 143 144 Describe("Execute", func() { 145 var runCLIErr error 146 147 BeforeEach(func() { 148 err := flagContext.Parse("domain-name", "service-instance") 149 Expect(err).NotTo(HaveOccurred()) 150 cmd.Requirements(factory, flagContext) 151 ui.Inputs = []string{"n"} 152 }) 153 154 JustBeforeEach(func() { 155 runCLIErr = cmd.Execute(flagContext) 156 }) 157 158 It("tries to find the route", func() { 159 Expect(runCLIErr).NotTo(HaveOccurred()) 160 Expect(routeRepo.FindCallCount()).To(Equal(1)) 161 host, domain, path, port := routeRepo.FindArgsForCall(0) 162 Expect(host).To(Equal("")) 163 Expect(domain).To(Equal(fakeDomain)) 164 Expect(path).To(Equal("")) 165 Expect(port).To(Equal(0)) 166 }) 167 168 Context("when given a hostname", func() { 169 BeforeEach(func() { 170 flagContext = flags.NewFlagContext(cmd.MetaData().Flags) 171 err := flagContext.Parse("domain-name", "service-instance", "-n", "the-hostname") 172 Expect(err).NotTo(HaveOccurred()) 173 ui.Inputs = []string{"n"} 174 }) 175 176 It("tries to find the route with the given hostname", func() { 177 Expect(runCLIErr).NotTo(HaveOccurred()) 178 Expect(routeRepo.FindCallCount()).To(Equal(1)) 179 host, _, _, _ := routeRepo.FindArgsForCall(0) 180 Expect(host).To(Equal("the-hostname")) 181 }) 182 }) 183 184 Context("when given a path", func() { 185 BeforeEach(func() { 186 flagContext = flags.NewFlagContext(cmd.MetaData().Flags) 187 err := flagContext.Parse("domain-name", "service-instance", "--path", "/path") 188 Expect(err).NotTo(HaveOccurred()) 189 ui.Inputs = []string{"n"} 190 }) 191 192 It("should attempt to find the route", func() { 193 Expect(runCLIErr).NotTo(HaveOccurred()) 194 Expect(routeRepo.FindCallCount()).To(Equal(1)) 195 _, _, path, _ := routeRepo.FindArgsForCall(0) 196 Expect(path).To(Equal("/path")) 197 }) 198 199 Context("when the path does not contain a leading slash", func() { 200 BeforeEach(func() { 201 flagContext = flags.NewFlagContext(cmd.MetaData().Flags) 202 err := flagContext.Parse("domain-name", "service-instance", "--path", "path") 203 Expect(err).NotTo(HaveOccurred()) 204 ui.Inputs = []string{"n"} 205 }) 206 207 It("should prefix the path with a leading slash and attempt to find the route", func() { 208 Expect(runCLIErr).NotTo(HaveOccurred()) 209 Expect(routeRepo.FindCallCount()).To(Equal(1)) 210 _, _, path, _ := routeRepo.FindArgsForCall(0) 211 Expect(path).To(Equal("/path")) 212 }) 213 }) 214 }) 215 216 Context("when given hostname and path", func() { 217 BeforeEach(func() { 218 flagContext = flags.NewFlagContext(cmd.MetaData().Flags) 219 err := flagContext.Parse("domain-name", "service-instance", "--hostname", "the-hostname", "--path", "path") 220 Expect(err).NotTo(HaveOccurred()) 221 ui.Inputs = []string{"n"} 222 }) 223 224 It("should attempt to find the route", func() { 225 Expect(runCLIErr).NotTo(HaveOccurred()) 226 Expect(routeRepo.FindCallCount()).To(Equal(1)) 227 hostname, _, path, _ := routeRepo.FindArgsForCall(0) 228 Expect(hostname).To(Equal("the-hostname")) 229 Expect(path).To(Equal("/path")) 230 }) 231 }) 232 233 Context("when the route can be found", func() { 234 BeforeEach(func() { 235 routeRepo.FindReturns(models.Route{GUID: "route-guid"}, nil) 236 ui.Inputs = []string{"n"} 237 }) 238 239 It("asks the user to confirm", func() { 240 Expect(runCLIErr).NotTo(HaveOccurred()) 241 Expect(ui.Prompts).To(ContainSubstrings( 242 []string{"Unbinding may leave apps mapped to route", "Do you want to proceed?"}, 243 )) 244 }) 245 246 Context("when the user confirms", func() { 247 BeforeEach(func() { 248 ui.Inputs = []string{"y"} 249 }) 250 251 It("does not warn", func() { 252 Expect(runCLIErr).NotTo(HaveOccurred()) 253 Expect(func() []string { 254 return ui.Outputs() 255 }).NotTo(ContainSubstrings( 256 []string{"Unbind cancelled"}, 257 )) 258 }) 259 260 It("tells the user it is unbinding the route service", func() { 261 Expect(runCLIErr).NotTo(HaveOccurred()) 262 Expect(ui.Outputs()).To(ContainSubstrings( 263 []string{"Unbinding route", "from service instance"}, 264 )) 265 }) 266 267 It("tries to unbind the route service", func() { 268 Expect(runCLIErr).NotTo(HaveOccurred()) 269 Expect(routeServiceBindingRepo.UnbindCallCount()).To(Equal(1)) 270 }) 271 272 Context("when unbinding the route service succeeds", func() { 273 BeforeEach(func() { 274 routeServiceBindingRepo.UnbindReturns(nil) 275 }) 276 277 It("says OK", func() { 278 Expect(runCLIErr).NotTo(HaveOccurred()) 279 Expect(ui.Outputs()).To(ContainSubstrings( 280 []string{"OK"}, 281 )) 282 }) 283 }) 284 285 Context("when unbinding the route service fails because it was not bound", func() { 286 BeforeEach(func() { 287 routeServiceBindingRepo.UnbindReturns(errors.NewHTTPError(http.StatusOK, errors.InvalidRelation, "http-err")) 288 }) 289 290 It("says OK", func() { 291 Expect(runCLIErr).NotTo(HaveOccurred()) 292 Expect(ui.Outputs()).To(ContainSubstrings( 293 []string{"OK"}, 294 )) 295 }) 296 297 It("warns", func() { 298 Expect(runCLIErr).NotTo(HaveOccurred()) 299 Expect(ui.Outputs()).To(ContainSubstrings( 300 []string{"Route", "was not bound to service instance"}, 301 )) 302 }) 303 }) 304 305 Context("when unbinding the route service fails for any other reason", func() { 306 BeforeEach(func() { 307 routeServiceBindingRepo.UnbindReturns(errors.New("unbind-err")) 308 }) 309 310 It("fails with the error", func() { 311 Expect(runCLIErr).To(HaveOccurred()) 312 Expect(runCLIErr.Error()).To(Equal("unbind-err")) 313 }) 314 }) 315 }) 316 317 Context("when the user does not confirm", func() { 318 BeforeEach(func() { 319 ui.Inputs = []string{"n"} 320 }) 321 322 It("warns", func() { 323 Expect(runCLIErr).NotTo(HaveOccurred()) 324 Expect(ui.Outputs()).To(ContainSubstrings( 325 []string{"Unbind cancelled"}, 326 )) 327 }) 328 329 It("does not bind the route service", func() { 330 Expect(runCLIErr).NotTo(HaveOccurred()) 331 Expect(routeServiceBindingRepo.UnbindCallCount()).To(Equal(0)) 332 }) 333 }) 334 335 Context("when the -f flag has been passed", func() { 336 BeforeEach(func() { 337 flagContext = flags.NewFlagContext(cmd.MetaData().Flags) 338 flagContext.Parse("domain-name", "-f") 339 }) 340 341 It("does not ask the user to confirm", func() { 342 Expect(runCLIErr).NotTo(HaveOccurred()) 343 Expect(ui.Prompts).NotTo(ContainSubstrings( 344 []string{"Unbinding may leave apps mapped to route", "Do you want to proceed?"}, 345 )) 346 }) 347 }) 348 }) 349 350 Context("when finding the route results in an error", func() { 351 BeforeEach(func() { 352 routeRepo.FindReturns(models.Route{GUID: "route-guid"}, errors.New("find-err")) 353 }) 354 355 It("fails with error", func() { 356 Expect(runCLIErr).To(HaveOccurred()) 357 Expect(runCLIErr.Error()).To(Equal("find-err")) 358 }) 359 }) 360 }) 361 })