Использование Page Object в Explicit Waits

Имеется набор тестов (на C#). Все замечательно бегает на ФФ и Хром. На ИЕ9 тесты начинают непредсказуемо падать в разных местах, не находя объекты.

Вычитал про способ подмены стандартного метода FindElement():

public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}
return driver.FindElement(by);
}

В принципе так работает, но в тестах всюду юзается Page Object, а в примере метод хочет явный локатор

Вот такая конструкция работает :

new WebDriverWait(_driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementExists(By.CssSelector("input[title='Unapprove']"))).Click();

А вот так - нет:

var dash = new DashboardPage(_driver);

new WebDriverWait(_driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementExists(dash.Unapprove)).Click();

Елемент Unapprove объявлен в классе  DashboardPage:

[FindsBy(How = How.CssSelector, Using = "input[title='Unapprove']")]
public IWebElement Unapprove;

Если прописывать явные ожидания для ИЕ с конкретными локаторами, то вся концепция Page Object теряет смысл.

Можно-ли как-то заюзать элементы Page Object типа dash.Unapprove в ожиданиях Until(ExpectedConditions.ElementExist(), т.е. не By().

Заранее благодарен.

у меня похожее реализованно, вкратце - как то так:

http://pastebin.com/RVARjA0G

правда без FindsBy ...

Спасибо за ответ, но вопрос упирается именно в элементы объявленные FindsBy...

С явными локаторами все вроде бы ясно и работает.

на С# уже очень давно не программировал, потому конкретный код не покажу

тем не менее, к вам пару вопросов, вы используете PageObject или PageFactory

просто если вы используете FindsBy, тогда вы должны инициализировать свою страницу через initElements

как вы инициализируете Вашу страницу? можете показать код?

Ок.

Есть класс с Элементами страницы

public class DashboardPage
{

private readonly IWebDriver _driver;

public DashboardPage(IWebDriver driver)
{
_driver = driver;
PageFactory.InitElements(driver, this);
}
[FindsBy(How = How.XPath, Using = "//a[@id='zz15_Menu']/span")]
private IWebElement userName;

[FindsBy(How = How.Id, Using = "zz15_Menu_t")]
private IWebElement menuLink;

[FindsBy(How = How.XPath, Using = "//span[@id='zz13_ID_Logout']/span")]
private IWebElement menuLinkSignout;

.................................

В тесте вызывается:

 

[Test, Description("Data Approve"), Category("Release")]
public void _15_DataApprove()
{
_driver.Navigate().GoToUrl(_targetUrl);
var dash = new DashboardPage(_driver);
var set = new AdminSettings(_driver);
set.TimeSetSetup(0); 

dash.Unapprove.Click();    //     такой код временами падает в ИЕ 

new WebDriverWait(_driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementExists(By.CssSelector("input[title='Unapprove']"))).Click();   //  такой идет, но в нем не могу заюзать ранее объявленный елемент FindsBy - "input[title='Unapprove']"

Дело в том, что таких мест много. Пока поставил Thread.Sleep(period); через отдельный метод который запускается только под ИЕ, но это "не наш метод" - коряво, да и срабатывает не всегда

с кодом вроде бы нормально выглядит

потому, тут без дебага не обойтись, надо идти в дебри ExpectedConditions и PageFactory

возможна ситуация, когда просто элемента еще нет на странице и dash.Unapprove просто null

вы дойдите до кода

new WebDriverWait(_driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementExists(dash.Unapprove)).Click(); 

и посмотрите все ли верно инициализированно и возвращает значение 

но это надо дебажить и проверять, просто мысли вслух

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

Код new WebDriverWait(_driver, TimeSpan.FromSeconds(5)).Until(ExpectedConditions.ElementExists(dash.Unapprove)).Click(); - невалидный. Метод ElementExists() не принимает елемента объявленного PageFactory. Хочет исключительно (By.....). В том-то и вопрос, существует-ли какое-то хитрое колдунство способное скормить методу ElementExists() елемент PageFactory. Альтернатива - переопределять все елементы без использования FindsBy и т.д. но елементов дофига, а все уже написано и работает (за исключением ИЕ)

А implicitlyWait вообще используется? Если да - то я думаю будет достаточно его просто увеличить для ИЕ.

Как минимум нужно убедиться, что implicit отрабатывает как положено - в stack trace указывается время, обратите на него внимание.

Да и покажите ее (трассу) на всякий случай - что-то мне подсказывает что проблема не в вейтах.

ну если ExpectedConditions.ElementExists не принимает, таких объектов, то попробуйте тогда определить свой метод ожидания под свои потребности

ведь ExpectedConditions.ElementExists это уже подготовленные для вас заранее частые случаи ожидания

но вы без проблем можете написать свои

переопределять все элементы не стоит

 

а также, если в пошаговом дебаг режиме все прекрасно работает - это означает, что проблема именно в ожидании или в видимости\доступности элемента

Пробовал.

Сейчас выглядит так:

if (Browser == "ie")
{
_driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));
}
else
{
_driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(20));
}

Результата нет. Неужели 30 сек мало.

Пока в "ключевых" точках стоят "костыли":

private void IEWait(int period)
{
if (Browser == "ie")
{
Thread.Sleep(period);
}
}

 

Спасибо. ОК. Только тестовый сервер упал :)

Сервер подняли.

Не было времени копать сабж. Было много другой работы. В попыхах написал по образу и подобию.

public static IWebElement FindElement(this IWebDriver driver, IWebElement element, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => element);
}
return element;
}

Отторжения нет. Елемент возвращает. Надо будет пробовать.