Множественный выбор после нажатия кнопки

Здравствуйте!

У меня возникла такая проблема. После заполнения формы нового пользователя и нажатия на кнопку “Сохранить” может быть 2 разных дальнейших сценария:

  • Пользователь с таким ФИО уже существует.
  • Создался новый пользователь.

Если брать первый сценарий, то после нажатия на кнопку “Сохранить” появляется небольшой alert, который состоит из заголовка - “Внимание!” Описания - “пользователь с ФИО xxx уже существует. Продолжить?” и кнопками - “Да” и “Отменить”.

Если брать второй сценарий, то после нажатия на кнопку “Сохранить” появляется небольшой alert, который состоит из заголовка - “Информация”. Описание - “данные пользователя сохранены” и кнопкой - “Ок”.

Задача такая - независимо от сценария - нажать кнопку “Да” или “Ок”. Я решил использовать инструкцию if, а распознавать разные алерты при помощи xpath по заголовку алерта.

self.driver.find_element(By.XPATH, "//em/button/b[contains(text(), 'Сохранить')]").click()
time.sleep(3)
user_already_exists = self.driver.find_element(By.XPATH, "//*/div/span[contains(text(), 'Внимание')]")
user_new = self.driver.find_element(By.XPATH, "//*/div/span[contains(text(), 'Информация')]")
if user_already_exists.text == "Внимание":
        self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'Да')]").click()
elif user_new.text == "Информация":
        self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'OK')]").click()

Но естественно скрипт не работает. А все потому, что если пользователь уже существует, то появляется ошибка

Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*/div/span[contains(text(), 'Информация')]"}

А если пользователь новый, то

Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*/div/span[contains(text(), 'Внимание')]"}

Скажите, как в таких ситуациях поступают знающие люди? Правильно ли я определяю какой алерт выскочил используя заголовок или это не правильно и есть специальный инструмент для всплывающих окошек? И как мне в принципе решить данную задачку?

Попробуйте конструкцию try- except

Попробовал, но появилась новая ошибка.

selenium.common.exceptions.WebDriverException: Message: chrome not reachable

Код стал таким

from selenium.common.exceptions import NoSuchElementException
        try:
            user_already_exists = self.driver.find_element(By.XPATH, "//*/div/span[contains(text(), 'Внимание')]")
        except NoSuchElementException:
            pass
        try:
            user_new = self.driver.find_element(By.XPATH, "//*/div/span[contains(text(), 'Информация')]")
        except NoSuchElementException:
            pass
        if user_already_exists.text == "Внимание":
            self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'Да')]").click()
        elif user_new.text == "Информация":
            self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'OK')]").click()

Клики нужно перенести в try- except, блок с if ненужен

Блин, попробовал, но теперь он пишет что элемент не виден в случае, если я создаю нового пользователя

ElementNotVisibleException: Message: element not visible

А если создаю уже имеющегося, то все норм

Код теперь такой

        try:
            self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'Да')]").click()
        except NoSuchElementException:
            self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'OK')]").click()

я имел ввиду в этот блок:

try:
            user_already_exists = self.driver.find_element(By.XPATH, "//*/div/span[contains(text(), 'Внимание')]")
        except NoSuchElementException:
            pass
        try:
            user_new = self.driver.find_element(By.XPATH, "//*/div/span[contains(text(), 'Информация')]")
        except NoSuchElementException:
            pass

после проверки алерта вставить сразу клик по нужной кнопке.

я не силен впитоне, на джаве это бы выглядело примерно так:

    try {
            find(By.xpath("//div/span[contains(text(), 'Внимание')]"));
            find(By.xpath( "//em/button[contains(text(), 'Да')]")).click();     
        } catch (NoSuchElementException e) {
            try {
                find(By.xpath("//div/span[contains(text(), 'Информация')]"));
                find(By.xpath("//em/button[contains(text(), 'OK')]")).click();                    
            } catch (NoSuchElementException ex) {
                ex.printStackTrace();
            }
        }

Я сделол) Может кастыльно, но все работает самое главное.

try:
        self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'Да')]").click()
        time.sleep(5)
        self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'OK')]").click()
except ElementNotVisibleException:
        self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'OK')]").click()
self.driver.find_element(By.XPATH, "//*/em/button[contains(text(), 'Закрыть')]").click()
time.sleep(5)
assert_user_creat = self.driver.find_element(By.XPATH, "//*/td/div[contains(text(), 'Тестовый')]").text
space = " "
new_user_fullname = last_name + space + first_name + space + patronymic
assert_equal(assert_user_creat, new_user_fullname)

Используйте
find_elements - этот метод исключение не бросает, если элемент не найден, и возвращает массив из элементов или пустой массив.
А дальше просто: проверяем количество элементов. Если больше 0 - значит есть такой элемент на странице.

3 лайка

А почему бы не написать один локатор, который бы находил нужную кнопку (“ок” или “да”) в любой ситуации. Другими словами объединить два xpath-а в один, а в коде находить этот элемент и кликать по нему - в первом сценарии найдется кнопка “ок” в другом “да” и никаких try-catch-ей не нужно будет.

1 лайк

О, круто, а как это делается? Можете пример показать?

Элементарно:
"//*/em/button[contains(text(), 'Да') or contains(text(), 'OK')]"

1 лайк

Ну, у меня нет HTML-я Вашей страницы, но предположу, что вот так:
//em/button[contains(text(), 'OK') or contains(text(), 'Да')]
Только проверьте ручками предварительно. Может получиться так, что в HTML-e страницы всегда присутствуют обе кнопки, просто одна из них делается видимой в зависимости от сценария.
В таком случае нужно будет усложнить xpath - что-то вроде:
//div[@style=‘display: block’]//em/button[contains(text(), ‘OK’) or contains(text(), ‘Да’)]
Опять-таки это предположение, Вам нужно будет самостоятельно проанализировать и придумать xpath

1 лайк

Спасибо - буду знать. Благодаря вам и проекту каждый день узнаю какие-то новые фичи, меня это радует)

1 лайк

По поводу xPath начни отсюда http://internetka.in.ua/xpath-start-part1/ там 4 статьи…