github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/cf/terminal/ui_test.go (about) 1 package terminal_test 2 3 import ( 4 "io" 5 "os" 6 "strings" 7 8 "github.com/cloudfoundry/cli/cf" 9 "github.com/cloudfoundry/cli/cf/configuration/core_config" 10 "github.com/cloudfoundry/cli/cf/i18n" 11 "github.com/cloudfoundry/cli/cf/i18n/detection" 12 "github.com/cloudfoundry/cli/cf/models" 13 testassert "github.com/cloudfoundry/cli/testhelpers/assert" 14 "github.com/cloudfoundry/cli/testhelpers/configuration" 15 testconfig "github.com/cloudfoundry/cli/testhelpers/configuration" 16 io_helpers "github.com/cloudfoundry/cli/testhelpers/io" 17 18 . "github.com/cloudfoundry/cli/cf/terminal" 19 . "github.com/cloudfoundry/cli/testhelpers/matchers" 20 . "github.com/onsi/ginkgo" 21 . "github.com/onsi/gomega" 22 ) 23 24 var _ = Describe("UI", func() { 25 26 Describe("Printing message to stdout with PrintCapturingNoOutput", func() { 27 It("prints strings without using the TeePrinter", func() { 28 bucket := &[]string{} 29 30 printer := NewTeePrinter() 31 printer.SetOutputBucket(bucket) 32 33 io_helpers.SimulateStdin("", func(reader io.Reader) { 34 output := io_helpers.CaptureOutput(func() { 35 ui := NewUI(reader, printer) 36 ui.PrintCapturingNoOutput("Hello") 37 }) 38 39 Expect("Hello").To(Equal(strings.Join(output, ""))) 40 Expect(len(*bucket)).To(Equal(0)) 41 }) 42 }) 43 }) 44 45 Describe("Printing message to stdout with Say", func() { 46 It("prints strings", func() { 47 io_helpers.SimulateStdin("", func(reader io.Reader) { 48 output := io_helpers.CaptureOutput(func() { 49 ui := NewUI(reader, NewTeePrinter()) 50 ui.Say("Hello") 51 }) 52 53 Expect("Hello").To(Equal(strings.Join(output, ""))) 54 }) 55 }) 56 57 It("prints formatted strings", func() { 58 io_helpers.SimulateStdin("", func(reader io.Reader) { 59 output := io_helpers.CaptureOutput(func() { 60 ui := NewUI(reader, NewTeePrinter()) 61 ui.Say("Hello %s", "World!") 62 }) 63 64 Expect("Hello World!").To(Equal(strings.Join(output, ""))) 65 }) 66 }) 67 68 It("does not format strings when provided no args", func() { 69 output := io_helpers.CaptureOutput(func() { 70 ui := NewUI(os.Stdin, NewTeePrinter()) 71 ui.Say("Hello %s World!") // whoops 72 }) 73 74 Expect(strings.Join(output, "")).To(Equal("Hello %s World!")) 75 }) 76 }) 77 78 Describe("Asking user for input", func() { 79 It("allows string with whitespaces", func() { 80 io_helpers.CaptureOutput(func() { 81 io_helpers.SimulateStdin("foo bar\n", func(reader io.Reader) { 82 ui := NewUI(reader, NewTeePrinter()) 83 Expect(ui.Ask("?")).To(Equal("foo bar")) 84 }) 85 }) 86 }) 87 88 It("returns empty string if an error occured while reading string", func() { 89 io_helpers.CaptureOutput(func() { 90 io_helpers.SimulateStdin("string without expected delimiter", func(reader io.Reader) { 91 ui := NewUI(reader, NewTeePrinter()) 92 Expect(ui.Ask("?")).To(Equal("")) 93 }) 94 }) 95 }) 96 97 It("always outputs the prompt, even when output is disabled", func() { 98 output := io_helpers.CaptureOutput(func() { 99 io_helpers.SimulateStdin("things are great\n", func(reader io.Reader) { 100 printer := NewTeePrinter() 101 printer.DisableTerminalOutput(true) 102 ui := NewUI(reader, printer) 103 ui.Ask("You like things?") 104 }) 105 }) 106 Expect(strings.Join(output, "")).To(ContainSubstring("You like things?")) 107 }) 108 }) 109 110 Describe("Confirming user input", func() { 111 It("treats 'y' as an affirmative confirmation", func() { 112 io_helpers.SimulateStdin("y\n", func(reader io.Reader) { 113 out := io_helpers.CaptureOutput(func() { 114 ui := NewUI(reader, NewTeePrinter()) 115 Expect(ui.Confirm("Hello %s", "World?")).To(BeTrue()) 116 }) 117 118 Expect(out).To(ContainSubstrings([]string{"Hello World?"})) 119 }) 120 }) 121 122 It("treats 'yes' as an affirmative confirmation when default language is not en_US", func() { 123 oldLang := os.Getenv("LC_ALL") 124 defer os.Setenv("LC_ALL", oldLang) 125 126 oldT := i18n.T 127 defer func() { 128 i18n.T = oldT 129 }() 130 131 os.Setenv("LC_ALL", "fr_FR") 132 133 config := configuration.NewRepositoryWithDefaults() 134 i18n.T = i18n.Init(config, &detection.JibberJabberDetector{}) 135 136 io_helpers.SimulateStdin("yes\n", func(reader io.Reader) { 137 out := io_helpers.CaptureOutput(func() { 138 ui := NewUI(reader, NewTeePrinter()) 139 Expect(ui.Confirm("Hello %s", "World?")).To(BeTrue()) 140 }) 141 Expect(out).To(ContainSubstrings([]string{"Hello World?"})) 142 }) 143 }) 144 145 It("treats 'yes' as an affirmative confirmation", func() { 146 io_helpers.SimulateStdin("yes\n", func(reader io.Reader) { 147 out := io_helpers.CaptureOutput(func() { 148 ui := NewUI(reader, NewTeePrinter()) 149 Expect(ui.Confirm("Hello %s", "World?")).To(BeTrue()) 150 }) 151 152 Expect(out).To(ContainSubstrings([]string{"Hello World?"})) 153 }) 154 }) 155 156 It("treats other input as a negative confirmation", func() { 157 io_helpers.SimulateStdin("wat\n", func(reader io.Reader) { 158 out := io_helpers.CaptureOutput(func() { 159 ui := NewUI(reader, NewTeePrinter()) 160 Expect(ui.Confirm("Hello %s", "World?")).To(BeFalse()) 161 }) 162 163 Expect(out).To(ContainSubstrings([]string{"Hello World?"})) 164 }) 165 }) 166 }) 167 168 Describe("Confirming deletion", func() { 169 It("formats a nice output string with exactly one prompt", func() { 170 io_helpers.SimulateStdin("y\n", func(reader io.Reader) { 171 out := io_helpers.CaptureOutput(func() { 172 ui := NewUI(reader, NewTeePrinter()) 173 Expect(ui.ConfirmDelete("fizzbuzz", "bizzbump")).To(BeTrue()) 174 }) 175 176 Expect(out).To(ContainSubstrings([]string{ 177 "Really delete the fizzbuzz", 178 "bizzbump", 179 "?> ", 180 })) 181 }) 182 }) 183 184 It("treats 'yes' as an affirmative confirmation", func() { 185 io_helpers.SimulateStdin("yes\n", func(reader io.Reader) { 186 out := io_helpers.CaptureOutput(func() { 187 ui := NewUI(reader, NewTeePrinter()) 188 Expect(ui.ConfirmDelete("modelType", "modelName")).To(BeTrue()) 189 }) 190 191 Expect(out).To(ContainSubstrings([]string{"modelType modelName"})) 192 }) 193 }) 194 195 It("treats other input as a negative confirmation and warns the user", func() { 196 io_helpers.SimulateStdin("wat\n", func(reader io.Reader) { 197 out := io_helpers.CaptureOutput(func() { 198 ui := NewUI(reader, NewTeePrinter()) 199 Expect(ui.ConfirmDelete("modelType", "modelName")).To(BeFalse()) 200 }) 201 202 Expect(out).To(ContainSubstrings([]string{"Delete cancelled"})) 203 }) 204 }) 205 }) 206 207 Describe("Confirming deletion with associations", func() { 208 It("warns the user that associated objects will also be deleted", func() { 209 io_helpers.SimulateStdin("wat\n", func(reader io.Reader) { 210 out := io_helpers.CaptureOutput(func() { 211 ui := NewUI(reader, NewTeePrinter()) 212 Expect(ui.ConfirmDeleteWithAssociations("modelType", "modelName")).To(BeFalse()) 213 }) 214 215 Expect(out).To(ContainSubstrings([]string{"Delete cancelled"})) 216 }) 217 }) 218 }) 219 220 Context("when user is not logged in", func() { 221 var config core_config.Reader 222 223 BeforeEach(func() { 224 config = testconfig.NewRepository() 225 }) 226 227 It("prompts the user to login", func() { 228 output := io_helpers.CaptureOutput(func() { 229 ui := NewUI(os.Stdin, NewTeePrinter()) 230 ui.ShowConfiguration(config) 231 }) 232 233 Expect(output).ToNot(ContainSubstrings([]string{"API endpoint:"})) 234 Expect(output).To(ContainSubstrings([]string{"Not logged in", "Use", "log in"})) 235 }) 236 }) 237 238 Context("when an api endpoint is set and the user logged in", func() { 239 var config core_config.ReadWriter 240 241 BeforeEach(func() { 242 accessToken := core_config.TokenInfo{ 243 UserGuid: "my-user-guid", 244 Username: "my-user", 245 Email: "my-user-email", 246 } 247 config = testconfig.NewRepositoryWithAccessToken(accessToken) 248 config.SetApiEndpoint("https://test.example.org") 249 config.SetApiVersion("☃☃☃") 250 }) 251 252 Describe("tells the user what is set in the config", func() { 253 var output []string 254 255 JustBeforeEach(func() { 256 output = io_helpers.CaptureOutput(func() { 257 ui := NewUI(os.Stdin, NewTeePrinter()) 258 ui.ShowConfiguration(config) 259 }) 260 }) 261 262 It("tells the user which api endpoint is set", func() { 263 Expect(output).To(ContainSubstrings([]string{"API endpoint:", "https://test.example.org"})) 264 }) 265 266 It("tells the user the api version", func() { 267 Expect(output).To(ContainSubstrings([]string{"API version:", "☃☃☃"})) 268 }) 269 270 It("tells the user which user is logged in", func() { 271 Expect(output).To(ContainSubstrings([]string{"User:", "my-user-email"})) 272 }) 273 274 Context("when an org is targeted", func() { 275 BeforeEach(func() { 276 config.SetOrganizationFields(models.OrganizationFields{ 277 Name: "org-name", 278 Guid: "org-guid", 279 }) 280 }) 281 282 It("tells the user which org is targeted", func() { 283 Expect(output).To(ContainSubstrings([]string{"Org:", "org-name"})) 284 }) 285 }) 286 287 Context("when a space is targeted", func() { 288 BeforeEach(func() { 289 config.SetSpaceFields(models.SpaceFields{ 290 Name: "my-space", 291 Guid: "space-guid", 292 }) 293 }) 294 295 It("tells the user which space is targeted", func() { 296 Expect(output).To(ContainSubstrings([]string{"Space:", "my-space"})) 297 }) 298 }) 299 }) 300 301 It("prompts the user to target an org and space when no org or space is targeted", func() { 302 output := io_helpers.CaptureOutput(func() { 303 ui := NewUI(os.Stdin, NewTeePrinter()) 304 ui.ShowConfiguration(config) 305 }) 306 307 Expect(output).To(ContainSubstrings([]string{"No", "org", "space", "targeted", "-o ORG", "-s SPACE"})) 308 }) 309 310 It("prompts the user to target an org when no org is targeted", func() { 311 sf := models.SpaceFields{} 312 sf.Guid = "guid" 313 sf.Name = "name" 314 315 output := io_helpers.CaptureOutput(func() { 316 ui := NewUI(os.Stdin, NewTeePrinter()) 317 ui.ShowConfiguration(config) 318 }) 319 320 Expect(output).To(ContainSubstrings([]string{"No", "org", "targeted", "-o ORG"})) 321 }) 322 323 It("prompts the user to target a space when no space is targeted", func() { 324 of := models.OrganizationFields{} 325 of.Guid = "of-guid" 326 of.Name = "of-name" 327 328 output := io_helpers.CaptureOutput(func() { 329 ui := NewUI(os.Stdin, NewTeePrinter()) 330 ui.ShowConfiguration(config) 331 }) 332 333 Expect(output).To(ContainSubstrings([]string{"No", "space", "targeted", "-s SPACE"})) 334 }) 335 }) 336 337 Describe("failing", func() { 338 It("panics with a specific string", func() { 339 io_helpers.CaptureOutput(func() { 340 testassert.AssertPanic(QuietPanic, func() { 341 NewUI(os.Stdin, NewTeePrinter()).Failed("uh oh") 342 }) 343 }) 344 }) 345 346 It("does not use 'T' func to translate when it is not initialized", func() { 347 t := i18n.T 348 i18n.T = nil 349 350 io_helpers.CaptureOutput(func() { 351 testassert.AssertPanic(QuietPanic, func() { 352 NewUI(os.Stdin, NewTeePrinter()).Failed("uh oh") 353 }) 354 }) 355 356 i18n.T = t 357 }) 358 }) 359 360 Describe("NotifyUpdateIfNeeded", func() { 361 362 var ( 363 output []string 364 config core_config.ReadWriter 365 ) 366 367 BeforeEach(func() { 368 config = testconfig.NewRepository() 369 }) 370 371 It("Prints a notification to user if current version < min cli version", func() { 372 config.SetMinCliVersion("6.0.0") 373 config.SetMinRecommendedCliVersion("6.5.0") 374 config.SetApiVersion("2.15.1") 375 cf.Version = "5.0.0" 376 output = io_helpers.CaptureOutput(func() { 377 ui := NewUI(os.Stdin, NewTeePrinter()) 378 ui.NotifyUpdateIfNeeded(config) 379 }) 380 381 Ω(output).To(ContainSubstrings([]string{"Cloud Foundry API version", 382 "requires CLI version 6.0.0", 383 "You are currently on version 5.0.0", 384 "To upgrade your CLI, please visit: https://github.com/cloudfoundry/cli#downloads", 385 })) 386 }) 387 388 It("Doesn't print a notification to user if current version >= min cli version", func() { 389 config.SetMinCliVersion("6.0.0") 390 config.SetMinRecommendedCliVersion("6.5.0") 391 config.SetApiVersion("2.15.1") 392 cf.Version = "6.0.0" 393 output = io_helpers.CaptureOutput(func() { 394 ui := NewUI(os.Stdin, NewTeePrinter()) 395 ui.NotifyUpdateIfNeeded(config) 396 }) 397 398 Ω(output[0]).To(Equal("")) 399 }) 400 }) 401 })