Part 6. Extensions

Extensions (Static Methods)

Due to the way we structure our framework, we can create static methods that we can use as extensions on methods involving different object types, such as tapping or long-pressing on a MobileElement, swiping from one element to another, explicitly waiting for an AppiumDriver, or waiting for a MobileElement to be displayed or clickable etc.

MobileElement Extensions

We will begin each method name with ‘me’ (for MobileElement).

First things first, let’s add a private static iOSDriver variable and set it to what’s returned from our ‘appDriver()’ method.

  1. Open up the ‘MobileElementExtensions’ class in the ‘utils.extensions’ package and add the following static variable inside the class at the top…
    private static IOSDriver driver = appDriver();

meWaitForSeconds() Static Method

  1. Open up the ‘MobileElementExtensions’ class in the ‘utils.extensions’ package and add the following static method for making the Driver wait for a specified number of seconds…
    public static WebDriverWait meWaitForSeconds() {
        WebDriverWait wait = new WebDriverWait(driver, sec);
        return wait;
    }
  2. Make sure the import for ‘WebDriverWait’ and the static import for appDriver() method have been added above the class…
    import org.openqa.selenium.support.ui.WebDriverWait;
    
    import static utils.appium.Driver.appDriver;
  3. Add a static integer variable set to a value of 10 for ‘sec’, and make it private to the class it is in, just above the weWaitForSeconds() method…
    private static int sec = 10;

meElementIsDisplayed() Static Method

  1. Add the following static method in the ‘MobileElementExtensions’ class to check that a given MobileElement is displayed, after waiting the specified amount of time from the weWaitForSeconds() method …
    public static boolean meElementIsDisplayed(MobileElement element) {
        meWaitForSeconds().until(ExpectedConditions.visibilityOf(element));
        return element.isDisplayed();
    }
  2. Also make sure the import for ‘ExpectedConditions’ is added above the class, as well as an import for ‘WebElement’…
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import io.appium.java_client.MobileElement;

meElementToBeClickable() Static Method

  1. Add the following static method in the ‘MobileElementExtensions’ class to check that a given MobileElement is clickable, after waiting the specified amount of time from the meWaitForSeconds() method…
    public static boolean meElementToBeClickable(MobileElement element) {
        meWaitForSeconds().until(ExpectedConditions.elementToBeClickable(element));
        return element.isEnabled();
    }

meTap() Static Method

  1. Add the following static method in the ‘MobileElementExtensions’ class to wait for a given MobileElement to be clickable/tappable, highlight the clickable/tappable MobileElement, and then tap the MobileElement (this is better than simply clicking as on mobile the more realistic action would actually be tapping)…
    public static void meTap(MobileElement mobileElement) {
        meElementToBeClickable(mobileElement);
        touchAction.tap(tapOptions().withElement(element(mobileElement))).perform();
    }

    For the above to work, we need to add the following static imports…

    import static io.appium.java_client.touch.TapOptions.tapOptions;
    import static io.appium.java_client.touch.offset.ElementOption.*;

    We also need to make sure we import the TouchAction class…

    import io.appium.java_client.TouchAction;

    We then need to add a a private static TouchAction object in the top of our class (this way we can reuse the TouchAction class in other similar methods)…

    private static TouchAction touchAction = new TouchAction(driver);

meLongPress() Static Method

  1. Edit the meTap() method so it looks like below…
    public static void meTap(MobileElement mobileElement) {
        meElementClickableToBeClickable(mobileElement);
        touchAction.tap(tapOptions().withElement(element(mobileElement))).perform();
    }
  2. Add the following method for long pressing on a Mobile element for two seconds, and then releasing your finger from it…
    public static void meLongPress(MobileElement mobileElement) {
            meElementToBeClickable(mobileElement);
            touchAction.longPress(longPressOptions().withElement(element(mobileElement))
                    .withDuration(ofSeconds(2))).release().perform();
        }

    For the above to work, we need to add two more static imports for all Duration methods (* is wildcard for all) and LongPressOptions longPressOptions method

    import static io.appium.java_client.touch.LongPressOptions.longPressOptions;
    import static java.time.Duration.*;

meSwipeFromElementToElement() Static Method

  1. Add the following static method in the ‘MobileElementExtensions’ class to check that the elements to swipe to and from are clickable and highlighted, and then press down on one element and swipe it to another element and then release the finger / touch…
    public static void meSwipeFromElementToElement(MobileElement fromMobileElement, MobileElement toMobileElement) {
        meElementToBeClickable(fromMobileElement);
        meElementToBeClickable(toMobileElement);
        touchAction.longPress(longPressOptions().withElement(element(fromMobileElement))
                .withDuration(ofSeconds(2))).moveTo(element(toMobileElement)).release().perform();
    }

meSwipeDirection() Static Methods

  1. Add the following DIRECTION enum to the MobileExtensions class…
    public enum DIRECTION {
        DOWN, UP, LEFT, RIGHT;
    }
  2. Add the following method which uses a switch case with the enum we made to swipe in any given direction…
    public static void meSwipe(DIRECTION direction, long duration) {
        Dimension size = appDriver().manage().window().getSize();
        int startX = 0;
        int endX = 0;
        int startY = 0;
        int endY = 0;
    
        switch (direction) {
            case RIGHT:
                startY = size.height / 2;
                startX = (int) (size.width * 0.90);
                endX = (int) (size.width * 0.05);
                touchAction
                    .press(PointOption.point(startX, startY))
                    .waitAction(WaitOptions.waitOptions(Duration.ofMillis(duration)))
                    .moveTo(PointOption.point(endX, startY))
                    .release()
                    .perform();
                break;
    
            case LEFT:
                startY = size.height / 2;
                startX = (int) (size.width * 0.05);
                endX = (int) (size.width * 0.90);
                touchAction
                    .press(PointOption.point(startX, startY))
                    .waitAction(WaitOptions.waitOptions(Duration.ofMillis(duration)))
                    .moveTo(PointOption.point(endX, startY))
                    .release()
                    .perform();
                break;
    
            case UP:
                startY = (int) (size.height * 0.30);
                startX = (size.width / 2);
                touchAction
                    .press(PointOption.point(startX, startY))
                    .waitAction(WaitOptions.waitOptions(Duration.ofMillis(duration)))
                    .moveTo(PointOption.point(endX, startY))
                    .release()
                    .perform();
                break;
    
            case DOWN:
                startY = (int) (size.height * 0.70);
                endY = (int) (size.height * 0.30);
                startX = (size.width / 2);
                touchAction
                    .press(PointOption.point(startX, startY))
                    .waitAction(WaitOptions.waitOptions(Duration.ofMillis(duration)))
                    .moveTo(PointOption.point(startX, endY))
                    .release()
                    .perform();
                break;
        }
    }

meSendKeys() Static Method

  1. Add the following static method in the ‘MobileElementExtensions’ class to wait for a given textfield MobileElement to be displayed, clear the textfield if necessary (if ‘clearFirst’ is true), and then input a given String into the textfield…
    public static void meSendKeys(MobileElement element, String text, boolean clearFirst) {
        meElementIsDisplayed(element);
        if (clearFirst) meTap(element);
        element.sendKeys(text);
    }

meElementIsInvisible() Static Method

  1. Add the following static method in the ‘MobileElementExtensions’ class to wait for a given MobileElement to not be visible anymore…
    public static boolean meElementIsInvisible(MobileElement element) {
        meWaitForSeconds().until(ExpectedConditions.invisibilityOf(element));
        return !element.isDisplayed();
    }

meGetAttribute() Static Method

  1. Add the following static method in the ‘MobileElementExtensions’ class to find a specified attribute of a given element…
    public static String meGetAttribute(MobileElement element, String attribute) {
        return element.getAttribute(attribute);
    }

iOS Specific Gestures (XCUITest)

Unfortunately Apple’s XCTest framework does not natively support W3C standards for TouchAction interface implementation.  It has to serialise the XML into a format XCTest will understand, which can often times be slow in performance.  Although, XCTest does provide a rich set of gestures, including these, that are unique for iOS platform.

If you ever run into difficulty using the W3C Action API, Appium provides direct access to these vendor-supported action methods as well. In this article we’ll take a look at the ones available for iOS. Because these are not part of the WebDriver spec, Appium provides this access by overloading the executeScript command, as you’ll see in the examples below.

We will being each method name with ‘xc’ (as it is specific to XCUITest mobile gestures).

First things first, let’s make this ‘XCTestExtensions’ class extend ‘MobileElementExtensions’ class and also add a private static iOSDriver variable and set it to what’s returned from our ‘appDriver()’ method (making sure we add the correct static import), like below…

package utils.extensions;

import io.appium.java_client.ios.IOSDriver;

import static utils.appium.Driver.appDriver;

public class XCTestExtensions extends MobileElementExtensions {

    private static IOSDriver driver = appDriver();

}

xcSwipe() Static Methods

xcSwipe(String direction) Static Method

  1. Add the following static method in the ‘XCTestExtensions’ class in the ‘utils.extensions’ package to swipe the whole screen in a given direction…
    public static void xcSwipe(String direction) {
        Map<String, Object> params = new HashMap<>();
        params.put("direction", direction);
        driver.executeScript("mobile: swipe", params);
    }

    Also make sure the following imports are added…

    import org.openqa.selenium.JavascriptExecutor;
    import java.util.HashMap;
    import java.util.Map;

xcSwipe(String direction, MobileElement element) Static Method

This is an overloaded version of the above method that also takes a given element that can be swiped on specifically.

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to swipe a given element in a given direction…
    public static void xcSwipe(String direction, MobileElement element) {
        meElementIsDisplayed(element);
        Map<String, Object> params = new HashMap<>();
        params.put("direction", direction);
        params.put("element", element.getId());
        driver.executeScript("mobile: swipe", params);
    }

    Unfortunately, XCUITest does not provide any parameters to modify the speed or distance of the swipe. For that, use the more general Actions API.

    Also make sure the following import is added for MobileElement…

    import io.appium.java_client.MobileElement;

xcScroll() Static Methods

xcScroll(String direction) Static Method

If you want to try and make sure that each movement of your gesture moves a view by the height of the scrollable content, or if you want to scroll until a particular element is visible, try mobile: scroll. It works similarly to mobile: swipe but takes more parameters:

  • element: the id of the element to scroll within (the application element by default). Call this the “bounding element”
  • direction: the opposite of how direction is used in mobile: swipe. A swipe “up” will scroll view contents down, whereas this is what a scroll “down” will do.
  • name: the accessibility ID of an element to scroll to within the bounding element
  • predicateString: the NSPredicate of an element to scroll to within the bounding element
  • toVisible: if true, and if element is set to a custom element, then simply scroll to the first visible child of element
  1. Add the following static method in the ‘XCTestExtensions’ class to scroll the screen a given direction (direction is opposite to swipe, so swiping up would be the same as scrolling down)…
    public static void xcScroll(String direction) {
        Map<String, Object> params = new HashMap<>();
        params.put("direction", direction);
        driver.executeScript("mobile:scroll", params);
    }

xcScroll(String direction, MobileElement element) Static Method

  1. Add the following static method in the ‘XCTestExtensions’ class to scroll a given direction on a given element…
    public static void xcScroll(String direction) {
        meElementIsDisplayed(element);
        Map<String, Object> params = new HashMap<>();
        params.put("direction", direction);
        params.put("element", element);
        driver.executeScript("mobile:scroll", scrollObject);
    }

xcScroll(String direction, String parameter, String nameOrPredicateString) Static Method

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to scroll a given direction to a child element (found by either ‘name’ [accessibility ID] or ‘predicateString’)…
    public static void xcScroll(String direction, String parameter, String nameOrPredicateString) {
        Map<String, Object> params = new HashMap<>();
        params.put("direction", direction);
        params.put(parameter, nameOrPredicateString);
        driver.executeScript("mobile:scroll", params);
    }

xcPinchOrZoom() Static Methods

This method is to pinch (described by a two-finger gesture where the fingers start far apart and come together).

The only required parameter is scale:

  • Values between 0 and 1 refer to a “pinch”
  • Values greater than 1 refer to a “zoom in” (or pinching open).

xcPinchOrZoom(double scale) Static Method

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to pinch or zoom the whole application based on a given ‘double’ scale number (between 0 and 1) that we pass…
    public static void xcPinchOrZoom(double scale) {
        Map<String, Object> args = new HashMap<>();
        args.put("scale", scale);
        driver.executeScript("mobile: pinch", args);
    }

xcPinchOrZoom(MobileElement element, double scale) Static Method

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to pinch or zoom a given element based on a given ‘double’ scale number (between 0 and 1) that we pass…
    public static void xcPinchOrZoom(MobileElement element, double scale) {
        meElementIsDisplayed(element);
        Map<String, Object> args = new HashMap<>();
        args.put("scale", scale);
        args.put("element", element.getID());
        driver.executeScript("mobile: pinch", args);
    }

xcTapOn() Static Methods

The best way to tap on an element is using element.click(). So why do we have mobile: tap? This method allows for extra mandatory parameters x and y signifying the coordinate at which to tap. The nice thing is that this coordinate is either screen-relative (if an element parameter is not included, the default), or element-relative (if an element parameter is included).

This means that if you want to tap at the very top left corner of an element rather than dead centre, you can!

xcTapOn(double x, double y) Static Method

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to tap on the screen at given x and y coordinates…
    public static void xcTapOn(double x, double y) {
        Map<String, Object> args = new HashMap<>();
        args.put("x", x);
        args.put("y", y);
        driver.executeScript("mobile: tap", args);
    }

xcTapOn(MobileElement element, double x, double y) Static Method

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to tap on a given element at the given x and y coordinates of that element…
    public static void xcTapOn(MobileElement element, double x, double y) {
        meElementIsDisplayed(element);
        Map<String, Object> args = new HashMap<>();
        args.put("element", element.getId());
        args.put("x", x);
        args.put("y", y);
        driver.executeScript("mobile: tap", args);
    }

xcDoubleTapOn() Static Methods

xcDoubleTapOn(double x, double y) Static Method

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to double tap on the screen at the given x and y coordinates…
    public static void xcDoubleTapOn(double x, double y) {
        Map<String, Object> args = new HashMap<>();
        args.put("x", x);
        args.put("y", y);
        driver.executeScript("mobile: doubleTap", args);
    }

xcDoubleTapOn(MobileElement element) Static Method

  1. Add the following overloaded static method in the ‘XCTestExtensions’ class to double tap on a given element…
    public static void xcDoubleTapOn(MobileElement element) {
        meElementIsDisplayed(element);
        Map<String, Object> args = new HashMap<>();
        args.put("element", element.getId());
        driver.executeScript("mobile: doubleTap", args);
    }

xcTwoFingerTapOn(MobileElement element) Static Method

Not to be confused with a double-tap, a two-finger-tap is a single tap using two fingers! This method has only one parameter, which is required: good old element (it only works in the context of an element, not a point on the screen).

  1. Add the following static method in the ‘XCTestExtensions’ class to two-finger tap on a given element…
    public static void xcTwoFingerTapOn(MobileElement element) {
        meElementIsDisplayed(element);
        Map<String, Object> args = new HashMap<>();
        args.put("element", element.getId());
        driver.executeScript("mobile: twoFingerTap", args);
    }

xcTouchAndHoldOn(MobileElement element, double duration) Static Method

Many iOS apps allow a user to trigger special behaviour by tapping and holding the finger down on a certain UI element. You can specify all the same parameters as for doubleTap (elementx, and y) with the same semantics. In addition you must set the duration parameter to specify how many seconds you want the touch to be held.

  1. Add the following static method in the ‘XCTestExtensions’ class to touch and hold on a given element for a given duration…
    public static void xcTouchAndHoldOn(MobileElement element, double duration) {
        meElementIsDisplayed(element);
        Map<String, Object> args = new HashMap<>();
        args.put("element", element.getId());
        args.put("duration", duration);
        driver.executeScript("mobile: touchAndHold", args);
    }

xcDragFromToForDuration() Static Methods

Another commonly-implemented app gesture is “drag-and-drop”. As with all of these gestures, it’s possible to build a respectable drag-and-drop using the Actions API, but if for some reason this doesn’t work, XCUITest has provided a method directly for this purpose. It’s a method on the XCUICoordinate class.

What’s going on here is that we’re defining a start and an end coordinate, and also the duration of the hold on the start coordinate. In other words, we have no control over the drag duration itself, only on how long the first coordinate is held before the drag happens. What parameters do we use?

  • element: an element ID, which if provided will cause Appium to treat the coordinates as relative to this element. Absolute screen coordinates otherwise.
  • duration: the number of seconds (between 0.5 and 6.0) that the start coordinates should be held
  • fromX: the x-coordinate of the start position
  • fromY: the y-coordinate of the start position
  • toX: the x-coordinate of the end position
  • toY: the y-coordinate of the end position

xcDragFromToForDuration(double duration, double fromX, double fromY, double toX, double toY) Static Method

  1. Add the following static method in the ‘XCTestExtensions’ class to drag and drop from given x and y coordinates of the whole screen/application, to given x and y coordinates, again of the whole screen/application…
    public static void xcDragFromToForDuration(double duration, double fromX, double fromY, double toX, double toY) {
        Map<String, Object> args = new HashMap<>();
        args.put("duration", duration);
        args.put("fromX", fromX);
        args.put("fromY", fromY);
        args.put("toX", toX);
        args.put("toY", toY);
        driver.executeScript("mobile: dragFromToForDuration", args);
    }

xcDragFromToForDuration(MobileElement element, double duration, double fromX, double fromY, double toX, double toY) Static Method

  1. Add the following static method in the ‘XCTestExtensions’ class to drag and drop from given x and y coordinates of the given element, to given x and y coordinates, again of the same given element…
    public static void xcDragFromToForDuration(MobileElement element, double duration, double fromX, double fromY, double toX, double toY) {
        meElementIsDisplayed(element);
        Map<String, Object> args = new HashMap<>();
        args.put("element", element.getId());
        args.put("duration", duration);
        args.put("fromX", fromX);
        args.put("fromY", fromY);
        args.put("toX", toX);
        args.put("toY", toY);
        driver.executeScript("mobile: dragFromToForDuration", args);
    }

xcSelectPickerWheelValue(MobileElement element, String order, double offset) Static Method

This method performs selection of the next or previous picker wheel value.

Supported arguments

  • element: PickerWheel’s internal element id (as hexadecimal hash string) to perform value selection on. The element must be of type XCUIElementTypePickerWheel. Mandatory parameter
  • order: Either next to select the value next to the current one from the target picker wheel or previous to select the previous one. Mandatory parameter
  • offset: The value in range [0.01, 0.5]. It defines how far from picker wheel’s centre the click should happen. The actual distance is calculated by multiplying this value to the actual picker wheel height. Too small offset value may not change the picker wheel value and too high value may cause the wheel to switch two or more values at once. Usually the optimal value is located in range [0.15, 0.3]. 0.2 by default
  1. Add the following static method in the ‘XCTestExtensions’ class to select the next or previous picker wheel value from the current value…
    public static void xcSelectPickerWheelValue(MobileElement element, String order, double offset) {
        Map<String, Object> params = new HashMap<>();
        params.put("order", order);
        params.put("offset", offset);
        params.put("element", element.getId());
        driver.executeScript("mobile: selectPickerWheelValue", params);
    }

xcPerformActionOnAlert() Static Methods

These methods perform operations on NSAlert instance.

When we see an alert popup, it will generally always have ‘accept’ and ‘dismiss’ options available for selection, and may also optionally have other options with different labels that can be selected.  Therefore, our method should account for when there are more than the standard ‘accept’ and ‘dismiss’ options and when there are just the simple ones

xcPerformActionOnAlert(String action) Static Method

  1. Add the following static method in the ‘XCTestExtensions’ class to select a given action on a simple alert…
    public static void xcPerformActionOnAlert(String action) {
        meWaitForSeconds().until(ExpectedConditions.alertIsPresent());
        HashMap<String, String> args = new HashMap<>();
        args.put("action", action);
        driver.executeScript("mobile: alert", args);
    }

    Also make sure you add the following import for ‘ExpectedConditions’…

    import org.openqa.selenium.support.ui.ExpectedConditions;

xcPerformActionOnAlert(String action, String buttonLabel) Static Method

  1. Add the following static method in the ‘XCTestExtensions’ class to select a given action on a given button label in an alert…
    public static void xcPerformActionOnAlert(String action, String buttonLabel) {
        meWaitForSeconds().until(ExpectedConditions.alertIsPresent());
        HashMap<String, String> args = new HashMap<>();
        args.put("action", action);
        args.put("buttonLabel", buttonLabel);
        driver.executeScript("mobile: alert", args);
    }

Note: The whole list of XCUITest specific mobile commands can be found at http://appium.io/docs/en/commands/mobile-command/#ios-xcuitest-only

WebDriver Extensions

We will begin each method name with ‘wd’ (for WebDriver).

wdHighlight() Static Method

  1. Open up the ‘WebDriverExtensions’ class in the ‘utils.extensions’ package and add the following static method for highlighting a given locator using JavaScript…
    public static Object wdHighlight(By locator) {
        WebDriver driver = appDriver();
        WebElement myLocator = driver.findElement(locator);
        JavascriptExecutor js = (JavascriptExecutor) appDriver();
        return js.executeScript(wdHighlightedColour, myLocator);
    }
  2. You will notice that an error is thrown due to not knowing what ‘wdHighlightedColour’ is, so let’s add that in the ‘Settings’ class of the ‘utils.selenium’ package (of course you can also customise this to change the colour and size of the border etc.)…
    public static String wdHighlightedColour = "arguments[0].style.border='5px solid blue";
  3. Next, go back to the ‘WebDriverExtensions’ class and add a static import for ‘wdHighlightedColour’ in the ‘Settings’ class…
    import static utils.appium.Settings.wdHighlightedColour;
  4. Of course, also check that the imports for ‘WebDriver’, ‘WebElement’, ‘JavaScriptExecutor’ and ‘By’ have been added above the class, as well as a static import again for the browser() method in the ‘Drivers’ class of the ‘utils.selenium’ package…
    import org.openqa.selenium.By;
    import org.openqa.selenium.JavascriptExecutor;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import static utils.appium.Driver.appDriver;

wdElementIsDisplayed() Static Method

  1. Open up the ‘WebDriverExtensions’ class in the ‘utils.extensions’ package and add the following static method for checking that a highlighted locator is displayed…
    public static Object wdElementIsDisplayed(By locator) {
        wdHighlight(locator);
        WebDriverWait wait = new WebDriverWait(appDriver(), sec);
        return wait.until(ExpectedConditions.visibilityOf((WebElement) locator));
    }
  2. Make sure the import for ‘WebDriverWait’ and ‘ExpectedConditions’ have been added above the class…
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;
  3. Add a static integer variable set to a value of 10 for ‘sec’, and make it private to the class it is in, just above the weWaitForSeconds() method…
    private static int sec = 10;

wdElementIsInvisible() Static Method

  1. Add the following static method in the ‘WebDriverExtensions’ class to wait for a given locator to not be visible…
    public static void wdElementToDisappear(By locator) {
        WebDriverWait wait = new WebDriverWait(appDriver(), 5);
        wait.until(ExpectedConditions.invisibilityOfElementLocated(locator));
    }

wdFindElement() Static Method

  1. Add the following static method in the ‘WebDriverExtensions’ class to find a displayed element by its locator…
    public static WebElement wdFindElement(By locator) {
        wdElementIsDisplayed(locator);
        return appDriver().findElement(locator);
    }

wdClick() Static Method

  1. Add the following static method in the ‘WebDriverExtensions’ class to click on an element which has been found by its locator…
    public static void wdClick(By locator) {
        wdFindElement(locator).click();
    }

wdSendKeys() Static Method

  1. Add the following static method in the ‘WebDriverExtensions’ class to wait for a given textfield element (which has been found by its locator) to be displayed, clear the textfield if necessary (if ‘clearFirst’ is true), and then input a given String into the textfield…
    public static void wdSendKeys(By locator, String text, boolean clearFirst) {
        if (clearFirst) wdClick(locator);
        wdFindElement(locator).sendKeys(text);
    }

Refactoring our Test Scenario to use the Extensions

We can now use our extensions (static methods) to replace previous lines of code in our test methods.  Over time, this helps us follow DRY principles (Don’t Repeat Yourself) as well as make our code easier to read 🙂

‘navToPabloPicasso()’ method

  1. Edit the ‘navToPabloPicasso()’ method in the ‘BasePage’ class so it uses the meTap() static method from the ‘MobileElementExtensions’ class (you will have to add a static import to access all the static methods in the MobileElementExtensions class)…
    import static utils.extensions.MobileElementExtensions.*;
    public PabloPicassoPage navToPabloPicasso() {
        meTap(btnPabloPicasso);
        log.info(":: We navigate to the Pablo Picasso screen");
        return instanceOf(PabloPicassoPage.class);
    }

‘viewMoreInfoGuernica()’ method

  1. Edit the ‘viewMoreInfoGuernica()’ method in the ‘BasePage’ class so it uses the meTap() static method from the ‘MobileElementExtensions’ class again (you will have to add a static import to access all the static methods in the MobileElementExtensions class)…
    import static utils.extensions.MobileElementExtensions.*;
    public void viewMoreInfoGuernica() {
        meTap(btnGuernica);
        log.info(":: We select to view more info for the 'Guernica' painting");
    }

Running the Test Scenario

Running the Test

  1. Open up ‘BaseScenarios.feature’ file and make sure you have the ‘@Iphone8’ tag at the top of the feature file or above each test scenario you want to run
  2. Right-click on the test scenario and run it

It should pass 😀