github.com/saucelabs/saucectl@v0.175.1/internal/cmd/ini/initializer_test.go (about) 1 package ini 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "fmt" 8 "os" 9 "reflect" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/saucelabs/saucectl/internal/flags" 15 "github.com/saucelabs/saucectl/internal/iam" 16 "github.com/saucelabs/saucectl/internal/imagerunner" 17 "github.com/saucelabs/saucectl/internal/msg" 18 "github.com/spf13/pflag" 19 20 "github.com/AlecAivazis/survey/v2/terminal" 21 "github.com/Netflix/go-expect" 22 "github.com/hinshun/vt10x" 23 "github.com/stretchr/testify/require" 24 "gotest.tools/v3/fs" 25 26 "github.com/saucelabs/saucectl/internal/config" 27 "github.com/saucelabs/saucectl/internal/cypress" 28 "github.com/saucelabs/saucectl/internal/devices" 29 "github.com/saucelabs/saucectl/internal/espresso" 30 "github.com/saucelabs/saucectl/internal/framework" 31 "github.com/saucelabs/saucectl/internal/mocks" 32 "github.com/saucelabs/saucectl/internal/playwright" 33 "github.com/saucelabs/saucectl/internal/region" 34 "github.com/saucelabs/saucectl/internal/testcafe" 35 "github.com/saucelabs/saucectl/internal/vmd" 36 "github.com/saucelabs/saucectl/internal/xcuitest" 37 ) 38 39 // Test Case setup is partially reused from: 40 // - https://github.com/AlecAivazis/survey/blob/master/survey_test.go 41 // - https://github.com/AlecAivazis/survey/blob/master/survey_posix_test.go 42 43 // As everything related to console may result in hanging, it's preferable 44 // to add a timeout to avoid any test to stay for ages. 45 func executeQuestionTestWithTimeout(t *testing.T, test questionTest) { 46 timeout := time.After(2 * time.Second) 47 done := make(chan bool) 48 49 go func() { 50 executeQuestionTest(t, test) 51 done <- true 52 }() 53 54 select { 55 case <-timeout: 56 t.Fatal("Test timed-out") 57 case <-done: 58 } 59 } 60 61 func executeQuestionTest(t *testing.T, test questionTest) { 62 buf := new(bytes.Buffer) 63 c, state, err := vt10x.NewVT10XConsole(expect.WithStdout(buf)) 64 require.Nil(t, err) 65 defer c.Close() 66 67 donec := make(chan struct{}) 68 go func() { 69 defer close(donec) 70 if lerr := test.procedure(c); lerr != nil { 71 if lerr.Error() != "read /dev/ptmx: input/output error" { 72 t.Errorf("error: %v", lerr) 73 } 74 } 75 }() 76 77 test.ini.stdio = terminal.Stdio{In: c.Tty(), Out: c.Tty(), Err: c.Tty()} 78 err = test.execution(test.ini, test.ini.cfg) 79 require.Nil(t, err) 80 81 if !reflect.DeepEqual(test.ini.cfg, test.expectedState) { 82 t.Errorf("got: %v, want: %v", test.ini.cfg, test.expectedState) 83 } 84 85 // Close the slave end of the pty, and read the remaining bytes from the master end. 86 c.Tty().Close() 87 <-donec 88 89 t.Logf("Raw output: %q", buf.String()) 90 91 // Dump the terminal's screen. 92 t.Logf("\n%s", expect.StripTrailingEmptyLines(state.String())) 93 } 94 95 func stringToProcedure(actions string) func(*expect.Console) error { 96 return func(c *expect.Console) error { 97 for _, chr := range actions { 98 var err error 99 switch chr { 100 case 'β': 101 _, err = c.Send(string(terminal.KeyArrowDown)) 102 case 'β': 103 _, err = c.Send(string(terminal.KeyArrowUp)) 104 case 'β': 105 _, err = c.Send(string(terminal.KeyEnter)) 106 case 'π': 107 _, err = c.ExpectEOF() 108 default: 109 _, err = c.Send(fmt.Sprintf("%c", chr)) 110 } 111 if err != nil { 112 return err 113 } 114 } 115 return nil 116 } 117 } 118 119 type questionTest struct { 120 name string 121 ini *initializer 122 execution func(*initializer, *initConfig) error 123 procedure func(*expect.Console) error 124 expectedState *initConfig 125 } 126 127 func TestAskRegion(t *testing.T) { 128 testCases := []questionTest{ 129 { 130 name: "Default", 131 procedure: stringToProcedure("βπ"), 132 ini: &initializer{ 133 cfg: &initConfig{}, 134 }, 135 execution: func(i *initializer, cfg *initConfig) error { 136 regio, err := askRegion(i.stdio) 137 cfg.region = regio 138 return err 139 }, 140 expectedState: &initConfig{region: region.USWest1.String()}, 141 }, 142 { 143 name: "Type US", 144 procedure: stringToProcedure("us-βπ"), 145 ini: &initializer{ 146 cfg: &initConfig{}, 147 }, 148 execution: func(i *initializer, cfg *initConfig) error { 149 regio, err := askRegion(i.stdio) 150 cfg.region = regio 151 return err 152 }, 153 expectedState: &initConfig{region: region.USWest1.String()}, 154 }, 155 { 156 name: "Type EU", 157 procedure: stringToProcedure("eu-βπ"), 158 ini: &initializer{ 159 infoReader: &mocks.FakeFrameworkInfoReader{}, 160 cfg: &initConfig{}, 161 }, 162 execution: func(i *initializer, cfg *initConfig) error { 163 regio, err := askRegion(i.stdio) 164 cfg.region = regio 165 return err 166 }, 167 expectedState: &initConfig{region: region.EUCentral1.String()}, 168 }, 169 { 170 name: "Select EU", 171 procedure: stringToProcedure("ββπ"), 172 ini: &initializer{ 173 infoReader: &mocks.FakeFrameworkInfoReader{}, 174 cfg: &initConfig{}, 175 }, 176 execution: func(i *initializer, cfg *initConfig) error { 177 regio, err := askRegion(i.stdio) 178 cfg.region = regio 179 return err 180 }, 181 expectedState: &initConfig{region: region.EUCentral1.String()}, 182 }, 183 } 184 for _, tt := range testCases { 185 t.Run(tt.name, func(lt *testing.T) { 186 executeQuestionTestWithTimeout(lt, tt) 187 }) 188 } 189 } 190 191 func TestAskDownloadWhen(t *testing.T) { 192 testCases := []questionTest{ 193 { 194 name: "Defaults to Fail", 195 procedure: stringToProcedure("βπ"), 196 ini: &initializer{ 197 cfg: &initConfig{}, 198 }, 199 execution: func(i *initializer, cfg *initConfig) error { 200 return i.askDownloadWhen() 201 }, 202 expectedState: &initConfig{artifactWhen: config.WhenFail}, 203 }, 204 { 205 name: "Second is pass", 206 procedure: stringToProcedure("ββπ"), 207 ini: &initializer{ 208 infoReader: &mocks.FakeFrameworkInfoReader{}, 209 cfg: &initConfig{}, 210 }, 211 execution: func(i *initializer, cfg *initConfig) error { 212 return i.askDownloadWhen() 213 }, 214 expectedState: &initConfig{artifactWhen: config.WhenPass}, 215 }, 216 { 217 name: "Type always", 218 procedure: stringToProcedure("alwβπ"), 219 ini: &initializer{ 220 infoReader: &mocks.FakeFrameworkInfoReader{}, 221 cfg: &initConfig{}, 222 }, 223 execution: func(i *initializer, cfg *initConfig) error { 224 return i.askDownloadWhen() 225 }, 226 expectedState: &initConfig{artifactWhen: config.WhenAlways}, 227 }, 228 } 229 for _, tt := range testCases { 230 t.Run(tt.name, func(lt *testing.T) { 231 executeQuestionTestWithTimeout(lt, tt) 232 }) 233 } 234 } 235 236 func TestAskDevice(t *testing.T) { 237 devs := []string{"Google Pixel 3", "Google Pixel 4"} 238 testCases := []questionTest{ 239 { 240 name: "Default Device", 241 procedure: stringToProcedure("βπ"), 242 ini: &initializer{ 243 cfg: &initConfig{}, 244 }, 245 execution: func(i *initializer, cfg *initConfig) error { 246 return i.askDevice(devs) 247 }, 248 expectedState: &initConfig{device: config.Device{Name: "Google Pixel 3"}}, 249 }, 250 { 251 name: "Input is captured", 252 procedure: stringToProcedure("Pixel 4βπ"), 253 ini: &initializer{ 254 infoReader: &mocks.FakeFrameworkInfoReader{}, 255 cfg: &initConfig{}, 256 }, 257 execution: func(i *initializer, cfg *initConfig) error { 258 return i.askDevice(devs) 259 }, 260 expectedState: &initConfig{device: config.Device{Name: "Google Pixel 4"}}, 261 }, 262 } 263 for _, tt := range testCases { 264 t.Run(tt.name, func(lt *testing.T) { 265 executeQuestionTestWithTimeout(lt, tt) 266 }) 267 } 268 } 269 270 func TestAskEmulator(t *testing.T) { 271 vmds := []vmd.VirtualDevice{ 272 {Name: "Google Pixel 3 Emulator", OSVersion: []string{"9.0", "8.0", "7.0"}}, 273 {Name: "Google Pixel 4 Emulator", OSVersion: []string{"9.0", "8.0", "7.0"}}, 274 } 275 testCases := []questionTest{ 276 { 277 name: "Empty is allowed", 278 procedure: func(c *expect.Console) error { 279 _, err := c.ExpectString("Select emulator:") 280 if err != nil { 281 return err 282 } 283 _, err = c.SendLine("") 284 if err != nil { 285 return err 286 } 287 _, err = c.ExpectString("Select platform version:") 288 if err != nil { 289 return err 290 } 291 _, err = c.SendLine("") 292 if err != nil { 293 return err 294 } 295 _, err = c.ExpectEOF() 296 if err != nil { 297 return err 298 } 299 return nil 300 }, 301 ini: &initializer{ 302 cfg: &initConfig{}, 303 }, 304 execution: func(i *initializer, cfg *initConfig) error { 305 return i.askEmulator(vmds) 306 }, 307 expectedState: &initConfig{emulator: config.Emulator{Name: "Google Pixel 3 Emulator", PlatformVersions: []string{"9.0"}}}, 308 }, 309 { 310 name: "Input is captured", 311 procedure: func(c *expect.Console) error { 312 _, err := c.ExpectString("Select emulator:") 313 if err != nil { 314 return err 315 } 316 _, err = c.SendLine("Pixel 4") 317 if err != nil { 318 return err 319 } 320 _, err = c.ExpectString("Select platform version:") 321 if err != nil { 322 return err 323 } 324 _, err = c.SendLine("7.0") 325 if err != nil { 326 return err 327 } 328 _, err = c.ExpectEOF() 329 if err != nil { 330 return err 331 } 332 return nil 333 }, 334 ini: &initializer{ 335 infoReader: &mocks.FakeFrameworkInfoReader{}, 336 cfg: &initConfig{}, 337 }, 338 execution: func(i *initializer, cfg *initConfig) error { 339 return i.askEmulator(vmds) 340 }, 341 expectedState: &initConfig{emulator: config.Emulator{Name: "Google Pixel 4 Emulator", PlatformVersions: []string{"7.0"}}}, 342 }, 343 } 344 for _, tt := range testCases { 345 t.Run(tt.name, func(lt *testing.T) { 346 executeQuestionTestWithTimeout(lt, tt) 347 }) 348 } 349 } 350 351 func TestAskPlatform(t *testing.T) { 352 metas := []framework.Metadata{ 353 { 354 FrameworkName: testcafe.Kind, 355 FrameworkVersion: "1.5.0", 356 DockerImage: "dummy-docker-image", 357 Platforms: []framework.Platform{ 358 { 359 PlatformName: "Windows 10", 360 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 361 }, 362 { 363 PlatformName: "macOS 11.00", 364 BrowserNames: []string{"safari", "googlechrome", "firefox", "microsoftedge"}, 365 }, 366 }, 367 }, 368 { 369 FrameworkName: testcafe.Kind, 370 FrameworkVersion: "1.3.0", 371 Platforms: []framework.Platform{ 372 { 373 PlatformName: "Windows 10", 374 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 375 }, 376 { 377 PlatformName: "macOS 11.00", 378 BrowserNames: []string{"safari", "googlechrome", "firefox", "microsoftedge"}, 379 }, 380 }, 381 }, 382 } 383 384 testCases := []questionTest{ 385 { 386 name: "Windows 10", 387 procedure: func(c *expect.Console) error { 388 _, err := c.ExpectString("Select browser") 389 if err != nil { 390 return err 391 } 392 _, err = c.SendLine("chrome") 393 if err != nil { 394 return err 395 } 396 _, err = c.ExpectString("Select platform") 397 if err != nil { 398 return err 399 } 400 _, err = c.SendLine("Windows 10") 401 if err != nil { 402 return err 403 } 404 _, err = c.ExpectEOF() 405 if err != nil { 406 return err 407 } 408 return nil 409 }, 410 ini: &initializer{ 411 cfg: &initConfig{ 412 frameworkName: testcafe.Kind, 413 frameworkVersion: "1.5.0", 414 }, 415 }, 416 execution: func(i *initializer, cfg *initConfig) error { 417 return i.askPlatform(metas) 418 }, 419 expectedState: &initConfig{ 420 frameworkName: testcafe.Kind, 421 frameworkVersion: "1.5.0", 422 browserName: "chrome", 423 platformName: "Windows 10", 424 }, 425 }, 426 { 427 name: "macOS", 428 procedure: func(c *expect.Console) error { 429 _, err := c.ExpectString("Select browser") 430 if err != nil { 431 return err 432 } 433 _, err = c.SendLine("firefox") 434 if err != nil { 435 return err 436 } 437 _, err = c.ExpectString("Select platform") 438 if err != nil { 439 return err 440 } 441 _, err = c.SendLine("macOS") 442 if err != nil { 443 return err 444 } 445 _, err = c.ExpectEOF() 446 if err != nil { 447 return err 448 } 449 return nil 450 }, 451 ini: &initializer{ 452 cfg: &initConfig{ 453 frameworkName: testcafe.Kind, 454 frameworkVersion: "1.5.0", 455 }, 456 }, 457 execution: func(i *initializer, cfg *initConfig) error { 458 return i.askPlatform(metas) 459 }, 460 expectedState: &initConfig{ 461 frameworkName: testcafe.Kind, 462 frameworkVersion: "1.5.0", 463 platformName: "macOS 11.00", 464 browserName: "firefox", 465 }, 466 }, 467 } 468 for _, tt := range testCases { 469 t.Run(tt.name, func(lt *testing.T) { 470 executeQuestionTestWithTimeout(lt, tt) 471 }) 472 } 473 } 474 475 func TestAskVersion(t *testing.T) { 476 metas := []framework.Metadata{ 477 { 478 FrameworkName: testcafe.Kind, 479 FrameworkVersion: "1.5.0", 480 Platforms: []framework.Platform{ 481 { 482 PlatformName: "macOS 11.00", 483 BrowserNames: []string{"safari", "googlechrome", "firefox", "microsoftedge"}, 484 }, 485 { 486 PlatformName: "Windows 10", 487 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 488 }, 489 }, 490 }, 491 { 492 FrameworkName: testcafe.Kind, 493 FrameworkVersion: "1.3.0", 494 Platforms: []framework.Platform{ 495 { 496 PlatformName: "macOS 11.00", 497 BrowserNames: []string{"safari", "googlechrome", "firefox", "microsoftedge"}, 498 }, 499 { 500 PlatformName: "Windows 10", 501 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 502 }, 503 }, 504 }, 505 } 506 507 testCases := []questionTest{ 508 { 509 name: "Default", 510 procedure: func(c *expect.Console) error { 511 _, err := c.ExpectString("Select testcafe version") 512 if err != nil { 513 return err 514 } 515 _, err = c.SendLine(string(terminal.KeyEnter)) 516 if err != nil { 517 return err 518 } 519 _, err = c.ExpectEOF() 520 if err != nil { 521 return err 522 } 523 return nil 524 }, 525 ini: &initializer{ 526 infoReader: &mocks.FakeFrameworkInfoReader{}, 527 cfg: &initConfig{ 528 frameworkName: testcafe.Kind, 529 }, 530 }, 531 execution: func(i *initializer, cfg *initConfig) error { 532 return i.askVersion(metas) 533 }, 534 expectedState: &initConfig{ 535 frameworkName: testcafe.Kind, 536 frameworkVersion: "1.5.0", 537 }, 538 }, 539 { 540 name: "Second", 541 procedure: func(c *expect.Console) error { 542 _, err := c.ExpectString("Select testcafe version") 543 if err != nil { 544 return err 545 } 546 _, err = c.Send(string(terminal.KeyArrowDown)) 547 if err != nil { 548 return err 549 } 550 _, err = c.Send(string(terminal.KeyEnter)) 551 if err != nil { 552 return err 553 } 554 _, err = c.ExpectEOF() 555 if err != nil { 556 return err 557 } 558 return nil 559 }, 560 ini: &initializer{ 561 infoReader: &mocks.FakeFrameworkInfoReader{}, 562 cfg: &initConfig{ 563 frameworkName: testcafe.Kind, 564 }, 565 }, 566 execution: func(i *initializer, cfg *initConfig) error { 567 return i.askVersion(metas) 568 }, 569 expectedState: &initConfig{ 570 frameworkName: testcafe.Kind, 571 frameworkVersion: "1.3.0", 572 }, 573 }, 574 } 575 for _, tt := range testCases { 576 t.Run(tt.name, func(lt *testing.T) { 577 executeQuestionTestWithTimeout(lt, tt) 578 }) 579 } 580 } 581 582 func TestAskFile(t *testing.T) { 583 dir := fs.NewDir(t, "apps", 584 fs.WithFile("android-app.apk", "myAppContent", fs.WithMode(0644)), 585 fs.WithFile("ios-app.ipa", "myAppContent", fs.WithMode(0644)), 586 fs.WithDir("ios-folder-app.app", fs.WithMode(0755))) 587 defer dir.Remove() 588 589 testCases := []questionTest{ 590 { 591 name: "Default", 592 procedure: func(c *expect.Console) error { 593 _, err := c.ExpectString("Filename") 594 if err != nil { 595 return err 596 } 597 _, err = c.SendLine(dir.Join("android")) 598 if err != nil { 599 return err 600 } 601 _, err = c.ExpectString("Sorry, your reply was invalid") 602 if err != nil { 603 return err 604 } 605 _, err = c.SendLine("-app.apk") 606 if err != nil { 607 return err 608 } 609 _, err = c.ExpectEOF() 610 if err != nil { 611 return err 612 } 613 return nil 614 }, 615 ini: &initializer{ 616 infoReader: &mocks.FakeFrameworkInfoReader{}, 617 cfg: &initConfig{}, 618 }, 619 execution: func(i *initializer, cfg *initConfig) error { 620 return i.askFile("Filename", func(ans interface{}) error { 621 val := ans.(string) 622 if !strings.HasSuffix(val, ".apk") { 623 return errors.New("not-an-apk") 624 } 625 fi, err := os.Stat(val) 626 if err != nil { 627 return err 628 } 629 if fi.IsDir() { 630 return errors.New("not-a-file") 631 } 632 return nil 633 }, nil, &cfg.app) 634 }, 635 expectedState: &initConfig{ 636 app: dir.Join("android-app.apk"), 637 }, 638 }, 639 } 640 for _, tt := range testCases { 641 t.Run(tt.name, func(lt *testing.T) { 642 executeQuestionTestWithTimeout(lt, tt) 643 }) 644 } 645 } 646 647 func TestConfigure(t *testing.T) { 648 dir := fs.NewDir(t, "apps", 649 fs.WithFile("cypress.json", "{}", fs.WithMode(0644)), 650 fs.WithFile("android-app.apk", "myAppContent", fs.WithMode(0644)), 651 fs.WithFile("ios-app.ipa", "myAppContent", fs.WithMode(0644)), 652 fs.WithDir("ios-folder-app.app", fs.WithMode(0755))) 653 defer dir.Remove() 654 655 frameworkVersions := []framework.Metadata{ 656 { 657 FrameworkName: cypress.Kind, 658 FrameworkVersion: "7.5.0", 659 DockerImage: "dummy-docker-image", 660 Platforms: []framework.Platform{ 661 { 662 PlatformName: "windows 10", 663 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 664 }, 665 }, 666 }, 667 } 668 ir := &mocks.FakeFrameworkInfoReader{ 669 VersionsFn: func(ctx context.Context, frameworkName string) ([]framework.Metadata, error) { 670 return frameworkVersions, nil 671 }, 672 FrameworksFn: func(ctx context.Context) ([]string, error) { 673 return []string{cypress.Kind, espresso.Kind}, nil 674 }, 675 } 676 dr := &mocks.FakeDevicesReader{ 677 GetDevicesFn: func(ctx context.Context, s string) ([]devices.Device, error) { 678 return []devices.Device{ 679 {Name: "Google Pixel 3"}, 680 {Name: "Google Pixel 4"}, 681 }, nil 682 }, 683 } 684 er := &mocks.FakeEmulatorsReader{ 685 GetVirtualDevicesFn: func(ctx context.Context, s string) ([]vmd.VirtualDevice, error) { 686 return []vmd.VirtualDevice{ 687 {Name: "Google Pixel Emulator", OSVersion: []string{"9.0", "8.0", "7.0"}}, 688 {Name: "Samsung Galaxy Emulator", OSVersion: []string{"9.0", "8.0", "7.0"}}, 689 }, nil 690 }, 691 } 692 693 testCases := []questionTest{ 694 { 695 name: "Complete Configuration (espresso)", 696 procedure: func(c *expect.Console) error { 697 _, err := c.ExpectString("Application to test") 698 if err != nil { 699 return err 700 } 701 _, err = c.SendLine(dir.Join("android-app.apk")) 702 if err != nil { 703 return err 704 } 705 _, err = c.ExpectString("Test application") 706 if err != nil { 707 return err 708 } 709 _, err = c.SendLine(dir.Join("android-app.apk")) 710 if err != nil { 711 return err 712 } 713 _, err = c.ExpectString("Select device pattern:") 714 if err != nil { 715 return err 716 } 717 _, err = c.SendLine("Google Pixel .*") 718 if err != nil { 719 return err 720 } 721 _, err = c.ExpectString("Select emulator:") 722 if err != nil { 723 return err 724 } 725 _, err = c.SendLine("Google Pixel Emulator") 726 if err != nil { 727 return err 728 } 729 _, err = c.ExpectString("Select platform version:") 730 if err != nil { 731 return err 732 } 733 _, err = c.SendLine("7.0") 734 if err != nil { 735 return err 736 } 737 _, err = c.ExpectString("Download artifacts:") 738 if err != nil { 739 return err 740 } 741 _, err = c.SendLine("when tests are passing") 742 if err != nil { 743 return err 744 } 745 _, err = c.ExpectEOF() 746 if err != nil { 747 return err 748 } 749 return nil 750 }, 751 ini: &initializer{ 752 infoReader: ir, 753 deviceReader: dr, 754 vmdReader: er, 755 cfg: &initConfig{ 756 frameworkName: espresso.Kind, 757 }, 758 }, 759 execution: func(i *initializer, cfg *initConfig) error { 760 return i.configure() 761 }, 762 expectedState: &initConfig{ 763 frameworkName: espresso.Kind, 764 app: dir.Join("android-app.apk"), 765 testApp: dir.Join("android-app.apk"), 766 emulator: config.Emulator{Name: "Google Pixel Emulator", PlatformVersions: []string{"7.0"}}, 767 device: config.Device{Name: "Google Pixel .*"}, 768 artifactWhen: config.WhenPass, 769 }, 770 }, 771 { 772 name: "Complete Configuration (cypress)", 773 procedure: func(c *expect.Console) error { 774 _, err := c.ExpectString("Select cypress version") 775 if err != nil { 776 return err 777 } 778 _, err = c.SendLine("7.5.0") 779 if err != nil { 780 return err 781 } 782 _, err = c.ExpectString("Cypress configuration file:") 783 if err != nil { 784 return err 785 } 786 _, err = c.SendLine(dir.Join("cypress.json")) 787 if err != nil { 788 return err 789 } 790 _, err = c.ExpectString("Select browser:") 791 if err != nil { 792 return err 793 } 794 _, err = c.SendLine("chrome") 795 if err != nil { 796 return err 797 } 798 _, err = c.ExpectString("Select platform:") 799 if err != nil { 800 return err 801 } 802 _, err = c.SendLine("Windows 10") 803 if err != nil { 804 return err 805 } 806 _, err = c.ExpectString("Download artifacts:") 807 if err != nil { 808 return err 809 } 810 _, err = c.SendLine("when tests are passing") 811 if err != nil { 812 return err 813 } 814 _, err = c.ExpectEOF() 815 if err != nil { 816 return err 817 } 818 return nil 819 }, 820 ini: &initializer{ 821 infoReader: ir, 822 deviceReader: dr, 823 vmdReader: er, 824 cfg: &initConfig{ 825 frameworkName: cypress.Kind, 826 }, 827 }, 828 execution: func(i *initializer, cfg *initConfig) error { 829 return i.configure() 830 }, 831 expectedState: &initConfig{ 832 frameworkName: cypress.Kind, 833 frameworkVersion: "7.5.0", 834 cypressConfigFile: dir.Join("cypress.json"), 835 platformName: "Windows 10", 836 browserName: "chrome", 837 artifactWhen: config.WhenPass, 838 }, 839 }, 840 } 841 for _, tt := range testCases { 842 t.Run(tt.name, func(lt *testing.T) { 843 executeQuestionTestWithTimeout(lt, tt) 844 }) 845 } 846 } 847 848 func TestAskCredentials(t *testing.T) { 849 testCases := []questionTest{ 850 { 851 name: "Default", 852 procedure: func(c *expect.Console) error { 853 _, err := c.ExpectString("Sauce Labs username:") 854 if err != nil { 855 return err 856 } 857 _, err = c.SendLine("dummy-user") 858 if err != nil { 859 return err 860 } 861 _, err = c.ExpectString("Sauce Labs access key:") 862 if err != nil { 863 return err 864 } 865 _, err = c.SendLine("dummy-access-key") 866 if err != nil { 867 return err 868 } 869 _, err = c.ExpectEOF() 870 if err != nil { 871 return err 872 } 873 return nil 874 }, 875 ini: &initializer{ 876 cfg: &initConfig{}, 877 }, 878 execution: func(i *initializer, cfg *initConfig) error { 879 creds, err := askCredentials(i.stdio) 880 if err != nil { 881 t.Fatalf("unexpected error: %v", err) 882 } 883 expect := &iam.Credentials{Username: "dummy-user", AccessKey: "dummy-access-key"} 884 if reflect.DeepEqual(creds, expect) { 885 t.Fatalf("got: %v, want: %v", creds, expect) 886 } 887 return nil 888 }, 889 expectedState: &initConfig{}, 890 }, 891 } 892 for _, tt := range testCases { 893 t.Run(tt.name, func(lt *testing.T) { 894 executeQuestionTestWithTimeout(lt, tt) 895 }) 896 } 897 } 898 899 func Test_initializers(t *testing.T) { 900 dir := fs.NewDir(t, "apps", 901 fs.WithFile("cypress.json", "{}", fs.WithMode(0644)), 902 fs.WithFile("android-app.apk", "myAppContent", fs.WithMode(0644)), 903 fs.WithFile("ios-app.ipa", "myAppContent", fs.WithMode(0644)), 904 fs.WithDir("ios-folder-app.app", fs.WithMode(0755))) 905 defer dir.Remove() 906 907 frameworkVersions := map[string][]framework.Metadata{ 908 cypress.Kind: { 909 { 910 FrameworkName: cypress.Kind, 911 FrameworkVersion: "7.5.0", 912 DockerImage: "dummy-docker-image", 913 Platforms: []framework.Platform{ 914 { 915 PlatformName: "windows 10", 916 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 917 }, 918 }, 919 }, 920 }, 921 playwright.Kind: { 922 { 923 FrameworkName: playwright.Kind, 924 FrameworkVersion: "1.11.0", 925 DockerImage: "dummy-docker-image", 926 Platforms: []framework.Platform{ 927 { 928 PlatformName: "windows 10", 929 BrowserNames: []string{"playwright-chromium", "playwright-firefox", "playwright-webkit"}, 930 }, 931 }, 932 }, 933 }, 934 testcafe.Kind: { 935 { 936 FrameworkName: testcafe.Kind, 937 FrameworkVersion: "1.12.0", 938 DockerImage: "dummy-docker-image", 939 Platforms: []framework.Platform{ 940 { 941 PlatformName: "windows 10", 942 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 943 }, 944 { 945 PlatformName: "macOS 11.00", 946 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge", "safari"}, 947 }, 948 }, 949 }, 950 }, 951 imagerunner.Kind: { 952 { 953 FrameworkName: imagerunner.Kind, 954 FrameworkVersion: "1.0.0", 955 }, 956 }, 957 } 958 ir := &mocks.FakeFrameworkInfoReader{ 959 VersionsFn: func(ctx context.Context, frameworkName string) ([]framework.Metadata, error) { 960 return frameworkVersions[frameworkName], nil 961 }, 962 FrameworksFn: func(ctx context.Context) ([]string, error) { 963 return []string{ 964 cypress.Kind, 965 espresso.Kind, 966 imagerunner.Kind, 967 playwright.Kind, 968 testcafe.Kind, 969 xcuitest.Kind, 970 }, nil 971 }, 972 } 973 974 er := &mocks.FakeEmulatorsReader{ 975 GetVirtualDevicesFn: func(ctx context.Context, s string) ([]vmd.VirtualDevice, error) { 976 return []vmd.VirtualDevice{ 977 {Name: "Google Pixel Emulator", OSVersion: []string{"9.0", "8.0", "7.0"}}, 978 {Name: "Samsung Galaxy Emulator", OSVersion: []string{"9.0", "8.0", "7.0"}}, 979 }, nil 980 }, 981 } 982 983 testCases := []questionTest{ 984 { 985 name: "Cypress - Windows 10 - chrome", 986 procedure: func(c *expect.Console) error { 987 _, err := c.ExpectString("Select cypress version") 988 if err != nil { 989 return err 990 } 991 _, err = c.SendLine("7.5.0") 992 if err != nil { 993 return err 994 } 995 _, err = c.ExpectString("Cypress configuration file:") 996 if err != nil { 997 return err 998 } 999 _, err = c.SendLine(dir.Join("cypress.json")) 1000 if err != nil { 1001 return err 1002 } 1003 _, err = c.ExpectString("Select browser:") 1004 if err != nil { 1005 return err 1006 } 1007 _, err = c.SendLine("chrome") 1008 if err != nil { 1009 return err 1010 } 1011 _, err = c.ExpectString("Select platform:") 1012 if err != nil { 1013 return err 1014 } 1015 _, err = c.SendLine("Windows 10") 1016 if err != nil { 1017 return err 1018 } 1019 _, err = c.ExpectString("Download artifacts:") 1020 if err != nil { 1021 return err 1022 } 1023 _, err = c.SendLine("when tests are passing") 1024 if err != nil { 1025 return err 1026 } 1027 _, err = c.ExpectEOF() 1028 if err != nil { 1029 return err 1030 } 1031 return nil 1032 }, 1033 ini: &initializer{ 1034 infoReader: ir, 1035 cfg: &initConfig{ 1036 frameworkName: cypress.Kind, 1037 }, 1038 }, 1039 execution: func(i *initializer, cfg *initConfig) error { 1040 return i.initializeCypress() 1041 }, 1042 expectedState: &initConfig{ 1043 frameworkName: cypress.Kind, 1044 frameworkVersion: "7.5.0", 1045 cypressConfigFile: dir.Join("cypress.json"), 1046 platformName: "Windows 10", 1047 browserName: "chrome", 1048 artifactWhen: config.WhenPass, 1049 }, 1050 }, 1051 { 1052 name: "Playwright - Windows 10 - chromium", 1053 procedure: func(c *expect.Console) error { 1054 _, err := c.ExpectString("Select playwright version") 1055 if err != nil { 1056 return err 1057 } 1058 _, err = c.SendLine("1.11.0") 1059 if err != nil { 1060 return err 1061 } 1062 _, err = c.ExpectString("Select browser:") 1063 if err != nil { 1064 return err 1065 } 1066 _, err = c.SendLine("chromium") 1067 if err != nil { 1068 return err 1069 } 1070 _, err = c.ExpectString("Select platform:") 1071 if err != nil { 1072 return err 1073 } 1074 _, err = c.SendLine("Windows 10") 1075 if err != nil { 1076 return err 1077 } 1078 _, err = c.ExpectString("Playwright project name. Leave empty if your configuration does not contain projects:") 1079 if err != nil { 1080 return err 1081 } 1082 _, err = c.SendLine("") 1083 if err != nil { 1084 return err 1085 } 1086 _, err = c.ExpectString("Test file pattern to match against:") 1087 if err != nil { 1088 return err 1089 } 1090 _, err = c.SendLine("") 1091 if err != nil { 1092 return err 1093 } 1094 _, err = c.ExpectString("Download artifacts:") 1095 if err != nil { 1096 return err 1097 } 1098 _, err = c.SendLine("when tests are passing") 1099 if err != nil { 1100 return err 1101 } 1102 _, err = c.ExpectEOF() 1103 if err != nil { 1104 return err 1105 } 1106 return nil 1107 }, 1108 ini: &initializer{ 1109 infoReader: ir, 1110 cfg: &initConfig{ 1111 frameworkName: playwright.Kind, 1112 }, 1113 }, 1114 execution: func(i *initializer, cfg *initConfig) error { 1115 return i.initializePlaywright() 1116 }, 1117 expectedState: &initConfig{ 1118 frameworkName: playwright.Kind, 1119 frameworkVersion: "1.11.0", 1120 platformName: "Windows 10", 1121 browserName: "chromium", 1122 artifactWhen: config.WhenPass, 1123 testMatch: []string{".*.spec.js"}, 1124 }, 1125 }, 1126 { 1127 name: "Testcafe - macOS 11.00 - safari", 1128 procedure: func(c *expect.Console) error { 1129 _, err := c.ExpectString("Select testcafe version") 1130 if err != nil { 1131 return err 1132 } 1133 _, err = c.SendLine("1.12.0") 1134 if err != nil { 1135 return err 1136 } 1137 _, err = c.ExpectString("Select browser:") 1138 if err != nil { 1139 return err 1140 } 1141 _, err = c.SendLine("safari") 1142 if err != nil { 1143 return err 1144 } 1145 _, err = c.ExpectString("Select platform:") 1146 if err != nil { 1147 return err 1148 } 1149 _, err = c.SendLine("macOS 11.00") 1150 if err != nil { 1151 return err 1152 } 1153 _, err = c.ExpectString("Download artifacts:") 1154 if err != nil { 1155 return err 1156 } 1157 _, err = c.SendLine("when tests are passing") 1158 if err != nil { 1159 return err 1160 } 1161 _, err = c.ExpectEOF() 1162 if err != nil { 1163 return err 1164 } 1165 return nil 1166 }, 1167 ini: &initializer{ 1168 infoReader: ir, 1169 cfg: &initConfig{ 1170 frameworkName: testcafe.Kind, 1171 }, 1172 }, 1173 execution: func(i *initializer, cfg *initConfig) error { 1174 return i.initializeTestcafe() 1175 }, 1176 expectedState: &initConfig{ 1177 frameworkName: testcafe.Kind, 1178 frameworkVersion: "1.12.0", 1179 platformName: "macOS 11.00", 1180 browserName: "safari", 1181 artifactWhen: config.WhenPass, 1182 }, 1183 }, 1184 { 1185 name: "XCUITest - .ipa", 1186 procedure: func(c *expect.Console) error { 1187 _, err := c.ExpectString("Select target:") 1188 if err != nil { 1189 return err 1190 } 1191 _, err = c.SendLine("Real Devices") 1192 if err != nil { 1193 return err 1194 } 1195 _, err = c.ExpectString("Select device pattern:") 1196 if err != nil { 1197 return err 1198 } 1199 _, err = c.SendLine("iPhone .*") 1200 if err != nil { 1201 return err 1202 } 1203 _, err = c.ExpectString("Application to test:") 1204 if err != nil { 1205 return err 1206 } 1207 _, err = c.SendLine(dir.Join("ios-app.ipa")) 1208 if err != nil { 1209 return err 1210 } 1211 _, err = c.ExpectString("Test application:") 1212 if err != nil { 1213 return err 1214 } 1215 _, err = c.SendLine(dir.Join("ios-app.ipa")) 1216 if err != nil { 1217 return err 1218 } 1219 _, err = c.ExpectString("Download artifacts:") 1220 if err != nil { 1221 return err 1222 } 1223 _, err = c.SendLine("when tests are passing") 1224 if err != nil { 1225 return err 1226 } 1227 _, err = c.ExpectEOF() 1228 if err != nil { 1229 return err 1230 } 1231 return nil 1232 }, 1233 ini: &initializer{ 1234 infoReader: ir, 1235 cfg: &initConfig{ 1236 frameworkName: xcuitest.Kind, 1237 }, 1238 }, 1239 execution: func(i *initializer, cfg *initConfig) error { 1240 return i.initializeXCUITest() 1241 }, 1242 expectedState: &initConfig{ 1243 frameworkName: xcuitest.Kind, 1244 app: dir.Join("ios-app.ipa"), 1245 testApp: dir.Join("ios-app.ipa"), 1246 device: config.Device{Name: "iPhone .*"}, 1247 artifactWhen: config.WhenPass, 1248 }, 1249 }, 1250 { 1251 name: "XCUITest - .app", 1252 procedure: func(c *expect.Console) error { 1253 _, err := c.ExpectString("Select target:") 1254 if err != nil { 1255 return err 1256 } 1257 _, err = c.SendLine("Real Devices") 1258 if err != nil { 1259 return err 1260 } 1261 _, err = c.ExpectString("Select device pattern:") 1262 if err != nil { 1263 return err 1264 } 1265 _, err = c.SendLine("iPad .*") 1266 if err != nil { 1267 return err 1268 } 1269 _, err = c.ExpectString("Application to test:") 1270 if err != nil { 1271 return err 1272 } 1273 _, err = c.SendLine(dir.Join("ios-folder-app.app")) 1274 if err != nil { 1275 return err 1276 } 1277 _, err = c.ExpectString("Test application:") 1278 if err != nil { 1279 return err 1280 } 1281 _, err = c.SendLine(dir.Join("ios-folder-app.app")) 1282 if err != nil { 1283 return err 1284 } 1285 _, err = c.ExpectString("Download artifacts:") 1286 if err != nil { 1287 return err 1288 } 1289 _, err = c.SendLine("when tests are passing") 1290 if err != nil { 1291 return err 1292 } 1293 _, err = c.ExpectEOF() 1294 if err != nil { 1295 return err 1296 } 1297 return nil 1298 }, 1299 ini: &initializer{ 1300 infoReader: ir, 1301 cfg: &initConfig{ 1302 frameworkName: xcuitest.Kind, 1303 }, 1304 }, 1305 execution: func(i *initializer, cfg *initConfig) error { 1306 return i.initializeXCUITest() 1307 }, 1308 expectedState: &initConfig{ 1309 frameworkName: xcuitest.Kind, 1310 app: dir.Join("ios-folder-app.app"), 1311 testApp: dir.Join("ios-folder-app.app"), 1312 device: config.Device{Name: "iPad .*"}, 1313 artifactWhen: config.WhenPass, 1314 }, 1315 }, 1316 { 1317 name: "Espresso - .apk", 1318 procedure: func(c *expect.Console) error { 1319 _, err := c.ExpectString("Application to test:") 1320 if err != nil { 1321 return err 1322 } 1323 _, err = c.SendLine(dir.Join("android-app.apk")) 1324 if err != nil { 1325 return err 1326 } 1327 _, err = c.ExpectString("Test application:") 1328 if err != nil { 1329 return err 1330 } 1331 _, err = c.SendLine(dir.Join("android-app.apk")) 1332 if err != nil { 1333 return err 1334 } 1335 _, err = c.ExpectString("Select device pattern:") 1336 if err != nil { 1337 return err 1338 } 1339 _, err = c.SendLine("HTC .*") 1340 if err != nil { 1341 return err 1342 } 1343 _, err = c.ExpectString("Select emulator:") 1344 if err != nil { 1345 return err 1346 } 1347 _, err = c.SendLine("Samsung Galaxy Emulator") 1348 if err != nil { 1349 return err 1350 } 1351 _, err = c.ExpectString("Select platform version:") 1352 if err != nil { 1353 return err 1354 } 1355 _, err = c.SendLine("8.0") 1356 if err != nil { 1357 return err 1358 } 1359 _, err = c.ExpectString("Download artifacts:") 1360 if err != nil { 1361 return err 1362 } 1363 _, err = c.SendLine("when tests are passing") 1364 if err != nil { 1365 return err 1366 } 1367 _, err = c.ExpectEOF() 1368 if err != nil { 1369 return err 1370 } 1371 return nil 1372 }, 1373 ini: &initializer{ 1374 infoReader: ir, 1375 vmdReader: er, 1376 cfg: &initConfig{ 1377 frameworkName: espresso.Kind, 1378 }, 1379 }, 1380 execution: func(i *initializer, cfg *initConfig) error { 1381 return i.initializeEspresso() 1382 }, 1383 expectedState: &initConfig{ 1384 frameworkName: espresso.Kind, 1385 app: dir.Join("android-app.apk"), 1386 testApp: dir.Join("android-app.apk"), 1387 device: config.Device{Name: "HTC .*"}, 1388 emulator: config.Emulator{Name: "Samsung Galaxy Emulator", PlatformVersions: []string{"8.0"}}, 1389 artifactWhen: config.WhenPass, 1390 }, 1391 }, 1392 { 1393 name: "ImageRunner - DockerImage", 1394 procedure: func(c *expect.Console) error { 1395 _, err := c.ExpectString("Docker Image to use:") 1396 if err != nil { 1397 return err 1398 } 1399 _, err = c.SendLine("ubuntu:latest") 1400 if err != nil { 1401 return err 1402 } 1403 _, err = c.ExpectString("Set workload:") 1404 if err != nil { 1405 return err 1406 } 1407 _, err = c.SendLine("webdriver") 1408 if err != nil { 1409 return err 1410 } 1411 _, err = c.ExpectString("Download artifacts:") 1412 if err != nil { 1413 return err 1414 } 1415 _, err = c.SendLine("when tests are passing") 1416 if err != nil { 1417 return err 1418 } 1419 _, err = c.ExpectEOF() 1420 if err != nil { 1421 return err 1422 } 1423 return nil 1424 }, 1425 ini: &initializer{ 1426 infoReader: ir, 1427 cfg: &initConfig{ 1428 frameworkName: imagerunner.Kind, 1429 }, 1430 }, 1431 execution: func(i *initializer, cfg *initConfig) error { 1432 return i.initializeImageRunner() 1433 }, 1434 expectedState: &initConfig{ 1435 frameworkName: imagerunner.Kind, 1436 dockerImage: "ubuntu:latest", 1437 workload: "webdriver", 1438 artifactWhen: config.WhenPass, 1439 }, 1440 }, 1441 } 1442 for _, tt := range testCases { 1443 t.Run(tt.name, func(lt *testing.T) { 1444 executeQuestionTestWithTimeout(lt, tt) 1445 }) 1446 } 1447 } 1448 1449 func Test_metaToBrowsers(t *testing.T) { 1450 type args struct { 1451 metadatas []framework.Metadata 1452 frameworkName string 1453 frameworkVersion string 1454 } 1455 tests := []struct { 1456 name string 1457 args args 1458 wantBrowsers []string 1459 wantPlatforms map[string][]string 1460 }{ 1461 { 1462 name: "1 version / 1 platform", 1463 args: args{ 1464 frameworkName: "framework", 1465 frameworkVersion: "1.1.0", 1466 metadatas: []framework.Metadata{ 1467 { 1468 FrameworkName: "framework", 1469 FrameworkVersion: "1.1.0", 1470 Platforms: []framework.Platform{ 1471 { 1472 PlatformName: "windows 10", 1473 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 1474 }, 1475 }, 1476 }, 1477 }, 1478 }, 1479 wantBrowsers: []string{"chrome", "firefox", "microsoftedge"}, 1480 wantPlatforms: map[string][]string{ 1481 "chrome": {"Windows 10"}, 1482 "firefox": {"Windows 10"}, 1483 "microsoftedge": {"Windows 10"}, 1484 }, 1485 }, 1486 { 1487 name: "1 version / docker only", 1488 args: args{ 1489 frameworkName: "framework", 1490 frameworkVersion: "1.1.0", 1491 metadatas: []framework.Metadata{ 1492 { 1493 FrameworkName: "framework", 1494 DockerImage: "framework-images", 1495 FrameworkVersion: "1.1.0", 1496 Platforms: []framework.Platform{}, 1497 }, 1498 }, 1499 }, 1500 wantPlatforms: map[string][]string{}, 1501 }, 1502 { 1503 name: "1 version / 1 platform + docker", 1504 args: args{ 1505 frameworkName: "framework", 1506 frameworkVersion: "1.1.0", 1507 metadatas: []framework.Metadata{ 1508 { 1509 FrameworkName: "framework", 1510 DockerImage: "framework-image:latest", 1511 FrameworkVersion: "1.1.0", 1512 Platforms: []framework.Platform{ 1513 { 1514 PlatformName: "Windows 10", 1515 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 1516 }, 1517 }, 1518 }, 1519 }, 1520 }, 1521 wantBrowsers: []string{"chrome", "firefox", "microsoftedge"}, 1522 wantPlatforms: map[string][]string{ 1523 "chrome": {"Windows 10"}, 1524 "firefox": {"Windows 10"}, 1525 "microsoftedge": {"Windows 10"}, 1526 }, 1527 }, 1528 { 1529 name: "1 version / 2 platform + docker", 1530 args: args{ 1531 frameworkName: "framework", 1532 frameworkVersion: "1.1.0", 1533 metadatas: []framework.Metadata{ 1534 { 1535 FrameworkName: "framework", 1536 DockerImage: "framework-image:latest", 1537 FrameworkVersion: "1.1.0", 1538 Platforms: []framework.Platform{ 1539 { 1540 PlatformName: "Windows 10", 1541 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 1542 }, 1543 { 1544 PlatformName: "macOS 11.00", 1545 BrowserNames: []string{"googlechrome", "firefox", "safari", "microsoftedge"}, 1546 }, 1547 }, 1548 }, 1549 }, 1550 }, 1551 wantBrowsers: []string{"chrome", "firefox", "microsoftedge", "safari"}, 1552 wantPlatforms: map[string][]string{ 1553 "chrome": {"Windows 10", "macOS 11.00"}, 1554 "firefox": {"Windows 10", "macOS 11.00"}, 1555 "microsoftedge": {"Windows 10", "macOS 11.00"}, 1556 "safari": {"macOS 11.00"}, 1557 }, 1558 }, 1559 { 1560 name: "2 version / 2 platform + docker", 1561 args: args{ 1562 frameworkName: "framework", 1563 frameworkVersion: "1.1.0", 1564 metadatas: []framework.Metadata{ 1565 { 1566 FrameworkName: "framework", 1567 DockerImage: "framework-image:latest", 1568 FrameworkVersion: "1.2.0", 1569 Platforms: []framework.Platform{ 1570 { 1571 PlatformName: "Windows 10", 1572 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 1573 }, 1574 }, 1575 }, 1576 { 1577 FrameworkName: "framework", 1578 DockerImage: "framework-image:latest", 1579 FrameworkVersion: "1.1.0", 1580 Platforms: []framework.Platform{ 1581 { 1582 PlatformName: "Windows 10", 1583 BrowserNames: []string{"googlechrome", "firefox", "microsoftedge"}, 1584 }, 1585 { 1586 PlatformName: "macOS 11.00", 1587 BrowserNames: []string{"googlechrome", "firefox", "safari", "microsoftedge"}, 1588 }, 1589 }, 1590 }, 1591 }, 1592 }, 1593 wantBrowsers: []string{"chrome", "firefox", "microsoftedge", "safari"}, 1594 wantPlatforms: map[string][]string{ 1595 "chrome": {"Windows 10", "macOS 11.00"}, 1596 "firefox": {"Windows 10", "macOS 11.00"}, 1597 "microsoftedge": {"Windows 10", "macOS 11.00"}, 1598 "safari": {"macOS 11.00"}, 1599 }, 1600 }, 1601 } 1602 for _, tt := range tests { 1603 t.Run(tt.name, func(t *testing.T) { 1604 gotBrowsers, gotPlatforms := metaToBrowsers(tt.args.metadatas, tt.args.frameworkName, tt.args.frameworkVersion) 1605 if !reflect.DeepEqual(gotBrowsers, tt.wantBrowsers) { 1606 t.Errorf("metaToBrowsers() got = %v, want %v", gotBrowsers, tt.wantBrowsers) 1607 } 1608 if !reflect.DeepEqual(gotPlatforms, tt.wantPlatforms) { 1609 t.Errorf("metaToBrowsers() got = %v, want %v", gotPlatforms, tt.wantPlatforms) 1610 } 1611 }) 1612 } 1613 } 1614 1615 func Test_checkCredentials(t *testing.T) { 1616 tests := []struct { 1617 name string 1618 frameworkFn func(ctx context.Context) ([]string, error) 1619 wantErr error 1620 }{ 1621 { 1622 name: "Success", 1623 frameworkFn: func(ctx context.Context) ([]string, error) { 1624 return []string{cypress.Kind}, nil 1625 }, 1626 wantErr: nil, 1627 }, 1628 { 1629 name: "Invalid credentials", 1630 frameworkFn: func(ctx context.Context) ([]string, error) { 1631 errMsg := "unexpected status '401' from test-composer: Unauthorized\n" 1632 return []string{}, fmt.Errorf(errMsg) 1633 }, 1634 wantErr: errors.New("invalid credentials provided"), 1635 }, 1636 { 1637 name: "Other error", 1638 frameworkFn: func(ctx context.Context) ([]string, error) { 1639 return []string{}, errors.New("other error") 1640 }, 1641 wantErr: errors.New("other error"), 1642 }, 1643 } 1644 for _, tt := range tests { 1645 t.Run(tt.name, func(t *testing.T) { 1646 ini := &initializer{ 1647 infoReader: &mocks.FakeFrameworkInfoReader{ 1648 FrameworksFn: tt.frameworkFn, 1649 }, 1650 } 1651 if err := ini.checkCredentials("us-west-1"); !reflect.DeepEqual(err, tt.wantErr) { 1652 t.Errorf("checkCredentials() error = %v, wantErr %v", err, tt.wantErr) 1653 } 1654 }) 1655 } 1656 } 1657 1658 func Test_checkFrameworkVersion(t *testing.T) { 1659 metadatas := []framework.Metadata{ 1660 { 1661 FrameworkName: testcafe.Kind, 1662 FrameworkVersion: "1.0.0", 1663 Platforms: []framework.Platform{ 1664 { 1665 PlatformName: "windows 10", 1666 BrowserNames: []string{"chrome", "firefox"}, 1667 }, 1668 { 1669 PlatformName: "macos 11.00", 1670 BrowserNames: []string{"chrome", "firefox", "safari"}, 1671 }, 1672 { 1673 PlatformName: "docker", 1674 BrowserNames: []string{"chrome", "firefox"}, 1675 }, 1676 }, 1677 }, 1678 } 1679 type args struct { 1680 frameworkName string 1681 frameworkVersion string 1682 metadatas []framework.Metadata 1683 } 1684 tests := []struct { 1685 name string 1686 args args 1687 wantErr error 1688 }{ 1689 { 1690 name: "Available version", 1691 args: args{ 1692 frameworkName: testcafe.Kind, 1693 frameworkVersion: "1.0.0", 1694 metadatas: metadatas, 1695 }, 1696 wantErr: nil, 1697 }, 1698 { 1699 name: "Unavailable version", 1700 args: args{ 1701 frameworkName: testcafe.Kind, 1702 frameworkVersion: "buggy-version", 1703 metadatas: metadatas, 1704 }, 1705 wantErr: errors.New("testcafe buggy-version is not supported. Supported versions are: 1.0.0"), 1706 }, 1707 } 1708 for _, tt := range tests { 1709 t.Run(tt.name, func(t *testing.T) { 1710 err := checkFrameworkVersion(tt.args.metadatas, tt.args.frameworkName, tt.args.frameworkVersion) 1711 if !reflect.DeepEqual(err, tt.wantErr) { 1712 t.Errorf("checkFrameworkVersion() error = %v, wantErr %v", err, tt.wantErr) 1713 } 1714 }) 1715 } 1716 } 1717 1718 func Test_checkBrowserAndPlatform(t *testing.T) { 1719 metadatas := []framework.Metadata{ 1720 { 1721 FrameworkName: testcafe.Kind, 1722 FrameworkVersion: "1.0.0", 1723 Platforms: []framework.Platform{ 1724 { 1725 PlatformName: "windows 10", 1726 BrowserNames: []string{"chrome", "firefox"}, 1727 }, 1728 { 1729 PlatformName: "macos 11.00", 1730 BrowserNames: []string{"chrome", "firefox", "safari"}, 1731 }, 1732 { 1733 PlatformName: "docker", 1734 BrowserNames: []string{"chrome", "firefox"}, 1735 }, 1736 }, 1737 }, 1738 } 1739 1740 type args struct { 1741 frameworkName string 1742 frameworkVersion string 1743 browserName string 1744 platformName string 1745 } 1746 tests := []struct { 1747 name string 1748 args args 1749 wantErr error 1750 }{ 1751 { 1752 name: "Default", 1753 args: args{ 1754 frameworkName: testcafe.Kind, 1755 frameworkVersion: "1.0.0", 1756 platformName: "Windows 10", 1757 browserName: "chrome", 1758 }, 1759 wantErr: nil, 1760 }, 1761 { 1762 name: "Unavailable browser", 1763 args: args{ 1764 frameworkName: testcafe.Kind, 1765 frameworkVersion: "1.0.0", 1766 platformName: "Windows 10", 1767 browserName: "webkit", 1768 }, 1769 wantErr: errors.New("webkit: unsupported browser. Supported browsers are: chrome, firefox, safari"), 1770 }, 1771 { 1772 name: "Unavailable browser on platform", 1773 args: args{ 1774 frameworkName: testcafe.Kind, 1775 frameworkVersion: "1.0.0", 1776 platformName: "Windows 10", 1777 browserName: "safari", 1778 }, 1779 wantErr: errors.New("safari: unsupported browser on Windows 10"), 1780 }, 1781 } 1782 for _, tt := range tests { 1783 t.Run(tt.name, func(t *testing.T) { 1784 err := checkBrowserAndPlatform(metadatas, tt.args.frameworkName, tt.args.frameworkVersion, tt.args.browserName, tt.args.platformName) 1785 if !reflect.DeepEqual(err, tt.wantErr) { 1786 t.Errorf("checkBrowserAndPlatform() error = %v, wantErr %v", err, tt.wantErr) 1787 } 1788 }) 1789 } 1790 } 1791 1792 func Test_checkArtifactDownloadSetting(t *testing.T) { 1793 type args struct { 1794 when string 1795 } 1796 tests := []struct { 1797 name string 1798 args args 1799 want config.When 1800 wantErr bool 1801 }{ 1802 { 1803 name: `Passing: fail`, 1804 args: args{ 1805 when: "fail", 1806 }, 1807 want: config.WhenFail, 1808 wantErr: false, 1809 }, 1810 { 1811 name: `Invalid kind`, 1812 args: args{ 1813 when: "dummy-value", 1814 }, 1815 wantErr: true, 1816 }, 1817 } 1818 for _, tt := range tests { 1819 t.Run(tt.name, func(t *testing.T) { 1820 got, err := checkArtifactDownloadSetting(tt.args.when) 1821 if (err != nil) != tt.wantErr { 1822 t.Errorf("checkArtifactDownloadSetting() error = %v, wantErr %v", err, tt.wantErr) 1823 return 1824 } 1825 if got != tt.want { 1826 t.Errorf("checkArtifactDownloadSetting() got = %v, want %v", got, tt.want) 1827 } 1828 }) 1829 } 1830 } 1831 1832 func Test_checkEmulators(t *testing.T) { 1833 vmds := []vmd.VirtualDevice{ 1834 { 1835 Name: "Google Api Emulator", 1836 OSVersion: []string{ 1837 "11.0", 1838 "10.0", 1839 "9.0", 1840 }, 1841 }, 1842 { 1843 Name: "Samsung Galaxy Emulator", 1844 OSVersion: []string{ 1845 "11.0", 1846 "10.0", 1847 "8.1", 1848 "8.0", 1849 }, 1850 }, 1851 } 1852 1853 type args struct { 1854 emulator config.Emulator 1855 } 1856 tests := []struct { 1857 name string 1858 args args 1859 want config.Emulator 1860 wantErrs []error 1861 }{ 1862 { 1863 name: "single version", 1864 args: args{ 1865 emulator: config.Emulator{ 1866 Name: "Google Api Emulator", 1867 PlatformVersions: []string{"10.0"}, 1868 }, 1869 }, 1870 want: config.Emulator{ 1871 Name: "Google Api Emulator", 1872 PlatformVersions: []string{"10.0"}, 1873 }, 1874 wantErrs: []error{}, 1875 }, 1876 { 1877 name: "multiple versions", 1878 args: args{ 1879 emulator: config.Emulator{ 1880 Name: "Google Api Emulator", 1881 PlatformVersions: []string{"10.0", "9.0"}, 1882 }, 1883 }, 1884 want: config.Emulator{ 1885 Name: "Google Api Emulator", 1886 PlatformVersions: []string{"10.0", "9.0"}, 1887 }, 1888 wantErrs: []error{}, 1889 }, 1890 { 1891 name: "multiple + buggy versions", 1892 args: args{ 1893 emulator: config.Emulator{ 1894 Name: "Google Api Emulator", 1895 PlatformVersions: []string{"10.0", "8.1"}, 1896 }, 1897 }, 1898 want: config.Emulator{}, 1899 wantErrs: []error{errors.New("emulator: Google Api Emulator does not support platform 8.1")}, 1900 }, 1901 { 1902 name: "case sensitiveness correction", 1903 args: args{ 1904 emulator: config.Emulator{ 1905 Name: "google api emulator", 1906 PlatformVersions: []string{"10.0"}, 1907 }, 1908 }, 1909 want: config.Emulator{ 1910 Name: "Google Api Emulator", 1911 PlatformVersions: []string{"10.0"}, 1912 }, 1913 wantErrs: []error{}, 1914 }, 1915 { 1916 name: "invalid emulator", 1917 args: args{ 1918 emulator: config.Emulator{ 1919 Name: "buggy emulator", 1920 PlatformVersions: []string{"10.0"}, 1921 }, 1922 }, 1923 want: config.Emulator{}, 1924 wantErrs: []error{errors.New("emulator: buggy emulator does not exists")}, 1925 }, 1926 } 1927 for _, tt := range tests { 1928 t.Run(tt.name, func(t *testing.T) { 1929 got, errs := checkEmulators(vmds, tt.args.emulator) 1930 if !reflect.DeepEqual(got, tt.want) { 1931 t.Errorf("checkEmulators() got = %v, want %v", got, tt.want) 1932 } 1933 if !reflect.DeepEqual(errs, tt.wantErrs) { 1934 t.Errorf("checkEmulators() got = %v, want %v", errs, tt.wantErrs) 1935 } 1936 }) 1937 } 1938 } 1939 1940 func Test_initializer_initializeBatchCypress(t *testing.T) { 1941 dir := fs.NewDir(t, "apps", 1942 fs.WithFile("cypress.json", "{}", fs.WithMode(0644))) 1943 defer dir.Remove() 1944 1945 ini := &initializer{ 1946 infoReader: &mocks.FakeFrameworkInfoReader{VersionsFn: func(ctx context.Context, frameworkName string) ([]framework.Metadata, error) { 1947 return []framework.Metadata{ 1948 { 1949 FrameworkName: cypress.Kind, 1950 FrameworkVersion: "7.0.0", 1951 Platforms: []framework.Platform{ 1952 { 1953 PlatformName: "windows 10", 1954 BrowserNames: []string{"chrome", "firefox"}, 1955 }, 1956 }, 1957 }, 1958 }, nil 1959 }}, 1960 userService: &mocks.UserService{ConcurrencyFn: func(ctx context.Context) (iam.Concurrency, error) { 1961 return iam.Concurrency{ 1962 Org: iam.OrgConcurrency{ 1963 Allowed: iam.CloudConcurrency{ 1964 VDC: 2, 1965 }, 1966 }, 1967 }, nil 1968 }}, 1969 cfg: &initConfig{}, 1970 } 1971 var emptyErr []error 1972 1973 type args struct { 1974 initCfg *initConfig 1975 } 1976 tests := []struct { 1977 name string 1978 args args 1979 want *initConfig 1980 wantErrs []error 1981 }{ 1982 { 1983 name: "Basic", 1984 args: args{ 1985 initCfg: &initConfig{ 1986 frameworkName: cypress.Kind, 1987 frameworkVersion: "7.0.0", 1988 browserName: "chrome", 1989 platformName: "Windows 10", 1990 cypressConfigFile: dir.Join("cypress.json"), 1991 region: "us-west-1", 1992 artifactWhen: "fail", 1993 }, 1994 }, 1995 want: &initConfig{ 1996 frameworkName: cypress.Kind, 1997 frameworkVersion: "7.0.0", 1998 browserName: "chrome", 1999 platformName: "Windows 10", 2000 cypressConfigFile: dir.Join("cypress.json"), 2001 region: "us-west-1", 2002 artifactWhen: config.WhenFail, 2003 }, 2004 wantErrs: emptyErr, 2005 }, 2006 { 2007 name: "invalid browser/platform", 2008 args: args{ 2009 initCfg: &initConfig{ 2010 frameworkName: cypress.Kind, 2011 frameworkVersion: "7.0.0", 2012 browserName: "dummy", 2013 platformName: "dummy", 2014 artifactWhenStr: "dummy", 2015 }, 2016 }, 2017 want: &initConfig{ 2018 frameworkName: cypress.Kind, 2019 frameworkVersion: "7.0.0", 2020 browserName: "dummy", 2021 platformName: "dummy", 2022 artifactWhenStr: "dummy", 2023 }, 2024 wantErrs: []error{ 2025 errors.New("no cypress config file specified"), 2026 errors.New("dummy: unsupported browser. Supported browsers are: chrome, firefox"), 2027 errors.New("dummy: unknown download condition"), 2028 }, 2029 }, 2030 { 2031 name: "no flags", 2032 args: args{ 2033 initCfg: &initConfig{ 2034 frameworkName: cypress.Kind, 2035 }, 2036 }, 2037 want: &initConfig{ 2038 frameworkName: cypress.Kind, 2039 }, 2040 wantErrs: []error{ 2041 errors.New("no cypress version specified"), 2042 errors.New("no cypress config file specified"), 2043 errors.New("no platform name specified"), 2044 errors.New("no browser name specified"), 2045 }, 2046 }, 2047 { 2048 name: "invalid framework version / Invalid config file", 2049 args: args{ 2050 initCfg: &initConfig{ 2051 frameworkName: cypress.Kind, 2052 frameworkVersion: "8.0.0", 2053 cypressConfigFile: "/my/fake/cypress.json", 2054 }, 2055 }, 2056 want: &initConfig{ 2057 frameworkName: cypress.Kind, 2058 frameworkVersion: "8.0.0", 2059 cypressConfigFile: "/my/fake/cypress.json", 2060 }, 2061 wantErrs: []error{ 2062 errors.New("no platform name specified"), 2063 errors.New("no browser name specified"), 2064 errors.New("cypress 8.0.0 is not supported. Supported versions are: 7.0.0"), 2065 errors.New("/my/fake/cypress.json: stat /my/fake/cypress.json: no such file or directory"), 2066 }, 2067 }, 2068 } 2069 for _, tt := range tests { 2070 t.Run(tt.name, func(t *testing.T) { 2071 ini.cfg = tt.args.initCfg 2072 errs := ini.initializeBatchCypress() 2073 if !reflect.DeepEqual(ini.cfg, tt.want) { 2074 t.Errorf("initializeBatchCypress() got = %v, want %v", ini.cfg, tt.want) 2075 } 2076 if !reflect.DeepEqual(errs, tt.wantErrs) { 2077 t.Errorf("initializeBatchCypress() got = %v, want %v", errs, tt.wantErrs) 2078 } 2079 }) 2080 } 2081 } 2082 2083 func Test_initializer_initializeBatchTestcafe(t *testing.T) { 2084 ini := &initializer{ 2085 infoReader: &mocks.FakeFrameworkInfoReader{VersionsFn: func(ctx context.Context, frameworkName string) ([]framework.Metadata, error) { 2086 return []framework.Metadata{ 2087 { 2088 FrameworkName: testcafe.Kind, 2089 FrameworkVersion: "1.0.0", 2090 Platforms: []framework.Platform{ 2091 { 2092 PlatformName: "windows 10", 2093 BrowserNames: []string{"chrome", "firefox"}, 2094 }, 2095 { 2096 PlatformName: "macOS 11.00", 2097 BrowserNames: []string{"chrome", "firefox", "safari"}, 2098 }, 2099 }, 2100 }, 2101 }, nil 2102 }}, 2103 userService: &mocks.UserService{ConcurrencyFn: func(ctx context.Context) (iam.Concurrency, error) { 2104 return iam.Concurrency{ 2105 Org: iam.OrgConcurrency{ 2106 Allowed: iam.CloudConcurrency{ 2107 VDC: 2, 2108 }, 2109 }, 2110 }, nil 2111 }}, 2112 cfg: &initConfig{}, 2113 } 2114 var emptyErr []error 2115 2116 type args struct { 2117 initCfg *initConfig 2118 } 2119 tests := []struct { 2120 name string 2121 args args 2122 want *initConfig 2123 wantErrs []error 2124 }{ 2125 { 2126 name: "Basic", 2127 args: args{ 2128 initCfg: &initConfig{ 2129 frameworkName: testcafe.Kind, 2130 frameworkVersion: "1.0.0", 2131 browserName: "chrome", 2132 platformName: "Windows 10", 2133 region: "us-west-1", 2134 artifactWhen: "fail", 2135 }, 2136 }, 2137 want: &initConfig{ 2138 frameworkName: testcafe.Kind, 2139 frameworkVersion: "1.0.0", 2140 browserName: "chrome", 2141 platformName: "Windows 10", 2142 region: "us-west-1", 2143 artifactWhen: config.WhenFail, 2144 }, 2145 wantErrs: emptyErr, 2146 }, 2147 { 2148 name: "invalid browser/platform", 2149 args: args{ 2150 initCfg: &initConfig{ 2151 frameworkName: testcafe.Kind, 2152 frameworkVersion: "1.0.0", 2153 browserName: "dummy", 2154 platformName: "dummy", 2155 artifactWhenStr: "dummy", 2156 }, 2157 }, 2158 want: &initConfig{ 2159 frameworkName: testcafe.Kind, 2160 frameworkVersion: "1.0.0", 2161 browserName: "dummy", 2162 platformName: "dummy", 2163 artifactWhenStr: "dummy", 2164 }, 2165 wantErrs: []error{ 2166 errors.New("dummy: unsupported browser. Supported browsers are: chrome, firefox, safari"), 2167 errors.New("dummy: unknown download condition"), 2168 }, 2169 }, 2170 { 2171 name: "no flags", 2172 args: args{ 2173 initCfg: &initConfig{ 2174 frameworkName: testcafe.Kind, 2175 }, 2176 }, 2177 want: &initConfig{ 2178 frameworkName: testcafe.Kind, 2179 }, 2180 wantErrs: []error{ 2181 errors.New("no testcafe version specified"), 2182 errors.New("no platform name specified"), 2183 errors.New("no browser name specified"), 2184 }, 2185 }, 2186 { 2187 name: "invalid framework version / Invalid config file", 2188 args: args{ 2189 initCfg: &initConfig{ 2190 frameworkName: testcafe.Kind, 2191 frameworkVersion: "8.0.0", 2192 }, 2193 }, 2194 want: &initConfig{ 2195 frameworkName: testcafe.Kind, 2196 frameworkVersion: "8.0.0", 2197 }, 2198 wantErrs: []error{ 2199 errors.New("no platform name specified"), 2200 errors.New("no browser name specified"), 2201 errors.New("testcafe 8.0.0 is not supported. Supported versions are: 1.0.0"), 2202 }, 2203 }, 2204 } 2205 for _, tt := range tests { 2206 t.Run(tt.name, func(t *testing.T) { 2207 ini.cfg = tt.args.initCfg 2208 errs := ini.initializeBatchTestcafe() 2209 if !reflect.DeepEqual(ini.cfg, tt.want) { 2210 t.Errorf("initializeBatchTestcafe() got = %v, want %v", ini.cfg, tt.want) 2211 } 2212 if !reflect.DeepEqual(errs, tt.wantErrs) { 2213 t.Errorf("initializeBatchTestcafe() got = %v, want %v", errs, tt.wantErrs) 2214 } 2215 }) 2216 } 2217 } 2218 2219 func Test_initializer_initializeBatchPlaywright(t *testing.T) { 2220 ini := &initializer{ 2221 infoReader: &mocks.FakeFrameworkInfoReader{VersionsFn: func(ctx context.Context, frameworkName string) ([]framework.Metadata, error) { 2222 return []framework.Metadata{ 2223 { 2224 FrameworkName: playwright.Kind, 2225 FrameworkVersion: "1.0.0", 2226 Platforms: []framework.Platform{ 2227 { 2228 PlatformName: "windows 10", 2229 BrowserNames: []string{"chromium", "firefox", "webkit"}, 2230 }, 2231 }, 2232 }, 2233 }, nil 2234 }}, 2235 userService: &mocks.UserService{ConcurrencyFn: func(ctx context.Context) (iam.Concurrency, error) { 2236 return iam.Concurrency{ 2237 Org: iam.OrgConcurrency{ 2238 Allowed: iam.CloudConcurrency{ 2239 VDC: 2, 2240 }, 2241 }, 2242 }, nil 2243 }}, 2244 cfg: &initConfig{}, 2245 } 2246 var emptyErr []error 2247 2248 type args struct { 2249 initCfg *initConfig 2250 } 2251 tests := []struct { 2252 name string 2253 args args 2254 want *initConfig 2255 wantErrs []error 2256 }{ 2257 { 2258 name: "Basic", 2259 args: args{ 2260 initCfg: &initConfig{ 2261 frameworkName: playwright.Kind, 2262 frameworkVersion: "1.0.0", 2263 browserName: "chromium", 2264 platformName: "Windows 10", 2265 region: "us-west-1", 2266 artifactWhen: "fail", 2267 }, 2268 }, 2269 want: &initConfig{ 2270 frameworkName: playwright.Kind, 2271 frameworkVersion: "1.0.0", 2272 browserName: "chromium", 2273 platformName: "Windows 10", 2274 region: "us-west-1", 2275 artifactWhen: config.WhenFail, 2276 }, 2277 wantErrs: emptyErr, 2278 }, 2279 { 2280 name: "invalid browser/platform", 2281 args: args{ 2282 initCfg: &initConfig{ 2283 frameworkName: playwright.Kind, 2284 frameworkVersion: "1.0.0", 2285 browserName: "dummy", 2286 platformName: "dummy", 2287 artifactWhenStr: "dummy", 2288 }, 2289 }, 2290 want: &initConfig{ 2291 frameworkName: playwright.Kind, 2292 frameworkVersion: "1.0.0", 2293 browserName: "dummy", 2294 platformName: "dummy", 2295 artifactWhenStr: "dummy", 2296 }, 2297 wantErrs: []error{ 2298 errors.New("dummy: unsupported browser. Supported browsers are: chromium, firefox, webkit"), 2299 errors.New("dummy: unknown download condition"), 2300 }, 2301 }, 2302 { 2303 name: "no flags", 2304 args: args{ 2305 initCfg: &initConfig{ 2306 frameworkName: playwright.Kind, 2307 }, 2308 }, 2309 want: &initConfig{ 2310 frameworkName: playwright.Kind, 2311 }, 2312 wantErrs: []error{ 2313 errors.New("no playwright version specified"), 2314 errors.New("no platform name specified"), 2315 errors.New("no browser name specified"), 2316 }, 2317 }, 2318 { 2319 name: "invalid framework version / Invalid config file", 2320 args: args{ 2321 initCfg: &initConfig{ 2322 frameworkName: playwright.Kind, 2323 frameworkVersion: "8.0.0", 2324 }, 2325 }, 2326 want: &initConfig{ 2327 frameworkName: playwright.Kind, 2328 frameworkVersion: "8.0.0", 2329 }, 2330 wantErrs: []error{ 2331 errors.New("no platform name specified"), 2332 errors.New("no browser name specified"), 2333 errors.New("playwright 8.0.0 is not supported. Supported versions are: 1.0.0"), 2334 }, 2335 }, 2336 } 2337 for _, tt := range tests { 2338 t.Run(tt.name, func(t *testing.T) { 2339 ini.cfg = tt.args.initCfg 2340 errs := ini.initializeBatchPlaywright() 2341 if !reflect.DeepEqual(ini.cfg, tt.want) { 2342 t.Errorf("initializeBatchPlaywright() got = %v, want %v", ini.cfg, tt.want) 2343 } 2344 if !reflect.DeepEqual(errs, tt.wantErrs) { 2345 t.Errorf("initializeBatchPlaywright() got = %v, want %v", errs, tt.wantErrs) 2346 } 2347 }) 2348 } 2349 } 2350 2351 func Test_initializer_initializeBatchXcuitest(t *testing.T) { 2352 dir := fs.NewDir(t, "apps", 2353 fs.WithFile("ios-app.ipa", "myAppContent", fs.WithMode(0644)), 2354 fs.WithDir("ios-folder-app.app", fs.WithMode(0755))) 2355 defer dir.Remove() 2356 2357 ini := &initializer{ 2358 cfg: &initConfig{}, 2359 } 2360 var emptyErr []error 2361 2362 type args struct { 2363 initCfg *initConfig 2364 flags func() *pflag.FlagSet 2365 } 2366 tests := []struct { 2367 name string 2368 args args 2369 want *initConfig 2370 wantErrs []error 2371 }{ 2372 { 2373 name: "Basic", 2374 args: args{ 2375 flags: func() *pflag.FlagSet { 2376 var deviceFlag flags.Device 2377 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2378 p.Var(&deviceFlag, "device", "") 2379 err := p.Parse([]string{`--device`, `name=iPhone .*`}) 2380 if err != nil { 2381 t.Errorf("failed to parse test args: %v", err) 2382 } 2383 return p 2384 }, 2385 initCfg: &initConfig{ 2386 frameworkName: xcuitest.Kind, 2387 app: dir.Join("ios-app.ipa"), 2388 testApp: dir.Join("ios-app.ipa"), 2389 deviceFlag: flags.Device{ 2390 Changed: true, 2391 Device: config.Device{ 2392 Name: "iPhone .*", 2393 }, 2394 }, 2395 device: config.Device{ 2396 Name: "iPhone .*", 2397 }, 2398 region: "us-west-1", 2399 artifactWhen: "fail", 2400 }, 2401 }, 2402 want: &initConfig{ 2403 frameworkName: xcuitest.Kind, 2404 app: dir.Join("ios-app.ipa"), 2405 testApp: dir.Join("ios-app.ipa"), 2406 deviceFlag: flags.Device{ 2407 Changed: true, 2408 Device: config.Device{ 2409 Name: "iPhone .*", 2410 }, 2411 }, 2412 device: config.Device{ 2413 Name: "iPhone .*", 2414 }, 2415 region: "us-west-1", 2416 artifactWhen: config.WhenFail, 2417 }, 2418 wantErrs: emptyErr, 2419 }, 2420 { 2421 name: "invalid download config", 2422 args: args{ 2423 flags: func() *pflag.FlagSet { 2424 var deviceFlag flags.Device 2425 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2426 p.Var(&deviceFlag, "device", "") 2427 return p 2428 }, 2429 initCfg: &initConfig{ 2430 frameworkName: xcuitest.Kind, 2431 artifactWhenStr: "dummy", 2432 }, 2433 }, 2434 want: &initConfig{ 2435 frameworkName: xcuitest.Kind, 2436 artifactWhenStr: "dummy", 2437 }, 2438 wantErrs: []error{ 2439 errors.New("no app provided"), 2440 errors.New("no testApp provided"), 2441 errors.New("either device or simulator configuration needs to be provided"), 2442 errors.New("dummy: unknown download condition"), 2443 }, 2444 }, 2445 { 2446 name: "no flags", 2447 args: args{ 2448 flags: func() *pflag.FlagSet { 2449 var deviceFlag flags.Device 2450 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2451 p.Var(&deviceFlag, "device", "") 2452 return p 2453 }, 2454 initCfg: &initConfig{ 2455 frameworkName: xcuitest.Kind, 2456 }, 2457 }, 2458 want: &initConfig{ 2459 frameworkName: xcuitest.Kind, 2460 }, 2461 wantErrs: []error{ 2462 errors.New("no app provided"), 2463 errors.New("no testApp provided"), 2464 errors.New("either device or simulator configuration needs to be provided"), 2465 }, 2466 }, 2467 { 2468 name: "invalid app file / test file", 2469 args: args{ 2470 flags: func() *pflag.FlagSet { 2471 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2472 return p 2473 }, 2474 initCfg: &initConfig{ 2475 frameworkName: xcuitest.Kind, 2476 app: dir.Join("truc", "ios-app.ipa"), 2477 testApp: dir.Join("truc", "ios-app.ipa"), 2478 }, 2479 }, 2480 want: &initConfig{ 2481 frameworkName: xcuitest.Kind, 2482 app: dir.Join("truc", "ios-app.ipa"), 2483 testApp: dir.Join("truc", "ios-app.ipa"), 2484 }, 2485 wantErrs: []error{ 2486 errors.New("either device or simulator configuration needs to be provided"), 2487 fmt.Errorf("app: %s: stat %s: no such file or directory", dir.Join("truc", "ios-app.ipa"), dir.Join("truc", "ios-app.ipa")), 2488 fmt.Errorf("testApp: %s: stat %s: no such file or directory", dir.Join("truc", "ios-app.ipa"), dir.Join("truc", "ios-app.ipa")), 2489 }, 2490 }, 2491 } 2492 for _, tt := range tests { 2493 t.Run(tt.name, func(t *testing.T) { 2494 ini.cfg = tt.args.initCfg 2495 errs := ini.initializeBatchXcuitest(tt.args.flags()) 2496 if !reflect.DeepEqual(ini.cfg, tt.want) { 2497 t.Errorf("initializeBatchXcuitest() got = %v, want %v", ini.cfg, tt.want) 2498 } 2499 if !reflect.DeepEqual(errs, tt.wantErrs) { 2500 t.Errorf("initializeBatchXcuitest() got = %v, want %v", errs, tt.wantErrs) 2501 } 2502 }) 2503 } 2504 } 2505 2506 func Test_initializer_initializeBatchEspresso(t *testing.T) { 2507 dir := fs.NewDir(t, "apps", 2508 fs.WithFile("android-app.apk", "myAppContent", fs.WithMode(0644))) 2509 defer dir.Remove() 2510 2511 ini := &initializer{ 2512 cfg: &initConfig{}, 2513 } 2514 var emptyErr []error 2515 2516 type args struct { 2517 initCfg *initConfig 2518 flags func() *pflag.FlagSet 2519 } 2520 tests := []struct { 2521 name string 2522 args args 2523 want *initConfig 2524 wantErrs []error 2525 }{ 2526 { 2527 name: "Basic", 2528 args: args{ 2529 flags: func() *pflag.FlagSet { 2530 var deviceFlag flags.Device 2531 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2532 p.Var(&deviceFlag, "device", "") 2533 err := p.Parse([]string{`--device`, `name=HTC .*`}) 2534 if err != nil { 2535 t.Errorf("failed to parse test args: %v", err) 2536 } 2537 return p 2538 }, 2539 initCfg: &initConfig{ 2540 frameworkName: espresso.Kind, 2541 app: dir.Join("android-app.apk"), 2542 testApp: dir.Join("android-app.apk"), 2543 deviceFlag: flags.Device{ 2544 Changed: true, 2545 Device: config.Device{ 2546 Name: "HTC .*", 2547 }, 2548 }, 2549 region: "us-west-1", 2550 artifactWhen: "fail", 2551 }, 2552 }, 2553 want: &initConfig{ 2554 frameworkName: espresso.Kind, 2555 app: dir.Join("android-app.apk"), 2556 testApp: dir.Join("android-app.apk"), 2557 deviceFlag: flags.Device{ 2558 Changed: true, 2559 Device: config.Device{ 2560 Name: "HTC .*", 2561 }, 2562 }, 2563 device: config.Device{ 2564 Name: "HTC .*", 2565 }, 2566 region: "us-west-1", 2567 artifactWhen: config.WhenFail, 2568 }, 2569 wantErrs: emptyErr, 2570 }, 2571 { 2572 name: "invalid download config", 2573 args: args{ 2574 flags: func() *pflag.FlagSet { 2575 var deviceFlag flags.Device 2576 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2577 p.Var(&deviceFlag, "device", "") 2578 return p 2579 }, 2580 initCfg: &initConfig{ 2581 frameworkName: espresso.Kind, 2582 artifactWhenStr: "dummy", 2583 }, 2584 }, 2585 want: &initConfig{ 2586 frameworkName: espresso.Kind, 2587 artifactWhenStr: "dummy", 2588 }, 2589 wantErrs: []error{ 2590 errors.New("no app provided"), 2591 errors.New("no testApp provided"), 2592 errors.New("either device or emulator configuration needs to be provided"), 2593 errors.New("dummy: unknown download condition"), 2594 }, 2595 }, 2596 { 2597 name: "no flags", 2598 args: args{ 2599 flags: func() *pflag.FlagSet { 2600 var deviceFlag flags.Device 2601 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2602 p.Var(&deviceFlag, "device", "") 2603 return p 2604 }, 2605 initCfg: &initConfig{ 2606 frameworkName: espresso.Kind, 2607 }, 2608 }, 2609 want: &initConfig{ 2610 frameworkName: espresso.Kind, 2611 }, 2612 wantErrs: []error{ 2613 errors.New("no app provided"), 2614 errors.New("no testApp provided"), 2615 errors.New("either device or emulator configuration needs to be provided"), 2616 }, 2617 }, 2618 { 2619 name: "invalid app file / test file", 2620 args: args{ 2621 flags: func() *pflag.FlagSet { 2622 var deviceFlag flags.Device 2623 p := pflag.NewFlagSet("tests", pflag.ContinueOnError) 2624 p.Var(&deviceFlag, "device", "") 2625 return p 2626 }, 2627 initCfg: &initConfig{ 2628 frameworkName: espresso.Kind, 2629 app: dir.Join("truc", "android-app.apk"), 2630 testApp: dir.Join("truc", "android-app.apk"), 2631 }, 2632 }, 2633 want: &initConfig{ 2634 frameworkName: espresso.Kind, 2635 app: dir.Join("truc", "android-app.apk"), 2636 testApp: dir.Join("truc", "android-app.apk"), 2637 }, 2638 wantErrs: []error{ 2639 errors.New("either device or emulator configuration needs to be provided"), 2640 fmt.Errorf("app: %s: stat %s: no such file or directory", dir.Join("truc", "android-app.apk"), dir.Join("truc", "android-app.apk")), 2641 fmt.Errorf("testApp: %s: stat %s: no such file or directory", dir.Join("truc", "android-app.apk"), dir.Join("truc", "android-app.apk")), 2642 }, 2643 }, 2644 } 2645 for _, tt := range tests { 2646 t.Run(tt.name, func(t *testing.T) { 2647 ini.cfg = tt.args.initCfg 2648 errs := ini.initializeBatchEspresso(tt.args.flags()) 2649 if !reflect.DeepEqual(ini.cfg, tt.want) { 2650 t.Errorf("initializeBatchEspresso() got = %v, want %v", ini.cfg, tt.want) 2651 } 2652 if !reflect.DeepEqual(errs, tt.wantErrs) { 2653 t.Errorf("initializeBatchEspresso() got = %v, want %v", errs, tt.wantErrs) 2654 } 2655 }) 2656 } 2657 } 2658 2659 func Test_initializer_initializeBatchImageRunner(t *testing.T) { 2660 ini := &initializer{ 2661 infoReader: &mocks.FakeFrameworkInfoReader{VersionsFn: func(ctx context.Context, frameworkName string) ([]framework.Metadata, error) { 2662 return []framework.Metadata{ 2663 { 2664 FrameworkName: "imagerunner", 2665 FrameworkVersion: "", 2666 }, 2667 }, nil 2668 }}, 2669 userService: &mocks.UserService{ConcurrencyFn: func(ctx context.Context) (iam.Concurrency, error) { 2670 return iam.Concurrency{ 2671 Org: iam.OrgConcurrency{ 2672 Allowed: iam.CloudConcurrency{ 2673 VDC: 2, 2674 }, 2675 }, 2676 }, nil 2677 }}, 2678 cfg: &initConfig{}, 2679 } 2680 var emptyErr []error 2681 2682 type args struct { 2683 initCfg *initConfig 2684 } 2685 tests := []struct { 2686 name string 2687 args args 2688 want *initConfig 2689 wantErrs []error 2690 }{ 2691 { 2692 name: "Basic", 2693 args: args{ 2694 initCfg: &initConfig{ 2695 frameworkName: "imagerunner", 2696 dockerImage: "ubuntu:latest", 2697 region: "us-west-1", 2698 artifactWhen: "fail", 2699 }, 2700 }, 2701 want: &initConfig{ 2702 frameworkName: "imagerunner", 2703 dockerImage: "ubuntu:latest", 2704 region: "us-west-1", 2705 artifactWhen: config.WhenFail, 2706 }, 2707 wantErrs: emptyErr, 2708 }, 2709 { 2710 name: "invalid browser/platform", 2711 args: args{ 2712 initCfg: &initConfig{ 2713 frameworkName: "imagerunner", 2714 dockerImage: "ubuntu::buggy", 2715 artifactWhenStr: "dummy", 2716 }, 2717 }, 2718 want: &initConfig{ 2719 frameworkName: "imagerunner", 2720 dockerImage: "ubuntu::buggy", 2721 artifactWhenStr: "dummy", 2722 }, 2723 wantErrs: []error{ 2724 errors.New("dockerImage: ubuntu::buggy is not a valid docker image"), 2725 errors.New("dummy: unknown download condition"), 2726 }, 2727 }, 2728 { 2729 name: "no flags", 2730 args: args{ 2731 initCfg: &initConfig{ 2732 frameworkName: "imagerunner", 2733 }, 2734 }, 2735 want: &initConfig{ 2736 frameworkName: "imagerunner", 2737 }, 2738 wantErrs: []error{ 2739 errors.New(msg.MissingDockerImage), 2740 }, 2741 }, 2742 } 2743 for _, tt := range tests { 2744 t.Run(tt.name, func(t *testing.T) { 2745 ini.cfg = tt.args.initCfg 2746 errs := ini.initializeBatchImageRunner() 2747 if !reflect.DeepEqual(ini.cfg, tt.want) { 2748 t.Errorf("initializeBatchImageRunner() got = %v, want %v", ini.cfg, tt.want) 2749 } 2750 if !reflect.DeepEqual(errs, tt.wantErrs) { 2751 t.Errorf("initializeBatchImageRunner() got = %v, want %v", errs, tt.wantErrs) 2752 } 2753 }) 2754 } 2755 }