github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/cf/commands/route/unmap_route_test.go (about)

     1  package route_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	"code.cloudfoundry.org/cli/cf/commandregistry"
     7  	"code.cloudfoundry.org/cli/cf/commands/route"
     8  	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
     9  	"code.cloudfoundry.org/cli/cf/flags"
    10  	"code.cloudfoundry.org/cli/cf/models"
    11  	"code.cloudfoundry.org/cli/cf/requirements"
    12  	"code.cloudfoundry.org/cli/cf/requirements/requirementsfakes"
    13  	"github.com/blang/semver"
    14  
    15  	"code.cloudfoundry.org/cli/cf/api/apifakes"
    16  
    17  	testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration"
    18  	testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal"
    19  
    20  	"strings"
    21  
    22  	. "code.cloudfoundry.org/cli/util/testhelpers/matchers"
    23  	. "github.com/onsi/ginkgo"
    24  	. "github.com/onsi/gomega"
    25  )
    26  
    27  var _ = Describe("UnmapRoute", func() {
    28  	var (
    29  		ui         *testterm.FakeUI
    30  		configRepo coreconfig.Repository
    31  		routeRepo  *apifakes.FakeRouteRepository
    32  
    33  		cmd         commandregistry.Command
    34  		deps        commandregistry.Dependency
    35  		factory     *requirementsfakes.FakeFactory
    36  		flagContext flags.FlagContext
    37  
    38  		loginRequirement         requirements.Requirement
    39  		applicationRequirement   *requirementsfakes.FakeApplicationRequirement
    40  		domainRequirement        *requirementsfakes.FakeDomainRequirement
    41  		minAPIVersionRequirement requirements.Requirement
    42  
    43  		fakeDomain models.DomainFields
    44  	)
    45  
    46  	BeforeEach(func() {
    47  		ui = &testterm.FakeUI{}
    48  		configRepo = testconfig.NewRepositoryWithDefaults()
    49  		routeRepo = new(apifakes.FakeRouteRepository)
    50  		repoLocator := deps.RepoLocator.SetRouteRepository(routeRepo)
    51  
    52  		deps = commandregistry.Dependency{
    53  			UI:          ui,
    54  			Config:      configRepo,
    55  			RepoLocator: repoLocator,
    56  		}
    57  
    58  		cmd = &route.UnmapRoute{}
    59  		cmd.SetDependency(deps, false)
    60  
    61  		flagContext = flags.NewFlagContext(cmd.MetaData().Flags)
    62  
    63  		factory = new(requirementsfakes.FakeFactory)
    64  
    65  		loginRequirement = &passingRequirement{Name: "login-requirement"}
    66  		factory.NewLoginRequirementReturns(loginRequirement)
    67  
    68  		applicationRequirement = new(requirementsfakes.FakeApplicationRequirement)
    69  		factory.NewApplicationRequirementReturns(applicationRequirement)
    70  
    71  		fakeApplication := models.Application{}
    72  		fakeApplication.GUID = "fake-app-guid"
    73  		applicationRequirement.GetApplicationReturns(fakeApplication)
    74  
    75  		domainRequirement = new(requirementsfakes.FakeDomainRequirement)
    76  		factory.NewDomainRequirementReturns(domainRequirement)
    77  
    78  		fakeDomain = models.DomainFields{
    79  			GUID: "fake-domain-guid",
    80  			Name: "fake-domain-name",
    81  		}
    82  		domainRequirement.GetDomainReturns(fakeDomain)
    83  
    84  		minAPIVersionRequirement = &passingRequirement{Name: "min-api-version-requirement"}
    85  		factory.NewMinAPIVersionRequirementReturns(minAPIVersionRequirement)
    86  	})
    87  
    88  	Describe("Help text", func() {
    89  		var usage []string
    90  
    91  		BeforeEach(func() {
    92  			cmd := &route.UnmapRoute{}
    93  			up := commandregistry.CLICommandUsagePresenter(cmd)
    94  
    95  			usage = strings.Split(up.Usage(), "\n")
    96  		})
    97  
    98  		It("contains an example", func() {
    99  			Expect(usage).To(ContainElement("   cf unmap-route my-app example.com --port 5000                  # example.com:5000"))
   100  		})
   101  
   102  		It("contains the options", func() {
   103  			Expect(usage).To(ContainElement("   --hostname, -n      Hostname used to identify the HTTP route"))
   104  			Expect(usage).To(ContainElement("   --path              Path used to identify the HTTP route"))
   105  			Expect(usage).To(ContainElement("   --port              Port used to identify the TCP route"))
   106  		})
   107  
   108  		It("shows the usage", func() {
   109  			Expect(usage).To(ContainElement("   Unmap an HTTP route:"))
   110  			Expect(usage).To(ContainElement("      cf unmap-route APP_NAME DOMAIN [--hostname HOSTNAME] [--path PATH]"))
   111  
   112  			Expect(usage).To(ContainElement("   Unmap a TCP route:"))
   113  			Expect(usage).To(ContainElement("      cf unmap-route APP_NAME DOMAIN --port PORT"))
   114  		})
   115  	})
   116  
   117  	Describe("Requirements", func() {
   118  		Context("when not provided exactly two args", func() {
   119  			BeforeEach(func() {
   120  				flagContext.Parse("app-name")
   121  			})
   122  
   123  			It("fails with usage", func() {
   124  				_, err := cmd.Requirements(factory, flagContext)
   125  				Expect(err).To(HaveOccurred())
   126  				Expect(ui.Outputs()).To(ContainSubstrings(
   127  					[]string{"Incorrect Usage. Requires app_name, domain_name as arguments"},
   128  					[]string{"NAME"},
   129  					[]string{"USAGE"},
   130  				))
   131  			})
   132  		})
   133  
   134  		Context("when provided exactly two args", func() {
   135  			BeforeEach(func() {
   136  				flagContext.Parse("app-name", "domain-name")
   137  			})
   138  
   139  			It("returns a LoginRequirement", func() {
   140  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   141  				Expect(err).NotTo(HaveOccurred())
   142  				Expect(factory.NewLoginRequirementCallCount()).To(Equal(1))
   143  
   144  				Expect(actualRequirements).To(ContainElement(loginRequirement))
   145  			})
   146  
   147  			It("returns an ApplicationRequirement", func() {
   148  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   149  				Expect(err).NotTo(HaveOccurred())
   150  				Expect(factory.NewApplicationRequirementCallCount()).To(Equal(1))
   151  
   152  				Expect(factory.NewApplicationRequirementArgsForCall(0)).To(Equal("app-name"))
   153  				Expect(actualRequirements).To(ContainElement(applicationRequirement))
   154  			})
   155  
   156  			It("returns a DomainRequirement", func() {
   157  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   158  				Expect(err).NotTo(HaveOccurred())
   159  				Expect(factory.NewDomainRequirementCallCount()).To(Equal(1))
   160  
   161  				Expect(factory.NewDomainRequirementArgsForCall(0)).To(Equal("domain-name"))
   162  				Expect(actualRequirements).To(ContainElement(domainRequirement))
   163  			})
   164  
   165  			Context("when a path is passed", func() {
   166  				BeforeEach(func() {
   167  					flagContext.Parse("app-name", "domain-name", "--path", "the-path")
   168  				})
   169  
   170  				It("returns a MinAPIVersionRequirement as the first requirement", func() {
   171  					actualRequirements, err := cmd.Requirements(factory, flagContext)
   172  					Expect(err).NotTo(HaveOccurred())
   173  
   174  					expectedVersion, err := semver.Make("2.36.0")
   175  					Expect(err).NotTo(HaveOccurred())
   176  
   177  					Expect(factory.NewMinAPIVersionRequirementCallCount()).To(Equal(1))
   178  					feature, requiredVersion := factory.NewMinAPIVersionRequirementArgsForCall(0)
   179  					Expect(feature).To(Equal("Option '--path'"))
   180  					Expect(requiredVersion).To(Equal(expectedVersion))
   181  					Expect(actualRequirements[0]).To(Equal(minAPIVersionRequirement))
   182  				})
   183  			})
   184  
   185  			Context("when passing port with a hostname", func() {
   186  				BeforeEach(func() {
   187  					flagContext.Parse("app-name", "example.com", "--port", "8080", "--hostname", "something-else")
   188  				})
   189  
   190  				It("fails", func() {
   191  					_, err := cmd.Requirements(factory, flagContext)
   192  					Expect(err).To(HaveOccurred())
   193  					Expect(ui.Outputs()).To(ContainSubstrings(
   194  						[]string{"FAILED"},
   195  						[]string{"Cannot specify port together with hostname and/or path."},
   196  					))
   197  				})
   198  			})
   199  
   200  			Context("when passing port with a path", func() {
   201  				BeforeEach(func() {
   202  					flagContext.Parse("app-name", "example.com", "--port", "8080", "--path", "something-else")
   203  				})
   204  
   205  				It("fails", func() {
   206  					_, err := cmd.Requirements(factory, flagContext)
   207  					Expect(err).To(HaveOccurred())
   208  					Expect(ui.Outputs()).To(ContainSubstrings(
   209  						[]string{"FAILED"},
   210  						[]string{"Cannot specify port together with hostname and/or path."},
   211  					))
   212  				})
   213  			})
   214  
   215  			Context("when no options are passed", func() {
   216  				BeforeEach(func() {
   217  					flagContext.Parse("app-name", "domain-name")
   218  				})
   219  
   220  				It("does not return a MinAPIVersionRequirement", func() {
   221  					actualRequirements, err := cmd.Requirements(factory, flagContext)
   222  					Expect(err).NotTo(HaveOccurred())
   223  					Expect(factory.NewMinAPIVersionRequirementCallCount()).To(Equal(0))
   224  					Expect(actualRequirements).NotTo(ContainElement(minAPIVersionRequirement))
   225  				})
   226  			})
   227  
   228  			Context("when a port is passed", func() {
   229  				BeforeEach(func() {
   230  					flagContext.Parse("app-name", "domain-name", "--port", "5000")
   231  				})
   232  
   233  				It("returns a MinAPIVersionRequirement as the first requirement", func() {
   234  					actualRequirements, err := cmd.Requirements(factory, flagContext)
   235  					Expect(err).NotTo(HaveOccurred())
   236  
   237  					expectedVersion, err := semver.Make("2.53.0")
   238  					Expect(err).NotTo(HaveOccurred())
   239  
   240  					Expect(factory.NewMinAPIVersionRequirementCallCount()).To(Equal(1))
   241  					feature, requiredVersion := factory.NewMinAPIVersionRequirementArgsForCall(0)
   242  					Expect(feature).To(Equal("Option '--port'"))
   243  					Expect(requiredVersion).To(Equal(expectedVersion))
   244  					Expect(actualRequirements[0]).To(Equal(minAPIVersionRequirement))
   245  				})
   246  			})
   247  		})
   248  	})
   249  
   250  	Describe("Execute", func() {
   251  		var err error
   252  
   253  		BeforeEach(func() {
   254  			err := flagContext.Parse("app-name", "domain-name")
   255  			Expect(err).NotTo(HaveOccurred())
   256  			cmd.Requirements(factory, flagContext)
   257  		})
   258  
   259  		JustBeforeEach(func() {
   260  			err = cmd.Execute(flagContext)
   261  		})
   262  
   263  		It("tries to find the route", func() {
   264  			Expect(err).NotTo(HaveOccurred())
   265  			Expect(routeRepo.FindCallCount()).To(Equal(1))
   266  			hostname, domain, path, port := routeRepo.FindArgsForCall(0)
   267  			Expect(hostname).To(Equal(""))
   268  			Expect(domain).To(Equal(fakeDomain))
   269  			Expect(path).To(Equal(""))
   270  			Expect(port).To(Equal(0))
   271  		})
   272  
   273  		Context("when a path is passed", func() {
   274  			BeforeEach(func() {
   275  				err := flagContext.Parse("app-name", "domain-name", "--path", "the-path")
   276  				Expect(err).NotTo(HaveOccurred())
   277  				cmd.Requirements(factory, flagContext)
   278  			})
   279  
   280  			It("tries to find the route with the path", func() {
   281  				Expect(err).NotTo(HaveOccurred())
   282  				Expect(routeRepo.FindCallCount()).To(Equal(1))
   283  				_, _, path, _ := routeRepo.FindArgsForCall(0)
   284  				Expect(path).To(Equal("the-path"))
   285  			})
   286  		})
   287  
   288  		Context("when a port is passed", func() {
   289  			BeforeEach(func() {
   290  				err := flagContext.Parse("app-name", "domain-name", "--port", "60000")
   291  				Expect(err).NotTo(HaveOccurred())
   292  				cmd.Requirements(factory, flagContext)
   293  			})
   294  
   295  			It("tries to find the route with the port", func() {
   296  				Expect(err).NotTo(HaveOccurred())
   297  				Expect(routeRepo.FindCallCount()).To(Equal(1))
   298  				_, _, _, port := routeRepo.FindArgsForCall(0)
   299  				Expect(port).To(Equal(60000))
   300  			})
   301  		})
   302  
   303  		Context("when the route can be found", func() {
   304  			BeforeEach(func() {
   305  				routeRepo.FindReturns(models.Route{GUID: "route-guid"}, nil)
   306  			})
   307  
   308  			It("tells the user that it is removing the route", func() {
   309  				Expect(err).NotTo(HaveOccurred())
   310  				Expect(ui.Outputs()).To(ContainSubstrings(
   311  					[]string{"Removing route", "from app", "in org"},
   312  				))
   313  			})
   314  
   315  			Context("when the returned route has an app with the requested app's guid", func() {
   316  				BeforeEach(func() {
   317  					route := models.Route{
   318  						GUID: "route-guid",
   319  						Apps: []models.ApplicationFields{
   320  							{GUID: "fake-app-guid"},
   321  						},
   322  					}
   323  					routeRepo.FindReturns(route, nil)
   324  				})
   325  
   326  				It("tries to unbind the route from the app", func() {
   327  					Expect(err).NotTo(HaveOccurred())
   328  					Expect(routeRepo.UnbindCallCount()).To(Equal(1))
   329  					routeGUID, appGUID := routeRepo.UnbindArgsForCall(0)
   330  					Expect(routeGUID).To(Equal("route-guid"))
   331  					Expect(appGUID).To(Equal("fake-app-guid"))
   332  				})
   333  
   334  				Context("when unbinding the route from the app fails", func() {
   335  					BeforeEach(func() {
   336  						routeRepo.UnbindReturns(errors.New("unbind-err"))
   337  					})
   338  
   339  					It("returns an error", func() {
   340  						Expect(err).To(HaveOccurred())
   341  						Expect(err.Error()).To(Equal("unbind-err"))
   342  					})
   343  				})
   344  
   345  				Context("when unbinding the route from the app succeeds", func() {
   346  					BeforeEach(func() {
   347  						routeRepo.UnbindReturns(nil)
   348  					})
   349  
   350  					It("tells the user it succeeded", func() {
   351  						Expect(err).NotTo(HaveOccurred())
   352  						Expect(ui.Outputs()).To(BeInDisplayOrder(
   353  							[]string{"OK"},
   354  						))
   355  					})
   356  				})
   357  			})
   358  
   359  			Context("when the returned route does not have an app with the requested app's guid", func() {
   360  				BeforeEach(func() {
   361  					route := models.Route{
   362  						GUID: "route-guid",
   363  						Apps: []models.ApplicationFields{
   364  							{GUID: "other-fake-app-guid"},
   365  						},
   366  					}
   367  					routeRepo.FindReturns(route, nil)
   368  				})
   369  
   370  				It("does not unbind the route from the app", func() {
   371  					Expect(err).NotTo(HaveOccurred())
   372  					Expect(routeRepo.UnbindCallCount()).To(Equal(0))
   373  				})
   374  
   375  				It("tells the user 'OK'", func() {
   376  					Expect(err).NotTo(HaveOccurred())
   377  					Expect(ui.Outputs()).To(ContainSubstrings(
   378  						[]string{"OK"},
   379  					))
   380  				})
   381  
   382  				It("warns the user the route was not mapped to the application", func() {
   383  					Expect(err).NotTo(HaveOccurred())
   384  					Expect(ui.Outputs()).To(ContainSubstrings(
   385  						[]string{"Route to be unmapped is not currently mapped to the application."},
   386  					))
   387  				})
   388  			})
   389  		})
   390  
   391  		Context("when the route cannot be found", func() {
   392  			BeforeEach(func() {
   393  				routeRepo.FindReturns(models.Route{}, errors.New("find-by-host-and-domain-err"))
   394  			})
   395  
   396  			It("returns an error", func() {
   397  				Expect(err).To(HaveOccurred())
   398  				Expect(err.Error()).To(Equal("find-by-host-and-domain-err"))
   399  			})
   400  		})
   401  
   402  	})
   403  })