Подтвердить что ты не робот

WebDriver: Как проверить, существует ли веб-элемент веб-страницы?

Как проверить, существует ли Элемент, при использовании Объектов страницы с webdriver.

Пока я делаю это так.

DefaultPage defaultPage = PageFactory.initElements(this.driver,
      DefaultPage.class);
assertTrue(defaultPage.isUserCreateMenuLinkPresent());

Объект страницы:

public class DefaultPage {     
    @FindBy(id = "link_i_user_create")
    private WebElement userCreateMenuLink;


    public boolean isUserCreateMenuLinkPresent() {
        try {
            this.userCreateMenuLink.getTagName();
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }
 }

Но я не могу поверить, что эта попытка/улов - это то, как это нужно делать. Итак, что было бы лучшим способом проверить, не выходят ли элементы (с использованием объектов страницы)?

4b9b3361

Ответ 2

Проблема заключается в самом шаблоне. Он использует аннотацию @FindBy (используется PageFactory для инициализации полей, которые должны быть обернуты Proxy), которая заменяет стандартные элементы их экземплярами прокси, которые содержат InvocationHandler.

Каждый раз, когда вы пытаетесь получить доступ к полю, аннотируемому с помощью @FindBy, обработчик вызова пытается найти элемент, используя ElementLocator по умолчанию. Проблема заключается в том, что метод ElementLocator.findElement() генерирует исключение TimeoutException/NoSuchElementException, если нет элементы, представленные в DOM.

public WebElement findElement(SearchContext context) {
   List<WebElement> allElements = findElements(context);
   if (allElements == null || allElements.isEmpty())
      throw new NoSuchElementException("Cannot locate an element using "
      + toString());
   return allElements.get(0);
}

Поэтому каждый раз, когда вам нужно проверить, отображается ли элемент или нет, вам нужно найти список элементов и проверить его размер.

@FindBy(css = "div.custom")
private List<WebElement> elements
...

public isElementPresented(){
   return elements != null && elements.size > 0
}

Еще один способ решить эту проблему - создать собственную реализацию LocatingElementHandler и ElementLocator

Итак, если вам нужен собственный метод isDisplayed() для возврата false вместо Exception, вам необходимо заменить метод findElement() в ElementLocator примерно таким:

...
List<WebElement> elements = searchContext.findElements(by)
if(elements != null && elements.size() > 0){
   List<WebElement> visibleElements = []
   elements.each {
      if(it.displayed){
         visibleElements.add(it)
      }
   }
   if(visibleElements.size() > 0){
      return visibleElements.get(0)
   }
}
return null
...

И добавьте новые условия в LocatingElementHandler.invoke()

Что-то вроде:

element = locator.findElement()
if(element == null){
   if(method.name == "isDisplayed"){
      return false
   }
}

Ответ 3

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

public void login() 
{
    if (!loginButton.isDisplayed())
    {
        throw new IllegalStateException("Login button is not displayed!");
    } else
    {
        loginButton.click();    
    }        
}

или

public boolean loginButtinIsDisplayed() {
    try {
        this.loginButton.getTagName();
        return true;
    } catch (NoSuchElementException e) {
        e.printStackTrace();
        return false;
    }
}

Ответ 4

@Ralph: Я делаю это точно так же: try/catch. Я никогда не находил другого пути. Вы можете поменять блок try/catch в суперкласс и создать его общий. Другими словами: вы можете написать метод, который ожидает объект типа WebElement. Этот метод содержит блок try/catch и возвращает true/false...

Итак, я написал следующий открытый метод в тестовом фреймворке суперкласс, и теперь я могу использовать его в каждом объекте страницы:

public boolean isElementExisting(WebElement we) {
    try {
        we.isDisplayed();
        return true;
    } catch(NoSuchElementException e) {
        LOGGER.severe("Element does not exist.");
        return false;
    }
}

Я не знаю, почему это не реализовано в WebDriver...

В противном случае вы можете использовать WebDriverWait.

Ответ 5

Недавно я столкнулся с этим старым сообщением и считаю, что нашел одно решение.

Я тестировал страницу с кнопкой Add User. Когда кнопка была нажата, появились различные редактируемые текстовые поля (для имени, фамилии, электронной почты и т.д.) И одного раскрывающегося списка.

Когда нажата кнопка Cancel, поля исчезли и больше не существовали. Использование WebDriverWait с ExpectedConditions.visibilityOf() не будет работать, поскольку в DOM элементы больше не существовали.

Я обнаружил, что @FindAll был для меня решением, хотя я должен признать, что мой тест заметно замедлился в моем утверждении списка.

Для вашего кода, примерно так:

public class DefaultPage {     
@FindAll({@FindBy(id = "link_i_user_create")}) List<WebElement> userCreateMenuLink;


public boolean isUserCreateMenuLinkPresent() {
    if (this.userCreateMenuLink.isEmpty()) fail("Link does not exist");}

Я могу использовать что-то подобное в своих собственных тестах, но, похоже, надежный способ сгладить исключение "Нет такого элемента". Это в основном адаптация объекта страницы утверждения: driver.findElements(By.locator).size() < 1.

Ответ 6

Использование привязок С#:

using System.Collections.Generic;
using System.Linq;

public class DefaultPage 
{
    [FindsBy(How = How.Id, Using = "link_i_user_create")]
    private IList<IWebElement> userCreateMenuLink;

    public bool isUserCreateMenuLinkPresent()
    {
        return userCreateMenuLink.Any();
    }
}

Вы говорите Selenium, чтобы захватить все элементы, которые соответствуют этому Id, и помещают их в Список IWebElement. Затем вы вызываете .Any() в список, который оценивает значение true, если найдено хотя бы один IWebElement.

Ответ 8

попробуйте, чтобы это вызывающе работало в pom

public boolean isPrebuiltTestButtonVisible() {
    try {

        if (preBuiltTestButton.isEnabled()) {

            return true;

        } else {

            return false;
        }

    } catch (Exception e) {

        e.printStackTrace();
        return false;
    }
}

это, безусловно, будет работать в окружении объектной модели страницы с помощью try catch