Ejecute JavaScript usando Selenium WebDriver en C #

103

¿Cómo se logra esto? Aquí dice que la versión de Java es:

WebDriver driver; // Assigned elsewhere
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("return document.title");

Pero no puedo encontrar el código C # para hacer esto.

JontyMC
fuente

Respuestas:

216

Los nombres de objeto, método y propiedad en los enlaces del lenguaje .NET no se corresponden exactamente con los de los enlaces Java. Uno de los principios del proyecto es que cada enlace de idioma debe "sentirse natural" para quienes se sientan cómodos codificando en ese idioma. En C #, el código que desea para ejecutar JavaScript es el siguiente

IWebDriver driver; // assume assigned elsewhere
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
string title = (string)js.ExecuteScript("return document.title");

Tenga en cuenta que la documentación completa de la API de WebDriver para .NET se puede encontrar en este enlace .

JimEvans
fuente
10
NOTA las mayúsculas en la palabra Java S cript. Esto me sorprendió.
WheretheresaWill el
1
La respuesta de Jim es lo más autoritaria posible. Consulte el historial de confirmaciones en, bueno, todos los archivos .NET de Selenium :-)
Ross Patterson
¿Podría decirme cómo hacer clic en un botón en C #? ¿Respuestas como si arguments[0].click();no me funciona? No tengo ninguna excepción cuando ejecuto mi código, pero no hace clic en el botón.
Almett
Me resulta incómodo tener que lanzar el controlador. ¿Por qué ExecuteJavascriptno es solo un método en el driver?
Kolob Canyon
Eso es un vestigio de una época en que no todas las implementaciones de controladores admitían la ejecución de JavaScript arbitrario. Los enlaces .NET, como los de Java, utilizan interfaces basadas en roles para modelar la funcionalidad que puede ser compatible con un controlador, pero no con todos. En el ensamblado de Soporte ( WebDriver.Support.dlldisponible a través de NuGet en el Selenium.Supportpaquete), hay un método de extensión que maneja la conversión por usted y hace que parezca que el controlador tiene un ExecuteJavaScriptmétodo.
JimEvans
51

Prefiero usar un método de extensión para obtener el objeto scripts:

public static IJavaScriptExecutor Scripts(this IWebDriver driver)
{
    return (IJavaScriptExecutor)driver;
}

Usado como este:

driver.Scripts().ExecuteScript("some script");
Morten Christiansen
fuente
El selenio debería tener esto por defecto
Kolob Canyon
13

¿Qué tal una versión ligeramente simplificada de la bonita idea del método de extensión de @Morten Christiansen?

public static object Execute(this IWebDriver driver, string script)
{
    return ((IJavaScriptExecutor)driver).ExecuteScript(script);
}

// usage
var title = (string)driver.Execute("return document.title");

o tal vez la versión genérica:

public static T Execute<T>(this IWebDriver driver, string script)
{
    return (T)((IJavaScriptExecutor)driver).ExecuteScript(script);
}

// usage
var title = driver.Execute<string>("return document.title");
agentnega
fuente
1
¿Se puede usar esto para obtener WebElement y bool también?
rahoolm
12

el paquete nuget Selenium.Supportya contiene un método de extensión para ayudar con esto. Una vez que se incluye, una línea para ejecutar el script

  Driver.ExecuteJavaScript("console.clear()");

o

  string result = Driver.ExecuteJavaScript<string>("console.clear()");
harishr
fuente
Esta es una solución moderna y agradable. El método de extensión agrega la validación que implementa el controlador IJavaScriptExecutory proporciona un mejor mensaje de excepción si el tipo de retorno es nulo cuando no debería ser o no se puede convertir al tipo de retorno deseado.
Jeffrey LeCours
¿cuál es el Driver? VS no puede reconocer eso
anatol
¿Has instalado el nuget?
harishr
8

También puedes hacer:

public static IWebElement FindElementByJs(this IWebDriver driver, string jsCommand)
{
    return (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(jsCommand);
}

public static IWebElement FindElementByJsWithWait(this IWebDriver driver, string jsCommand, int timeoutInSeconds)
{
    if (timeoutInSeconds > 0)
    {
        var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
        wait.Until(d => d.FindElementByJs(jsCommand));
    }
    return driver.FindElementByJs(jsCommand);
}

public static IWebElement FindElementByJsWithWait(this IWebDriver driver, string jsCommand)
{
    return FindElementByJsWithWait(driver, jsCommand, s_PageWaitSeconds);
}
Perryzheng
fuente
2
Buena idea. Para otros que lean esto, su código javascript debería devolver un elemento DOM.
joelsand
Ni siquiera consideré esto como posible. Esto es enorme, ya que ahora puedo crear un método usando javascript para devolver nextSibling.
jibbs
1
public void javascriptclick(String element)
    { 
        WebElement webElement=driver.findElement(By.xpath(element));
        JavascriptExecutor js = (JavascriptExecutor) driver;

        js.executeScript("arguments[0].click();",webElement);   
        System.out.println("javascriptclick"+" "+ element);

    }
akhilesh gulati
fuente
0
public static class Webdriver
{        
    public static void ExecuteJavaScript(string scripts)
    {
        IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
        js.ExecuteScript(scripts);
    }

    public static T ExecuteJavaScript<T>(string scripts)
    {
        IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
        return (T)js.ExecuteScript(scripts);
    }
}

En su código puede hacer

string test = Webdriver.ExecuteJavaScript<string>(" return 'hello World'; ");
int test = Webdriver.ExecuteJavaScript<int>(" return 3; ");
Mo D Genesis
fuente
0

El código más corto

ChromeDriver drv = new ChromeDriver();

drv.Navigate().GoToUrl("/programming/6229769/execute-javascript-using-selenium-webdriver-in-c-sharp");

drv.ExecuteScript("return alert(document.title);");

Ebubekir Bastama
fuente