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

Issue 342/enable horizontal scrolling #419

Open
wants to merge 3 commits into
base: master
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kaspersky.kaspresso.autoscroll

import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.UiScrollable
import androidx.test.uiautomator.UiSelector
import com.kaspersky.components.kautomator.intercept.interaction.UiObjectInteraction
Expand Down Expand Up @@ -27,6 +28,7 @@ class ObjectAutoScrollProviderImpl(
*/
override fun <T> withAutoScroll(interaction: UiObjectInteraction, action: () -> T): T {
return try {
interaction.findUiObject()
action.invoke()
} catch (error: Throwable) {
if (error.isAllowed(autoScrollParams.allowedExceptions) && UiScrollable(UiSelector().scrollable(true)).exists()) {
Expand Down Expand Up @@ -56,7 +58,7 @@ class ObjectAutoScrollProviderImpl(
* Scrolls to the bottom and looks for the given view. Invokes the action if the view was found.
*/
do {
if (interaction.uiObject2 != null) {
if (interaction.findUiObject() != null) {
logger.i("UiObject autoscroll to the bottom successfully performed.")
return action.invoke()
} else {
Expand All @@ -68,7 +70,7 @@ class ObjectAutoScrollProviderImpl(
* Scrolls to the beginning and looks for the given view. Invokes the action if the view was found.
*/
do {
if (interaction.uiObject2 != null) {
if (interaction.findUiObject() != null) {
logger.i("UiObject autoscroll to the beginning successfully performed.")
return action.invoke()
} else {
Expand All @@ -79,4 +81,12 @@ class ObjectAutoScrollProviderImpl(
logger.i("UiObject autoscroll did not help. Throwing exception.")
throw cachedError
}

private fun UiObjectInteraction.findUiObject(): UiObject2? {
if (uiObject2 != null) {
return uiObject2
}
reFindUiObject()
return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,36 @@ import com.kaspersky.components.kautomator.intercept.operation.UiOperationType

interface UiScrollableActions : UiBaseActions {

val setUiScrollableOrientation: UiScrollable.() -> UiScrollable

fun scrollToStart() {
view.perform(UiScrollableActionType.SCROLL_TO_START) {
val scrollable = UiScrollable(UiSelector().resourceId(resourceName))
scrollable.setAsVerticalList()
scrollable.setUiScrollableOrientation()
scrollable.flingToBeginning(Int.MAX_VALUE)
}
}

fun scrollToEnd() {
view.perform(UiScrollableActionType.SCROLL_TO_END) {
val scrollable = UiScrollable(UiSelector().resourceId(resourceName))
scrollable.setAsVerticalList()
scrollable.setUiScrollableOrientation()
scrollable.flingToEnd(Int.MAX_VALUE)
}
}

fun <T> scrollToView(to: UiBaseView<T>) {
view.perform(UiScrollableActionType.SCROLL_TO_VIEW) {
val scrollable = UiScrollable(UiSelector().resourceId(resourceName))
scrollable.setUiScrollableOrientation()
do {
if (findObject(to.view.interaction.selector.bySelector) != null)
if (findObject(to.view.interaction.selector.bySelector) != null) {
return@perform
}
} while (scrollable.scrollForward())
do {
if (findObject(to.view.interaction.selector.bySelector) != null)
return@perform
return@perform
} while (scrollable.scrollBackward())
to.isDisplayed()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@file:Suppress("unused")
package com.kaspersky.components.kautomator.component.scroll

import androidx.test.uiautomator.UiScrollable
import com.kaspersky.components.kautomator.component.common.actions.UiScrollableActions
import com.kaspersky.components.kautomator.component.common.actions.UiSwipeableActions
import com.kaspersky.components.kautomator.component.common.builders.UiViewBuilder
import com.kaspersky.components.kautomator.component.common.builders.UiViewSelector
import com.kaspersky.components.kautomator.component.common.views.UiBaseView

class UiHorizontalScrollView : UiBaseView<UiScrollView>, UiSwipeableActions, UiScrollableActions {
constructor(selector: UiViewSelector) : super(selector)
constructor(builder: UiViewBuilder.() -> Unit) : super(builder)

override val setUiScrollableOrientation: UiScrollable.() -> UiScrollable
get() = { setAsHorizontalList() }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@file:Suppress("unused")

package com.kaspersky.components.kautomator.component.scroll

import androidx.test.uiautomator.UiScrollable
import com.kaspersky.components.kautomator.component.common.actions.UiScrollableActions
import com.kaspersky.components.kautomator.component.common.actions.UiSwipeableActions
import com.kaspersky.components.kautomator.component.common.builders.UiViewBuilder
Expand All @@ -10,4 +12,7 @@ import com.kaspersky.components.kautomator.component.common.views.UiBaseView
class UiScrollView : UiBaseView<UiScrollView>, UiSwipeableActions, UiScrollableActions {
constructor(selector: UiViewSelector) : super(selector)
constructor(builder: UiViewBuilder.() -> Unit) : super(builder)

override val setUiScrollableOrientation: UiScrollable.() -> UiScrollable
get() = { setAsVerticalList() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.kaspersky.kaspresso.kautomatorsample.screen

import com.kaspersky.components.kautomator.component.scroll.UiHorizontalScrollView
import com.kaspersky.components.kautomator.component.text.UiButton
import com.kaspersky.components.kautomator.screen.UiScreen

object NestedScrollViewsScreen : UiScreen<NestedScrollViewsScreen>() {

override val packageName: String = "com.kaspersky.kaspresso.kautomatorsample"

val hscrollView = UiHorizontalScrollView { withId([email protected], "hscrollView") }
val nnHscrollView = UiHorizontalScrollView { withId([email protected], "nnHscrollView") }
val hbutton1 = UiButton { withId([email protected], "hvText1") }
val hbutton7 = UiButton { withId([email protected], "hvText7") }
val button1 = UiButton { withId([email protected], "tvText1") }
val button20 = UiButton { withId([email protected], "tvText20") }
val nnHbutton5 = UiButton { withId([email protected], "nnHtvText5") }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.kaspersky.kaspresso.kautomatorsample.test.components

import androidx.test.ext.junit.rules.activityScenarioRule
import com.kaspersky.kaspresso.kautomatorsample.scroll.NestedScrollViewsActivity
import com.kaspersky.kaspresso.kautomatorsample.screen.NestedScrollViewsScreen
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
import org.junit.Rule
import org.junit.Test

/**
* This sample shows how to work with nested vertical and horizontal ScrollViews
*/
class NestedScrollViewsTest : TestCase() {

@get:Rule
val activityRule = activityScenarioRule<NestedScrollViewsActivity>()

@Test
fun click_last_button_in_ScrollView_and_then_first_one() =
run {
step("Click button20 in ScrollView, last item") {
NestedScrollViewsScreen {
button20.click()
}
}

step("Click button1 in ScrollView, first item") {
NestedScrollViewsScreen {
button1.click()
}
}
}

@Test
fun click_last_button_in_ScrollView_and_then_last_one_in_HorizontalScrollView() =
run {
step("Click button20 in ScrollView, last item") {
NestedScrollViewsScreen {
button20.click()
}
}

step("Click hbutton7 in HorizontalScrollView, first item") {
NestedScrollViewsScreen {
hscrollView.scrollToView(hbutton7)
hbutton7.click()
}
}
}

@Test
fun click_last_button_in_HorizontalScrollView_and_then_first_one() =
run {
step("Click hbutton7 in HorizontalScrollView, last item") {
NestedScrollViewsScreen {
hscrollView.scrollToView(hbutton7)
hbutton7.click()
}
}
step("Click hbutton1 in HorizontalScrollView, first item") {
NestedScrollViewsScreen {
hscrollView.scrollToView(hbutton1)
hbutton1.click()
}
}
}

@Test
fun click_last_button_in_3LevelNestedHorizontalScrollView_and_then_last_one_in_1LevelNestedHorizontalScrollView() =
run {
step("Click nnHbutton5 in 3LevelNestedScrollView, middle item") {
NestedScrollViewsScreen {
nnHscrollView.scrollToView(nnHbutton5)
nnHbutton5.click()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by implementing point 2 #342 (comment), nnHscrollView.scrollToView(nnHbutton5) would not be needed since it would be done by the autoscroll.

Same for the other horizontalScrollView#scrollToView() calls in other tests of this class

}
}

step("Click button7 in HorizontalScrollView, last item") {
NestedScrollViewsScreen {
hscrollView.scrollToView(hbutton7)
hbutton7.click()
}
}
}
}
1 change: 1 addition & 0 deletions samples/kautomator-sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<activity android:name=".ComponentsActivity" />
<activity android:name=".recycler.RecyclerActivity" />
<activity android:name=".scroll.ScrollActivity" />
<activity android:name=".scroll.NestedScrollViewsActivity" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.kaspersky.kaspresso.kautomatorsample.scroll

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.kaspersky.kaspresso.kautomatorsample.R

class NestedScrollViewsActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_nested_scrollviews)
}
}
Loading