Ребят, такая проблема - в апликации которую тестирую есть модуль для ввода данных о пользователе и при этом можно создать несколько модулей с разными пользователями, при этом модуль будет просто клонироваться. Так вот -
надо сначало ввести данные в первый модуль о пользователе Х
затем создать новый модуль для пользователя Y, при этом старый модуль будет спрятан за новым модулем, но всё ещё будет находиться в DOM.
ввести данные для пользователя в новом модуле
Естественно, на эти модуль у меня один page object и когда я пытаюсь ввесту данные в новый модуль то селениум вылетает с ошибкой ElementNotVisible. Полагаю что webdriver в момент взаимодействия с новым модулем хранит в себе ссылку на первый модуль, который в свою очередь скрыт за новым модулем.
Пробовал явно вызвать инициализацию новых елементов в новом модуле, но не помогло.
Поддерживаю, с моей точки зрения лучше хранить final static поля типа By в классе пейдж обжекта, а затем использовать их в методах этого пейдж обжекта (исп. например Selenide и его краткие $ и $$)
Ничего не зло) У нас на странице добавился новый элемент(пусть он такой же, как и уже существующий, это не важно), а объекта в тесте для него нет. Чего ж тут хотеть?
Тут я вижу два наиболее логичных объяснения:
Создать новый объект для нового диалога
Модифицировать ваш Page Object так, что бы он работал только с тем объектом, поля которого visible
Идеологически правильный первый вариант. Для работы более удобный второй. Исходите от своих задач.
Я имплементировал динамическую инициализацию элементов. Т.е. тот или иной элемент будет искаться на странице перед выполнение какого либо действия над ним. Это решило все мои подобные проблемы.
100500 раз обсуждалось, ответ кроется в вашем вопросе.
Page Object элемент, это описание страничных/интерфейсных моделей которые вы видите на ДАННЫЙ момент. и каждый PG объект это есть конечная модель ОДНОГО элемента, или же композиция PG показывающая сложный элемент (вся страница например)
Тогда элеменыт второго уровня объявляются атрибутами/методами, а при обращении к ним используется дексриктор, который следит - а на этой ли я странице (в питоне, хватает засунуть проверку в init, если ты не на той странице - класс не инициализируется и ты вывалишься сразу). Второе, переход между PG, осуществляется только при изменении текущего состояния страницы. К примеру, вызов окна нового письма нельзя считать переходом PG, потому что основное доступно - это просто переход между элементами, и вот когда вы на элементе, вы должны инициализить эту часть PG и следить, что:
пока я вижу скажем татл этого окна, я могу обращаться к элементам этого окна, если тайтл пропал - я где то в другом месте.
Для слежения за элементами, очень подходит тулзы от selenium, которые возвращают статус элемента по его состоянию (выделен, виден, кликабелен и т.д)
У меня в фреймворке есть Core пакет, где у меня ядро всего что нужно. В этом пакете есть WebPage and WebItem основные классы, в которых храняться все основные инструменты управление.
Все элементы страницы у меня класифицированы и разделены на Кнопки, ПопапЛисты, Грид и т.д., которые в свою очередь унаследованы от WebItem. Это позволяет мне иметь набор тех или иных уникальных методов для каждого типа отдельно.
Так вот в WebItem классе, у меня есть конструктор, который я использую что бы присвоить внутреннему полю объекта “By byId;” значение из @FindBy() аннотации, которое я вынимаю в конструкторе страницы класса WebPage используя reflection. На этом создание объекта страницы и инициализация его полей заканчиваеться. Т.е. я не ищу сразу елементы аля Driver.findElement при создании объкта страницы, а я просто запоминаю идетнификаторы этих элементов внутри их объектов в приватных полях.
После, когда мне нада сделать click(), sendKeys() и т.д., я вызываю getItem() метод внутри переписаных методов click(), sendKeys() в WebItem классе, где и происходит реальный поиск элемента. Конечно это все дополнено explicit and implicit вейтами, что бы элемент был в нужном состоянии, и что бы страница прогрузилась.
Таким образом мне пофик что проиходит со страницой во время выполнения скрипта, и я уверен что действие выполниться на 100%, не зависимо от обновления DOM структуры страницы.
Простите если что не так написал, но я решал свои проблемы по мере их поступления. Пока что доволен. Кстати быстродействие из-за этого тоже выросло, так как в обьектах страницы не храняться все обьекты WebElement постоянно, а инициализируються только те, что нужны в конкретном тесте.
В классе PG (или блока элементов) храним поля типа By (константы, static)
Там где нужно (в методах класса) юзаем к примеру Селенид: $(LOGIN_BUTTON).click();
Немного не по теме, но вдруг кто не знает:
Если вдруг приспичило найти элемент через цепочку предшествующих и не хочется городить .findElement().findElement()…etc , то берем наши константы типа By и объединяем в ByChained chain = new ByChained (GRANDPA_ELEMENT, FATHER_ELEMENT, SON_ELEMENT);
Локатор chain передаем куда нужно ( в findElement или селенидовский $/$$)