【问题标题】:Hover over element?将鼠标悬停在元素上?
【发布时间】:2020-01-03 17:44:30
【问题描述】:

使用 Visual Studio 和 Selenium,我试图将鼠标悬停在下拉菜单中的某个元素上,以便单击其中的“隐藏”元素。不能只点击,我必须悬停。

我尝试了几种不同的方法都没有成功:

首先,我尝试将鼠标悬停在第一个元素上,如下所示:

var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
Actions builder = new Actions(driver);
IWebElement hoverElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("xpath adress here')]")));
builder.MoveToElement(hoverElement).Build().Perform();

这种方法使第一个下拉元素被“标记”,但由于某种原因下拉菜单没有打开,所以我无法点击第二个元素。

然后我尝试将鼠标悬停在第一个元素上,并在同一命令中单击第二个元素:

var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
Actions builder = new Actions(driver);
IWebElement hoverElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("xpath adress here')]")));
builder.MoveToElement(hoverElement).MoveToElement(wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("second xpath adress")))).Click().Build().Perform();

这根本不起作用。第一个元素甚至没有被“标记”。测试仅在 10 秒后超时。

所以现在我尝试使用定位器:

var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
Actions builder = new Actions(driver);
IWebElement hoverElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("xpath adress for first element')]")));
builder.MoveToElement(hoverElement).Perform();
By locator = By.XPath("2nd element xpath");
driver.click(locator);

但是我不能执行这个测试,因为 IWebDriver 不包含点击的定义。当我尝试写入时出现此错误:

driver.click

有什么建议吗?

第一个元素:

By.XPath("//span[contains(@class,'item-text')][contains(text(),'Change')]"

第二个元素:

By.XPath("//span[contains(@class,'item-text')][contains(text(),'Create Change Order')]"

更新:

悬停下拉菜单部分的 HTML 结构如下所示:

<div class="topbar-menu-dd responsive-dropdown-menu add">
   <div class="scrollable-dropdown-menu scrollable-dropdown-menu-root dropdown- 
    menu dropdown-menu-root dropdown-menu dropdown-menu-root dropdown 
    dropdown-root responsive-dropdown-menu-root active">
      <div class="no-native-scrollbars  scroller-content">
          <ul class="dropdown-menu-wrap" tabindex="1">
             <li class="item topbar-menu-dd-item item-submenu" id="699143f1- 
              e470-49f0-99f4-a96fee365260/c171" title name="699143f1-e470-49f0- 
              99f4-a96fee365260/c171">
                 <div class="item item-template" id="699143f1-e470-49f0-99f4- 
                 a96fee365260/c171">
                    <span class="item-text">Change</span>
                 </div>
                 <div class="next-icon">
                    <span class="fonticon fonticon-right-open">
                    ::before
                    </span>
                 </div>
             </li>
   ...
   <div class="dropdown-menu dropdown-menu-root responsive  scroller scroller- 
   root bottom-right conceal">
      <div class="no-native-scrollbars  scroller-content">
         <ul class="dropdown-menu-wrap" tabindex="1">
            <li class="item item-back" id="itm-a7b1b6" title>
               <div class="back-icon">
               <span class="item-text">Change</span>
            </li>
            <li class="item topbar-menu-dd-item" id="cbf405dc-5f99-4efd-810d- 
            a69666da9c75/c172" title name="cbf405dc-5f99-4efd-810d- 
            a69666da9c75/c172">
               <div class="item item-template" id="cbf405dc-5f99-4efd-810d- 
            a69666da9c75/c172">
                  <span class="item-text">Create Change Order</span>
               </div>
           </li>
   ...
</div>

我添加的“...”表示代码中不相关的其他部分。

当我将鼠标悬停在“更改”上时,会显示“创建更改订单”,我可以点击它。

【问题讨论】:

  • 显示你的元素代码
  • 显示你的元素 HTML 代码 无法理解它的结构。为什么你必须悬停某些东西而不是单击下拉菜单然后单击菜单项?
  • @Somber 无法通过单击打开下拉菜单中的不同列表项,单击时没有任何反应,而是必须将鼠标光标悬停在所需的列表项上扩张。我在问题中添加了 HTML 结构。

标签: c# visual-studio selenium hover


【解决方案1】:

我通常使用 C# Selenium 的自定义点击功能。

public async Task<bool> TryClick(By by, int mode = 0)
{
   try
   {
       if (mode == 0)
       {
           Driver.ExecuteScript("arguments[0].click('');", ((RemoteWebDriver)Driver).FindElement(by));
       }
       else if (mode == 1)
       {
           Driver.FindElement(by).Click();
       }
       else if (mode == 2)
       {
           Actions action = new Actions(Driver);
           action.MoveToElement(Driver.FindElement(by)).Perform();
           action.Click(Driver.FindElement(by)).Perform();
       }

       return true;
   }
   catch (Exception ex) { }
   return false;
}

根据我的经验,上述 3 种方法中至少有一种适用于所有场景。 此外,我们可以通过检查函数的返回值来检查是否发生了异常。 您可以按如下方式使用此功能。

By first = By.XPath("//span[contains(@class,'item-text')][contains(text(),'Change')]";
if(!await TryClick(first,0)) // If this does not work, try 1 and 2 for the second parameter
{
    // Failed to click
}
By second = By.XPath("//span[contains(@class,'item-text')][contains(text(),'Create Change Order')]";
if(!await TryClick(second,0)) // If this does not work, try 1 and 2 for the second parameter
{
    // Failed to click
}

我不确定这是否有帮助。 但正如@Somber 所提到的,如果您分享 URL 并解释要实现的目标,那么获得帮助会更好。

【讨论】:

  • 我尝试按照您的建议使用操作,但出现错误:“消息:OpenQA.Selenium.WebDriverException:javascript 错误:无法读取未定义的属性“左侧””不太确定这意味着什么。我也尝试按照您的建议使用“Driver.ExecuteScript”,但我的驱动程序不包含“ExcecuteScript”。如果您想看一下,我现在已经用部分 HTML 代码更新了问题。
  • 你能分享链接吗?我想先在我这边测试。
  • 很遗憾不可能。该页面只能通过我工作的公司访问。
【解决方案2】:

仅使用悬停 (MoveToElement) 不足以激活和展开下拉菜单。我还需要使用MoveByOffset 稍微移动鼠标。

菜单展开后,我点击第二个元素没有问题。

//1. Hover mouse over "Change" and move it slightly to the left to open up the menu
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var DropDown1 = wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//span[contains(@class,'item-text')][contains(text(),'Change')]")));
Actions action = new Actions(driver);
action.MoveToElement(DropDown1).Perform();
action.MoveByOffset(-10, -10).Perform();

//2. Click on "Create Change Order"
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//span[contains(@class,'item-text')][contains(text(),'Create Change Order')]"))).Click();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    • 2011-11-08
    • 2017-09-18
    • 2021-07-15
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多