Java tutorial
/** * Copyright (c) 2017, Wasiq Bhamla. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.wasiqb.coteafs.appium.device; import static com.github.wasiqb.coteafs.appium.constants.ErrorMessage.SERVER_STOPPED; import static com.github.wasiqb.coteafs.appium.utils.ErrorUtils.fail; import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfAllElementsLocatedBy; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.openqa.selenium.By; import org.openqa.selenium.InvalidSelectorException; import org.openqa.selenium.NoSuchSessionException; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import com.github.wasiqb.coteafs.appium.checker.ServerChecker; import com.github.wasiqb.coteafs.appium.config.DeviceSetting; import com.github.wasiqb.coteafs.appium.config.PlaybackSetting; import com.github.wasiqb.coteafs.appium.config.enums.AutomationType; import com.github.wasiqb.coteafs.appium.config.enums.PlatformType; import com.github.wasiqb.coteafs.appium.config.enums.WaitStrategy; import com.github.wasiqb.coteafs.appium.error.AppiumSelectorNotImplementedError; import com.github.wasiqb.coteafs.appium.error.AppiumServerStoppedError; import com.github.wasiqb.coteafs.appium.error.DeviceElementFindTimedOutError; import com.github.wasiqb.coteafs.appium.error.DeviceElementNameNotFoundError; import com.github.wasiqb.coteafs.appium.error.DeviceElementNotFoundError; import io.appium.java_client.AppiumDriver; import io.appium.java_client.MobileElement; import io.appium.java_client.TouchAction; /** * @author wasiq.bhamla * @param <D> * @param <E> * @param <T> * @since 26-Apr-2017 4:31:24 PM */ public abstract class DeviceActivity<D extends AppiumDriver<MobileElement>, E extends Device<D, T>, T extends TouchAction<T>> { private static final Logger log = LogManager.getLogger(DeviceActivity.class); protected final AutomationType automation; protected final E device; protected final Map<String, DeviceElement> deviceElements; protected final PlatformType platform; private final DeviceSetting deviceSetting; private final PlaybackSetting playSetting; private final T touch; private final WebDriverWait wait; /** * @author wasiq.bhamla * @param device * @param touch * @since 26-Apr-2017 4:32:45 PM */ public DeviceActivity(final E device, final T touch) { this.device = device; this.touch = touch; this.deviceElements = new HashMap<>(); this.deviceSetting = device.getSetting(); this.automation = this.deviceSetting.getAutomationName(); this.platform = this.deviceSetting.getPlatformType(); this.playSetting = this.deviceSetting.getPlayback(); this.wait = new WebDriverWait(device.getDriver(), this.playSetting.getWaitForElementUntil()); } /** * @author wasiq.bhamla * @since Feb 2, 2018 1:44:52 PM * @param name * @return element */ public MobileElement getElement(final String name) { load(); final String msg = "Getting element with name [%s]..."; log.trace(String.format(msg, name)); return findElements(getDeviceElement(name)); } /** * @author wasiq.bhamla * @since 26-Apr-2017 8:41:07 PM * @return device actions */ public DeviceActions<D, E, T> onDevice() { this.device.checkServerRunning(); log.info("Preparing to perform actions on device..."); return new DeviceActions<>(this.device, this.touch); } /** * @author wasiq.bhamla * @since 26-Apr-2017 6:45:09 PM * @param name * @return element actions */ public DeviceElementActions<D, E, T> onElement(final String name) { ServerChecker.checkServerRunning(this.device.server); final String msg = "Preparing to perform actions on device element [%s]..."; log.trace(String.format(msg, name)); return new DeviceElementActions<>(this.device, name, getElement(name), this.touch); } /** * @author wasiq.bhamla * @since Jul 5, 2017 6:55:54 AM * @param name * @param index * @return actions */ public DeviceElementActions<D, E, T> onElement(final String name, final int index) { ServerChecker.checkServerRunning(this.device.server); final String msg = "Preparing to perform actions on dynamic device element [%s] on index [%d]..."; log.trace(String.format(msg, name, index)); final DeviceElement element = getDeviceElement(name).index(index); return new DeviceElementActions<>(this.device, name, findElements(element), this.touch); } /** * @author wasiq.bhamla * @return element * @since 02-May-2017 4:38:00 PM */ protected abstract DeviceElement prepare(); private void captureScreenshotOnError() { if (this.playSetting.isScreenshotOnError()) { onDevice().captureScreenshot(); } } private MobileElement find(final D deviceDriver, final DeviceElement parent, final By locator, final int index, final WaitStrategy strategy) { try { wait(locator, strategy); List<MobileElement> result = null; if (parent != null) { final String message = "Finding child element of [%s] parent using [%s] at index [%d]..."; log.trace(String.format(message, parent.name(), locator, index)); final MobileElement mobileElement = getElement(parent.name()); result = mobileElement.findElements(locator); } else { final String message = "Finding root element using [%s] at index [%d]..."; log.trace(String.format(message, locator, index)); result = deviceDriver.findElements(locator); } return result.get(index); } catch (final TimeoutException e) { captureScreenshotOnError(); final String message = "[%s] locator timed out."; fail(DeviceElementFindTimedOutError.class, String.format(message, locator), e); } catch (final NoSuchSessionException e) { fail(AppiumServerStoppedError.class, SERVER_STOPPED, e); } catch (final InvalidSelectorException e) { fail(AppiumSelectorNotImplementedError.class, "Selector not supported", e); } catch (final Exception e) { captureScreenshotOnError(); String message = ""; if (parent == null) { message = "Error occured while finding root device element with locator [%s] at index [%d]."; fail(DeviceElementNotFoundError.class, String.format(message, locator, index), e); } else { message = "Error occured while finding device element with locator [%s] at index [%d] under parent %s."; fail(DeviceElementNotFoundError.class, String.format(message, locator, index, parent.name()), e); } } return null; } private MobileElement findElements(final DeviceElement element) { final DeviceElement parent = element.parent(); final By locator = element.locator(this.platform, this.automation); final int index = element.index(); final WaitStrategy strategy = element.waitStrategy(); return find(this.device.getDriver(), parent, locator, index, strategy); } private DeviceElement getDeviceElement(final String name) { if (this.deviceElements.containsKey(name)) return this.deviceElements.get(name); final String msg = "DeviceElement with name [%s] not found."; fail(DeviceElementNameNotFoundError.class, String.format(msg, name)); return null; } private void load() { if (this.deviceElements.size() == 0) { final String msg = "Loading elements on [%s] activity..."; log.trace(String.format(msg, this.platform)); loadElements(prepare()); } } private void loadElements(final DeviceElement rootElement) { ServerChecker.checkServerRunning(this.device.server); if (!this.deviceElements.containsKey(rootElement.name())) { this.deviceElements.put(rootElement.name(), rootElement); } final List<DeviceElement> childs = rootElement.childs(); for (final DeviceElement child : childs) { loadElements(child); } } /** * @author wasiq.bhamla * @since Jan 30, 2018 7:33:47 PM * @param locator * @param waitStrategy */ private void wait(final By locator, final WaitStrategy waitStrategy) { switch (waitStrategy) { case ENABLED: this.wait.until(ExpectedConditions.elementToBeClickable(locator)); break; case PRESENT: this.wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(locator)); break; case VISIBLE: this.wait.until(visibilityOfAllElementsLocatedBy(locator)); break; case NONE: default: break; } } }