Skip to content

Commit 5ad30e4

Browse files
chore: roll Playwright to 1.65.0-next (f33f0b751b) (#3299)
Co-authored-by: microsoft-playwright-automation[bot] <203992400+microsoft-playwright-automation[bot]@users.noreply.github.com>
1 parent ccfa835 commit 5ad30e4

51 files changed

Lines changed: 1050 additions & 239 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎DRIVER_VERSION‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
b4695e3eb2e6736d1a7b1fd255c4e94f78553660
1+
f33f0b751be0dd559d86c1ed27ca8baa5f9cb2b2

‎NODE_VERSION‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
24.22.1
1+
26.13.0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<script>
2+
window.registrationPromise = navigator.serviceWorker.register('sw.js');
3+
window.activationPromise = new Promise(resolve => navigator.serviceWorker.oncontrollerchange = resolve);
4+
</script>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
self.addEventListener('install', () => self.skipWaiting());
2+
3+
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()));
4+
5+
self.addEventListener('fetch', () => {
6+
// Hold the request for a while, then let it fall back to the network.
7+
const start = Date.now();
8+
while (Date.now() - start < 500) {}
9+
});

‎tests/async/library/chromium/test_connect_over_cdp.py‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,3 +904,50 @@ async def test_CD_035_no_defaults_should_not_affect_new_contexts(
904904
await browser.close()
905905
finally:
906906
await browser_server.close()
907+
908+
909+
async def test_CD_053_should_connect_when_another_client_inspects_a_terminated_shared_worker(
910+
browser_type: BrowserType, server: Server, launch_arguments: Dict, port: int
911+
) -> None:
912+
pytest.skip("fixme")
913+
browser = await launch(browser_type, launch_arguments, port)
914+
try:
915+
# Another client inspects the shared worker.
916+
page = await browser.new_page()
917+
inspector = await browser.new_browser_cdp_session()
918+
worker_created: asyncio.Future[str] = asyncio.get_running_loop().create_future()
919+
920+
def on_target_created(event: Dict[str, Any]) -> None:
921+
if event["targetInfo"]["type"] == "shared_worker":
922+
worker_created.set_result(event["targetInfo"]["targetId"])
923+
924+
inspector.on("Target.targetCreated", on_target_created)
925+
await inspector.send("Target.setDiscoverTargets", {"discover": True})
926+
await page.goto(server.PREFIX + "/shared-worker/shared-worker.html")
927+
assert await page.evaluate("window.sharedWorkerResponsePromise") == "echo:hello"
928+
worker_target_id = await worker_created
929+
await inspector.send(
930+
"Target.attachToTarget", {"targetId": worker_target_id, "flatten": True}
931+
)
932+
933+
# The last client of the shared worker goes away, so the worker is terminated.
934+
# The inspector stays attached, so the worker target lingers without a browser context.
935+
await page.close()
936+
# Python: poll the CDP target list instead of expect.poll.
937+
deadline = asyncio.get_running_loop().time() + 5
938+
while True:
939+
targets = await inspector.send("Target.getTargets")
940+
if not any(
941+
info["targetId"] == worker_target_id for info in targets["targetInfos"]
942+
):
943+
break
944+
assert asyncio.get_running_loop().time() < deadline
945+
await asyncio.sleep(0.1)
946+
947+
# A new client auto-attaches to the lingering worker target.
948+
cdp_browser = await browser_type.connect_over_cdp(f"http://127.0.0.1:{port}/")
949+
page2 = await cdp_browser.contexts[0].new_page()
950+
assert await page2.evaluate("1 + 1") == 2
951+
await cdp_browser.close()
952+
finally:
953+
await browser.close()

‎tests/async/library/chromium/test_oopif.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,13 @@ async def test_OO_012_should_take_screenshot(
313313
browser: Browser,
314314
server: Server,
315315
assert_to_be_golden: Callable[[bytes, str], None],
316+
utils: Utils,
316317
) -> None:
317318
await page.set_viewport_size({"width": 500, "height": 500})
318319
await page.goto(server.PREFIX + "/dynamic-oopif.html")
319320
assert len(page.frames) == 2
320321
await assert_oopif_count(browser, 1)
322+
await utils.rafraf(page.frames[1])
321323
assert_to_be_golden(await page.screenshot(), "screenshot-oopif.png")
322324

323325

‎tests/async/library/test_browsercontext_har.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
"""Port of tests/library/browsercontext-har.spec.ts."""
1616

17+
import io
1718
import json
1819
import re
1920
import zipfile
@@ -316,6 +317,24 @@ async def test_HA_085_should_round_trip_har_zip(
316317
)
317318

318319

320+
async def test_HA_114_should_reject_a_malformed_har_zip(
321+
context_factory: Callable[..., Awaitable[BrowserContext]], tmp_path: Path
322+
) -> None:
323+
# Python: zipfile builds the in-memory archive instead of yazl's output stream.
324+
output = io.BytesIO()
325+
with zipfile.ZipFile(output, "w") as zip_file:
326+
zip_file.writestr("aa/x.har", b"{}")
327+
# yauzl reports '..' in an entry name as an 'error' event while reading entries.
328+
zip_data = output.getvalue().replace(b"aa/x.har", b"../x.har")
329+
har_path = tmp_path / "malformed.har.zip"
330+
har_path.write_bytes(zip_data)
331+
332+
context = await context_factory()
333+
with pytest.raises(Error) as exc_info:
334+
await context.route_from_har(har_path)
335+
assert "invalid relative path: ../x.har" in exc_info.value.message
336+
337+
319338
async def test_HA_086_should_produce_extracted_zip(
320339
context_factory: Callable[..., Awaitable[BrowserContext]],
321340
server: Server,

‎tests/async/library/test_browsercontext_user_agent.py‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import pytest
2121

22-
from playwright.async_api import Browser, BrowserContext, Error, Playwright
22+
from playwright.async_api import Browser, BrowserContext, Error, Playwright, Route
2323
from tests.server import Server, TestServerRequest
2424
from tests.utils import chromium_version_less_than, must
2525

@@ -41,6 +41,25 @@ async def test_UA_001_should_work(browser: Browser, server: Server) -> None:
4141
await context.close()
4242

4343

44+
async def test_UA_007_should_preserve_custom_user_agent_in_route_fetch(
45+
context_factory: Callable[..., Awaitable[BrowserContext]], server: Server
46+
) -> None:
47+
context = await context_factory(user_agent="my-custom-user-agent")
48+
page = await context.new_page()
49+
50+
async def handle(route: Route) -> None:
51+
await route.fulfill(response=await route.fetch())
52+
53+
await page.route("**/empty.html", handle)
54+
request, server_request, _ = await asyncio.gather(
55+
page.wait_for_event("request", predicate=lambda r: r.url == server.EMPTY_PAGE),
56+
server.wait_for_request("/empty.html"),
57+
page.goto(server.EMPTY_PAGE),
58+
)
59+
assert request.headers["user-agent"] == "my-custom-user-agent"
60+
assert server_request.getHeader("user-agent") == "my-custom-user-agent"
61+
62+
4463
async def test_UA_002_should_work_for_subframes(
4564
browser: Browser, server: Server, utils: Utils
4665
) -> None:

‎tests/async/library/test_capabilities.py‎

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -183,27 +183,19 @@ async def test_CA_011_should_not_crash_on_show_directory_picker(
183183
await page.goto(server.EMPTY_PAGE)
184184
# "User activation is required to show a file picker." - so we click first.
185185
await page.locator("body").click()
186-
picker = asyncio.create_task(
187-
page.evaluate(
188-
"""async () => {
189-
const dir = await window.showDirectoryPicker();
190-
return dir.name;
191-
// In headless it throws (aborted), in headed it stalls (Test ended) and waits for the picker to be accepted.
186+
await page.evaluate(
187+
"""() => {
188+
window.showDirectoryPicker().catch(e => { window.__pickerError = String(e); });
192189
}"""
193-
)
194190
)
195191
# The dialog will not be accepted, so we just wait for some time to
196192
# to give the browser a chance to crash.
197193
await page.wait_for_timeout(3_000)
198-
if picker.done():
199-
error = picker.exception()
200-
assert isinstance(error, Error)
201-
assert re.search(
202-
r"(DOMException|AbortError): .*The user aborted a request", error.message
203-
)
204-
else:
205-
# In headed mode the picker stalls until the test ends.
206-
picker.add_done_callback(lambda task: task.exception())
194+
# In headless it throws (aborted), in headed it stalls and waits for the picker to be accepted.
195+
error = await page.evaluate("() => window.__pickerError ?? 'stalled'")
196+
assert re.search(
197+
r"((DOMException|AbortError): .*The user aborted a request|stalled)", error
198+
)
207199

208200

209201
async def test_CA_012_should_not_crash_on_storage_get_directory(

‎tests/async/library/test_multiclient.py‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,3 +563,50 @@ async def test_MC_018_should_stop_tracing_upon_disconnect(
563563
await disconnect(playwright, page_a)
564564

565565
await page_b.context.tracing.start()
566+
567+
568+
@pytest.mark.slow
569+
async def test_MC_020_should_run_locator_handlers_after_reconnecting_with_a_pending_callback(
570+
playwright: Playwright,
571+
connect: Callable[..., Awaitable[Browser]],
572+
remote_server: RemoteServer,
573+
server: Server,
574+
) -> None:
575+
browser = await connect(remote_server.ws_endpoint)
576+
page = await browser.new_page()
577+
await page.goto(server.PREFIX + "/input/handle-locator.html")
578+
579+
called = 0
580+
581+
async def handler() -> None:
582+
nonlocal called
583+
called += 1
584+
await asyncio.Future()
585+
586+
await page.add_locator_handler(
587+
page.get_by_text("This interstitial covers the button"), handler
588+
)
589+
await page.evaluate(
590+
"""() => {
591+
window.setupAnnoyingInterstitial('none', 1);
592+
}"""
593+
)
594+
with pytest.raises(Error) as exc_info:
595+
await page.locator("#target").click(timeout=1000)
596+
assert "Timeout 1000ms exceeded" in exc_info.value.message
597+
assert called == 1
598+
599+
await disconnect(playwright, page)
600+
601+
reconnected_browser = await connect(remote_server.ws_endpoint)
602+
reconnected_page = reconnected_browser.contexts[0].pages[0]
603+
604+
async def reconnected_handler() -> None:
605+
await reconnected_page.locator("#close").click()
606+
607+
await reconnected_page.add_locator_handler(
608+
reconnected_page.get_by_text("This interstitial covers the button"),
609+
reconnected_handler,
610+
)
611+
await reconnected_page.locator("#target").click(timeout=3000)
612+
assert await reconnected_page.evaluate("window.clicked") == 1

0 commit comments

Comments
 (0)