Jak przejść do nowego okna przeglądarki, które otwiera się po kliknięciu przycisku?

86

Mam sytuację, gdy kliknięcie przycisku otwiera nowe okno przeglądarki z wynikami wyszukiwania.

Czy jest jakiś sposób na połączenie się i skupienie się na nowo otwartym oknie przeglądarki?

Pracuj z nim, a następnie wróć do oryginalnego (pierwszego) okna.

Volodymyr Prysiazhniuk
źródło
Możemy zrobić to automatycznie - sprawdź tutaj zaawansowane użycie - testautomationguru.com/…
vins

Odpowiedzi:

117

Możesz przełączać się między oknami, jak poniżej:

// 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
źródło
3
Mogę potwierdzić, że zaakceptowane rozwiązanie konsekwentnie działa w Chrome, ale nie w IE. Nowa klamka okna nie jest rozpoznawana w IE. @Elmue jest niepoprawne, ponieważ getWindowHandles()zwraca zestaw, a zestaw nie gwarantuje zamówienia . Ostatni element nie zawsze jest ostatnim oknem. Dziwię się, że jego komentarz spotkał się z wieloma pozytywnymi opiniami.
srebrny
@silver: Nie mam pojęcia, o czym mówisz. W moim kodzie WindowHandles zwraca ReadOnlyCollection <string>, dla którego mogę zagwarantować, że ostatni wpis jest zawsze ostatnim otwartym oknem. Przetestowałem to. Jeśli to działa doskonale w C #, ale jest nieprawidłowo zaimplementowane w Javie, powinieneś zgłosić to jako błąd.
Elmue
@Elmue To jest wątek Java. Proszę przeczytać (selen Developer) Luke'a odpowiedzi dotyczącej getWindowHandles(). Jest to znane zachowanie (nie błąd) metody, aw szczególności Java Set <T>. Dlatego switchTo().window(handles[handles.length-1])nie jest gwarantowane w Javie. Nie można twierdzić, że rozwiązanie AC # jest poprawne.
srebrny
5
@Elmue Po raz trzeci (i ostatni) Twoja odpowiedź jest fałszywa w przypadku Javy, ponieważ jest obsługiwana przez dokumentację i programistów, które mogą ZŁĄCZYĆ ludzi. Opublikuj odpowiedź, w której mówisz, że jest przeznaczona dla C #, nie ma problemu. Podnieś kartę problemu w GitHub dla Java, śmiało. Po prostu Twoja odpowiedź nie dotyczy języka OZNACZONEGO w wątku i ludzie mogą myśleć inaczej. Jeśli nie możesz dokonać rozróżnienia, brakuje ci zrozumienia.
srebro
3
@Elmue Nawiasem mówiąc, mylisz się również mówiąc, że driver.close () zamyka oba okna. To tylko zamyka prąd. driver.quit () zabija wszystkie instancje. Widzę, że ktoś już ci to zwrócił. Twój komentarz jest pełen błędów. Miłego dnia.
srebro
12

Wystarczy dodać do treści ...

Powrót do okna głównego (okno domyślne).

posługiwać się driver.switchTo().defaultContent();

Amarnath Rayudu
źródło
11

Ten skrypt pomaga ci przełączać się z okna nadrzędnego do okna podrzędnego iz powrotem cntrl do okna nadrzędnego

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
źródło
1
driver.close () będzie działać w nowym oknie. Jeśli jest to nowa karta, użyj kodu, aby zamknąć nową kartę: driver.findElement (By.cssSelector ("body")). SendKeys (Keys.CONTROL + "w");
Ripon Al Wasim
4

Surya, twój sposób nie zadziała z dwóch powodów:

  1. nie możesz zamknąć sterownika podczas oceny testu, ponieważ straci on fokus przed przełączeniem na aktywny element, a otrzymasz NoSuchWindowException.
  2. jeśli test zostanie uruchomiony na ChromeDriver, nie pojawi się okno, ale karta po kliknięciu w aplikacji. Ponieważ SeleniumDriver nie może działać z kartami , tylko przełącza się między oknami, zawiesza się po kliknięciu w miejscu otwierania nowej karty i ulega awarii po przekroczeniu limitu czasu.
Invy
źródło
1
W rzeczywistości możesz użyć wywołania driver.close (), ponieważ przełączasz klamki okien w sterowniku i wzywasz do zamknięcia okna, w którym aktualnie się znajdujesz. Używam go regularnie w moim kodzie, gdy mam do czynienia z wieloma oknami. driver.Quit () to wywołanie, które zakończy test. W Chromedriver nadal możesz wywołać getWindowHandles (), aby uzyskać listę dostępnych okien. Nie mogę wymyślić powodu, dla którego miałbym używać karty w teście sieciowym.
Ben
@Elmue Pierwotne pytanie mówiło, że kliknięcie otwiera drugie okno, tworząc wiele uchwytów okiennych. Mogę wywołać driver.close (); i zamknij moje okno, na którym aktualnie jest fokus. Mogę wtedy przejść do dowolnego innego wybranego przeze mnie aktywnego okna. driver.close () i driver.quit () nie mają tych samych funkcji. Wywołanie driver.quit () zabije instancję aktywnego sterownika, podczas gdy close zabije tylko bieżącą klamkę okna. Ponadto nie widziałem jeszcze żadnego wywołania, które otwierałoby kartę wyłącznie po wywołaniu kliknięcia, gdy javascript w witrynie tworzy nowe okno.
Ben
Myliłem się i usunąłem swój komentarz. Możesz również usunąć swoją odpowiedź.
Elmue,
3

Zmodyfikuj rejestr dla IE:

ie_x64_tabprocgrowth.png

  1. HKEY_CURRENT_USER \ Software \ Microsoft \ Internet Explorer \ Main
  2. Kliknij prawym przyciskiem myszy → Nowy → Wartość ciągu → Nazwa wartości: TabProcGrowth (utwórz, jeśli nie istnieje)
  3. TabProcGrowth (prawy przycisk myszy) → Modyfikuj ... → Dane wartości: 0

Źródło: Problem z przełączaniem okien Selenium WebDriver w przeglądarce Internet Explorer 8-10

W moim przypadku IE zaczął wykrywać nowe uchwyty okien po edycji rejestru.

Zaczerpnięte z bloga MSDN:

Wzrost procesów kart: Ustawia szybkość, z jaką IE tworzy procesy nowej karty.

Algorytm „Max-Number”: określa maksymalną liczbę procesów kart, które mogą być wykonane dla pojedynczej sesji izolacji dla procesu pojedynczej ramki na określonym obowiązkowym poziomie integralności (MIC). Względne wartości to:

  • TabProcGrowth = 0: karty i ramki działają w ramach tego samego procesu; ramki nie są ujednolicone na poziomach MIC.
  • TabProcGrowth = 1: wszystkie karty dla danego procesu ramki są uruchamiane w pojedynczym procesie karty dla danego poziomu MIC.

Źródło: Otwarcie nowej karty może uruchomić nowy proces w przeglądarce Internet Explorer 8.0


Opcje internetowe:

  • Bezpieczeństwo → Odznacz opcję Włącz tryb chroniony dla wszystkich stref (Internet, Lokalny intranet, Zaufane witryny, Witryny z ograniczeniami)
  • Zaawansowane → Bezpieczeństwo → Odznacz opcję Włącz rozszerzony tryb chroniony

Kod:

Przeglądarka: IE11 x64 (Zoom: 100%)
System operacyjny: Windows 7 x64
Selenium: 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);

Powyższy kod zawiera sprawdzenie, czy nie przechodzisz do okna nadrzędnego, ponieważ Set<T>nie ma gwarantowanej kolejności w Javie . WebDriverWaitwydaje się zwiększać szansę na sukces, co potwierdza poniższe stwierdzenie.

Cytat z Luke Inman-Semerau : (Developer for Selenium)

Potwierdzenie nowego okna przez przeglądarkę może zająć trochę czasu i możesz wpaść w pętlę switchTo (), zanim pojawi się wyskakujące okienko.

Automatycznie zakładasz, że ostatnie okno zwrócone przez getWindowHandles () będzie ostatnim otwartym oknem. Niekoniecznie jest to prawda, ponieważ nie gwarantuje się ich zwrotu w dowolnej kolejności.

Źródło: nie można obsłużyć wyskakującego okienka w IE, kontrola nie przenosi się do wyskakującego okienka


Powiązane posty:

srebro
źródło
2

Możesz użyć:

driver.SwitchTo().Window(WindowName);

Gdzie WindowName to ciąg reprezentujący nazwę okna, na które chcesz przełączyć fokus. Wywołaj tę funkcję ponownie, podając nazwę oryginalnego okna, aby wrócić do niego po zakończeniu.

Breeze91
źródło
1
dziękuję za sugestię, czy jest jakiś sposób, jak mogę ustawić maskę nazwy okna? Na przykład „WinName *”, gdzie * - dowolny symbol.
Volodymyr Prysiazhniuk
1
Moja niejawnie wynosi 10 sekund, ale w ciągu 2 sekund daje mi wyjątek NoSuchWindowException.
Volodymyr Prysiazhniuk
2

Używam iteratora i pętli while do przechowywania różnych klamek okiennych, a następnie przełączam się tam iz powrotem.

//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);
            }
StatusQuo
źródło
Nie można przełączyć się na nowe karty, ale wykonuje kliknięcia na żądanej nowej karcie. Czemu?
paul
czy jest jakiś powód, dla którego ten kod może spowodować spowolnienie testu? Wygląda na to, że po tym fragmencie kodu zajmie około 10 minut wykonanie jakichkolwiek czynności w newwin
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
źródło
0

Więc problem z wieloma z tych rozwiązań polega na tym, że zakładasz, że okno pojawia się natychmiast (nic nie dzieje się natychmiast, a rzeczy dzieją się znacznie rzadziej w IE). Zakładasz również, że przed kliknięciem elementu będzie tylko jedno okno, co nie zawsze ma miejsce. IE nie zwróci również klamek okien w przewidywalnej kolejności. Więc zrobiłbym co następuje.

 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
źródło
-1

Jeśli masz więcej niż jedną przeglądarkę (używając 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
źródło