Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value from Javascript function in Selenium webdriver

How do i return an array from a javascript function using selenium webdriver ? the code which i have tried is -

System.setProperty("webdriver.chrome.driver", "D:/chromedriver_win32/chromedriver.exe");
    wd=new ChromeDriver();
    wd.navigate().to("http://www.makemytrip.com");
    wd.manage().window().maximize();
    Thread.sleep(5000);
    wd.findElement(By.id("from_typeahead1")).click();
    WebElement span= wd.findElement(By.xpath(".//*[@id='one_round_default']/div/div[1]/div/div[1]/span/span/div[1]/span"));

    JavascriptExecutor jse = (JavascriptExecutor)wd;
    jse.executeScript("window.showList = function(){"+
            "var source=[];"+
            "var inputs = arguments[0].getElementsByTagName('div');"+
            "for(var i = 0; i < inputs.length; i++) {"+
                "source.push(inputs[i])"+
            "}"+
            "return source;"+
            "};",span);

    /*List<?> al =  (List<?>) jse.executeScript(
            "var source = [];"+
            "var inputs = arguments[0].getElementsByTagName('div');"+
            "for(var i = 0; i < inputs.length; i++) {"+
               "source.push(inputs[i])"+      
            "}"+
            "return source;"                 
            ,span);*/

    List<?> al =  (List<?>) jse.executeScript("showList();");
    for(Object web:al){
        System.out.println(((WebElement) web).getText());
    }

I am getting an exception stating - "org.openqa.selenium.WebDriverException: unknown error: Cannot read property 'getElementsByTagName' of undefined."

Incidently when i try this code it works perfectly -

System.setProperty("webdriver.chrome.driver", "D:/chromedriver_win32/chromedriver.exe");
    wd=new ChromeDriver();
    wd.navigate().to("http://www.makemytrip.com");
    wd.manage().window().maximize();
    Thread.sleep(5000);
    wd.findElement(By.id("from_typeahead1")).click();
    WebElement span= wd.findElement(By.xpath(".//*[@id='one_round_default']/div/div[1]/div/div[1]/span/span/div[1]/span"));

    List<?> al =  (List<?>) jse.executeScript(
            "var source = [];"+
            "var inputs = arguments[0].getElementsByTagName('div');"+
            "for(var i = 0; i < inputs.length; i++) {"+
               "source.push(inputs[i])"+      
            "}"+
            "return source;"                 
            ,span);

    for(Object web:al){
        System.out.println(((WebElement) web).getText());
    }

But i want to first create a function which returns me the array and then call the function whenever i want. How to achieve that? Also if possible how do i use an external .js file to do the same logic and use it in my script? Any help will be greatly appreciated. Thanks in advance !

like image 808
Aritro Sen Avatar asked Mar 03 '26 18:03

Aritro Sen


1 Answers

As you have found out the executeScript method creates a function using the first argument and pass the remaining arguments to it.

To break out of the scope of this function, simply define something in the global object or manipulate the DOM.

For example, call the jse.executeScript("window.showList = function(){... from your first code snippet somewhere in your test but do not pass it the span argument. This defines the showList function in the global scope.

Later you can simply do jse.executeScript("return showList.apply(null, arguments)", span) to call it.

Similarly, you can include an external script using the snippet

driver.executeScript("var s = document.createElement('script'); s.type = 'text/javascript'; s.src = arguments[0]; document.body.appendChild(s);", scriptUrl);

(or simply hard-code the url).

For both cases, remember to only run the definition/include call once to avoid redefining things.

like image 196
billc.cn Avatar answered Mar 06 '26 06:03

billc.cn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!