Кастомный FieldDecorator и PageFactory

Друзья! Доброго времени суток!

Буду признателен, если поможете разобрать следующую ситуацию. Пишу фреймворк с использованием PageFactory и до тех пор пока пользовался интерфейсом WebElement в сочетании с аннотацией @FindBy для описания элементов страницы в page object классах проблем не возникало. Когда решил воспользоваться стандартным Select для описания select элемента, то уже пришлось вызывать конструктор при описании поля:

Select mySelect = new Select(driver.findElement(By.id("select_id")));

Конструкция типа:

@FindBy(id = "foo") private WebElement wannabeSelect;

Select realSelect = new Select(wannabeSelect);

также не срабатывала.

Но самое интересное началось когда я решил использовать свои интерфейсы для контролов на странице:

public class MainPage extends BasePage {

@FindBy(id = "text_id")

private TextField myField;

@FindBy(css = "input[type=\"submit\"]")

private Button myButton;

public MainPage(WebDriver driver) {

super(driver);

PageFactory.initElements(driver, this);  // ! в таком виде initElements() не может инициализировать элементы страницы, которые не являются WebElement  !

}

...

}

В общем, в данном случае нужно использовать другой вариант метода initElements(), а именно:

static void initElements(FieldDecorator decorator, java.lang.Object page)

В документации сказано: "Similar to the other "initElements" methods, but takes an FieldDecorator which is used for decorating each of the fields."

В общем, насколько я понимаю нужно реализовать свой декоратор, так как именно он вызывается PageFactory применительно к полям с типом отличным от WebElement.

Если кто-то реализовывал свои декораторы, пожалуйста, поделитесь опытом как это правильно делать.

 

обьясните что такое Select и TexField класы ?)

Никогда подобного делать не приходилось, но задачка заинтересовала. Сделал для Select. Думаю не проблема расширить. Интересно увидеть другие решения.

 

package test.ExtendedPageFactory;
 
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.pagefactory.DefaultElementLocatorFactory;
import org.openqa.selenium.support.pagefactory.DefaultFieldDecorator;
import org.openqa.selenium.support.pagefactory.ElementLocator;
import org.openqa.selenium.support.pagefactory.ElementLocatorFactory;
import org.openqa.selenium.support.ui.Select;
 
import java.lang.reflect.Field;
 
/**
 * User: Ruslan Semerenko
 * Date: 21.03.12 23:09
 */
public class ExtendedPageFactorySample {
    public static void main(String[] args) {
        FirefoxDriver driver = new FirefoxDriver();
        driver.get("http://htmlbook.ru/html/select");
        SelectPage page = new SelectPage();
        PageFactory.initElements(new ExtendedFieldDecorator(new DefaultElementLocatorFactory(driver)), page);
        page.select(2);
    }
    
    public static class SelectPage {
        @FindBy(css = "[name=select2]")
        private Select selectElement;
 
        public void select(int index) {
            selectElement.selectByIndex(index);
        }
    }
 
    public static class ExtendedFieldDecorator extends DefaultFieldDecorator {
        public ExtendedFieldDecorator(ElementLocatorFactory factory) {
            super(factory);
        }
 
        @Override
        public Object decorate(ClassLoader loader, Field field) {
            if (field.getType().equals(Select.class)) {
                ElementLocator locator = factory.createLocator(field);
                if (locator == null) {
                    return null;
                }
                return new Select(proxyForLocator(loader, locator));
            }
            return super.decorate(loader, field);
        }
    }
}
 

        
1 лайк

Спасибо, Kedanachi! Это то что я имел в виду. Еще вот нагуглил проект в котором используется ExtendedFieldDecorator: https://github.com/oraz/selenium

Select это вспомогательный класс WebDriver, который призван упростить работу с контролами типа:

<select>
  <option>Пункт 1</option>
  <option>Пункт 2</option>
</select>

Подробнее здесь: http://seleniumhq.org/docs/03_webdriver.html#user-input-filling-in-forms и здесь: http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/support/ui/Select.html

TextField в данном случае это свой интерфейс-обертка для контролов типа <input type="text" name="fname" />, чтобы не работать с ними как с просто WebElement'ами. По аналогии как правило пишутся классы-обертки для других типов контролов на странице - кнопок, форм, таблиц и т.п.

а я дурак через джава скрипт екзекюшин делал такое ))

Пример класса обертки можете написать ???