How to use test_locators_wait_for 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_locators.py

Source: test_locators.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 os
16import re
17from urllib.parse import urlparse
18
19import pytest
20
21from playwright._impl._path_utils import get_file_dirname
22from playwright.async_api import Error, Page, expect
23from tests.server import Server
24
25_dirname = get_file_dirname()
26FILE_TO_UPLOAD = _dirname / ".." / "assets/file-to-upload.txt"
27
28
29async def test_locators_click_should_work(page: Page, server: Server):
30    await page.goto(server.PREFIX + "/input/button.html")
31    button = page.locator("button")
32    await button.click()
33    assert await page.evaluate("window['result']") == "Clicked"
34
35
36async def test_locators_click_should_work_with_node_removed(page: Page, server: Server):
37    await page.goto(server.PREFIX + "/input/button.html")
38    await page.evaluate("delete window['Node']")
39    button = page.locator("button")
40    await button.click()
41    assert await page.evaluate("window['result']") == "Clicked"
42
43
44async def test_locators_click_should_work_for_text_nodes(page: Page, server: Server):
45    await page.goto(server.PREFIX + "/input/button.html")
46    await page.evaluate(
47        """() => {
48        window['double'] = false;
49        const button = document.querySelector('button');
50        button.addEventListener('dblclick', event => {
51        window['double'] = true;
52        });
53    }"""
54    )
55    button = page.locator("button")
56    await button.dblclick()
57    assert await page.evaluate("double") is True
58    assert await page.evaluate("result") == "Clicked"
59
60
61async def test_locators_should_have_repr(page: Page, server: Server):
62    await page.goto(server.PREFIX + "/input/button.html")
63    button = page.locator("button")
64    await button.click()
65    assert (
66        str(button)
67        == f"<Locator frame=<Frame name= url='{server.PREFIX}/input/button.html'> selector='button'>"
68    )
69
70
71async def test_locators_get_attribute_should_work(page: Page, server: Server):
72    await page.goto(server.PREFIX + "/dom.html")
73    button = page.locator("#outer")
74    assert await button.get_attribute("name") == "value"
75    assert await button.get_attribute("foo") is None
76
77
78async def test_locators_input_value_should_work(page: Page, server: Server):
79    await page.goto(server.PREFIX + "/dom.html")
80    await page.fill("#textarea", "input value")
81    text_area = page.locator("#textarea")
82    assert await text_area.input_value() == "input value"
83
84
85async def test_locators_inner_html_should_work(page: Page, server: Server):
86    await page.goto(server.PREFIX + "/dom.html")
87    locator = page.locator("#outer")
88    assert await locator.inner_html() == '<div id="inner">Text,\nmore text</div>'
89
90
91async def test_locators_inner_text_should_work(page: Page, server: Server):
92    await page.goto(server.PREFIX + "/dom.html")
93    locator = page.locator("#inner")
94    assert await locator.inner_text() == "Text, more text"
95
96
97async def test_locators_text_content_should_work(page: Page, server: Server):
98    await page.goto(server.PREFIX + "/dom.html")
99    locator = page.locator("#inner")
100    assert await locator.text_content() == "Text,\nmore text"
101
102
103async def test_locators_is_hidden_and_is_visible_should_work(page: Page):
104    await page.set_content("<div>Hi</div><span></span>")
105
106    div = page.locator("div")
107    assert await div.is_visible() is True
108    assert await div.is_hidden() is False
109
110    span = page.locator("span")
111    assert await span.is_visible() is False
112    assert await span.is_hidden() is True
113
114
115async def test_locators_is_enabled_and_is_disabled_should_work(page: Page):
116    await page.set_content(
117        """
118        <button disabled>button1</button>
119        <button>button2</button>
120        <div>div</div>
121    """
122    )
123
124    div = page.locator("div")
125    assert await div.is_enabled() is True
126    assert await div.is_disabled() is False
127
128    button1 = page.locator(':text("button1")')
129    assert await button1.is_enabled() is False
130    assert await button1.is_disabled() is True
131
132    button1 = page.locator(':text("button2")')
133    assert await button1.is_enabled() is True
134    assert await button1.is_disabled() is False
135
136
137async def test_locators_is_editable_should_work(page: Page):
138    await page.set_content(
139        """
140        <input id=input1 disabled><textarea></textarea><input id=input2>
141    """
142    )
143
144    input1 = page.locator("#input1")
145    assert await input1.is_editable() is False
146
147    input2 = page.locator("#input2")
148    assert await input2.is_editable() is True
149
150
151async def test_locators_is_checked_should_work(page: Page):
152    await page.set_content(
153        """
154        <input type='checkbox' checked><div>Not a checkbox</div>
155    """
156    )
157
158    element = page.locator("input")
159    assert await element.is_checked() is True
160    await element.evaluate("e => e.checked = false")
161    assert await element.is_checked() is False
162
163
164async def test_locators_all_text_contents_should_work(page: Page):
165    await page.set_content(
166        """
167        <div>A</div><div>B</div><div>C</div>
168    """
169    )
170
171    element = page.locator("div")
172    assert await element.all_text_contents() == ["A", "B", "C"]
173
174
175async def test_locators_all_inner_texts(page: Page):
176    await page.set_content(
177        """
178        <div>A</div><div>B</div><div>C</div>
179    """
180    )
181
182    element = page.locator("div")
183    assert await element.all_inner_texts() == ["A", "B", "C"]
184
185
186async def test_locators_should_query_existing_element(page: Page, server: Server):
187    await page.goto(server.PREFIX + "/playground.html")
188    await page.set_content(
189        """<html><body><div class="second"><div class="inner">A</div></div></body></html>"""
190    )
191    html = page.locator("html")
192    second = html.locator(".second")
193    inner = second.locator(".inner")
194    assert (
195        await page.evaluate("e => e.textContent", await inner.element_handle()) == "A"
196    )
197
198
199async def test_locators_evaluate_handle_should_work(page: Page, server: Server):
200    await page.goto(server.PREFIX + "/dom.html")
201    outer = page.locator("#outer")
202    inner = outer.locator("#inner")
203    check = inner.locator("#check")
204    text = await inner.evaluate_handle("e => e.firstChild")
205    await page.evaluate("1 + 1")
206    assert (
207        str(outer)
208        == f"<Locator frame=<Frame name= url='{server.PREFIX}/dom.html'> selector='#outer'>"
209    )
210    assert (
211        str(inner)
212        == f"<Locator frame=<Frame name= url='{server.PREFIX}/dom.html'> selector='#outer >> #inner'>"
213    )
214    assert str(text) == "[email protected]#text=Text,↵more text"
215    assert (
216        str(check)
217        == f"<Locator frame=<Frame name= url='{server.PREFIX}/dom.html'> selector='#outer >> #inner >> #check'>"
218    )
219
220
221async def test_locators_should_query_existing_elements(page: Page):
222    await page.set_content(
223        """<html><body><div>A</div><br/><div>B</div></body></html>"""
224    )
225    html = page.locator("html")
226    elements = await html.locator("div").element_handles()
227    assert len(elements) == 2
228    result = []
229    for element in elements:
230        result.append(await page.evaluate("e => e.textContent", element))
231    assert result == ["A", "B"]
232
233
234async def test_locators_return_empty_array_for_non_existing_elements(page: Page):
235    await page.set_content(
236        """<html><body><div>A</div><br/><div>B</div></body></html>"""
237    )
238    html = page.locator("html")
239    elements = await html.locator("abc").element_handles()
240    assert len(elements) == 0
241    assert elements == []
242
243
244async def test_locators_evaluate_all_should_work(page: Page):
245    await page.set_content(
246        """<html><body><div class="tweet"><div class="like">100</div><div class="like">10</div></div></body></html>"""
247    )
248    tweet = page.locator(".tweet .like")
249    content = await tweet.evaluate_all("nodes => nodes.map(n => n.innerText)")
250    assert content == ["100", "10"]
251
252
253async def test_locators_evaluate_all_should_work_with_missing_selector(page: Page):
254    await page.set_content(
255        """<div class="a">not-a-child-div</div><div id="myId"></div"""
256    )
257    tweet = page.locator("#myId .a")
258    nodes_length = await tweet.evaluate_all("nodes => nodes.length")
259    assert nodes_length == 0
260
261
262async def test_locators_hover_should_work(page: Page, server: Server):
263    await page.goto(server.PREFIX + "/input/scrollable.html")
264    button = page.locator("#button-6")
265    await button.hover()
266    assert (
267        await page.evaluate("document.querySelector('button:hover').id") == "button-6"
268    )
269
270
271async def test_locators_fill_should_work(page: Page, server: Server):
272    await page.goto(server.PREFIX + "/input/textarea.html")
273    button = page.locator("input")
274    await button.fill("some value")
275    assert await page.evaluate("result") == "some value"
276
277
278async def test_locators_check_should_work(page: Page):
279    await page.set_content("<input id='checkbox' type='checkbox'></input>")
280    button = page.locator("input")
281    await button.check()
282    assert await page.evaluate("checkbox.checked") is True
283
284
285async def test_locators_uncheck_should_work(page: Page):
286    await page.set_content("<input id='checkbox' type='checkbox' checked></input>")
287    button = page.locator("input")
288    await button.uncheck()
289    assert await page.evaluate("checkbox.checked") is False
290
291
292async def test_locators_select_option_should_work(page: Page, server: Server):
293    await page.goto(server.PREFIX + "/input/select.html")
294    select = page.locator("select")
295    await select.select_option("blue")
296    assert await page.evaluate("result.onInput") == ["blue"]
297    assert await page.evaluate("result.onChange") == ["blue"]
298
299
300async def test_locators_focus_should_work(page: Page, server: Server):
301    await page.goto(server.PREFIX + "/input/button.html")
302    button = page.locator("button")
303    assert await button.evaluate("button => document.activeElement === button") is False
304    await button.focus()
305    assert await button.evaluate("button => document.activeElement === button") is True
306
307
308async def test_locators_dispatch_event_should_work(page: Page, server: Server):
309    await page.goto(server.PREFIX + "/input/button.html")
310    button = page.locator("button")
311    await button.dispatch_event("click")
312    assert await page.evaluate("result") == "Clicked"
313
314
315async def test_locators_should_upload_a_file(page: Page, server: Server):
316    await page.goto(server.PREFIX + "/input/fileupload.html")
317    input = page.locator("input[type=file]")
318
319    file_path = os.path.relpath(FILE_TO_UPLOAD, os.getcwd())
320    await input.set_input_files(file_path)
321    assert (
322        await page.evaluate("e => e.files[0].name", await input.element_handle())
323        == "file-to-upload.txt"
324    )
325
326
327async def test_locators_should_press(page: Page):
328    await page.set_content("<input type='text' />")
329    await page.locator("input").press("h")
330    await page.eval_on_selector("input", "input => input.value") == "h"
331
332
333async def test_locators_should_scroll_into_view(page: Page, server: Server):
334    await page.goto(server.PREFIX + "/offscreenbuttons.html")
335    for i in range(11):
336        button = page.locator(f"#btn{i}")
337        before = await button.evaluate(
338            "button => button.getBoundingClientRect().right - window.innerWidth"
339        )
340        assert before == 10 * i
341        await button.scroll_into_view_if_needed()
342        after = await button.evaluate(
343            "button => button.getBoundingClientRect().right - window.innerWidth"
344        )
345        assert after <= 0
346        await page.evaluate("window.scrollTo(0, 0)")
347
348
349async def test_locators_should_select_textarea(
350    page: Page, server: Server, browser_name: str
351):
352    await page.goto(server.PREFIX + "/input/textarea.html")
353    textarea = page.locator("textarea")
354    await textarea.evaluate("textarea => textarea.value = 'some value'")
355    await textarea.select_text()
356    if browser_name == "firefox":
357        assert await textarea.evaluate("el => el.selectionStart") == 0
358        assert await textarea.evaluate("el => el.selectionEnd") == 10
359    else:
360        assert await page.evaluate("window.getSelection().toString()") == "some value"
361
362
363async def test_locators_should_type(page: Page):
364    await page.set_content("<input type='text' />")
365    await page.locator("input").type("hello")
366    await page.eval_on_selector("input", "input => input.value") == "hello"
367
368
369async def test_locators_should_screenshot(
370    page: Page, server: Server, assert_to_be_golden
371):
372    await page.set_viewport_size(
373        {
374            "width": 500,
375            "height": 500,
376        }
377    )
378    await page.goto(server.PREFIX + "/grid.html")
379    await page.evaluate("window.scrollBy(50, 100)")
380    element = page.locator(".box:nth-of-type(3)")
381    assert_to_be_golden(
382        await element.screenshot(), "screenshot-element-bounding-box.png"
383    )
384
385
386async def test_locators_should_return_bounding_box(page: Page, server: Server):
387    await page.set_viewport_size(
388        {
389            "width": 500,
390            "height": 500,
391        }
392    )
393    await page.goto(server.PREFIX + "/grid.html")
394    element = page.locator(".box:nth-of-type(13)")
395    box = await element.bounding_box()
396    assert box == {
397        "x": 100,
398        "y": 50,
399        "width": 50,
400        "height": 50,
401    }
402
403
404async def test_locators_should_respect_first_and_last(page: Page):
405    await page.set_content(
406        """
407        <section>
408            <div><p>A</p></div>
409            <div><p>A</p><p>A</p></div>
410            <div><p>A</p><p>A</p><p>A</p></div>
411        </section>"""
412    )
413    assert await page.locator("div >> p").count() == 6
414    assert await page.locator("div").locator("p").count() == 6
415    assert await page.locator("div").first.locator("p").count() == 1
416    assert await page.locator("div").last.locator("p").count() == 3
417
418
419async def test_locators_should_respect_nth(page: Page):
420    await page.set_content(
421        """
422    <section>
423        <div><p>A</p></div>
424        <div><p>A</p><p>A</p></div>
425        <div><p>A</p><p>A</p><p>A</p></div>
426    </section>"""
427    )
428    assert await page.locator("div >> p").nth(0).count() == 1
429    assert await page.locator("div").nth(1).locator("p").count() == 2
430    assert await page.locator("div").nth(2).locator("p").count() == 3
431
432
433async def test_locators_should_throw_on_capture_without_nth(page: Page):
434    await page.set_content(
435        """
436        <section><div><p>A</p></div></section>
437    """
438    )
439    with pytest.raises(Error, match="Can't query n-th element"):
440        await page.locator("*css=div >> p").nth(1).click()
441
442
443async def test_locators_should_throw_due_to_strictness(page: Page):
444    await page.set_content(
445        """
446        <div>A</div><div>B</div>
447    """
448    )
449    with pytest.raises(Error, match="strict mode violation"):
450        await page.locator("div").is_visible()
451
452
453async def test_locators_should_throw_due_to_strictness_2(page: Page):
454    await page.set_content(
455        """
456        <select><option>One</option><option>Two</option></select>
457    """
458    )
459    with pytest.raises(Error, match="strict mode violation"):
460        await page.locator("option").evaluate("e => {}")
461
462
463async def test_locators_set_checked(page: Page):
464    await page.set_content("`<input id='checkbox' type='checkbox'></input>`")
465    locator = page.locator("input")
466    await locator.set_checked(True)
467    assert await page.evaluate("checkbox.checked")
468    await locator.set_checked(False)
469    assert await page.evaluate("checkbox.checked") is False
470
471
472async def test_locators_wait_for(page: Page) -> None:
473    await page.set_content("<div></div>")
474    locator = page.locator("div")
475    task = locator.wait_for()
476    await page.eval_on_selector("div", "div => div.innerHTML = '<span>target</span>'")
477    await task
478    assert await locator.text_content() == "target"
479
480
481async def route_iframe(page: Page) -> None:
482    await page.route(
483        "**/empty.html",
484        lambda route: route.fulfill(
485            body='<iframe src="iframe.html"></iframe>', content_type="text/html"
486        ),
487    )
488    await page.route(
489        "**/iframe.html",
490        lambda route: route.fulfill(
491            body="""<html>
492          <div>
493            <button>Hello iframe</button>
494            <iframe src="iframe-2.html"></iframe>
495          </div>
496          <span>1</span>
497          <span>2</span>
498        </html>""",
499            content_type="text/html",
500        ),
501    )
502    await page.route(
503        "**/iframe-2.html",
504        lambda route: route.fulfill(
505            body="<html><button>Hello nested iframe</button></html>",
506            content_type="text/html",
507        ),
508    )
509
510
511async def test_locators_frame_should_work_with_iframe(
512    page: Page, server: Server
513) -> None:
514    await route_iframe(page)
515    await page.goto(server.EMPTY_PAGE)
516    button = page.frame_locator("iframe").locator("button")
517    await button.wait_for()
518    assert await button.inner_text() == "Hello iframe"
519    await button.click()
520
521
522async def test_locators_frame_should_work_for_nested_iframe(
523    page: Page, server: Server
524) -> None:
525    await route_iframe(page)
526    await page.goto(server.EMPTY_PAGE)
527    button = page.frame_locator("iframe").frame_locator("iframe").locator("button")
528    await button.wait_for()
529    assert await button.inner_text() == "Hello nested iframe"
530    await button.click()
531
532
533async def test_locators_frame_should_work_with_locator_frame_locator(
534    page: Page, server: Server
535) -> None:
536    await route_iframe(page)
537    await page.goto(server.EMPTY_PAGE)
538    button = page.locator("body").frame_locator("iframe").locator("button")
539    await button.wait_for()
540    assert await button.inner_text() == "Hello iframe"
541    await button.click()
542
543
544async def route_ambiguous(page: Page) -> None:
545    await page.route(
546        "**/empty.html",
547        lambda route: route.fulfill(
548            body="""
549        <iframe src="iframe-1.html"></iframe>
550        <iframe src="iframe-2.html"></iframe>
551        <iframe src="iframe-3.html"></iframe>
552    """,
553            content_type="text/html",
554        ),
555    )
556    await page.route(
557        "**/iframe-*",
558        lambda route: route.fulfill(
559            body=f"<html><button>Hello from {urlparse(route.request.url).path[1:]}</button></html>",
560            content_type="text/html",
561        ),
562    )
563
564
565async def test_locator_frame_locator_should_throw_on_ambiguity(
566    page: Page, server: Server
567) -> None:
568    await route_ambiguous(page)
569    await page.goto(server.EMPTY_PAGE)
570    button = page.locator("body").frame_locator("iframe").locator("button")
571    with pytest.raises(
572        Error,
573        match='.*strict mode violation: "body >> iframe" resolved to 3 elements.*',
574    ):
575        await button.wait_for()
576
577
578async def test_locator_frame_locator_should_not_throw_on_first_last_nth(
579    page: Page, server: Server
580) -> None:
581    await route_ambiguous(page)
582    await page.goto(server.EMPTY_PAGE)
583    button1 = page.locator("body").frame_locator("iframe").first.locator("button")
584    assert await button1.text_content() == "Hello from iframe-1.html"
585    button2 = page.locator("body").frame_locator("iframe").nth(1).locator("button")
586    assert await button2.text_content() == "Hello from iframe-2.html"
587    button3 = page.locator("body").frame_locator("iframe").last.locator("button")
588    assert await button3.text_content() == "Hello from iframe-3.html"
589
590
591async def test_drag_to(page: Page, server: Server) -> None:
592    await page.goto(server.PREFIX + "/drag-n-drop.html")
593    await page.locator("#source").drag_to(page.locator("#target"))
594    assert (
595        await page.eval_on_selector(
596            "#target", "target => target.contains(document.querySelector('#source'))"
597        )
598        is True
599    )
600
601
602async def test_drag_to_with_position(page: Page, server: Server):
603    await page.goto(server.EMPTY_PAGE)
604    await page.set_content(
605        """
606      <div style="width:100px;height:100px;background:red;" id="red">
607      </div>
608      <div style="width:100px;height:100px;background:blue;" id="blue">
609      </div>
610    """
611    )
612    events_handle = await page.evaluate_handle(
613        """
614        () => {
615        const events = [];
616        document.getElementById('red').addEventListener('mousedown', event => {
617            events.push({
618            type: 'mousedown',
619            x: event.offsetX,
620            y: event.offsetY,
621            });
622        });
623        document.getElementById('blue').addEventListener('mouseup', event => {
624            events.push({
625            type: 'mouseup',
626            x: event.offsetX,
627            y: event.offsetY,
628            });
629        });
630        return events;
631        }
632    """
633    )
634    await page.locator("#red").drag_to(
635        page.locator("#blue"),
636        source_position={"x": 34, "y": 7},
637        target_position={"x": 10, "y": 20},
638    )
639    assert await events_handle.json_value() == [
640        {"type": "mousedown", "x": 34, "y": 7},
641        {"type": "mouseup", "x": 10, "y": 20},
642    ]
643
644
645async def test_locator_query_should_filter_by_text(page: Page, server: Server) -> None:
646    await page.set_content("<div>Foobar</div><div>Bar</div>")
647    await expect(page.locator("div", has_text="Foo")).to_have_text("Foobar")
648
649
650async def test_locator_query_should_filter_by_text_2(
651    page: Page, server: Server
652) -> None:
653    await page.set_content("<div>foo <span>hello world</span> bar</div>")
654    await expect(page.locator("div", has_text="hello world")).to_have_text(
655        "foo hello world bar"
656    )
657
658
659async def test_locator_query_should_filter_by_regex(page: Page, server: Server) -> None:
660    await page.set_content("<div>Foobar</div><div>Bar</div>")
661    await expect(page.locator("div", has_text=re.compile(r"Foo.*"))).to_have_text(
662        "Foobar"
663    )
664
665
666async def test_locator_query_should_filter_by_text_with_quotes(
667    page: Page, server: Server
668) -> None:
669    await page.set_content('<div>Hello "world"</div><div>Hello world</div>')
670    await expect(page.locator("div", has_text='Hello "world"')).to_have_text(
671        'Hello "world"'
672    )
673
674
675async def test_locator_query_should_filter_by_regex_with_quotes(
676    page: Page, server: Server
677) -> None:
678    await page.set_content('<div>Hello "world"</div><div>Hello world</div>')
679    await expect(
680        page.locator("div", has_text=re.compile('Hello "world"'))
681    ).to_have_text('Hello "world"')
682
683
684async def test_locator_query_should_filter_by_regex_and_regexp_flags(
685    page: Page, server: Server
686) -> None:
687    await page.set_content('<div>Hello "world"</div><div>Hello world</div>')
688    await expect(
689        page.locator("div", has_text=re.compile('hElLo "world', re.IGNORECASE))
690    ).to_have_text('Hello "world"')
691
692
693async def test_locator_should_return_page(page: Page, server: Server) -> None:
694    await page.goto(server.PREFIX + "/frames/two-frames.html")
695    outer = page.locator("#outer")
696    assert outer.page == page
697
698    inner = outer.locator("#inner")
699    assert inner.page == page
700
701    in_frame = page.frames[1].locator("div")
702    assert in_frame.page == page
703
704
705async def test_locator_should_support_has_locator(page: Page, server: Server) -> None:
706    await page.set_content("<div><span>hello</span></div><div><span>world</span></div>")
707    await expect(page.locator("div", has=page.locator("text=world"))).to_have_count(1)
708    assert (
709        await page.locator("div", has=page.locator("text=world")).evaluate(
710            "e => e.outerHTML"
711        )
712        == "<div><span>world</span></div>"
713    )
714    await expect(page.locator("div", has=page.locator('text="hello"'))).to_have_count(1)
715    assert (
716        await page.locator("div", has=page.locator('text="hello"')).evaluate(
717            "e => e.outerHTML"
718        )
719        == "<div><span>hello</span></div>"
720    )
721    await expect(page.locator("div", has=page.locator("xpath=./span"))).to_have_count(2)
722    await expect(page.locator("div", has=page.locator("span"))).to_have_count(2)
723    await expect(
724        page.locator("div", has=page.locator("span", has_text="wor"))
725    ).to_have_count(1)
726    assert (
727        await page.locator("div", has=page.locator("span", has_text="wor")).evaluate(
728            "e => e.outerHTML"
729        )
730        == "<div><span>world</span></div>"
731    )
732    await expect(
733        page.locator(
734            "div",
735            has=page.locator("span"),
736            has_text="wor",
737        )
738    ).to_have_count(1)
739
740
741async def test_locator_should_enforce_same_frame_for_has_locator(
742    page: Page, server: Server
743) -> None:
744    await page.goto(server.PREFIX + "/frames/two-frames.html")
745    child = page.frames[1]
746    with pytest.raises(Error) as exc_info:
747        page.locator("div", has=child.locator("span"))
748    assert (
749        'Inner "has" locator must belong to the same frame.' in exc_info.value.message
750    )
751
752
753async def test_locator_highlight_should_work(page: Page, server: Server) -> None:
754    await page.goto(server.PREFIX + "/grid.html")
755    await page.locator(".box").nth(3).highlight()
756    assert await page.locator("x-pw-glass").is_visible()
757
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)