通过Selenium驱动程序执行Javascript elementFromPoint

时间:2015-08-10 01:38:24

标签: javascript c# selenium selenium-webdriver

我正在尝试实现一个"对象选择器"在大多数商业自动化工具中常见的基于Selenium的框架。要做到这一点,我使用Javascript命令在鼠标位置找到元素,但我没有得到我期望的元素。

如果我使用的是ChromeDriver或InternetExplorerDriver,则脚本始终会返回标头对象。无论我看什么网页或鼠标的位置。虽然听起来脚本采用坐标0,0而不是鼠标位置,但我确认Cursor.Position正在发送正确的值。

如果我使用的是FirefoxDriver,我会遇到异常:

"Argument 1 of Document.elementFromPoint is not a finite floating-point value. (UnexpectedJavaScriptError)"

谁能看到我做错了什么?

    private void OnHovering()
    {
        if (Control.ModifierKeys == System.Windows.Forms.Keys.Control)
        {
            IWebElement ele = null;
            try
            {
                // Find the element at the mouse position
                if (driver is IJavaScriptExecutor)
                    ele = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(
                        "return document.elementFromPoint(arguments[0], arguments[1])", 
                        new int[] { Cursor.Position.X, Cursor.Position.Y });

                // Select the element found
                if (ele != null)
                    SelectElement(ele);
            }
            catch (Exception) { }
        }
    }

谢谢!

3 个答案:

答案 0 :(得分:2)

实际上是关于如何将坐标传递给脚本。 脚本参数必须单独指定为单独的"use strict"; describe("PFTs", function(){ it("cannot be created without a subjId", function(){ var testDate = new Date(); var invalidNewPFT = {pftDate: testDate} var preinsertCount = PFTs.find().fetch().length; // expect used here to swallow the msg sent to the browser by Collection2 expect( function(){ PFTs.insert(invalidNewPFT); }).toThrow; // Verify that a record was not saved expect( PFTs.find().fetch().length ).toEqual(preinsertCount); }); }); 参数。在您的情况下发生的事情是您基本上指定了一个ExecuteScript()参数,这使得它认为x应该被视为默认y值。在0,通常会有一个标题。

而不是:

y=0

你应该这样做:

ele = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(
                        "return document.elementFromPoint(arguments[0], arguments[1])", 
                        new int[] { Cursor.Position.X, Cursor.Position.Y });

答案 1 :(得分:1)

alecxe的代码在大多数情况下都有效,但如果页面包含框架或iframe,则会失败。

还需要更多代码来尊重帧/ iframe。

/// <summary>
/// Get the element at the viewport coordinates X, Y
/// </summary>
static public RemoteWebElement GetElementFromPoint(RemoteWebDriver i_Driver, int X, int Y)
{
    while (true)
    {
        String s_Script = "return document.elementFromPoint(arguments[0], arguments[1]);";

        RemoteWebElement i_Elem = (RemoteWebElement)i_Driver.ExecuteScript(s_Script, X, Y);
        if (i_Elem == null)
            return null;

        if (i_Elem.TagName != "frame" && i_Elem.TagName != "iframe")
            return i_Elem;

        Point p_Pos = GetElementPosition(i_Elem);
        X -= p_Pos.X;
        Y -= p_Pos.Y;

        i_Driver.SwitchTo().Frame(i_Elem);
    }
}

/// <summary>
/// Get the position of the top/left corner of the Element in the document.
/// NOTE: RemoteWebElement.Location is always measured from the top of the document and ignores the scroll position.
/// </summary>
static public Point GetElementPosition(RemoteWebElement i_Elem)
{
    String s_Script = "var X, Y; "
                    + "if (window.pageYOffset) " // supported by most browsers 
                    + "{ "
                    + "  X = window.pageXOffset; "
                    + "  Y = window.pageYOffset; "
                    + "} "
                    + "else " // Internet Explorer 6, 7, 8
                    + "{ "
                    + "  var  Elem = document.documentElement; "         // <html> node (IE with DOCTYPE)
                    + "  if (!Elem.clientHeight) Elem = document.body; " // <body> node (IE in quirks mode)
                    + "  X = Elem.scrollLeft; "
                    + "  Y = Elem.scrollTop; "
                    + "} "
                    + "return new Array(X, Y);";

    RemoteWebDriver i_Driver = (RemoteWebDriver)i_Elem.WrappedDriver;
    IList<Object>   i_Coord  = (IList<Object>)  i_Driver.ExecuteScript(s_Script);

    int s32_ScrollX = Convert.ToInt32(i_Coord[0]);
    int s32_ScrollY = Convert.ToInt32(i_Coord[1]);

    return new Point(i_Elem.Location.X - s32_ScrollX,
                     i_Elem.Location.Y - s32_ScrollY);
}

这应该在WebDriver中实现。

答案 2 :(得分:0)

我也遇到了这个问题。我发现它被抛出的原因是因为我试图获取其位置的元素是隐藏的(具有属性display:none)。因此没有位置。