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  }