Playwright 中有没有办法在动态表中选择特定按钮?

Posted

技术标签:

【中文标题】Playwright 中有没有办法在动态表中选择特定按钮?【英文标题】:Is there a way in Playwright to select a specific button inside a dynamic table? 【发布时间】:2021-04-17 17:52:55 【问题描述】:

我是开发新手,在创建一个 e2e 测试时遇到了真正的问题。 基本上,我有一个包含 2 行或更多行的表,每行有 5 列(标题、x、y、z 按钮)。 如何使用标题单击正确行上的按钮? (这是一个测试来证明这个表的删除过程是有效的)。 我正在测试的应用程序是使用 React 框架编写的,因此所有表都经常更改,我需要一种方法来信任代码并且没有任何错误。 I need to click this element but it is not ever in the same position

html

<table>
    <tr>
     <td>Some Title</td>
     <td>x</td>
     <td>y</td>
     <td>
       <button>I need to click this</button>
    </td>
    </tr>
    <!--other rows--!>
</table>  

这是我遇到的解决方案

const rows = await page.$$eval("tr", (row) =>
    row.map((e) => e.textContent)
);
const correctRowIndex = rows.findIndex((e) => e.includes(TITLE_I_KNOW));
await page.click(
    "//tr[normalize-space(.)='" + rows[correctRowIndex] + "']/td/button"
);

期望的行为

我的代码似乎没有遵循最佳实践,我需要一个解决方案,将这个东西分成两部分。 1 - 将正确的行保存到变量中 2 - 单击已保存行中包含的按钮

【问题讨论】:

我真的不知道你所说的右行是什么意思。行是堆叠的,它们不在左侧或右侧。也许你的意思是一个专栏?是否要选择按钮所在的最右侧列?还是别的什么? 我的意思是我需要的那个,基本上,我在这个表中添加了一个具有特定标题的元素,现在我想删除我在行的第四列中使用按钮添加的那个元素 “对”是指正确的 这能回答你的问题吗? Selecting the right row 【参考方案1】:

快速解答

使用以下选择器组合可靠地单击右键。

const row = await page.waitForSelector('*css=tr >> text=Some title');
const button = await row.$('button');
await button.click();

深入讲解

Playwright 是一个很棒的工具,可能是迄今为止最好的网络自动化工具之一。但需要正确使用。

1。选择正确的行

const row = await page.waitForSelector('*css=tr >> text=Some title');

此行指示 Playwright 在页面中查找包含文本内容与字符串 Some title 匹配的元素的 tr 元素。

表达式由两个独立的选择器组成,即css=trtext=Some title

第一个将使用css 选择器引擎并且只针对所有tr 元素。第二个使用text引擎匹配文本内容。

&gt;&gt; 指示 Playwright 将两个选择器合并为一个。这通过评估第一个 css=tr 来工作。在第一个选择器的每个匹配元素上应用第二个选择器。

通常,组合选择器返回最右边选择器的结果: tr &gt;&gt; text=Some title 会给你元素&lt;td&gt;Some Title&lt;/td&gt;。 但是可以使用* 标记所需的选择器(同时仍然使用所有组合选择器缩小结果范围)。

注意:asterix * 强制要求明确指定选择器引擎 (css=),否则 Playwright 会猜错引擎。

Here you can read more about Playwright selectors.

2。选择按钮

const button = await row.$('button');

一旦我们有了正确的行,在这种情况下选择按钮就更容易了。一个简单的查询选择器 ($) 就足够了,因为它是一行中唯一存在的按钮元素。

row(而不是page)上调用$ 将仅匹配row 的DOM 子树中的元素。这与组合匹配器完全一样。

下一部分解释了为什么第 1 步必须使用waitForSelector()


正确的时机

就像您的示例一样,许多网站都是动态的。这意味着您在使用自动脚本查找页面中的内容时会遇到时间问题:当 Playwright 搜索所需内容时,表格可能尚未呈现。更糟糕的是,如果它在您的计算机上运行,​​它可能会在数周后在另一台计算机上失败。

这就是为什么查看与网页交互的每一行并确定是否存在需要解决的时间问题很重要的原因。

某些 Playwright 方法会定期探测匹配的选择器,并且仅在特定超时后才会失败。其他人不会等待并立即失败。

有时方法会在它们的名称中指明它们是否正在等待(例如page.waitForSelector())。但情况并非总是如此(例如,elementHandle.click() 实际上正在等待)。

因此必须查看API reference 并仔细阅读说明。

现在回到例子: 在第 1 步中,我们不得不使用等待方法,因为我们不知道动态表何时实际呈现到页面。在第 2 步中不需要使用等待方法,因为我们可以确定第 1 步成功后页面中存在表格。

【讨论】:

【参考方案2】:

我参加聚会迟到了,但可能对其他人有所帮助。有一个 :has 伪类恰好用于此类用例。试试:

await page.click('tr:has(td:text("Some Title")) button')

【讨论】:

以上是关于Playwright 中有没有办法在动态表中选择特定按钮?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Playwright for Python,如何从下拉列表中选择一个选项?

有没有办法根据 Python 中的一列或多列中具有相似值的行来选择表中的某些行?

SQL - 如何从多个可能的列名中进行选择?

有没有办法将此插入合并到选择查询中?

如何使用元素标题的一部分在 Puppeteer 或 Playwright 中找到元素?

有没有办法在不写查询中所有字段名称的情况下选择第一个表?