Wie wechsle ich zum neuen Browserfenster, das nach dem Klicken auf die Schaltfläche geöffnet wird?

86

Ich habe eine Situation, wenn durch Klicken auf die Schaltfläche das neue Browserfenster mit Suchergebnissen geöffnet wird.

Gibt es eine Möglichkeit, eine Verbindung herzustellen und sich auf ein neu geöffnetes Browserfenster zu konzentrieren?

Und arbeiten Sie damit, und kehren Sie dann zum ursprünglichen (ersten) Fenster zurück.

Volodymyr Prysiazhniuk
quelle
Wir können den Wechsel automatisch durchführen - überprüfen Sie hier die erweiterte Verwendung - testautomationguru.com/…
vins

Antworten:

117

Sie können wie folgt zwischen den Fenstern wechseln:

// Store the current window handle
String winHandleBefore = driver.getWindowHandle();

// Perform the click operation that opens new window

// Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
    driver.switchTo().window(winHandle);
}

// Perform the actions on new window

// Close the new window, if that window no more required
driver.close();

// Switch back to original browser (first window)
driver.switchTo().window(winHandleBefore);

// Continue with original browser (first window)
Surya
quelle
3
Ich kann bestätigen, dass die akzeptierte Lösung in Chrome konsistent funktioniert, jedoch nicht im IE. Das neue Fensterhandle wird im IE nicht erkannt. @Elmue ist falsch, da getWindowHandles()ein Set zurückgegeben wird und ein Set die Bestellung nicht garantiert . Das letzte Element ist nicht immer das letzte Fenster. Ich bin überrascht, dass sein Kommentar viele positive Stimmen erhält.
Silber
@silver: Ich habe keine Ahnung, wovon du sprichst. In meinem Code gibt WindowHandles eine ReadOnlyCollection <string> zurück, für die ich garantieren kann, dass der letzte Eintrag immer das zuletzt geöffnete Fenster ist. Ich habe das getestet. Wenn dies in C # perfekt funktioniert, aber in Java falsch implementiert ist, sollten Sie dies als Fehler melden.
Elmue
@ Elmue Dies ist ein Java-Thread. Bitte lesen Sie die Antwort von Luke (Selenium-Entwickler) bezüglich getWindowHandles(). Es ist ein bekanntes Verhalten (kein Fehler) der Methode und insbesondere des Java-Sets <T>. Daher switchTo().window(handles[handles.length-1])ist in Java nicht garantiert. Es kann nicht behauptet werden, dass die AC # -Lösung korrekt ist.
Silber
5
@Elmue Zum dritten (und letzten) Mal ist Ihre Antwort für Java falsch, da dies von Dokumenten und Entwicklern unterstützt wird, die Menschen irreführen können. Schreiben Sie eine Antwort, in der Sie sagen, dass es sich um C # handelt, kein Problem. Erhöhen Sie eine Problemkarte in GitHub für Java. Ihre Antwort gilt einfach nicht für die Sprache, die im Thread markiert ist, und die Leute denken möglicherweise anders. Wenn Sie die Unterscheidung nicht treffen können, fehlt Ihr Verständnis.
Silber
3
@Elmue Übrigens, Sie sagen auch falsch, dass driver.close () beide Fenster schließt. Es schließt nur den Strom. driver.quit () beendet alle Instanzen. Ich kann jemanden sehen, der Sie bereits darauf hingewiesen hat. Ihr Kommentar ist voller Fehler. Haben Sie einen guten Tag.
Silber
12

Nur um den Inhalt zu ergänzen ...

Zurück zum Hauptfenster (Standardfenster).

verwenden driver.switchTo().defaultContent();

Amarnath Rayudu
quelle
11

Dieses Skript hilft Ihnen , von einem wechseln Elternfenster zu einem Kind Fenster und zurück cntrl Übergeordnetes Fenster

String parentWindow = driver.getWindowHandle();
Set<String> handles =  driver.getWindowHandles();
   for(String windowHandle  : handles)
       {
       if(!windowHandle.equals(parentWindow))
          {
          driver.switchTo().window(windowHandle);
         <!--Perform your operation here for new window-->
         driver.close(); //closing child window
         driver.switchTo().window(parentWindow); //cntrl to parent window
          }
       }
Prashanth Sams
quelle
1
driver.close () funktioniert für neues Fenster. Wenn es sich um eine neue Registerkarte handelt, schließen Sie die neue Registerkarte mit dem folgenden Code: driver.findElement (By.cssSelector ("body")). SendKeys (Keys.CONTROL + "w");
Ripon Al Wasim
4

Surya, dein Weg wird aus zwei Gründen nicht funktionieren:

  1. Sie können den Treiber während der Testauswertung nicht schließen, da er den Fokus verliert, bevor Sie zum aktiven Element wechseln, und Sie erhalten NoSuchWindowException.
  2. Wenn der Test auf ChromeDriver ausgeführt wird, wird kein Fenster angezeigt, sondern ein Tab auf Klicken in Ihrer Anwendung. Da SeleniumDriver nicht mit Registerkarten arbeiten kann , sondern nur zwischen Fenstern wechselt, hängt es beim Klicken, wo eine neue Registerkarte geöffnet wird, und stürzt bei Zeitüberschreitung ab.
Neid
quelle
1
Sie können den Aufruf für driver.close () tatsächlich verwenden, da Sie die Fensterhandles des Treibers wechseln und das Fenster aufrufen, in dem Sie sich gerade befinden, um es zu schließen. Ich verwende es regelmäßig in meinem Code, wenn ich mit mehreren Fenstern arbeite. driver.Quit () ist der Aufruf, der den Test beendet. In Chromedriver können Sie weiterhin getWindowHandles () aufrufen, um Ihre Liste der verfügbaren Fenster abzurufen. Ich kann mir keinen Grund vorstellen, einen Tab in einem Webtest zu verwenden.
Ben
@Elmue Die ursprüngliche Frage besagte, dass ein Klick ein zweites Fenster öffnet, in dem mehrere Fenstergriffe erstellt werden. Ich kann den Aufruf driver.close () machen; und habe mein Fenster, das derzeit Fokus hat, geschlossen. Ich kann dann zu einem anderen aktiven Fenster meiner Wahl wechseln. driver.close () und driver.quit () haben nicht dieselbe Funktionalität. Ein Aufruf von driver.quit () beendet die aktive Treiberinstanz, während close nur das aktuelle Fensterhandle beendet. Außerdem habe ich noch keinen Aufruf gesehen, der nur einen Tab öffnet, nachdem ein Klick aufgerufen wurde, wenn das Javascript auf der Website ein neues Fenster erstellt.
Ben
Ich habe mich geirrt und meinen Kommentar gelöscht. Sie können Ihre Antwort auch löschen.
Elmue
3

Ändern Sie die Registrierung für IE:

ie_x64_tabprocgrowth.png

  1. HKEY_CURRENT_USER \ Software \ Microsoft \ Internet Explorer \ Main
  2. Klicken Sie mit der rechten Maustaste → Neu → Zeichenfolgenwert → Wertname: TabProcGrowth (erstellen, falls nicht vorhanden)
  3. TabProcGrowth (Rechtsklick) → Ändern ... → Wertdaten: 0

Quelle: Problem beim Umschalten von Selenium WebDriver-Fenstern in Internet Explorer 8-10

In meinem Fall hat der IE nach der Bearbeitung der Registrierung begonnen, neue Fensterhandles zu erkennen.

Entnommen aus dem MSDN-Blog:

Tab-Prozesswachstum: Legt die Rate fest, mit der der IE neue Tab-Prozesse erstellt.

Der "Max-Number" -Algorithmus: Dies gibt die maximale Anzahl von Registerkartenprozessen an, die für eine einzelne Isolationssitzung für einen einzelnen Frame-Prozess auf einer bestimmten obligatorischen Integritätsstufe (MIC) ausgeführt werden können. Relative Werte sind:

  • TabProcGrowth = 0: Registerkarten und Frames werden im selben Prozess ausgeführt. Frames sind nicht über MIC-Ebenen hinweg einheitlich.
  • TabProcGrowth = 1: Alle Registerkarten für einen bestimmten Frame-Prozess werden in einem einzelnen Registerkartenprozess für eine bestimmte MIC-Ebene ausgeführt.

Quelle: Durch Öffnen einer neuen Registerkarte wird möglicherweise ein neuer Prozess mit Internet Explorer 8.0 gestartet


Internet Optionen:

  • Sicherheit → Deaktivieren Sie " Geschützten Modus aktivieren" für alle Zonen (Internet, lokales Intranet, vertrauenswürdige Sites, eingeschränkte Sites).
  • Erweitert → Sicherheit → Deaktivieren Sie den erweiterten geschützten Modus aktivieren

Code:

Browser: IE11 x64 (Zoom: 100%)
Betriebssystem: Windows 7 x64
Selen: 3.5.1
WebDriver: IEDriverServer x64 3.5.1

public static String openWindow(WebDriver driver, By by) throws IOException {
String parentHandle = driver.getWindowHandle(); // Save parent window
WebElement clickableElement = driver.findElement(by);
clickableElement.click(); // Open child window
WebDriverWait wait = new WebDriverWait(driver, 10); // Timeout in 10s
boolean isChildWindowOpen = wait.until(ExpectedConditions.numberOfWindowsToBe(2));
if (isChildWindowOpen) {
    Set<String> handles = driver.getWindowHandles();
    // Switch to child window
    for (String handle : handles) {
        driver.switchTo().window(handle);
        if (!parentHandle.equals(handle)) {
            break;
        }
    }
    driver.manage().window().maximize();
}
return parentHandle; // Returns parent window if need to switch back
}



/* How to use method */
String parentHandle = Selenium.openWindow(driver, by);

// Do things in child window
driver.close();

// Return to parent window
driver.switchTo().window(parentHandle);

Der obige Code enthält eine If-Prüfung, um sicherzustellen, dass Sie nicht zum übergeordneten Fenster wechseln, da Set<T>in Java keine garantierte Reihenfolge besteht . WebDriverWaitscheint die Erfolgschance zu erhöhen, wie durch die folgende Aussage gestützt.

Zitat aus Luke Inman-Semerau : (Entwickler für Selen)

Es kann einige Zeit dauern, bis der Browser das neue Fenster bestätigt, und Sie fallen möglicherweise in Ihre switchTo () -Schleife, bevor das Popup-Fenster angezeigt wird.

Sie gehen automatisch davon aus, dass das letzte von getWindowHandles () zurückgegebene Fenster das zuletzt geöffnete ist. Dies ist nicht unbedingt der Fall, da nicht garantiert wird, dass sie in beliebiger Reihenfolge zurückgegeben werden.

Quelle: Ein Popup im IE kann nicht verarbeitet werden. Die Steuerung wird nicht in das Popup-Fenster übertragen


Zusammenhängende Posts:

Silber
quelle
2

Du könntest benutzen:

driver.SwitchTo().Window(WindowName);

Wobei WindowName eine Zeichenfolge ist, die den Namen des Fensters darstellt, auf das Sie den Fokus wechseln möchten. Rufen Sie diese Funktion erneut mit dem Namen des ursprünglichen Fensters auf, um darauf zurückzugreifen, wenn Sie fertig sind.

Breeze91
quelle
1
Vielen Dank für den Vorschlag. Gibt es eine Möglichkeit, wie ich die Fensternamenmaske festlegen kann? Wie "WinName *", wobei * - ein beliebiges Symbol.
Volodymyr Prysiazhniuk
1
Meine implizite ist 10 Sekunden, aber in 2 Sekunden gibt es mir Ausnahme NoSuchWindowException.
Volodymyr Prysiazhniuk
2

Ich benutze Iterator und eine while-Schleife, um die verschiedenen Fenstergriffe zu speichern und dann hin und her zu wechseln.

//Click your link
driver.findElement(By.xpath("xpath")).click();
//Get all the window handles in a set
Set <String> handles =driver.getWindowHandles();
Iterator<String> it = handles.iterator();
//iterate through your windows
while (it.hasNext()){
String parent = it.next();
String newwin = it.next();
driver.switchTo().window(newwin);
//perform actions on new window
driver.close();
driver.switchTo().window(parent);
            }
Status Quo
quelle
Es kann nicht zu neuen Registerkarten gewechselt werden, es werden jedoch Klicks auf die gewünschte neue Registerkarte ausgeführt. Warum?
Paul
Gibt es einen Grund, warum dieser Code dazu führen kann, dass der Test sehr langsam wird? Es scheint, dass es nach diesem Code ungefähr 10 Minuten dauert, um irgendwelche Aktionen im newwin auszuführen
Hugo
0
 main you can do :

 String mainTab = page.goToNewTab ();
 //do what you want
 page.backToMainPage(mainTab);  

 What you need to have in order to use the main   

        private static Set<String> windows;

            //get all open windows 
            //return current window
            public String initWindows() {
                windows = new HashSet<String>();
                driver.getWindowHandles().stream().forEach(n ->   windows.add(n));
                return driver.getWindowHandle();
            }

            public String getNewWindow() {
                List<String> newWindow = driver.getWindowHandles().stream().filter(n -> windows.contains(n) == false)
                        .collect(Collectors.toList());
                logger.info(newWindow.get(0));
                return newWindow.get(0);
            }


            public String goToNewTab() {
                String startWindow = driver.initWindows();
                driver.findElement(By.cssSelector("XX")).click();
                String newWindow = driver.getNewWindow();
                driver.switchTo().window(newWindow);
                return startWindow;
            }

            public void backToMainPage(String startWindow) {
                driver.close();
                driver.switchTo().window(startWindow);
            }
Ran Adler
quelle
0

Das Problem bei vielen dieser Lösungen ist also, dass Sie davon ausgehen, dass das Fenster sofort angezeigt wird (nichts passiert sofort und die Dinge passieren im IE deutlich weniger sofort). Außerdem gehen Sie davon aus, dass vor dem Klicken auf das Element nur ein Fenster angezeigt wird, was nicht immer der Fall ist. Außerdem gibt der IE die Fensterhandles nicht in einer vorhersehbaren Reihenfolge zurück. Also würde ich folgendes tun.

 public String clickAndSwitchWindow(WebElement elementToClick, Duration 
    timeToWaitForWindowToAppear) {
    Set<String> priorHandles = _driver.getWindowHandles();

    elementToClick.click();
    try {
        new WebDriverWait(_driver,
                timeToWaitForWindowToAppear.getSeconds()).until(
                d -> {
                    Set<String> newHandles = d.getWindowHandles();
                    if (newHandles.size() > priorHandles.size()) {
                        for (String newHandle : newHandles) {
                            if (!priorHandles.contains(newHandle)) {
                                d.switchTo().window(newHandle);
                                return true;
                            }
                        }
                        return false;
                    } else {
                        return false;
                    }

                });
    } catch (Exception e) {
        Logging.log_AndFail("Encountered error while switching to new window after clicking element " + elementToClick.toString()
                + " seeing error: \n" + e.getMessage());
    }

    return _driver.getWindowHandle();
}
Dominic Giallombardo
quelle
-1

Wenn Sie mehr als einen Browser haben (mit Java 8)

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class TestLink {

  private static Set<String> windows;

  public static void main(String[] args) {

    WebDriver driver = new FirefoxDriver();
    driver.get("file:///C:/Users/radler/Desktop/myLink.html");
    setWindows(driver);
    driver.findElement(By.xpath("//body/a")).click();
    // get new window
    String newWindow = getWindow(driver);
    driver.switchTo().window(newWindow);

    // Perform the actions on new window
    String text = driver.findElement(By.cssSelector(".active")).getText();
    System.out.println(text);

    driver.close();
    // Switch back
    driver.switchTo().window(windows.iterator().next());


    driver.findElement(By.xpath("//body/a")).click();

  }

  private static void setWindows(WebDriver driver) {
    windows = new HashSet<String>();
    driver.getWindowHandles().stream().forEach(n -> windows.add(n));
  }

  private static String getWindow(WebDriver driver) {
    List<String> newWindow = driver.getWindowHandles().stream()
        .filter(n -> windows.contains(n) == false).collect(Collectors.toList());
    System.out.println(newWindow.get(0));
    return newWindow.get(0);
  }

}
Ran Adler
quelle