Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Chromedriver не всегда переключается на другое окно и не видит кнопки

chrome
webdriver
Теги: #<Tag:0x00007f7b6491d930> #<Tag:0x00007f7b6491d728>

#1

Переключаюсь командой
for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle);}
но хром не всегда переключается. Дожидаюсь значения тайтла:
waitDriver.until(ExpectedConditions.titleIs(“new title”));
Но, как я понял, если webdriver не переключается на окно, он остается в прежнем окне и дожидается заголовка в том же окне, а не в новом.
В итоге получаю:
Timed out after 10 seconds waiting for title to be “new titile”. Current title: “old titile”. Непонятно почему он это делает не каждый раз, но постоянно.


(Дмитрий Нечаев) #2

Поставь банальный sleep потока на 500-1000 милисекунд. Не хороший стиль, но мне помогал


#3

Можно вот так сдеалть!
Я так реализовал!

public boolean clickToOpenInNewWindow() throws Exception {
String windowOrigin = driver.getWindowHandle();
something.click();
sleepALoop(2);

for (String window : driver.getWindowHandles()) {
    if (!window.equals(windowOrigin)) {
        driver.switchTo().window(window);
    }
}


if (driver.getCurrentUrl().equals("something")) {
    driver.close();
    driver.switchTo().window(windowOrigin);
    return true;
}

return false  } 

На этот метод я ставлю assert, по этому он boolean, также можно его сделать void и внутри метода делать assert вместо if!
У меня работает как с FF так и с Chrome. C IE не пробывал.


#4

Думал, но хочется более изящного решения. В FF все хорошо работает, а хром чудит.


#5

спасибо, попробую


(Дмитрий Нечаев) #6

aceton41k, попробуйте в таком случае обертку Selenium под названием Selenide. В ней очень просто реализованы методы ожидания события. К примеру: WebElement.shouldBe(visible). Таким образом можно дождаться в вашем примере названия новой страницы и там уже выполнять действия.


#7

интересно, спасибо!


#8

ЧТо это?


#9

sleepAloop - задержка. В твоем случае Thread.sleep(2000)
Использовать Thread.sleep(2000) как то не правильно , можно сделать метод для задержки.

 private void sleepALoop(int seconds) throws InterruptedException {
    for (int c = 0; c < seconds; c++) {
        Thread.sleep(1000);
    }
}

и использовать sleepAloop.


#10

проблема в том, что драйвер не хочет переключаться на окно. Если он не переключился на нужное окно, то становится бесполезно дожидаться элементов, т.к. их уже не будет никогда. Видимо придется использовать цикл в котором проверять, переключился ли драйвер


#11

Покажи код реализации свой в студию


(breakmt) #12

Нужно дожидаться не элементов, а когда количество окон браузера станет больше. И уж тем более не использовать sleep.
Вот как сделал я - отдельный класс WindowsSwitcher, в нем два статик метода: prepareForWindowsSwitch() и switchToNewBrowserWindow(), которые вызываются непосредственно ДО события, которое повлечет открытие нового окна и после него.
Используется ожидалка селенида, но вообще неважно - её легко заменить на WebDriverWait.

public class WindowsSwitcher {

    private static Set<String> oldWindowsHandles;

    public static void prepareForWindowsSwitch() {
        oldWindowsHandles = getWebDriver().getWindowHandles();
    }

    public static void switchToNewBrowserWindow() throws NoSuchWindowException {
        try {
            Selenide.Wait().until(new Predicate<WebDriver>() {
                @Override
                public boolean apply(WebDriver webDriver) {
                    return !getWebDriver().getWindowHandles().equals(oldWindowsHandles);
                }
            });
        } catch (Exception exception) {
            throw new NoSuchWindowException("Новое окно не появилось за время отведенное WebDriverWait!");
        }

        for (String windowHandle : getWebDriver().getWindowHandles()) {
            if (oldWindowsHandles.contains(windowHandle)) {
                switchTo().window(windowHandle);
                getWebDriver().close();
            }
        }

        for (String windowHandle : getWebDriver().getWindowHandles()) {
            if (!oldWindowsHandles.contains(windowHandle)) {
                switchTo().window(windowHandle);
            }
        }

        getWebDriver().manage().window().maximize();
    }

}


#13

Сейчас переключаюсь вот так

 while (!driver.getTitle().equals("title")) {
    for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle);}
}

В основном у меня не работают клики. Хром либо нажимает на кнопку, которая еще как бы не совсем кнопка, либо он промахивается и пишет что другой элемент получил клик. Есть пока вот такой метод

public static void chromeClick(WebDriver driver, String xpath) throws InterruptedException {
    WebDriverWait waitDriver = new WebDriverWait(driver, 5);
    waitDriver.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
    waitDriver.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
    driver.findElement(By.xpath(xpath)).click();
}

Заменял click() на javaexecutor click - не помогает. Дожидался различных состояний кнопки, тоже не работает.


#14

Я дожидаюсь нужного заголовка окна, до тех пор я переключаюсь между теми окнами, что есть

 while (!driver.getTitle().equals("title")) {
    for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle);}
}

(breakmt) #15

Ну, значит ваш способ не работает. Ждите появления нового окна и переключайтесь в него. Зачем вам ждать конкретного заголовка?


#16

Согласен. Работай с дискрипторами окон, будет на много проще


#17

Так тема решена или нет! Отпишись, интересно твоё решение!


#18

С переключением решена тем способом, что написал, через ожидание заголовка. Но с нажатием кнопок пока нет. Но я тогда новую тему создам лучше.


#19

Ну так отметь что проблема решена и закрвай тему!


#20

Ок ок, че орать то =)