github.com/sleungcy/cli@v7.1.0+incompatible/command/common/install_plugin_command_test.go (about) 1 package common_test 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "os" 7 8 "code.cloudfoundry.org/cli/actor/actionerror" 9 "code.cloudfoundry.org/cli/api/plugin/pluginerror" 10 "code.cloudfoundry.org/cli/api/plugin/pluginfakes" 11 "code.cloudfoundry.org/cli/command/commandfakes" 12 . "code.cloudfoundry.org/cli/command/common" 13 "code.cloudfoundry.org/cli/command/common/commonfakes" 14 "code.cloudfoundry.org/cli/command/translatableerror" 15 "code.cloudfoundry.org/cli/util/configv3" 16 "code.cloudfoundry.org/cli/util/ui" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 . "github.com/onsi/gomega/gbytes" 20 ) 21 22 var _ = Describe("install-plugin command", func() { 23 var ( 24 cmd InstallPluginCommand 25 testUI *ui.UI 26 input *Buffer 27 fakeConfig *commandfakes.FakeConfig 28 fakeActor *commonfakes.FakeInstallPluginActor 29 fakeProgressBar *pluginfakes.FakeProxyReader 30 executeErr error 31 expectedErr error 32 pluginHome string 33 ) 34 35 BeforeEach(func() { 36 input = NewBuffer() 37 testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer()) 38 fakeConfig = new(commandfakes.FakeConfig) 39 fakeActor = new(commonfakes.FakeInstallPluginActor) 40 fakeProgressBar = new(pluginfakes.FakeProxyReader) 41 42 cmd = InstallPluginCommand{ 43 UI: testUI, 44 Config: fakeConfig, 45 Actor: fakeActor, 46 ProgressBar: fakeProgressBar, 47 } 48 49 var err error 50 pluginHome, err = ioutil.TempDir("", "some-pluginhome") 51 Expect(err).NotTo(HaveOccurred()) 52 53 fakeConfig.PluginHomeReturns(pluginHome) 54 fakeConfig.BinaryNameReturns("faceman") 55 }) 56 57 AfterEach(func() { 58 os.RemoveAll(pluginHome) 59 }) 60 61 JustBeforeEach(func() { 62 executeErr = cmd.Execute(nil) 63 }) 64 65 Describe("installing from a local file", func() { 66 BeforeEach(func() { 67 cmd.OptionalArgs.PluginNameOrLocation = "some-path" 68 }) 69 70 When("the local file does not exist", func() { 71 BeforeEach(func() { 72 fakeActor.FileExistsReturns(false) 73 }) 74 75 It("does not print installation messages and returns a FileNotFoundError", func() { 76 Expect(executeErr).To(MatchError(translatableerror.PluginNotFoundOnDiskOrInAnyRepositoryError{PluginName: "some-path", BinaryName: "faceman"})) 77 78 Expect(testUI.Out).ToNot(Say(`Attention: Plugins are binaries written by potentially untrusted authors\.`)) 79 Expect(testUI.Out).ToNot(Say(`Installing plugin some-path\.\.\.`)) 80 }) 81 }) 82 83 When("the file exists", func() { 84 BeforeEach(func() { 85 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 86 fakeActor.FileExistsReturns(true) 87 }) 88 89 When("the -f argument is given", func() { 90 BeforeEach(func() { 91 cmd.Force = true 92 }) 93 94 When("the plugin is invalid", func() { 95 var returnedErr error 96 97 BeforeEach(func() { 98 returnedErr = actionerror.PluginInvalidError{} 99 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{}, returnedErr) 100 }) 101 102 It("returns an error", func() { 103 Expect(executeErr).To(MatchError(returnedErr)) 104 105 Expect(testUI.Out).ToNot(Say("Installing plugin")) 106 }) 107 }) 108 109 When("the plugin is valid but generates an error when fetching metadata", func() { 110 var wrappedErr error 111 112 BeforeEach(func() { 113 wrappedErr = errors.New("some-error") 114 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{}, actionerror.PluginInvalidError{Err: wrappedErr}) 115 }) 116 117 It("returns an error", func() { 118 Expect(executeErr).To(MatchError(actionerror.PluginInvalidError{Err: wrappedErr})) 119 120 Expect(testUI.Out).ToNot(Say("Installing plugin")) 121 }) 122 }) 123 124 When("the plugin is already installed", func() { 125 var ( 126 plugin configv3.Plugin 127 newPlugin configv3.Plugin 128 ) 129 BeforeEach(func() { 130 plugin = configv3.Plugin{ 131 Name: "some-plugin", 132 Version: configv3.PluginVersion{ 133 Major: 1, 134 Minor: 2, 135 Build: 2, 136 }, 137 } 138 newPlugin = configv3.Plugin{ 139 Name: "some-plugin", 140 Version: configv3.PluginVersion{ 141 Major: 1, 142 Minor: 2, 143 Build: 3, 144 }, 145 } 146 fakeActor.GetAndValidatePluginReturns(newPlugin, nil) 147 fakeConfig.GetPluginCaseInsensitiveReturns(plugin, true) 148 }) 149 150 When("an error is encountered uninstalling the existing plugin", func() { 151 BeforeEach(func() { 152 expectedErr = errors.New("uninstall plugin error") 153 fakeActor.UninstallPluginReturns(expectedErr) 154 }) 155 156 It("returns the error", func() { 157 Expect(executeErr).To(MatchError(expectedErr)) 158 159 Expect(testUI.Out).ToNot(Say(`Plugin some-plugin successfully uninstalled\.`)) 160 }) 161 }) 162 163 When("no errors are encountered uninstalling the existing plugin", func() { 164 It("uninstalls the existing plugin and installs the current plugin", func() { 165 Expect(executeErr).ToNot(HaveOccurred()) 166 167 Expect(testUI.Out).To(Say(`Attention: Plugins are binaries written by potentially untrusted authors\.`)) 168 Expect(testUI.Out).To(Say(`Install and use plugins at your own risk\.`)) 169 Expect(testUI.Out).To(Say(`Plugin some-plugin 1\.2\.2 is already installed\. Uninstalling existing plugin\.\.\.`)) 170 Expect(testUI.Out).To(Say("OK")) 171 Expect(testUI.Out).To(Say(`Plugin some-plugin successfully uninstalled\.`)) 172 Expect(testUI.Out).To(Say(`Installing plugin some-plugin\.\.\.`)) 173 Expect(testUI.Out).To(Say("OK")) 174 Expect(testUI.Out).To(Say(`Plugin some-plugin 1\.2\.3 successfully installed\.`)) 175 176 Expect(fakeActor.FileExistsCallCount()).To(Equal(1)) 177 Expect(fakeActor.FileExistsArgsForCall(0)).To(Equal("some-path")) 178 179 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(1)) 180 _, _, path := fakeActor.GetAndValidatePluginArgsForCall(0) 181 Expect(path).To(Equal("copy-path")) 182 183 Expect(fakeConfig.GetPluginCaseInsensitiveCallCount()).To(Equal(1)) 184 Expect(fakeConfig.GetPluginCaseInsensitiveArgsForCall(0)).To(Equal("some-plugin")) 185 186 Expect(fakeActor.UninstallPluginCallCount()).To(Equal(1)) 187 _, pluginName := fakeActor.UninstallPluginArgsForCall(0) 188 Expect(pluginName).To(Equal("some-plugin")) 189 190 Expect(fakeActor.InstallPluginFromPathCallCount()).To(Equal(1)) 191 path, installedPlugin := fakeActor.InstallPluginFromPathArgsForCall(0) 192 Expect(path).To(Equal("copy-path")) 193 Expect(installedPlugin).To(Equal(newPlugin)) 194 }) 195 196 When("an error is encountered installing the plugin", func() { 197 BeforeEach(func() { 198 expectedErr = errors.New("install plugin error") 199 fakeActor.InstallPluginFromPathReturns(expectedErr) 200 }) 201 202 It("returns the error", func() { 203 Expect(executeErr).To(MatchError(expectedErr)) 204 205 Expect(testUI.Out).ToNot(Say(`Plugin some-plugin 1\.2\.3 successfully installed\.`)) 206 }) 207 }) 208 }) 209 }) 210 211 When("the plugin is not already installed", func() { 212 var plugin configv3.Plugin 213 214 BeforeEach(func() { 215 plugin = configv3.Plugin{ 216 Name: "some-plugin", 217 Version: configv3.PluginVersion{ 218 Major: 1, 219 Minor: 2, 220 Build: 3, 221 }, 222 } 223 fakeActor.GetAndValidatePluginReturns(plugin, nil) 224 }) 225 226 It("installs the plugin", func() { 227 Expect(executeErr).ToNot(HaveOccurred()) 228 229 Expect(testUI.Out).To(Say(`Attention: Plugins are binaries written by potentially untrusted authors\.`)) 230 Expect(testUI.Out).To(Say(`Install and use plugins at your own risk\.`)) 231 Expect(testUI.Out).To(Say(`Installing plugin some-plugin\.\.\.`)) 232 Expect(testUI.Out).To(Say("OK")) 233 Expect(testUI.Out).To(Say(`Plugin some-plugin 1\.2\.3 successfully installed\.`)) 234 235 Expect(fakeActor.FileExistsCallCount()).To(Equal(1)) 236 Expect(fakeActor.FileExistsArgsForCall(0)).To(Equal("some-path")) 237 238 Expect(fakeActor.CreateExecutableCopyCallCount()).To(Equal(1)) 239 pathArg, pluginDirArg := fakeActor.CreateExecutableCopyArgsForCall(0) 240 Expect(pathArg).To(Equal("some-path")) 241 Expect(pluginDirArg).To(ContainSubstring("some-pluginhome")) 242 Expect(pluginDirArg).To(ContainSubstring("temp")) 243 244 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(1)) 245 _, _, path := fakeActor.GetAndValidatePluginArgsForCall(0) 246 Expect(path).To(Equal("copy-path")) 247 248 Expect(fakeConfig.GetPluginCaseInsensitiveCallCount()).To(Equal(1)) 249 Expect(fakeConfig.GetPluginCaseInsensitiveArgsForCall(0)).To(Equal("some-plugin")) 250 251 Expect(fakeActor.InstallPluginFromPathCallCount()).To(Equal(1)) 252 path, installedPlugin := fakeActor.InstallPluginFromPathArgsForCall(0) 253 Expect(path).To(Equal("copy-path")) 254 Expect(installedPlugin).To(Equal(plugin)) 255 256 Expect(fakeActor.UninstallPluginCallCount()).To(Equal(0)) 257 }) 258 259 When("there is an error making an executable copy of the plugin binary", func() { 260 BeforeEach(func() { 261 expectedErr = errors.New("create executable copy error") 262 fakeActor.CreateExecutableCopyReturns("", expectedErr) 263 }) 264 265 It("returns the error", func() { 266 Expect(executeErr).To(MatchError(expectedErr)) 267 }) 268 }) 269 270 When("an error is encountered installing the plugin", func() { 271 BeforeEach(func() { 272 expectedErr = errors.New("install plugin error") 273 fakeActor.InstallPluginFromPathReturns(expectedErr) 274 }) 275 276 It("returns the error", func() { 277 Expect(executeErr).To(MatchError(expectedErr)) 278 279 Expect(testUI.Out).ToNot(Say(`Plugin some-plugin 1\.2\.3 successfully installed\.`)) 280 }) 281 }) 282 }) 283 }) 284 285 When("the -f argument is not given (user is prompted for confirmation)", func() { 286 BeforeEach(func() { 287 cmd.Force = false 288 }) 289 290 When("the user chooses no", func() { 291 BeforeEach(func() { 292 _, err := input.Write([]byte("n\n")) 293 Expect(err).ToNot(HaveOccurred()) 294 }) 295 296 It("cancels plugin installation", func() { 297 Expect(executeErr).ToNot(HaveOccurred()) 298 299 Expect(testUI.Out).To(Say(`Plugin installation cancelled\.`)) 300 }) 301 }) 302 303 When("the user chooses the default", func() { 304 BeforeEach(func() { 305 _, err := input.Write([]byte("\n")) 306 Expect(err).ToNot(HaveOccurred()) 307 }) 308 309 It("cancels plugin installation", func() { 310 Expect(executeErr).ToNot(HaveOccurred()) 311 312 Expect(testUI.Out).To(Say(`Plugin installation cancelled\.`)) 313 }) 314 }) 315 316 When("the user input is invalid", func() { 317 BeforeEach(func() { 318 _, err := input.Write([]byte("e\n")) 319 Expect(err).ToNot(HaveOccurred()) 320 }) 321 322 It("returns an error", func() { 323 Expect(executeErr).To(HaveOccurred()) 324 325 Expect(testUI.Out).ToNot(Say("Installing plugin")) 326 }) 327 }) 328 329 When("the user chooses yes", func() { 330 BeforeEach(func() { 331 _, err := input.Write([]byte("y\n")) 332 Expect(err).ToNot(HaveOccurred()) 333 }) 334 335 When("the plugin is not already installed", func() { 336 var plugin configv3.Plugin 337 338 BeforeEach(func() { 339 plugin = configv3.Plugin{ 340 Name: "some-plugin", 341 Version: configv3.PluginVersion{ 342 Major: 1, 343 Minor: 2, 344 Build: 3, 345 }, 346 } 347 fakeActor.GetAndValidatePluginReturns(plugin, nil) 348 }) 349 350 It("installs the plugin", func() { 351 Expect(executeErr).ToNot(HaveOccurred()) 352 353 Expect(testUI.Out).To(Say(`Attention: Plugins are binaries written by potentially untrusted authors\.`)) 354 Expect(testUI.Out).To(Say(`Install and use plugins at your own risk\.`)) 355 Expect(testUI.Out).To(Say(`Do you want to install the plugin some-path\? \[yN\]`)) 356 Expect(testUI.Out).To(Say(`Installing plugin some-plugin\.\.\.`)) 357 Expect(testUI.Out).To(Say("OK")) 358 Expect(testUI.Out).To(Say(`Plugin some-plugin 1\.2\.3 successfully installed\.`)) 359 360 Expect(fakeActor.FileExistsCallCount()).To(Equal(1)) 361 Expect(fakeActor.FileExistsArgsForCall(0)).To(Equal("some-path")) 362 363 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(1)) 364 _, _, path := fakeActor.GetAndValidatePluginArgsForCall(0) 365 Expect(path).To(Equal("copy-path")) 366 367 Expect(fakeConfig.GetPluginCaseInsensitiveCallCount()).To(Equal(1)) 368 Expect(fakeConfig.GetPluginCaseInsensitiveArgsForCall(0)).To(Equal("some-plugin")) 369 370 Expect(fakeActor.InstallPluginFromPathCallCount()).To(Equal(1)) 371 path, plugin := fakeActor.InstallPluginFromPathArgsForCall(0) 372 Expect(path).To(Equal("copy-path")) 373 Expect(plugin).To(Equal(plugin)) 374 375 Expect(fakeActor.UninstallPluginCallCount()).To(Equal(0)) 376 }) 377 }) 378 379 When("the plugin is already installed", func() { 380 BeforeEach(func() { 381 fakeConfig.GetPluginCaseInsensitiveReturns(configv3.Plugin{ 382 Name: "some-plugin", 383 Version: configv3.PluginVersion{ 384 Major: 1, 385 Minor: 2, 386 Build: 2, 387 }, 388 }, true) 389 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 390 Name: "some-plugin", 391 Version: configv3.PluginVersion{ 392 Major: 1, 393 Minor: 2, 394 Build: 3, 395 }, 396 }, nil) 397 }) 398 399 It("returns PluginAlreadyInstalledError", func() { 400 Expect(executeErr).To(MatchError(translatableerror.PluginAlreadyInstalledError{ 401 BinaryName: "faceman", 402 Name: "some-plugin", 403 Version: "1.2.3", 404 })) 405 }) 406 }) 407 }) 408 }) 409 }) 410 }) 411 412 Describe("installing from an unsupported URL scheme", func() { 413 BeforeEach(func() { 414 cmd.OptionalArgs.PluginNameOrLocation = "ftp://some-url" 415 }) 416 417 It("returns an error indicating an unsupported URL scheme", func() { 418 Expect(executeErr).To(MatchError(translatableerror.UnsupportedURLSchemeError{ 419 UnsupportedURL: string(cmd.OptionalArgs.PluginNameOrLocation), 420 })) 421 }) 422 }) 423 424 Describe("installing from an HTTP URL", func() { 425 var ( 426 plugin configv3.Plugin 427 pluginName string 428 executablePluginPath string 429 ) 430 431 BeforeEach(func() { 432 cmd.OptionalArgs.PluginNameOrLocation = "http://some-url" 433 pluginName = "some-plugin" 434 executablePluginPath = "executable-path" 435 }) 436 437 It("displays the plugin warning", func() { 438 Expect(testUI.Out).To(Say(`Attention: Plugins are binaries written by potentially untrusted authors\.`)) 439 Expect(testUI.Out).To(Say(`Install and use plugins at your own risk\.`)) 440 }) 441 442 When("the -f argument is given", func() { 443 BeforeEach(func() { 444 cmd.Force = true 445 }) 446 447 It("begins downloading the plugin", func() { 448 Expect(testUI.Out).To(Say(`Starting download of plugin binary from URL\.\.\.`)) 449 450 Expect(fakeActor.DownloadExecutableBinaryFromURLCallCount()).To(Equal(1)) 451 url, tempPluginDir, proxyReader := fakeActor.DownloadExecutableBinaryFromURLArgsForCall(0) 452 Expect(url).To(Equal(cmd.OptionalArgs.PluginNameOrLocation.String())) 453 Expect(tempPluginDir).To(ContainSubstring("some-pluginhome")) 454 Expect(tempPluginDir).To(ContainSubstring("temp")) 455 Expect(proxyReader).To(Equal(fakeProgressBar)) 456 }) 457 458 When("getting the binary fails", func() { 459 BeforeEach(func() { 460 expectedErr = errors.New("some-error") 461 fakeActor.DownloadExecutableBinaryFromURLReturns("", expectedErr) 462 }) 463 464 It("returns the error", func() { 465 Expect(executeErr).To(MatchError(expectedErr)) 466 467 Expect(testUI.Out).ToNot(Say("downloaded")) 468 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(0)) 469 }) 470 471 When("a 4xx or 5xx status is encountered while downloading the plugin", func() { 472 BeforeEach(func() { 473 fakeActor.DownloadExecutableBinaryFromURLReturns("", pluginerror.RawHTTPStatusError{Status: "some-status"}) 474 }) 475 476 It("returns a DownloadPluginHTTPError", func() { 477 Expect(executeErr).To(MatchError(pluginerror.RawHTTPStatusError{Status: "some-status"})) 478 }) 479 }) 480 481 When("a SSL error is encountered while downloading the plugin", func() { 482 BeforeEach(func() { 483 fakeActor.DownloadExecutableBinaryFromURLReturns("", pluginerror.UnverifiedServerError{}) 484 }) 485 486 It("returns a DownloadPluginHTTPError", func() { 487 Expect(executeErr).To(MatchError(pluginerror.UnverifiedServerError{})) 488 }) 489 }) 490 }) 491 492 When("getting the binary succeeds", func() { 493 BeforeEach(func() { 494 fakeActor.DownloadExecutableBinaryFromURLReturns("some-path", nil) 495 fakeActor.CreateExecutableCopyReturns(executablePluginPath, nil) 496 }) 497 498 It("sets up the progress bar", func() { 499 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(1)) 500 _, _, path := fakeActor.GetAndValidatePluginArgsForCall(0) 501 Expect(path).To(Equal(executablePluginPath)) 502 503 Expect(fakeActor.DownloadExecutableBinaryFromURLCallCount()).To(Equal(1)) 504 urlArg, pluginDirArg, proxyReader := fakeActor.DownloadExecutableBinaryFromURLArgsForCall(0) 505 Expect(urlArg).To(Equal("http://some-url")) 506 Expect(pluginDirArg).To(ContainSubstring("some-pluginhome")) 507 Expect(pluginDirArg).To(ContainSubstring("temp")) 508 Expect(proxyReader).To(Equal(fakeProgressBar)) 509 510 Expect(fakeActor.CreateExecutableCopyCallCount()).To(Equal(1)) 511 pathArg, pluginDirArg := fakeActor.CreateExecutableCopyArgsForCall(0) 512 Expect(pathArg).To(Equal("some-path")) 513 Expect(pluginDirArg).To(ContainSubstring("some-pluginhome")) 514 Expect(pluginDirArg).To(ContainSubstring("temp")) 515 }) 516 517 When("the plugin is invalid", func() { 518 var returnedErr error 519 520 BeforeEach(func() { 521 returnedErr = actionerror.PluginInvalidError{} 522 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{}, returnedErr) 523 }) 524 525 It("returns an error", func() { 526 Expect(executeErr).To(MatchError(returnedErr)) 527 528 Expect(fakeConfig.GetPluginCaseInsensitiveCallCount()).To(Equal(0)) 529 }) 530 }) 531 532 When("the plugin is valid", func() { 533 var newPlugin configv3.Plugin 534 535 BeforeEach(func() { 536 plugin = configv3.Plugin{ 537 Name: pluginName, 538 Version: configv3.PluginVersion{ 539 Major: 1, 540 Minor: 2, 541 Build: 2, 542 }, 543 } 544 newPlugin = configv3.Plugin{ 545 Name: pluginName, 546 Version: configv3.PluginVersion{ 547 Major: 1, 548 Minor: 2, 549 Build: 3, 550 }, 551 } 552 fakeActor.GetAndValidatePluginReturns(newPlugin, nil) 553 }) 554 555 When("the plugin is already installed", func() { 556 BeforeEach(func() { 557 fakeConfig.GetPluginCaseInsensitiveReturns(plugin, true) 558 }) 559 560 It("displays uninstall message", func() { 561 Expect(testUI.Out).To(Say(`Plugin %s 1\.2\.2 is already installed\. Uninstalling existing plugin\.\.\.`, pluginName)) 562 }) 563 564 When("an error is encountered uninstalling the existing plugin", func() { 565 BeforeEach(func() { 566 expectedErr = errors.New("uninstall plugin error") 567 fakeActor.UninstallPluginReturns(expectedErr) 568 }) 569 570 It("returns the error", func() { 571 Expect(executeErr).To(MatchError(expectedErr)) 572 573 Expect(testUI.Out).ToNot(Say(`Plugin some-plugin successfully uninstalled\.`)) 574 }) 575 }) 576 577 When("no errors are encountered uninstalling the existing plugin", func() { 578 It("displays uninstall message", func() { 579 Expect(testUI.Out).To(Say(`Plugin %s successfully uninstalled\.`, pluginName)) 580 }) 581 582 When("no errors are encountered installing the plugin", func() { 583 It("uninstalls the existing plugin and installs the current plugin", func() { 584 Expect(executeErr).ToNot(HaveOccurred()) 585 586 Expect(testUI.Out).To(Say(`Installing plugin %s\.\.\.`, pluginName)) 587 Expect(testUI.Out).To(Say("OK")) 588 Expect(testUI.Out).To(Say(`Plugin %s 1\.2\.3 successfully installed\.`, pluginName)) 589 }) 590 }) 591 592 When("an error is encountered installing the plugin", func() { 593 BeforeEach(func() { 594 expectedErr = errors.New("install plugin error") 595 fakeActor.InstallPluginFromPathReturns(expectedErr) 596 }) 597 598 It("returns the error", func() { 599 Expect(executeErr).To(MatchError(expectedErr)) 600 601 Expect(testUI.Out).ToNot(Say(`Plugin some-plugin 1\.2\.3 successfully installed\.`)) 602 }) 603 }) 604 }) 605 }) 606 607 When("the plugin is not already installed", func() { 608 It("installs the plugin", func() { 609 Expect(executeErr).ToNot(HaveOccurred()) 610 611 Expect(testUI.Out).To(Say(`Installing plugin %s\.\.\.`, pluginName)) 612 Expect(testUI.Out).To(Say("OK")) 613 Expect(testUI.Out).To(Say(`Plugin %s 1\.2\.3 successfully installed\.`, pluginName)) 614 615 Expect(fakeActor.UninstallPluginCallCount()).To(Equal(0)) 616 }) 617 }) 618 }) 619 }) 620 }) 621 622 When("the -f argument is not given (user is prompted for confirmation)", func() { 623 BeforeEach(func() { 624 plugin = configv3.Plugin{ 625 Name: pluginName, 626 Version: configv3.PluginVersion{ 627 Major: 1, 628 Minor: 2, 629 Build: 3, 630 }, 631 } 632 633 cmd.Force = false 634 fakeActor.DownloadExecutableBinaryFromURLReturns("some-path", nil) 635 fakeActor.CreateExecutableCopyReturns("executable-path", nil) 636 }) 637 638 When("the user chooses no", func() { 639 BeforeEach(func() { 640 _, err := input.Write([]byte("n\n")) 641 Expect(err).ToNot(HaveOccurred()) 642 }) 643 644 It("cancels plugin installation", func() { 645 Expect(executeErr).ToNot(HaveOccurred()) 646 647 Expect(testUI.Out).To(Say(`Plugin installation cancelled\.`)) 648 }) 649 }) 650 651 When("the user chooses the default", func() { 652 BeforeEach(func() { 653 _, err := input.Write([]byte("\n")) 654 Expect(err).ToNot(HaveOccurred()) 655 }) 656 657 It("cancels plugin installation", func() { 658 Expect(executeErr).ToNot(HaveOccurred()) 659 660 Expect(testUI.Out).To(Say(`Plugin installation cancelled\.`)) 661 }) 662 }) 663 664 When("the user input is invalid", func() { 665 BeforeEach(func() { 666 _, err := input.Write([]byte("e\n")) 667 Expect(err).ToNot(HaveOccurred()) 668 }) 669 670 It("returns an error", func() { 671 Expect(executeErr).To(HaveOccurred()) 672 673 Expect(testUI.Out).ToNot(Say("Installing plugin")) 674 }) 675 }) 676 677 When("the user chooses yes", func() { 678 BeforeEach(func() { 679 _, err := input.Write([]byte("y\n")) 680 Expect(err).ToNot(HaveOccurred()) 681 }) 682 683 When("the plugin is not already installed", func() { 684 BeforeEach(func() { 685 fakeActor.GetAndValidatePluginReturns(plugin, nil) 686 }) 687 688 It("installs the plugin", func() { 689 Expect(executeErr).ToNot(HaveOccurred()) 690 691 Expect(testUI.Out).To(Say(`Attention: Plugins are binaries written by potentially untrusted authors\.`)) 692 Expect(testUI.Out).To(Say(`Install and use plugins at your own risk\.`)) 693 Expect(testUI.Out).To(Say(`Do you want to install the plugin %s\? \[yN\]`, cmd.OptionalArgs.PluginNameOrLocation)) 694 Expect(testUI.Out).To(Say(`Starting download of plugin binary from URL\.\.\.`)) 695 Expect(testUI.Out).To(Say(`Installing plugin %s\.\.\.`, pluginName)) 696 Expect(testUI.Out).To(Say("OK")) 697 Expect(testUI.Out).To(Say(`Plugin %s 1\.2\.3 successfully installed\.`, pluginName)) 698 699 Expect(fakeActor.DownloadExecutableBinaryFromURLCallCount()).To(Equal(1)) 700 url, tempPluginDir, proxyReader := fakeActor.DownloadExecutableBinaryFromURLArgsForCall(0) 701 Expect(url).To(Equal(cmd.OptionalArgs.PluginNameOrLocation.String())) 702 Expect(tempPluginDir).To(ContainSubstring("some-pluginhome")) 703 Expect(tempPluginDir).To(ContainSubstring("temp")) 704 Expect(proxyReader).To(Equal(fakeProgressBar)) 705 706 Expect(fakeActor.CreateExecutableCopyCallCount()).To(Equal(1)) 707 path, tempPluginDir := fakeActor.CreateExecutableCopyArgsForCall(0) 708 Expect(path).To(Equal("some-path")) 709 Expect(tempPluginDir).To(ContainSubstring("some-pluginhome")) 710 Expect(tempPluginDir).To(ContainSubstring("temp")) 711 712 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(1)) 713 _, _, path = fakeActor.GetAndValidatePluginArgsForCall(0) 714 Expect(path).To(Equal(executablePluginPath)) 715 716 Expect(fakeConfig.GetPluginCaseInsensitiveCallCount()).To(Equal(1)) 717 Expect(fakeConfig.GetPluginCaseInsensitiveArgsForCall(0)).To(Equal(pluginName)) 718 719 Expect(fakeActor.InstallPluginFromPathCallCount()).To(Equal(1)) 720 path, installedPlugin := fakeActor.InstallPluginFromPathArgsForCall(0) 721 Expect(path).To(Equal(executablePluginPath)) 722 Expect(installedPlugin).To(Equal(plugin)) 723 724 Expect(fakeActor.UninstallPluginCallCount()).To(Equal(0)) 725 }) 726 }) 727 728 When("the plugin is already installed", func() { 729 BeforeEach(func() { 730 fakeConfig.GetPluginCaseInsensitiveReturns(configv3.Plugin{ 731 Name: "some-plugin", 732 Version: configv3.PluginVersion{ 733 Major: 1, 734 Minor: 2, 735 Build: 2, 736 }, 737 }, true) 738 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 739 Name: "some-plugin", 740 Version: configv3.PluginVersion{ 741 Major: 1, 742 Minor: 2, 743 Build: 3, 744 }, 745 }, nil) 746 }) 747 748 It("returns PluginAlreadyInstalledError", func() { 749 Expect(executeErr).To(MatchError(translatableerror.PluginAlreadyInstalledError{ 750 BinaryName: "faceman", 751 Name: pluginName, 752 Version: "1.2.3", 753 })) 754 }) 755 }) 756 }) 757 }) 758 }) 759 })