:::java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ImplementedBy(MyOwnValidatorImpl.class)
public @interface MyOwnLocator {
String value();
}
public class MyOwnValidatorImpl implements ILocatorProcessor<MyOwnLocator>{
public MyOwnValidatorImpl(WebDriver webdriver, WebdriverContext context) {
super();
if (webdriver == null) {
throw new IllegalArgumentException("webdriver may not be null");
}
if (context == null) {
throw new IllegalArgumentException("context may not be null");
}
}
@Override
public Loc getLocator(MyOwnLocator constraintAnnotation, LocatorContextInformation info) {
if (constraintAnnotation.value().equals("42")) {
return Loc.id("idLocator");
// using parameter-syntax must be implemented yourself
}
throw new RuntimeException("no valid Syntax");
}
}
@Page(name="Self Implemented Locator")
public interface SelfImplementedLocator {
@PageAccessor(uri="/pages/defaultAnnotations.html")
void open();
@Locator(name="Valid Locator")
@MyOwnLocator("42")
ILabel valid(String param1, Long param2);
@Locator(name="Not Valid Locator")
@MyOwnLocator("666")
ILabel notValid(String param1, Long param2);
}
In your tests you wish to type into some kind of textbox, something like a ITextBox, but that textbox may be implemented in many ways in your application, f.e. it may be an Input, an Textarea or a rich edit Textbox.
Sometime you need to help PopperFW to decide the right implementation. PopperFW supports deciding the right implementation at three levels
At element level you may annotate an Locator-method with the @Type-annotation to define the datatype to use (Regard that the given datatype has to implement the Interface of the method):
:::java
@Page(name="Page with textarea")
public interface TextareaPO {
@PageAccessor(uri="/pages/severalTypes.html")
void open();
@Locator(name="Textarea", id="textarea_normal")
@Type(TextArea.class)
ITextBox textarea();
}
At page level you may define an element factory to decide for what interface which implementation to use
:::java
@ElementFactory(GxtElementFactory.class)
@Page(name="Element Factory")
public interface ManyTypesWithElementFactoryPO {
@PageAccessor(uri="/pages/severalTypes.html")
void open();
@Locator(name="Button", id="button_normal")
IButton button(); // will return a GxtCheckbox instead of DefaultCheckbox
@Locator(name="Checkbox", id="checkbox_normal")
ICheckbox checkbox(); // will return a GxtCheckbox instead of DefaultCheckbox
}
public class GxtElementFactory implements IElementFactory {
private static final Map<Class<?>, Class<?>> impls = new HashMap<Class<?>, Class<?>>();
static {
impls.put(IButton.class, GxtButton.class);
impls.put(ICheckbox.class, GxtCheckbox.class);
}
@Override
public Class<?> getImplClassForElement(Class<?> clazz) {
return impls.get(clazz);
}
@Override
public void addImplClassForElement(
Class<?> interfaceClass,
Class<?> targetClass) {
impls.put(interfaceClass, targetClass);
}
}
If you want to use a special ElementFactory for your Whole application you may register it in IPoFactory
:::java
WebdriverContext context = new WebdriverContext();
context.setDefaultElementFactory(new GxtElementFactory());
:::java
public interface ISpecialElement {
public void doSomethingSpecial();
}
public class SpecialElement extends AbstractWebElement implements ISpecialElement {
public DefaultLabel(String name, PageObjectImplementation parent, Loc loc, WebdriverContext context) {
super(name, parent, loc, context);
}
@Override
public void doSomethingSpecial() {
getDriver()...
}
}
@Page(name="Page with special element")
public interface TextareaPO {
@PageAccessor(uri="/pages/severalTypes.html")
void open();
@Locator(name="Textarea", id="textarea_normal")
@Type(SpecialElement.class)
ISpecialElement special();
}
When defining a new type of Element (like ISpecialElement) you may register the implementation in DefaultElementFactory without overwriting an existing type.
:::java
context.getDefaultElementFactory().addImplClassForElement(ISpecialElement.class, SpecialElement .class);
:::java
public class MyConfiguration implements IWebdriverConfig {
@Override
public WebDriver createDriver() {
return new FirefoxDriver();
}
@Override
public Browser getBrowser() {
return Browser.FIREFOX;
}
@Override
public String getBaseUrl() {
return "http://localhost:8080";
}
}
public class LoginTest {
protected IPoFactory factory;
@Before
public void setup() {
WebdriverContext context = new WebdriverContext();
context.setConfig(new MyConfiguration());
factory = context.getFactory();
}
@Test
public void testLogin() {
Login login = factory.createPage(Login.class);
login.open();
login.usernameTextbox().type("Michael");
login.passwordTextbox().type("secret");
login.submitLoginButton().click();
}
}