Scrolling up or down is one of the important action for any mobile application use.
Scenario: some times elements can’t be identified as those are not visible on screen, but once we scroll down to make it visible on viewport and take action.
Scroll normally happens by help of swipe on screen, from source to destination coordinates. so it’s important to identify the desired source/start and dest/end coordinates.
Note – scrolling can happen on the entire screen or on an app element like on a panel which is scrollable (example – contacts screen)
Appium provides different methods to get the element coordinates with respect to the app screen, so irrespective of the screen sizes you can get dynamic coordinates.
For example –
on the below screenshot, the entire screen is not scrollable rather the contacts list only scrollable.
So we will get the coordinate of contacts list wrt entire screen, and then we will calculate the start and end points.
Get the location of contacts list
Let’s say our element is contacts list, then use element.getLocation()
that returns the top left corner X & Y coordinates as 0,2
Now we can use the element.getSize()
to get the width and height of the element.
Through width and height we can get the mid start and end point of the element, which will help us to scroll on the contacts list.
Util methods for scrolling
public static void scroll(WebElement panel, ScrollDirection dir, double scrollRatio) { Point midPoint; Dimension size; if (scrollRatio < 0 || scrollRatio > 1) { throw new Error("Scroll distance must be between 0 and 1"); } if(panel != null){ midPoint = getCenter(panel); }else{ //entire screen is scrollable size = AppDriver.getDriver().manage().window().getSize(); System.out.println(size); midPoint = new Point((int) (size.width * 0.5), (int) (size.height * 0.5)); } int bottom = midPoint.y + (int) (midPoint.y * scrollRatio); int top = midPoint.y - (int) (midPoint.y * scrollRatio); int left = midPoint.x - (int) (midPoint.x * scrollRatio); int right = midPoint.x + (int) (midPoint.x * scrollRatio); if (dir == ScrollDirection.UP) { swipe(new Point(midPoint.x, top), new Point(midPoint.x, bottom), SCROLL_DUR); } else if (dir == ScrollDirection.DOWN) { swipe(new Point(midPoint.x, bottom), new Point(midPoint.x, top), SCROLL_DUR); } else if (dir == ScrollDirection.LEFT) { swipe(new Point(left, midPoint.y), new Point(right, midPoint.y), SCROLL_DUR); } else { swipe(new Point(right, midPoint.y), new Point(left, midPoint.y), SCROLL_DUR); } } protected static void swipe(Point start, Point end, Duration duration) { PointerInput input = new PointerInput(PointerInput.Kind.TOUCH, "finger1"); Sequence swipe = new Sequence(input, 0); swipe.addAction(input.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), start.x, start.y)); swipe.addAction(input.createPointerDown(PointerInput.MouseButton.LEFT.asArg())); /*if (isAndroid) { duration = duration.dividedBy(ANDROID_SCROLL_DIVISOR); } else { swipe.addAction(new Pause(input, duration)); duration = Duration.ZERO; }*/ swipe.addAction(input.createPointerMove(duration, PointerInput.Origin.viewport(), end.x, end.y)); swipe.addAction(input.createPointerUp(PointerInput.MouseButton.LEFT.asArg())); ((AppiumDriver) AppDriver.getDriver()).perform(ImmutableList.of(swipe)); } private static Point getCenter(WebElement el) { Point location = el.getLocation(); Dimension size = el.getSize(); return new Point(location.x + size.getWidth() / 2, location.y + size.getHeight() / 2); } public enum ScrollDirection { UP, DOWN, LEFT, RIGHT }
Swipe() is the gesture action which uses PointerInput
and Sequence
class to perform finger gestures like press and move from one Point to another Point.
This method accepts the start and end coordinates (Point class) and the duration determines how slow or fast the move has to happen.
Scroll() actually gets the start and end coordinates based on the direction we would like to scroll.
The scroll can happen on an entire screen or on a panel or list (webElement) that is scrollable.
this method uses getSize()
to get the height and width of the element or screen
and getLocation()
fetches the elements X-Y coordinate of the element’s top left corder with respect to screen.
Use of above Util methods –
@Test public static ExampleScrollAndroid() throws InterruptedException, MalformedURLException, MalformedURLException { UiAutomator2Options options = new UiAutomator2Options(); options.setDeviceName("emulator-5554") .setPlatformVersion("12.0") .setAppPackage("com.wdiodemoapp") .setAppActivity("com.wdiodemoapp.MainActivity"); driver = new AndroidDriver(new URL("http://0.0.0.0:4723"), options); driver.findElement(AppiumBy.accessibilityId("Swipe")).click(); Thread.sleep(2000); Util.scroll(Util.ScrollDirection.DOWN, 0.5); Thread.sleep(1000); Util.scroll(ScrollDirection.UP, 0.5); Thread.sleep(2000); Util.scroll(ScrollDirection.RIGHT, 0.5); Thread.sleep(2000); Util.scroll(ScrollDirection.LEFT, 0.5); Thread.sleep(2000); driver.quit(); }
You can call the scroll() with the direction(Util.scrollDirection enum) you prefer the scroll to happen.
On java-client <= 7.x versions, we can use TouchAction class to scroll from one point to another point.
PointOptions.point() to assign coordinates and WaitOptions.waitOptions() to assign duration
new TouchAction((PerformsTouchActions) MobileDriver.getDriver()) .press(PointOption.point(0, scrollStart)) .waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1))) .moveTo(PointOption.point(startPoint, endPoint)) .release().perform();
On mobile browser:
For mobile browsers we can use JavaScriptExecutor concept to scroll on screen as we do in Selenium for desktop browsers.
Even you can use the above scroll method which we discussed for native apps.
public class Scrolling { static DesiredCapabilities cap; static AndroidDriver driver; public static void main(String args[]) throws MalformedURLException, InterruptedException{ UiAutomator2Options options = new UiAutomator2Options(); options.setDeviceName("emulator-5554") .setPlatformVersion("12.0") .withBrowserName("chrome"); driver = new AndroidDriver(new URL("http://127.0.0.1:4723/"), options); driver.get("http://qavalidation.com"); Thread.sleep(3000); JavascriptExecutor js = (JavascriptExecutor) driver; while(driver.findelements(By.id("back-to-top")).size()==0) { //Scroll page down to 250px js.executeScript("window.scrollBy(0,250)", ""); } Thread.sleep(3000); driver.quit(); }
Complete code repo – https://github.com/sunilpatro1985/appium-topics
For more ways to scroll on Desktop browsers, follow Scrolling browser using selenium
Im getting error for getDriver() –> The method getDriver() is undefined for the type MobileDriver
please help
Please correct your code,
Close app method is missing