当容器的位置每次都可以改变时,有没有更好的方法从下拉列表中选择一个项目
Posted
技术标签:
【中文标题】当容器的位置每次都可以改变时,有没有更好的方法从下拉列表中选择一个项目【英文标题】:Is there a better way to select an item from a dropdown list when the location of the containers can change each time 【发布时间】:2021-12-14 08:51:10 【问题描述】:我正在尝试从下拉列表中选择特定项目,但是页面上列表的位置可能会随着每次运行而改变。
目前我的代码试图找到下拉列表,单击它,然后根据页面中下拉列表的位置选择特定元素 - 不幸的是,body
中包含的 div 的位置可以是每次负载都不同,因此对数组计数器进行硬编码在后续运行中不起作用 - 即,在 /html/body/div[16]
中,16
可以更改:
IWebElement questType = _driver.FindElement(By.XPath("/html/body/div[4]/div/div/div/div[4]/table/tbody/tr[2]/td[2]/div/div[4]/table/tbody/tr[2]/td[2]/div/div/div[2]/div/div[4]/table/tbody/tr/td[5]/span[1]/span"));
questType.Click();
IWebElement slctquestType = _driver.FindElement(By.XPath("/html/body/div[16]/div/div[3]/ul/li[1][contains(text(),'" + Questn_Type + "')]"));
slctquestType.Click();
选择元素如下所示:
<ul unselectable="on" class="k-list k-reset" tabindex="-1" aria-hidden="true" id="TypeId_listbox" aria-live="off" data-role="staticlist" role="listbox">
<li tabindex="-1" role="option" unselectable="on" class="k-item" aria-selected="false" data-offset-index="0">Data</li>
<li tabindex="-1" role="option" unselectable="on" class="k-item" aria-selected="false" data-offset-index="1">Other</li>
...
</ul>
【问题讨论】:
<ul unselectable="on" class="k-list k-reset" tabindex="-1" aria-hidden="true" id="TypeId_listbox" aria-live="off" data-role="staticlist" role="listbox"><li tabindex="-1" role="option" unselectable="on" class="k-item" aria-selected="false" data-offset-index="0">Data</li><li tabindex="-1" role="option"
你可以编辑你的问题
【参考方案1】:
XPath 非常强大。使用这种直接路径是最简单的方法。您还可以执行其他类似的操作来找到您想要的元素:
在节点内搜索一些文本:
By.XPath("//*[contains(text(), 'message part')]")
查找具有特定标题的按钮:
By.XPath("//button[@title = 'Continue']")
使用特定的类名查找 div 元素,该类名有一个子 div 元素,其标题中有一些文本:
By.XPath("//div[@class='className']//div[contains(@title, 'Title')]")
如您所见,您可以使用大量信息来查找特定元素。什么最符合您的具体情况取决于您,您可能应该查看有关 XPath syntax
的更多文档以深入了解。
【讨论】:
【参考方案2】:这里有一些隐藏的复杂性,因为这不是传统的<select>
元素。据推测,javascript 正在打开和关闭下拉菜单。切换下拉菜单时,这些元素可能会淡入或淡出(或向上或向下滑动)。当这些元素处于淡出或向上或向下滑动的过程中时,Selenium 将无法点击它们。这不仅仅是定位器问题,也是时间问题。
您可能需要点击下拉菜单,然后等待。单击该选项,然后再次等待。由于逻辑不平凡,请考虑使用Page Object Model Design Pattern 来封装此行为。
要更直接地处理您的代码,请首先通过 HTML 标记 ID 找到下拉列表。 HTML 标记 ID 在网页上是唯一的。如果它们不是唯一的,则应该解决此问题,因为 HTML 规范声明 HTML 标记 Id 值在网页上应该是唯一的。
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(30));
var questType = _driver.FindElement(By.Id("TypeId_listbox"));
questType.Click();
var optionLocator = By.XPath("//ul[@role = 'listbox']/li[contains(text(),'" + Questn_Type + "')]");
var slctquestType = wait.Until(ExpectedConditions.ElementIsClickable(optionLocator);
slctquestType.Click();
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(optionLocator);
要记住的重要一点是 XPath 选择器不需要精确。两个连续的正斜杠字符//
返回文档树中任意深度的元素。这允许您跳过几个级别,并仅定位您感兴趣的元素。例如,查找列表框选项可以简化为:
"//ul[@role = 'listbox']/li[contains(text(),'" + Questn_Type + "')]"
最初的//
字符将在任何级别的文档树中搜索<ul>
标记。这使得 xpath 表达式对 HTML 结构的变化更具弹性,这将导致更稳定的测试。
【讨论】:
以上是关于当容器的位置每次都可以改变时,有没有更好的方法从下拉列表中选择一个项目的主要内容,如果未能解决你的问题,请参考以下文章