4

For automation purposes, I am working on creating a script that finds a row in a table. This row is clickable and opens a new tab/adress.

With selenium, I am now able to find the table row, click on the link, and the new tab opens. The problem is that I can't find any way to switch the focus to the newly opened tab. I tried to get all windowHandles and see if I could switch, but even after the new tab has opened, there is only 1 windowHandle.

Below is my code:

WebElement tableRow=driver.findElement(By.xpath("/html/body/div[1]/table/tbody/tr[2]"));

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", tableRow);

ArrayList<String> tabs = new ArrayList<String> (driver.getWindowHandles());
    for(String winHandle : driver.getWindowHandles()){
        driver.switchTo().window(winHandle);
    }

The Arraylist always contains 1 single windowHandle, not 2. So I am not able to switch focus to the new tab. Is there any way to solve this?

Jelleko
  • 53
  • 1
  • 9

3 Answers3

6

To properly switch to the newly opened Tab you need to induce WebDriverWait for the New Tab to render and then through a for() loop you need to iterate through the available WindowHandles and invoke switchTo().window() with the WindowHandle which is not the previous TAB through the following code block :

String first_handle = driver.getWindowHandle();
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", tableRow);
new WebDriverWait(driver,5).until(ExpectedConditions.numberOfWindowsToBe(2));
Set<String> allHandles = driver.getWindowHandles();
for(String winHandle:allHandles)
{
    if (!first_handle.equalsIgnoreCase(winHandle)
    {
        driver.switchTo().window(winHandle);
    }
}
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • @Ryan Glad that you have brought up. In [this](https://stackoverflow.com/questions/46251494/best-way-to-keep-track-and-iterate-through-tabs-and-windows-using-windowhandles/46346324#46346324) discussion I have explained in details why Simon says `While the datatype used for storing the list of handles may be ordered by insertion, the order in which the WebDriver implementation iterates over the window handles to insert them has no requirement to be stable. The ordering is arbitrary`. So I would avoid the index by all possible means. – undetected Selenium Apr 30 '19 at 07:22
  • I see. Does this apply even if there are only 2 possible tabs to choose from? – Ryan Apr 30 '19 at 07:27
  • @Ryan I would prefer to be as generic as possible no matter how many windows/tabs 2, 3, 4 .... are present – undetected Selenium Apr 30 '19 at 07:28
2

Maybe you just have to wait until a second window is created? Maybe selenium checks window handles too fast?

Try with WebDriverWait

Example:

String currentHandle = driver.getWindowHandle();
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.numberOfWindowsToBe(2));

Set<String> allHandles = driver.getWindowHandles();
for (String handle : allHandles) {
    if (!handle.equals(currentHandle)) driver.switchTo().window(handle);
}

If a number of windows will be less or more than 2, TimeoutException will occur.

Fenio
  • 3,528
  • 1
  • 13
  • 27
1
 **Try this code:**

   public static void switchToNewWindow(WebDriver driver, WebElement 
   causeOfNewWindow) {

    // Get Handles before opening new window
    Set<String> oldHandles = driver.getWindowHandles();

    // Click element to open new Window
    causeOfNewWindow.click();

    // Get Handles after opening new window
    Set<String> newHandles = driver.getWindowHandles();

    for (String handle : newHandles) {

        if (!oldHandles.contains(handle)) {
            driver.switchTo().window(handle);
        }

    }
}