How to use test_should_be_able_to_navigate_away_from_page_with_before_unload method in Playwright Python

Best Python code snippet using playwright-python

Run Playwright Python automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

test_page.py

Source: test_page.py Github

copy
1# Copyright (c) Microsoft Corporation.
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
15import asyncio
16import os
17import re
18
19import pytest
20
21from playwright.async_api import Error, Page, Route, TimeoutError
22from tests.server import Server
23
24
25async def test_close_should_reject_all_promises(context):
26    new_page = await context.new_page()
27    with pytest.raises(Error) as exc_info:
28        await asyncio.gather(
29            new_page.evaluate("() => new Promise(r => {})"), new_page.close()
30        )
31    assert "Target closed" in exc_info.value.message
32
33
34async def test_closed_should_not_visible_in_context_pages(context):
35    page = await context.new_page()
36    assert page in context.pages
37    await page.close()
38    assert page not in context.pages
39
40
41async def test_close_should_run_beforeunload_if_asked_for(
42    context, server, is_chromium, is_webkit
43):
44    page = await context.new_page()
45    await page.goto(server.PREFIX + "/beforeunload.html")
46    # We have to interact with a page so that 'beforeunload' handlers
47    # fire.
48    await page.click("body")
49
50    async with page.expect_event("dialog") as dialog_info:
51        await page.close(run_before_unload=True)
52    dialog = await dialog_info.value
53
54    assert dialog.type == "beforeunload"
55    assert dialog.default_value == ""
56    if is_chromium:
57        assert dialog.message == ""
58    elif is_webkit:
59        assert dialog.message == "Leave?"
60    else:
61        assert (
62            "This page is asking you to confirm that you want to leave"
63            in dialog.message
64        )
65    async with page.expect_event("close"):
66        await dialog.accept()
67
68
69async def test_close_should_not_run_beforeunload_by_default(context, server):
70    page = await context.new_page()
71    await page.goto(server.PREFIX + "/beforeunload.html")
72    # We have to interact with a page so that 'beforeunload' handlers
73    # fire.
74    await page.click("body")
75    await page.close()
76
77
78async def test_should_be_able_to_navigate_away_from_page_with_before_unload(
79    server: Server, page: Page
80):
81    await page.goto(server.PREFIX + "/beforeunload.html")
82    # We have to interact with a page so that 'beforeunload' handlers
83    # fire.
84    await page.click("body")
85    await page.goto(server.EMPTY_PAGE)
86
87
88async def test_close_should_set_the_page_close_state(context):
89    page = await context.new_page()
90    assert page.is_closed() is False
91    await page.close()
92    assert page.is_closed()
93
94
95async def test_close_should_terminate_network_waiters(context, server):
96    page = await context.new_page()
97
98    async def wait_for_request():
99        with pytest.raises(Error) as exc_info:
100            async with page.expect_request(server.EMPTY_PAGE):
101                pass
102        return exc_info.value
103
104    async def wait_for_response():
105        with pytest.raises(Error) as exc_info:
106            async with page.expect_response(server.EMPTY_PAGE):
107                pass
108        return exc_info.value
109
110    results = await asyncio.gather(
111        wait_for_request(), wait_for_response(), page.close()
112    )
113    for i in range(2):
114        error = results[i]
115        assert "Page closed" in error.message
116        assert "Timeout" not in error.message
117
118
119async def test_close_should_be_callable_twice(context):
120    page = await context.new_page()
121    await asyncio.gather(
122        page.close(),
123        page.close(),
124    )
125    await page.close()
126
127
128async def test_load_should_fire_when_expected(page):
129    async with page.expect_event("load"):
130        await page.goto("about:blank")
131
132
133async def test_async_stacks_should_work(page, server):
134    await page.route(
135        "**/empty.html", lambda route, response: asyncio.create_task(route.abort())
136    )
137    with pytest.raises(Error) as exc_info:
138        await page.goto(server.EMPTY_PAGE)
139    assert __file__ in exc_info.value.stack
140
141
142async def test_opener_should_provide_access_to_the_opener_page(page):
143    async with page.expect_popup() as popup_info:
144        await page.evaluate("window.open('about:blank')"),
145    popup = await popup_info.value
146    opener = await popup.opener()
147    assert opener == page
148
149
150async def test_opener_should_return_null_if_parent_page_has_been_closed(page):
151    async with page.expect_popup() as popup_info:
152        await page.evaluate("window.open('about:blank')"),
153    popup = await popup_info.value
154    await page.close()
155    opener = await popup.opener()
156    assert opener is None
157
158
159async def test_domcontentloaded_should_fire_when_expected(page, server):
160    future = asyncio.create_task(page.goto("about:blank"))
161    async with page.expect_event("domcontentloaded"):
162        pass
163    await future
164
165
166async def test_wait_for_request(page, server):
167    await page.goto(server.EMPTY_PAGE)
168    async with page.expect_request(server.PREFIX + "/digits/2.png") as request_info:
169        await page.evaluate(
170            """() => {
171                fetch('/digits/1.png')
172                fetch('/digits/2.png')
173                fetch('/digits/3.png')
174            }"""
175        )
176    request = await request_info.value
177    assert request.url == server.PREFIX + "/digits/2.png"
178
179
180async def test_wait_for_request_should_work_with_predicate(page, server):
181    await page.goto(server.EMPTY_PAGE)
182    async with page.expect_request(
183        lambda request: request.url == server.PREFIX + "/digits/2.png"
184    ) as request_info:
185        await page.evaluate(
186            """() => {
187                fetch('/digits/1.png')
188                fetch('/digits/2.png')
189                fetch('/digits/3.png')
190            }"""
191        )
192    request = await request_info.value
193    assert request.url == server.PREFIX + "/digits/2.png"
194
195
196async def test_wait_for_request_should_timeout(page, server):
197    with pytest.raises(Error) as exc_info:
198        async with page.expect_event("request", timeout=1):
199            pass
200    assert exc_info.type is TimeoutError
201
202
203async def test_wait_for_request_should_respect_default_timeout(page, server):
204    page.set_default_timeout(1)
205    with pytest.raises(Error) as exc_info:
206        async with page.expect_event("request", lambda _: False):
207            pass
208    assert exc_info.type is TimeoutError
209
210
211async def test_wait_for_request_should_work_with_no_timeout(page, server):
212    await page.goto(server.EMPTY_PAGE)
213    async with page.expect_request(
214        server.PREFIX + "/digits/2.png", timeout=0
215    ) as request_info:
216        await page.evaluate(
217            """() => setTimeout(() => {
218                fetch('/digits/1.png')
219                fetch('/digits/2.png')
220                fetch('/digits/3.png')
221            }, 50)"""
222        )
223    request = await request_info.value
224    assert request.url == server.PREFIX + "/digits/2.png"
225
226
227async def test_wait_for_request_should_work_with_url_match(page, server):
228    await page.goto(server.EMPTY_PAGE)
229    async with page.expect_request(re.compile(r"digits\/\d\.png")) as request_info:
230        await page.evaluate("fetch('/digits/1.png')")
231    request = await request_info.value
232    assert request.url == server.PREFIX + "/digits/1.png"
233
234
235async def test_wait_for_event_should_fail_with_error_upon_disconnect(page):
236    with pytest.raises(Error) as exc_info:
237        async with page.expect_download():
238            await page.close()
239    assert "Page closed" in exc_info.value.message
240
241
242async def test_wait_for_response_should_work(page, server):
243    await page.goto(server.EMPTY_PAGE)
244    async with page.expect_response(server.PREFIX + "/digits/2.png") as response_info:
245        await page.evaluate(
246            """() => {
247                fetch('/digits/1.png')
248                fetch('/digits/2.png')
249                fetch('/digits/3.png')
250            }"""
251        )
252    response = await response_info.value
253    assert response.url == server.PREFIX + "/digits/2.png"
254
255
256async def test_wait_for_response_should_respect_timeout(page):
257    with pytest.raises(Error) as exc_info:
258        async with page.expect_response("**/*", timeout=1):
259            pass
260    assert exc_info.type is TimeoutError
261
262
263async def test_wait_for_response_should_respect_default_timeout(page):
264    page.set_default_timeout(1)
265    with pytest.raises(Error) as exc_info:
266        async with page.expect_response(lambda _: False):
267            pass
268    assert exc_info.type is TimeoutError
269
270
271async def test_wait_for_response_should_work_with_predicate(page, server):
272    await page.goto(server.EMPTY_PAGE)
273    async with page.expect_response(
274        lambda response: response.url == server.PREFIX + "/digits/2.png"
275    ) as response_info:
276        await page.evaluate(
277            """() => {
278                fetch('/digits/1.png')
279                fetch('/digits/2.png')
280                fetch('/digits/3.png')
281            }"""
282        )
283    response = await response_info.value
284    assert response.url == server.PREFIX + "/digits/2.png"
285
286
287async def test_wait_for_response_should_work_with_no_timeout(page, server):
288    await page.goto(server.EMPTY_PAGE)
289    async with page.expect_response(server.PREFIX + "/digits/2.png") as response_info:
290        await page.evaluate(
291            """() => {
292                fetch('/digits/1.png')
293                fetch('/digits/2.png')
294                fetch('/digits/3.png')
295            }"""
296        )
297    response = await response_info.value
298    assert response.url == server.PREFIX + "/digits/2.png"
299
300
301async def test_expose_binding(page):
302    binding_source = []
303
304    def binding(source, a, b):
305        binding_source.append(source)
306        return a + b
307
308    await page.expose_binding("add", lambda source, a, b: binding(source, a, b))
309
310    result = await page.evaluate("add(5, 6)")
311
312    assert binding_source[0]["context"] == page.context
313    assert binding_source[0]["page"] == page
314    assert binding_source[0]["frame"] == page.main_frame
315    assert result == 11
316
317
318async def test_expose_function(page, server):
319    await page.expose_function("compute", lambda a, b: a * b)
320    result = await page.evaluate("compute(9, 4)")
321    assert result == 36
322
323
324async def test_expose_function_should_throw_exception_in_page_context(page, server):
325    def throw():
326        raise Exception("WOOF WOOF")
327
328    await page.expose_function("woof", lambda: throw())
329    result = await page.evaluate(
330        """async() => {
331            try {
332                await woof()
333            } catch (e) {
334                return {message: e.message, stack: e.stack}
335            }
336        }"""
337    )
338    assert result["message"] == "WOOF WOOF"
339    assert __file__ in result["stack"]
340
341
342async def test_expose_function_should_be_callable_from_inside_add_init_script(page):
343    called = []
344    await page.expose_function("woof", lambda: called.append(True))
345    await page.add_init_script("woof()")
346    await page.reload()
347    assert called == [True]
348
349
350async def test_expose_function_should_survive_navigation(page, server):
351    await page.expose_function("compute", lambda a, b: a * b)
352    await page.goto(server.EMPTY_PAGE)
353    result = await page.evaluate("compute(9, 4)")
354    assert result == 36
355
356
357async def test_expose_function_should_await_returned_promise(page):
358    async def mul(a, b):
359        return a * b
360
361    await page.expose_function("compute", mul)
362    assert await page.evaluate("compute(3, 5)") == 15
363
364
365async def test_expose_function_should_work_on_frames(page, server):
366    await page.expose_function("compute", lambda a, b: a * b)
367    await page.goto(server.PREFIX + "/frames/nested-frames.html")
368    frame = page.frames[1]
369    assert await frame.evaluate("compute(3, 5)") == 15
370
371
372async def test_expose_function_should_work_on_frames_before_navigation(page, server):
373    await page.goto(server.PREFIX + "/frames/nested-frames.html")
374    await page.expose_function("compute", lambda a, b: a * b)
375    frame = page.frames[1]
376    assert await frame.evaluate("compute(3, 5)") == 15
377
378
379async def test_expose_function_should_work_after_cross_origin_navigation(page, server):
380    await page.goto(server.EMPTY_PAGE)
381    await page.expose_function("compute", lambda a, b: a * b)
382    await page.goto(server.CROSS_PROCESS_PREFIX + "/empty.html")
383    assert await page.evaluate("compute(9, 4)") == 36
384
385
386async def test_expose_function_should_work_with_complex_objects(page, server):
387    await page.expose_function("complexObject", lambda a, b: dict(x=a["x"] + b["x"]))
388    result = await page.evaluate("complexObject({x: 5}, {x: 2})")
389    assert result["x"] == 7
390
391
392async def test_expose_bindinghandle_should_work(page, server):
393    targets = []
394
395    def logme(t):
396        targets.append(t)
397        return 17
398
399    await page.expose_binding("logme", lambda source, t: logme(t), handle=True)
400    result = await page.evaluate("logme({ foo: 42 })")
401    assert (await targets[0].evaluate("x => x.foo")) == 42
402    assert result == 17
403
404
405async def test_page_error_should_fire(page, server, browser_name):
406    url = server.PREFIX + "/error.html"
407    async with page.expect_event("pageerror") as error_info:
408        await page.goto(url)
409    error = await error_info.value
410    assert error.name == "Error"
411    assert error.message == "Fancy error!"
412    # Note that WebKit reports the stack of the 'throw' statement instead of the Error constructor call.
413    if browser_name == "chromium":
414        assert (
415            error.stack
416            == """Error: Fancy error!
417    at c (myscript.js:14:11)
418    at b (myscript.js:10:5)
419    at a (myscript.js:6:5)
420    at myscript.js:3:1"""
421        )
422    if browser_name == "firefox":
423        assert (
424            error.stack
425            == """Error: Fancy error!
426    at c (myscript.js:14:11)
427    at b (myscript.js:10:5)
428    at a (myscript.js:6:5)
429    at  (myscript.js:3:1)"""
430        )
431    if browser_name == "webkit":
432        assert (
433            error.stack
434            == f"""Error: Fancy error!
435    at c ({url}:14:36)
436    at b ({url}:10:6)
437    at a ({url}:6:6)
438    at global code ({url}:3:2)"""
439        )
440
441
442async def test_page_error_should_handle_odd_values(page):
443    cases = [["null", "null"], ["undefined", "undefined"], ["0", "0"], ['""', ""]]
444    for [value, message] in cases:
445        async with page.expect_event("pageerror") as error_info:
446            await page.evaluate(f"() => setTimeout(() => {{ throw {value}; }}, 0)")
447        error = await error_info.value
448        assert error.message == message
449
450
451async def test_page_error_should_handle_object(page, is_chromium):
452    async with page.expect_event("pageerror") as error_info:
453        await page.evaluate("() => setTimeout(() => { throw {}; }, 0)")
454    error = await error_info.value
455    assert error.message == "Object" if is_chromium else "[object Object]"
456
457
458async def test_page_error_should_handle_window(page, is_chromium):
459    async with page.expect_event("pageerror") as error_info:
460        await page.evaluate("() => setTimeout(() => { throw window; }, 0)")
461    error = await error_info.value
462    assert error.message == "Window" if is_chromium else "[object Window]"
463
464
465async def test_page_error_should_pass_error_name_property(page):
466    async with page.expect_event("pageerror") as error_info:
467        await page.evaluate(
468            """() => setTimeout(() => {
469            const error = new Error("my-message");
470            error.name = "my-name";
471            throw error;
472        }, 0)
473        """
474        )
475    error = await error_info.value
476    assert error.message == "my-message"
477    assert error.name == "my-name"
478
479
480expected_output = "<html><head></head><body><div>hello</div></body></html>"
481
482
483async def test_set_content_should_work(page, server):
484    await page.set_content("<div>hello</div>")
485    result = await page.content()
486    assert result == expected_output
487
488
489async def test_set_content_should_work_with_domcontentloaded(page, server):
490    await page.set_content("<div>hello</div>", wait_until="domcontentloaded")
491    result = await page.content()
492    assert result == expected_output
493
494
495async def test_set_content_should_work_with_doctype(page, server):
496    doctype = "<!DOCTYPE html>"
497    await page.set_content(f"{doctype}<div>hello</div>")
498    result = await page.content()
499    assert result == f"{doctype}{expected_output}"
500
501
502async def test_set_content_should_work_with_HTML_4_doctype(page, server):
503    doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
504    await page.set_content(f"{doctype}<div>hello</div>")
505    result = await page.content()
506    assert result == f"{doctype}{expected_output}"
507
508
509async def test_set_content_should_respect_timeout(page, server):
510    img_path = "/img.png"
511    # stall for image
512    server.set_route(img_path, lambda request: None)
513    with pytest.raises(Error) as exc_info:
514        await page.set_content(
515            f'<img src="{server.PREFIX + img_path}"></img>', timeout=1
516        )
517    assert exc_info.type is TimeoutError
518
519
520async def test_set_content_should_respect_default_navigation_timeout(page, server):
521    page.set_default_navigation_timeout(1)
522    img_path = "/img.png"
523    # stall for image
524    await page.route(img_path, lambda route, request: None)
525
526    with pytest.raises(Error) as exc_info:
527        await page.set_content(f'<img src="{server.PREFIX + img_path}"></img>')
528    assert "Timeout 1ms exceeded" in exc_info.value.message
529    assert exc_info.type is TimeoutError
530
531
532async def test_set_content_should_await_resources_to_load(page, server):
533    img_path = "/img.png"
534    img_route = asyncio.Future()
535    await page.route(img_path, lambda route, request: img_route.set_result(route))
536    loaded = []
537
538    async def load():
539        await page.set_content(f'<img src="{server.PREFIX + img_path}"></img>')
540        loaded.append(True)
541
542    content_promise = asyncio.create_task(load())
543    await asyncio.sleep(0)  # execute scheduled tasks, but don't await them
544    route = await img_route
545    assert loaded == []
546    asyncio.create_task(route.continue_())
547    await content_promise
548
549
550async def test_set_content_should_work_with_tricky_content(page):
551    await page.set_content("<div>hello world</div>" + "\x7F")
552    assert await page.eval_on_selector("div", "div => div.textContent") == "hello world"
553
554
555async def test_set_content_should_work_with_accents(page):
556    await page.set_content("<div>aberración</div>")
557    assert await page.eval_on_selector("div", "div => div.textContent") == "aberración"
558
559
560async def test_set_content_should_work_with_emojis(page):
561    await page.set_content("<div>🐥</div>")
562    assert await page.eval_on_selector("div", "div => div.textContent") == "🐥"
563
564
565async def test_set_content_should_work_with_newline(page):
566    await page.set_content("<div>\n</div>")
567    assert await page.eval_on_selector("div", "div => div.textContent") == "\n"
568
569
570async def test_add_script_tag_should_work_with_a_url(page, server):
571    await page.goto(server.EMPTY_PAGE)
572    script_handle = await page.add_script_tag(url="/injectedfile.js")
573    assert script_handle.as_element()
574    assert await page.evaluate("__injected") == 42
575
576
577async def test_add_script_tag_should_work_with_a_url_and_type_module(page, server):
578    await page.goto(server.EMPTY_PAGE)
579    await page.add_script_tag(url="/es6/es6import.js", type="module")
580    assert await page.evaluate("__es6injected") == 42
581
582
583async def test_add_script_tag_should_work_with_a_path_and_type_module(
584    page, server, assetdir
585):
586    await page.goto(server.EMPTY_PAGE)
587    await page.add_script_tag(path=assetdir / "es6" / "es6pathimport.js", type="module")
588    await page.wait_for_function("window.__es6injected")
589    assert await page.evaluate("__es6injected") == 42
590
591
592async def test_add_script_tag_should_work_with_a_content_and_type_module(page, server):
593    await page.goto(server.EMPTY_PAGE)
594    await page.add_script_tag(
595        content="import num from '/es6/es6module.js';window.__es6injected = num;",
596        type="module",
597    )
598    await page.wait_for_function("window.__es6injected")
599    assert await page.evaluate("__es6injected") == 42
600
601
602async def test_add_script_tag_should_throw_an_error_if_loading_from_url_fail(
603    page, server
604):
605    await page.goto(server.EMPTY_PAGE)
606    with pytest.raises(Error) as exc_info:
607        await page.add_script_tag(url="/nonexistfile.js")
608    assert exc_info.value
609
610
611async def test_add_script_tag_should_work_with_a_path(page, server, assetdir):
612    await page.goto(server.EMPTY_PAGE)
613    script_handle = await page.add_script_tag(path=assetdir / "injectedfile.js")
614    assert script_handle.as_element()
615    assert await page.evaluate("__injected") == 42
616
617
618@pytest.mark.skip_browser("webkit")
619async def test_add_script_tag_should_include_source_url_when_path_is_provided(
620    page, server, assetdir
621):
622    # Lacking sourceURL support in WebKit
623    await page.goto(server.EMPTY_PAGE)
624    await page.add_script_tag(path=assetdir / "injectedfile.js")
625    result = await page.evaluate("__injectedError.stack")
626    assert os.path.join("assets", "injectedfile.js") in result
627
628
629async def test_add_script_tag_should_work_with_content(page, server):
630    await page.goto(server.EMPTY_PAGE)
631    script_handle = await page.add_script_tag(content="window.__injected = 35;")
632    assert script_handle.as_element()
633    assert await page.evaluate("__injected") == 35
634
635
636@pytest.mark.skip_browser("firefox")
637async def test_add_script_tag_should_throw_when_added_with_content_to_the_csp_page(
638    page, server
639):
640    # Firefox fires onload for blocked script before it issues the CSP console error.
641    await page.goto(server.PREFIX + "/csp.html")
642    with pytest.raises(Error) as exc_info:
643        await page.add_script_tag(content="window.__injected = 35;")
644    assert exc_info.value
645
646
647async def test_add_script_tag_should_throw_when_added_with_URL_to_the_csp_page(
648    page, server
649):
650    await page.goto(server.PREFIX + "/csp.html")
651    with pytest.raises(Error) as exc_info:
652        await page.add_script_tag(url=server.CROSS_PROCESS_PREFIX + "/injectedfile.js")
653    assert exc_info.value
654
655
656async def test_add_script_tag_should_throw_a_nice_error_when_the_request_fails(
657    page, server
658):
659    await page.goto(server.EMPTY_PAGE)
660    url = server.PREFIX + "/this_does_not_exist.js"
661    with pytest.raises(Error) as exc_info:
662        await page.add_script_tag(url=url)
663    assert url in exc_info.value.message
664
665
666async def test_add_style_tag_should_work_with_a_url(page, server):
667    await page.goto(server.EMPTY_PAGE)
668    style_handle = await page.add_style_tag(url="/injectedstyle.css")
669    assert style_handle.as_element()
670    assert (
671        await page.evaluate(
672            "window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')"
673        )
674        == "rgb(255, 0, 0)"
675    )
676
677
678async def test_add_style_tag_should_throw_an_error_if_loading_from_url_fail(
679    page, server
680):
681    await page.goto(server.EMPTY_PAGE)
682    with pytest.raises(Error) as exc_info:
683        await page.add_style_tag(url="/nonexistfile.js")
684    assert exc_info.value
685
686
687async def test_add_style_tag_should_work_with_a_path(page, server, assetdir):
688    await page.goto(server.EMPTY_PAGE)
689    style_handle = await page.add_style_tag(path=assetdir / "injectedstyle.css")
690    assert style_handle.as_element()
691    assert (
692        await page.evaluate(
693            "window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')"
694        )
695        == "rgb(255, 0, 0)"
696    )
697
698
699async def test_add_style_tag_should_include_source_url_when_path_is_provided(
700    page, server, assetdir
701):
702    await page.goto(server.EMPTY_PAGE)
703    await page.add_style_tag(path=assetdir / "injectedstyle.css")
704    style_handle = await page.query_selector("style")
705    style_content = await page.evaluate("style => style.innerHTML", style_handle)
706    assert os.path.join("assets", "injectedstyle.css") in style_content
707
708
709async def test_add_style_tag_should_work_with_content(page, server):
710    await page.goto(server.EMPTY_PAGE)
711    style_handle = await page.add_style_tag(content="body { background-color: green; }")
712    assert style_handle.as_element()
713    assert (
714        await page.evaluate(
715            "window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')"
716        )
717        == "rgb(0, 128, 0)"
718    )
719
720
721async def test_add_style_tag_should_throw_when_added_with_content_to_the_CSP_page(
722    page, server
723):
724    await page.goto(server.PREFIX + "/csp.html")
725    with pytest.raises(Error) as exc_info:
726        await page.add_style_tag(content="body { background-color: green; }")
727    assert exc_info.value
728
729
730async def test_add_style_tag_should_throw_when_added_with_URL_to_the_CSP_page(
731    page, server
732):
733    await page.goto(server.PREFIX + "/csp.html")
734    with pytest.raises(Error) as exc_info:
735        await page.add_style_tag(url=server.CROSS_PROCESS_PREFIX + "/injectedstyle.css")
736    assert exc_info.value
737
738
739async def test_url_should_work(page, server):
740    assert page.url == "about:blank"
741    await page.goto(server.EMPTY_PAGE)
742    assert page.url == server.EMPTY_PAGE
743
744
745async def test_url_should_include_hashes(page, server):
746    await page.goto(server.EMPTY_PAGE + "#hash")
747    assert page.url == server.EMPTY_PAGE + "#hash"
748    await page.evaluate("window.location.hash = 'dynamic'")
749    assert page.url == server.EMPTY_PAGE + "#dynamic"
750
751
752async def test_title_should_return_the_page_title(page, server):
753    await page.goto(server.PREFIX + "/title.html")
754    assert await page.title() == "Woof-Woof"
755
756
757async def test_select_option_should_select_single_option(page, server):
758    await page.goto(server.PREFIX + "/input/select.html")
759    await page.select_option("select", "blue")
760    assert await page.evaluate("result.onInput") == ["blue"]
761    assert await page.evaluate("result.onChange") == ["blue"]
762
763
764async def test_select_option_should_select_single_option_by_value(page, server):
765    await page.goto(server.PREFIX + "/input/select.html")
766    await page.select_option("select", "blue")
767    assert await page.evaluate("result.onInput") == ["blue"]
768    assert await page.evaluate("result.onChange") == ["blue"]
769
770
771async def test_select_option_should_select_single_option_by_label(page, server):
772    await page.goto(server.PREFIX + "/input/select.html")
773    await page.select_option("select", label="Indigo")
774    assert await page.evaluate("result.onInput") == ["indigo"]
775    assert await page.evaluate("result.onChange") == ["indigo"]
776
777
778async def test_select_option_should_select_single_option_by_handle(page, server):
779    await page.goto(server.PREFIX + "/input/select.html")
780    await page.select_option(
781        "select", element=await page.query_selector("[id=whiteOption]")
782    )
783    assert await page.evaluate("result.onInput") == ["white"]
784    assert await page.evaluate("result.onChange") == ["white"]
785
786
787async def test_select_option_should_select_single_option_by_index(page, server):
788    await page.goto(server.PREFIX + "/input/select.html")
789    await page.select_option("select", index=2)
790    assert await page.evaluate("result.onInput") == ["brown"]
791    assert await page.evaluate("result.onChange") == ["brown"]
792
793
794async def test_select_option_should_select_only_first_option(page, server):
795    await page.goto(server.PREFIX + "/input/select.html")
796    await page.select_option("select", ["blue", "green", "red"])
797    assert await page.evaluate("result.onInput") == ["blue"]
798    assert await page.evaluate("result.onChange") == ["blue"]
799
800
801async def test_select_option_should_not_throw_when_select_causes_navigation(
802    page, server
803):
804    await page.goto(server.PREFIX + "/input/select.html")
805    await page.eval_on_selector(
806        "select",
807        "select => select.addEventListener('input', () => window.location = '/empty.html')",
808    )
809    async with page.expect_navigation():
810        await page.select_option("select", "blue")
811    assert "empty.html" in page.url
812
813
814async def test_select_option_should_select_multiple_options(page, server):
815    await page.goto(server.PREFIX + "/input/select.html")
816    await page.evaluate("makeMultiple()")
817    await page.select_option("select", ["blue", "green", "red"])
818    assert await page.evaluate("result.onInput") == ["blue", "green", "red"]
819    assert await page.evaluate("result.onChange") == ["blue", "green", "red"]
820
821
822async def test_select_option_should_select_multiple_options_with_attributes(
823    page, server
824):
825    await page.goto(server.PREFIX + "/input/select.html")
826    await page.evaluate("makeMultiple()")
827    await page.select_option(
828        "select",
829        value="blue",
830        label="Green",
831        index=4,
832    )
833    assert await page.evaluate("result.onInput") == ["blue", "gray", "green"]
834    assert await page.evaluate("result.onChange") == ["blue", "gray", "green"]
835
836
837async def test_select_option_should_respect_event_bubbling(page, server):
838    await page.goto(server.PREFIX + "/input/select.html")
839    await page.select_option("select", "blue")
840    assert await page.evaluate("result.onBubblingInput") == ["blue"]
841    assert await page.evaluate("result.onBubblingChange") == ["blue"]
842
843
844async def test_select_option_should_throw_when_element_is_not_a__select_(page, server):
845    await page.goto(server.PREFIX + "/input/select.html")
846    with pytest.raises(Error) as exc_info:
847        await page.select_option("body", "")
848    assert "Element is not a <select> element" in exc_info.value.message
849
850
851async def test_select_option_should_return_on_no_matched_values(page, server):
852    await page.goto(server.PREFIX + "/input/select.html")
853    with pytest.raises(TimeoutError) as exc_info:
854        await page.select_option("select", ["42", "abc"], timeout=1000)
855    assert "Timeout 1000" in exc_info.value.message
856
857
858async def test_select_option_should_return_an_array_of_matched_values(page, server):
859    await page.goto(server.PREFIX + "/input/select.html")
860    await page.evaluate("makeMultiple()")
861    result = await page.select_option("select", ["blue", "black", "magenta"])
862    assert result == ["black", "blue", "magenta"]
863
864
865async def test_select_option_should_return_an_array_of_one_element_when_multiple_is_not_set(
866    page, server
867):
868    await page.goto(server.PREFIX + "/input/select.html")
869    result = await page.select_option("select", ["42", "blue", "black", "magenta"])
870    assert len(result) == 1
871
872
873async def test_select_option_should_return_on_no_values(page, server):
874    await page.goto(server.PREFIX + "/input/select.html")
875    result = await page.select_option("select", [])
876    assert result == []
877
878
879async def test_select_option_should_not_allow_null_items(page, server):
880    await page.goto(server.PREFIX + "/input/select.html")
881    await page.evaluate("makeMultiple()")
882    with pytest.raises(Error) as exc_info:
883        await page.select_option("select", ["blue", None, "black", "magenta"])
884    assert "expected string, got object" in exc_info.value.message
885
886
887async def test_select_option_should_unselect_with_null(page, server):
888    await page.goto(server.PREFIX + "/input/select.html")
889    await page.evaluate("makeMultiple()")
890    result = await page.select_option("select", ["blue", "black", "magenta"])
891    assert result == ["black", "blue", "magenta"]
892    await page.select_option("select", None)
893    assert await page.eval_on_selector(
894        "select",
895        "select => Array.from(select.options).every(option => !option.selected)",
896    )
897
898
899async def test_select_option_should_deselect_all_options_when_passed_no_values_for_a_multiple_select(
900    page, server
901):
902    await page.goto(server.PREFIX + "/input/select.html")
903    await page.evaluate("makeMultiple()")
904    await page.select_option("select", ["blue", "black", "magenta"])
905    await page.select_option("select", [])
906    assert await page.eval_on_selector(
907        "select",
908        "select => Array.from(select.options).every(option => !option.selected)",
909    )
910
911
912async def test_select_option_should_deselect_all_options_when_passed_no_values_for_a_select_without_multiple(
913    page, server
914):
915    await page.goto(server.PREFIX + "/input/select.html")
916    await page.select_option("select", ["blue", "black", "magenta"])
917    await page.select_option("select", [])
918    assert await page.eval_on_selector(
919        "select",
920        "select => Array.from(select.options).every(option => !option.selected)",
921    )
922
923
924async def test_select_option_should_work_when_re_defining_top_level_event_class(
925    page, server
926):
927    await page.goto(server.PREFIX + "/input/select.html")
928    await page.evaluate("window.Event = null")
929    await page.select_option("select", "blue")
930    assert await page.evaluate("result.onInput") == ["blue"]
931    assert await page.evaluate("result.onChange") == ["blue"]
932
933
934async def give_it_a_chance_to_fill(page):
935    for i in range(5):
936        await page.evaluate(
937            "() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"
938        )
939
940
941async def test_fill_should_fill_textarea(page, server):
942    await page.goto(server.PREFIX + "/input/textarea.html")
943    await page.fill("textarea", "some value")
944    assert await page.evaluate("result") == "some value"
945
946
947async def test_fill_should_fill_input(page, server):
948    await page.goto(server.PREFIX + "/input/textarea.html")
949    await page.fill("input", "some value")
950    assert await page.evaluate("result") == "some value"
951
952
953async def test_fill_should_throw_on_unsupported_inputs(page, server):
954    await page.goto(server.PREFIX + "/input/textarea.html")
955    for type in [
956        "button",
957        "checkbox",
958        "file",
959        "image",
960        "radio",
961        "reset",
962        "submit",
963    ]:
964        await page.eval_on_selector(
965            "input", "(input, type) => input.setAttribute('type', type)", type
966        )
967        with pytest.raises(Error) as exc_info:
968            await page.fill("input", "")
969        assert f'input of type "{type}" cannot be filled' in exc_info.value.message
970
971
972async def test_fill_should_fill_different_input_types(page, server):
973    await page.goto(server.PREFIX + "/input/textarea.html")
974    for type in ["password", "search", "tel", "text", "url"]:
975        await page.eval_on_selector(
976            "input", "(input, type) => input.setAttribute('type', type)", type
977        )
978        await page.fill("input", "text " + type)
979        assert await page.evaluate("result") == "text " + type
980
981
982async def test_fill_should_fill_date_input_after_clicking(page, server):
983    await page.set_content("<input type=date>")
984    await page.click("input")
985    await page.fill("input", "2020-03-02")
986    assert await page.eval_on_selector("input", "input => input.value") == "2020-03-02"
987
988
989@pytest.mark.skip_browser("webkit")
990async def test_fill_should_throw_on_incorrect_date(page, server):
991    # Disabled as in upstream, we should validate time in the Playwright lib
992    await page.set_content("<input type=date>")
993    with pytest.raises(Error) as exc_info:
994        await page.fill("input", "2020-13-05")
995    assert "Malformed value" in exc_info.value.message
996
997
998async def test_fill_should_fill_time_input(page, server):
999    await page.set_content("<input type=time>")
1000    await page.fill("input", "13:15")
1001    assert await page.eval_on_selector("input", "input => input.value") == "13:15"
1002
1003
1004@pytest.mark.skip_browser("webkit")
1005async def test_fill_should_throw_on_incorrect_time(page, server):
1006    # Disabled as in upstream, we should validate time in the Playwright lib
1007    await page.set_content("<input type=time>")
1008    with pytest.raises(Error) as exc_info:
1009        await page.fill("input", "25:05")
1010    assert "Malformed value" in exc_info.value.message
1011
1012
1013async def test_fill_should_fill_datetime_local_input(page, server):
1014    await page.set_content("<input type=datetime-local>")
1015    await page.fill("input", "2020-03-02T05:15")
1016    assert (
1017        await page.eval_on_selector("input", "input => input.value")
1018        == "2020-03-02T05:15"
1019    )
1020
1021
1022@pytest.mark.only_browser("chromium")
1023async def test_fill_should_throw_on_incorrect_datetime_local(page):
1024    await page.set_content("<input type=datetime-local>")
1025    with pytest.raises(Error) as exc_info:
1026        await page.fill("input", "abc")
1027    assert "Malformed value" in exc_info.value.message
1028
1029
1030async def test_fill_should_fill_contenteditable(page, server):
1031    await page.goto(server.PREFIX + "/input/textarea.html")
1032    await page.fill("div[contenteditable]", "some value")
1033    assert (
1034        await page.eval_on_selector("div[contenteditable]", "div => div.textContent")
1035        == "some value"
1036    )
1037
1038
1039async def test_fill_should_fill_elements_with_existing_value_and_selection(
1040    page, server
1041):
1042    await page.goto(server.PREFIX + "/input/textarea.html")
1043
1044    await page.eval_on_selector("input", "input => input.value = 'value one'")
1045    await page.fill("input", "another value")
1046    assert await page.evaluate("result") == "another value"
1047
1048    await page.eval_on_selector(
1049        "input",
1050        """input => {
1051        input.selectionStart = 1
1052        input.selectionEnd = 2
1053    }""",
1054    )
1055
1056    await page.fill("input", "maybe this one")
1057    assert await page.evaluate("result") == "maybe this one"
1058
1059    await page.eval_on_selector(
1060        "div[contenteditable]",
1061        """div => {
1062        div.innerHTML = 'some text <span>some more text<span> and even more text'
1063        range = document.createRange()
1064        range.selectNodeContents(div.querySelector('span'))
1065        selection = window.getSelection()
1066        selection.removeAllRanges()
1067        selection.addRange(range)
1068    }""",
1069    )
1070
1071    await page.fill("div[contenteditable]", "replace with this")
1072    assert (
1073        await page.eval_on_selector("div[contenteditable]", "div => div.textContent")
1074        == "replace with this"
1075    )
1076
1077
1078async def test_fill_should_throw_when_element_is_not_an_input_textarea_or_contenteditable(
1079    page, server
1080):
1081    await page.goto(server.PREFIX + "/input/textarea.html")
1082    with pytest.raises(Error) as exc_info:
1083        await page.fill("body", "")
1084    assert "Element is not an <input>" in exc_info.value.message
1085
1086
1087async def test_fill_should_throw_if_passed_a_non_string_value(page, server):
1088    await page.goto(server.PREFIX + "/input/textarea.html")
1089    with pytest.raises(Error) as exc_info:
1090        await page.fill("textarea", 123)
1091    assert "expected string, got number" in exc_info.value.message
1092
1093
1094async def test_fill_should_retry_on_disabled_element(page, server):
1095    await page.goto(server.PREFIX + "/input/textarea.html")
1096    await page.eval_on_selector("input", "i => i.disabled = true")
1097    done = []
1098
1099    async def fill():
1100        await page.fill("input", "some value")
1101        done.append(True)
1102
1103    promise = asyncio.create_task(fill())
1104    await give_it_a_chance_to_fill(page)
1105    assert done == []
1106    assert await page.evaluate("result") == ""
1107
1108    await page.eval_on_selector("input", "i => i.disabled = false")
1109    await promise
1110    assert await page.evaluate("result") == "some value"
1111
1112
1113async def test_fill_should_retry_on_readonly_element(page, server):
1114    await page.goto(server.PREFIX + "/input/textarea.html")
1115    await page.eval_on_selector("textarea", "i => i.readOnly = true")
1116    done = []
1117
1118    async def fill():
1119        await page.fill("textarea", "some value")
1120        done.append(True)
1121
1122    promise = asyncio.create_task(fill())
1123    await give_it_a_chance_to_fill(page)
1124    assert done == []
1125    assert await page.evaluate("result") == ""
1126
1127    await page.eval_on_selector("textarea", "i => i.readOnly = false")
1128    await promise
1129    assert await page.evaluate("result") == "some value"
1130
1131
1132async def test_fill_should_retry_on_invisible_element(page, server):
1133    await page.goto(server.PREFIX + "/input/textarea.html")
1134    await page.eval_on_selector("input", "i => i.style.display = 'none'")
1135    done = []
1136
1137    async def fill():
1138        await page.fill("input", "some value")
1139        done.append(True)
1140
1141    promise = asyncio.create_task(fill())
1142    await give_it_a_chance_to_fill(page)
1143    assert done == []
1144    assert await page.evaluate("result") == ""
1145
1146    await page.eval_on_selector("input", "i => i.style.display = 'inline'")
1147    await promise
1148    assert await page.evaluate("result") == "some value"
1149
1150
1151async def test_fill_should_be_able_to_fill_the_body(page):
1152    await page.set_content('<body contentEditable="true"></body>')
1153    await page.fill("body", "some value")
1154    assert await page.evaluate("document.body.textContent") == "some value"
1155
1156
1157async def test_fill_should_fill_fixed_position_input(page):
1158    await page.set_content('<input style="position: fixed;" />')
1159    await page.fill("input", "some value")
1160    assert await page.evaluate("document.querySelector('input').value") == "some value"
1161
1162
1163async def test_fill_should_be_able_to_fill_when_focus_is_in_the_wrong_frame(page):
1164    await page.set_content(
1165        """
1166      <div contentEditable="true"></div>
1167      <iframe></iframe>
1168    """
1169    )
1170    await page.focus("iframe")
1171    await page.fill("div", "some value")
1172    assert await page.eval_on_selector("div", "d => d.textContent") == "some value"
1173
1174
1175async def test_fill_should_be_able_to_fill_the_input_type_number_(page):
1176    await page.set_content('<input id="input" type="number"></input>')
1177    await page.fill("input", "42")
1178    assert await page.evaluate("input.value") == "42"
1179
1180
1181async def test_fill_should_be_able_to_fill_exponent_into_the_input_type_number_(page):
1182    await page.set_content('<input id="input" type="number"></input>')
1183    await page.fill("input", "-10e5")
1184    assert await page.evaluate("input.value") == "-10e5"
1185
1186
1187async def test_fill_should_be_able_to_fill_input_type_number__with_empty_string(page):
1188    await page.set_content('<input id="input" type="number" value="123"></input>')
1189    await page.fill("input", "")
1190    assert await page.evaluate("input.value") == ""
1191
1192
1193async def test_fill_should_not_be_able_to_fill_text_into_the_input_type_number_(page):
1194    await page.set_content('<input id="input" type="number"></input>')
1195    with pytest.raises(Error) as exc_info:
1196        await page.fill("input", "abc")
1197    assert "Cannot type text into input[type=number]" in exc_info.value.message
1198
1199
1200async def test_fill_should_be_able_to_clear(page, server):
1201    await page.goto(server.PREFIX + "/input/textarea.html")
1202    await page.fill("input", "some value")
1203    assert await page.evaluate("result") == "some value"
1204    await page.fill("input", "")
1205    assert await page.evaluate("result") == ""
1206
1207
1208async def test_close_event_should_work_with_window_close(page, server):
1209    async with page.expect_popup() as popup_info:
1210        await page.evaluate("window['newPage'] = window.open('about:blank')")
1211    popup = await popup_info.value
1212
1213    async with popup.expect_event("close"):
1214        await page.evaluate("window['newPage'].close()")
1215
1216
1217async def test_close_event_should_work_with_page_close(context, server):
1218    page = await context.new_page()
1219    async with page.expect_event("close"):
1220        await page.close()
1221
1222
1223async def test_page_context_should_return_the_correct_browser_instance(page, context):
1224    assert page.context == context
1225
1226
1227async def test_frame_should_respect_name(page, server):
1228    await page.set_content("<iframe name=target></iframe>")
1229    assert page.frame(name="bogus") is None
1230    frame = page.frame(name="target")
1231    assert frame
1232    assert frame == page.main_frame.child_frames[0]
1233
1234
1235async def test_frame_should_respect_url(page, server):
1236    await page.set_content(f'<iframe src="{server.EMPTY_PAGE}"></iframe>')
1237    assert page.frame(url=re.compile(r"bogus")) is None
1238    assert page.frame(url=re.compile(r"empty")).url == server.EMPTY_PAGE
1239
1240
1241async def test_press_should_work(page, server):
1242    await page.goto(server.PREFIX + "/input/textarea.html")
1243    await page.press("textarea", "a")
1244    assert await page.evaluate("document.querySelector('textarea').value") == "a"
1245
1246
1247async def test_frame_press_should_work(page, server):
1248    await page.set_content(
1249        f'<iframe name=inner src="{server.PREFIX}/input/textarea.html"></iframe>'
1250    )
1251    frame = page.frame("inner")
1252    await frame.press("textarea", "a")
1253    assert await frame.evaluate("document.querySelector('textarea').value") == "a"
1254
1255
1256async def test_should_emulate_reduced_motion(page, server):
1257    assert await page.evaluate(
1258        "matchMedia('(prefers-reduced-motion: no-preference)').matches"
1259    )
1260    await page.emulate_media(reduced_motion="reduce")
1261    assert await page.evaluate("matchMedia('(prefers-reduced-motion: reduce)').matches")
1262    assert not await page.evaluate(
1263        "matchMedia('(prefers-reduced-motion: no-preference)').matches"
1264    )
1265    await page.emulate_media(reduced_motion="no-preference")
1266    assert not await page.evaluate(
1267        "matchMedia('(prefers-reduced-motion: reduce)').matches"
1268    )
1269    assert await page.evaluate(
1270        "matchMedia('(prefers-reduced-motion: no-preference)').matches"
1271    )
1272
1273
1274async def test_input_value(page: Page, server: Server):
1275    await page.goto(server.PREFIX + "/input/textarea.html")
1276
1277    await page.fill("input", "my-text-content")
1278    assert await page.input_value("input") == "my-text-content"
1279
1280    await page.fill("input", "")
1281    assert await page.input_value("input") == ""
1282
1283
1284async def test_drag_and_drop_helper_method(page: Page, server: Server):
1285    await page.goto(server.PREFIX + "/drag-n-drop.html")
1286    await page.drag_and_drop("#source", "#target")
1287    assert (
1288        await page.eval_on_selector(
1289            "#target", "target => target.contains(document.querySelector('#source'))"
1290        )
1291        is True
1292    )
1293
1294
1295async def test_drag_and_drop_with_position(page: Page, server: Server):
1296    await page.goto(server.EMPTY_PAGE)
1297    await page.set_content(
1298        """
1299      <div style="width:100px;height:100px;background:red;" id="red">
1300      </div>
1301      <div style="width:100px;height:100px;background:blue;" id="blue">
1302      </div>
1303    """
1304    )
1305    events_handle = await page.evaluate_handle(
1306        """
1307        () => {
1308        const events = [];
1309        document.getElementById('red').addEventListener('mousedown', event => {
1310            events.push({
1311            type: 'mousedown',
1312            x: event.offsetX,
1313            y: event.offsetY,
1314            });
1315        });
1316        document.getElementById('blue').addEventListener('mouseup', event => {
1317            events.push({
1318            type: 'mouseup',
1319            x: event.offsetX,
1320            y: event.offsetY,
1321            });
1322        });
1323        return events;
1324        }
1325    """
1326    )
1327    await page.drag_and_drop(
1328        "#red",
1329        "#blue",
1330        source_position={"x": 34, "y": 7},
1331        target_position={"x": 10, "y": 20},
1332    )
1333    assert await events_handle.json_value() == [
1334        {"type": "mousedown", "x": 34, "y": 7},
1335        {"type": "mouseup", "x": 10, "y": 20},
1336    ]
1337
1338
1339async def test_should_check_box_using_set_checked(page: Page):
1340    await page.set_content("`<input id='checkbox' type='checkbox'></input>`")
1341    await page.set_checked("input", True)
1342    assert await page.evaluate("checkbox.checked") is True
1343    await page.set_checked("input", False)
1344    assert await page.evaluate("checkbox.checked") is False
1345
1346
1347async def test_should_set_bodysize_and_headersize(page: Page, server: Server):
1348    await page.goto(server.EMPTY_PAGE)
1349    async with page.expect_request("*/**") as request_info:
1350        await page.evaluate(
1351            "() => fetch('./get', { method: 'POST', body: '12345'}).then(r => r.text())"
1352        )
1353    request = await request_info.value
1354    sizes = await request.sizes()
1355    assert sizes["requestBodySize"] == 5
1356    assert sizes["requestHeadersSize"] >= 300
1357
1358
1359async def test_should_set_bodysize_to_0(page: Page, server: Server):
1360    await page.goto(server.EMPTY_PAGE)
1361    async with page.expect_request("*/**") as request_info:
1362        await page.evaluate("() => fetch('./get').then(r => r.text())")
1363    request = await request_info.value
1364    sizes = await request.sizes()
1365    assert sizes["requestBodySize"] == 0
1366    assert sizes["requestHeadersSize"] >= 200
1367
1368
1369@pytest.mark.skip_browser("webkit")  # https://bugs.webkit.org/show_bug.cgi?id=225281
1370async def test_should_emulate_forced_colors(page):
1371    assert await page.evaluate("matchMedia('(forced-colors: none)').matches")
1372    await page.emulate_media(forced_colors="none")
1373    assert await page.evaluate("matchMedia('(forced-colors: none)').matches")
1374    assert not await page.evaluate("matchMedia('(forced-colors: active)').matches")
1375    await page.emulate_media(forced_colors="active")
1376    assert await page.evaluate("matchMedia('(forced-colors: active)').matches")
1377    assert not await page.evaluate("matchMedia('(forced-colors: none)').matches")
1378
1379
1380async def test_should_not_throw_when_continuing_while_page_is_closing(
1381    page: Page, server: Server
1382):
1383    done = None
1384
1385    def handle_route(route: Route) -> None:
1386        nonlocal done
1387        done = asyncio.gather(route.continue_(), page.close())
1388
1389    await page.route("**/*", handle_route)
1390    with pytest.raises(Error):
1391        await page.goto(server.EMPTY_PAGE)
1392    await done
1393
1394
1395async def test_should_not_throw_when_continuing_after_page_is_closed(
1396    page: Page, server: Server
1397):
1398    done = asyncio.Future()
1399
1400    async def handle_route(route: Route) -> None:
1401        await page.close()
1402        await route.continue_()
1403        nonlocal done
1404        done.set_result(True)
1405
1406    await page.route("**/*", handle_route)
1407    with pytest.raises(Error):
1408        await page.goto(server.EMPTY_PAGE)
1409    await done
1410
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run Python Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Python on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)