Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @Override
- public boolean is(Condition<WebElement> condition) {
- try {
- return condition.check(getWrappedEntity());
- } catch (NullPointerException ex) {
- throw new ElementNotFoundException(this.toString());
- }
- }
- /*
- не, Null Pointer Exception - ловить не стоит)
- это bad practice
- да нам это и не нужно - см ниже
- https://www.quora.com/Is-it-bad-practice-to-catch-null-pointer-exceptions-in-Java
- http://stackoverflow.com/questions/4716353/if-catching-null-pointer-exception-is-not-a-good-practice-is-catching-exception
- */
- *****************************************
- public <V> V until(Condition<V> condition, long timeout){
- ...
- do {
- try {
- ...
- } catch (WebDriverException | IndexOutOfBoundsException ex) {
- ...
- /*
- в WaitFor#until - мы ловим лишь WebDriverException и нам этого достаточно
- собственно - это же - WebDriverException - и в is нужно ловить
- IndexOutOfBoundsException - уже ловить не нужно
- мы же словили это в LazyCollectionNthElement и вместо этого бросили свой эксепшен-потомок WebDriverException
- так что - ловим только WebDriverException
- и тут, и в is
- если при использовании is - возникает NullPointerException - то надо искать источник
- */
- ***********************************************
- public abstract class AbstractLazyElement implements LazyElement {
- ...
- @Override
- public WebElement getWrappedEntity() {
- ...
- throw new ElementNotFoundException();
- ...
- /*
- не забывай - везде где бросаешь исключения
- передавай в конструктор исключения строку - полезную информацию
- я писала - лучше this.toString() что-то сложно придумать
- не throw new ElementNotFoundException();
- а throw new ElementNotFoundException(this.toString());
- тогда - при возникновении такого исключения
- в сообщении об ошибке будет фигурировать и полезное сообщение
- тут - это описание нашего лейзи элемента
- */
- ***************************************************
- public class LazyCollectionFoundByConditionElement extends AbstractLazyElement {
- ...
- @Override
- public String toString() {
- return parentCollection.getClass().getSimpleName() + " find(" + condition.getClass().getSimpleName() + ")";
- }
- /*
- вот для кондишена - и правда - тут уместнее condition.getClass().getSimpleName()
- почему это лучше в данном случае чем condition.toString() - посмотри на реализацию condition.toString() -
- нам в данном случае это только усложнило бы выражение
- а вот для parentCollection - лучше использовать toString()
- именно toString() для родительской коллекции - опишет нормально - как получена эта коллекция
- а имя класса коллекции - никому особо не поможет
- чтоб увидеть - насколько полезно сообщение - моделируй ситуацию
- для элемента/коллекции нужного вида - выполни проверку
- которая заведомо должна упасть
- и смотри на описание ошибки
- и сам кондишен
- и лейзи-сущность - для которой эта проверка вызывалась -
- все это должно быть описано понятно и достаточно
- то же касается и LazyFilteredCollection
- */
- ************************************
- public class LazyWebDriverElement extends AbstractLazyElement {
- ....
- @Override
- public String toString() {
- return "WebElement by locator " + locator;
- }
- /*
- я бы использовала только locator
- то же самое - посмотри на сообщение об ошибке
- и аналогично - LazyWebDriverCollection
- */
- **********************************
- public class CssClass extends ElementCondition{
- public Boolean actualState;
- public String expectedClass;
- ....
- @Override
- public String expected() {
- return "True";
- }
- @Override
- public String actual() {
- return String.valueOf(actualState);
- }
- }
- /*
- тут в expected() - правильнее сообщить expectedClass
- а в actual() - actual класс
- тут - бесполезно оперировать категориями да-нет
- в данном случае - это скрывает важные детали
- категории да-нет - хороши там, где больше и нету подробностей
- а тут они есть
- */
- **************************************************
- public abstract class ElementCondition extends AbstractCondition<WebElement> {
- }
- /*
- мне кажется, я это писала
- в общем-то - можно обойтись без этого класса
- т к сейчас - в реализации класса - кода нет
- и класс используется только как предок для кондишенов
- в принципе - наследовать кондишены можно и от AbstractCondition<WebElement>
- и тогда не потребуется класс ElementCondition
- CollectionCondition - аналогично
- */
- ***************************************
- public class NthElementText extends CollectionCondition
- /*
- этот кондишен уже не нужен
- кондишена text - достаточно
- будем оперировать $$(...).get(...).shouldHave(text(...))
- */
- ****************************************
- public class Texts extends CollectionCondition {
- /*
- а вот тут - еще бы и exactTexts не помешал бы )
- реализуй
- можно отнаследоваться от Texts
- */
- *************************************************
- public abstract class Load<T, V> {
- /*
- Вариант рабочий, и делает то, что нам нужно
- но - сложный
- и нарушает принцип Single Responsibility Principle
- у нас будет класс WithWaitFor (например)
- в конструктор которого передадим
- лейзи-элемент
- кондишен
- и у этого класса - будет метод run (например)
- метод в качестве параметра - получит объект-команду
- и вернет значение некого типа (тут нам пригодятся дженерики - т к нам нужны результаты разных типов,
- заостряю внимание - это работаем с дженерик-типом - на уровне метода run)
- именно в этом методе -
- мы сначала пытаемся выполнить команду над вебэлементом
- полученным без жлущей проверки
- и если возникнут проблемы - сначала выполним ждущую проверку
- и затем - выполним команду
- что до объекта-команды
- это как раз то, что мы будем реализовывать как объекты анонимного класса
- все эти объекты - будут имплементировать один интерфейс (например Command)
- а в интерфейсе - мы объявляем метод run (например)
- в реализации которого
- мы будем выполнять нужные действия
- и возвращать нужное нам значение
- действия будут совершаться над вебэлементом
- потому - вебЭлемент - будет параметром этого метода
- потому и на уровне этого интерфейса - мы будем оперировать дженерик-типом
- чтобы задать - значение какого типа вернет метод run
- параметров методу run не нужно
- благодаря тому - что мы воспользуемся объектами анонимного класса
- (см прошлую информацию)
- приведу пример - что получим с внешней стороны
- */
- public LazyElement setValue(final String text) {
- new WithWaitFor(this, visible()).run(new Command<WebElement>() {
- public WebElement run(WebElement element) {
- element.clear();
- element.sendKeys(text);
- return element;
- }
- });
- return this;
- }
- /*
- заметь - когда нам безразлично - что возвращать - мы возвращаем WebElement - в методе WithWaitFor#run
- (и в методе команды - тоже)
- что нам даст такой подход
- у нас логика команды и логика запускателя команды - будут реализованы в разных классах
- каждый из которых - будет отвечать за свое
- */
Advertisement
Add Comment
Please, Sign In to add comment