【Playwright+Python】系列教程(五)元素定位

时间:2024-07-10 07:21:44
包含文本“This is inside the Shadow DOM.”,示例代码如下:

page.goto("http://localhost:8080/shadowDOM.html")
expect(page.get_by_text("This is inside the Shadow DOM.")).to_contain_text("Shadow DOM")
expect(page.locator("div", has_text="This is inside the Shadow DOM.")).to_contain_text("This is inside")

三、筛选定位

1、dom结构

image.png

2、按文本筛选定位

可以使用 locator.filter() 方法按文本过滤定位器。它将在不区分大小写的情况下搜索元素内部的某个特定字符串,可能在后代元素中。
示例代码:

page.get_by_role("listitem").filter(has_text="Product 2").get_by_role(
    "button", name="Add to cart"
).click()

#传递正则表达式。
page.get_by_role("listitem").filter(has_text=re.compile("Product 2")).get_by_role(
    "button", name="Add to cart"
).click()

2.1、按没有文本进行筛选

expect(page.get_by_role("listitem").filter(has_not_text="Out of stock")).to_have_count(2)

2.2、按子项/后代筛选

定位器支持仅选择具有或没有与另一个定位器匹配的后代的元素的选项。因此,您可以按任何其他定位器进行过滤,例如 locator.get_by_role()、locator.get_by_test_id()、locator.get_by_text() 等。
示例代码:

page.get_by_role("listitem").filter(
    has=page.get_by_role("heading", name="Product 2")
).get_by_role("button", name="Add to cart").click()

断言产品卡,确保只有一个,示例代码如下:

expect(
    page.get_by_role("listitem").filter(
        has=page.get_by_role("heading", name="Product 2")
    )
).to_have_count(1)

过滤定位器必须相对于原始定位器,并且从原始定位器匹配项(而不是文档根节点)开始查询。

2.3、按没有子/后代进行筛选

通过内部没有匹配的元素进行过滤,示例代码:

expect(
    page.get_by_role("listitem").filter(
        has_not=page.get_by_role("heading", name="Product 2")
    )
).to_have_count(1)

注意,内部定位器是从外部定位器开始匹配的,而不是从文档根目节点开始匹配的。

四、使用约束条件定位

1、在定位器内匹配

就先定位元素,再去定位子节点元素,以将搜索范围缩小到页面的特定部分。
示例代码

product = page.get_by_role("listitem").filter(has_text="Product 2")
product.get_by_role("button", name="Add to cart").click()

也可以将两个元素定位组合在一起使用,示例代码如下:

save_button = page.get_by_role("button", name="Save")
# ...
dialog = page.get_by_test_id("settings-dialog")
dialog.locator(save_button).click()

2、使用and条件匹配

方法 locator.and_() 通过匹配其他定位器来缩小现有定位器的范围,可以理解为xpath的and使用方法,都是定位一个元素,示例代码如下:

page.get_by_role("link").and_(page.get_by_text("新闻")).click()

3、使用or条件匹配

如果您想定位两个或多个元素中的一个,但不知道会是哪一个,请使用 locator.or_() 创建与所有备选项匹配的定位器。示例代码如下:

def test_navigationCnblogs(page: Page):
    page.goto("https://www.baidu.com/")
    login=page.get_by_role("link").and_(page.get_by_text("登录"))
    message=page.get_by_text("短信登录")
    expect(message.or_(login).first).to_be_visible()
    if (login.is_visible()):
        login.click()
    message.click()

4、仅匹配可见元素

考虑一个有两个按钮的页面,第一个不可见,第二个可见,这时候就可以进行约束,示例代码如下:

page.locator("button").locator("visible=true").click()

五、列表元素操作

dom结构:
image.png

1、使用 count 断言

使用 count 断言确保列表有 3 个项目,示例代码如下:

expect(page.get_by_role("listitem")).to_have_count(3)

2、断言列表中的所有文本

断言定位器以查找列表中的所有文本,示例代码如下:

expect(page.get_by_role("listitem")).to_have_text(["apple", "banana", "orange"])

3、定位某个列表元素

使用 page.get_by_text() 方法按文本内容在列表中查找元素,示例代码如下:

page.get_by_text("orange").click()

也可以使用 locator.filter() 查找列表中的特定元素,示例代码如下:

page.get_by_role("listitem").filter(has_text="orange").click()

4、按下标定位指定元素

您有一个相同元素的列表,并且区分它们的唯一方法是顺序,则可以使用 locator.firstlocator.lastlocator.nth() 从列表中选择特定元素。

    banana = page.get_by_role("listitem").nth(1)
    expect(banana).to_have_text('banana')

5、链接筛选器定位元素

当您有具有各种相似性的元素时,使用 locator.filter() 方法选择正确的元素。还可以链接多个筛选器以缩小选择范,就是层级定位,个人感觉。
DOM 结构
image.png
示例代码

row_locator = page.get_by_role("listitem")

row_locator.filter(has_text="Mary").filter(
    has=page.get_by_role("button", name="Say goodbye")
).screenshot(path="screenshot.png")

6、遍历每个元素

对列表中的每个元素执行操作,示例代码如下:

for row in page.get_by_role("listitem").all():
    print(row.text_content())

rows = page.get_by_role("listitem")
count = rows.count()
for i in range(count):
    print(rows.nth(i).text_content())

7、Evaluate in the page在页面中评估

我觉得这个就是很ES6呀,示例代码如下:

rows = page.get_by_role("listitem")
# 很前端了吧
texts = rows.evaluate_all("list => list.map(element => element.textContent)")

8、检查定位元素的个数

定位元素如果出现定位多个元素,这个就很好用了,可以作为检验是否定位到唯一元素检测,示例代码如下:

print(page.get_by_role("button").count()) #2