title: Selenium Page Object Reuse
body: <p>I really like how selenium 2 by convention pushes you towards using PageObjects as POJOs, and then simply using the PageFactory to instantiate the fields in this class.</p>
  
  <p>What I am finding limiting is that we reuse a lot of elements on many different pages.  The big problem is that these reused components do not have the same id / name when they appear on different pages; however the tests we would run for each of them is the same.</p>
  
  <p>As an example we collect dates in many places.  So an example page object for this could be (month, day fields removed):</p>
  
  <pre><code>public class DatePageObject {
      private WebDriver driver;
  
      DatePageObject(WebDriver driver) {
          this.driver = driver;
      }
  
      @FindBy( id = "someIdForThisInstance")
      private WebElement year;
  
      public void testYearNumeric() {
          this.year.sendKeys('aa');
          this.year.submit();
          //Logic to determine Error message shows up
      }
  }
  </code></pre>
  
  <p>Then I could simply test this with the code below:</p>
  
  <pre><code>public class Test {
      public static void main(String[] args) {
           WebDriver driver = new FirefoxDriver();
           DatePageObject dpo = PageFactory.initElements(driver, DriverPageObject.class);
           driver.get("Some URL");
           dpo.testYearNumeric();
      }
  }
  </code></pre>
  
  <p>What I'd really like to do is have a setup whereby with Spring I can inject that id/name/xpath, etc... into the application.  </p>
  
  <p>Is there a way I can do this, without losing the ability to utilize the PageFactory?</p>
  
  <p>Edit 1 -- Adding ideal base level classes, working on Custom Locators and Factories.</p>
  
  <pre><code>public class PageElement {
      private WebElement element;
      private How how;
      private String using;
  
      PageElement(How how, String using) {
          this.how = how;
          this.using = using;
      }
      //Getters and Setters
  }
  
  
  public class PageWidget {
      private List&lt;PageElement&gt; widgetElements;
  }
  
  
  public class Screen {
      private List&lt;PageWidget&gt; fullPage;
      private WebDriver driver;
  
      public Screen(WebDriver driver) {
          this.driver = driver;
          for (PageWidget pw : fullPage) {
              CustomPageFactory.initElements(driver, pw.class);
          }
  }
  </code></pre>
  
  <p>Edit 2 -- Just as a note, as long as you are running Selenium 2.0.a5 or greater, you can now give the driver an implicit timeout value.</p>
  
  <p>So you can replace your code with:</p>
  
  <pre><code>private class CustomElementLocator implements ElementLocator {
      private WebDriver driver;
      private int timeOutInSeconds;
      private final By by;
  
  
      public CustomElementLocator(WebDriver driver, Field field,
              int timeOutInSeconds) {
          this.driver = driver;
          this.timeOutInSeconds = timeOutInSeconds;
          CustomAnnotations annotations = new CustomAnnotations(field);
          this.by = annotations.buildBy();
          driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); //Set this value in a more realistic place
      }
  
  
      public WebElement findElement() {
          return driver.findElement(by);
      }
  }
  </code></pre>