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