Skip to content

Commit

Permalink
[plugin-mobile-app] Limit swipe action area to device screen size (#3826
Browse files Browse the repository at this point in the history
)
  • Loading branch information
valfirst authored Apr 13, 2023
1 parent 99d5b1f commit 2e37c80
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ public void swipeUntil(SwipeDirection direction, Duration swipeDuration, Rectang
Duration stabilizationDuration = swipeConfiguration.getSwipeStabilizationDuration();
int swipeLimit = swipeConfiguration.getSwipeLimit();
BufferedImage previousFrame = null;
MoveCoordinates swipeCoordinates = direction.calculateCoordinates(swipeArea, swipeConfiguration);

Rectangle adjustedSwipeArea = adjustSwipeArea(swipeArea);

MoveCoordinates swipeCoordinates = direction.calculateCoordinates(adjustedSwipeArea,
swipeConfiguration);
for (int count = 0; count <= swipeLimit; count++)
{
swipe(swipeCoordinates, swipeDuration);
Expand Down Expand Up @@ -253,6 +257,21 @@ private Supplier<BufferedImage> createScreenShooter(SearchContext searchContext)
}
}

/**
* Make sure swipe area is not outside screen
* @param swipeArea Desired swipe area
* @return Adjusted with screen size swipe area
*/
private Rectangle adjustSwipeArea(Rectangle swipeArea)
{
Dimension screenSize = genericWebDriverManager.getSize();
int x = Math.max(swipeArea.getX(), 0);
int y = Math.max(swipeArea.getY(), 0);
int height = Math.min(swipeArea.getHeight(), screenSize.getHeight());
int width = Math.min(swipeArea.getWidth(), screenSize.getWidth());
return new Rectangle(x, y, height, width);
}

/**
* Performs vertical or horizontal swipe from <b>start</b> to <b>end</b> coordinate with <b>swipeDuration</b>
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 the original author or authors.
* Copyright 2019-2023 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 @@ -126,7 +126,7 @@ void shouldTapOnVisibleElement()

var touchActionCaptor = ArgumentCaptor.forClass(TouchAction.class);
verify(performsTouchActions).performTouchAction(touchActionCaptor.capture());
String actions = ACTIONS_OPEN + PRESS
var actions = ACTIONS_OPEN + PRESS
+ WAIT
+ RELEASE
+ ACTIONS_CLOSE;
Expand All @@ -146,7 +146,7 @@ void shouldTapOnInvisibleElement()

var touchActionCaptor = ArgumentCaptor.forClass(TouchAction.class);
verify(performsTouchActions).performTouchAction(touchActionCaptor.capture());
String actions = ACTIONS_OPEN + "{action=press, options={x=2, y=5}}, "
var actions = ACTIONS_OPEN + "{action=press, options={x=2, y=5}}, "
+ WAIT
+ RELEASE
+ ACTIONS_CLOSE;
Expand All @@ -171,7 +171,7 @@ void shouldTapOnInvisibleElementOutsideViewport(int x, int y)

var touchActionCaptor = ArgumentCaptor.forClass(TouchAction.class);
verify(performsTouchActions).performTouchAction(touchActionCaptor.capture());
String actions = ACTIONS_OPEN + PRESS
var actions = ACTIONS_OPEN + PRESS
+ WAIT
+ RELEASE
+ ACTIONS_CLOSE;
Expand All @@ -189,8 +189,8 @@ void shouldTapOnVisibleElementWithoutWaitIfDurationIsZero()

verify(performsTouchActions).performTouchAction(argThat(arg ->
{
String parameters = arg.getParameters().toString();
String actions = ACTIONS_OPEN + "{action=tap, options={element=elementId}}" + ACTIONS_CLOSE;
var parameters = arg.getParameters().toString();
var actions = ACTIONS_OPEN + "{action=tap, options={element=elementId}}" + ACTIONS_CLOSE;
return actions.equals(parameters);
}));
}
Expand All @@ -208,7 +208,8 @@ void shouldSwipeUntilConditionIsTrue() throws IOException
when(screenshotTaker.takeViewportScreenshot()).thenReturn(getImage(BLACK_IMAGE))
.thenReturn(getImage(WHITE_IMAGE));

touchActions.swipeUntil(SwipeDirection.UP, DURATION, ACTION_AREA, stopCondition);
var swipeArea = new Rectangle(new Point(-5, -5), new Dimension(700, 900));
touchActions.swipeUntil(SwipeDirection.UP, DURATION, swipeArea, stopCondition);

verifySwipe(3);
}
Expand All @@ -219,6 +220,7 @@ void shouldNotCropElementContextScreenshot()
mockPerformsTouchActions();
var context = mock(WebElement.class);
when(uiContext.getOptionalSearchContext()).thenReturn(Optional.of(context));
when(genericWebDriverManager.getSize()).thenReturn(DIMENSION);
when(stopCondition.getAsBoolean()).thenReturn(false)
.thenReturn(false)
.thenReturn(true);
Expand All @@ -233,7 +235,6 @@ void shouldNotCropElementContextScreenshot()
touchActions.swipeUntil(SwipeDirection.UP, DURATION, ACTION_AREA, stopCondition);

verifySwipe(3);
verifyNoMoreInteractions(genericWebDriverManager);
verify(blackImage, never()).getSubimage(anyInt(), anyInt(), anyInt(), anyInt());
verify(whiteImage, never()).getSubimage(anyInt(), anyInt(), anyInt(), anyInt());
}
Expand All @@ -252,12 +253,12 @@ void shouldWrapIOException() throws IOException
mockPerformsTouchActions();
when(uiContext.getOptionalSearchContext()).thenReturn(Optional.of(mock(AppiumDriver.class)));
when(genericWebDriverManager.getSize()).thenReturn(DIMENSION);
IOException exception = mock(IOException.class);
var exception = mock(IOException.class);

when(stopCondition.getAsBoolean()).thenReturn(false);
doThrow(exception).when(screenshotTaker).takeViewportScreenshot();

UncheckedIOException wrapper = assertThrows(UncheckedIOException.class,
var wrapper = assertThrows(UncheckedIOException.class,
() -> touchActions.swipeUntil(SwipeDirection.UP, DURATION, ACTION_AREA, stopCondition));

assertEquals(exception, wrapper.getCause());
Expand All @@ -279,7 +280,7 @@ void shouldNotExceedSwipeLimit() throws IOException
.thenReturn(getImage(BLACK_IMAGE))
.thenReturn(getImage(WHITE_IMAGE));

IllegalStateException exception = assertThrows(IllegalStateException.class,
var exception = assertThrows(IllegalStateException.class,
() -> touchActions.swipeUntil(SwipeDirection.UP, DURATION, ACTION_AREA, stopCondition));

assertEquals("Swiping is stopped due to exceeded swipe limit '5'", exception.getMessage());
Expand Down Expand Up @@ -344,7 +345,7 @@ void shouldFailDoubleTapElementIfNotSupportedPlatform()
{
when(genericWebDriverManager.isAndroid()).thenReturn(false);
when(genericWebDriverManager.isIOS()).thenReturn(false);
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
var exception = assertThrows(IllegalArgumentException.class,
() -> touchActions.doubleTap(element));
assertEquals("Double tap action is available only for Android and iOS platforms", exception.getMessage());
}
Expand All @@ -358,7 +359,7 @@ void shouldFailDoubleTapElementIfNotSupportedPlatform()
void shouldPerformZoom(ZoomType zoomType, int point1StartX, int point1StartY, int point1EndX, int point1EndY,
int point2StartX, int point2StartY, int point2EndX, int point2EndY)
{
Interactive webDriver = mock(Interactive.class);
var webDriver = mock(Interactive.class);
when(webDriverProvider.getUnwrapped(Interactive.class)).thenReturn(webDriver);
var pointerMoveTemplate = "{duration=%d, x=%%s, y=%%s, type=pointerMove, origin=viewport}";
var swipeSequenceTemplate = "{id=%s, type=pointer, parameters={pointerType=touch}, actions=["
Expand All @@ -384,7 +385,7 @@ private BufferedImage getImage(String image)
{
try
{
byte[] bytes = ResourceUtils.loadResourceAsByteArray(getClass(), image);
var bytes = ResourceUtils.loadResourceAsByteArray(getClass(), image);
return ImageTool.toBufferedImage(bytes);
}
catch (IOException e)
Expand Down

0 comments on commit 2e37c80

Please sign in to comment.