github.com/DaAlbrecht/cf-cli@v0.0.0-20231128151943-1fe19bb400b9/command/v7/bind_route_service_command_test.go (about)

     1  package v7_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"code.cloudfoundry.org/cli/actor/actionerror"
     8  	"code.cloudfoundry.org/cli/actor/v7action"
     9  	"code.cloudfoundry.org/cli/command/commandfakes"
    10  	v7 "code.cloudfoundry.org/cli/command/v7"
    11  	"code.cloudfoundry.org/cli/command/v7/v7fakes"
    12  	"code.cloudfoundry.org/cli/types"
    13  	"code.cloudfoundry.org/cli/util/configv3"
    14  	"code.cloudfoundry.org/cli/util/ui"
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/gomega"
    17  	. "github.com/onsi/gomega/gbytes"
    18  )
    19  
    20  var _ = Describe("bind-route-service Command", func() {
    21  	var (
    22  		cmd             v7.BindRouteServiceCommand
    23  		testUI          *ui.UI
    24  		fakeConfig      *commandfakes.FakeConfig
    25  		fakeSharedActor *commandfakes.FakeSharedActor
    26  		executeErr      error
    27  		fakeActor       *v7fakes.FakeActor
    28  	)
    29  
    30  	const (
    31  		fakeUserName            = "fake-user-name"
    32  		fakeServiceInstanceName = "fake-service-instance-name"
    33  		fakeDomainName          = "fake-domain-name"
    34  		fakeHostname            = "fake-hostname"
    35  		fakePath                = "fake-path"
    36  		fakeOrgName             = "fake-org-name"
    37  		fakeSpaceName           = "fake-space-name"
    38  		fakeSpaceGUID           = "fake-space-guid"
    39  	)
    40  
    41  	BeforeEach(func() {
    42  		testUI = ui.NewTestUI(NewBuffer(), NewBuffer(), NewBuffer())
    43  		fakeConfig = new(commandfakes.FakeConfig)
    44  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    45  		fakeActor = new(v7fakes.FakeActor)
    46  
    47  		cmd = v7.BindRouteServiceCommand{
    48  			BaseCommand: v7.BaseCommand{
    49  				UI:          testUI,
    50  				Config:      fakeConfig,
    51  				SharedActor: fakeSharedActor,
    52  				Actor:       fakeActor,
    53  			},
    54  		}
    55  
    56  		fakeConfig.TargetedSpaceReturns(configv3.Space{
    57  			Name: fakeSpaceName,
    58  			GUID: fakeSpaceGUID,
    59  		})
    60  
    61  		fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: fakeOrgName})
    62  
    63  		fakeActor.GetCurrentUserReturns(configv3.User{Name: fakeUserName}, nil)
    64  
    65  		fakeActor.CreateRouteBindingReturns(
    66  			nil,
    67  			v7action.Warnings{"fake warning"},
    68  			nil,
    69  		)
    70  
    71  		setPositionalFlags(&cmd, fakeDomainName, fakeServiceInstanceName)
    72  		setFlag(&cmd, "--hostname", fakeHostname)
    73  		setFlag(&cmd, "--path", fakePath)
    74  		setFlag(&cmd, "-c", `{"foo": "bar"}`)
    75  	})
    76  
    77  	JustBeforeEach(func() {
    78  		executeErr = cmd.Execute(nil)
    79  	})
    80  
    81  	It("checks the user is logged in, and targeting an org and space", func() {
    82  		Expect(executeErr).NotTo(HaveOccurred())
    83  
    84  		Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
    85  		actualOrg, actualSpace := fakeSharedActor.CheckTargetArgsForCall(0)
    86  		Expect(actualOrg).To(BeTrue())
    87  		Expect(actualSpace).To(BeTrue())
    88  	})
    89  
    90  	It("delegates to the actor", func() {
    91  		Expect(fakeActor.CreateRouteBindingCallCount()).To(Equal(1))
    92  		Expect(fakeActor.CreateRouteBindingArgsForCall(0)).To(Equal(v7action.CreateRouteBindingParams{
    93  			SpaceGUID:           fakeSpaceGUID,
    94  			ServiceInstanceName: fakeServiceInstanceName,
    95  			DomainName:          fakeDomainName,
    96  			Hostname:            fakeHostname,
    97  			Path:                fmt.Sprintf("/%s", fakePath),
    98  			Parameters:          types.NewOptionalObject(map[string]interface{}{"foo": "bar"}),
    99  		}))
   100  	})
   101  
   102  	Describe("intro message", func() {
   103  		It("prints an intro and warnings", func() {
   104  			Expect(executeErr).NotTo(HaveOccurred())
   105  			Expect(testUI.Err).To(Say("fake warning"))
   106  			Expect(testUI.Out).To(Say(
   107  				`Binding route %s.%s/%s to service instance %s in org %s / space %s as %s\.\.\.\n`,
   108  				fakeHostname,
   109  				fakeDomainName,
   110  				fakePath,
   111  				fakeServiceInstanceName,
   112  				fakeOrgName,
   113  				fakeSpaceName,
   114  				fakeUserName,
   115  			))
   116  		})
   117  
   118  		When("no hostname", func() {
   119  			BeforeEach(func() {
   120  				setFlag(&cmd, "--hostname", "")
   121  			})
   122  
   123  			It("prints an appropriate intro", func() {
   124  				Expect(testUI.Out).To(Say(
   125  					`Binding route %s/%s to service instance`,
   126  					fakeDomainName,
   127  					fakePath,
   128  				))
   129  			})
   130  		})
   131  
   132  		When("no path", func() {
   133  			BeforeEach(func() {
   134  				setFlag(&cmd, "--path", "")
   135  			})
   136  
   137  			It("prints an appropriate intro", func() {
   138  				Expect(testUI.Out).To(Say(
   139  					`Binding route %s.%s to service instance`,
   140  					fakeHostname,
   141  					fakeDomainName,
   142  				))
   143  			})
   144  		})
   145  	})
   146  
   147  	When("binding already exists", func() {
   148  		BeforeEach(func() {
   149  			fakeActor.CreateRouteBindingReturns(
   150  				nil,
   151  				v7action.Warnings{"fake warning"},
   152  				actionerror.ResourceAlreadyExistsError{},
   153  			)
   154  		})
   155  
   156  		It("prints a message and warnings", func() {
   157  			Expect(testUI.Out).To(SatisfyAll(
   158  				Say(
   159  					`Route %s.%s/%s is already bound to service instance %s\.\n`,
   160  					fakeHostname,
   161  					fakeDomainName,
   162  					fakePath,
   163  					fakeServiceInstanceName,
   164  				),
   165  				Say(`OK\n`),
   166  			))
   167  
   168  			Expect(testUI.Err).To(Say("fake warning"))
   169  		})
   170  	})
   171  
   172  	Describe("processing the response stream", func() {
   173  		Context("nil stream", func() {
   174  			It("prints a message and warnings", func() {
   175  				Expect(testUI.Out).To(Say(`OK\n`))
   176  				Expect(testUI.Err).To(Say("fake warning"))
   177  			})
   178  		})
   179  
   180  		Context("stream goes to complete", func() {
   181  			BeforeEach(func() {
   182  				eventStream := make(chan v7action.PollJobEvent)
   183  				go func() {
   184  					eventStream <- v7action.PollJobEvent{
   185  						State:    v7action.JobProcessing,
   186  						Warnings: v7action.Warnings{"job processing warning"},
   187  					}
   188  					eventStream <- v7action.PollJobEvent{
   189  						State:    v7action.JobComplete,
   190  						Warnings: v7action.Warnings{"job complete warning"},
   191  					}
   192  					close(eventStream)
   193  				}()
   194  
   195  				fakeActor.CreateRouteBindingReturns(
   196  					eventStream,
   197  					v7action.Warnings{"fake warning"},
   198  					nil,
   199  				)
   200  			})
   201  
   202  			It("prints a message and warnings", func() {
   203  				Expect(testUI.Out).To(Say(`OK\n`))
   204  
   205  				Expect(testUI.Err).To(SatisfyAll(
   206  					Say("fake warning"),
   207  					Say("job processing warning"),
   208  					Say("job complete warning"),
   209  				))
   210  			})
   211  		})
   212  
   213  		Context("stream goes to polling", func() {
   214  			BeforeEach(func() {
   215  				eventStream := make(chan v7action.PollJobEvent)
   216  				go func() {
   217  					eventStream <- v7action.PollJobEvent{
   218  						State:    v7action.JobProcessing,
   219  						Warnings: v7action.Warnings{"job processing warning"},
   220  					}
   221  					eventStream <- v7action.PollJobEvent{
   222  						State:    v7action.JobPolling,
   223  						Warnings: v7action.Warnings{"job polling warning"},
   224  					}
   225  				}()
   226  
   227  				fakeActor.CreateRouteBindingReturns(
   228  					eventStream,
   229  					v7action.Warnings{"fake warning"},
   230  					nil,
   231  				)
   232  			})
   233  
   234  			It("prints a message and warnings", func() {
   235  				Expect(testUI.Out).To(SatisfyAll(
   236  					Say(`OK\n`),
   237  					Say(`\n`),
   238  					Say(`Binding in progress\.\n`),
   239  				))
   240  
   241  				Expect(testUI.Err).To(SatisfyAll(
   242  					Say("fake warning"),
   243  					Say("job processing warning"),
   244  					Say("job polling warning"),
   245  				))
   246  			})
   247  		})
   248  
   249  		Context("stream goes to error", func() {
   250  			BeforeEach(func() {
   251  				eventStream := make(chan v7action.PollJobEvent)
   252  				go func() {
   253  					eventStream <- v7action.PollJobEvent{
   254  						State:    v7action.JobFailed,
   255  						Warnings: v7action.Warnings{"job failed warning"},
   256  						Err:      errors.New("boom"),
   257  					}
   258  				}()
   259  
   260  				fakeActor.CreateRouteBindingReturns(
   261  					eventStream,
   262  					v7action.Warnings{"fake warning"},
   263  					nil,
   264  				)
   265  			})
   266  
   267  			It("prints warnings and returns the error", func() {
   268  				Expect(executeErr).To(MatchError("boom"))
   269  
   270  				Expect(testUI.Err).To(SatisfyAll(
   271  					Say("fake warning"),
   272  					Say("job failed warning"),
   273  				))
   274  			})
   275  		})
   276  
   277  		When("--wait flag specified", func() {
   278  			BeforeEach(func() {
   279  				eventStream := make(chan v7action.PollJobEvent)
   280  				go func() {
   281  					eventStream <- v7action.PollJobEvent{
   282  						State:    v7action.JobProcessing,
   283  						Warnings: v7action.Warnings{"job processing warning"},
   284  					}
   285  					eventStream <- v7action.PollJobEvent{
   286  						State:    v7action.JobPolling,
   287  						Warnings: v7action.Warnings{"job polling warning"},
   288  					}
   289  					eventStream <- v7action.PollJobEvent{
   290  						State:    v7action.JobComplete,
   291  						Warnings: v7action.Warnings{"job complete warning"},
   292  					}
   293  					close(eventStream)
   294  				}()
   295  
   296  				fakeActor.CreateRouteBindingReturns(
   297  					eventStream,
   298  					v7action.Warnings{"fake warning"},
   299  					nil,
   300  				)
   301  
   302  				setFlag(&cmd, "--wait")
   303  			})
   304  
   305  			It("waits for the event stream to complete", func() {
   306  				Expect(testUI.Out).To(SatisfyAll(
   307  					Say(`Waiting for the operation to complete\.\.\.\n`),
   308  					Say(`\n`),
   309  					Say(`OK\n`),
   310  				))
   311  
   312  				Expect(testUI.Err).To(SatisfyAll(
   313  					Say("fake warning"),
   314  					Say("job processing warning"),
   315  					Say("job polling warning"),
   316  					Say("job complete warning"),
   317  				))
   318  			})
   319  		})
   320  	})
   321  
   322  	When("checking the target returns an error", func() {
   323  		BeforeEach(func() {
   324  			fakeSharedActor.CheckTargetReturns(errors.New("explode"))
   325  		})
   326  
   327  		It("returns the error", func() {
   328  			Expect(executeErr).To(MatchError("explode"))
   329  		})
   330  	})
   331  
   332  	When("actor returns error", func() {
   333  		BeforeEach(func() {
   334  			fakeActor.CreateRouteBindingReturns(
   335  				nil,
   336  				v7action.Warnings{"fake warning"},
   337  				errors.New("boom"),
   338  			)
   339  		})
   340  
   341  		It("prints warnings and returns the error", func() {
   342  			Expect(testUI.Err).To(Say("fake warning"))
   343  			Expect(executeErr).To(MatchError("boom"))
   344  		})
   345  	})
   346  
   347  	When("getting the username returns an error", func() {
   348  		BeforeEach(func() {
   349  			fakeActor.GetCurrentUserReturns(configv3.User{}, errors.New("bad thing"))
   350  		})
   351  
   352  		It("returns the error", func() {
   353  			Expect(executeErr).To(MatchError("bad thing"))
   354  		})
   355  	})
   356  })