Execute JavaScript usando Selenium WebDriver em C #

103

Como isso é feito? Aqui , diz que a versão java é:

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

Mas não consigo encontrar o código C # para fazer isso.

JontyMC
fonte

Respostas:

216

Os nomes de objeto, método e propriedade nas ligações da linguagem .NET não correspondem exatamente aos das ligações Java. Um dos princípios do projeto é que cada ligação de linguagem deve "parecer natural" para aqueles que se sentem confortáveis ​​com a codificação nessa linguagem. Em C #, o código que você deseja para a execução de JavaScript é o seguinte

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

Observe que a documentação completa da API WebDriver para .NET pode ser encontrada neste link .

JimEvans
fonte
10
OBSERVE a capitalização na palavra Java S cript. Isso me pegou de surpresa.
WheretheresaWill
1
A resposta de Jim é a mais confiável que você pode imaginar. Verifique o histórico de commits em, bem, todos os arquivos Selenium .NET :-)
Ross Patterson
Você poderia me dizer como clicar em um botão em C #? Respostas como arguments[0].click();não está funcionando para mim? Não tenho exceção quando executo meu código, mas ele não clica no botão.
Almett
Acho estranho ter que escalar o piloto. Por que ExecuteJavascriptnão é apenas um método no driver?
Kolob Canyon
Isso é um resquício de uma época em que nem toda implementação de driver suportava a execução de JavaScript arbitrário. As ligações .NET, como as Java, usam interfaces baseadas em funções para modelar a funcionalidade que pode ser suportada por um driver, mas não todos. No assembly Support ( WebDriver.Support.dlldisponível por meio do NuGet no Selenium.Supportpacote), há um método de extensão que lida com a conversão para você e faz com que pareça que o driver tem um ExecuteJavaScriptmétodo.
JimEvans de
51

Eu prefiro usar um método de extensão para obter o objeto de scripts:

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

Usado desta forma:

driver.Scripts().ExecuteScript("some script");
Morten Christiansen
fonte
Selênio deve ter isso por padrão
Kolob Canyon
13

Que tal uma versão ligeiramente simplificada da bela ideia do método de extensão 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");

ou talvez a versão 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
fonte
1
Isso pode ser usado para obter WebElement e bool também?
rahoolm
12

o pacote nuget Selenium.Supportjá contém um método de extensão para ajudar com isso. Uma vez incluído, um script de liner para executor

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

ou

  string result = Driver.ExecuteJavaScript<string>("console.clear()");
Harishr
fonte
Esta é uma solução bonita e moderna. O método de extensão adiciona validação que o driver implementa IJavaScriptExecutore fornece uma mensagem de exceção melhor se o tipo de retorno for nulo quando não deveria ou não pode ser convertido para o tipo de retorno desejado.
Jeffrey LeCours de
o que é Driver? VS não consegue reconhecer isso
anatol
Você instalou o nuget ??
harishr
8

Você também pode fazer:

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
fonte
2
Boa ideia. Para quem está lendo isso, seu código javascript deve retornar um elemento DOM.
joelsand
Eu nem mesmo considerei isso possível. Isso é enorme, pois agora posso criar um método usando javascript para retornar nextSibling.
Jibbs de
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
fonte
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);
    }
}

Em seu código, você pode fazer

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

O código mais curto

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
fonte