github.com/sleungcy/cli@v7.1.0+incompatible/integration/v7/isolated/login_command_test.go (about) 1 package isolated 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 "net/url" 9 "path/filepath" 10 "regexp" 11 12 "code.cloudfoundry.org/cli/integration/helpers" 13 "code.cloudfoundry.org/cli/util/configv3" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 . "github.com/onsi/gomega/gbytes" 17 . "github.com/onsi/gomega/gexec" 18 "github.com/onsi/gomega/ghttp" 19 ) 20 21 var _ = Describe("login command", func() { 22 BeforeEach(func() { 23 helpers.SkipIfClientCredentialsTestMode() 24 }) 25 26 Describe("Help Text", func() { 27 When("--help flag is set", func() { 28 It("displays the command usage", func() { 29 session := helpers.CF("login", "--help") 30 Eventually(session).Should(Exit(0)) 31 32 Expect(session).Should(Say("NAME:\n")) 33 Expect(session).Should(Say("login - Log user in")) 34 35 Expect(session).Should(Say("USAGE:\n")) 36 Expect(session).Should(Say(`cf login \[-a API_URL\] \[-u USERNAME\] \[-p PASSWORD\] \[-o ORG\] \[-s SPACE\] \[--sso | --sso-passcode PASSCODE\] \[--origin ORIGIN\]`)) 37 38 Expect(session).Should(Say("WARNING:\n")) 39 Expect(session).Should(Say("Providing your password as a command line option is highly discouraged\n")) 40 Expect(session).Should(Say("Your password may be visible to others and may be recorded in your shell history\n")) 41 42 Expect(session).Should(Say("EXAMPLES:\n")) 43 Expect(session).Should(Say(regexp.QuoteMeta("cf login (omit username and password to login interactively -- cf will prompt for both)"))) 44 Expect(session).Should(Say(regexp.QuoteMeta("cf login -u name@example.com -p pa55woRD (specify username and password as arguments)"))) 45 Expect(session).Should(Say(regexp.QuoteMeta("cf login -u name@example.com -p \"my password\" (use quotes for passwords with a space)"))) 46 Expect(session).Should(Say(regexp.QuoteMeta("cf login -u name@example.com -p \"\\\"password\\\"\" (escape quotes if used in password)"))) 47 Expect(session).Should(Say(regexp.QuoteMeta("cf login --sso (cf will provide a url to obtain a one-time passcode to login)"))) 48 Expect(session).Should(Say(regexp.QuoteMeta("cf login --origin ldap"))) 49 50 Expect(session).Should(Say("ALIAS:\n")) 51 Expect(session).Should(Say("l")) 52 53 Expect(session).Should(Say("OPTIONS:\n")) 54 Expect(session).Should(Say(`-a\s+API endpoint \(e.g. https://api\.example\.com\)`)) 55 Expect(session).Should(Say(`-o\s+Org`)) 56 Expect(session).Should(Say(`-p\s+Password`)) 57 Expect(session).Should(Say(`-s\s+Space`)) 58 Expect(session).Should(Say(`--skip-ssl-validation\s+Skip verification of the API endpoint\. Not recommended\!`)) 59 Expect(session).Should(Say(`--sso\s+Prompt for a one-time passcode to login`)) 60 Expect(session).Should(Say(`--sso-passcode\s+One-time passcode`)) 61 Expect(session).Should(Say(`-u\s+Username`)) 62 63 Expect(session).Should(Say("SEE ALSO:\n")) 64 Expect(session).Should(Say("api, auth, target")) 65 }) 66 }) 67 }) 68 69 Describe("API Endpoint", func() { 70 var ( 71 username string 72 password string 73 ) 74 75 When("the API endpoint is not set", func() { 76 BeforeEach(func() { 77 helpers.UnsetAPI() 78 username, password = helpers.GetCredentials() 79 }) 80 81 When("the user does not provide the -a flag", func() { 82 It("prompts the user for an endpoint", func() { 83 session := helpers.CF("login") 84 Eventually(session).Should(Say("API endpoint:")) 85 session.Interrupt() 86 Eventually(session).Should(Exit()) 87 }) 88 89 When("the API endpoint provided at the prompt is unreachable", func() { 90 It("returns an error", func() { 91 input := NewBuffer() 92 _, err := input.Write([]byte("does.not.exist\n")) 93 Expect(err).ToNot(HaveOccurred()) 94 95 session := helpers.CFWithStdin(input, "login") 96 Eventually(session).Should(Say("API endpoint:")) 97 Eventually(session).Should(Say("FAILED")) 98 Eventually(session.Err).Should(Say("Request error: ")) 99 Eventually(session.Err).Should(Say("TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection.")) 100 Eventually(session).Should(Exit(1)) 101 }) 102 }) 103 }) 104 105 When("the user provides the -a flag", func() { 106 107 When("the provided API endpoint is reachable", func() { 108 109 var session *Session 110 111 BeforeEach(func() { 112 session = helpers.CF("login", "-a", apiURL, "-u", username, "-p", password, "--skip-ssl-validation") 113 Eventually(session).Should(Say("API endpoint: %s", apiURL)) 114 Eventually(session).Should(Exit(0)) 115 }) 116 It("writes fields to the config file when targeting an API", func() { 117 rawConfig, err := ioutil.ReadFile(filepath.Join(homeDir, ".cf", "config.json")) 118 Expect(err).NotTo(HaveOccurred()) 119 120 var configFile configv3.JSONConfig 121 err = json.Unmarshal(rawConfig, &configFile) 122 Expect(err).NotTo(HaveOccurred()) 123 124 Expect(configFile.ConfigVersion).To(Equal(configv3.CurrentConfigVersion)) 125 Expect(configFile.Target).To(Equal(apiURL)) 126 Expect(configFile.APIVersion).To(MatchRegexp(`\d+\.\d+\.\d+`)) 127 Expect(configFile.AuthorizationEndpoint).ToNot(BeEmpty()) 128 Expect(configFile.DopplerEndpoint).To(MatchRegexp("^wss://")) 129 Expect(configFile.LogCacheEndpoint).To(MatchRegexp(".*log-cache.*")) 130 131 }) 132 133 It("sets the API endpoint to the provided value", func() { 134 session = helpers.CF("api") 135 Eventually(session).Should(Exit(0)) 136 Expect(session).Should(Say("API endpoint: %s", apiURL)) 137 }) 138 }) 139 140 When("the provided API endpoint is unreachable", func() { 141 It("displays an error and fails", func() { 142 session := helpers.CF("login", "-a", "does.not.exist", "--skip-ssl-validation") 143 144 Eventually(session).Should(Say("API endpoint: does.not.exist")) 145 Eventually(session).Should(Say("FAILED")) 146 Eventually(session.Err).Should(Say("Request error: ")) 147 Eventually(session.Err).Should(Say("TIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection.")) 148 Eventually(session).Should(Exit(1)) 149 }) 150 }) 151 }) 152 }) 153 154 When("the API endpoint is already set", func() { 155 It("does not prompt the user for API endpoint", func() { 156 session := helpers.CF("login") 157 Consistently(session).ShouldNot(Say("API endpoint>")) 158 session.Interrupt() 159 Eventually(session).Should(Exit()) 160 }) 161 162 When("the user provides a new API endpoint with the -a flag", func() { 163 It("attempts the new API endpoint, and does not update the API endpoint unless it succeeds", func() { 164 session := helpers.CF("login", "-a", "does.not.exist", "--skip-ssl-validation") 165 Eventually(session).Should(Say("API endpoint: does.not.exist")) 166 Eventually(session).Should(Say("FAILED")) 167 Eventually(session).Should(Exit(1)) 168 169 apiSession := helpers.CF("api") 170 Eventually(apiSession).Should(Exit(0)) 171 Eventually(apiSession).Should(Say("API endpoint: %s", apiURL)) 172 }) 173 }) 174 }) 175 }) 176 177 Describe("API URL scheme", func() { 178 When("no scheme is included in the API endpoint", func() { 179 var ( 180 hostname string 181 serverURL *url.URL 182 err error 183 session *Session 184 ) 185 186 BeforeEach(func() { 187 serverURL, err = url.Parse(helpers.GetAPI()) 188 Expect(err).NotTo(HaveOccurred()) 189 190 hostname = serverURL.Hostname() 191 username, password := helpers.GetCredentials() 192 193 session = helpers.CF("login", "-u", username, "-p", password, "-a", hostname, "--skip-ssl-validation") 194 }) 195 196 It("displays the API endpoint as https once targeted", func() { 197 Eventually(session).Should(Say("API endpoint: %s", hostname)) 198 Eventually(session).Should(Say(`API version:\s+\d\.\d{1,3}\.\d{1,3}`)) 199 Eventually(session).Should(Exit(0)) 200 }) 201 202 }) 203 204 When("the API endpoint's scheme is http", func() { 205 var httpURL string 206 207 BeforeEach(func() { 208 apiURL, err := url.Parse(helpers.GetAPI()) 209 Expect(err).NotTo(HaveOccurred()) 210 apiURL.Scheme = "http" 211 212 httpURL = apiURL.String() 213 }) 214 215 It("shows a warning to the user and logs in successfully", func() { 216 username, password := helpers.GetCredentials() 217 session := helpers.CF("login", "-u", username, "-p", password, "-a", httpURL, "--skip-ssl-validation") 218 219 Eventually(session).Should(Say("API endpoint: %s", httpURL)) 220 Eventually(session.Err).Should(Say("Warning: Insecure http API endpoint detected: secure https API endpoints are recommended")) 221 Eventually(session).Should(Exit(0)) 222 }) 223 }) 224 225 When("the API endpoint's scheme is https", func() { 226 // This test is somewhat redundant because the integration test setup will have alreayd logged in successfully with certificates at this point 227 // In the interest of test coverage however, we have decided to keep it in. 228 When("the OS provides a valid SSL Certificate (Unix: SSL_CERT_FILE or SSL_CERT_DIR Environment variables) (Windows: Import-Certificate call)", func() { 229 BeforeEach(func() { 230 if skipSSLValidation { 231 Skip("SKIP_SSL_VALIDATION is enabled") 232 } 233 }) 234 235 It("trusts the cert and allows the users to log in", func() { 236 username, password := helpers.GetCredentials() 237 session := helpers.CF("login", "-u", username, "-p", password, "-a", helpers.GetAPI()) 238 Eventually(session).Should(Say("API endpoint: %s", apiURL)) 239 Eventually(session).Should(Exit()) 240 241 session = helpers.CF("api") 242 Eventually(session).Should(Exit(0)) 243 Expect(session).Should(Say("API endpoint: %s", apiURL)) 244 }) 245 }) 246 247 When("the SSL Certificate is invalid", func() { 248 var server *ghttp.Server 249 250 BeforeEach(func() { 251 cliVersion := "1.0.0" 252 server = helpers.StartMockServerWithMinimumCLIVersion(cliVersion) 253 fakeTokenResponse := map[string]string{ 254 "access_token": "", 255 "token_type": "bearer", 256 } 257 server.RouteToHandler(http.MethodPost, "/oauth/token", 258 ghttp.RespondWithJSONEncoded(http.StatusOK, fakeTokenResponse)) 259 server.RouteToHandler(http.MethodGet, "/v3/organizations", 260 ghttp.RespondWith(http.StatusOK, `{ 261 "total_results": 0, 262 "total_pages": 1, 263 "resources": []}`)) 264 }) 265 266 AfterEach(func() { 267 server.Close() 268 }) 269 270 It("errors when --skip-ssl-validation is not provided", func() { 271 session := helpers.CF("login", "-a", server.URL()) 272 Eventually(session).Should(Say("API endpoint: %s", server.URL())) 273 Eventually(session).Should(Say("FAILED")) 274 Eventually(session.Err).Should(Say("Invalid SSL Cert for %s", server.URL())) 275 Eventually(session.Err).Should(Say("TIP: Use 'cf login --skip-ssl-validation' to continue with an insecure API endpoint")) 276 Eventually(session).Should(Exit(1)) 277 }) 278 279 It("doesn't complain about an invalid cert when we specify --skip-ssl-validation", func() { 280 session := helpers.CF("login", "-a", server.URL(), "--skip-ssl-validation") 281 Eventually(session).Should(Exit(0)) 282 283 Expect(string(session.Err.Contents())).Should(Not(ContainSubstring("Invalid SSL Cert for %s", server.URL()))) 284 }) 285 286 When("targeted with --skip-ssl-validation", func() { 287 BeforeEach(func() { 288 Eventually(helpers.CF("api", server.URL(), "--skip-ssl-validation")).Should(Exit(0)) 289 }) 290 291 When("logging in without --skip-ssl-validation", func() { 292 It("displays a helpful error message and exits 1", func() { 293 session := helpers.CF("login", "-a", server.URL()) 294 Eventually(session).Should(Say("API endpoint: %s", server.URL())) 295 Eventually(session).Should(Say("FAILED")) 296 Eventually(session.Err).Should(Say("Invalid SSL Cert for %s", server.URL())) 297 Eventually(session.Err).Should(Say("TIP: Use 'cf login --skip-ssl-validation' to continue with an insecure API endpoint")) 298 Eventually(session).Should(Exit(1)) 299 }) 300 }) 301 }) 302 }) 303 }) 304 }) 305 306 Describe("SSO", func() { 307 When("--sso-passcode is provided", func() { 308 Context("and --sso is also passed", func() { 309 It("fails with a useful error message", func() { 310 session := helpers.CF("login", "--sso-passcode", "some-passcode", "--sso") 311 Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: --sso-passcode, --sso")) 312 Eventually(session).Should(Exit(1)) 313 }) 314 }) 315 316 Context("and the provided passcode is incorrect", func() { 317 It("prompts twice, displays an error and fails", func() { 318 input := NewBuffer() 319 _, err := input.Write([]byte("bad-passcode-again\nbad-passcode-strikes-back\n")) 320 Expect(err).ToNot(HaveOccurred()) 321 session := helpers.CFWithStdin(input, "login", "--sso-passcode", "some-passcode") 322 Eventually(session).Should(Say("API endpoint:\\s+" + helpers.GetAPI())) 323 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 324 Eventually(session.Err).Should(Say(`Invalid passcode`)) 325 326 // Leaving out expectation of prompt text, since it comes from UAA (and doesn't show up on Windows) 327 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 328 Eventually(session.Err).Should(Say(`Invalid passcode`)) 329 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 330 Eventually(session.Err).Should(Say(`Invalid passcode`)) 331 Eventually(session).Should(Say(`API endpoint:\s+` + helpers.GetAPI())) 332 Eventually(session).Should(Say(`API version:\s+\d\.\d{1,3}\.\d{1,3}`)) 333 Eventually(session).Should(Say(`Not logged in. Use 'cf login' or 'cf login --sso' to log in.`)) 334 Eventually(session.Err).Should(Say(`Unable to authenticate`)) 335 Eventually(session).Should(Say(`FAILED`)) 336 337 Eventually(session).Should(Exit(1)) 338 }) 339 }) 340 341 When("a passcode isn't provided", func() { 342 It("prompts the user to try again", func() { 343 session := helpers.CF("login", "--sso-passcode") 344 Eventually(session.Err).Should(Say("Incorrect Usage: expected argument for flag `--sso-passcode'")) 345 Eventually(session).Should(Exit(1)) 346 }) 347 }) 348 }) 349 }) 350 351 Describe("Choosing the identity provider", func() { 352 When("the user provides the --origin flag", func() { 353 It("logs in successfully", func() { 354 username, password := helpers.GetCredentials() 355 session := helpers.CF("login", "-u", username, "-p", password, "--origin", "uaa") 356 Eventually(session).Should(Say("API endpoint:\\s+" + helpers.GetAPI())) 357 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 358 Eventually(session).Should(Say(`OK`)) 359 Eventually(session).Should(Say(`API endpoint:\s+` + helpers.GetAPI())) 360 Eventually(session).Should(Say(`API version:\s+\d\.\d{1,3}\.\d{1,3}`)) 361 Eventually(session).Should(Say("user:\\s+" + username)) 362 Eventually(session).Should(Exit(0)) 363 }) 364 }) 365 }) 366 367 Describe("User Credentials", func() { 368 var ( 369 username string 370 password string 371 ) 372 373 BeforeEach(func() { 374 username, password = helpers.GetCredentials() 375 }) 376 377 It("prompts the user for email and password", func() { 378 buffer := NewBuffer() 379 _, err := buffer.Write([]byte(fmt.Sprintf("%s\n%s\n", username, password))) 380 Expect(err).ToNot(HaveOccurred()) 381 session := helpers.CFWithStdin(buffer, "login") 382 Eventually(session).Should(Say("Email:")) 383 Eventually(session).Should(Say("\n")) 384 Eventually(session).Should(Say("Password:")) 385 Eventually(session).Should(Say("\n\n")) 386 Eventually(session).Should(Exit(0)) 387 }) 388 389 When("the user's account has been locked due to too many failed attempts", func() { 390 BeforeEach(func() { 391 helpers.LoginCF() 392 username, _ = helpers.CreateUser() 393 helpers.LogoutCF() 394 }) 395 396 It("displays a helpful error and does not reprompt", func() { 397 input := NewBuffer() 398 _, err := input.Write([]byte("garbage\ngarbage\ngarbage\n")) 399 Expect(err).ToNot(HaveOccurred()) 400 session := helpers.CFWithStdin(input, "login", "-u", username) 401 Eventually(session).Should(Exit(1)) 402 403 input = NewBuffer() 404 _, err = input.Write([]byte("garbage\ngarbage\ngarbage\n")) 405 Expect(err).ToNot(HaveOccurred()) 406 session = helpers.CFWithStdin(input, "login", "-u", username) 407 Eventually(session).Should(Exit(1)) 408 409 input = NewBuffer() 410 _, err = input.Write([]byte("garbage\ngarbage\ngarbage\n")) 411 Expect(err).NotTo(HaveOccurred()) 412 session = helpers.CFWithStdin(input, "login", "-u", username) 413 Eventually(session).Should(Say(`Password`)) 414 Eventually(session.Err).Should(Say(`Your account has been locked because of too many failed attempts to login\.`)) 415 Consistently(session).ShouldNot(Say(`Password`)) 416 Eventually(session.Err).Should(Say(`Unable to authenticate.`)) 417 Eventually(session).Should(Say("FAILED")) 418 Eventually(session).Should(Exit(1)) 419 }) 420 }) 421 422 When("the -u flag is provided", func() { 423 It("prompts the user for their password", func() { 424 buffer := NewBuffer() 425 _, err := buffer.Write([]byte(fmt.Sprintf("%s\n", password))) 426 Expect(err).ToNot(HaveOccurred()) 427 session := helpers.CFWithStdin(buffer, "login", "-u", username) 428 Eventually(session).Should(Say("Password: ")) 429 Eventually(session).Should(Exit(0)) 430 }) 431 }) 432 433 When("the user provides the -p flag", func() { 434 It("prompts the user for their email and logs in successfully", func() { 435 input := NewBuffer() 436 _, err := input.Write([]byte(username + "\n")) 437 Expect(err).ToNot(HaveOccurred()) 438 session := helpers.CFWithStdin(input, "login", "-p", password) 439 Eventually(session).Should(Say("Email: ")) 440 Eventually(session).Should(Exit(0)) 441 }) 442 443 When("the password flag is given incorrectly", func() { 444 It("Prompts the user two more times before exiting with an error", func() { 445 input := NewBuffer() 446 _, err := input.Write([]byte(username + "\n" + "bad-password\n" + "bad-password\n")) 447 Expect(err).ToNot(HaveOccurred()) 448 session := helpers.CFWithStdin(input, "login", "-p", "bad-password") 449 Eventually(session).Should(Say("Email: ")) 450 Eventually(session.Err).Should(Say("Credentials were rejected, please try again.")) 451 Eventually(session).Should(Say("Password: ")) 452 Eventually(session.Err).Should(Say("Credentials were rejected, please try again.")) 453 Eventually(session).Should(Say("Not logged in. Use 'cf login' or 'cf login --sso' to log in.")) 454 Eventually(session).Should(Say("FAILED")) 455 Eventually(session.Err).Should(Say("Unable to authenticate.")) 456 Eventually(session).Should(Exit(1)) 457 }) 458 }) 459 }) 460 461 When("the user provides the -p and -u flags", func() { 462 Context("and the credentials are correct", func() { 463 It("logs in successfully", func() { 464 session := helpers.CF("login", "-p", password, "-u", username) 465 Eventually(session).Should(Say("API endpoint:\\s+" + helpers.GetAPI())) 466 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 467 Eventually(session).Should(Say(`OK`)) 468 Eventually(session).Should(Say(`API endpoint:\s+` + helpers.GetAPI())) 469 Eventually(session).Should(Say(`API version:\s+\d\.\d{1,3}\.\d{1,3}`)) 470 Eventually(session).Should(Say("user:\\s+" + username)) 471 Eventually(session).Should(Exit(0)) 472 }) 473 }) 474 475 Context("and the credentials are incorrect", func() { 476 It("prompts twice, displays an error and fails", func() { 477 input := NewBuffer() 478 _, err := input.Write([]byte("garbage\ngarbage\n")) 479 Expect(err).ToNot(HaveOccurred()) 480 session := helpers.CFWithStdin(input, "login", "-p", "nope", "-u", "faker") 481 Eventually(session).Should(Say("API endpoint:\\s+" + helpers.GetAPI())) 482 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 483 Eventually(session.Err).Should(Say(`Credentials were rejected, please try again.`)) 484 Eventually(session).Should(Say(`Password:`)) 485 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 486 Eventually(session.Err).Should(Say(`Credentials were rejected, please try again.`)) 487 Eventually(session).Should(Say(`Password:`)) 488 Eventually(session).Should(Say(`Authenticating\.\.\.`)) 489 Eventually(session.Err).Should(Say(`Credentials were rejected, please try again.`)) 490 Eventually(session).Should(Say(`API endpoint:\s+` + helpers.GetAPI())) 491 Eventually(session).Should(Say(`API version:\s+\d\.\d{1,3}\.\d{1,3}`)) 492 Eventually(session).Should(Say(`Not logged in. Use 'cf login' or 'cf login --sso' to log in.`)) 493 Eventually(session.Err).Should(Say(`Unable to authenticate.`)) 494 Eventually(session).Should(Say(`FAILED`)) 495 496 Eventually(session).Should(Exit(1)) 497 }) 498 499 Context("and the user was previously logged in", func() { 500 BeforeEach(func() { 501 helpers.LoginCF() 502 }) 503 504 It("logs them out", func() { 505 session := helpers.CF("login", "-p", "nope", "-u", "faker") 506 Eventually(session).Should(Say(`Not logged in. Use 'cf login' or 'cf login --sso' to log in.`)) 507 Eventually(session).Should(Exit()) 508 509 orgsSession := helpers.CF("orgs") 510 Eventually(orgsSession.Err).Should(Say(`Not logged in. Use 'cf login' or 'cf login --sso' to log in.`)) 511 Eventually(orgsSession).Should(Exit()) 512 }) 513 }) 514 }) 515 }) 516 517 When("MFA is enabled", func() { 518 var ( 519 mfaCode string 520 server *ghttp.Server 521 ) 522 523 BeforeEach(func() { 524 password = "some-password" 525 mfaCode = "123456" 526 server = helpers.StartAndTargetMockServerWithAPIVersions(helpers.DefaultV2Version, helpers.DefaultV3Version) 527 helpers.AddMfa(server, password, mfaCode) 528 }) 529 530 AfterEach(func() { 531 server.Close() 532 }) 533 534 When("correct MFA code and credentials are provided", func() { 535 BeforeEach(func() { 536 fakeTokenResponse := map[string]string{ 537 "access_token": "", 538 "token_type": "bearer", 539 } 540 server.RouteToHandler(http.MethodPost, "/oauth/token", 541 ghttp.RespondWithJSONEncoded(http.StatusOK, fakeTokenResponse)) 542 server.RouteToHandler(http.MethodGet, "/v3/organizations", 543 ghttp.RespondWith(http.StatusOK, `{ 544 "total_results": 0, 545 "total_pages": 1, 546 "resources": []}`)) 547 }) 548 549 It("logs in the user", func() { 550 input := NewBuffer() 551 _, err := input.Write([]byte(username + "\n" + password + "\n" + mfaCode + "\n")) 552 Expect(err).ToNot(HaveOccurred()) 553 session := helpers.CFWithStdin(input, "login") 554 Eventually(session).Should(Say("Email: ")) 555 Eventually(session).Should(Say("\n")) 556 Eventually(session).Should(Say("Password:")) 557 Eventually(session).Should(Say("\n")) 558 Eventually(session).Should(Say("MFA Code \\( Register at %[1]s \\)", server.URL())) 559 Eventually(session).Should(Exit(0)) 560 }) 561 }) 562 563 When("incorrect MFA code and credentials are provided", func() { 564 It("fails", func() { 565 input := NewBuffer() 566 wrongMfaCode := mfaCode + "foo" 567 _, err := input.Write([]byte(username + "\n" + password + "\n" + wrongMfaCode + "\n" + password + "\n" + wrongMfaCode + "\n")) 568 Expect(err).ToNot(HaveOccurred()) 569 session := helpers.CFWithStdin(input, "login") 570 Eventually(session).Should(Say("Password: ")) 571 Eventually(session).Should(Say("MFA Code \\( Register at %[1]s \\)", server.URL())) 572 Eventually(session).Should(Say("Password: ")) 573 Eventually(session).Should(Say("MFA Code \\( Register at %[1]s \\)", server.URL())) 574 Eventually(session).Should(Say("Not logged in. Use 'cf login' or 'cf login --sso' to log in.")) 575 Eventually(session).Should(Say("FAILED")) 576 Eventually(session.Err).Should(Say("Unable to authenticate.")) 577 578 Eventually(session).Should(Exit(1)) 579 }) 580 }) 581 }) 582 }) 583 584 Describe("Client Credentials", func() { 585 var ( 586 username string 587 password string 588 clientID string 589 clientSecret string 590 ) 591 592 When("the user has manually added client credentials to the config file", func() { 593 BeforeEach(func() { 594 clientID, clientSecret = helpers.SkipIfCustomClientCredentialsNotSet() 595 username, password = helpers.GetCredentials() 596 helpers.SetConfig(func(config *configv3.Config) { 597 config.ConfigFile.UAAOAuthClient = clientID 598 config.ConfigFile.UAAOAuthClientSecret = clientSecret 599 config.ConfigFile.UAAGrantType = "" 600 }) 601 }) 602 603 It("returns an unsupported error", func() { 604 errorMessage := "Error: Support for manually writing your client credentials to config.json has been removed. For similar functionality please use `cf auth --client-credentials`." 605 606 session := helpers.CF("login", "-u", username, "-p", password) 607 Eventually(session.Err).Should(Say(errorMessage)) 608 Eventually(session).Should(Exit(1)) 609 }) 610 }) 611 612 When("already logged in with client credentials", func() { 613 BeforeEach(func() { 614 clientID, clientSecret = helpers.SkipIfClientCredentialsNotSet() 615 username, password = helpers.GetCredentials() 616 617 session := helpers.CF("auth", clientID, clientSecret, "--client-credentials") 618 Eventually(session).Should(Exit(0)) 619 }) 620 621 It("should fail log in and display an error informing the user they need to log out", func() { 622 session := helpers.CF("login", "-p", password, "-u", username) 623 Eventually(session).Should(Say("FAILED")) 624 Eventually(session.Err).Should(Say("Service account currently logged in. Use 'cf logout' to log out service account and try again.")) 625 Eventually(session).Should(Exit(1)) 626 627 //And I am still logged in 628 targetSession := helpers.CF("target") 629 Eventually(targetSession).Should(Exit(0)) 630 }) 631 }) 632 }) 633 634 Describe("Target Organization", func() { 635 var ( 636 orgName string 637 username string 638 password string 639 ) 640 641 BeforeEach(func() { 642 helpers.LoginCF() 643 orgName = helpers.NewOrgName() 644 session := helpers.CF("create-org", orgName) 645 Eventually(session).Should(Exit(0)) 646 username, password = helpers.CreateUserInOrgRole(orgName, "OrgManager") 647 }) 648 649 When("there is only one org available to the user", func() { 650 It("logs the user in and targets the organization automatically", func() { 651 session := helpers.CF("login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 652 Eventually(session).Should(Exit(0)) 653 654 targetSession := helpers.CF("target") 655 Eventually(targetSession).Should(Exit(0)) 656 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 657 }) 658 }) 659 660 When("the -o flag is not passed", func() { 661 When("there are multiple orgs available to the user", func() { 662 BeforeEach(func() { 663 orgName = helpers.NewOrgName() 664 createOrgSession := helpers.CF("create-org", orgName) 665 Eventually(createOrgSession).Should(Exit(0)) 666 setOrgRoleSession := helpers.CF("set-org-role", username, orgName, "OrgManager") 667 Eventually(setOrgRoleSession).Should(Exit(0)) 668 }) 669 670 When("there are more than 50 orgs", func() { 671 var server *ghttp.Server 672 673 BeforeEach(func() { 674 server = helpers.StartAndTargetMockServerWithAPIVersions(helpers.DefaultV2Version, helpers.DefaultV3Version) 675 helpers.AddLoginRoutes(server) 676 helpers.AddFiftyOneOrgs(server) 677 // handle request for spaces under "org20" 678 helpers.AddEmptyPaginatedResponse(server, "/v3/spaces?order_by=name&organization_guids=f6653aac-938e-4469-9a66-56a02796412b") 679 }) 680 681 AfterEach(func() { 682 server.Close() 683 }) 684 685 It("displays a message and prompts the user for the org name", func() { 686 input := NewBuffer() 687 _, wErr := input.Write([]byte(fmt.Sprintf("%s\n", "org20"))) // "org20" is one of the orgs in the test fixture 688 Expect(wErr).ToNot(HaveOccurred()) 689 690 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "--skip-ssl-validation") 691 692 Eventually(session).Should(Say("Select an org:")) 693 Eventually(session).Should(Say("There are too many options to display; please type in the name.")) 694 Eventually(session).Should(Say("\n\n")) 695 Eventually(session).Should(Say(regexp.QuoteMeta(`Org (enter to skip):`))) 696 Eventually(session).Should(Say(`Targeted org org20\.`)) 697 698 Eventually(session).Should(Exit(0)) 699 }) 700 }) 701 702 When("user selects an organization by using numbered list", func() { 703 It("prompts the user for org and targets the selected org", func() { 704 input := NewBuffer() 705 _, err := input.Write([]byte("1\n")) 706 Expect(err).ToNot(HaveOccurred()) 707 708 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 709 Eventually(session).Should(Exit(0)) 710 711 re := regexp.MustCompile("1\\. (?P<OrgName>.*)\n") 712 matches := re.FindStringSubmatch(string(session.Out.Contents())) 713 Expect(matches).To(HaveLen((2))) 714 expectedOrgName := matches[1] 715 716 targetSession := helpers.CF("target") 717 Eventually(targetSession).Should(Exit(0)) 718 Eventually(targetSession).Should(Say(`org:\s+%s`, expectedOrgName)) 719 }) 720 721 When("the user selects a number greater than the number of orgs", func() { 722 It("prompts the user until a valid number is entered", func() { 723 input := NewBuffer() 724 _, err := input.Write([]byte("3\n")) 725 Expect(err).ToNot(HaveOccurred()) 726 727 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password) 728 729 Eventually(session).Should(Say(regexp.QuoteMeta("Select an org:"))) 730 Eventually(session).Should(Say(regexp.QuoteMeta(`Org (enter to skip):`))) 731 Eventually(session).Should(Say(regexp.QuoteMeta(`Org (enter to skip):`))) 732 733 session.Interrupt() 734 Eventually(session).Should(Exit()) 735 }) 736 }) 737 }) 738 739 When("user selects an organization by org name", func() { 740 It("prompts the user for an org and then targets the selected org", func() { 741 input := NewBuffer() 742 _, err := input.Write([]byte(fmt.Sprintf("%s\n", orgName))) 743 Expect(err).ToNot(HaveOccurred()) 744 745 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 746 Eventually(session).Should(Say(`\d\. %s`, orgName)) 747 Eventually(session).Should(Exit(0)) 748 749 targetSession := helpers.CF("target") 750 Eventually(targetSession).Should(Exit(0)) 751 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 752 }) 753 }) 754 755 When("user does not select an organization", func() { 756 It("succesfully logs in but does not target any org", func() { 757 input := NewBuffer() 758 _, err := input.Write([]byte("\n")) 759 Expect(err).ToNot(HaveOccurred()) 760 761 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 762 Eventually(session).Should(Say(`Org \(enter to skip\):`)) 763 Consistently(session).ShouldNot(Say(`Org \(enter to skip\):`)) 764 Eventually(session).Should(Exit(0)) 765 766 targetSession := helpers.CF("target") 767 Eventually(targetSession).Should(Exit(0)) 768 Eventually(targetSession).Should(Say("No org or space targeted, use 'cf target -o ORG -s SPACE'")) 769 }) 770 }) 771 772 When("the user enters an invalid organization at the prompt", func() { 773 It("displays an error message and does not target the org", func() { 774 orgName = "invalid-org" 775 input := NewBuffer() 776 _, err := input.Write([]byte(fmt.Sprintf("%s\n", orgName))) 777 Expect(err).ToNot(HaveOccurred()) 778 779 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "--skip-ssl-validation") 780 Eventually(session).Should(Exit(1)) 781 Eventually(session).Should(Say("FAILED")) 782 Eventually(session.Err).Should(Say("Organization '%s' not found", orgName)) 783 784 targetSession := helpers.CF("target") 785 Eventually(targetSession).Should(Exit(0)) 786 Eventually(targetSession).Should(Say(`user:\s+%s`, username)) 787 Eventually(targetSession).ShouldNot(Say(`org:\s+%s`, orgName)) 788 Eventually(targetSession).Should(Say("No org or space targeted, use 'cf target -o ORG -s SPACE'")) 789 }) 790 }) 791 }) 792 }) 793 794 When("the -o flag is not passed, and the -s flag is passed", func() { 795 var ( 796 spaceName string 797 secondOrgName string 798 thirdOrgName string 799 ) 800 801 BeforeEach(func() { 802 orgName = helpers.NewOrgName() 803 createOrgSession := helpers.CF("create-org", orgName) 804 Eventually(createOrgSession).Should(Exit(0)) 805 setOrgRoleSession := helpers.CF("set-org-role", username, orgName, "OrgManager") 806 Eventually(setOrgRoleSession).Should(Exit(0)) 807 spaceName = helpers.NewSpaceName() 808 createSpaceSession := helpers.CF("create-space", "-o", orgName, spaceName) 809 Eventually(createSpaceSession).Should(Exit(0)) 810 roleSession := helpers.CF("set-space-role", username, orgName, spaceName, "SpaceManager") 811 Eventually(roleSession).Should(Exit(0)) 812 813 secondOrgName = helpers.NewOrgName() 814 createOrgSession = helpers.CF("create-org", secondOrgName) 815 Eventually(createOrgSession).Should(Exit(0)) 816 setOrgRoleSession = helpers.CF("set-org-role", username, secondOrgName, "OrgManager") 817 Eventually(setOrgRoleSession).Should(Exit(0)) 818 secondSpaceName := helpers.NewSpaceName() 819 createSpaceSession = helpers.CF("create-space", "-o", secondOrgName, secondSpaceName) 820 Eventually(createSpaceSession).Should(Exit(0)) 821 roleSession = helpers.CF("set-space-role", username, secondOrgName, secondSpaceName, "SpaceManager") 822 Eventually(roleSession).Should(Exit(0)) 823 }) 824 825 Context("only one org has a correctly named space", func() { 826 It("automatically targets the org associated with the space", func() { 827 session := helpers.CF("login", "-u", username, "-p", password, "-s", spaceName, "-a", apiURL, "--skip-ssl-validation") 828 Eventually(session).Should(Exit(0)) 829 830 targetSession := helpers.CF("target") 831 Eventually(targetSession).Should(Exit(0)) 832 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 833 Eventually(targetSession).Should(Say(`space:\s+%s`, spaceName)) 834 }) 835 }) 836 837 Context("multiple orgs have the correctly named space", func() { 838 BeforeEach(func() { 839 thirdOrgName = helpers.NewOrgName() 840 createOrgSession := helpers.CF("create-org", thirdOrgName) 841 Eventually(createOrgSession).Should(Exit(0)) 842 setOrgRoleSession := helpers.CF("set-org-role", username, thirdOrgName, "OrgManager") 843 Eventually(setOrgRoleSession).Should(Exit(0)) 844 createSpaceSession := helpers.CF("create-space", "-o", thirdOrgName, spaceName) 845 Eventually(createSpaceSession).Should(Exit(0)) 846 roleSession := helpers.CF("set-space-role", username, thirdOrgName, spaceName, "SpaceManager") 847 Eventually(roleSession).Should(Exit(0)) 848 }) 849 850 It("prompts the user to select from the matching orgs", func() { 851 input := NewBuffer() 852 _, err := input.Write([]byte("1\n")) 853 Expect(err).ToNot(HaveOccurred()) 854 855 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-s", spaceName, "-a", apiURL, "--skip-ssl-validation") 856 Eventually(session).Should(Exit(0)) 857 858 re := regexp.MustCompile("[0-9]+\\. (?P<OrgName>.*)") 859 matches := re.FindStringSubmatch(string(session.Out.Contents())) 860 Expect(matches).To(HaveLen((2))) 861 expectedOrgName := matches[1] 862 863 targetSession := helpers.CF("target") 864 Eventually(targetSession).Should(Exit(0)) 865 Eventually(targetSession).Should(Say(`org:\s+%s`, expectedOrgName)) 866 Eventually(targetSession).Should(Say(`space:\s+%s`, spaceName)) 867 }) 868 869 When("the user enters an organization that doesn't contain the space at the prompt", func() { 870 It("targets the org, then displays an error message and does not target the space", func() { 871 input := NewBuffer() 872 _, err := input.Write([]byte(fmt.Sprintf("%s\n", secondOrgName))) 873 Expect(err).ToNot(HaveOccurred()) 874 875 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-s", spaceName, "-a", apiURL, "--skip-ssl-validation") 876 877 Eventually(session).Should(Exit(1)) 878 Eventually(session).Should(Say("FAILED")) 879 Eventually(session.Err).Should(Say("Organization '%s' containing space '%s' not found.", secondOrgName, spaceName)) 880 881 targetSession := helpers.CF("target") 882 Eventually(targetSession).Should(Exit(0)) 883 Eventually(targetSession).Should(Say(`user:\s+%s`, username)) 884 Eventually(targetSession).ShouldNot(Say(`org:\s+%s`, orgName)) 885 Eventually(targetSession).Should(Say("No org or space targeted, use 'cf target -o ORG -s SPACE'")) 886 }) 887 }) 888 }) 889 }) 890 891 When("the -o flag is passed", func() { 892 BeforeEach(func() { 893 helpers.LogoutCF() 894 }) 895 896 When("the organization is valid", func() { 897 It("targets the organization that was passed as an argument", func() { 898 session := helpers.CF("login", "-u", username, "-p", password, "-o", orgName) 899 900 Eventually(session).Should(Exit(0)) 901 Eventually(session).Should(Say(`org:\s+%s`, orgName)) 902 903 targetSession := helpers.CF("target") 904 Eventually(targetSession).Should(Exit(0)) 905 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 906 }) 907 }) 908 909 When("the organization is invalid", func() { 910 It("logs in the user, displays an error message, and does not target any organization", func() { 911 orgName = "invalid-org" 912 session := helpers.CF("login", "-u", username, "-p", password, "-o", orgName) 913 914 Eventually(session).Should(Exit(1)) 915 Eventually(session).Should(Say("FAILED")) 916 Eventually(session.Err).Should(Say("Organization '%s' not found", orgName)) 917 918 targetSession := helpers.CF("target") 919 Eventually(targetSession).Should(Exit(0)) 920 Eventually(targetSession).Should(Say(`user:\s+%s`, username)) 921 Eventually(targetSession).ShouldNot(Say(`org:\s+%s`, orgName)) 922 Eventually(targetSession).Should(Say("No org or space targeted, use 'cf target -o ORG -s SPACE'")) 923 }) 924 }) 925 }) 926 }) 927 928 Describe("Target Space", func() { 929 var ( 930 orgName string 931 username string 932 password string 933 ) 934 935 BeforeEach(func() { 936 helpers.LoginCF() 937 orgName = helpers.NewOrgName() 938 session := helpers.CF("create-org", orgName) 939 Eventually(session).Should(Exit(0)) 940 username, password = helpers.CreateUser() 941 }) 942 943 When("only one space is available to the user", func() { 944 var spaceName string 945 946 BeforeEach(func() { 947 spaceName = helpers.NewSpaceName() 948 session := helpers.CF("create-space", "-o", orgName, spaceName) 949 Eventually(session).Should(Exit(0)) 950 roleSession := helpers.CF("set-space-role", username, orgName, spaceName, "SpaceManager") 951 Eventually(roleSession).Should(Exit(0)) 952 }) 953 954 It("logs the user in and targets the org and the space", func() { 955 session := helpers.CF("login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 956 Eventually(session).Should(Exit(0)) 957 958 targetSession := helpers.CF("target") 959 Eventually(targetSession).Should(Exit(0)) 960 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 961 Eventually(targetSession).Should(Say(`space:\s+%s`, spaceName)) 962 }) 963 }) 964 965 When("multiple spaces are available to the user", func() { 966 var ( 967 spaceName string 968 spaceName2 string 969 ) 970 971 BeforeEach(func() { 972 spaceName = helpers.NewSpaceName() 973 session := helpers.CF("create-space", "-o", orgName, spaceName) 974 Eventually(session).Should(Exit(0)) 975 roleSession := helpers.CF("set-space-role", username, orgName, spaceName, "SpaceManager") 976 Eventually(roleSession).Should(Exit(0)) 977 978 spaceName2 = helpers.NewSpaceName() 979 session2 := helpers.CF("create-space", "-o", orgName, spaceName2) 980 Eventually(session2).Should(Exit(0)) 981 roleSession2 := helpers.CF("set-space-role", username, orgName, spaceName2, "SpaceManager") 982 Eventually(roleSession2).Should(Exit(0)) 983 }) 984 985 When("the -s flag is passed", func() { 986 BeforeEach(func() { 987 orgName2 := helpers.NewOrgName() 988 session := helpers.CF("create-org", orgName2) 989 Eventually(session).Should(Exit(0)) 990 session = helpers.CF("set-org-role", username, orgName2, "OrgManager") 991 Eventually(session).Should(Exit(0)) 992 }) 993 994 It("targets the org and the space", func() { 995 stdin := NewBuffer() 996 _, writeErr := stdin.Write([]byte(orgName + "\n")) 997 Expect(writeErr).ToNot(HaveOccurred()) 998 session := helpers.CFWithStdin(stdin, "login", "-u", username, "-p", password, "-a", apiURL, "-s", spaceName, "--skip-ssl-validation") 999 1000 Eventually(session).Should(Say(`Targeted org\s+%s\.`, orgName)) 1001 Eventually(session).Should(Say(`\nTargeted space\s+%s\.`, spaceName)) 1002 1003 Eventually(session).Should(Say(`org:\s+%s`, orgName)) 1004 Eventually(session).Should(Say(`space:\s+%s`, spaceName)) 1005 Eventually(session).Should(Exit(0)) 1006 1007 sessionOutput := string(session.Out.Contents()) 1008 Expect(sessionOutput).To(MatchRegexp(`\S\nAPI`)) 1009 1010 targetSession := helpers.CF("target") 1011 Eventually(targetSession).Should(Exit(0)) 1012 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 1013 Eventually(targetSession).Should(Say(`space:\s+%s`, spaceName)) 1014 }) 1015 1016 When("the space name is invalid", func() { 1017 BeforeEach(func() { 1018 spaceName = "invalid-space-name" 1019 }) 1020 1021 It("the command fails and displays an error message. It targets the org but not the space.", func() { 1022 stdin := NewBuffer() 1023 _, writeErr := stdin.Write([]byte(orgName + "\n")) 1024 Expect(writeErr).ToNot(HaveOccurred()) 1025 session := helpers.CFWithStdin(stdin, "login", "-u", username, "-p", password, "-a", apiURL, "-o", orgName, "-s", spaceName, "--skip-ssl-validation") 1026 Eventually(session).Should(Exit(1)) 1027 Eventually(session).Should(Say("FAILED")) 1028 Eventually(session.Err).Should(Say("Space '%s' not found", spaceName)) 1029 1030 targetSession := helpers.CF("target") 1031 Eventually(targetSession).Should(Exit(0)) 1032 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 1033 Eventually(targetSession).Should(Say("No space targeted, use 'cf target -s SPACE'")) 1034 }) 1035 }) 1036 }) 1037 1038 When("the -s flag is not passed", func() { 1039 It("prompts the user to pick their space by list position", func() { 1040 input := NewBuffer() 1041 _, err := input.Write([]byte("1\n")) 1042 Expect(err).ToNot(HaveOccurred()) 1043 1044 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 1045 Eventually(session).Should(Exit(0)) 1046 1047 re := regexp.MustCompile("1\\. (?P<SpaceName>.*)\n") 1048 submatches := re.FindStringSubmatch(string(session.Out.Contents())) 1049 Expect(submatches).ToNot(BeEmpty(), "missing numbered space list") 1050 expectedSpaceName := submatches[1] 1051 1052 targetSession := helpers.CF("target") 1053 Eventually(targetSession).Should(Exit(0)) 1054 Eventually(targetSession).Should(Say(`space:\s+%s`, expectedSpaceName)) 1055 }) 1056 1057 It("reprompts the user if an invalid number is entered", func() { 1058 input := NewBuffer() 1059 _, err := input.Write([]byte("4\n")) 1060 Expect(err).ToNot(HaveOccurred()) 1061 1062 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 1063 Eventually(session).Should(Say(regexp.QuoteMeta("Space (enter to skip):"))) 1064 Eventually(session).Should(Say(regexp.QuoteMeta("Space (enter to skip):"))) 1065 session.Interrupt() 1066 Eventually(session).Should(Exit()) 1067 }) 1068 1069 It("allows the user to pick their space by name", func() { 1070 input := NewBuffer() 1071 _, err := input.Write([]byte(spaceName + "\n")) 1072 Expect(err).ToNot(HaveOccurred()) 1073 1074 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 1075 Eventually(session).Should(Exit(0)) 1076 1077 targetSession := helpers.CF("target") 1078 Eventually(targetSession).Should(Exit(0)) 1079 Eventually(targetSession).Should(Say(`space:\s+%s`, spaceName)) 1080 }) 1081 1082 It("allows the user to skip picking a space", func() { 1083 input := NewBuffer() 1084 _, err := input.Write([]byte("\n")) 1085 Expect(err).ToNot(HaveOccurred()) 1086 1087 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 1088 Eventually(session).Should(Exit(0)) 1089 1090 targetSession := helpers.CF("target") 1091 Eventually(targetSession).Should(Exit(0)) 1092 Eventually(targetSession).Should(Say(`No space targeted, use 'cf target -s SPACE'`)) 1093 }) 1094 1095 When("the input space name is invalid", func() { 1096 BeforeEach(func() { 1097 spaceName = "invalid-space-name" 1098 }) 1099 1100 It("the command fails and displays an error message. It does not target the space.", func() { 1101 input := NewBuffer() 1102 _, err := input.Write([]byte(spaceName + "\n")) 1103 Expect(err).ToNot(HaveOccurred()) 1104 1105 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "-a", apiURL, "--skip-ssl-validation") 1106 Eventually(session).Should(Exit(1)) 1107 Eventually(session).Should(Say("FAILED")) 1108 Eventually(session.Err).Should(Say("Space '%s' not found", spaceName)) 1109 1110 targetSession := helpers.CF("target") 1111 Eventually(targetSession).Should(Exit(0)) 1112 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName)) 1113 Eventually(targetSession).Should(Say("No space targeted, use 'cf target -s SPACE'")) 1114 }) 1115 }) 1116 1117 When("there are more than 50 spaces", func() { 1118 var server *ghttp.Server 1119 BeforeEach(func() { 1120 server = helpers.StartAndTargetMockServerWithAPIVersions(helpers.DefaultV2Version, helpers.DefaultV3Version) 1121 helpers.AddLoginRoutes(server) 1122 helpers.AddFiftyOneSpaces(server) 1123 }) 1124 1125 AfterEach(func() { 1126 server.Close() 1127 }) 1128 1129 It("displays a message and prompts the user for the space name", func() { 1130 input := NewBuffer() 1131 _, wErr := input.Write([]byte(fmt.Sprintf("%s\n", "test-space-1"))) 1132 Expect(wErr).ToNot(HaveOccurred()) 1133 1134 session := helpers.CFWithStdin(input, "login", "-u", username, "-p", password, "--skip-ssl-validation") 1135 1136 Eventually(session).Should(Say("Select a space:")) 1137 Eventually(session).Should(Say("There are too many options to display; please type in the name.")) 1138 Eventually(session).Should(Say("\n\n")) 1139 Eventually(session).Should(Say(regexp.QuoteMeta(`Space (enter to skip):`))) 1140 Eventually(session).Should(Say(`Targeted space test-space-1\.`)) 1141 1142 Eventually(session).Should(Exit(0)) 1143 }) 1144 }) 1145 }) 1146 }) 1147 }) 1148 1149 Describe("Full interactive happy path", func() { 1150 var ( 1151 orgName1 string 1152 orgName2 string 1153 spaceName1 string 1154 spaceName2 string 1155 username string 1156 password string 1157 ) 1158 1159 BeforeEach(func() { 1160 helpers.LoginCF() 1161 orgName1 = helpers.NewOrgName() 1162 orgName2 = helpers.NewOrgName() 1163 spaceName1 = helpers.NewSpaceName() 1164 spaceName2 = helpers.NewSpaceName() 1165 1166 Eventually(helpers.CF("create-org", orgName1)).Should(Exit(0)) 1167 Eventually(helpers.CF("create-org", orgName2)).Should(Exit(0)) 1168 Eventually(helpers.CF("create-space", "-o", orgName1, spaceName1)).Should(Exit(0)) 1169 Eventually(helpers.CF("create-space", "-o", orgName1, spaceName2)).Should(Exit(0)) 1170 1171 username, password = helpers.CreateUser() 1172 Eventually(helpers.CF("set-org-role", username, orgName1, "OrgManager")).Should(Exit(0)) 1173 Eventually(helpers.CF("set-org-role", username, orgName2, "OrgManager")).Should(Exit(0)) 1174 Eventually(helpers.CF("set-space-role", username, orgName1, spaceName1, "SpaceManager")).Should(Exit(0)) 1175 Eventually(helpers.CF("set-space-role", username, orgName1, spaceName2, "SpaceManager")).Should(Exit(0)) 1176 1177 helpers.UnsetAPI() 1178 }) 1179 1180 When("there are multiple orgs and spaces available to a user", func() { 1181 It("prompts for username, password, org, and space. Then logs in and targets correctly", func() { 1182 buffer := NewBuffer() 1183 _, err := buffer.Write([]byte(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", apiURL, username, password, orgName1, spaceName2))) 1184 Expect(err).ToNot(HaveOccurred()) 1185 1186 session := helpers.CFWithStdin(buffer, "login", "--skip-ssl-validation") 1187 Eventually(session).Should(Say("API endpoint:")) 1188 Eventually(session).Should(Say("\n")) 1189 Eventually(session).Should(Say("Email:")) 1190 Eventually(session).Should(Say("\n")) 1191 Eventually(session).Should(Say("Password:")) 1192 Eventually(session).Should(Say("OK")) 1193 Eventually(session).Should(Say("\n\n")) 1194 Eventually(session).Should(Say("Select an org:")) 1195 Eventually(session).Should(Say("\n\n")) 1196 Eventually(session).Should(Say(regexp.QuoteMeta(`Org (enter to skip):`))) 1197 Eventually(session).Should(Say(fmt.Sprintf("Targeted org %s", orgName1))) 1198 Eventually(session).Should(Say("\n\n")) 1199 Eventually(session).Should(Say("Select a space:")) 1200 Eventually(session).Should(Say("\n\n")) 1201 Eventually(session).Should(Say(regexp.QuoteMeta(`Space (enter to skip):`))) 1202 Eventually(session).Should(Say(fmt.Sprintf(`Targeted space %s\.`, spaceName2))) 1203 Eventually(session).Should(Say("\n\n")) 1204 Eventually(session).Should(Say(`org:\s+%s`, orgName1)) 1205 Eventually(session).Should(Say(`space:\s+%s`, spaceName2)) 1206 Eventually(session).Should(Exit(0)) 1207 1208 targetSession := helpers.CF("target") 1209 Eventually(targetSession).Should(Exit(0)) 1210 Eventually(targetSession).Should(Say(`org:\s+%s`, orgName1)) 1211 Eventually(targetSession).Should(Say(`space:\s+%s`, spaceName2)) 1212 }) 1213 }) 1214 }) 1215 })