diff --git a/gradle.properties b/gradle.properties
index 045020de..28ffeb12 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -16,7 +16,7 @@ kotlin.code.style=official
android.useAndroidX=true
GROUP=com.atiurin
POM_ARTIFACT_ID=ultron
-VERSION_NAME=1.0.17
+VERSION_NAME=1.0.18
POM_NAME=ultron
POM_PACKAGING=aar
diff --git a/sample-app/src/androidTest/java/com/atiurin/sampleapp/tests/espresso/CustomClicksTest.kt b/sample-app/src/androidTest/java/com/atiurin/sampleapp/tests/espresso/CustomClicksTest.kt
new file mode 100644
index 00000000..51df31fe
--- /dev/null
+++ b/sample-app/src/androidTest/java/com/atiurin/sampleapp/tests/espresso/CustomClicksTest.kt
@@ -0,0 +1,69 @@
+package com.atiurin.sampleapp.tests.espresso
+
+import androidx.test.core.app.ActivityScenario
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import com.atiurin.sampleapp.R
+import com.atiurin.sampleapp.activity.CustomClicksActivity
+import com.atiurin.sampleapp.tests.BaseTest
+import com.atiurin.ultron.extensions.*
+import com.atiurin.ultron.testlifecycle.setupteardown.SetUpRule
+import org.junit.Test
+
+class CustomClicksTest : BaseTest() {
+
+ private val startActivity = SetUpRule().add {
+ ActivityScenario.launch(CustomClicksActivity::class.java)
+ }
+
+ init {
+ ruleSequence.addLast(startActivity)
+ }
+
+ @Test
+ fun clickTopLeft() {
+ withId(R.id.imageView).clickTopLeft(offsetX = 30, offsetY = 30)
+ withId(R.id.rB_top_left).isChecked()
+ }
+
+ @Test
+ fun clickTopCenter() {
+ withId(R.id.imageView).clickTopCenter(offsetY = 30)
+ withId(R.id.rB_top_center).isChecked()
+ }
+
+ @Test
+ fun clickTopRight() {
+ withId(R.id.imageView).clickTopRight(offsetX = -30, offsetY = 30)
+ withId(R.id.rB_top_right).isChecked()
+ }
+
+ @Test
+ fun clickCenterRight() {
+ withId(R.id.imageView).clickCenterRight(offsetX = -30)
+ withId(R.id.rB_center_right).isChecked()
+ }
+
+ @Test
+ fun clickBottomRight() {
+ withId(R.id.imageView).clickBottomRight(offsetX = -30, offsetY = -30)
+ withId(R.id.rB_bottom_right).isChecked()
+ }
+
+ @Test
+ fun clickBottomCenter() {
+ withId(R.id.imageView).clickBottomCenter(offsetY = -30)
+ withId(R.id.rB_bottom_center).isChecked()
+ }
+
+ @Test
+ fun clickBottomLeft() {
+ withId(R.id.imageView).clickBottomLeft(offsetX = 30, offsetY = -30)
+ withId(R.id.rB_bottom_left).isChecked()
+ }
+
+ @Test
+ fun clickCenterLeft() {
+ withId(R.id.imageView).clickCenterLeft(offsetX = 30)
+ withId(R.id.rB_center_left).isChecked()
+ }
+}
\ No newline at end of file
diff --git a/sample-app/src/main/AndroidManifest.xml b/sample-app/src/main/AndroidManifest.xml
index 800919d4..e465263a 100644
--- a/sample-app/src/main/AndroidManifest.xml
+++ b/sample-app/src/main/AndroidManifest.xml
@@ -1,20 +1,20 @@
+ package="com.atiurin.sampleapp">
+
-
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:requestLegacyExternalStorage="true"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme"
+ android:usesCleartextTraffic="true">
+
@@ -22,31 +22,28 @@
-
+ android:name="com.atiurin.sampleapp.activity.MainActivity"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme.NoActionBar" />
-
+ android:name="com.atiurin.sampleapp.activity.ChatActivity"
+ android:theme="@style/AppTheme.NoActionBar" />
-
+ android:name="com.atiurin.sampleapp.activity.LoginActivity"
+ android:theme="@style/AppTheme" />
-
+ android:name="com.atiurin.sampleapp.activity.ProfileActivity"
+ android:theme="@style/AppTheme.NoActionBar" />
-
+ android:name="com.atiurin.sampleapp.activity.UiElementsActivity"
+ android:theme="@style/AppTheme.NoActionBar" />
-
+ android:theme="@style/AppTheme.NoActionBar" />
+
\ No newline at end of file
diff --git a/sample-app/src/main/java/com/atiurin/sampleapp/activity/CustomClicksActivity.kt b/sample-app/src/main/java/com/atiurin/sampleapp/activity/CustomClicksActivity.kt
new file mode 100644
index 00000000..a2428411
--- /dev/null
+++ b/sample-app/src/main/java/com/atiurin/sampleapp/activity/CustomClicksActivity.kt
@@ -0,0 +1,12 @@
+package com.atiurin.sampleapp.activity
+
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import com.atiurin.sampleapp.R
+
+class CustomClicksActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_custom_clicks)
+ }
+}
\ No newline at end of file
diff --git a/sample-app/src/main/java/com/atiurin/sampleapp/activity/MainActivity.kt b/sample-app/src/main/java/com/atiurin/sampleapp/activity/MainActivity.kt
index daf046ad..b9c3cab9 100644
--- a/sample-app/src/main/java/com/atiurin/sampleapp/activity/MainActivity.kt
+++ b/sample-app/src/main/java/com/atiurin/sampleapp/activity/MainActivity.kt
@@ -132,6 +132,10 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
val intent = Intent(applicationContext, WebViewActivity::class.java)
startActivity(intent)
}
+ R.id.custom_clicks_nav_item -> {
+ val intent = Intent(applicationContext, CustomClicksActivity::class.java)
+ startActivity(intent)
+ }
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
drawerLayout.closeDrawer(GravityCompat.START)
diff --git a/sample-app/src/main/res/layout/activity_custom_clicks.xml b/sample-app/src/main/res/layout/activity_custom_clicks.xml
new file mode 100644
index 00000000..c5c8659e
--- /dev/null
+++ b/sample-app/src/main/res/layout/activity_custom_clicks.xml
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample-app/src/main/res/menu/activity_main_drawer.xml b/sample-app/src/main/res/menu/activity_main_drawer.xml
index 1f0d5536..115a80cc 100644
--- a/sample-app/src/main/res/menu/activity_main_drawer.xml
+++ b/sample-app/src/main/res/menu/activity_main_drawer.xml
@@ -29,7 +29,11 @@
+ android:title="@string/menu_web_view" />
+
diff --git a/sample-app/src/main/res/values/strings.xml b/sample-app/src/main/res/values/strings.xml
index f5e9dac5..42d48e29 100644
--- a/sample-app/src/main/res/values/strings.xml
+++ b/sample-app/src/main/res/values/strings.xml
@@ -35,5 +35,6 @@
Double Click
Default AppCompatTextView
+ Custom Clicks
diff --git a/ultron/src/main/java/com/atiurin/ultron/core/espresso/UltronEspressoInteraction.kt b/ultron/src/main/java/com/atiurin/ultron/core/espresso/UltronEspressoInteraction.kt
index bce7280a..6261bc70 100644
--- a/ultron/src/main/java/com/atiurin/ultron/core/espresso/UltronEspressoInteraction.kt
+++ b/ultron/src/main/java/com/atiurin/ultron/core/espresso/UltronEspressoInteraction.kt
@@ -3,6 +3,8 @@ package com.atiurin.ultron.core.espresso
import android.view.View
import androidx.test.espresso.*
import androidx.test.espresso.action.EspressoKey
+import androidx.test.espresso.action.GeneralLocation
+import androidx.test.espresso.action.Tap
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.assertion.ViewAssertions.matches
@@ -11,6 +13,7 @@ import com.atiurin.ultron.core.config.UltronConfig
import com.atiurin.ultron.core.espresso.UltronEspresso.executeAction
import com.atiurin.ultron.core.espresso.UltronEspresso.executeAssertion
import com.atiurin.ultron.core.espresso.action.EspressoActionType
+import com.atiurin.ultron.core.espresso.action.UltronCustomClickAction
import com.atiurin.ultron.core.espresso.assertion.EspressoAssertionType
import com.atiurin.ultron.custom.espresso.assertion.ExistsEspressoViewAssertion
import com.atiurin.ultron.exceptions.UltronException
@@ -31,6 +34,10 @@ class UltronEspressoInteraction(
)
}
+ private fun getActionTimeout(): Long = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
+
+ private fun getAssertionTimeout(): Long = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
+
fun withResultHandler(resultHandler: (EspressoOperationResult) -> Unit): UltronEspressoInteraction {
return UltronEspressoInteraction(this.interaction, this.timeoutMs, resultHandler)
}
@@ -39,211 +46,245 @@ class UltronEspressoInteraction(
return UltronEspressoInteraction(this.interaction, timeoutMs, this.resultHandler)
}
+ // =========== CUSTOM CLICKS ============================
+ private fun customClick(type: EspressoActionType, location: GeneralLocation, offsetX: Int, offsetY: Int) = apply {
+ executeAction(
+ UltronEspressoOperation(
+ operationBlock = getInteractionActionBlock(
+ UltronCustomClickAction(Tap.SINGLE, location, areaPercentage = 20, offsetX = offsetX, offsetY = offsetY)
+ ),
+ name = "$type for '${getInteractionMatcher()}'",
+ type = type,
+ description = "${interaction!!::class.java.simpleName} action '${type}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
+ ),
+ resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
+ )
+ }
+
+ fun clickTopLeft(offsetX: Int, offsetY: Int) = apply {
+ customClick(EspressoActionType.CLICK_TOP_LEFT, GeneralLocation.TOP_LEFT, offsetX = offsetX, offsetY = offsetY)
+ }
+
+ fun clickTopCenter(offsetY: Int) = apply {
+ customClick(EspressoActionType.CLICK_TOP_CENTER, GeneralLocation.TOP_CENTER, offsetY = offsetY, offsetX = 0)
+ }
+
+ fun clickTopRight(offsetX: Int, offsetY: Int) = apply {
+ customClick(EspressoActionType.CLICK_TOP_RIGHT, GeneralLocation.TOP_RIGHT, offsetY = offsetY, offsetX = offsetX)
+ }
+
+ fun clickCenterRight(offsetX: Int) = apply {
+ customClick(EspressoActionType.CLICK_CENTER_RIGHT, GeneralLocation.CENTER_RIGHT, offsetY = 0, offsetX = offsetX)
+ }
+
+ fun clickBottomRight(offsetX: Int, offsetY: Int) = apply {
+ customClick(EspressoActionType.CLICK_BOTTOM_RIGHT, GeneralLocation.BOTTOM_RIGHT, offsetY = offsetY, offsetX = offsetX)
+ }
+
+ fun clickBottomCenter(offsetY: Int) = apply {
+ customClick(EspressoActionType.CLICK_BOTTOM_CENTER, GeneralLocation.BOTTOM_CENTER, offsetY = offsetY, offsetX = 0)
+ }
+
+ fun clickBottomLeft(offsetX: Int, offsetY: Int) = apply {
+ customClick(EspressoActionType.CLICK_BOTTOM_LEFT, GeneralLocation.BOTTOM_LEFT, offsetY = offsetY, offsetX = offsetX)
+ }
+
+ fun clickCenterLeft(offsetX: Int) = apply {
+ customClick(EspressoActionType.CLICK_CENTER_LEFT, GeneralLocation.CENTER_LEFT, offsetY = 0, offsetX = offsetX)
+ }
+ // ======================================================
+
fun click() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.click()),
name = "Click to '${getInteractionMatcher()}'",
type = EspressoActionType.CLICK,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CLICK}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CLICK}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun doubleClick() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.doubleClick()),
name = "DoubleClick to '${getInteractionMatcher()}'",
type = EspressoActionType.CLICK,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.DOUBLE_CLICK}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.DOUBLE_CLICK}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun longClick() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.longClick()),
name = "LongClick to '${getInteractionMatcher()}'",
type = EspressoActionType.LONG_CLICK,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.LONG_CLICK}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.LONG_CLICK}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun typeText(text: String) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.typeText(text)),
name = "Type text '$text' to '${getInteractionMatcher()}'",
type = EspressoActionType.TYPE_TEXT,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.TYPE_TEXT}' '$text' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.TYPE_TEXT}' '$text' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun replaceText(text: String) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.replaceText(text)),
name = "Replace text '$text' to '${getInteractionMatcher()}'",
type = EspressoActionType.REPLACE_TEXT,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.REPLACE_TEXT}' '$text' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.REPLACE_TEXT}' '$text' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun clearText() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.clearText()),
name = "Clear text in '${getInteractionMatcher()}'",
type = EspressoActionType.CLEAR_TEXT,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CLEAR_TEXT}' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CLEAR_TEXT}' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun pressKey(keyCode: Int) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.pressKey(keyCode)),
name = "PressKey code '$keyCode' on '${getInteractionMatcher()}'",
type = EspressoActionType.PRESS_KEY,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.PRESS_KEY}' '$keyCode' on '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.PRESS_KEY}' '$keyCode' on '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun pressKey(key: EspressoKey) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.pressKey(key)),
name = "Press EspressoKey '$key' on '${getInteractionMatcher()}'",
type = EspressoActionType.PRESS_KEY,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.PRESS_KEY}' EspressoKey '$key' on '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.PRESS_KEY}' EspressoKey '$key' on '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun closeSoftKeyboard() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.closeSoftKeyboard()),
name = "CloseSoftKeyboard with '${getInteractionMatcher()}'",
type = EspressoActionType.CLOSE_SOFT_KEYBOARD,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CLOSE_SOFT_KEYBOARD}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CLOSE_SOFT_KEYBOARD}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun swipeLeft() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.swipeLeft()),
name = "SwipeLeft with '${getInteractionMatcher()}'",
type = EspressoActionType.SWIPE_LEFT,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_LEFT}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_LEFT}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun swipeRight() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.swipeRight()),
name = "SwipeRight with '${getInteractionMatcher()}'",
type = EspressoActionType.SWIPE_RIGHT,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_RIGHT}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_RIGHT}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun swipeUp() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.swipeUp()),
name = "SwipeUp with '${getInteractionMatcher()}'",
type = EspressoActionType.SWIPE_UP,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_UP}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_UP}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun swipeDown() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.swipeDown()),
name = "SwipeDown with '${getInteractionMatcher()}'",
type = EspressoActionType.SWIPE_DOWN,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_DOWN}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SWIPE_DOWN}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun scrollTo() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(ViewActions.scrollTo()),
name = "ScrollTo with '${getInteractionMatcher()}'",
type = EspressoActionType.SCROLL,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SCROLL}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.SCROLL}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
}
fun perform(viewAction: ViewAction, description: String = "") = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ACTION_TIMEOUT
executeAction(
UltronEspressoOperation(
operationBlock = getInteractionActionBlock(viewAction),
name = "Custom action '$description' to ${getInteractionMatcher()}",
type = EspressoActionType.CUSTOM,
- description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CUSTOM}' of '${viewAction.description}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} action '${EspressoActionType.CUSTOM}' of '${viewAction.description}' to '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getActionTimeout()} ms",
+ timeoutMs = getActionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewActionConfig.resultHandler
)
@@ -251,14 +292,13 @@ class UltronEspressoInteraction(
//assertion
fun isDisplayed() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isDisplayed()),
name = "IsDisplayed of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_DISPLAYED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_DISPLAYED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_DISPLAYED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
@@ -269,14 +309,13 @@ class UltronEspressoInteraction(
* If these is no element in view hierarchy it throws [NoMatchingViewException]. In this case use [doesNotExist]
*/
fun isNotDisplayed() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(Matchers.not(ViewMatchers.isDisplayed())),
name = "IsNotDisplayed of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_NOT_DISPLAYED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_DISPLAYED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_DISPLAYED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
@@ -286,14 +325,13 @@ class UltronEspressoInteraction(
* Asserts ui element presents in view hierarchy
*/
fun exists() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ExistsEspressoViewAssertion()),
name = "Exists of '${getInteractionMatcher()}'",
type = EspressoAssertionType.EXISTS,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.EXISTS}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.EXISTS}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
@@ -303,35 +341,32 @@ class UltronEspressoInteraction(
* Asserts ui element isn't presents in view hierarchy
*/
fun doesNotExist() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewAssertions.doesNotExist()),
name = "DoesNotExist of '${getInteractionMatcher()}'",
type = EspressoAssertionType.DOES_NOT_EXIST,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.DOES_NOT_EXIST}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.DOES_NOT_EXIST}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isCompletelyDisplayed() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isCompletelyDisplayed()),
name = "IsCompletelyDisplayed of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_COMPLETELY_DISPLAYED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_COMPLETELY_DISPLAYED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_COMPLETELY_DISPLAYED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isDisplayingAtLeast(percentage: Int) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(
@@ -341,225 +376,209 @@ class UltronEspressoInteraction(
),
name = "IsDisplayingAtLeast '$percentage'% of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_DISPLAYING_AT_LEAST,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_DISPLAYING_AT_LEAST}' '$percentage'% of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_DISPLAYING_AT_LEAST}' '$percentage'% of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isEnabled() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isEnabled()),
name = "IsEnabled of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_ENABLED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_ENABLED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_ENABLED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isNotEnabled() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(Matchers.not(ViewMatchers.isEnabled())),
name = "IsNotEnabled of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_NOT_ENABLED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_ENABLED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_ENABLED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isSelected() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isSelected()),
name = "IsSelected of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_SELECTED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_SELECTED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_SELECTED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isNotSelected() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(Matchers.not(ViewMatchers.isSelected())),
name = "IsNotSelected of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_NOT_SELECTED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_SELECTED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_SELECTED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isClickable() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isClickable()),
name = "IsClickable of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_CLICKABLE,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_CLICKABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_CLICKABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isNotClickable() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(Matchers.not(ViewMatchers.isClickable())),
name = "IsNotClickable of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_NOT_CLICKABLE,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_CLICKABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_CLICKABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isChecked() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isChecked()),
name = "IsChecked of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_CHECKED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_CHECKED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_CHECKED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isNotChecked() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isNotChecked()),
name = "IsNotChecked of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_NOT_CHECKED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_CHECKED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_CHECKED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isFocusable() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isFocusable()),
name = "IsFocusable of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_FOCUSABLE,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_FOCUSABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_FOCUSABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isNotFocusable() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(Matchers.not(ViewMatchers.isFocusable())),
name = "IsNotFocusable of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_NOT_FOCUSABLE,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_FOCUSABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_NOT_FOCUSABLE}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun hasFocus() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.hasFocus()),
name = "HasFocus of '${getInteractionMatcher()}'",
type = EspressoAssertionType.HAS_FOCUS,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_FOCUS}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_FOCUS}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun isJavascriptEnabled() = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.isJavascriptEnabled()),
name = "IsJavascriptEnabled of '${getInteractionMatcher()}'",
type = EspressoAssertionType.IS_JS_ENABLED,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_JS_ENABLED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.IS_JS_ENABLED}' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun hasText(text: String) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.withText(text)),
name = "HasText '$text' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.HAS_TEXT,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_TEXT}' '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_TEXT}' '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun hasText(resourceId: Int) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.withText(resourceId)),
name = "HasText with resourceId '$resourceId' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.HAS_TEXT,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_TEXT}' with resourceId '$resourceId' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_TEXT}' with resourceId '$resourceId' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun hasText(stringMatcher: Matcher) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(ViewMatchers.withText(stringMatcher)),
name = "HasText with matcher '$stringMatcher' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.HAS_TEXT,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_TEXT}' with matcher '$stringMatcher' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_TEXT}' with matcher '$stringMatcher' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun textContains(text: String) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(
@@ -571,15 +590,14 @@ class UltronEspressoInteraction(
),
name = "ContainsText '$text' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.CONTAINS_TEXT,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.CONTAINS_TEXT}' '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.CONTAINS_TEXT}' '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun hasContentDescription(text: String) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(
@@ -589,15 +607,14 @@ class UltronEspressoInteraction(
),
name = "HasContentDescription '$text' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.HAS_CONTENT_DESCRIPTION,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_CONTENT_DESCRIPTION}' '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_CONTENT_DESCRIPTION}' '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun hasContentDescription(resourceId: Int) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(
@@ -607,15 +624,14 @@ class UltronEspressoInteraction(
),
name = "HasContentDescription resourceId = '$resourceId' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.HAS_CONTENT_DESCRIPTION,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_CONTENT_DESCRIPTION}' resourceId = '$resourceId' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_CONTENT_DESCRIPTION}' resourceId = '$resourceId' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun hasContentDescription(charSequenceMatcher: Matcher) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(
@@ -625,15 +641,14 @@ class UltronEspressoInteraction(
),
name = "HasContentDescription charSequenceMatcher = '$charSequenceMatcher' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.HAS_CONTENT_DESCRIPTION,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_CONTENT_DESCRIPTION}' charSequenceMatcher = '$charSequenceMatcher' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.HAS_CONTENT_DESCRIPTION}' charSequenceMatcher = '$charSequenceMatcher' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun contentDescriptionContains(text: String) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(
@@ -643,22 +658,21 @@ class UltronEspressoInteraction(
),
name = "ContentDescriptionContains text '$text' in '${getInteractionMatcher()}'",
type = EspressoAssertionType.CONTENT_DESCRIPTION_CONTAINS_TEXT,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.CONTENT_DESCRIPTION_CONTAINS_TEXT}' text '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.CONTENT_DESCRIPTION_CONTAINS_TEXT}' text '$text' in '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
}
fun assertMatches(condition: Matcher) = apply {
- val timeout = timeoutMs ?: UltronConfig.Espresso.ASSERTION_TIMEOUT
executeAssertion(
UltronEspressoOperation(
operationBlock = getInteractionAssertionBlock(condition),
name = "Custom assertion with '$condition' of '${getInteractionMatcher()}'",
type = EspressoAssertionType.ASSERT_MATCHES,
- description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.ASSERT_MATCHES}' with '$condition' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during $timeout ms",
- timeoutMs = timeout
+ description = "${interaction!!::class.java.simpleName} assertion '${EspressoAssertionType.ASSERT_MATCHES}' with '$condition' of '${getInteractionMatcher()}' with root '${getInteractionRootMatcher()}' during ${getAssertionTimeout()} ms",
+ timeoutMs = getAssertionTimeout()
),
resultHandler = resultHandler ?: UltronConfig.Espresso.ViewAssertionConfig.resultHandler
)
@@ -724,5 +738,3 @@ class UltronEspressoInteraction(
}
}
}
-
-
diff --git a/ultron/src/main/java/com/atiurin/ultron/core/espresso/action/EspressoActionType.kt b/ultron/src/main/java/com/atiurin/ultron/core/espresso/action/EspressoActionType.kt
index 03db2db9..f430ce71 100644
--- a/ultron/src/main/java/com/atiurin/ultron/core/espresso/action/EspressoActionType.kt
+++ b/ultron/src/main/java/com/atiurin/ultron/core/espresso/action/EspressoActionType.kt
@@ -4,6 +4,7 @@ import com.atiurin.ultron.core.common.UltronOperationType
enum class EspressoActionType : UltronOperationType {
CLICK, LONG_CLICK, DOUBLE_CLICK,
+ CLICK_TOP_LEFT, CLICK_TOP_RIGHT, CLICK_TOP_CENTER, CLICK_BOTTOM_CENTER, CLICK_BOTTOM_LEFT, CLICK_BOTTOM_RIGHT, CLICK_CENTER_RIGHT, CLICK_CENTER_LEFT,
TYPE_TEXT, REPLACE_TEXT, CLEAR_TEXT, PRESS_KEY,
SWIPE_LEFT, SWIPE_RIGHT, SWIPE_UP, SWIPE_DOWN, SCROLL, CUSTOM,
CLOSE_SOFT_KEYBOARD, PRESS_BACK, OPEN_ACTION_BAR_OVERFLOW_OR_OPTION_MENU, OPEN_CONTEXTUAL_ACTION_MODE_OVERFLOW_MENU
diff --git a/ultron/src/main/java/com/atiurin/ultron/core/espresso/action/UltronCustomClickAction.kt b/ultron/src/main/java/com/atiurin/ultron/core/espresso/action/UltronCustomClickAction.kt
new file mode 100644
index 00000000..9714edf7
--- /dev/null
+++ b/ultron/src/main/java/com/atiurin/ultron/core/espresso/action/UltronCustomClickAction.kt
@@ -0,0 +1,164 @@
+package com.atiurin.ultron.core.espresso.action
+
+import android.view.InputDevice
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewConfiguration
+import android.webkit.WebView
+import androidx.test.espresso.PerformException
+import androidx.test.espresso.UiController
+import androidx.test.espresso.ViewAction
+import androidx.test.espresso.action.*
+import androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast
+import androidx.test.espresso.util.HumanReadables
+import org.hamcrest.Matcher
+import java.util.*
+
+
+class UltronCustomClickAction(
+ private val tapper: Tapper,
+ private val coordinatesProvider: CoordinatesProvider,
+ private val precisionDescriber: PrecisionDescriber = Press.THUMB,
+ private val inputDevice: Int = InputDevice.SOURCE_UNKNOWN,
+ private val buttonState: Int = MotionEvent.BUTTON_PRIMARY,
+ private val areaPercentage: Int,
+ /**
+ * negative value for LEFT direction, positive value for RIGHT direction
+ */
+ private val offsetX: Int = 0,
+ /**
+ * negative value for TOP direction, positive value for BOTTOM direction
+ */
+ private val offsetY: Int = 0
+) : ViewAction {
+
+ override fun getConstraints(): Matcher {
+ return isDisplayingAtLeast(areaPercentage)
+ }
+
+ override fun getDescription(): String {
+ return tapper.toString().lowercase(Locale.ROOT) + " click";
+ }
+
+ override fun perform(uiController: UiController, view: View) {
+ val coordinates = coordinatesProvider
+ .calculateCoordinates(view)
+ .apply {
+ this[0] += offsetX.toFloat()
+ this[1] += offsetY.toFloat()
+ }
+ val precision = precisionDescriber.describePrecision()
+
+ var status = Tapper.Status.FAILURE
+ var loopCount = 0
+ // Native event injection is quite a tricky process. A tap is actually 2
+ // seperate motion events which need to get injected into the system. Injection
+ // makes an RPC call from our app under test to the Android system server, the
+ // system server decides which window layer to deliver the event to, the system
+ // server makes an RPC to that window layer, that window layer delivers the event
+ // to the correct UI element, activity, or window object. Now we need to repeat
+ // that 2x. for a simple down and up. Oh and the down event triggers timers to
+ // detect whether or not the event is a long vs. short press. The timers are
+ // removed the moment the up event is received (NOTE: the possibility of eventTime
+ // being in the future is totally ignored by most motion event processors).
+ //
+ // Phew.
+ //
+ // The net result of this is sometimes we'll want to do a regular tap, and for
+ // whatever reason the up event (last half) of the tap is delivered after long
+ // press timeout (depending on system load) and the long press behaviour is
+ // displayed (EG: show a context menu). There is no way to avoid or handle this more
+ // gracefully. Also the longpress behavour is app/widget specific. So if you have
+ // a seperate long press behaviour from your short press, you can pass in a
+ // 'RollBack' SmartViewAction which when executed will undo the effects of long press.
+
+ // Native event injection is quite a tricky process. A tap is actually 2
+ // seperate motion events which need to get injected into the system. Injection
+ // makes an RPC call from our app under test to the Android system server, the
+ // system server decides which window layer to deliver the event to, the system
+ // server makes an RPC to that window layer, that window layer delivers the event
+ // to the correct UI element, activity, or window object. Now we need to repeat
+ // that 2x. for a simple down and up. Oh and the down event triggers timers to
+ // detect whether or not the event is a long vs. short press. The timers are
+ // removed the moment the up event is received (NOTE: the possibility of eventTime
+ // being in the future is totally ignored by most motion event processors).
+ //
+ // Phew.
+ //
+ // The net result of this is sometimes we'll want to do a regular tap, and for
+ // whatever reason the up event (last half) of the tap is delivered after long
+ // press timeout (depending on system load) and the long press behaviour is
+ // displayed (EG: show a context menu). There is no way to avoid or handle this more
+ // gracefully. Also the longpress behavour is app/widget specific. So if you have
+ // a seperate long press behaviour from your short press, you can pass in a
+ // 'RollBack' SmartViewAction which when executed will undo the effects of long press.
+ val action = "perform: ${
+ String.format(
+ "%s - At Coordinates: %d, %d and precision: %d, %d",
+ this.description,
+ coordinates[0].toInt(),
+ coordinates[1].toInt(),
+ precision[0].toInt(),
+ precision[1].toInt()
+ )
+ }"
+
+ while (status != Tapper.Status.SUCCESS && loopCount < 3) {
+ try {
+ status = tapper.sendTap(
+ uiController, coordinates, precision, inputDevice, buttonState
+ )
+ } catch (re: RuntimeException) {
+ throw PerformException.Builder()
+ .withActionDescription(
+ String.format(
+ "%s - At Coordinates: %d, %d and precision: %d, %d",
+ this.description,
+ coordinates[0].toInt(),
+ coordinates[1].toInt(),
+ precision[0].toInt(),
+ precision[1].toInt()
+ )
+ )
+ .withViewDescription(HumanReadables.describe(view))
+ .withCause(re)
+ .build()
+ }
+ val duration = ViewConfiguration.getPressedStateDuration()
+ // ensures that all work enqueued to process the tap has been run.
+ if (duration > 0) {
+ uiController.loopMainThreadForAtLeast(duration.toLong())
+ }
+ if (status == Tapper.Status.WARNING) {
+ break
+ }
+ loopCount++
+ }
+ if (status == Tapper.Status.FAILURE) {
+ val actionFail = String.format(
+ "Couldn't "
+ + "click at: %s,%s precision: %s, %s . Tapper: %s coordinate provider: %s precision "
+ + "describer: %s. Tried %s times.",
+ coordinates[0],
+ coordinates[1],
+ precision[0],
+ precision[1],
+ tapper,
+ coordinatesProvider,
+ precisionDescriber,
+ loopCount
+ )
+
+ throw PerformException.Builder()
+ .withActionDescription(this.description)
+ .withViewDescription(HumanReadables.describe(view))
+ .withCause(RuntimeException(actionFail)).build()
+ }
+
+ if (tapper === Tap.SINGLE && view is WebView) {
+ // WebViews will not process click events until double tap
+ // timeout. Not the best place for this - but good for now.
+ uiController.loopMainThreadForAtLeast(ViewConfiguration.getDoubleTapTimeout().toLong())
+ }
+ }
+}
\ No newline at end of file
diff --git a/ultron/src/main/java/com/atiurin/ultron/core/espresso/recyclerview/UltronRecyclerViewItem.kt b/ultron/src/main/java/com/atiurin/ultron/core/espresso/recyclerview/UltronRecyclerViewItem.kt
index 670305bf..a9a5e5d4 100644
--- a/ultron/src/main/java/com/atiurin/ultron/core/espresso/recyclerview/UltronRecyclerViewItem.kt
+++ b/ultron/src/main/java/com/atiurin/ultron/core/espresso/recyclerview/UltronRecyclerViewItem.kt
@@ -3,7 +3,9 @@ package com.atiurin.ultron.core.espresso.recyclerview
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.ViewAction
+import androidx.test.espresso.ViewInteraction
import com.atiurin.ultron.core.espresso.EspressoOperationResult
+import com.atiurin.ultron.core.espresso.UltronEspressoInteraction
import com.atiurin.ultron.core.espresso.UltronEspressoOperation
import com.atiurin.ultron.exceptions.UltronException
import com.atiurin.ultron.extensions.*
@@ -74,6 +76,16 @@ open class UltronRecyclerViewItem {
fun click() = apply { this.getMatcher().click() }
fun longClick() = apply { this.getMatcher().longClick() }
fun doubleClick() = apply { this.getMatcher().doubleClick() }
+
+ fun clickTopLeft(offsetX: Int = 0, offsetY: Int = 0) = apply { this.getMatcher().clickTopLeft(offsetX, offsetY) }
+ fun clickTopCenter(offsetY: Int) = apply { this.getMatcher().clickTopCenter(offsetY) }
+ fun clickTopRight(offsetX: Int = 0, offsetY: Int = 0) = apply { this.getMatcher().clickTopRight(offsetX, offsetY) }
+ fun clickCenterRight(offsetX: Int = 0) = apply { this.getMatcher().clickCenterRight(offsetX) }
+ fun clickBottomRight(offsetX: Int = 0, offsetY: Int = 0) = apply { this.getMatcher().clickBottomRight(offsetX, offsetY) }
+ fun clickBottomCenter(offsetY: Int = 0) = apply { this.getMatcher().clickBottomCenter(offsetY) }
+ fun clickBottomLeft(offsetX: Int = 0, offsetY: Int = 0) = apply { this.getMatcher().clickBottomLeft(offsetX, offsetY) }
+ fun clickCenterLeft(offsetX: Int = 0) = apply { this.getMatcher().clickCenterLeft(offsetX) }
+
fun swipeDown() = apply { this.getMatcher().swipeDown() }
fun swipeLeft() = apply { this.getMatcher().swipeLeft() }
fun swipeRight() = apply { this.getMatcher().swipeRight() }
diff --git a/ultron/src/main/java/com/atiurin/ultron/extensions/DataInterationExt.kt b/ultron/src/main/java/com/atiurin/ultron/extensions/DataInterationExt.kt
index 2fb9e6db..3555af63 100644
--- a/ultron/src/main/java/com/atiurin/ultron/extensions/DataInterationExt.kt
+++ b/ultron/src/main/java/com/atiurin/ultron/extensions/DataInterationExt.kt
@@ -3,6 +3,7 @@ package com.atiurin.ultron.extensions
import android.view.View
import androidx.annotation.DrawableRes
import androidx.test.espresso.DataInteraction
+import androidx.test.espresso.Espresso
import androidx.test.espresso.ViewAction
import androidx.test.espresso.ViewInteraction
import androidx.test.espresso.action.EspressoKey
@@ -28,6 +29,16 @@ fun DataInteraction.withResultHandler(resultHandler: (EspressoOperationResult.withResultHandler(resultHandler: (EspressoOperationResult.click() = UltronEspressoInteraction(onView(this)).click()
fun Matcher.doubleClick() = UltronEspressoInteraction(onView(this)).doubleClick()
fun Matcher.longClick() = UltronEspressoInteraction(onView(this)).longClick()
+
+fun Matcher.clickTopLeft(offsetX: Int = 0, offsetY: Int = 0) = UltronEspressoInteraction(onView(this)).clickTopLeft(offsetX, offsetY)
+fun Matcher.clickTopCenter(offsetY: Int) = UltronEspressoInteraction(onView(this)).clickTopCenter(offsetY)
+fun Matcher.clickTopRight(offsetX: Int = 0, offsetY: Int = 0) = UltronEspressoInteraction(onView(this)).clickTopRight(offsetX, offsetY)
+fun Matcher.clickCenterRight(offsetX: Int = 0) = UltronEspressoInteraction(onView(this)).clickCenterRight(offsetX)
+fun Matcher.clickBottomRight(offsetX: Int = 0, offsetY: Int = 0) = UltronEspressoInteraction(onView(this)).clickBottomRight(offsetX, offsetY)
+fun Matcher.clickBottomCenter(offsetY: Int = 0) = UltronEspressoInteraction(onView(this)).clickBottomCenter(offsetY)
+fun Matcher.clickBottomLeft(offsetX: Int = 0, offsetY: Int = 0) = UltronEspressoInteraction(onView(this)).clickBottomLeft(offsetX, offsetY)
+fun Matcher.clickCenterLeft(offsetX: Int = 0) = UltronEspressoInteraction(onView(this)).clickCenterLeft(offsetX)
+
fun Matcher.typeText(text: String) = UltronEspressoInteraction(onView(this)).typeText(text)
fun Matcher.replaceText(text: String) = UltronEspressoInteraction(onView(this)).replaceText(text)
fun Matcher.clearText() = UltronEspressoInteraction(onView(this)).clearText()
diff --git a/ultron/src/main/java/com/atiurin/ultron/extensions/ViewInteractionExt.kt b/ultron/src/main/java/com/atiurin/ultron/extensions/ViewInteractionExt.kt
index d502cb05..f1336260 100644
--- a/ultron/src/main/java/com/atiurin/ultron/extensions/ViewInteractionExt.kt
+++ b/ultron/src/main/java/com/atiurin/ultron/extensions/ViewInteractionExt.kt
@@ -2,6 +2,7 @@ package com.atiurin.ultron.extensions
import android.view.View
import androidx.annotation.DrawableRes
+import androidx.test.espresso.DataInteraction
import androidx.test.espresso.ViewAction
import androidx.test.espresso.ViewInteraction
import androidx.test.espresso.action.EspressoKey
@@ -28,6 +29,16 @@ fun ViewInteraction.withResultHandler(resultHandler: (EspressoOperationResult