github.com/saucelabs/saucectl@v0.175.1/internal/espresso/config_test.go (about)

     1  package espresso
     2  
     3  import (
     4  	"errors"
     5  	"path/filepath"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/saucelabs/saucectl/internal/config"
    10  	"github.com/saucelabs/saucectl/internal/insights"
    11  	"github.com/stretchr/testify/assert"
    12  	"gotest.tools/v3/fs"
    13  )
    14  
    15  func TestValidateThrowsErrors(t *testing.T) {
    16  	dir := fs.NewDir(t, "espresso",
    17  		fs.WithFile("test.apk", "", fs.WithMode(0655)))
    18  	defer dir.Remove()
    19  	appAPK := filepath.Join(dir.Path(), "test.apk")
    20  
    21  	testCases := []struct {
    22  		name        string
    23  		p           *Project
    24  		expectedErr error
    25  	}{
    26  		{
    27  			name:        "validating throws error on empty app",
    28  			p:           &Project{Sauce: config.SauceConfig{Region: "us-west-1"}},
    29  			expectedErr: errors.New("missing path to app. Define a path to an .apk or .aab file in the espresso.app property of your config"),
    30  		},
    31  		{
    32  			name: "validating throws error on app missing .apk",
    33  			p: &Project{
    34  				Sauce: config.SauceConfig{Region: "us-west-1"},
    35  				Espresso: Espresso{
    36  					App: "/path/to/app",
    37  				},
    38  			},
    39  			expectedErr: errors.New("invalid application file: /path/to/app, make sure extension is one of the following: .apk, .aab"),
    40  		},
    41  		{
    42  			name: "validating throws error on empty app",
    43  			p: &Project{
    44  				Sauce: config.SauceConfig{Region: "us-west-1"},
    45  				Espresso: Espresso{
    46  					App: appAPK,
    47  				},
    48  			},
    49  			expectedErr: errors.New("missing path to test app. Define a path to an .apk or .aab file in the espresso.testApp property of your config"),
    50  		},
    51  		{
    52  			name: "validating throws error on test app missing .apk",
    53  			p: &Project{
    54  				Sauce: config.SauceConfig{Region: "us-west-1"},
    55  				Espresso: Espresso{
    56  					App:     appAPK,
    57  					TestApp: "/path/to/testApp",
    58  				},
    59  			},
    60  			expectedErr: errors.New("invalid test application file: /path/to/testApp, make sure extension is one of the following: .apk, .aab"),
    61  		},
    62  		{
    63  			name: "validating throws error on missing suites",
    64  			p: &Project{
    65  				Sauce: config.SauceConfig{Region: "us-west-1"},
    66  				Espresso: Espresso{
    67  					App:     appAPK,
    68  					TestApp: appAPK,
    69  				},
    70  			},
    71  			expectedErr: errors.New("no suites defined"),
    72  		},
    73  		{
    74  			name: "validating throws error on missing devices",
    75  			p: &Project{
    76  				Sauce: config.SauceConfig{Region: "us-west-1"},
    77  				Espresso: Espresso{
    78  					App:     appAPK,
    79  					TestApp: appAPK,
    80  				},
    81  				Suites: []Suite{
    82  					{
    83  						Name:    "no devices",
    84  						Devices: []config.Device{},
    85  					},
    86  				},
    87  			},
    88  			expectedErr: errors.New("missing devices or emulators configuration for suite: no devices"),
    89  		},
    90  		{
    91  			name: "validating throws error on missing device name",
    92  			p: &Project{
    93  				Sauce: config.SauceConfig{Region: "us-west-1"},
    94  				Espresso: Espresso{
    95  					App:     appAPK,
    96  					TestApp: appAPK,
    97  				},
    98  				Suites: []Suite{
    99  					{
   100  						Name: "empty emulator name",
   101  						Emulators: []config.Emulator{
   102  							{
   103  								Name: "",
   104  							},
   105  						},
   106  					},
   107  				},
   108  			},
   109  			expectedErr: errors.New("missing emulator name for suite: empty emulator name. Emulators index: 0"),
   110  		},
   111  		{
   112  			name: "validating throws error on missing Emulator suffix on device name",
   113  			p: &Project{
   114  				Sauce: config.SauceConfig{Region: "us-west-1"},
   115  				Espresso: Espresso{
   116  					App:     appAPK,
   117  					TestApp: appAPK,
   118  				},
   119  				Suites: []Suite{
   120  					{
   121  						Name: "no emulator device name",
   122  						Emulators: []config.Emulator{
   123  							{
   124  								Name: "Android GoogleApi something",
   125  							},
   126  						},
   127  					},
   128  				},
   129  			},
   130  			expectedErr: errors.New(`missing "emulator" in emulator name: Android GoogleApi something. Suite name: no emulator device name. Emulators index: 0`),
   131  		},
   132  		{
   133  			name: "validating throws error on missing platform versions",
   134  			p: &Project{
   135  				Sauce: config.SauceConfig{Region: "us-west-1"},
   136  				Espresso: Espresso{
   137  					App:     appAPK,
   138  					TestApp: appAPK,
   139  				},
   140  				Suites: []Suite{
   141  					{
   142  						Name: "no emulator device name",
   143  						Emulators: []config.Emulator{
   144  							{
   145  								Name:             "Android GoogleApi Emulator",
   146  								PlatformVersions: []string{},
   147  							},
   148  						},
   149  					},
   150  				},
   151  			},
   152  			expectedErr: errors.New("missing platform versions for emulator: Android GoogleApi Emulator. Suite name: no emulator device name. Emulators index: 0"),
   153  		},
   154  	}
   155  	for _, tc := range testCases {
   156  		t.Run(tc.name, func(t *testing.T) {
   157  			err := Validate(*tc.p)
   158  			assert.NotNil(t, err)
   159  			assert.Equal(t, tc.expectedErr.Error(), err.Error())
   160  		})
   161  	}
   162  }
   163  
   164  func TestFromFile(t *testing.T) {
   165  	dir := fs.NewDir(t, "espresso-cfg",
   166  		fs.WithFile("config.yml", `apiVersion: v1alpha
   167  kind: espresso
   168  espresso:
   169    app: ./tests/apps/mda-1.0.17-20.apk
   170    testApp: ./tests/apps/mda-androidTest-1.0.17-20.apk
   171  suites:
   172    - name: "saucy barista"
   173      devices:
   174        - name: "Device name"
   175          platformVersion: 8.1
   176          options:
   177            deviceType: TABLET
   178      emulators:
   179        - name: "Google Pixel C GoogleAPI Emulator"
   180          platformVersions:
   181            - "8.1"
   182  `, fs.WithMode(0655)))
   183  	defer dir.Remove()
   184  
   185  	cfg, err := FromFile(filepath.Join(dir.Path(), "config.yml"))
   186  	if err != nil {
   187  		t.Errorf("expected error: %v, got: %v", nil, err)
   188  	}
   189  	expected := Project{
   190  		ConfigFilePath: filepath.Join(dir.Path(), "config.yml"),
   191  		Espresso: Espresso{
   192  			App:     "./tests/apps/mda-1.0.17-20.apk",
   193  			TestApp: "./tests/apps/mda-androidTest-1.0.17-20.apk",
   194  		},
   195  		Suites: []Suite{
   196  			{
   197  				Name: "saucy barista",
   198  				Devices: []config.Device{
   199  					{
   200  						Name:            "Device name",
   201  						PlatformVersion: "8.1",
   202  						Options: config.DeviceOptions{
   203  							DeviceType: "TABLET",
   204  						},
   205  					},
   206  				},
   207  				Emulators: []config.Emulator{
   208  					{
   209  						Name: "Google Pixel C GoogleAPI Emulator",
   210  						PlatformVersions: []string{
   211  							"8.1",
   212  						},
   213  					},
   214  				}},
   215  		},
   216  	}
   217  	if !reflect.DeepEqual(cfg.Espresso, expected.Espresso) {
   218  		t.Errorf("expected: %v, got: %v", expected.Espresso, cfg.Espresso)
   219  	}
   220  	if !reflect.DeepEqual(cfg.Suites, expected.Suites) {
   221  		t.Errorf("expected: %v, got: %v", expected.Suites, cfg.Suites)
   222  	}
   223  
   224  }
   225  
   226  func TestSetDefaults_TestApp(t *testing.T) {
   227  	testCase := []struct {
   228  		name      string
   229  		project   Project
   230  		expResult string
   231  	}{
   232  		{
   233  			name: "Set TestApp on suite level",
   234  			project: Project{
   235  				Espresso: Espresso{
   236  					TestApp: "test-app",
   237  				},
   238  				Suites: []Suite{
   239  					{
   240  						TestApp: "suite-test-app",
   241  					},
   242  				},
   243  			},
   244  			expResult: "suite-test-app",
   245  		},
   246  		{
   247  			name: "Set empty TestApp on suite level",
   248  			project: Project{
   249  				Espresso: Espresso{
   250  					TestApp: "test-app",
   251  				},
   252  				Suites: []Suite{
   253  					{},
   254  				},
   255  			},
   256  			expResult: "test-app",
   257  		},
   258  	}
   259  	for _, tc := range testCase {
   260  		t.Run(tc.name, func(t *testing.T) {
   261  			SetDefaults(&tc.project)
   262  			assert.Equal(t, tc.expResult, tc.project.Suites[0].TestApp)
   263  		})
   264  	}
   265  }
   266  
   267  func TestEspresso_SortByHistory(t *testing.T) {
   268  	testCases := []struct {
   269  		name    string
   270  		suites  []Suite
   271  		history insights.JobHistory
   272  		expRes  []Suite
   273  	}{
   274  		{
   275  			name: "sort suites by job history",
   276  			suites: []Suite{
   277  				Suite{Name: "suite 1"},
   278  				Suite{Name: "suite 2"},
   279  				Suite{Name: "suite 3"},
   280  			},
   281  			history: insights.JobHistory{
   282  				TestCases: []insights.TestCase{
   283  					insights.TestCase{Name: "suite 2"},
   284  					insights.TestCase{Name: "suite 1"},
   285  					insights.TestCase{Name: "suite 3"},
   286  				},
   287  			},
   288  			expRes: []Suite{
   289  				Suite{Name: "suite 2"},
   290  				Suite{Name: "suite 1"},
   291  				Suite{Name: "suite 3"},
   292  			},
   293  		},
   294  		{
   295  			name: "suites is the subset of job history",
   296  			suites: []Suite{
   297  				Suite{Name: "suite 1"},
   298  				Suite{Name: "suite 2"},
   299  			},
   300  			history: insights.JobHistory{
   301  				TestCases: []insights.TestCase{
   302  					insights.TestCase{Name: "suite 2"},
   303  					insights.TestCase{Name: "suite 1"},
   304  					insights.TestCase{Name: "suite 3"},
   305  				},
   306  			},
   307  			expRes: []Suite{
   308  				Suite{Name: "suite 2"},
   309  				Suite{Name: "suite 1"},
   310  			},
   311  		},
   312  		{
   313  			name: "job history is the subset of suites",
   314  			suites: []Suite{
   315  				Suite{Name: "suite 1"},
   316  				Suite{Name: "suite 2"},
   317  				Suite{Name: "suite 3"},
   318  				Suite{Name: "suite 4"},
   319  				Suite{Name: "suite 5"},
   320  			},
   321  			history: insights.JobHistory{
   322  				TestCases: []insights.TestCase{
   323  					insights.TestCase{Name: "suite 2"},
   324  					insights.TestCase{Name: "suite 1"},
   325  					insights.TestCase{Name: "suite 3"},
   326  				},
   327  			},
   328  			expRes: []Suite{
   329  				Suite{Name: "suite 2"},
   330  				Suite{Name: "suite 1"},
   331  				Suite{Name: "suite 3"},
   332  				Suite{Name: "suite 4"},
   333  				Suite{Name: "suite 5"},
   334  			},
   335  		},
   336  	}
   337  
   338  	for _, tc := range testCases {
   339  		t.Run(tc.name, func(t *testing.T) {
   340  			result := SortByHistory(tc.suites, tc.history)
   341  			for i := 0; i < len(result); i++ {
   342  				assert.Equal(t, tc.expRes[i].Name, result[i].Name)
   343  			}
   344  		})
   345  	}
   346  }