Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public abstract class ConciseAPI {
- /*
- не с самого примитивного варианта ты начала)
- конечно, упрощать не будем, просто - сделаем эту и следующую работу - как одну
- сейчас объясню про самый простой вариант
- мы его делать не будем, но эти объяснения нам понадобятся для последующих заданий
- можно было реализовать проще - все методы ConciseAPI
- в которых требовуется вебдрайвер - снабдить еще одним параметром для вебдрайвера
- и не применять наследование от ConciseAPI
- да, вызовы этих методов получатся немного громоздкими - плата за простоту реализации
- напоминаю - мы не будем упрощать до этой версии)
- */
- *****************************
- public void open(){
- getWebDriver().get("https://mail.google.com");
- }
- /*
- тут, в ConciseAPI - разумнее реализовывать методы универсально
- без привязки к особенностям реализуемых тестов
- потому - разумнее реализовать метод open(String url)
- */
- ***********************************************
- public WebElement $(By locator){
- public WebElement $(String cssSelector){
- /*
- с реализацией этих методов - согласна полностью
- надеюсь, тебе понятно, почему в данном случае assertThat возвращает WebElement )
- на всякий случай - приведу пояснения этого момента
- (уже в конце ревью такие пространные пояснения приведу)
- */
- *********************************************
- public List<WebElement> $$(By locator){
- return assertThat(visibilityOfAllElementsLocatedBy(locator));
- }
- public List<WebElement> $$(String cssSelector){
- return $$(By.cssSelector(cssSelector));
- }
- /*
- а с методом $$ - не так все просто)
- если для реализации $ - нам и правда достаточно было ждать видимости элемента
- т к чтоб работать с элементом - он нам в 99% нужен видимым
- то со списком - не все так просто)
- кстати, полюбопытствуй - как реализован кондишен visibilityOfAllElementsLocatedBy
- зажми ctrl + кликни на имени єтого кондишена
- ты удивишься )
- часто списки элементов загружаются постепенно
- и нам в разных случаях - нужно ждать разного
- вспомни предыдущую работу - как перед followLink мы ждали minimumSizeOf
- да и пока - нам вообще не нужен метод $$
- ниже поясню - почему
- */
- ****************************************************
- public <V> V assertThat(Function<? super WebDriver, V> condition){
- return (new WebDriverWait(getWebDriver(), 10)).until(condition);
- }
- /*
- реализовала метод - грамотно )
- действительно, у ExpectedCondition<V> - вот такой предок Function<? super WebDriver, V>
- и именно объект такого типа Function<? super WebDriver, V> - и ждет метод until
- т к это класс предка для ExpectedCondition<V> - мы в метод until можем передавать значения типа
- ExpectedCondition<...>
- поскольку в метод assertThat в качестве параметра ты будешь передавать только значения типа
- ExpectedCondition<...> - то и у этого метода можно объявить параметр типа ExpectedCondition<V>
- станет чуть понятнее и лаконичнее
- в принципе - это не обязательно делать)
- тут - уже почти ок)
- надо добавить немного гибкости
- ведь не всегда таймаут именно такого размера требуется
- если
- реализовать assertThat со вторым параметром - таймаутом
- то
- можно будет при вызове проверки - явно указывать размер таймаута
- это бывает удобно - когда в проекте есть проверки, требующие какого-то не стандартного таймаута
- в то же время
- для всех проверок указывать таймаут - уже перебор)
- потому - реализуем второй assertThat - уже без параметра - таймута
- в нем - вызовем первый assertThat и в качестве таймаута укажем значение Configuration.timeout
- Тут же, в core, реализуем класс Configuration со статическим полем timeout,
- в котором будет задан таймаут по умолчанию (разумно его установить равным 4 секунды)
- А если для тестов значения по умолчанию Configuration.timeout недостаточно
- то всегда есть возможность в тест-классе настроить самостоятельно Configuration.timeout
- Собственно - мы аналогично поступали - когда реализовывали версию этого задания на Selenide
- мы для этого теста изменяли значение Configuration.timeout
- */
- *********************************
- public class Main extends ConciseAPI{
- /*
- реализация для предка пейджа - верная
- единственное - теперь, в этой работе
- мы уже не сможем использовать пейджи в качестве пейджей-модулей
- а будем создавать пейджи-объекты
- вспомни работы по пейджам
- для пейджей объектов - имя класса должно заканчиваться на Page
- все классы пейджей и их предка - переименуй
- а для предка - вообще стоит применить имя BasePage
- и перенести его в core - т к его реализация универсальна
- и может быть применена и для других проектов
- */
- ****************************************
- public void assertNthMail(int index, String mailText){
- assertThat(textToBePresentInElement($$(mails).get(index), mailText));
- }
- /*
- Вот тут - очень важный момент
- его надо понять и запомнить обязательно
- если у кондишена первый параметр - WebElement или List<WemElement> -
- то кондишен ждет не просто элемент или список элементов
- кондишен ждет лейзи прокси элемент или список элементов (аннотированный @FindBy)
- потому что - такие элементы - могут переискиваться
- а если у кондишена первый параметр - By - локатор для элемента или списка элементов
- то уже внутри кондишена по локатору происходит получение элемента или списка элементов
- и мы в таком случае не нуждаемся в лейзи прокси элементах или списках элементов (аннотированных @FindBy)
- еще момент
- предположим, у тебя есть лейзи прокси List<WebElement> elements;
- вот такой элемент elements.get(...) - не будет лейзи прокси
- это - уже обычный вебэлемент
- его передавать в кондишен бесполезно
- в этой работе - можно реализовать задание как с использовалием лейзи прокси списка элементов - для списка мейлов
- так и используя локатор для списка мейлов
- это на твое усмотрение
- в любом случае - не удастся работать с textToBePresentInElement
- т к в этот кондишен - надо передать лейзи прокси элемент
- которого у нас нету)
- почитать про лейзи прокси
- http://selenium2advanced.blogspot.com/2013/08/working-with-page-factory-and-webdriver.html
- понятная внятная
- https://github.com/SeleniumHQ/selenium/wiki/PageFactory
- http://joxi.ru/KAxzGoyu4NGlNm
- */
- /*
- тут тебе нужен новый кондишен)
- listNthElementHasText(final ... elements, final int index, final String expectedText)
- который для проверит текст нн-ого элемента
- уже мы писали кондишены, правда попроще
- теперь - усложним задачку
- но сначала давай обговорим тип первого параметра
- мы можем написать кондишен для List<WebElement> elements
- или для By elements
- если выбираешь первый вариант - пишем кондишен для лейзи прокси списка (полученного через FindBy)
- написать и тот, и тот кондишен - примерно одинаково усилий нужно
- решай сама - какой вариант реализовать
- */
- ****************************
- public void assertMails(String... mailTexts){
- List<WebElement> webElementList = $$(mails);
- String[] mailTextArr = mailTexts.clone();
- int i = 0;
- for (WebElement webElement : webElementList) {
- assertThat(textToBePresentInElement(webElement, mailTextArr[i]));
- i++;
- }
- }
- /*
- Писала тебе выше - про то, что ждущая проверка visibilityOfAllElementsLocatedBy для списка - мало что дает)
- вот, мы получили список вебэлементов (не лейзи прокси = даже если на странице далее будут изменения -
- они никак не повлияют на стотояние нами полученного списка)
- это первая проблемка
- и вторая - что мы в textToBePresentInElement - также передаем вебэлемент, который уже не будет переискиваться
- а это не имеет смысла
- нам и тут понадобится новый кондишен
- аналогичный по логике селенидовскому texts
- что касается работы с varArgs - параметром метода - String... mailTexts
- можно обойтись и без массива mailTextArr
- почитай http://www.linkex.ru/java/varargs.php
- */
- /*
- Итак, нам нужен кондишен для коллекции элементов - texts
- в селениуме - такого кондишена нету
- и мы его напишем и разместим в CustomConditions
- можно заглянуть в реализацию селенидовского кондишена - чтобы использовать
- идеи из логики проверки
- давай сначала разберемся с типом кондишена, который будем реализовывать
- можно реализовать ExpectedCondition<Boolean>
- тогда в случае успеха - assertThat - вернет True
- в случае не успеха - тест упадет (как ему и положено)
- а метод apply кондишена - будет возвращать
- True - если проверка пройдена
- False - если она не пройдена
- мы можем больше пользы извлечь из ситуации, если такой кондишен будет типа
- ExpectedCondition<List<WebElement>>
- тогда в случае успеха - assertThat вернет List<WebElement>
- и можно будет писать что-то такое - assertThat(sizeOf(elementsList,10)).get(9).click();
- (это если кондишен sizeOf был бы реализован с первым параметром - List<WebElement>)
- а метод apply кондишена - будет возвращать
- List<WebElement> - если проверка пройдена
- в случае работы с лейзи прокси списком элементов - тот же лейзи прокси список,
- который получили на входе
- в случае работы с локатором - список вебэлементов на момент, когда проверка пройдена
- null - если она не пройдена
- так
- с типом кондишена определились
- нужен кондишен ExpectedCondition<List<WebElement>>
- теперь с параметрами
- проверяем - лейзи прокси список веб элементов - List<WebElement> elements
- что проверяем у этого списка - текстЫ = String... expectedTexts
- Загляни в селениумский класс ExpectedConditions
- (в коде - зажав ctrl + кликнув на имя любого стандартного селениумского кондишена)
- там можно почерпнуть ряд идей
- нам - в apply кондишена - надо принять решение - в ЭТОМ состоянии - список удовлетворяет условию или нет
- а ЭТО состояние - предполагает - что оно на протяжении анализа - не меняется)
- т е задача номер один = зафиксировать = ЭТО состояние (это актуально для варианта с лейзи прокси списом)
- и задача номер два = если проверка не прошла - в toString() кондишена описать ожидаемые и фактические тексты
- а их надо готовить еще в apply - чтобы в toString() - просто вывести
- получается - что независимо от того, будем ли мы реализовывать кондишен для лейзи прокси списка элементов или
- для локатора списка элементов - нам в apply нужно получить список текстов элементов
- используй список строк для того, чтобы сохранить в нем тексты всех элементов ашего лейзи-прокси списка
- получили список актуальных текстов
- теперь - работаем только с ним - (это и есть ЭТО состояние для лейзи прокси списка)
- сравни размер списка актуальных текстов и количество переданных ожидаемых текстов
- если количество не равное - уже проверка не прошла
- если количество равное - сравнивай тексты
- нулевого актуального текста - с нулевым ожидаемым,
- первого - с первым и т д
- если какой-либо актуальный текст не содержит ожидаемого текста - проверка не прошла
- если тексты всех элементов прошли проверку - вот только в этом случае проверка прошла
- реализуем метод toString у кондишена
- когда проверка не проходит - эта информация выводится в описании ошибки
- потому - тут мы должны описать - и актуальное (ЭТО состоняние - которое мы зафиксировали в списке строк)
- и ожидаемое состояние (переданные в кондишен ожидаемые тексты)
- тестируй написанный кондишен - используя
- проверку, которая должна пройти (она должна пройти)
- проверку, которая не должна пройти (она не должна пройти + сообщение об ошибке должно быть понятным)
- так надо поступать с любым кондишеном, который самостоятельно реализуешь
- */
- /*
- Итого)
- Нам нужны 2 новых кондишена
- первый кондишен - textsOf(... elements, String... texts)
- где параметры - список элементов (или его локатор) и текстЫ которые мы будем проверять для каждого из элементов
- второй кондишен - listNthElementHasText(.... elements, int index, String text)
- где параметры - список элементов(или его локатор), индекс проверяемого элемента
- и текст который мы для него проверим
- Про textsOf - выше подробно обсудили
- думаю, большинство вопросов про listNthElementHasText ушли автоматом)
- Но если вдруг остались
- стандартные кондишены реализованы в классе ExpectedConditions
- напиши ExpectedConditions в своем коде
- зажми ctrl+кликни на ExpectedConditions
- откроется модуль (ниже этого комментария привела код этих 2-ух кондишенов,
- в принципе, ты и сама в IntelIJ Idea сможешь это увидеть, но и тут привожу их)
- Еще источники полезных сведений
- У тебя есть лекция Якова, которая рассказывает, как кондишены устроены
- У тебя есть пример кондишена с первым параметром такого же типа, как нам нужно
- У тебя есть пример кондишена, который проверяет текст
- Ты можешь открыть код селенидовского кондишена texts or exactTexts и тоже взять оттуда идеи
- Мы определились с тем, что наши новые кондишены должны делать, с их именами и парамерами
- Попробуй написать эти 2 кондишена.
- Будет сложно - обращайся, будем упрощать задачу)
- */
- ****************************************
- public void visit(){
- open();
- }
- /*
- а вот тут - уже вызовешь open(...), указав ему урл нужный
- так open(...) - будет гораздо полезнее)
- */
- **********************************************
- public void goToSent(){
- $(navigation).findElement(By.partialLinkText("Sent")).click();
- }
- public void goToInbox(){
- $(navigation).findElement(By.partialLinkText("Inbox")).click();
- }
- /*
- вот эти методы могут быть проблемными
- если элементы внутри $(navigation) загружаются не сразу - то и с работой этих методов может быть проблема
- если тесты будут падать на этом коде - то можно
- найти локатор By для каждой из линок и использовать
- $(...) - уже для такого локатора
- у обоих линок этих (Inbox & Sent)
- можно опереться Title -
- если напишешь метод By byTitle(String title) -
- или построишь css selector - который отбирает по Title -
- то эту проблему удастся вот так решить)
- */
- ****************************************
- $(By.xpath("//*[.='COMPOSE']"))
- Есть проблема с подиском переменной, пока реализовала через xpath, други вариантов нет(
- /*
- посмотри как в Selenide устроен метод By byText(...)
- )
- внутри него - как раз и используется xpath-выражение)
- правда, более сложное и универсальное
- реализуй и ты в ConciseAPI - такой метод
- и используй его для поиска по тексту
- */
Advertisement
Add Comment
Please, Sign In to add comment