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 }