github.com/saucelabs/saucectl@v0.175.1/internal/testcafe/config_test.go (about) 1 package testcafe 2 3 import ( 4 "errors" 5 "os" 6 "reflect" 7 "testing" 8 9 "github.com/saucelabs/saucectl/internal/insights" 10 "github.com/saucelabs/saucectl/internal/saucereport" 11 "github.com/stretchr/testify/assert" 12 "gotest.tools/v3/fs" 13 ) 14 15 func Test_appleDeviceRegex(t *testing.T) { 16 tests := []struct { 17 deviceName string 18 want bool 19 }{ 20 { 21 deviceName: "iPhone Simulator", 22 want: true, 23 }, 24 { 25 deviceName: "iphone simulator", 26 want: true, 27 }, 28 { 29 deviceName: "iPhone SE (2nd generation) Simulator", 30 want: true, 31 }, 32 { 33 deviceName: "iPhone 8 Simulator", 34 want: true, 35 }, 36 { 37 deviceName: "iPhone 8 Plus Simulator", 38 want: true, 39 }, 40 { 41 deviceName: "iPad Pro (12.9 inch) Simulator", 42 want: true, 43 }, 44 { 45 deviceName: "iPad Pro (12.9 inch) (4th generation) Simulator", 46 want: true, 47 }, 48 { 49 deviceName: "iPad Air Simulator", 50 want: true, 51 }, 52 { 53 deviceName: "iPad (8th generation) Simulator", 54 want: true, 55 }, 56 { 57 deviceName: "iPad mini (5th generation) Simulator", 58 want: true, 59 }, 60 { 61 deviceName: "Android GoogleAPI Emulator", 62 want: false, 63 }, 64 { 65 deviceName: "Google Pixel 3a GoogleAPI Emulator", 66 want: false, 67 }, 68 } 69 for _, tt := range tests { 70 t.Run(tt.deviceName, func(t *testing.T) { 71 got := appleDeviceRegex.MatchString(tt.deviceName) 72 if got != tt.want { 73 t.Errorf("appleDeviceRegex.MatchString() got = %v, want %v", got, tt.want) 74 } 75 }) 76 } 77 } 78 79 func TestFilterSuites(t *testing.T) { 80 testCase := []struct { 81 name string 82 config *Project 83 suiteName string 84 expConfig Project 85 expErr string 86 }{ 87 { 88 name: "filtered suite exists in config", 89 config: &Project{Suites: []Suite{ 90 { 91 Name: "suite1", 92 }, 93 { 94 Name: "suite2", 95 }, 96 }}, 97 suiteName: "suite1", 98 expConfig: Project{Suites: []Suite{ 99 { 100 Name: "suite1", 101 }, 102 }}, 103 }, 104 { 105 name: "filtered suite does not exist in config", 106 config: &Project{Suites: []Suite{ 107 { 108 Name: "suite1", 109 }, 110 { 111 Name: "suite2", 112 }, 113 }}, 114 suiteName: "suite3", 115 expConfig: Project{Suites: []Suite{ 116 { 117 Name: "suite1", 118 }, 119 { 120 Name: "suite2", 121 }, 122 }}, 123 expErr: "no suite named 'suite3' found", 124 }, 125 } 126 127 for _, tc := range testCase { 128 t.Run(tc.name, func(t *testing.T) { 129 err := FilterSuites(tc.config, tc.suiteName) 130 if err != nil { 131 assert.Equal(t, tc.expErr, err.Error()) 132 } 133 assert.True(t, reflect.DeepEqual(*tc.config, tc.expConfig)) 134 }) 135 } 136 } 137 138 func Test_shardSuites_withSplit(t *testing.T) { 139 dir := fs.NewDir(t, "testcafe", 140 fs.WithFile(".sauceignore", "", fs.WithMode(0644)), 141 fs.WithDir("tests", 142 fs.WithMode(0755), 143 fs.WithDir("dir1", 144 fs.WithMode(0755), 145 fs.WithFile("example1.tests.js", "", fs.WithMode(0644)), 146 ), 147 fs.WithDir("dir2", 148 fs.WithMode(0755), 149 fs.WithFile("example2.tests.js", "", fs.WithMode(0644)), 150 ), 151 fs.WithDir("dir3", 152 fs.WithMode(0755), 153 fs.WithFile("example3.tests.js", "", fs.WithMode(0644)), 154 ), 155 ), 156 ) 157 defer dir.Remove() 158 159 // Beginning state 160 rootDir := dir.Path() 161 origSuites := []Suite{ 162 { 163 Name: "Demo Suite", 164 Src: []string{"tests/**/*.js"}, 165 Shard: "spec", 166 }, 167 } 168 169 expectedSuites := []Suite{ 170 { 171 Name: "Demo Suite - tests/dir1/example1.tests.js", 172 Src: []string{"tests/dir1/example1.tests.js"}, 173 Shard: "spec", 174 }, 175 { 176 Name: "Demo Suite - tests/dir2/example2.tests.js", 177 Src: []string{"tests/dir2/example2.tests.js"}, 178 Shard: "spec", 179 }, 180 { 181 Name: "Demo Suite - tests/dir3/example3.tests.js", 182 Src: []string{"tests/dir3/example3.tests.js"}, 183 Shard: "spec", 184 }, 185 } 186 var err error 187 var suites []Suite 188 189 // Absolute path 190 suites, err = shardSuites(rootDir, origSuites, 1, dir.Join(".sauceignore")) 191 192 assert.Equal(t, err, nil) 193 assert.Equal(t, expectedSuites, suites) 194 195 // Relative path 196 if err := os.Chdir(rootDir); err != nil { 197 t.Errorf("Unexpected error %s", err) 198 } 199 suites, err = shardSuites(".", origSuites, 1, dir.Join(".sauceignore")) 200 201 assert.Equal(t, err, nil) 202 assert.Equal(t, expectedSuites, suites) 203 } 204 205 func Test_shardSuites_withoutSplit(t *testing.T) { 206 dir := fs.NewDir(t, "testcafe", 207 fs.WithFile(".sauceignore", "", fs.WithMode(0644)), 208 ) 209 defer dir.Remove() 210 origSuites := []Suite{ 211 { 212 Name: "Demo Suite", 213 Src: []string{"tests/**/*.js"}, 214 }, 215 } 216 var err error 217 var suites []Suite 218 219 // Absolute path 220 suites, err = shardSuites("", origSuites, 1, dir.Join(".sauceignore")) 221 222 assert.Equal(t, err, nil) 223 assert.Equal(t, origSuites, suites) 224 } 225 226 func Test_shardSuites_withSplitNoMatch(t *testing.T) { 227 dir := fs.NewDir(t, "testcafe", 228 fs.WithFile(".sauceignore", "", fs.WithMode(0644)), 229 fs.WithDir("tests", 230 fs.WithMode(0755), 231 fs.WithDir("dir1", 232 fs.WithMode(0755), 233 fs.WithFile("example1.tests.js", "", fs.WithMode(0644)), 234 ), 235 fs.WithDir("dir2", 236 fs.WithMode(0755), 237 fs.WithFile("example2.tests.js", "", fs.WithMode(0644)), 238 ), 239 fs.WithDir("dir3", 240 fs.WithMode(0755), 241 fs.WithFile("example3.tests.js", "", fs.WithMode(0644)), 242 ), 243 ), 244 ) 245 defer dir.Remove() 246 247 // Beginning state 248 rootDir := dir.Path() 249 origSuites := []Suite{ 250 { 251 Name: "Demo Suite", 252 Src: []string{"dummy/**/*.js"}, 253 Shard: "spec", 254 }, 255 } 256 257 expectedSuites := make([]Suite, 0) 258 var err error 259 var suites []Suite 260 261 // Absolute path 262 suites, err = shardSuites(rootDir, origSuites, 1, dir.Join(".sauceignore")) 263 264 assert.Equal(t, err, errors.New("suite 'Demo Suite' patterns have no matching files")) 265 assert.Equal(t, expectedSuites, suites) 266 267 // Relative path 268 if err := os.Chdir(rootDir); err != nil { 269 t.Errorf("Unexpected error %s", err) 270 } 271 suites, err = shardSuites(".", origSuites, 1, dir.Join(".sauceignore")) 272 273 assert.Equal(t, err, errors.New("suite 'Demo Suite' patterns have no matching files")) 274 assert.Equal(t, expectedSuites, suites) 275 } 276 277 func TestTestcafe_SortByHistory(t *testing.T) { 278 testCases := []struct { 279 name string 280 suites []Suite 281 history insights.JobHistory 282 expRes []Suite 283 }{ 284 { 285 name: "sort suites by job history", 286 suites: []Suite{ 287 Suite{Name: "suite 1"}, 288 Suite{Name: "suite 2"}, 289 Suite{Name: "suite 3"}, 290 }, 291 history: insights.JobHistory{ 292 TestCases: []insights.TestCase{ 293 insights.TestCase{Name: "suite 2"}, 294 insights.TestCase{Name: "suite 1"}, 295 insights.TestCase{Name: "suite 3"}, 296 }, 297 }, 298 expRes: []Suite{ 299 Suite{Name: "suite 2"}, 300 Suite{Name: "suite 1"}, 301 Suite{Name: "suite 3"}, 302 }, 303 }, 304 { 305 name: "suites is the subset of job history", 306 suites: []Suite{ 307 Suite{Name: "suite 1"}, 308 Suite{Name: "suite 2"}, 309 }, 310 history: insights.JobHistory{ 311 TestCases: []insights.TestCase{ 312 insights.TestCase{Name: "suite 2"}, 313 insights.TestCase{Name: "suite 1"}, 314 insights.TestCase{Name: "suite 3"}, 315 }, 316 }, 317 expRes: []Suite{ 318 Suite{Name: "suite 2"}, 319 Suite{Name: "suite 1"}, 320 }, 321 }, 322 { 323 name: "job history is the subset of suites", 324 suites: []Suite{ 325 Suite{Name: "suite 1"}, 326 Suite{Name: "suite 2"}, 327 Suite{Name: "suite 3"}, 328 Suite{Name: "suite 4"}, 329 Suite{Name: "suite 5"}, 330 }, 331 history: insights.JobHistory{ 332 TestCases: []insights.TestCase{ 333 insights.TestCase{Name: "suite 2"}, 334 insights.TestCase{Name: "suite 1"}, 335 insights.TestCase{Name: "suite 3"}, 336 }, 337 }, 338 expRes: []Suite{ 339 Suite{Name: "suite 2"}, 340 Suite{Name: "suite 1"}, 341 Suite{Name: "suite 3"}, 342 Suite{Name: "suite 4"}, 343 Suite{Name: "suite 5"}, 344 }, 345 }, 346 } 347 348 for _, tc := range testCases { 349 t.Run(tc.name, func(t *testing.T) { 350 result := SortByHistory(tc.suites, tc.history) 351 for i := 0; i < len(result); i++ { 352 assert.Equal(t, tc.expRes[i].Name, result[i].Name) 353 } 354 }) 355 } 356 } 357 358 func TestTestcafe_FilterFailedTests(t *testing.T) { 359 testcases := []struct { 360 name string 361 suiteName string 362 report saucereport.SauceReport 363 project *Project 364 expResult string 365 expErr error 366 }{ 367 { 368 name: "it should set failed tests to specified suite", 369 suiteName: "my suite", 370 report: saucereport.SauceReport{ 371 Status: saucereport.StatusFailed, 372 Suites: []saucereport.Suite{ 373 { 374 Name: "my suite", 375 Status: saucereport.StatusFailed, 376 Tests: []saucereport.Test{ 377 { 378 Status: saucereport.StatusFailed, 379 Name: "failed test1", 380 }, 381 { 382 Status: saucereport.StatusFailed, 383 Name: "failed test2", 384 }, 385 }, 386 }, 387 }, 388 }, 389 project: &Project{ 390 Suites: []Suite{ 391 { 392 Name: "my suite", 393 }, 394 }, 395 }, 396 expResult: "failed test1|failed test2", 397 expErr: nil, 398 }, 399 { 400 name: "it should keep the original settings when suiteName doesn't exist in the project", 401 suiteName: "my suite2", 402 report: saucereport.SauceReport{ 403 Status: saucereport.StatusFailed, 404 Suites: []saucereport.Suite{ 405 { 406 Name: "my suite", 407 Status: saucereport.StatusFailed, 408 Tests: []saucereport.Test{ 409 { 410 Status: saucereport.StatusFailed, 411 Name: "failed test1", 412 }, 413 { 414 Status: saucereport.StatusFailed, 415 Name: "failed test2", 416 }, 417 }, 418 }, 419 }, 420 }, 421 project: &Project{ 422 Suites: []Suite{ 423 { 424 Name: "my suite", 425 }, 426 }, 427 }, 428 expResult: "", 429 expErr: errors.New("suite(my suite2) not found"), 430 }, 431 { 432 name: "it should keep the original settings when no failed test in SauceReport", 433 suiteName: "my suite", 434 report: saucereport.SauceReport{ 435 Status: saucereport.StatusPassed, 436 Suites: []saucereport.Suite{ 437 { 438 Name: "my suite", 439 Status: saucereport.StatusPassed, 440 Tests: []saucereport.Test{ 441 { 442 Status: saucereport.StatusPassed, 443 Name: "passed test1", 444 }, 445 { 446 Status: saucereport.StatusSkipped, 447 Name: "skipped test2", 448 }, 449 }, 450 }, 451 }, 452 }, 453 project: &Project{ 454 Suites: []Suite{ 455 { 456 Name: "my suite", 457 }, 458 }, 459 }, 460 expResult: "", 461 expErr: nil, 462 }, 463 } 464 for _, tc := range testcases { 465 t.Run(tc.name, func(t *testing.T) { 466 err := tc.project.FilterFailedTests(tc.suiteName, tc.report) 467 assert.Equal(t, tc.expErr, err) 468 assert.Equal(t, tc.expResult, tc.project.Suites[0].Filter.TestGrep) 469 }) 470 } 471 }