Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expanded swipe to support from: -> to: #2117

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions maestro-client/src/main/java/maestro/Maestro.kt
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,30 @@ class Maestro(
waitForAppToSettle()
}

fun swipeFromElementToPoint(
uiElement: UiElement,
endPoint: Point? = null,
endRelative: String? = null,
duration: Long = 300L
) {
val deviceInfo = deviceInfo()

when {
endPoint != null -> driver.swipe(uiElement.bounds.center(), endPoint, duration)
endRelative != null -> {
val endPoints = endRelative.replace("%", "")
.split(",").map { it.trim().toInt() }
val endX = deviceInfo.widthGrid * endPoints[0] / 100
val endY = deviceInfo.heightGrid * endPoints[1] / 100
val end = Point(endX, endY)

driver.swipe(uiElement.bounds.center(), end, duration)
}
}

waitForAppToSettle ()
}

fun scrollVertical() {
LOGGER.info("Scrolling vertically")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ data class SwipeCommand(
startRelative != null && endRelative != null -> {
"Swipe from ($startRelative) to ($endRelative) in $duration ms"
}
elementSelector != null && (endPoint != null || endRelative != null) -> {
"Swiping from ${elementSelector.description()} to ${endPoint ?: endRelative} coordinates"
}
else -> "Invalid input to swipe command"
}
}
Expand Down
16 changes: 15 additions & 1 deletion maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,21 @@ class Orchestra(
endPoint = end,
duration = command.duration
)

elementSelector != null && (end != null || endRelative != null) -> {
val uiElement = findElement(elementSelector, optional = command.optional)
if (end != null)
maestro.swipeFromElementToPoint(
uiElement = uiElement.element,
endPoint = end,
duration = command.duration
)
else
maestro.swipeFromElementToPoint(
uiElement = uiElement.element,
endRelative = endRelative,
duration = command.duration
)
}
else -> error("Illegal arguments for swiping")
}
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ data class YamlFluentCommand(
)
}
is YamlSwipeElement -> return swipeElementCommand(swipe)
is YamlRelativeCoordinateSwipeElement -> return swipeRelativeCoordinatesSwipeElementCommand(swipe)
else -> {
throw IllegalStateException(
"Provide swipe direction UP, DOWN, RIGHT OR LEFT or by giving explicit " +
Expand All @@ -547,6 +548,18 @@ data class YamlFluentCommand(
)
}

private fun swipeRelativeCoordinatesSwipeElementCommand(swipeElement: YamlRelativeCoordinateSwipeElement): MaestroCommand {
return MaestroCommand(
swipeCommand = SwipeCommand(
elementSelector = toElementSelector(swipeElement.from),
endRelative = swipeElement.to,
duration = swipeElement.duration,
label = swipeElement.label,
optional = swipeElement.optional,
)
)
}

private fun toElementSelector(selectorUnion: YamlElementSelectorUnion): ElementSelector {
return if (selectorUnion is StringElementSelector) {
ElementSelector(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface YamlSwipe {
}

data class YamlSwipeDirection(
val direction: SwipeDirection,
val direction: SwipeDirection,
override val duration: Long = DEFAULT_DURATION_IN_MILLIS,
override val label: String? = null,
override val optional: Boolean,
Expand Down Expand Up @@ -50,6 +50,14 @@ data class YamlSwipeElement(
override val optional: Boolean,
) : YamlSwipe

data class YamlRelativeCoordinateSwipeElement(
val from: YamlElementSelectorUnion,
val to: String,
override val duration: Long = DEFAULT_DURATION_IN_MILLIS,
override val label: String? = null,
override val optional: Boolean,
) : YamlSwipe

private const val DEFAULT_DURATION_IN_MILLIS = 400L

class YamlSwipeDeserializer : JsonDeserializer<YamlSwipe>() {
Expand All @@ -62,7 +70,7 @@ class YamlSwipeDeserializer : JsonDeserializer<YamlSwipe>() {
val label = getLabel(root)
val optional = getOptional(root)
when {
input.contains("start") || input.contains("end") -> {
input.contains("start") && input.contains("end") -> {
check(root.get("direction") == null) { "You cannot provide direction with start/end swipe." }
check(root.get("start") != null && root.get("end") != null) {
"You need to provide both start and end coordinates, to swipe with coordinates"
Expand All @@ -88,18 +96,53 @@ class YamlSwipeDeserializer : JsonDeserializer<YamlSwipe>() {
mapper.convertValue(root, YamlSwipeElement::class.java)
}
}
input.contains("from") && input.contains("to") -> {
return resolveRelativeCoordinateSwipeElement(root, duration, label, optional, mapper)
}
else -> {
throw IllegalArgumentException(
"Swipe command takes either: \n" +
"\t1. direction: Direction based swipe with: \"RIGHT\", \"LEFT\", \"UP\", or \"DOWN\" or \n" +
"\t2. start and end: Coordinates based swipe with: \"start\" and \"end\" coordinates \n" +
"\t3. direction and element to swipe directionally on element\n" +
"It seems you provided invalid input with: $input"
"\t1. direction: Direction based swipe with: \"RIGHT\", \"LEFT\", \"UP\", or \"DOWN\" or \n" +
"\t2. start and end: Coordinates based swipe with: \"start\" and \"end\" coordinates \n" +
"\t3. direction and element to swipe directionally on element\n" +
"\t4. from and direction/to: more precise swipe from one point to another\n" +

"It seems you provided invalid input with: $input"
)
}
}
}

private fun resolveRelativeCoordinateSwipeElement(
root: TreeNode,
duration: Long,
label: String?,
optional: Boolean,
mapper: ObjectMapper
): YamlRelativeCoordinateSwipeElement {
val from = mapper.convertValue(root.path("from"), YamlElementSelectorUnion::class.java)
val to = root.path("to").toString().replace("\"", "")

val isRelative = to.contains("%")

if (isRelative) {
val endPoints = to
.replace("%", "")
.split(",")
.map { it.trim().toInt() }
check(endPoints[0] in 0..100 && endPoints[1] in 0..100) {
"Invalid end point: $to should be between 0 to 100 when using relative coordinates."
}
} else {
val endPoints = to
.split(",")
.map { it.trim().toInt() }
check(endPoints.size == 2) { "Invalid format for absolute coordinates: $to" }
}

return YamlRelativeCoordinateSwipeElement(from, to, duration, label, optional)
}

private fun resolveCoordinateSwipe(root: TreeNode, duration: Long, label: String?, optional: Boolean): YamlSwipe {
when {
isRelativeSwipe(root) -> {
Expand Down
Loading