Friday, July 20, 2018

AbstractScreen

@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!");  
     }  
   }  
 }  

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