Все же закрыть другие окна нужно, так как есть определенные действия на странице, которые могут не сработать, если окно не в фокусе, например всяческие обработчики, навешанные на события перерисовки, браузер просто не будет их взвывать, если окно не в фокусе.
Такое решение будет работать в большинстве случаев, но не всегда. Так как список окон, который возвращает window_handles это неупорядоченный список (set), и в нем совсем не гарантируется то, что новые окна будут отсортированы в порядке появления и иметь соответствующие индексы, особенно в ситуациях, когда уже есть открытые окна. Но такие ситуации к счастью довольно редки.
А это надо заменить на явное ожидание:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
wait = WebDriverWait(driver, 10)
wait.until(ec.new_window_is_opened(old_windows))
#или
wait.until(ec.number_of_windows_to_be(3)) # 2,1 etc.
Я что-то не пойму тут. Что значит вот это?
wait.until(ec.new_window_is_opened(old_windows))
или это
wait.until(ec.number_of_windows_to_be(3)) # 2,1 etc.
Я сделал как вы написали. Но буквально на 5 шаге, где мне надо кликнуть по картинке, мой тест падает. Страница с картинкой после логина просто не успевает загрузиться.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//div/*/img"}
Вот пример кода моего теста.
driver = self.driver
wait = WebDriverWait(driver, 10) # ожидание
driver.get(hostname)
window_before = driver.window_handles[0]
wait
driver.find_element(By.XPATH, "//div/input[@name='username']").send_keys(username)
wait
driver.find_element(By.XPATH, "//div/input[@name='password']").send_keys(password)
wait
driver.find_element(By.XPATH, "//div/input[@name='code']").send_keys(code)
wait
driver.find_element(By.XPATH, "//em/button[@type='button']").click()
wait
driver.find_element(By.XPATH, "//div/*/img").click()
wait
driver.find_element(By.XPATH, "//div/div[contains(text(), 'Оператор')]").click()
wait
Хехе. Я попробовал сделать по инструкции и немного запутался. может вы сможете помочь.
driver = self.driver
wait = WebDriverWait(driver, 10)
driver.get(hostname)
window_before = driver.window_handles[0]
wait.until(lambda driver: driver.find_element(By.XPATH, "//div/input[@name='username']").send_keys(username)) #измененный вариант по документации
driver.find_element(By.XPATH, "//div/input[@name='password']").send_keys(password)
Во время прохождения теста, он не переходит ко второму шагу - ввода пароля, а застревает на первом и 10 секунд вводит логин в поле логин.
Что я делаю не так?
В итоге сделал вот так
driver = self.driver
wait = WebDriverWait(driver, 10)
driver.get(hostname)
window_before = driver.window_handles[0]
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div/input[@name='username']")))
element.send_keys(username)
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div/input[@name='password']")))
element.send_keys(password)
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div/input[@name='code']")))
element.send_keys(code)
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//em/button[@type='button']")))
element.click()
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div/*/img")))
element.click()
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div/div[contains(text(), 'Оператор')]")))
element.click()
И тест падает на том же самом месте когда надо кликнуть по картинке, со слипами такого не происходит.
У вас там ajax случаем нет? Ну и увас слишком много вейтов. Выберите что-то одно, что дольше всех грузится. После него и начинайте искать элементы. С каким эксепшеном падает тест?
Это extjs. Сначала появляется форма входа - я ввожу логин, пароль и т.д. Затем грузится страница после логина и там мне в главном меню надо перейти на другую страницу. Главное меню это раскрывающийся список. Я его открываю при помощи нажатия на “стрелочку вниз” - по xpath это обычная картинка (By.XPATH, “//div/*/img”). Если я ставлю sleep и затем кликаю по картинке, то все норм и все открывается. А в предыдущей реализации он мне пишет
Message: unknown error: Element <img src="extjs3.3/resources/images/default/s.gif"> is not clickable at point (319, 20)
Почему получается, что при sleep я жду когда страница откроется после логина и он нормально кликает, а при waits он мне пишет, что элемент не кликабельный.
Вам нужно дожидаться завершения ajax’а. Как это сделать с extjs, я вам не подскажу. Для jQuery делается как-то так:
@staticmethod
def wait_for_ajax(_type, _locator, timeout=5):
message = "Element '%s' was not visible in %s second(s)." % (_locator, str(timeout))
driver = SeleniumWrapper().driver
wait = WebDriverWait(driver, timeout)
wait.until(EC.element_to_be_clickable(_type, _locator)
and driver.execute_script("return $.active") == 0, message=message)
Уу-у-у это уже уровень. Посижу подумаю. А пока буду использовать sleep.
Ну просто поищите элемент который грузится позже всех, не обязательно его использовать, просто привяжите к нему ожидание.
)) А где можно посмотреть какой элемент грузится позже всего на странице?
Глазами или через инструменты разработчика )
Может просто у вас есть опыт отслеживания таких элементов, поделитесь пожалуйста.
Я же говорю, либо на глаз, либо откройте инструменты разработчика и смотрите на вкладке Network какие запросы куда идут и в какой последовательности. Еще лучше спросить у разработчиков, они смогут подсказать более точно.
А почему никто не пользует PyAutoGUI · PyPI ?
Крутая библа же, проста как 3 копейки. Эмуляция набора с клавиатуры и действия мыши. Реализовываю работу с всплывающими окнами
Прикольно, а вы сами используете? Можете показать какой-нибудь пример? Кусок кода?
Помогите что делать если в моем случае Как отрыть новую вкладку с определенным url в фоном режиме (приложение самое ничего не открывает) - #12 от пользователя Tatyana_Durova пожалуйста!