@Slf4j
public abstract class AbstractScreen {
private static final Integer DEFAULT_TIMEOUT = 20;
static final String ANDROID_PKG_INSTLR_ID = "com.android.packageinstaller:id/";
static final String ANDROID_ID = "android:id/";
private final AppiumDriver driver;
private final EventFiringWebDriver eventFiringWebDriver;
private final FluentWait<WebDriver> wait;
private int scrollStart;
private int scrollEnd;
AbstractScreen(ScreenContext context) {
this.driver = getAppiumDriver(context);
this.eventFiringWebDriver = new EventFiringWebDriver(driver);
this.wait = initializeScreenAndGetWaitDriver();
registerListener(context);
computeAndSetScrollValuesForScreen();
}
private FluentWait<WebDriver> initializeScreenAndGetWaitDriver() {
this.driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
PageFactory.initElements(new AppiumFieldDecorator(driver), this);
////TODO-READ THIS COMMENT!
/*at this point the eventFiringWebDriver cannot use the decorator above for listening
* this is because the the iOSFindBy annotation with accessiblity tag sequentially checks for name even if
* you do not use it in your elements, causing the test to fail. When this issue is fixed change the above
* line to :
* PageFactory.initElements(new AppiumFieldDecorator(eventFiringWebDriver), this);
*/
return new WebDriverWait(eventFiringWebDriver, DEFAULT_TIMEOUT)
.pollingEvery(1, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
}
private AppiumDriver getAppiumDriver(ScreenContext context) {
Driver driver = context.getDriver();
log.info(driver.toString());
return driver.getAppiumDriver();
}
private void registerListener(ScreenContext context) {
eventFiringWebDriver.register(context.getErrorModalListener());
}
private void computeAndSetScrollValuesForScreen() {
Dimension dimensions = driver.manage().window().getSize();
Double screenHeightStart = dimensions.getHeight() * 0.5;
int scrollStart = screenHeightStart.intValue();
log.info("scrollStart : {}", scrollStart);
Double screenHeightEnd = dimensions.getHeight() * 0.2;
int scrollEnd = screenHeightEnd.intValue();
log.info("scrollEnd : {}", scrollEnd);
this.scrollStart = scrollStart;
this.scrollEnd = scrollEnd;
}
abstract public String getName();
abstract public boolean isDisplayed();
private WebElement getIfVisible(WebElement element) {
element = checkNotNull(element);
return wait.until(visibilityOf(element));
}
final boolean isElementDisplayed(WebElement element) {
try {
element = checkNotNull(getIfVisible(element));
return element.isDisplayed();
} catch (final Exception e) {
log.info("Element {} is not displayed due to {}", element, e);
return false;
}
}
final boolean areElementsDisplayed(List<WebElement> elements) {
elements = checkNotNull(elements);
return elements.parallelStream().allMatch(this::isElementDisplayed);
}
final void clickOnLink(WebElement element) {
clickOnElement(element);
}
final void clickOnText(WebElement element) {
clickOnElement(element);
}
final void clickOnLabel(WebElement element) {
clickOnElement(element);
}
final void clickOnCheckBox(WebElement element) {
clickOnElement(element);
}
final void clickOnButton(WebElement element) {
element = scrollTo(element);
element.click();
//checkForErrorModalAfterClick();
}
final void clickOnElement(WebElement element) {
element = scrollTo(element);
element.click();
}
////TODO-READ THIS COMMENT!
/**
* This method is created as the listener does not work with iOSFindBy annotations
* This and it's usages should be deprecated in the future in preference of the listener
*/
final void checkForErrorModalAfterClick() {
log.info("checking if error modal is present!");
WebElement elmErrorModal = null;
try {
elmErrorModal = driver.findElement(By.id("errorMessage"));
elmErrorModal = wait.until(visibilityOf(elmErrorModal));
} catch (final Exception e) {
log.info("Ignoring exception for error Modal check!");
}
//Adding "success" condition to prevent success GSMs from getting flagged
if (elmErrorModal != null && elmErrorModal.isDisplayed() && !elmErrorModal.getText().contains("Success")) {
throw new RuntimeException("Error modal with id errorMessage is displayed!");
}
}
final String getText(WebElement element) {
element = scrollTo(element);
return element.getText().trim();
}
final void populate(WebElement element, String text) {
element = scrollTo(element);
element.clear();
element.sendKeys(text);
}
final void hideKeyboard() {
try {
driver.hideKeyboard();
} catch (final Exception e) {
log.info("Keyboard is absent, hence ignoring exception." +
" Hack as appium has no method to check for keyboard");
}
}
private WebElement scrollTo(WebElement element) {
for (int counter = 0; !isElementDisplayed(element) && counter < 5; counter++) {
log.info("element not present loop count {}", counter);
driver.swipe(0, scrollStart, 0, scrollEnd, 2000);
}
return element;
}
final WebElement getElementContainingText(List<WebElement> elements, String text) {
List<WebElement> candidates = elements.parallelStream().
filter(i -> i.getText().contains(text)).collect(Collectors.toList());
if (candidates.size() == 1) {
return candidates.get(0);
}else if(candidates.size() > 1) {
throw new RuntimeException("More than one element with text " + text + " found!");
} else {
throw new RuntimeException("Element with text " + text + " not found!");
}
}
}
Friday, July 20, 2018
AbstractScreen
cucumber step definition enhancements
@Slf4j
@ContextConfiguration(classes = Application.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class SpringContextConfigurationSteps {
@Before
public void dummy() {
log.info("Used to load spring context for cucumber due to constraints! Not a real step definition!");
}
}
Subscribe to:
Posts (Atom)