【问题标题】:Selenium ChromeDriver how to click elements with negative x,y pixel locations? C#Selenium ChromeDriver 如何单击具有负 x,y 像素位置的元素? C#
【发布时间】:2016-11-22 15:49:07
【问题描述】:

我正在使用具有弹出式表格的网站。例如,如果用户悬停或单击链接,则会出现一个带有数据表的小弹出窗口。在同一页面上有许多这些链接可用。从表中提取数据涉及通过按顺序单击链接顺序打开和关闭每个弹出窗口。

关闭弹出窗口需要点击弹出窗口右上角的小“X”按钮。大约 99% 的时间,这不是问题。然而,大约 1% 的时间,弹出窗口的顶部会在屏幕上方,带有负的 'y' 像素位置,隐藏关闭弹出窗口的 'X' 按钮 - 反过来,给它一个负的 ' y' 像素位置。通过手动操作(手动移动鼠标),我可以调整 Chrome 窗口的大小,并且弹出窗口将“捕捉”回窗口,并且“y”像素位置至少为零。

我无法使用 Selenium 命令复制弹出窗口的手动重新居中。我能找到的最接近的命令是 MoveToElement,它有时有效,但在其他时候无效(我无法理解为什么我看到部分成功,但这是对这个问题的题外话)。

据我所知,Selenium 不允许我与具有负 x 或 y 像素位置的元素进行交互。

这是我目前正在尝试的,但成功有限:

// example begins with pop-up already displayed. Data has been extracted.
// We are now ready to close the pop-up by clicking the 'X' button.

// here we move to the table, otherwise the detail popup close button will be off screen. Warning: this works with partial success. 

var actions = new Actions(Session.Driver);
actions.MoveToElement(table);
actions.Perform();

// Must close unless the popup may (or may not) cover the next link.
var closeButton = Session.Driver.FindElement(By.Id(id))
    .FindElements(By.CssSelector("a.cmg_close_button"))
    .FirstOrDefault();
if (closeButton != null)
{
    Wait.Until(d => closeButton.Displayed);

    if (closeButton.Location.Y < 0 || closeButton.Location.X < 0)
    {
        Log.Error("Could not close button. The popup displayed the close_button off-screen giving it a negative x or y pixel location.");
    }
    else
    {
        closeButton.Click();
    }
}

请告知处理弹出窗口负x,y像素位置的策略。

我正在使用 C# 4.6、Selenium 2.45、ChromeDriver (Chrome) 和 VS2015 CE IDE。

【问题讨论】:

  • 你为什么不尝试使用ExpectedConditions.ElementToBeClickable(By),它为你提供具有正高度和宽度的可点击元素..
  • @SaurabhGaur 是什么.ElementToBeClickable() 迫使元素出现在屏幕上?
  • @Jeffc 不,它只是检查直到元素可见并启用这意味着可点击..
  • @SaurabhGaur 所以如果元素不动,那如何解决 OP 的问题?一旦超时,它只会抛出异常,因为该元素永远不会变为可点击。
  • @JeffC 你怎么能说元素永远不会变得可点击,而 OP 实现等待直到可见??

标签: javascript c# css google-chrome selenium


【解决方案1】:

Selenium 旨在仅与用户可以交互的元素进行交互。在大多数情况下,这更适用于页面上的隐藏元素。根据我的经验,你有一个罕见的情况,你的“隐藏”元素不在页面上,而不是 display:none 等。

解决此问题的一种方法是使用IJavaScriptExecutor。这将允许您在页面上运行 JS 代码。 注意:如果您试图坚持严格的用户场景,即只做用户可以做的事情,那么这不适合您。您将需要继续研究使该弹出窗口重新出现在屏幕上的方法。

我认为如果你改变你的脚本,如下所示,它应该可以工作。

if (closeButton.Location.Y < 0 || closeButton.Location.X < 0)
{
    IJavaScriptExecutor jse = Session.Driver as IJavaScriptExecutor;
    jse.ExecuteScript("arguments[0].click()", closeButton);
    // Log.Error("Could not close button. The popup displayed the close_button off-screen giving it a negative x or y pixel location.");
}
else
{
    closeButton.Click();
}

【讨论】:

  • @SaurabhGaur 如果有充分的理由,我对人们对我的答案投反对票等没有问题......如果有充分的理由,我想知道它是什么,所以我可以纠正它或至少回应分歧。
【解决方案2】:

当链接靠近视图边框时,页面似乎没有正确设置弹出窗口的位置。

要解决这个问题,您可以先将目标元素滚动到视图的中心,然后再移动它:

// scroll the link close to the center of the view
Session.Driver.ExecuteScript(
  "arguments[0].scrollIntoView(true);" +
  "window.scrollBy(-200, -200);" ,
  table);

// move the mouse over
new Actions(Session.Driver)
  .MoveToElement(table)
  .Perform();

【讨论】:

  • IJavaScriptExecutor javaScriptExecutor = Session.Driver 作为 IJavaScriptExecutor; javaScriptExecutor?.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(-200, -200);", table);
  • 我必须将其更改为上述内容才能使其正常工作。我目前正在执行一个完整的测试。它运行了几个小时。手指交叉...
  • 只有在将驱动程序转换为“IWebDriver”接口时才需要转换为IJavaScriptExecutor。使用基类:RemoteWebDriver driver = new ChromeDriver(); driver.ExecuteScript('...');
  • 这非常有效。但是,违反直觉而不是“向上滚动”以使元素到位;我不得不“向下滚动” - 一直到页面底部 - 令人惊讶的是,弹出窗口以正 x 和正 y 坐标为中心。旁注:缩小是行不通的,是一个错误的希望。虽然弹出窗口确实可见,但 Chromium 将继续在 100% 缩放设置下使用元素的 x,y 坐标。
猜你喜欢
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 2022-08-02
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
相关资源
最近更新 更多