|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
15 | 15 | import asyncio
|
| 16 | +import pytest |
16 | 17 | import re
|
17 | 18 | from playwright import Error, TimeoutError
|
18 | 19 |
|
@@ -395,3 +396,142 @@ async def test_expose_function_should_work_with_complex_objects(page, server):
|
395 | 396 | await page.exposeFunction("complexObject", lambda a, b: dict(x=a["x"] + b["x"]))
|
396 | 397 | result = await page.evaluate("complexObject({x: 5}, {x: 2})")
|
397 | 398 | assert result["x"] == 7
|
| 399 | + |
| 400 | + |
| 401 | +async def test_page_error_should_fire(page, server, is_webkit): |
| 402 | + [error, _] = await asyncio.gather( |
| 403 | + page.waitForEvent("pageerror"), page.goto(server.PREFIX + "/error.html"), |
| 404 | + ) |
| 405 | + assert error.message == "Fancy error!" |
| 406 | + stack = await page.evaluate("window.e.stack") |
| 407 | + # Note that WebKit reports the stack of the 'throw' statement instead of the Error constructor call. |
| 408 | + if is_webkit: |
| 409 | + stack = stack.replace("14:25", "15:19") |
| 410 | + assert error.stack == stack |
| 411 | + |
| 412 | + |
| 413 | +async def test_page_error_should_handle_odd_values(page, is_firefox): |
| 414 | + cases = [["null", "null"], ["undefined", "undefined"], ["0", "0"], ['""', ""]] |
| 415 | + for [value, message] in cases: |
| 416 | + [error, _] = await asyncio.gather( |
| 417 | + page.waitForEvent("pageerror"), |
| 418 | + page.evaluate(f"() => setTimeout(() => {{ throw {value}; }}, 0)"), |
| 419 | + ) |
| 420 | + assert ( |
| 421 | + error.message == ("uncaught exception: " + message) if is_firefox else value |
| 422 | + ) |
| 423 | + |
| 424 | + |
| 425 | +@pytest.mark.skip_browser("firefox") |
| 426 | +async def test_page_error_should_handle_object(page, is_chromium): |
| 427 | + # Firefox just does not report this error. |
| 428 | + [error, _] = await asyncio.gather( |
| 429 | + page.waitForEvent("pageerror"), |
| 430 | + page.evaluate("() => setTimeout(() => { throw {}; }, 0)"), |
| 431 | + ) |
| 432 | + assert error.message == "Object" if is_chromium else "[object Object]" |
| 433 | + |
| 434 | + |
| 435 | +@pytest.mark.skip_browser("firefox") |
| 436 | +async def test_page_error_should_handle_window(page, is_chromium): |
| 437 | + # Firefox just does not report this error. |
| 438 | + [error, _] = await asyncio.gather( |
| 439 | + page.waitForEvent("pageerror"), |
| 440 | + page.evaluate("() => setTimeout(() => { throw window; }, 0)"), |
| 441 | + ) |
| 442 | + assert error.message == "Window" if is_chromium else "[object Window]" |
| 443 | + |
| 444 | + |
| 445 | +expected_output = "<html><head></head><body><div>hello</div></body></html>" |
| 446 | + |
| 447 | + |
| 448 | +async def test_set_content_should_work(page, server): |
| 449 | + await page.setContent("<div>hello</div>") |
| 450 | + result = await page.content() |
| 451 | + assert result == expected_output |
| 452 | + |
| 453 | + |
| 454 | +async def test_set_content_should_work_with_domcontentloaded(page, server): |
| 455 | + await page.setContent("<div>hello</div>", waitUntil="domcontentloaded") |
| 456 | + result = await page.content() |
| 457 | + assert result == expected_output |
| 458 | + |
| 459 | + |
| 460 | +async def test_set_content_should_work_with_doctype(page, server): |
| 461 | + doctype = "<!DOCTYPE html>" |
| 462 | + await page.setContent(f"{doctype}<div>hello</div>") |
| 463 | + result = await page.content() |
| 464 | + assert result == f"{doctype}{expected_output}" |
| 465 | + |
| 466 | + |
| 467 | +async def test_set_content_should_work_with_HTML_4_doctype(page, server): |
| 468 | + doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' |
| 469 | + await page.setContent(f"{doctype}<div>hello</div>") |
| 470 | + result = await page.content() |
| 471 | + assert result == f"{doctype}{expected_output}" |
| 472 | + |
| 473 | + |
| 474 | +async def test_set_content_should_respect_timeout(page, server): |
| 475 | + img_path = "/img.png" |
| 476 | + # stall for image |
| 477 | + server.set_route(img_path, lambda request: None) |
| 478 | + error = None |
| 479 | + try: |
| 480 | + await page.setContent( |
| 481 | + '<img src="${server.PREFIX + img_path}"></img>', timeout=1 |
| 482 | + ) |
| 483 | + except Error as e: |
| 484 | + error = e |
| 485 | + assert isinstance(error, TimeoutError) |
| 486 | + |
| 487 | + |
| 488 | +async def test_set_content_should_respect_default_navigation_timeout(page, server): |
| 489 | + page.setDefaultNavigationTimeout(1) |
| 490 | + img_path = "/img.png" |
| 491 | + # stall for image |
| 492 | + await page.route(img_path, lambda route, request: None) |
| 493 | + |
| 494 | + error = None |
| 495 | + try: |
| 496 | + await page.setContent(f'<img src="{server.PREFIX + img_path}"></img>') |
| 497 | + except Error as e: |
| 498 | + error = e |
| 499 | + assert "Timeout 1ms exceeded during" in error.message |
| 500 | + assert isinstance(error, TimeoutError) |
| 501 | + |
| 502 | + |
| 503 | +async def test_set_content_should_await_resources_to_load(page, server): |
| 504 | + img_path = "/img.png" |
| 505 | + img_route = page._scope._loop.create_future() |
| 506 | + await page.route(img_path, lambda route, request: img_route.set_result(route)) |
| 507 | + loaded = [] |
| 508 | + |
| 509 | + async def load(): |
| 510 | + await page.setContent(f'<img src="{server.PREFIX + img_path}"></img>') |
| 511 | + loaded.append(True) |
| 512 | + |
| 513 | + content_promise = asyncio.ensure_future(load()) |
| 514 | + route = await img_route |
| 515 | + assert loaded == [] |
| 516 | + asyncio.ensure_future(route.continue_()) |
| 517 | + await content_promise |
| 518 | + |
| 519 | + |
| 520 | +async def test_set_content_should_work_with_tricky_content(page): |
| 521 | + await page.setContent("<div>hello world</div>" + "\x7F") |
| 522 | + assert await page.evalOnSelector("div", "div => div.textContent") == "hello world" |
| 523 | + |
| 524 | + |
| 525 | +async def test_set_content_should_work_with_accents(page): |
| 526 | + await page.setContent("<div>aberración</div>") |
| 527 | + assert await page.evalOnSelector("div", "div => div.textContent") == "aberración" |
| 528 | + |
| 529 | + |
| 530 | +async def test_set_content_should_work_with_emojis(page): |
| 531 | + await page.setContent("<div>🐥</div>") |
| 532 | + assert await page.evalOnSelector("div", "div => div.textContent") == "🐥" |
| 533 | + |
| 534 | + |
| 535 | +async def test_set_content_should_work_with_newline(page): |
| 536 | + await page.setContent("<div>\n</div>") |
| 537 | + assert await page.evalOnSelector("div", "div => div.textContent") == "\n" |
0 commit comments