Menu

Defining own Types

Michael Bulla

Defining own Locators

:::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);
}

Using other Element-implementations

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

Element-Level

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();
}

PageObject-Level

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);
    }
}

Application-Level

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());

Defining own Webelement

:::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);

Defining your own Configuration

:::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();
    }
}

Related

Wiki: Cheatsheet
Wiki: Home

MongoDB Logo MongoDB