一尘不染

在selenium的PageFactory上选择对象

selenium

我知道您无法在中初始化Select对象PageFactory。我一直在互联网上搜索,但只找到了一个可能的答案,可以使用ElementLocatorFactory但在实现方面没有太多细节。我要问他们是成功实施它还是有实现它的想法的人,可以通过以外的其他方式来确定ElementLocatorFactory

目前,我仅使用以下内容:

@FindBy(how = How.ID, using = "select-log-status")
public WebElement __logStatus;
public Select selectLogStatus() {
    return new Select(__logStatus);
}

我正在寻找实现的东西是这样的。

@FindSelectBy(how = How.ID, using = "select-log-status")
public Select selectLogStatus;

PS。我是selenium的新手,也是回来的Java开发人员,所以请好好对待我:)


阅读 237

收藏
2020-06-26

共1个答案

一尘不染

由于没有人分享某些东西,因此我将分享我的做法。

我查看了一下代码,发现它的对象类型正在使用DefaultFieldDecoratordecorate方法进行过滤,因此我所做的只是创建了一个自定义FieldDecorator并扩展了DefaultFieldDecorator该类,因为我只想覆盖decorate

所以,我有一个PageObject类 MyPageObjects

public class MyPageObjects {
    protected final WebDriver driver;
    public MyPageObjects (WebDriver driver) {
        this.driver = driver;
    }


    @FindBy(id = "my-select-object")
    public Select mySelectObj;
}

我的CustomFieldDecorator将包含以下替代方法:

@Override
public Object decorate(ClassLoader loader, Field field) {
    if (!(WebElement.class.isAssignableFrom(field.getType())
        || Select.class.isAssignableFrom(field.getType())
        || List.class.isAssignableFrom(field.getType())
        || isDecoratableList(field))) {
      return null;
    }

    ElementLocator locator = factory.createLocator(field);
    if (locator == null) {
      return null;
    }

    if (WebElement.class.isAssignableFrom(field.getType())) {
      return proxyForLocator(loader, locator);
    } else if (List.class.isAssignableFrom(field.getType())) {
          return proxyForListLocator(loader, locator);
    } else if (Select.class.isAssignableFrom(field.getType())) {
          return new Select(locator.findElement());
    } else {
      return null;
    }
}

注意以下几行:

|| Select.class.isAssignableFrom(field.getType())

} else if (Select.class.isAssignableFrom(field.getType())) {
      return new Select(locator.findElement());

我会像这样初始化元素…

MyPageObjects page = new MyPageObjects(driver);
PageFactory.initElements(new CustomFieldDecorator(
    new DefaultElementLocatorFactory(driver), page);

并照常访问Select对象…

page.mySelectObj.selectByVisibleText("hello world");

警告 :这没有用Proxy,所以要小心。并且WebElement包装的Select类被缓存。


更新:

我为创建了代理处理程序Select。我创建了一个扩展类Select和一个包含Select的方法的接口。

CustomSelect.java

public class CustomSelect extends Select implements SelectInput {
    public CustomSelect(WebElement element) {
        super(element);
    }
}

SelectInput.java -接口

public interface SelectInput {
    boolean isMultiple();
    List<WebElement> getOptions();
    List<WebElement> getAllSelectedOptions();
    WebElement getFirstSelectedOption();
    void selectByVisibleText(String text);
    void selectByIndex(int index);
    void selectByValue(String value);
    void deselectAll();
    void deselectByValue(String value);
    void deselectByIndex(int index);
    void deselectByVisibleText(String text);
}

SelectElementHanlder.java -InvocationHandler

public class SelectElementWrapperHandler implements InvocationHandler {
    private final ElementLocator locator;

    public SelectElementWrapperHandler(ElementLocator locator) {
        this.locator = locator;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        CustomSelect element;
        try {
            element = new CustomSelect(locator.findElement());
        } catch (Exception e) {
            if ("toString".equals(method.getName())) {
                return "Proxy select(element) for: " + locator.toString();
            }
            else throw e;
        }

        try {
            return method.invoke(element, args);
        } catch (InvocationTargetException e) {
            throw e.getCause();
        }

    }

}

在CustomFieldDecorator中创建了一个方法

protected SelectInput proxySelectForLocator(ClassLoader loader, ElementLocator locator) {
        InvocationHandler handler = new SelectElementWrapperHandler(locator);

        SelectInput proxy;
        proxy = (SelectInput) Proxy.newProxyInstance(
            loader, new Class[]{SelectInput.class}, handler);
        return proxy;
    }

然后从CustomFieldDecorator更改此行

} else if (Select.class.isAssignableFrom(field.getType())) {
          return new Select(locator.findElement());

对此:

} else if (SelectInput.class.isAssignableFrom(field.getType())) {
              return proxySelectForLocator(loader, locator);

现在,我将在PageObject类中声明选择对象,例如:

@FindBy(xpath = "some..xpath")
public SelectInput ticketStatus;

希望能帮助到你。如果有更正,请修改:)

2020-06-26