Skip to content

Commit

Permalink
[plugin-mobile-app] Add step to set slider value
Browse files Browse the repository at this point in the history
  • Loading branch information
uarlouski committed Jan 17, 2022
1 parent f45f5fe commit 7f7b9fb
Show file tree
Hide file tree
Showing 9 changed files with 301 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* Copyright 2019-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -198,6 +198,22 @@ public void performVerticalSwipe(int startY, int endY, Rectangle swipeArea, Dura
mobileApplicationConfiguration.getSwipeVerticalXPosition(), swipeArea.getPoint()), swipeDuration);
}

/**
* Performs swipe by coordinates with duration
*
* @param coordinates the {@link SwipeCoordinates}
* @param swipeDuration the swipe duration in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> format
*/
public void swipe(SwipeCoordinates coordinates, Duration swipeDuration)
{
newTouchActions()
.press(point(coordinates.getStart()))
.waitAction(waitOptions(swipeDuration))
.moveTo(point(coordinates.getEnd()))
.release()
.perform();
}

private BufferedImage takeScreenshot()
{
try
Expand All @@ -210,16 +226,6 @@ private BufferedImage takeScreenshot()
}
}

private void swipe(SwipeCoordinates coordinates, Duration swipeDuration)
{
newTouchActions()
.press(point(coordinates.getStart()))
.waitAction(waitOptions(swipeDuration))
.moveTo(point(coordinates.getEnd()))
.release()
.perform();
}

private static Point getCenter(WebElement element)
{
Point upperLeft = element.getLocation();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* Copyright 2019-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,30 +18,48 @@

import static org.apache.commons.lang3.Validate.isTrue;

import java.time.Duration;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.jbehave.core.annotations.When;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vividus.mobileapp.action.TouchActions;
import org.vividus.mobileapp.model.SwipeCoordinates;
import org.vividus.monitor.TakeScreenshotOnFailure;
import org.vividus.selenium.WebDriverUtil;
import org.vividus.selenium.manager.IGenericWebDriverManager;
import org.vividus.steps.ui.validation.IBaseValidations;
import org.vividus.ui.action.JavascriptActions;
import org.vividus.ui.action.search.Locator;
import org.vividus.ui.mobile.action.MobileAppElementActions;

@TakeScreenshotOnFailure
public class ElementSteps
{
private static final Logger LOGGER = LoggerFactory.getLogger(ElementSteps.class);
private static final double PERCENT = 100.0;

private final IGenericWebDriverManager genericWebDriverManager;
private final JavascriptActions javascriptActions;
private final IBaseValidations baseValidations;
private final TouchActions touchActions;
private final MobileAppElementActions mobileAppElementActions;

public ElementSteps(JavascriptActions javascriptActions, IGenericWebDriverManager genericWebDriverManager,
IBaseValidations baseValidations)
IBaseValidations baseValidations, TouchActions touchActions,
MobileAppElementActions mobileAppElementActions)
{
this.javascriptActions = javascriptActions;
this.genericWebDriverManager = genericWebDriverManager;
this.baseValidations = baseValidations;
this.touchActions = touchActions;
this.mobileAppElementActions = mobileAppElementActions;
}

/**
Expand Down Expand Up @@ -71,6 +89,126 @@ public void selectPickerWheelValue(PickerWheelDirection direction, double offset
"offset", offset)));
}

/**
* Todo
*
* @param locator locator to find a slider
* @param number target value to slide to
*/
@SuppressWarnings("MagicNumber")
@When("I set value of slider located `$locator` to `$number`")
public void setSliderValue(Locator locator, int number)
{
baseValidations.assertElementExists("The slider", locator).map(Slider::new).ifPresent(slider ->
{
int initialPosition = slider.getPosition();
if (initialPosition == number)
{
logSliderPosition(number);
return;
}

int sliderPosition = swipeSlider(slider, initialPosition, number);

if (sliderPosition == number)
{
logSliderPosition(number);
return;
}

int diff = Math.abs(number - sliderPosition);

int previousSlide = number;
int previousDiff = diff;
int swipeLimit = 5;

do
{
int adjustment = diff == 1 ? 1 : diff / 2;
int position = sliderPosition < number ? previousSlide + adjustment : previousSlide - adjustment;
previousSlide = position;

sliderPosition = swipeSlider(slider, sliderPosition, position);
diff = Math.abs(number - sliderPosition);

if (previousDiff == diff || diff == 0)
{
break;
}

previousDiff = diff;

swipeLimit -= 1;
}
while (swipeLimit > 0);

logSliderPosition(number);
});
}

private static void logSliderPosition(int sliderPosition)
{
LOGGER.atInfo().addArgument(sliderPosition).log("Set slider value to '{}'");
}

private int swipeSlider(Slider slider, int currentPosition, int targetPosition)
{
SwipeCoordinates coordinates = getSwipeCoordinates(slider.getLocation(), slider.getSize(),
currentPosition, targetPosition);
touchActions.swipe(coordinates, Duration.ofSeconds(1));
return slider.getPosition();
}

private static SwipeCoordinates getSwipeCoordinates(Point sliderLocation, Dimension sliderSize, int currentValue,
int targetValue)
{
int sliderBarOffsetLeft = sliderLocation.getX();
int sliderBarWidth = sliderSize.getWidth();
int sliderBarCenterY = sliderLocation.getY() + sliderSize.getHeight() / 2;

int startX = (int) (sliderBarOffsetLeft + sliderBarWidth * (currentValue / PERCENT) + 0);
int startY = sliderBarCenterY;
int endX = (int) (sliderBarOffsetLeft + sliderBarWidth * (targetValue / PERCENT));
int endY = sliderBarCenterY;

return new SwipeCoordinates(startX, startY, endX, endY);
}

private final class Slider
{
private final Point location;
private final Dimension size;
private final WebElement target;

private Slider(WebElement target)
{
String tag = mobileAppElementActions.getTagName(target);
String sliderTag = genericWebDriverManager.isIOSNativeApp() ? "XCUIElementTypeSlider"
: "android.widget.SeekBar";
isTrue(sliderTag.equals(tag), "The slider element must be '%s', but got '%s'", sliderTag, tag);
this.location = target.getLocation();
this.size = target.getSize();
this.target = target;
}

private Point getLocation()
{
return location;
}

private Dimension getSize()
{
return size;
}

private int getPosition()
{
String text = mobileAppElementActions.getElementText(target);
return genericWebDriverManager.isIOSNativeApp() ? Integer.parseInt(StringUtils.removeEnd(text, "%"))
: Double.valueOf(text).intValue();
}
}

public enum PickerWheelDirection
{
NEXT, PREVIOUS;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* Copyright 2019-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,15 @@ public MobileAppElementActions(GenericWebDriverManager genericWebDriverManager)
this.genericWebDriverManager = genericWebDriverManager;
}

public String getTagName(WebElement element)
{
/*
* For Android platform the WebElement.getTagName() method returns content description of the element:
* https://github.com/appium/appium-uiautomator2-server/blob/master/app/src/main/java/io/appium/uiautomator2/model/UiObject2Element.java#L58
*/
return genericWebDriverManager.isAndroidNativeApp() ? element.getDomAttribute("class") : element.getTagName();
}

@Override
public String getElementText(WebElement element)
{
Expand Down
Loading

0 comments on commit 7f7b9fb

Please # to comment.