使用 Selenium WebDriver 和 Java 切换选项卡

Posted

技术标签:

【中文标题】使用 Selenium WebDriver 和 Java 切换选项卡【英文标题】:Switch tabs using Selenium WebDriver with Java 【发布时间】:2012-09-25 14:34:19 【问题描述】:

在 Java 中使用 Selenium WebDriver。 我正在尝试自动化一项功能,在该功能中我必须打开一个新选项卡并在那里执行一些操作并返回上一个选项卡(父级)。 我使用了开关手柄,但它不起作用。 一件奇怪的事情是两个选项卡具有相同的窗口句柄,因此我无法在选项卡之间切换。

但是,当我尝试使用不同的 Firefox 窗口时,它可以工作,但对于选项卡,它不起作用。

如何切换标签? 或者,如何在不使用窗口句柄的情况下切换选项卡,因为在我的情况下,两个选项卡的窗口句柄相同?

(我观察到当您在同一个窗口中打开不同的选项卡时,窗口句柄保持不变)

【问题讨论】:

我认为在大多数情况下 2 个选项卡与 2 个窗口相同 请看:riponalwasim.blogspot.com/2020/05/… 【参考方案1】:
    psdbComponent.clickDocumentLink();
    ArrayList<String> tabs2 = new ArrayList<String> (driver.getWindowHandles());
    driver.switchTo().window(tabs2.get(1));
    driver.close();
    driver.switchTo().window(tabs2.get(0));

这段代码非常适合我。试试看。在您想在新选项卡上执行某些操作之前,您始终需要将驱动程序切换到新选项卡。

【讨论】:

标签不是窗口。我猜它在 Firefox 中不起作用。 这个答案假定在 driver.getWindowHandles() 中的顺序。该方法返回一个 Set,因此保证在合约级别没有订单。也许您的 WebDriver 实现正在返回一个可以保证顺序的 Set 实现,但为什么要冒险呢? 使用 ChromeDriver 2.33,getWindowHandles() 确实返回一个 LinkedHashSet,因此通过索引访问效果很好。请注意,您需要使用 getAt() 而不是 get()【参考方案2】:

这是一个简单的解决方案,用于打开新标签、将焦点更改为它、关闭标签并将焦点返回到旧/原始标签:

@Test
public void testTabs() 
    driver.get("https://business.twitter.com/start-advertising");
    assertStartAdvertising();

    // considering that there is only one tab opened in that point.
    String oldTab = driver.getWindowHandle();
    driver.findElement(By.linkText("Twitter Advertising Blog")).click();
    ArrayList<String> newTab = new ArrayList<String>(driver.getWindowHandles());
    newTab.remove(oldTab);
    // change focus to new tab
    driver.switchTo().window(newTab.get(0));
    assertAdvertisingBlog();

    // Do what you want here, you are in the new tab

    driver.close();
    // change focus back to old tab
    driver.switchTo().window(oldTab);
    assertStartAdvertising();

    // Do what you want here, you are in the old tab


private void assertStartAdvertising() 
    assertEquals("Start Advertising | Twitter for Business", driver.getTitle());


private void assertAdvertisingBlog() 
    assertEquals("Twitter Advertising", driver.getTitle());

【讨论】:

我正在使用 chrome 驱动程序,并且当我使用“driver.switchTo().window(newTab.get(0));”行时一个新窗口与一个新标签一起打开...知道为什么会这样吗? 没查过,估计是浏览器配置吧。【参考方案3】:

Web 驱动程序处理不同窗口和处理不同选项卡的方式有所不同。案例 1: 如果有多个窗口,则以下代码可以提供帮助:

//Get the current window handle
String windowHandle = driver.getWindowHandle();

//Get the list of window handles
ArrayList tabs = new ArrayList (driver.getWindowHandles());
System.out.println(tabs.size());
//Use the list of window handles to switch between windows
driver.switchTo().window(tabs.get(0));

//Switch back to original window
driver.switchTo().window(mainWindowHandle);

案例 2: 如果同一窗口中有多个选项卡,则只有一个窗口句柄。因此,在窗口句柄之间切换会使控件保持在同一个选项卡中。 在这种情况下,使用 Ctrl + \t (Ctrl + Tab) 在选项卡之间切换更有用。

//Open a new tab using Ctrl + t
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"t");
//Switch between tabs using Ctrl + \t
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"\t");

详细的示例代码可以在这里找到:http://design-interviews.blogspot.com/2014/11/switching-between-tabs-in-same-browser-window.html

【讨论】:

是的。这是第一个响应,表明只有一个窗口句柄,并且与选项卡不同。我不知道其他解决方案是如何工作的。 getWindowHandles 如何获取它们的选项卡列表?它只在 IE 中为我获取窗口句柄(我知道,IE,blech)【参考方案4】:

解决方法

假设:通过单击网页上的某些内容会打开一个新标签。

使用以下逻辑切换到第二个标签。

new Actions(driver).sendKeys(driver.findElement(By.tagName("html")), Keys.CONTROL).sendKeys(driver.findElement(By.tagName("html")),Keys.NUMPAD2).build().perform();

以同样的方式,您可以再次切换回第一个选项卡。

new Actions(driver).sendKeys(driver.findElement(By.tagName("html")), Keys.CONTROL).sendKeys(driver.findElement(By.tagName("html")),Keys.NUMPAD1).build().perform();

【讨论】:

仅适用于 Chrome【参考方案5】:

由于driver.window_handles 不正常,因此这是一个更好的解决方案。

首先使用快捷方式Control + X切换到第一个选项卡以切换到浏览器窗口中的第'x'个选项卡。

driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "1");
# goes to 1st tab

driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "4");
# goes to 4th tab if its exists or goes to last tab.

【讨论】:

【参考方案6】:
String selectLinkOpeninNewTab = Keys.chord(Keys.CONTROL, Keys.RETURN);
    WebElement e = driver.findElement(By
            .xpath("html/body/header/div/div[1]/nav/a"));
e.sendKeys(selectLinkOpeninNewTab);//to open the link in a current page in to the browsers new tab

    e.sendKeys(Keys.CONTROL + "\t");//to move focus to next tab in same browser
    try 
        Thread.sleep(8000);
     catch (InterruptedException e1) 
        // TODO Auto-generated catch block
        e1.printStackTrace();
    
    //to wait some time in that tab
    e.sendKeys(Keys.CONTROL + "\t");//to switch the focus to old tab again

希望对你有帮助..

【讨论】:

【参考方案7】:

您需要做的第一件事是打开一个新标签并保存它的句柄名称。最好使用 javascript 而不是键 (ctrl+t) 来执行此操作,因为自动化服务器上​​的键并不总是可用的。示例:

public static String openNewTab(String url) 
    executeJavaScript("window.parent = window.open('parent');");
    ArrayList<String> tabs = new ArrayList<String>(bot.driver.getWindowHandles());
    String handleName = tabs.get(1);
    bot.driver.switchTo().window(handleName);
    System.setProperty("current.window.handle", handleName);
    bot.driver.get(url);
    return handleName;

您需要做的第二件事是在选项卡之间切换。仅通过切换窗口句柄来执行此操作并不总是有效,因为您将处理的选项卡不会始终处于焦点,并且 Selenium 会不时出现故障。 正如我所说,使用键有点问题,而且 javascript 并不真正支持切换选项卡,所以我使用警报来切换选项卡,它就像一个魅力:

public static void switchTab(int tabNumber, String handleName) 
        driver.switchTo().window(handleName);
        System.setProperty("current.window.handle", handleName);
        if (tabNumber==1)
            executeJavaScript("alert(\"alert\");");
        else
            executeJavaScript("parent.alert(\"alert\");");
        bot.wait(1000);
        driver.switchTo().alert().accept();
    

【讨论】:

【参考方案8】:
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL,Keys.SHIFT,Keys.TAB);

此方法有助于在多个窗口之间切换。这种方法的限制性问题是它只能使用这么多次,直到达到所需的窗口。希望对您有所帮助。

【讨论】:

可能在多个标签之间?【参考方案9】:

Selenium 2.53.1 使用 firefox 47.0.1 作为 Java 中的 WebDriver:无论我打开多少个选项卡,“driver.getWindowHandles()”都只会返回一个句柄,因此无法在选项卡之间切换。

一旦我开始使用 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

希望这能让您很好地了解如何在多个浏览器窗口中操作多个选项卡。

【讨论】:

【参考方案10】:

对我有用的简单答案:

for (String handle1 : driver1.getWindowHandles()) 
        System.out.println(handle1); 
        driver1.switchTo().window(handle1);     

【讨论】:

【参考方案11】:
Set<String> tabs = driver.getWindowHandles();
Iterator<String> it = tabs.iterator();
tab1 = it.next();
tab2 = it.next();
driver.switchTo().window(tab1);
driver.close();
driver.switchTo().window(tab2);

试试这个。它应该工作

【讨论】:

【参考方案12】:

我最近遇到了一个问题,链接是在新标签页中打开的,但 selenium 仍然专注于初始标签页。

我正在使用 Chromedriver,而专注于标签的唯一方法是使用 switch_to_window()

这是 Python 代码:

driver.switch_to_window(driver.window_handles[-1])

所以提示是找出你需要的窗口句柄的名称,它们以列表形式存储在

driver.window_handles

【讨论】:

在索引到窗口句柄集合时要非常非常小心。无法保证这些句柄以任何顺序显示,并且打开的第一个窗口可能具有 getWindowhandles 方法(或您的语言中的等效方法)返回的列表中的最后一个窗口句柄。【参考方案13】:

请看下面:

WebDriver driver = new FirefoxDriver();

driver.manage().window().maximize();
driver.get("https://www.irctc.co.in/");
String oldTab = driver.getWindowHandle();

//For opening window in New Tab
String selectLinkOpeninNewTab = Keys.chord(Keys.CONTROL,Keys.RETURN); 
driver.findElement(By.linkText("Hotels & Lounge")).sendKeys(selectLinkOpeninNewTab);

// Perform Ctrl + Tab to focus on new Tab window
new Actions(driver).sendKeys(Keys.chord(Keys.CONTROL, Keys.TAB)).perform();

// Switch driver control to focused tab window
driver.switchTo().window(oldTab);

driver.findElement(By.id("textfield")).sendKeys("bangalore");

希望这有帮助!

【讨论】:

【参考方案14】:

这是一个非常简单的过程:假设您有两个选项卡,因此您需要首先使用client.window(callback) 关闭当前选项卡,因为切换命令“切换到第一个可用的选项卡”。然后你可以使用client.switchTab轻松切换标签。

【讨论】:

【参考方案15】:

如何在浏览器中切换标签的简单示例(如果只有一个窗口):

// open the first tab
driver.get("https://www.google.com");
Thread.sleep(2000);

// open the second tab
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "t");
driver.get("https://www.google.com");
Thread.sleep(2000);

// switch to the previous tab
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "" + Keys.SHIFT + "" + Keys.TAB);
Thread.sleep(2000);

我写Thread.sleep(2000)只是为了有一个超时来查看标签之间的切换。

您可以使用 CTRL+TAB 切换到下一个选项卡,使用 CTRL+SHIFT+TAB 切换到上一个选项卡。

【讨论】:

【参考方案16】:

这适用于 Firefox 和 Chrome 的 MacOS:

// opens the default browser tab with the first webpage
driver.get("the url 1");
thread.sleep(2000);

// opens the second tab
driver.findElement(By.cssSelector("Body")).sendKeys(Keys.COMMAND + "t");
driver.get("the url 2");
Thread.sleep(2000);

// comes back to the first tab
driver.findElement(By.cssSelector("Body")).sendKeys(Keys.COMMAND, Keys.SHIFT, "");

【讨论】:

【参考方案17】:

获取父窗口句柄。

String parentHandle = driverObj.getWindowHandle();
public String switchTab(String parentHandle)
    String currentHandle ="";
    Set<String> win  = ts.getDriver().getWindowHandles();   

    Iterator<String> it =  win.iterator();
    if(win.size() > 1)
        while(it.hasNext())
            String handle = it.next();
            if (!handle.equalsIgnoreCase(parentHandle))
                ts.getDriver().switchTo().window(handle);
                currentHandle = handle;
            
        
    
    else
        System.out.println("Unable to switch");
    
    return currentHandle;

【讨论】:

【参考方案18】:

所选答案的缺陷是它不必要地假定webDriver.getWindowHandles() 中的顺序。 getWindowHandles() 方法返回一个Set,它不保证顺序。

我使用以下代码更改选项卡,它不假定任何顺序。

String currentTabHandle = driver.getWindowHandle();
String newTabHandle = driver.getWindowHandles()
       .stream()
       .filter(handle -> !handle.equals(currentTabHandle ))
       .findFirst()
       .get();
driver.switchTo().window(newTabHandle);

【讨论】:

【参考方案19】:
protected void switchTabsUsingPartOfUrl(String platform) 
    String currentHandle = null;
    try 
        final Set<String> handles = driver.getWindowHandles();
        if (handles.size() > 1) 
            currentHandle = driver.getWindowHandle();
        
        if (currentHandle != null) 
            for (final String handle : handles) 
                driver.switchTo().window(handle);
                if (currentUrl().contains(platform) && !currentHandle.equals(handle)) 
                    break;
                
            
         else 
            for (final String handle : handles) 
                driver.switchTo().window(handle);
                if (currentUrl().contains(platform)) 
                    break;
                
            
        
     catch (Exception e) 
        System.out.println("Switching tabs failed");
    

调用该方法并传递参数一个你要切换到的标签的url子串

【讨论】:

【参考方案20】:

公共类 TabBrowserDemo

public static void main(String[] args) throws InterruptedException 
    System.out.println("Main Started");
    System.setProperty("webdriver.gecko.driver", "driver//geckodriver.exe");
    WebDriver driver = new FirefoxDriver();
    driver.get("https://www.irctc.co.in/eticketing/userSignUp.jsf");
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

    driver.findElement(By.xpath("//a[text()='Flights']")).click();
    waitForLoad(driver);
    Set<String> ids = driver.getWindowHandles();
    Iterator<String> iterator = ids.iterator();
    String parentID = iterator.next();
    System.out.println("Parent WIn id " + parentID);
    String childID = iterator.next();
    System.out.println("child win id " + childID);

    driver.switchTo().window(childID);
    List<WebElement> hyperlinks = driver.findElements(By.xpath("//a"));

    System.out.println("Total links in tabbed browser " + hyperlinks.size());

    Thread.sleep(3000);
//  driver.close();
    driver.switchTo().window(parentID);
    List<WebElement> hyperlinksOfParent = driver.findElements(By.xpath("//a"));

    System.out.println("Total links " + hyperlinksOfParent.size());



public static void waitForLoad(WebDriver driver) 
    ExpectedCondition<Boolean> pageLoadCondition = new
            ExpectedCondition<Boolean>() 
                public Boolean apply(WebDriver driver) 
                    return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
                
            ;
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(pageLoadCondition);

【讨论】:

欢迎来到 Stack Overflow!请不要把你的源代码扔在这里。友善一点,并尝试对您的答案进行漂亮的描述,以便其他人会喜欢并支持它。见:How do I write a good answer?【参考方案21】:
    public void switchToNextTab() 
        ArrayList<String> tab = new ArrayList<>(driver.getWindowHandles());
        driver.switchTo().window(tab.get(1));
    
    
    public void closeAndSwitchToNextTab() 
        driver.close();
        ArrayList<String> tab = new ArrayList<>(driver.getWindowHandles());
        driver.switchTo().window(tab.get(1));
    

    public void switchToPreviousTab() 
        ArrayList<String> tab = new ArrayList<>(driver.getWindowHandles());
        driver.switchTo().window(tab.get(0));
    

    public void closeTabAndReturn() 
        driver.close();
        ArrayList<String> tab = new ArrayList<>(driver.getWindowHandles());
        driver.switchTo().window(tab.get(0));
    

    public void switchToPreviousTabAndClose() 
        ArrayList<String> tab = new ArrayList<>(driver.getWindowHandles());
        driver.switchTo().window(tab.get(1));
        driver.close();
    

【讨论】:

【参考方案22】:
WebDriver driver = new FirefoxDriver();

driver.switchTo().window(driver.getWindowHandles().toArray()[numPage].toString());

numPage - int (0,1..)

【讨论】:

您能否在您的答案中添加一些解释、对文档的一些参考等?

以上是关于使用 Selenium WebDriver 和 Java 切换选项卡的主要内容,如果未能解决你的问题,请参考以下文章

appium的webdriver和selenium有啥区别?

Selenium Webdriver概述

无法使用Selenium和Java 11导入org.openqa.selenium.WebDriver

无法使用 Selenium 和页面工厂在页面对象类中调用“org.openqa.selenium.WebDriver.getTitle()”

Selenium & webdriver.io 如何使用 executeScript?

org.openqa.selenium.InvalidCookieDomainException:文档是使用 Selenium 和 WebDriver 的 cookie-averse