diff --git a/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt b/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt index 5a1efec332..8444979435 100644 --- a/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt +++ b/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt @@ -95,7 +95,7 @@ data class SwipeCommand( data class ScrollUntilVisibleCommand( val selector: ElementSelector, val direction: ScrollDirection, - val scrollDuration: Long, + val scrollDuration: String = DEFAULT_SCROLL_DURATION, val visibilityPercentage: Int, val timeout: Long = DEFAULT_TIMEOUT_IN_MILLIS, val centerElement: Boolean, @@ -104,6 +104,10 @@ data class ScrollUntilVisibleCommand( val visibilityPercentageNormalized = (visibilityPercentage / 100).toDouble() + private fun String.speedToDuration(): String { + return ((1000 * (100 - this.toLong()).toDouble() / 100).toLong() + 1).toString() + } + override fun description(): String { return label ?: "Scrolling $direction until ${selector.description()} is visible." } @@ -111,12 +115,13 @@ data class ScrollUntilVisibleCommand( override fun evaluateScripts(jsEngine: JsEngine): ScrollUntilVisibleCommand { return copy( selector = selector.evaluateScripts(jsEngine), + scrollDuration = scrollDuration.evaluateScripts(jsEngine).speedToDuration() ) } companion object { const val DEFAULT_TIMEOUT_IN_MILLIS = 20 * 1000L - const val DEFAULT_SCROLL_DURATION = 40 + const val DEFAULT_SCROLL_DURATION = "40" const val DEFAULT_ELEMENT_VISIBILITY_PERCENTAGE = 100 const val DEFAULT_CENTER_ELEMENT = false } diff --git a/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt b/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt index dbd96fcd66..f1b4ab538b 100644 --- a/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt +++ b/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt @@ -500,7 +500,7 @@ class Orchestra( } } catch (ignored: MaestroException.ElementNotFound) { } - maestro.swipeFromCenter(direction, durationMs = command.scrollDuration) + maestro.swipeFromCenter(direction, durationMs = command.scrollDuration.toLong()) } while (System.currentTimeMillis() < endTime) throw MaestroException.ElementNotFound( diff --git a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt index 5873602fea..83a714e8b4 100644 --- a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt +++ b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt @@ -605,7 +605,7 @@ data class YamlFluentCommand( selector = toElementSelector(yaml.element), direction = yaml.direction, timeout = timeout, - scrollDuration = yaml.speedToDuration(), + scrollDuration = yaml.speed, visibilityPercentage = visibility, centerElement = yaml.centerElement, label = yaml.label diff --git a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlScrollUntilVisible.kt b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlScrollUntilVisible.kt index c7967248da..33c374ff0e 100644 --- a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlScrollUntilVisible.kt +++ b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlScrollUntilVisible.kt @@ -9,12 +9,8 @@ data class YamlScrollUntilVisible( val direction: ScrollDirection = ScrollDirection.DOWN, val element: YamlElementSelectorUnion, val timeout: Long = ScrollUntilVisibleCommand.DEFAULT_TIMEOUT_IN_MILLIS, - val speed: Int = ScrollUntilVisibleCommand.DEFAULT_SCROLL_DURATION, + val speed: String = ScrollUntilVisibleCommand.DEFAULT_SCROLL_DURATION, val visibilityPercentage: Int = ScrollUntilVisibleCommand.DEFAULT_ELEMENT_VISIBILITY_PERCENTAGE, val centerElement: Boolean = ScrollUntilVisibleCommand.DEFAULT_CENTER_ELEMENT, val label: String? = null -) { - fun speedToDuration(): Long { - return (1000 * (100 - speed).toDouble() / 100).toLong() + 1 - } -} \ No newline at end of file +) \ No newline at end of file diff --git a/maestro-orchestra/src/test/java/maestro/orchestra/yaml/YamlCommandReaderTest.kt b/maestro-orchestra/src/test/java/maestro/orchestra/yaml/YamlCommandReaderTest.kt index dedaa7b6ec..f53040bb80 100644 --- a/maestro-orchestra/src/test/java/maestro/orchestra/yaml/YamlCommandReaderTest.kt +++ b/maestro-orchestra/src/test/java/maestro/orchestra/yaml/YamlCommandReaderTest.kt @@ -433,7 +433,7 @@ internal class YamlCommandReaderTest { selector = ElementSelector(textRegex = "Footer"), direction = ScrollDirection.DOWN, timeout = 20000, - scrollDuration = 601, + scrollDuration = "40", visibilityPercentage = 100, label = "Scroll to the bottom", centerElement = false diff --git a/maestro-test/src/test/kotlin/maestro/test/IntegrationTest.kt b/maestro-test/src/test/kotlin/maestro/test/IntegrationTest.kt index 58b115c305..e0958bf8a9 100644 --- a/maestro-test/src/test/kotlin/maestro/test/IntegrationTest.kt +++ b/maestro-test/src/test/kotlin/maestro/test/IntegrationTest.kt @@ -2537,15 +2537,17 @@ class IntegrationTest { } // Then - driver.assertHasEvent(Event.LaunchApp( - appId = "com.example.app", - launchArguments = mapOf( - "argumentA" to true, - "argumentB" to 4, - "argumentC" to 4.0, - "argumentD" to "Hello String Value true" + driver.assertHasEvent( + Event.LaunchApp( + appId = "com.example.app", + launchArguments = mapOf( + "argumentA" to true, + "argumentB" to 4, + "argumentC" to 4.0, + "argumentD" to "Hello String Value true" + ) ) - )) + ) } @Test @@ -2931,7 +2933,7 @@ class IntegrationTest { fun `Case 110 - addMedia command emits add media event with correct path`() { // given val commands = readCommands("110_add_media_device") - val driver = driver {} + val driver = driver {} // when Maestro(driver).use { @@ -2946,7 +2948,7 @@ class IntegrationTest { fun `Case 111 - addMedia command allows adding multiple media`() { // given val commands = readCommands("111_add_multiple_media") - val driver = driver { } + val driver = driver { } // when Maestro(driver).use { @@ -3061,7 +3063,7 @@ class IntegrationTest { } @Test - fun `Case 115 - airplane mode`() { + fun `Case 115 - airplane mode`() { val commands = readCommands("115_airplane_mode") val driver = driver { } @@ -3069,7 +3071,7 @@ class IntegrationTest { orchestra(it).runFlow(commands) } } - + @Test fun `Case 116 - Kill app`() { // Given @@ -3089,6 +3091,38 @@ class IntegrationTest { driver.assertHasEvent(Event.KillApp("another.app")) } + @Test + fun `Case 117 - Scroll until view is visible - with speed evaluate`() { + // Given + val commands = readCommands("117_scroll_until_visible_speed") + val expectedDuration = "601" + val info = driver { }.deviceInfo() + + val elementBounds = Bounds(0, 0 + info.heightGrid, 100, 100 + info.heightGrid) + val driver = driver { + element { + id = "maestro" + bounds = elementBounds + } + } + + // When + var scrollDuration = "0" + Maestro(driver).use { + orchestra(it, onCommandMetadataUpdate = { _, metaData -> + scrollDuration = metaData.evaluatedCommand?.scrollUntilVisible?.scrollDuration.toString() + }).runFlow(commands) + } + + // Then + assertThat(scrollDuration).isEqualTo(expectedDuration) + driver.assertEvents( + listOf( + Event.SwipeElementWithDirection(Point(270, 480), SwipeDirection.UP, expectedDuration.toLong()), + ) + ) + } + private fun orchestra( maestro: Maestro, ) = Orchestra( diff --git a/maestro-test/src/test/resources/117_scroll_until_visible_speed.js b/maestro-test/src/test/resources/117_scroll_until_visible_speed.js new file mode 100644 index 0000000000..ad33541120 --- /dev/null +++ b/maestro-test/src/test/resources/117_scroll_until_visible_speed.js @@ -0,0 +1,6 @@ +output.speed = { + slow: 40 +} +output.element = { + id: "maestro" +} \ No newline at end of file diff --git a/maestro-test/src/test/resources/117_scroll_until_visible_speed.yaml b/maestro-test/src/test/resources/117_scroll_until_visible_speed.yaml new file mode 100644 index 0000000000..656d554465 --- /dev/null +++ b/maestro-test/src/test/resources/117_scroll_until_visible_speed.yaml @@ -0,0 +1,8 @@ +appId: com.example.app +--- +- runScript: 117_scroll_until_visible_speed.js +- scrollUntilVisible: + element: + id: ${output.element.id} + direction: DOWN + speed: ${output.speed.slow} \ No newline at end of file