How to use test_click_a_partially_obscured_button 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_click.py

Source: test_click.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
16
17import pytest
18
19from playwright.async_api import Error, TimeoutError
20
21
22async def give_it_a_chance_to_click(page):
23    for _ in range(5):
24        await page.evaluate(
25            "() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"
26        )
27
28
29async def test_click_the_button(page, server):
30    await page.goto(server.PREFIX + "/input/button.html")
31    await page.click("button")
32    assert await page.evaluate("result") == "Clicked"
33
34
35async def test_click_svg(page, server):
36    await page.set_content(
37        """
38        <svg height="100" width="100">
39            <circle onclick="javascript:window.__CLICKED=42" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
40        </svg>
41        """
42    )
43    await page.click("circle")
44    assert await page.evaluate("window.__CLICKED") == 42
45
46
47async def test_click_the_button_if_window_node_is_removed(page, server):
48    await page.goto(server.PREFIX + "/input/button.html")
49    await page.evaluate("() => delete window.Node")
50    await page.click("button")
51    assert await page.evaluate("() => result") == "Clicked"
52
53
54async def test_click_on_a_span_with_an_inline_element_inside(page, server):
55    await page.set_content(
56        """
57        <style>
58        span::before {
59            content: 'q'
60        }
61        </style>
62        <span onclick='javascript:window.CLICKED=42'></span>
63        """
64    )
65    await page.click("span")
66    assert await page.evaluate("window.CLICKED") == 42
67
68
69async def test_click_not_throw_when_page_closes(browser, server):
70    context = await browser.new_context()
71    page = await context.new_page()
72    try:
73        await asyncio.gather(
74            page.close(),
75            page.mouse.click(1, 2),
76        )
77    except Error:
78        pass
79    await context.close()
80
81
82async def test_click_the_button_after_navigation(page, server):
83    await page.goto(server.PREFIX + "/input/button.html")
84    await page.click("button")
85    await page.goto(server.PREFIX + "/input/button.html")
86    await page.click("button")
87    assert await page.evaluate("() => result") == "Clicked"
88
89
90async def test_click_the_button_after_a_cross_origin_navigation_(page, server):
91    await page.goto(server.PREFIX + "/input/button.html")
92    await page.click("button")
93    await page.goto(server.CROSS_PROCESS_PREFIX + "/input/button.html")
94    await page.click("button")
95    assert await page.evaluate("() => result") == "Clicked"
96
97
98async def test_click_with_disabled_javascript(browser, server):
99    context = await browser.new_context(java_script_enabled=False)
100    page = await context.new_page()
101    await page.goto(server.PREFIX + "/wrappedlink.html")
102    async with page.expect_navigation():
103        await page.click("a")
104    assert page.url == server.PREFIX + "/wrappedlink.html#clicked"
105    await context.close()
106
107
108async def test_click_when_one_of_inline_box_children_is_outside_of_viewport(
109    page, server
110):
111    await page.set_content(
112        """
113        <style>
114        i {
115            position: absolute
116            top: -1000px
117        }
118        </style>
119        <span onclick='javascript:window.CLICKED = 42;'><i>woof</i><b>doggo</b></span>
120        """
121    )
122    await page.click("span")
123    assert await page.evaluate("() => window.CLICKED") == 42
124
125
126async def test_select_the_text_by_triple_clicking(page, server):
127    await page.goto(server.PREFIX + "/input/textarea.html")
128    text = "This is the text that we are going to try to select. Let's see how it goes."
129    await page.fill("textarea", text)
130    await page.click("textarea", click_count=3)
131    assert (
132        await page.evaluate(
133            """() => {
134                textarea = document.querySelector('textarea')
135                return textarea.value.substring(textarea.selectionStart, textarea.selectionEnd)
136            }"""
137        )
138        == text
139    )
140
141
142async def test_click_offscreen_buttons(page, server):
143    await page.goto(server.PREFIX + "/offscreenbuttons.html")
144    messages = []
145    page.on("console", lambda msg: messages.append(msg.text))
146    for i in range(11):
147        # We might've scrolled to click a button - reset to (0, 0).
148        await page.evaluate("window.scrollTo(0, 0)")
149        await page.click(f"#btn{i}")
150    assert messages == [
151        "button #0 clicked",
152        "button #1 clicked",
153        "button #2 clicked",
154        "button #3 clicked",
155        "button #4 clicked",
156        "button #5 clicked",
157        "button #6 clicked",
158        "button #7 clicked",
159        "button #8 clicked",
160        "button #9 clicked",
161        "button #10 clicked",
162    ]
163
164
165async def test_waitFor_visible_when_already_visible(page, server):
166    await page.goto(server.PREFIX + "/input/button.html")
167    await page.click("button")
168    assert await page.evaluate("result") == "Clicked"
169
170
171async def test_wait_with_force(page, server):
172    error = None
173    await page.goto(server.PREFIX + "/input/button.html")
174    await page.eval_on_selector("button", "b => b.style.display = 'none'")
175    try:
176        await page.click("button", force=True)
177    except Error as e:
178        error = e
179    assert "Element is not visible" in error.message
180    assert await page.evaluate("result") == "Was not clicked"
181
182
183async def test_wait_for_display_none_to_be_gone(page, server):
184    done = list()
185    await page.goto(server.PREFIX + "/input/button.html")
186    await page.eval_on_selector("button", "b => b.style.display = 'none'")
187
188    async def click():
189        await page.click("button", timeout=0)
190        done.append(True)
191
192    clicked = asyncio.create_task(click())
193    await give_it_a_chance_to_click(page)
194    assert await page.evaluate("result") == "Was not clicked"
195    assert done == []
196    await page.eval_on_selector("button", "b => b.style.display = 'block'")
197    await clicked
198    assert done == [True]
199    assert await page.evaluate("result") == "Clicked"
200
201
202async def test_wait_for_visibility_hidden_to_be_gone(page, server):
203    done = list()
204    await page.goto(server.PREFIX + "/input/button.html")
205    await page.eval_on_selector("button", "b => b.style.visibility = 'hidden'")
206
207    async def click():
208        await page.click("button", timeout=0)
209        done.append(True)
210
211    clicked = asyncio.create_task(click())
212    await give_it_a_chance_to_click(page)
213    assert await page.evaluate("result") == "Was not clicked"
214    assert done == []
215    await page.eval_on_selector("button", "b => b.style.visibility = 'visible'")
216    await clicked
217    assert done == [True]
218    assert await page.evaluate("result") == "Clicked"
219
220
221async def test_timeout_waiting_for_display_none_to_be_gone(page, server):
222    await page.goto(server.PREFIX + "/input/button.html")
223    await page.eval_on_selector("button", "b => b.style.display = 'none'")
224    try:
225        await page.click("button", timeout=5000)
226    except Error as e:
227        error = e
228    assert "Timeout 5000ms exceeded" in error.message
229    assert "waiting for element to be visible, enabled and not moving" in error.message
230    assert "element is not visible - waiting" in error.message
231
232
233async def test_timeout_waiting_for_visbility_hidden_to_be_gone(page, server):
234    await page.goto(server.PREFIX + "/input/button.html")
235    await page.eval_on_selector("button", "b => b.style.visibility = 'hidden'")
236    try:
237        await page.click("button", timeout=5000)
238    except Error as e:
239        error = e
240    assert "Timeout 5000ms exceeded" in error.message
241    assert "waiting for element to be visible, enabled and not moving" in error.message
242    assert "element is not visible - waiting" in error.message
243
244
245async def test_waitFor_visible_when_parent_is_hidden(page, server):
246    done = list()
247    await page.goto(server.PREFIX + "/input/button.html")
248    await page.eval_on_selector("button", "b => b.parentElement.style.display = 'none'")
249
250    async def click():
251        await page.click("button", timeout=0)
252        done.append(True)
253
254    clicked = asyncio.create_task(click())
255    await give_it_a_chance_to_click(page)
256    assert done == []
257    await page.eval_on_selector(
258        "button", "b => b.parentElement.style.display = 'block'"
259    )
260    await clicked
261    assert done == [True]
262    assert await page.evaluate("result") == "Clicked"
263
264
265async def test_click_wrapped_links(page, server):
266    await page.goto(server.PREFIX + "/wrappedlink.html")
267    await page.click("a")
268    assert await page.evaluate("window.__clicked")
269
270
271async def test_click_on_checkbox_input_and_toggle(page, server):
272    await page.goto(server.PREFIX + "/input/checkbox.html")
273    assert await page.evaluate("() => result.check") is None
274    await page.click("input#agree")
275    assert await page.evaluate("result.check")
276    assert await page.evaluate("result.events") == [
277        "mouseover",
278        "mouseenter",
279        "mousemove",
280        "mousedown",
281        "mouseup",
282        "click",
283        "input",
284        "change",
285    ]
286    await page.click("input#agree")
287    assert await page.evaluate("result.check") is False
288
289
290async def test_click_on_checkbox_label_and_toggle(page, server):
291    await page.goto(server.PREFIX + "/input/checkbox.html")
292    assert await page.evaluate("result.check") is None
293    await page.click('label[for="agree"]')
294    assert await page.evaluate("result.check")
295    assert await page.evaluate("result.events") == [
296        "click",
297        "input",
298        "change",
299    ]
300    await page.click('label[for="agree"]')
301    assert await page.evaluate("result.check") is False
302
303
304async def test_not_hang_with_touch_enabled_viewports(playwright, server, browser):
305    iphone_6 = playwright.devices["iPhone 6"]
306    context = await browser.new_context(
307        viewport=iphone_6["viewport"], has_touch=iphone_6["has_touch"]
308    )
309    page = await context.new_page()
310    await page.mouse.down()
311    await page.mouse.move(100, 10)
312    await page.mouse.up()
313    await context.close()
314
315
316async def test_scroll_and_click_the_button(page, server):
317    await page.goto(server.PREFIX + "/input/scrollable.html")
318    await page.click("#button-5")
319    assert (
320        await page.evaluate("document.querySelector('#button-5').textContent")
321        == "clicked"
322    )
323    await page.click("#button-80")
324    assert (
325        await page.evaluate("document.querySelector('#button-80').textContent")
326        == "clicked"
327    )
328
329
330async def test_double_click_the_button(page, server):
331    await page.goto(server.PREFIX + "/input/button.html")
332    await page.evaluate(
333        """() => {
334            window.double = false;
335            button = document.querySelector('button');
336            button.addEventListener('dblclick', event => window.double = true);
337        }"""
338    )
339
340    await page.dblclick("button")
341    assert await page.evaluate("double")
342    assert await page.evaluate("result") == "Clicked"
343
344
345async def test_click_a_partially_obscured_button(page, server):
346    await page.goto(server.PREFIX + "/input/button.html")
347    await page.evaluate(
348        """() => {
349            button = document.querySelector('button');
350            button.textContent = 'Some really long text that will go offscreen';
351            button.style.position = 'absolute';
352            button.style.left = '368px';
353        }"""
354    )
355
356    await page.click("button")
357    assert await page.evaluate("() => window.result") == "Clicked"
358
359
360async def test_click_a_rotated_button(page, server):
361    await page.goto(server.PREFIX + "/input/rotatedButton.html")
362    await page.click("button")
363    assert await page.evaluate("result") == "Clicked"
364
365
366async def test_fire_contextmenu_event_on_right_click(page, server):
367    await page.goto(server.PREFIX + "/input/scrollable.html")
368    await page.click("#button-8", button="right")
369    assert (
370        await page.evaluate("document.querySelector('#button-8').textContent")
371        == "context menu"
372    )
373
374
375async def test_click_links_which_cause_navigation(page, server):
376    await page.set_content(f'<a href="{server.EMPTY_PAGE}">empty.html</a>')
377    # This await should not hang.
378    await page.click("a")
379
380
381async def test_click_the_button_inside_an_iframe(page, server, utils):
382    await page.goto(server.EMPTY_PAGE)
383    await page.set_content('<div style="width:100px;height:100px">spacer</div>')
384    await utils.attach_frame(page, "button-test", server.PREFIX + "/input/button.html")
385    frame = page.frames[1]
386    button = await frame.query_selector("button")
387    await button.click()
388    assert await frame.evaluate("window.result") == "Clicked"
389
390
391async def test_click_the_button_with_device_scale_factor_set(browser, server, utils):
392    context = await browser.new_context(
393        viewport={"width": 400, "height": 400}, device_scale_factor=5
394    )
395    page = await context.new_page()
396    assert await page.evaluate("window.devicePixelRatio") == 5
397    await page.set_content('<div style="width:100px;height:100px">spacer</div>')
398    await utils.attach_frame(page, "button-test", server.PREFIX + "/input/button.html")
399    frame = page.frames[1]
400    button = await frame.query_selector("button")
401    await button.click()
402    assert await frame.evaluate("window.result") == "Clicked"
403    await context.close()
404
405
406async def test_click_the_button_with_px_border_with_offset(page, server, is_webkit):
407    await page.goto(server.PREFIX + "/input/button.html")
408    await page.eval_on_selector("button", "button => button.style.borderWidth = '8px'")
409    await page.click("button", position={"x": 20, "y": 10})
410    assert await page.evaluate("result") == "Clicked"
411    # Safari reports border-relative offsetX/offsetY.
412    assert await page.evaluate("offsetX") == 20 + 8 if is_webkit else 20
413    assert await page.evaluate("offsetY") == 10 + 8 if is_webkit else 10
414
415
416async def test_click_the_button_with_em_border_with_offset(page, server, is_webkit):
417    await page.goto(server.PREFIX + "/input/button.html")
418    await page.eval_on_selector("button", "button => button.style.borderWidth = '2em'")
419    await page.eval_on_selector("button", "button => button.style.fontSize = '12px'")
420    await page.click("button", position={"x": 20, "y": 10})
421    assert await page.evaluate("result") == "Clicked"
422    # Safari reports border-relative offsetX/offsetY.
423    assert await page.evaluate("offsetX") == 12 * 2 + 20 if is_webkit else 20
424    assert await page.evaluate("offsetY") == 12 * 2 + 10 if is_webkit else 10
425
426
427async def test_click_a_very_large_button_with_offset(page, server, is_webkit):
428    await page.goto(server.PREFIX + "/input/button.html")
429    await page.eval_on_selector("button", "button => button.style.borderWidth = '8px'")
430    await page.eval_on_selector(
431        "button", "button => button.style.height = button.style.width = '2000px'"
432    )
433    await page.click("button", position={"x": 1900, "y": 1910})
434    assert await page.evaluate("() => window.result") == "Clicked"
435    # Safari reports border-relative offsetX/offsetY.
436    assert await page.evaluate("() => offsetX") == 1900 + 8 if is_webkit else 1900
437    assert await page.evaluate("() => offsetY") == 1910 + 8 if is_webkit else 1910
438
439
440async def test_click_a_button_in_scrolling_container_with_offset(
441    page, server, is_webkit
442):
443    await page.goto(server.PREFIX + "/input/button.html")
444    await page.eval_on_selector(
445        "button",
446        """button => {
447            container = document.createElement('div');
448            container.style.overflow = 'auto';
449            container.style.width = '200px';
450            container.style.height = '200px';
451            button.parentElement.insertBefore(container, button);
452            container.appendChild(button);
453            button.style.height = '2000px';
454            button.style.width = '2000px';
455            button.style.borderWidth = '8px';
456        }""",
457    )
458
459    await page.click("button", position={"x": 1900, "y": 1910})
460    assert await page.evaluate("window.result") == "Clicked"
461    # Safari reports border-relative offsetX/offsetY.
462    assert await page.evaluate("offsetX") == 1900 + 8 if is_webkit else 1900
463    assert await page.evaluate("offsetY") == 1910 + 8 if is_webkit else 1910
464
465
466@pytest.mark.skip_browser("firefox")
467async def test_click_the_button_with_offset_with_page_scale(
468    browser, server, is_chromium, is_webkit
469):
470    context = await browser.new_context(
471        viewport={"width": 400, "height": 400}, is_mobile=True
472    )
473    page = await context.new_page()
474    await page.goto(server.PREFIX + "/input/button.html")
475    await page.eval_on_selector(
476        "button",
477        """button => {
478      button.style.borderWidth = '8px'
479      document.body.style.margin = '0'
480    }""",
481    )
482
483    await page.click("button", position={"x": 20, "y": 10})
484    assert await page.evaluate("result") == "Clicked"
485    expected = {"x": 28, "y": 18}
486    if is_webkit:
487        # WebKit rounds up during css -> dip -> css conversion.
488        expected = {"x": 29, "y": 19}
489    elif is_chromium:
490        # Chromium rounds down during css -> dip -> css conversion.
491        expected = {"x": 27, "y": 18}
492    assert await page.evaluate("pageX") == expected["x"]
493    assert await page.evaluate("pageY") == expected["y"]
494    await context.close()
495
496
497async def test_wait_for_stable_position(page, server):
498    await page.goto(server.PREFIX + "/input/button.html")
499    await page.eval_on_selector(
500        "button",
501        """button => {
502            button.style.transition = 'margin 500ms linear 0s';
503            button.style.marginLeft = '200px';
504            button.style.borderWidth = '0';
505            button.style.width = '200px';
506            button.style.height = '20px';
507            // Set display to "block" - otherwise Firefox layouts with non-even
508            // values on Linux.
509            button.style.display = 'block';
510            document.body.style.margin = '0';
511        }""",
512    )
513
514    await page.click("button")
515    assert await page.evaluate("window.result") == "Clicked"
516    assert await page.evaluate("pageX") == 300
517    assert await page.evaluate("pageY") == 10
518
519
520async def test_timeout_waiting_for_stable_position(page, server):
521    await page.goto(server.PREFIX + "/input/button.html")
522    button = await page.query_selector("button")
523    await button.evaluate(
524        """button => {
525            button.style.transition = 'margin 5s linear 0s'
526            button.style.marginLeft = '200px'
527        }"""
528    )
529
530    error = None
531    try:
532        await button.click(timeout=5000)
533    except Error as e:
534        error = e
535    assert "Timeout 5000ms exceeded." in error.message
536    assert "waiting for element to be visible, enabled and not moving" in error.message
537    assert "element is moving - waiting" in error.message
538
539
540async def test_wait_for_becoming_hit_target(page, server):
541    await page.goto(server.PREFIX + "/input/button.html")
542    await page.eval_on_selector(
543        "button",
544        """button => {
545            button.style.borderWidth = '0';
546            button.style.width = '200px';
547            button.style.height = '20px';
548            document.body.style.margin = '0';
549            document.body.style.position = 'relative';
550            flyOver = document.createElement('div');
551            flyOver.className = 'flyover';
552            flyOver.style.position = 'absolute';
553            flyOver.style.width = '400px';
554            flyOver.style.height = '20px';
555            flyOver.style.left = '-200px';
556            flyOver.style.top = '0';
557            flyOver.style.background = 'red';
558            document.body.appendChild(flyOver);
559        }""",
560    )
561
562    clicked = [False]
563
564    async def click():
565        await page.click("button")
566        clicked.append(True)
567
568    click_promise = asyncio.create_task(click())
569    assert clicked == [False]
570
571    await page.eval_on_selector(".flyover", "flyOver => flyOver.style.left = '0'")
572    await give_it_a_chance_to_click(page)
573    assert clicked == [False]
574
575    await page.eval_on_selector(".flyover", "flyOver => flyOver.style.left = '200px'")
576    await click_promise
577    assert clicked == [False, True]
578    assert await page.evaluate("() => window.result") == "Clicked"
579
580
581async def test_timeout_waiting_for_hit_target(page, server):
582    await page.goto(server.PREFIX + "/input/button.html")
583    button = await page.query_selector("button")
584    await page.evaluate(
585        """() => {
586      document.body.style.position = 'relative'
587      blocker = document.createElement('div')
588      blocker.id = 'blocker';
589      blocker.style.position = 'absolute'
590      blocker.style.width = '400px'
591      blocker.style.height = '20px'
592      blocker.style.left = '0'
593      blocker.style.top = '0'
594      document.body.appendChild(blocker)
595      }"""
596    )
597    error = None
598    try:
599        await button.click(timeout=5000)
600    except TimeoutError as e:
601        error = e
602    assert "Timeout 5000ms exceeded." in error.message
603    assert '<div id="blocker"></div> intercepts pointer events' in error.message
604    assert "retrying click action" in error.message
605
606
607async def test_fail_when_obscured_and_not_waiting_for_hit_target(page, server):
608    await page.goto(server.PREFIX + "/input/button.html")
609    button = await page.query_selector("button")
610    await page.evaluate(
611        """() => {
612            document.body.style.position = 'relative'
613            blocker = document.createElement('div')
614            blocker.style.position = 'absolute'
615            blocker.style.width = '400px'
616            blocker.style.height = '20px'
617            blocker.style.left = '0'
618            blocker.style.top = '0'
619            document.body.appendChild(blocker)
620        }"""
621    )
622
623    await button.click(force=True)
624    assert await page.evaluate("window.result") == "Was not clicked"
625
626
627async def test_wait_for_button_to_be_enabled(page, server):
628    await page.set_content(
629        '<button onclick="javascript:window.__CLICKED=true;" disabled><span>Click target</span></button>'
630    )
631    done = list()
632
633    async def click():
634        await page.click("text=Click target")
635        done.append(True)
636
637    click_promise = asyncio.create_task(click())
638    await give_it_a_chance_to_click(page)
639    assert await page.evaluate("() => window.__CLICKED") is None
640    assert done == []
641    await page.evaluate("document.querySelector('button').removeAttribute('disabled')")
642    await click_promise
643    assert await page.evaluate("window.__CLICKED")
644
645
646async def test_timeout_waiting_for_button_to_be_enabled(page, server):
647    await page.set_content(
648        '<button onclick="javascript:window.__CLICKED=true;" disabled><span>Click target</span></button>'
649    )
650    error = None
651    try:
652        await page.click("text=Click target", timeout=3000)
653    except TimeoutError as e:
654        error = e
655    assert await page.evaluate("window.__CLICKED") is None
656    assert "Timeout 3000ms exceeded" in error.message
657    assert "element is disabled - waiting" in error.message
658
659
660async def test_wait_for_input_to_be_enabled(page, server):
661    await page.set_content(
662        '<input onclick="javascript:window.__CLICKED=true;" disabled>'
663    )
664    done = []
665
666    async def click():
667        await page.click("input")
668        done.append(True)
669
670    click_promise = asyncio.create_task(click())
671    await give_it_a_chance_to_click(page)
672    assert await page.evaluate("window.__CLICKED") is None
673    assert done == []
674    await page.evaluate("document.querySelector('input').removeAttribute('disabled')")
675    await click_promise
676    assert await page.evaluate("window.__CLICKED")
677
678
679async def test_wait_for_select_to_be_enabled(page, server):
680    await page.set_content(
681        '<select onclick="javascript:window.__CLICKED=true;" disabled><option selected>Hello</option></select>'
682    )
683    done = []
684
685    async def click():
686        await page.click("select")
687        done.append(True)
688
689    click_promise = asyncio.create_task(click())
690    await give_it_a_chance_to_click(page)
691    assert await page.evaluate("window.__CLICKED") is None
692    assert done == []
693    await page.evaluate("document.querySelector('select').removeAttribute('disabled')")
694    await click_promise
695    assert await page.evaluate("window.__CLICKED")
696
697
698async def test_click_disabled_div(page, server):
699    await page.set_content(
700        '<div onclick="javascript:window.__CLICKED=true;" disabled>Click target</div>'
701    )
702    await page.click("text=Click target")
703    assert await page.evaluate("window.__CLICKED")
704
705
706async def test_climb_dom_for_inner_label_with_pointer_events_none(page, server):
707    await page.set_content(
708        '<button onclick="javascript:window.__CLICKED=true;"><label style="pointer-events:none">Click target</label></button>'
709    )
710    await page.click("text=Click target")
711    assert await page.evaluate("window.__CLICKED")
712
713
714async def test_climb_up_to_role_button(page, server):
715    await page.set_content(
716        '<div role=button onclick="javascript:window.__CLICKED=true;"><div style="pointer-events:none"><span><div>Click target</div></span></div>'
717    )
718    await page.click("text=Click target")
719    assert await page.evaluate("window.__CLICKED")
720
721
722async def test_wait_for_BUTTON_to_be_clickable_when_it_has_pointer_events_none(
723    page, server
724):
725    await page.set_content(
726        '<button onclick="javascript:window.__CLICKED=true;" style="pointer-events:none"><span>Click target</span></button>'
727    )
728    done = []
729
730    async def click():
731        await page.click("text=Click target")
732        done.append(True)
733
734    click_promise = asyncio.create_task(click())
735    await give_it_a_chance_to_click(page)
736    assert await page.evaluate("window.__CLICKED") is None
737    assert done == []
738    await page.evaluate(
739        "document.querySelector('button').style.removeProperty('pointer-events')"
740    )
741    await click_promise
742    assert await page.evaluate("window.__CLICKED")
743
744
745async def test_wait_for_LABEL_to_be_clickable_when_it_has_pointer_events_none(
746    page, server
747):
748    await page.set_content(
749        '<label onclick="javascript:window.__CLICKED=true;" style="pointer-events:none"><span>Click target</span></label>'
750    )
751    click_promise = asyncio.create_task(page.click("text=Click target"))
752    #  Do a few roundtrips to the page.
753    for _ in range(5):
754        assert await page.evaluate("window.__CLICKED") is None
755    #  remove 'pointer-events: none' css from button.
756    await page.evaluate(
757        "document.querySelector('label').style.removeProperty('pointer-events')"
758    )
759    await click_promise
760    assert await page.evaluate("window.__CLICKED")
761
762
763async def test_update_modifiers_correctly(page, server):
764    await page.goto(server.PREFIX + "/input/button.html")
765    await page.click("button", modifiers=["Shift"])
766    assert await page.evaluate("shiftKey")
767    await page.click("button", modifiers=[])
768    assert await page.evaluate("shiftKey") is False
769
770    await page.keyboard.down("Shift")
771    await page.click("button", modifiers=[])
772    assert await page.evaluate("shiftKey") is False
773    await page.click("button")
774    assert await page.evaluate("shiftKey")
775    await page.keyboard.up("Shift")
776    await page.click("button")
777    assert await page.evaluate("shiftKey") is False
778
779
780async def test_click_an_offscreen_element_when_scroll_behavior_is_smooth(page):
781    await page.set_content(
782        """
783        <div style="border: 1px solid black; height: 500px; overflow: auto; width: 500px; scroll-behavior: smooth">
784            <button style="margin-top: 2000px" onClick="window.clicked = true">hi</button>
785        </div>
786        """
787    )
788    await page.click("button")
789    assert await page.evaluate("window.clicked")
790
791
792async def test_report_nice_error_when_element_is_detached_and_force_clicked(
793    page, server
794):
795    await page.goto(server.PREFIX + "/input/animating-button.html")
796    await page.evaluate("addButton()")
797    handle = await page.query_selector("button")
798    await page.evaluate("stopButton(true)")
799    error = None
800    try:
801        await handle.click(force=True)
802    except Error as e:
803        error = e
804    assert await page.evaluate("window.clicked") is None
805    assert "Element is not attached to the DOM" in error.message
806
807
808async def test_fail_when_element_detaches_after_animation(page, server):
809    await page.goto(server.PREFIX + "/input/animating-button.html")
810    await page.evaluate("addButton()")
811    handle = await page.query_selector("button")
812    promise = asyncio.create_task(handle.click())
813    await asyncio.sleep(0)  # execute scheduled tasks, but don't await them
814    await page.evaluate("stopButton(true)")
815    with pytest.raises(Error) as exc_info:
816        await promise
817    assert await page.evaluate("window.clicked") is None
818    assert "Element is not attached to the DOM" in exc_info.value.message
819
820
821async def test_retry_when_element_detaches_after_animation(page, server):
822    await page.goto(server.PREFIX + "/input/animating-button.html")
823    await page.evaluate("addButton()")
824    clicked = []
825
826    async def click():
827        await page.click("button")
828        clicked.append(True)
829
830    promise = asyncio.create_task(click())
831    await asyncio.sleep(0)  # execute scheduled tasks, but don't await them
832    assert clicked == []
833    assert await page.evaluate("window.clicked") is None
834    await page.evaluate("stopButton(true)")
835    await page.evaluate("addButton()")
836    assert clicked == []
837    assert await page.evaluate("window.clicked") is None
838    await page.evaluate("stopButton(true)")
839    await page.evaluate("addButton()")
840    assert clicked == []
841    assert await page.evaluate("window.clicked") is None
842    await page.evaluate("stopButton(false)")
843    await promise
844    assert clicked == [True]
845    assert await page.evaluate("window.clicked")
846
847
848async def test_retry_when_element_is_animating_from_outside_the_viewport(page, server):
849    await page.set_content(
850        """<style>
851        @keyframes move {
852            from { left: -300px; }
853            to { left: 0; }
854        }
855        button {
856            position: absolute
857            left: -300px
858            top: 0
859            bottom: 0
860            width: 200px
861        }
862        button.animated {
863            animation: 1s linear 1s move forwards
864        }
865        </style>
866        <div style="position: relative; width: 300px; height: 300px;">
867            <button onclick="window.clicked=true"></button>
868        </div>
869        """
870    )
871    handle = await page.query_selector("button")
872    promise = asyncio.create_task(handle.click())
873    await asyncio.sleep(0)  # execute scheduled tasks, but don't await them
874    await handle.evaluate("button => button.className = 'animated'")
875    await promise
876    assert await page.evaluate("window.clicked")
877
878
879async def test_fail_when_element_is_animating_from_outside_the_viewport_with_force(
880    page, server
881):
882    await page.set_content(
883        """<style>
884        @keyframes move {
885            from { left: -300px; }
886            to { left: 0; }
887        }
888        button {
889            position: absolute;
890            left: -300px;
891            top: 0;
892            bottom: 0
893            width: 200px;
894        }
895        button.animated {
896            animation: 1s linear 1s move forwards;
897        }
898        </style>
899        <div style="position: relative; width: 300px; height: 300px;">
900            <button onclick="window.clicked=true"></button>
901        </div>
902        """
903    )
904    handle = await page.query_selector("button")
905    promise = asyncio.create_task(handle.click(force=True))
906    await asyncio.sleep(0)  # execute scheduled tasks, but don't await them
907    await handle.evaluate("button => button.className = 'animated'")
908    error = None
909    try:
910        await promise
911    except Error as e:
912        error = e
913    assert await page.evaluate("window.clicked") is None
914    assert "Element is outside of the viewport" in error.message
915
916
917async def test_not_retarget_when_element_changes_on_hover(page, server):
918    await page.goto(server.PREFIX + "/react.html")
919    await page.evaluate(
920        """() => {
921          renderComponent(e('div', {}, [e(MyButton, { name: 'button1', renameOnHover: true }), e(MyButton, { name: 'button2' })] ));
922        }"""
923    )
924    await page.click("text=button1")
925    assert await page.evaluate("window.button1")
926    assert await page.evaluate("window.button2") is None
927
928
929async def test_not_retarget_when_element_is_recycled_on_hover(page, server):
930    await page.goto(server.PREFIX + "/react.html")
931    await page.evaluate(
932        """() => {
933            function shuffle() {
934                renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })] ));
935            }
936            renderComponent(e('div', {}, [e(MyButton, { name: 'button1', onHover: shuffle }), e(MyButton, { name: 'button2' })] ));
937        }"""
938    )
939
940    await page.click("text=button1")
941    assert await page.evaluate("window.button1") is None
942    assert await page.evaluate("window.button2")
943
944
945async def test_click_the_button_when_window_inner_width_is_corrupted(page, server):
946    await page.goto(server.PREFIX + "/input/button.html")
947    await page.evaluate("window.innerWidth = 0")
948    await page.click("button")
949    assert await page.evaluate("result") == "Clicked"
950
951
952async def test_timeout_when_click_opens_alert(page, server):
953    await page.set_content('<div onclick="window.alert(123)">Click me</div>')
954    async with page.expect_event("dialog") as dialog_info:
955        with pytest.raises(Error) as exc_info:
956            await page.click("div", timeout=3000)
957        assert "Timeout 3000ms exceeded" in exc_info.value.message
958    dialog = await dialog_info.value
959    await dialog.dismiss()
960
961
962async def test_check_the_box(page):
963    await page.set_content('<input id="checkbox" type="checkbox"></input>')
964    await page.check("input")
965    assert await page.evaluate("checkbox.checked")
966
967
968async def test_not_check_the_checked_box(page):
969    await page.set_content('<input id="checkbox" type="checkbox" checked></input>')
970    await page.check("input")
971    assert await page.evaluate("checkbox.checked")
972
973
974async def test_uncheck_the_box(page):
975    await page.set_content('<input id="checkbox" type="checkbox" checked></input>')
976    await page.uncheck("input")
977    assert await page.evaluate("checkbox.checked") is False
978
979
980async def test_not_uncheck_the_unchecked_box(page):
981    await page.set_content('<input id="checkbox" type="checkbox"></input>')
982    await page.uncheck("input")
983    assert await page.evaluate("checkbox.checked") is False
984
985
986async def test_check_the_box_by_label(page):
987    await page.set_content(
988        '<label for="checkbox"><input id="checkbox" type="checkbox"></input></label>'
989    )
990    await page.check("label")
991    assert await page.evaluate("checkbox.checked")
992
993
994async def test_check_the_box_outside_label(page):
995    await page.set_content(
996        '<label for="checkbox">Text</label><div><input id="checkbox" type="checkbox"></input></div>'
997    )
998    await page.check("label")
999    assert await page.evaluate("checkbox.checked")
1000
1001
1002async def test_check_the_box_inside_label_without_id(page):
1003    await page.set_content(
1004        '<label>Text<span><input id="checkbox" type="checkbox"></input></span></label>'
1005    )
1006    await page.check("label")
1007    assert await page.evaluate("checkbox.checked")
1008
1009
1010async def test_check_radio(page):
1011    await page.set_content(
1012        """
1013        <input type='radio'>one</input>
1014        <input id='two' type='radio'>two</input>
1015        <input type='radio'>three</input>"""
1016    )
1017    await page.check("#two")
1018    assert await page.evaluate("two.checked")
1019
1020
1021async def test_check_the_box_by_aria_role(page):
1022    await page.set_content(
1023        """<div role='checkbox' id='checkbox'>CHECKBOX</div>
1024        <script>
1025            checkbox.addEventListener('click', () => checkbox.setAttribute('aria-checked', 'true'))
1026        </script>"""
1027    )
1028    await page.check("div")
1029    assert await page.evaluate("checkbox.getAttribute ('aria-checked')")
1030
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)