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