javascriptexecutor - executescript selenium
Ejecutar el elemento Javascript desde el punto de partida hasta el controlador Selenium (2)
El código de Alecxe funciona en la mayoría de los casos, pero fallará si la página contiene marcos o marcos flotantes.
Se requiere mucho más código para respetar también los marcos / iframes.
/// <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);
}
Esto debería implementarse en WebDriver.
Estoy tratando de implementar un "selector de objetos" en mi framework basado en Selenium, como es común en la mayoría de las herramientas de automatización comerciales. Para hacer esto, estoy usando un comando de Javascript para encontrar el elemento en la ubicación del mouse, pero no obtengo el elemento que espero.
Si utilizo ChromeDriver o InternetExplorerDriver, la secuencia de comandos siempre devuelve el objeto de encabezado. No importa qué página web mire o la posición del mouse. Aunque parece que el script toma las coordenadas 0, 0 en lugar de la posición del mouse, he confirmado que Cursor.Position está enviando los valores correctos.
Si estoy usando FirefoxDriver obtengo una excepción:
"Argument 1 of Document.elementFromPoint is not a finite floating-point value. (UnexpectedJavaScriptError)"
¿Alguien puede ver lo que estoy haciendo mal?
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) { }
}
}
¡Gracias!
En realidad, se trata de cómo está pasando las coordenadas en el guión. Los argumentos del script deben especificarse por separado como argumentos ExecuteScript()
separados . Lo que sucedía en su caso es que básicamente ha especificado un argumento x
que le hizo pensar que y
debería considerarse un valor 0
predeterminado. Y en y=0
usualmente hay un encabezado.
En lugar de:
ele = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(
"return document.elementFromPoint(arguments[0], arguments[1])",
new int[] { Cursor.Position.X, Cursor.Position.Y });
Deberías hacer:
ele = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(
"return document.elementFromPoint(arguments[0], arguments[1])",
Cursor.Position.X, Cursor.Position.Y);