Menu

Experimental

Michael Bulla

At this sections there are some very experimental concepts described which need to be proofed and may change or be completly removed.

Defining PageAccessor at class level

As we have seen in [Basics] a page is opened by declaring a method with the annotation @PageAccessor.

Lets say you want to define a set of pages which can be accessed directly by entering an url. That PageObjects implement an interface Openable. To add the information which url to enter you have to redefine your methods in every PageObject:

:::java
public interface Openable {
  void open();

  void open(Map<String, String> parameters);
}

@Page(name="Search")
public interface Search extends Openable {
  @PageAccessor(uri="/search.jsp")
  void open();

  @PageAccess(uri="/search.jsp")
  void open(Map<String, String> parameters);
}

By adding the PageAccessor at page-level you can define your methods this way

:::java
public interface Openable {
  @PageAccessor
  void open();

  @PageAccessor
  void open(Map<String, String> parameters);
}

@Page(name="Search")
@PageAccessor(uri="/search.jsp")
public interface Search extends Openable {

}

Implementring methods on interfaces

Say you have a function you want to support all (or maybe a subset) of your PageObjects. That function cannot be declared but needs to be implemented. Then you would have something like that:

:::java
public abstract class ReloadableSite {
  private WebDriver driver;

  public ReloadableSite(WebDriver driver) {
    this.driver = driver;
  }

  public void reload() {
    driver.navigate().reload();
  }
}

@Page(name="Search")
@PageAccessor(uri="/search.jsp")
public abstract class Search extends ReloadableSite implements Openable {
  public Search(WebDriver driver) {
    super(driver);
  }

  @Locator(name="...", id="...")
  public abstract IButton someButton();
}

Thats ugly. Now all of your PageObjects need to define a constructor. You have to write "public abstract" to all of your Locator-methods and you loose the flexibility of interfaces. Just because you want to define one method at superclass-level.

PopperFramwork lets you implement methods on interfaces:

:::java
public interface ReloadableSite {
    @MethodImplementedBy(ReloadRunner.class)
    void reload();

    public static class ReloadRunner implements IMethodRunner<ReloadableSite, Void> {
        private WebDriver driver;

        public ReloadRunner(WebDriver driver) {
            this.driver = driver;
        }

        @Override
        public Void runMethod(ISite arg0, Object[] arg1) {
            driver.navigate().refresh();
            return null;
        }
    }
}

@Page(name="Search")
@PageAccessor(uri="/search.jsp")
public interface Search extends ReloadableSite, Openable {
  @Locator(name="...", id="...")
  IButton someButton();
}

Related

Wiki: Basics
Wiki: Cheatsheet
Wiki: Home

MongoDB Logo MongoDB