-
Notifications
You must be signed in to change notification settings - Fork 299
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
Reland iOS landscape mode support #1974
Changes from all commits
cdaab6f
9ae06fe
1c0228e
addac1e
9b929e7
d75bd93
6920c11
7f13ca9
8bab954
3cfb908
dae0fe6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,5 +41,4 @@ data class Point( | |
fun distance(other: Point): Float { | ||
return distance(x, y, other.x, other.y) | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,17 +42,6 @@ class IOSDriver( | |
private val iosDevice: IOSDevice, | ||
) : Driver { | ||
|
||
private val deviceInfo by lazy { | ||
iosDevice.deviceInfo() | ||
} | ||
|
||
private val widthPoints by lazy { | ||
deviceInfo.widthPoints | ||
} | ||
private val heightPoints by lazy { | ||
deviceInfo.heightPoints | ||
} | ||
|
||
private var appId: String? = null | ||
private var proxySet = false | ||
|
||
|
@@ -73,15 +62,7 @@ class IOSDriver( | |
} | ||
|
||
override fun deviceInfo(): DeviceInfo { | ||
return runDeviceCall { | ||
DeviceInfo( | ||
platform = Platform.IOS, | ||
widthPixels = deviceInfo.widthPixels, | ||
heightPixels = deviceInfo.heightPixels, | ||
widthGrid = deviceInfo.widthPoints, | ||
heightGrid = deviceInfo.heightPoints, | ||
) | ||
} | ||
return runDeviceCall { iosDevice.deviceInfo().toCommonDeviceInfo() } | ||
} | ||
|
||
override fun launchApp( | ||
|
@@ -200,9 +181,13 @@ class IOSDriver( | |
} | ||
|
||
override fun scrollVertical() { | ||
val deviceInfo = deviceInfo() | ||
val width = deviceInfo.widthGrid | ||
val height = deviceInfo.heightGrid | ||
|
||
swipe( | ||
start = Point(widthPercentToPoint(0.5), heightPercentToPoint(0.5)), | ||
end = Point(widthPercentToPoint(0.5), heightPercentToPoint(0.1)), | ||
start = Point(0.5.asPercentOf(width), 0.5.asPercentOf(height)), | ||
end = Point(0.5.asPercentOf(width), 0.1.asPercentOf(height)), | ||
durationMs = 333, | ||
) | ||
} | ||
|
@@ -211,32 +196,14 @@ class IOSDriver( | |
return runDeviceCall { iosDevice.isKeyboardVisible() } | ||
} | ||
|
||
private fun validate(start: Point, end: Point): Pair<Point, Point> { | ||
val screenWidth = widthPoints | ||
val screenHeight = heightPoints | ||
|
||
val validatedStart = Point( | ||
x = start.x.coerceIn(0, screenWidth), | ||
y = start.y.coerceIn(0, screenHeight) | ||
) | ||
|
||
val validatedEnd = Point( | ||
x = end.x.coerceIn(0, screenWidth), | ||
y = end.y.coerceIn(0, screenHeight) | ||
) | ||
|
||
return Pair(validatedStart, validatedEnd) | ||
} | ||
|
||
override fun swipe( | ||
start: Point, | ||
end: Point, | ||
durationMs: Long | ||
) { | ||
val validatedPoints = validate(start, end) | ||
|
||
val startPoint = validatedPoints.first | ||
val endPoint = validatedPoints.second | ||
val deviceInfo = deviceInfo() | ||
val startPoint = start.coerceIn(maxWidth = deviceInfo.widthGrid, maxHeight = deviceInfo.heightGrid) | ||
val endPoint = end.coerceIn(maxWidth = deviceInfo.widthGrid, maxHeight = deviceInfo.heightGrid) | ||
|
||
runDeviceCall { | ||
waitForAppToSettle(null, null) | ||
|
@@ -251,70 +218,84 @@ class IOSDriver( | |
} | ||
|
||
override fun swipe(swipeDirection: SwipeDirection, durationMs: Long) { | ||
val deviceInfo = deviceInfo() | ||
val width = deviceInfo.widthGrid | ||
val height = deviceInfo.heightGrid | ||
|
||
val startPoint: Point | ||
val endPoint: Point | ||
|
||
when (swipeDirection) { | ||
SwipeDirection.UP -> { | ||
startPoint = Point( | ||
x = widthPercentToPoint(0.5), | ||
y = heightPercentToPoint(0.9), | ||
x = 0.5.asPercentOf(width), | ||
y = 0.9.asPercentOf(height), | ||
) | ||
endPoint = Point( | ||
x = widthPercentToPoint(0.5), | ||
y = heightPercentToPoint(0.1), | ||
x = 0.5.asPercentOf(width), | ||
y = 0.1.asPercentOf(height), | ||
) | ||
} | ||
|
||
SwipeDirection.DOWN -> { | ||
startPoint = Point( | ||
x = widthPercentToPoint(0.5), | ||
y = heightPercentToPoint(0.2), | ||
x = 0.5.asPercentOf(width), | ||
y = 0.2.asPercentOf(height), | ||
) | ||
endPoint = Point( | ||
x = widthPercentToPoint(0.5), | ||
y = heightPercentToPoint(0.9), | ||
x = 0.5.asPercentOf(width), | ||
y = 0.9.asPercentOf(height), | ||
) | ||
} | ||
|
||
SwipeDirection.RIGHT -> { | ||
startPoint = Point( | ||
x = widthPercentToPoint(0.1), | ||
y = heightPercentToPoint(0.5), | ||
x = 0.1.asPercentOf(width), | ||
y = 0.5.asPercentOf(height), | ||
) | ||
endPoint = Point( | ||
x = widthPercentToPoint(0.9), | ||
y = heightPercentToPoint(0.5), | ||
x = 0.9.asPercentOf(width), | ||
y = 0.5.asPercentOf(height), | ||
) | ||
} | ||
|
||
SwipeDirection.LEFT -> { | ||
startPoint = Point( | ||
x = widthPercentToPoint(0.9), | ||
y = heightPercentToPoint(0.5), | ||
x = 0.9.asPercentOf(width), | ||
y = 0.5.asPercentOf(height), | ||
) | ||
endPoint = Point( | ||
x = widthPercentToPoint(0.1), | ||
y = heightPercentToPoint(0.5), | ||
x = 0.1.asPercentOf(width), | ||
y = 0.5.asPercentOf(height), | ||
) | ||
} | ||
} | ||
swipe(startPoint, endPoint, durationMs) | ||
} | ||
|
||
override fun swipe(elementPoint: Point, direction: SwipeDirection, durationMs: Long) { | ||
val deviceInfo = deviceInfo() | ||
val width = deviceInfo.widthGrid | ||
val height = deviceInfo.heightGrid | ||
|
||
when (direction) { | ||
SwipeDirection.UP -> { | ||
val end = Point(x = elementPoint.x, y = heightPercentToPoint(0.1)) | ||
val end = Point(x = elementPoint.x, y = 0.1.asPercentOf(height)) | ||
swipe(elementPoint, end, durationMs) | ||
} | ||
|
||
SwipeDirection.DOWN -> { | ||
val end = Point(x = elementPoint.x, y = heightPercentToPoint(0.9)) | ||
val end = Point(x = elementPoint.x, y = 0.9.asPercentOf(height)) | ||
swipe(elementPoint, end, durationMs) | ||
} | ||
|
||
SwipeDirection.RIGHT -> { | ||
val end = Point(x = widthPercentToPoint(0.9), y = elementPoint.y) | ||
val end = Point(x = (0.9).asPercentOf(width), y = elementPoint.y) | ||
swipe(elementPoint, end, durationMs) | ||
} | ||
|
||
SwipeDirection.LEFT -> { | ||
val end = Point(x = widthPercentToPoint(0.1), y = elementPoint.y) | ||
val end = Point(x = (0.1).asPercentOf(width), y = elementPoint.y) | ||
swipe(elementPoint, end, durationMs) | ||
} | ||
} | ||
|
@@ -323,21 +304,25 @@ class IOSDriver( | |
override fun backPress() {} | ||
|
||
override fun hideKeyboard() { | ||
dismissKeyboardIntroduction() | ||
val deviceInfo = deviceInfo() | ||
val width = deviceInfo.widthGrid | ||
val height = deviceInfo.heightGrid | ||
|
||
dismissKeyboardIntroduction(heightPoints = deviceInfo.heightGrid) | ||
|
||
if (isKeyboardHidden()) return | ||
|
||
swipe( | ||
start = Point(widthPercentToPoint(0.5), heightPercentToPoint(0.5)), | ||
end = Point(widthPercentToPoint(0.5), heightPercentToPoint(0.47)), | ||
start = Point(0.5.asPercentOf(width), 0.5.asPercentOf(height)), | ||
end = Point(0.5.asPercentOf(width), 0.47.asPercentOf(height)), | ||
durationMs = 50, | ||
) | ||
|
||
if (isKeyboardHidden()) return | ||
|
||
swipe( | ||
start = Point(widthPercentToPoint(0.5), heightPercentToPoint(0.5)), | ||
end = Point(widthPercentToPoint(0.47), heightPercentToPoint(0.5)), | ||
start = Point(0.5.asPercentOf(width), 0.5.asPercentOf(height)), | ||
end = Point(0.47.asPercentOf(width), 0.5.asPercentOf(height)), | ||
durationMs = 50, | ||
) | ||
|
||
|
@@ -353,8 +338,9 @@ class IOSDriver( | |
return element == null | ||
} | ||
|
||
private fun dismissKeyboardIntroduction() { | ||
val fastTypingInstruction = "Speed up your typing by sliding your finger across the letters to compose a word.*".toRegex() | ||
private fun dismissKeyboardIntroduction(heightPoints: Int) { | ||
val fastTypingInstruction = | ||
"Speed up your typing by sliding your finger across the letters to compose a word.*".toRegex() | ||
val instructionTextFilter = Filters.textMatches(fastTypingInstruction) | ||
val instructionText = MaestroTimer.withTimeout(2000) { | ||
instructionTextFilter(contentDescriptor().aggregate()).firstOrNull() | ||
|
@@ -472,14 +458,6 @@ class IOSDriver( | |
return runDeviceCall { iosDevice.isScreenStatic() } | ||
} | ||
|
||
private fun heightPercentToPoint(percent: Double): Int { | ||
return (percent * heightPoints).toInt() | ||
} | ||
|
||
private fun widthPercentToPoint(percent: Double): Int { | ||
return (percent * widthPoints).toInt() | ||
} | ||
|
||
private fun awaitLaunch() { | ||
val startTime = System.currentTimeMillis() | ||
|
||
|
@@ -529,3 +507,14 @@ class IOSDriver( | |
private const val SCREEN_SETTLE_TIMEOUT_MS: Long = 3000 | ||
} | ||
} | ||
|
||
private fun Double.asPercentOf(total: Int): Int { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's the advantage of this over the regular private functions from before? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Conciseness, mainly. If I were to keep using |
||
return (this * total).toInt() | ||
} | ||
|
||
private fun Point.coerceIn(maxWidth: Int, maxHeight: Int): Point { | ||
return Point( | ||
x = x.coerceIn(0, maxWidth), | ||
y = y.coerceIn(0, maxHeight), | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesnt seem to use the cached info - is that the intent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
If we use the cached version, then swipe will completely break if the device is rotated mid-flow (or when running
maestro test
in--continuous
mode).