github.com/bazelbuild/rules_webtesting@v0.2.0/go/webdriver/webdriver_test.go (about) 1 // Copyright 2016 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package webdriver 16 17 import ( 18 "context" 19 "net/url" 20 "os" 21 "strings" 22 "testing" 23 "time" 24 25 "github.com/bazelbuild/rules_webtesting/go/metadata/capabilities" 26 "github.com/bazelbuild/rules_webtesting/go/webtest" 27 ) 28 29 func TestCreateSessionAndQuit(t *testing.T) { 30 ctx := context.Background() 31 32 d, err := CreateSession(ctx, wdAddress(), 3, nil) 33 if err != nil { 34 t.Fatal(err) 35 } 36 if d.SessionID() == "" { 37 t.Error("session ID should be set") 38 } 39 if name, _ := d.Capabilities()["browserName"].(string); name == "" { 40 t.Error("capabilities browserName should be non-empty") 41 } 42 if sid, ok := d.Capabilities()["sessionId"]; ok { 43 t.Errorf("capabilities should not contain session ID; has sessionId key with value %q", sid) 44 } 45 if err := d.Quit(ctx); err != nil { 46 t.Error(err) 47 } 48 } 49 50 func TestHealthy(t *testing.T) { 51 ctx := context.Background() 52 53 d, err := CreateSession(ctx, wdAddress(), 1, nil) 54 if err != nil { 55 t.Fatal(err) 56 } 57 if err := d.Healthy(ctx); err != nil { 58 t.Error(err) 59 } 60 if err := d.Quit(ctx); err != nil { 61 t.Error(err) 62 } 63 if err := d.Healthy(ctx); err == nil { 64 t.Error("got nil error from Healthy after quit") 65 } 66 } 67 68 func TestExecuteScript(t *testing.T) { 69 testCases := []struct { 70 script string 71 args []interface{} 72 value int 73 expected int 74 err bool 75 }{ 76 { 77 "return 1 + 2;", 78 []interface{}{}, 79 0, 80 3, 81 false, 82 }, 83 { 84 "return arguments[0] + arguments[1];", 85 []interface{}{1, 2}, 86 0, 87 3, 88 false, 89 }, 90 { 91 "return argument[0] + arguments[1];", 92 []interface{}{1, 2}, 93 0, 94 0, 95 true, 96 }, 97 } 98 99 ctx := context.Background() 100 101 d, err := CreateSession(ctx, wdAddress(), 1, nil) 102 if err != nil { 103 t.Fatal(err) 104 } 105 defer d.Quit(ctx) 106 for _, tc := range testCases { 107 t.Run(tc.script, func(t *testing.T) { 108 if err := d.ExecuteScript(ctx, tc.script, tc.args, &tc.value); err != nil { 109 if !tc.err { 110 t.Errorf("got unexpected err %v for ExecuteScript(%q, %v)", err, tc.script, tc.args) 111 } 112 return 113 } 114 if tc.err { 115 t.Errorf("got nil err for ExecuteScript(%q, %v)", tc.script, tc.args) 116 return 117 } 118 if tc.value != tc.expected { 119 t.Errorf("got %v, expected %v for ExecuteScript(%q, %v)", tc.value, tc.expected, tc.script, tc.args) 120 } 121 }) 122 } 123 } 124 125 func TestExecuteScriptAsync(t *testing.T) { 126 testCases := []struct { 127 script string 128 args []interface{} 129 value int 130 expected int 131 err bool 132 }{ 133 { 134 "arguments[0](1 + 2);", 135 []interface{}{}, 136 0, 137 3, 138 false, 139 }, 140 { 141 "arguments[2](arguments[0] + arguments[1]);", 142 []interface{}{1, 2}, 143 0, 144 3, 145 false, 146 }, 147 { 148 "argument[2](argument[0] + argument[1]);", 149 []interface{}{1, 2}, 150 0, 151 0, 152 true, 153 }, 154 { 155 "return 1 + 2;", 156 []interface{}{1, 2}, 157 0, 158 0, 159 true, 160 }, 161 } 162 163 ctx := context.Background() 164 165 d, err := CreateSession(ctx, wdAddress(), 1, nil) 166 if err != nil { 167 t.Fatal(err) 168 } 169 defer d.Quit(ctx) 170 171 for _, tc := range testCases { 172 t.Run(tc.script, func(t *testing.T) { 173 if err := d.ExecuteScriptAsync(ctx, tc.script, tc.args, &tc.value); err != nil { 174 if !tc.err { 175 t.Errorf("got unexpected err %v for ExecuteScriptAsync(%q, %v)", err, tc.script, tc.args) 176 } 177 return 178 } 179 if tc.err { 180 t.Errorf("got nil err for ExecuteScriptAsync(%q, %v)", tc.script, tc.args) 181 return 182 } 183 if tc.value != tc.expected { 184 t.Errorf("got %v, expected %v for ExecuteScriptAsync(%q, %v)", tc.value, tc.expected, tc.script, tc.args) 185 } 186 }) 187 } 188 } 189 190 func TestCurrentURL(t *testing.T) { 191 ctx := context.Background() 192 193 d, err := CreateSession(ctx, wdAddress(), 3, nil) 194 if err != nil { 195 t.Fatal(err) 196 } 197 defer d.Quit(ctx) 198 199 u, err := d.CurrentURL(ctx) 200 if err != nil { 201 t.Fatal(err) 202 } 203 if u == nil { 204 t.Fatal("got nil, expected a url.URL ") 205 } 206 } 207 208 func TestNavigateTo(t *testing.T) { 209 ctx := context.Background() 210 211 d, err := CreateSession(ctx, wdAddress(), 3, nil) 212 if err != nil { 213 t.Fatal(err) 214 } 215 defer d.Quit(ctx) 216 217 u, err := url.Parse("https://www.google.com") 218 219 if err := d.NavigateTo(ctx, u); err != nil { 220 t.Fatal(err) 221 } 222 223 cu, err := d.CurrentURL(ctx) 224 if err != nil { 225 t.Fatal(err) 226 } 227 if !strings.Contains(cu.Hostname(), "google.com") { 228 t.Fatalf("got %s, expected to contain google.com", cu) 229 } 230 } 231 232 func TestScreenshot(t *testing.T) { 233 ctx := context.Background() 234 235 d, err := CreateSession(ctx, wdAddress(), 3, nil) 236 if err != nil { 237 t.Fatal(err) 238 } 239 defer d.Quit(ctx) 240 241 img, err := d.Screenshot(ctx) 242 if err != nil { 243 t.Fatal(err) 244 } 245 if img == nil { 246 t.Fatal("got nil, expected an image.Image") 247 } 248 } 249 250 func TestWindowHandles(t *testing.T) { 251 ctx := context.Background() 252 253 driver, err := CreateSession(ctx, wdAddress(), 3, nil) 254 if err != nil { 255 t.Fatal(err) 256 } 257 defer driver.Quit(ctx) 258 259 if windows, err := driver.WindowHandles(ctx); err != nil { 260 t.Fatal(err) 261 } else if len(windows) != 1 { 262 t.Fatalf("Got %d handles, expected 1", len(windows)) 263 } 264 } 265 266 func TestQuit(t *testing.T) { 267 ctx := context.Background() 268 269 driver, err := CreateSession(ctx, wdAddress(), 3, nil) 270 if err != nil { 271 t.Fatal(err) 272 } 273 driver.Quit(ctx) 274 275 if _, err := driver.WindowHandles(ctx); err == nil { 276 t.Fatal("Got nil err, expected unknown session err") 277 } 278 } 279 280 func TestExecuteScriptAsyncWithTimeout(t *testing.T) { 281 ctx := context.Background() 282 283 d, err := CreateSession(ctx, wdAddress(), 3, nil) 284 if err != nil { 285 t.Fatal(err) 286 } 287 defer d.Quit(ctx) 288 289 if err := d.SetScriptTimeout(ctx, 5*time.Second); err != nil { 290 t.Fatal(err) 291 } 292 293 start := time.Now() 294 if err := d.ExecuteScriptAsyncWithTimeout(ctx, time.Second, "return;", nil, nil); err == nil { 295 t.Error("Got nil err, expected timeout err") 296 } 297 if run := time.Now().Sub(start); run < time.Second || run > 5*time.Second { 298 t.Errorf("Got runtime %s, expected < 1 and < 5 seconds", run) 299 } 300 301 start = time.Now() 302 if err := d.ExecuteScriptAsync(ctx, "return;", nil, nil); err == nil { 303 t.Error("Got nil err, expected timeout err") 304 } 305 if run := time.Now().Sub(start); run < 5*time.Second { 306 t.Errorf("Got runtime %s, expected > 5 seconds", run) 307 } 308 } 309 310 func TestExecuteScriptAsyncWithTimeoutWithCaps(t *testing.T) { 311 ctx := context.Background() 312 313 d, err := CreateSession(ctx, wdAddress(), 3, &capabilities.Capabilities{ 314 AlwaysMatch: map[string]interface{}{ 315 "timeouts": map[string]interface{}{ 316 "script": 5000, 317 }, 318 }, 319 }) 320 if err != nil { 321 t.Fatal(err) 322 } 323 defer d.Quit(ctx) 324 325 start := time.Now() 326 if err := d.ExecuteScriptAsyncWithTimeout(ctx, time.Second, "return;", nil, nil); err == nil { 327 t.Error("Got nil err, expected timeout err") 328 } 329 if run := time.Now().Sub(start); run < time.Second || run > 5*time.Second { 330 t.Errorf("Got runtime %s, expected < 1 and < 5 seconds", run) 331 } 332 333 start = time.Now() 334 if err := d.ExecuteScriptAsync(ctx, "return;", nil, nil); err == nil { 335 t.Error("Got nil err, expected timeout err") 336 } 337 if run := time.Now().Sub(start); run < 5*time.Second { 338 t.Errorf("Got runtime %s, expected > 5 seconds", run) 339 } 340 } 341 342 func TestGetWindowRect(t *testing.T) { 343 if bi, _ := webtest.GetBrowserInfo(); bi.Environment == "sauce" { 344 t.Skip("fails on SauceLabs.") 345 } 346 347 ctx := context.Background() 348 349 d, err := CreateSession(ctx, wdAddress(), 3, nil) 350 if err != nil { 351 t.Fatal(err) 352 } 353 defer d.Quit(ctx) 354 355 rect, err := d.GetWindowRect(ctx) 356 if err != nil { 357 t.Fatal(err) 358 } 359 360 if rect.X < 0 { 361 t.Errorf("got rect.X == %d, expected >= 0", rect.X) 362 } 363 364 if rect.Y < 0 { 365 t.Errorf("got rect.Y == %d, expected >= 0", rect.Y) 366 } 367 368 if rect.Width <= 0 { 369 t.Errorf("got rect.Width == %d, expected > 0", rect.Width) 370 } 371 372 if rect.Height <= 0 { 373 t.Errorf("got rect.Height == %d, expected > 0", rect.Height) 374 } 375 } 376 377 func TestSetWindowRect(t *testing.T) { 378 testCases := []struct { 379 name string 380 rect Rectangle 381 check bool 382 err bool 383 }{ 384 { 385 "valid", 386 Rectangle{ 387 X: 200, 388 Y: 200, 389 Width: 500, 390 Height: 400, 391 }, 392 true, 393 false, 394 }, 395 { 396 "zeroes", 397 Rectangle{}, 398 false, 399 false, 400 }, 401 { 402 "negative location", 403 Rectangle{ 404 X: -200, 405 Y: -200, 406 Width: 500, 407 Height: 400, 408 }, 409 false, // what happens is os/wm dependent. 410 false, 411 }, 412 } 413 414 ctx := context.Background() 415 416 d, err := CreateSession(ctx, wdAddress(), 3, nil) 417 if err != nil { 418 t.Fatal(err) 419 } 420 defer d.Quit(ctx) 421 422 for _, tc := range testCases { 423 t.Run(tc.name, func(t *testing.T) { 424 err := d.SetWindowRect(ctx, tc.rect) 425 if tc.err { 426 if err == nil { 427 t.Fatal("got nil err, expected non-nil err") 428 } 429 return 430 } 431 if err != nil { 432 t.Fatal(err) 433 } 434 if !tc.check { 435 return 436 } 437 438 rect, err := d.GetWindowRect(ctx) 439 if err != nil { 440 t.Fatal(err) 441 } 442 443 if rect != tc.rect { 444 t.Errorf("got rect == %+v, expected %+v", rect, tc.rect) 445 } 446 }) 447 } 448 } 449 450 func TestSetWindowSize(t *testing.T) { 451 if bi, _ := webtest.GetBrowserInfo(); bi.Environment == "sauce" { 452 t.Skip("fails on SauceLabs.") 453 } 454 455 testCases := []struct { 456 name string 457 width float64 458 height float64 459 check bool 460 err bool 461 }{ 462 { 463 "valid", 464 500, 465 400, 466 true, 467 false, 468 }, 469 { 470 "zeroes", 471 0, 472 0, 473 false, 474 false, 475 }, 476 } 477 478 ctx := context.Background() 479 480 d, err := CreateSession(ctx, wdAddress(), 3, nil) 481 if err != nil { 482 t.Fatal(err) 483 } 484 defer d.Quit(ctx) 485 486 for _, tc := range testCases { 487 t.Run(tc.name, func(t *testing.T) { 488 err := d.SetWindowSize(ctx, tc.width, tc.height) 489 if tc.err { 490 if err == nil { 491 t.Fatal("got nil err, expected non-nil err") 492 } 493 return 494 } 495 if err != nil { 496 t.Fatal(err) 497 } 498 if !tc.check { 499 return 500 } 501 rect, err := d.GetWindowRect(ctx) 502 if err != nil { 503 t.Fatal(err) 504 } 505 506 if tc.width != rect.Width || tc.height != rect.Height { 507 t.Errorf("got (w, h) == (%d, %d), expected (%d, %d)", rect.Width, rect.Height, tc.width, tc.height) 508 } 509 }) 510 } 511 } 512 513 func TestSetWindowPosition(t *testing.T) { 514 if bi, _ := webtest.GetBrowserInfo(); bi.Environment == "sauce" { 515 t.Skip("fails on SauceLabs.") 516 } 517 518 testCases := []struct { 519 name string 520 x float64 521 y float64 522 check bool 523 err bool 524 }{ 525 { 526 "valid", 527 200, 528 200, 529 true, 530 false, 531 }, 532 { 533 "zeroes", 534 0, 535 0, 536 false, 537 false, 538 }, 539 { 540 "negative", 541 -200, 542 -200, 543 false, // what happens is os/wm dependent. 544 false, 545 }, 546 } 547 548 ctx := context.Background() 549 550 d, err := CreateSession(ctx, wdAddress(), 3, nil) 551 if err != nil { 552 t.Fatal(err) 553 } 554 defer d.Quit(ctx) 555 556 for _, tc := range testCases { 557 t.Run(tc.name, func(t *testing.T) { 558 err := d.SetWindowPosition(ctx, tc.x, tc.y) 559 if tc.err { 560 if err == nil { 561 t.Fatal("got nil err, expected non-nil err") 562 } 563 return 564 } 565 if err != nil { 566 t.Fatal(err) 567 } 568 if !tc.check { 569 return 570 } 571 572 rect, err := d.GetWindowRect(ctx) 573 if err != nil { 574 t.Fatal(err) 575 } 576 577 if rect.X != tc.x || rect.Y != tc.y { 578 t.Errorf("got rect == %+v, expected X: %d, Y: %d", rect, tc.x, tc.y) 579 } 580 }) 581 } 582 } 583 584 func wdAddress() string { 585 addr := os.Getenv("WEB_TEST_WEBDRIVER_SERVER") 586 if !strings.HasSuffix(addr, "/") { 587 addr = addr + "/" 588 } 589 return addr 590 }