Reputation: 515
I am opening google.com and then clicking on "GMail" hyperlink a new tab is opened on the same browser.
Now I want to switch to this new tab where GMail is opened using Selenium WebDriver.
Code snippet is :
WebDriver wd = new ChromeDriver();
wd.get("https://www.google.co.in/?gws_rd=ssl");
wd.findElement(By.linkText("Gmail")).sendKeys(Keys.CONTROL,Keys.RETURN);
Now I want to go to the tab where I have opened GMail link. I have googled through N number of solutions but none of them worked.
For e.g.
Solution 1 :
String Tab1 = wd.getWindowHandle();
ArrayList<String> availableWindows = new ArrayList<String>(wd.getWindowHandles());
if (!availableWindows.isEmpty()) {
wd.switchTo().window(availableWindows.get(1));
}
Solution 2 :
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"\t");
Kindly suggest. I am stuck on this.
Upvotes: 8
Views: 78684
Reputation: 16201
The window handles is not very safe with the index number since they could be very unordered. I would suggest you to find a list and do a loop and look for the intended one.
public void TabHandles() {
driver.get("https://www.google.co.in/?gws_rd=ssl");
String currentWindowHandle = driver.getWindowHandle();
driver.findElement(By.linkText("Gmail")).sendKeys(Keys.CONTROL, Keys.RETURN);
//Get the list of all window handles
ArrayList<String> windowHandles = new ArrayList<String>(driver.getWindowHandles());
for (String window:windowHandles){
//if it contains the current window we want to eliminate that from switchTo();
if (!window.equals(currentWindowHandle){
//Now switchTo new Tab.
driver.switchTo().window(window);
//Do whatever you want to do here.
//Close the newly opened tab
driver.close();
}
}
}
Upvotes: 4
Reputation: 4633
There is an easy and short way:
import java.util.ArrayList;
ArrayList<String> tabs2 = new ArrayList<String>(driver.getWindowHandles());
driver.switchTo().window(tabs2.get(1)); //Tab number
//Can change it for next tab like that or previous:
driver.switchTo().window(tabs2.get(1));
driver.close();
driver.switchTo().window(tabs2.get(0));
That's it, hope it help.
Upvotes: 1
Reputation: 13
You can provide tab name parameter and try this:
public boolean switchToTab(String tabName){
log.debug("Switch to {} tab",tabName);
ArrayList<String> tab = new ArrayList<>(driver.getWindowHandles());
ArrayList<String> tabList = new ArrayList<>();
for (int i =0;i<tab.size();i++){
tabList.add(i,driver.switchTo().window(tab.get(i)).getTitle());
driver.switchTo().window(tab.get(0));
if(tabList.get(i).equals(tabName)){
driver.switchTo().window(tab.get(i));
return true;
}
}
return false;
}
Upvotes: 1
Reputation: 11
Below is the Java Implementation using Robot Class, I have switched tabs multiple(7) times.
I Hope it will Help.
Imports:
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
Main Method
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "/Path/To/chromedriver/" + "chromedriver.exe");
WebDriver driver = new ChromeDriver();
// go to URL1
driver.navigate().to("http://www.facebook.com");
try {
// Open New Tab by simulating Ctrl+t
Robot r = new Robot();
r.keyPress(KeyEvent.VK_CONTROL);
r.keyPress(KeyEvent.VK_T);
r.keyRelease(KeyEvent.VK_CONTROL);
r.keyRelease(KeyEvent.VK_T);
Thread.sleep(1000);
// Create Array List to keep Tab information
ArrayList<String> tabs2 = new ArrayList<String>(driver.getWindowHandles());
// Navigate to New Tab
driver.switchTo().window(tabs2.get(1));
// go to URL2
driver.navigate().to("http://www.google.com");
// Navigate to Tab 0
driver.switchTo().window(tabs2.get(0));
Thread.sleep(2000);
// Navigate to Tab 1
driver.switchTo().window(tabs2.get(1));
Thread.sleep(2000);
// Navigate to Tab 0
driver.switchTo().window(tabs2.get(0));
Thread.sleep(2000);
// Navigate to Tab 1
driver.switchTo().window(tabs2.get(1));
Thread.sleep(2000);
// Navigate to Tab 1
driver.switchTo().window(tabs2.get(0));
driver.close();
Thread.sleep(2000);
// Navigate to Tab 1
driver.switchTo().window(tabs2.get(1));
driver.close();
} catch (Exception e) {
}
}
Upvotes: 0
Reputation: 1354
Seems to me that driver.getWindowHandles() does not work for tabs... you'll always get back a one item array with the CURRENT tab's handle... [deleted old answer as this seems to be fixed now]
UPDATE (6/16/2016): the current version of Selenium (server standalone 2.53.0) seems to act differently. Now I'm using something like this to open/switch the driver to the new tab:
UPDATE (11/16/2016): Selenium 3.0.1 seems to have changed things again? I have to use javascript to open a new tab now. This seems to work in Chrome only... Firefox opens a new window. I'm going to see if that behavior can be changed using geckodriver's settings (capabilities/profile?).
// Actions actions = new Actions(driver);
// actions.keyDown(Keys.CONTROL).sendKeys("t").keyUp(Keys.CONTROL).build().perform();
((JavascriptExecutor)driver).executeScript("window.open('about:blank', '_blank');");
Set<String> tab_handles = driver.getWindowHandles();
int number_of_tabs = tab_handles.size();
int new_tab_index = number_of_tabs-1;
driver.switchTo().window(tab_handles.toArray()[new_tab_index].toString());
the getWindowHandles() method is now returning a Set. This has only been tested in Chrome so far, since Firefox version 47 currently has some serious problems using the firefoxdriver... and using geckodriver the Actions aren't working at all. [update 6/11/2016]: Firefox through geckodriver now returns a Set]
You can also do something like this.. cast it to ArrayList:
// set tab_index to the number of window/tab you want. 0 is the first tab
ArrayList<String> tabs_windows = new ArrayList<String> (driver.getWindowHandles());
driver.switchTo().window(tabs_windows.get(tab_index));
Update: To get around the geckodriver bug, I've switched to using element.sendkeys... something like this seems to work in Marionette and Chrome.. (Update2): Updated to javascript because of changes in Selenium 3.0.1:
// driver.findElement(By.cssSelector("body")).sendKeys(Keys.chord(Keys.CONTROL, "t"));
((JavascriptExecutor)driver).executeScript("window.open('about:blank', '_blank');");
Set<String> tab_handles = driver.getWindowHandles();
int number_of_tabs = tab_handles.size();
int new_tab_index = number_of_tabs-1;
driver.switchTo().window(tab_handles.toArray()[new_tab_index].toString());
UPDATE (11/16/2016): the old method to close using Ctrl-W seems to be broken, too... use this:
((JavascriptExecutor)driver).executeScript("close();");
Upvotes: 11
Reputation: 23
I'd suggest initializing a second driver to do the work for that tab, or open a second tab in the first driver and have that tab have it's own set of logic accomplishing what you need.
The code below should give you a good idea of how you can manipulate different drivers/browsers/windows and multiple tabs within each driver using Selenium 2.53.1 and Chrome 51.0.
// INITIALIZE TWO DRIVERS (THESE REPRESENT SEPARATE CHROME WINDOWS)
driver1 = new ChromeDriver();
driver2 = new ChromeDriver();
// LOOP TO OPEN AS MANY TABS AS YOU WISH
for(int i = 0; i < TAB_NUMBER; i++) {
driver1.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "t");
// SLEEP FOR SPLIT SECOND TO ALLOW DRIVER TIME TO OPEN TAB
Thread.sleep(100);
// STORE TAB HANDLES IN ARRAY LIST FOR EASY ACCESS
ArrayList tabs1 = new ArrayList<String> (driver1.getWindowHandles());
// REPEAT FOR THE SECOND DRIVER (SECOND CHROME BROWSER WINDOW)
// LOOP TO OPEN AS MANY TABS AS YOU WISH
for(int i = 0; i < TAB_NUMBER; i++) {
driver2.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "t");
// SLEEP FOR SPLIT SECOND TO ALLOW DRIVER TIME TO OPEN TAB
Thread.sleep(100);
// STORE TAB HANDLES IN ARRAY LIST FOR EASY ACCESS
ArrayList tabs2 = new ArrayList<String> (driver1.getWindowHandles());
// NOW PERFORM DESIRED TASKS WITH FIRST BROWSER IN ANY TAB
for(int ii = 0; ii <= TAB_NUMBER; ii++) {
driver1.switchTo().window(tabs1.get(ii));
// LOGIC FOR THAT DRIVER'S CURRENT TAB
}
// PERFORM DESIRED TASKS WITH SECOND BROWSER IN ANY TAB
for(int ii = 0; ii <= TAB_NUMBER; ii++) {
drvier2.switchTo().window(tabs2.get(ii));
// LOGIC FOR THAT DRIVER'S CURRENT TAB
}
I hope that helps
Upvotes: 0
Reputation: 14076
The way we manually switch to next tab is by pressing - CTRL + Page Down
The same we can do using Selenium like -
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL, Keys.PAGE_DOWN);
Upvotes: 8
Reputation: 3461
You have a possible right solution (Sol2), but the problem is you can't switch to a new tab untill it will not be loaded fully.
So, solutions: 1) BAD ONE: put in a waiting timer, just sleep(2000) some time, and then
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"\t");
2) Good one!
Use native selenium things. First get all the available tabs opened with:
driver.getWindowHandle();
Then swith to another tab:
driver.switchTo().window(myWindowHandle );
Upvotes: 1