package com.redheap.selenium.page;
import com.redheap.selenium.component.AdfComponent;
import com.redheap.selenium.component.AdfDocument;
import com.redheap.selenium.domain.PageMessageWrapper;
import java.util.logging.Logger;
import oracle.adf.view.rich.automation.selenium.DialogManager;
import oracle.adf.view.rich.automation.selenium.RichWebDrivers;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import static org.junit.Assert.assertEquals;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.remote.RemoteWebDriver;
/**
* Full page running in a unbounded taskflow.
* Gets the WebDriver (full browser) as container it is running it, but should not expose this to users of this
* class. PageObjects should only expose "business" functions to their users like <br>
* <code>public login(String username, String password)</code>
* <p>
* The implementation of these business functions can interact with AdfComponents on the page and should not
* interact directly with the WebDriver or WebElements.
*/
public abstract class Page /*implements TakesScreenshot*/ {
private final RemoteWebDriver driver;
private static final String JS_GET_REGIONS =
"{ids=[]; AdfPage.PAGE.getComponentsByType('oracle.adf.RichRegion').forEach(function(r){ids.push(r.getClientId())}); return ids}";
private static final String JS_GET_DOCID = "return AdfPage.PAGE.getDocumentClientId()";
private static final Logger logger = Logger.getLogger(Page.class.getName());
public Page(WebDriver driver) {
this(driver, true);
}
Page(WebDriver driver, boolean verifyTitle) {
super();
this.driver = (RemoteWebDriver) driver; // keep handle which we don't expose but only use for navigatedTo
// this is specific for unbounded taskflow page. Bounded page fragments should be available as the caller
// already has to wait for its action to complete
RichWebDrivers.waitForRichPageToLoad(driver, AdfComponent.DFLT_WAIT_TIMEOUT_MSECS);
if (verifyTitle) {
assertEquals(getExpectedTitle(), getTitle());
}
// with animation enabled we sometimes try to click on elements still being rendered (like slowly expanding
// af:tree node)
findDocument().setAnimationEnabled(false);
if (!findDocument().isAutomationEnabled()) {
logger.warning("AUTOMATION IS DISABLED! set oracle.adf.view.rich.automation.ENABLED to true for all functions to work!");
}
}
protected AdfDocument findDocument() {
JavascriptExecutor jsdriver = (JavascriptExecutor) driver;
String docid = (String) jsdriver.executeScript(JS_GET_DOCID);
return AdfComponent.forClientId(driver, docid);
}
protected abstract String getExpectedTitle();
public String getTitle() {
return driver.getTitle();
}
protected <P extends Page> P navigatedTo(Class<? extends P> cls) {
try {
return ConstructorUtils.invokeConstructor(cls, driver);
} catch (Exception e) {
throw new WebDriverException(e.getCause() != null ? e.getCause() : e);
}
}
protected <D extends WindowDialog> D openedDialog(Class<? extends D> cls) {
try {
return ConstructorUtils.invokeConstructor(cls, driver, DialogManager.getInstance().getCurrentDialog());
} catch (Exception e) {
throw new WebDriverException(e.getCause() != null ? e.getCause() : e);
}
}
protected <T extends AdfComponent> T findAdfComponent(String relativeClientId) {
return findDocument().findAdfComponent(relativeClientId);
}
public <X extends Object> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
return driver.getScreenshotAs(target);
}
/**
* Convenience method to get all the messages on the page.
* @return A {@link com.redheap.selenium.domain.PageMessageWrapper PageMessageWrapper} object containing
* all messages and some convenicence methods
*/
public PageMessageWrapper getAllMessages() {
return PageMessageWrapper.getAllMessages(driver);
}
}