Как перейти в новое окно браузера, которое открывается после нажатия на кнопку?

86

У меня ситуация, когда при нажатии на кнопку открывается новое окно браузера с результатами поиска.

Есть ли способ подключиться и сосредоточиться в новом открытом окне браузера?

И поработайте с ним, затем вернитесь в исходное (первое) окно.

Владимир Присяжнюк
источник
Мы можем сделать переключение автоматически - проверьте здесь расширенное использование - testautomationguru.com/…
vins

Ответы:

117

Вы можете переключаться между окнами, как показано ниже:

// 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)
Сурья
источник
3
Я могу подтвердить, что принятое решение постоянно работает в Chrome, но не в IE. Новый дескриптор окна не распознается в IE. @Elmue неверен, потому что getWindowHandles()возвращает Set, а Set не гарантирует упорядочение . Последний элемент не всегда является последним окном. Я удивлен, что его комментарий получил много положительных отзывов.
серебро
@silver: Понятия не имею, о чем вы говорите. В моем коде WindowHandles возвращает ReadOnlyCollection <string>, для которого я могу гарантировать, что последняя запись всегда является последним открытым окном. Я это проверил. Если это отлично работает в C #, но неправильно реализовано в Java, вы должны сообщить об этом как об ошибке.
Elmue
@Elmue Это поток Java. Прочтите ответ Люка (разработчика Selenium) относительно getWindowHandles(). Это известное поведение (не ошибка) метода и, в частности, Java Set <T>. Следовательно, switchTo().window(handles[handles.length-1])в Java это не гарантируется. Решение AC # не может считаться правильным.
серебро
5
@Elmue В третий (и последний) раз ваш ответ неверен для Java, поскольку это поддерживается документами и разработчиками, которые могут ЗАМЕТАТЬ людей. Отправьте ответ, где вы говорите, что он для C #, без проблем. Поднимите карточку проблемы в GitHub для Java, вперед. Просто ваш ответ неприменим для языка, помеченного в ветке, и люди могут подумать иначе. Если вы не можете провести различие, значит, вам не хватает понимания.
серебро
3
@Elmue Кстати, вы тоже ошибаетесь, говоря, что driver.close () закрывает оба окна. Он только замыкает ток. driver.quit () убивает все экземпляры. Я вижу, что кто-то уже указал вам на это. Ваш комментарий полон ошибок. Хорошего дня.
серебро
12

Просто чтобы добавить к содержанию ...

Чтобы вернуться в главное окно (окно по умолчанию).

использовать driver.switchTo().defaultContent();

Амарнатх Райуду
источник
11

Этот скрипт поможет вам переключиться с родительского окна на дочернее окно и обратно cntrl в родительское окно.

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
          }
       }
Прашант Самс
источник
1
driver.close () будет работать в новом окне. Если это новая вкладка, используйте код, чтобы закрыть новую вкладку: driver.findElement (By.cssSelector ("body")). SendKeys (Keys.CONTROL + "w");
Рипон Аль Васим
4

Сурья, твой способ не сработает по двум причинам:

  1. нельзя закрыть драйвер во время оценки теста, так как он потеряет фокус перед переключением на активный элемент, и вы получите NoSuchWindowException.
  2. если тест запущен на ChromeDriver, вы получите не окно, а вкладку при нажатии в вашем приложении. Поскольку SeleniumDriver не может работать с вкладками , только переключается между окнами, он зависает при щелчке там, где открывается новая вкладка, и аварийно завершает работу по истечении времени ожидания.
Invy
источник
1
Фактически вы можете использовать вызов driver.close (), поскольку вы переключаете дескрипторы окон в драйвере и вызываете окно, в котором вы сейчас находитесь, для закрытия. Я регулярно использую его в своем коде при работе с несколькими окнами. driver.Quit () - это вызов, который завершит тест. В Chromedriver вы все еще можете вызвать getWindowHandles (), чтобы получить список доступных окон. Я не могу придумать причину использовать вкладку в веб-тесте.
Бен
@Elmue В исходном вопросе говорилось, что щелчок открывает второе окно, создавая несколько дескрипторов окон. Я могу вызвать driver.close (); и закрыть мое окно, в котором в настоящее время находится фокус. Затем я могу переключиться на любое другое активное окно по своему выбору. driver.close () и driver.quit () не имеют одинаковых функций. Вызов driver.quit () убивает активный экземпляр драйвера, тогда как close убивает только текущий дескриптор окна. Кроме того, я еще не видел ни одного вызова, который открывал бы вкладку только после того, как щелчок вызывается, когда javascript на веб-сайте создает новое окно.
Бен
Я ошибся и удалил свой комментарий. Вы тоже можете удалить свой ответ.
Elmue
3

Измените реестр для IE:

ie_x64_tabprocgrowth.png

  1. HKEY_CURRENT_USER \ Программное обеспечение \ Microsoft \ Internet Explorer \ Главная
  2. Щелкните правой кнопкой мыши → Создать → Строковое значение → Имя значения: TabProcGrowth (создать, если не существует)
  3. TabProcGrowth (щелкните правой кнопкой мыши) → Изменить ... → Значение данных: 0

Источник: проблема переключения окон Selenium WebDriver в Internet Explorer 8-10

В моем случае IE начал обнаруживать новые дескрипторы окон после редактирования реестра.

Взято из блога MSDN:

Рост процесса вкладки: устанавливает скорость, с которой IE создает процессы новой вкладки.

Алгоритм «Max-Number»: определяет максимальное количество процессов вкладки, которые могут быть выполнены для одного сеанса изоляции для одного процесса кадра на определенном обязательном уровне целостности (MIC). Относительные значения:

  • TabProcGrowth = 0: вкладки и фреймы выполняются в одном процессе; кадры не унифицированы по уровням MIC.
  • TabProcGrowth = 1: все вкладки для данного процесса кадра запускаются в одном процессе вкладок для заданного уровня MIC.

Источник: открытие новой вкладки может запустить новый процесс в Internet Explorer 8.0.


Настройки интернета:

  • Безопасность → Снимите флажок Включить защищенный режим для всех зон (Интернет, Местная интрасеть, Надежные сайты, Ограниченные сайты)
  • Дополнительно → Безопасность → Снимите флажок Включить расширенный защищенный режим

Код:

Браузер: IE11 x64 (Zoom: 100%)
ОС: 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);

Приведенный выше код включает if-check, чтобы убедиться, что вы не переключаетесь на родительское окно, так как Set<T>не имеет гарантированного порядка в Java .WebDriverWaitкак представляется, увеличивает шансы на успех, что подтверждается приведенным ниже утверждением.

Цитата из Люка Инман-Семерау : (Разработчик Selenium)

Браузеру может потребоваться время, чтобы подтвердить новое окно, и вы можете попасть в цикл switchTo () до того, как появится всплывающее окно.

Вы автоматически предполагаете, что последнее окно, возвращаемое getWindowHandles (), будет последним открытым. Это не обязательно так, поскольку их возврат в любом порядке не гарантируется.

Источник: невозможно обработать всплывающее окно в IE, управление не передается во всплывающее окно


Похожие сообщения:

Серебряный
источник
2

Вы можете использовать:

driver.SwitchTo().Window(WindowName);

Где WindowName - это строка, представляющая имя окна, на которое вы хотите переключить фокус. Вызовите эту функцию еще раз с именем исходного окна, чтобы вернуться к нему, когда закончите.

Бриз91
источник
1
спасибо за предложение, есть ли способ установить маску имени окна? Как "WinName *", где * - любой символ.
Владимир Присяжнюк,
1
У меня неявно 10 секунд, но через 2 секунды это дает мне исключение NoSuchWindowException.
Владимир Присяжнюк,
2

Я использую итератор и цикл while для хранения различных дескрипторов окон, а затем переключаюсь туда и обратно.

//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);
            }
Статус кво
источник
Он не может переключиться на новые вкладки, однако он выполняет щелчки по желаемой новой вкладке. Зачем?
Пол
есть ли причина, по которой этот код может привести к очень медленному тестированию? Похоже, что после этого фрагмента кода для выполнения каких-либо действий в newwin требуется около 10 минут
Хьюго
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);
            }
Ран Адлер
источник
0

Таким образом, проблема со многими из этих решений заключается в том, что вы предполагаете, что окно появляется мгновенно (ничего не происходит мгновенно, а в IE все происходит значительно реже). Также вы предполагаете, что до щелчка по элементу будет только одно окно, что не всегда так. Также IE не будет возвращать дескрипторы окон в предсказуемом порядке. Итак, я бы сделал следующее.

 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();
}
Доминик Джалломбардо
источник
-1

Если у вас более одного браузера (с использованием 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);
  }

}
Ран Адлер
источник