Как получить FindsByAttribute из IWebElement в C# Selenium? [Объектная модель страницы]

Учитывая шаблон проектирования Page Object Model в Selenium, мне нужно проверить, присутствует ли WebElement/включен/доступен для щелчка на странице, прежде чем выполнять над ним действие.

Базовый класс «Страница»:

 public class Page
{            
    public Page()
    {
        PageFactory.InitElements(SeleniumTests.driver, this);
    }  
}

Унаследованный класс:

class Page_Certificate_ChooseOperator : Page
    {               
        [FindsBy(How = How.Id, Using = "SearchOperatorName")]
        public IWebElement txtName { get; set; }

        [FindsBy(How = How.Id, Using = "SearchOperatorEstablishmentNumber")]
        public IWebElement txtEstablishmentNumber { get; set; }

        [FindsBy(How = How.Id, Using = "searchButton")]
        public IWebElement btnSearch { get; set; }

        public void SelectOperator(String name, String establishmentNumber)
        {
            this.txtName.SetInputField(name);
            this.txtEstablishmentNumber.SetInputField(establishmentNumber);                
            this.btnSearch.SafeClick();
        }           
    }

Наконец, класс для методов расширения:

 public static class SeleniumExtensionMethod
    {
        public static void SetInputField(this IWebElement webElement, String value)
        {
            webElement.Clear();
            webElement.SendKeys(value);
        }    

        public static void SafeClick(this IWebElement webElement, int timeout_in_seconds)
        {     
            //This is the difficult part. I need to check if the webElement is visible, but I don't want to write "low-level" code and specify the ID and  selector. Is there a way I can find out how the webElement was created by this class and say something like "webElement.How" to find "How.ID" or "webElement.Using" to find "btnSearch"? I need to use something like the below code using the PageObject
            // WebDriverWait wait = new WebDriverWait(SeleniumTests.driver, TimeSpan.FromSeconds(10));
            // IWebElement dynamicElement = wait.Until<IWebElement>(driver => driver.FindElement(By.Id("btnSearch")));  
            // dynamicElement.Click();

            //Now, I just use this, but it crashes on NoSuchElementFound since it goes too fast. I don't want to use ImplicitWait.
            btnSearch.Click();


        }
    }

Проблема, с которой я сталкиваюсь, заключается в том, что мне нужно ExplicitWaity, прежде чем нажимать кнопку btnSearch, поскольку она выдает исключение NoSuchElementFoundException. Поскольку я использую атрибут [FindsBy], я полагаю, что должен быть какой-то способ проверить, как был найден/создан веб-элемент? Как я могу это сделать? Или как я могу иметь аккуратный код и использовать ExplicitWait для объекта страницы?


person Happy Bird    schedule 25.05.2016    source источник


Ответы (1)


Чтобы дождаться появления/включения/доступности элемента, вы можете использовать официант с условием ElementToBeClickable:

[FindsBy(How = How.Id, Using = "searchButton")]
public IWebElement btnSearch { get; set; }

public void SelectOperator(String name, String establishmentNumber)
{
    this.txtName.SetInputField(name);
    this.txtEstablishmentNumber.SetInputField(establishmentNumber);                

    new WebDriverWait(SeleniumTests.driver, TimeSpan.FromSeconds(10))
        .Until(ExpectedConditions.ElementToBeClickable(this.btnSearch))
        .Click();
}
person Florent B.    schedule 25.05.2016
comment
Иногда это работает, но также иногда вызывает исключение TargetInvocationException в WebDriver.Support.dll. Вы знаете, как это исправить? Это очень важно для успеха нашего проекта. Спасибо! - person Happy Bird; 26.05.2016
comment
Что такое внутреннее исключение? Вы должны создать новый вопрос, кажется, это другая проблема. - person Florent B.; 26.05.2016