diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml
new file mode 100644
index 0000000..6adf318
--- /dev/null
+++ b/.idea/androidTestResultsUserPreferences.xml
@@ -0,0 +1,191 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b2cb255..888584a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,3 +10,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- `clickable` selector.
+- `getObject` function works like `findObject` used to work (throws if the view represented by the UiObject doesn't exist).
+- `findObject` now returns a `UiObject` even if the view represented by the UiObject doesn't exist.
\ No newline at end of file
diff --git a/relax/src/main/java/com/emergetools/relax/Flow.kt b/relax/src/main/java/com/emergetools/relax/Flow.kt
index 46d2851..ca29c29 100644
--- a/relax/src/main/java/com/emergetools/relax/Flow.kt
+++ b/relax/src/main/java/com/emergetools/relax/Flow.kt
@@ -184,11 +184,19 @@ class Flow(val packageName: String, val config: FlowConfig) {
textOrResId(textOrResId)
}
+ /**
+ * @return A UiObject which represents a view that matches the criteria.
+ */
+ fun findObject(select: RelaxSelector.() -> Unit): UiObject = intercept {
+ val selector = RelaxSelector(packageName).apply(select).toUiSelector()
+ device.findObject(selector)
+ }
+
/**
* If the object exists, calls [block] on it and returns its return value, otherwise returns
* [default].
*/
- private fun findObject(
+ private fun getObject(
select: RelaxSelector.() -> Unit,
default: T,
block: (UiObject) -> T
@@ -197,12 +205,23 @@ class Flow(val packageName: String, val config: FlowConfig) {
return if (obj.exists()) block(obj) else default
}
+ /**
+ * @param textOrResId If the string contains ":id/" it will be treated as a resource ID,
+ * otherwise searches for the element whose visible text matches exactly. Matching is
+ * case-sensitive.
+ * @return A UiObject which represents a view that matches the criteria.
+ * @throws UiObjectNotFoundException if the view represented by this UiObject does not exist
+ */
+ fun getObject(textOrResId: String) = getObject {
+ textOrResId(textOrResId)
+ }
+
/**
* @return A UiObject which represents a view that matches the criteria.
+ * @throws UiObjectNotFoundException if the view represented by this UiObject does not exist
*/
- fun findObject(select: RelaxSelector.() -> Unit): UiObject = intercept {
- val selector = RelaxSelector(packageName).apply(select).toUiSelector()
- device.findObject(selector).also {
+ fun getObject(select: RelaxSelector.() -> Unit): UiObject = intercept {
+ findObject(select).also {
if (!it.exists()) error(UiObjectNotFoundException(it.selector.toString()))
}
}
@@ -233,7 +252,7 @@ class Flow(val packageName: String, val config: FlowConfig) {
* @return true if successful, false otherwise
*/
fun click(select: RelaxSelector.() -> Unit): Boolean = intercept {
- findObject(select, false) {
+ getObject(select, false) {
it.click().also { result ->
if (!result) error(UnsupportedOperationException("click ${it.selector}"))
waitForIdle()
@@ -281,7 +300,7 @@ class Flow(val packageName: String, val config: FlowConfig) {
* @return true if successful, false otherwise
*/
fun longClick(select: RelaxSelector.() -> Unit): Boolean = intercept {
- findObject(select, false) {
+ getObject(select, false) {
it.longClick().also { result ->
if (!result) error(UnsupportedOperationException("longClick ${it.selector}"))
waitForIdle()
@@ -322,7 +341,7 @@ class Flow(val packageName: String, val config: FlowConfig) {
* @return true if successful, false otherwise
*/
fun inputText(inputText: String, select: RelaxSelector.() -> Unit): Boolean = intercept {
- findObject(select, false) {
+ getObject(select, false) {
it.setText(inputText).also { result ->
if (!result) error(UnsupportedOperationException("inputText $inputText ${it.selector}"))
waitForIdle()
@@ -575,7 +594,7 @@ class Flow(val packageName: String, val config: FlowConfig) {
* @return true if successful, false otherwise
*/
fun swipeDown(select: RelaxSelector.() -> Unit): Boolean = intercept {
- findObject(select, false) {
+ getObject(select, false) {
it.swipeDown(config.swipeSteps).also { result ->
if (!result) error(UnsupportedOperationException("swipeDown ${it.selector}"))
}
@@ -608,7 +627,7 @@ class Flow(val packageName: String, val config: FlowConfig) {
* @return true if successful, false otherwise
*/
fun swipeLeft(select: RelaxSelector.() -> Unit): Boolean = intercept {
- findObject(select, false) {
+ getObject(select, false) {
it.swipeLeft(config.swipeSteps).also { result ->
if (!result) error(UnsupportedOperationException("swipeLeft ${it.selector}"))
}
@@ -641,7 +660,7 @@ class Flow(val packageName: String, val config: FlowConfig) {
* @return true if successful, false otherwise
*/
fun swipeRight(select: RelaxSelector.() -> Unit): Boolean = intercept {
- findObject(select, false) {
+ getObject(select, false) {
it.swipeRight(config.swipeSteps).also { result ->
if (!result) error(UnsupportedOperationException("swipeRight ${it.selector}"))
}
@@ -674,7 +693,7 @@ class Flow(val packageName: String, val config: FlowConfig) {
* @return true if successful, false otherwise
*/
fun swipeUp(select: RelaxSelector.() -> Unit): Boolean = intercept {
- findObject(select, false) {
+ getObject(select, false) {
it.swipeUp(config.swipeSteps).also { result ->
if (!result) error(UnsupportedOperationException("swipeUp ${it.selector}"))
}
diff --git a/tests/src/main/AndroidManifest.xml b/tests/src/main/AndroidManifest.xml
index 3daa1c3..273da6a 100644
--- a/tests/src/main/AndroidManifest.xml
+++ b/tests/src/main/AndroidManifest.xml
@@ -3,5 +3,8 @@
+
+
+
\ No newline at end of file
diff --git a/tests/src/main/java/com/emergetools/relaxtests/AutoEmergeTest.kt b/tests/src/main/java/com/emergetools/relaxtests/AutoEmergeTest.kt
new file mode 100644
index 0000000..2f034da
--- /dev/null
+++ b/tests/src/main/java/com/emergetools/relaxtests/AutoEmergeTest.kt
@@ -0,0 +1,26 @@
+package com.emergetools.relaxtests
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.emergetools.relax.FlowConfig
+import com.emergetools.relax.Relax
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class AutoEmergeTest {
+
+ @Test
+ fun install() {
+ Relax("com.android.vending", FlowConfig(debug = true)) {
+ launchWithLink("https://play.google.com/store/apps/details?id=org.thoughtcrime.securesms")
+
+ if (findObject { description("Open") }.exists()) return@Relax
+
+ getObject { description("Install") }.click()
+
+ val installing = findObject("Installing…")
+ installing.waitForExists(60_000)
+ installing.waitUntilGone(60_000)
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/src/main/java/com/emergetools/relaxtests/FindObjectTest.kt b/tests/src/main/java/com/emergetools/relaxtests/FindObjectTest.kt
index 58a81a3..bfbd91f 100644
--- a/tests/src/main/java/com/emergetools/relaxtests/FindObjectTest.kt
+++ b/tests/src/main/java/com/emergetools/relaxtests/FindObjectTest.kt
@@ -3,6 +3,7 @@ package com.emergetools.relaxtests
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.UiObjectNotFoundException
import com.emergetools.relax.Relax
+import org.junit.Assert.assertFalse
import org.junit.Assert.assertThrows
import org.junit.Assert.assertTrue
import org.junit.Test
@@ -12,7 +13,7 @@ import org.junit.runner.RunWith
class FindObjectTest {
@Test
- fun findObject() {
+ fun findObjectExists() {
Relax("com.emergetools.relaxexamples") {
pressHome()
launch()
@@ -27,22 +28,9 @@ class FindObjectTest {
Relax("com.emergetools.relaxexamples") {
pressHome()
launch()
+ val obj = findObject("DOESN'T EXIST")
- assertThrows(UiObjectNotFoundException::class.java) {
- findObject("DOESN'T EXIST")
- }
- }
- }
-
- @Test
- fun optionalFindObject() {
- Relax("com.emergetools.relaxexamples") {
- pressHome()
- launch()
-
- optional {
- findObject("DOESN'T EXIST")
- }
+ assertFalse(obj.exists())
}
}
}
diff --git a/tests/src/main/java/com/emergetools/relaxtests/GetObjectTest.kt b/tests/src/main/java/com/emergetools/relaxtests/GetObjectTest.kt
new file mode 100644
index 0000000..1709ef6
--- /dev/null
+++ b/tests/src/main/java/com/emergetools/relaxtests/GetObjectTest.kt
@@ -0,0 +1,48 @@
+package com.emergetools.relaxtests
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.uiautomator.UiObjectNotFoundException
+import com.emergetools.relax.Relax
+import org.junit.Assert.assertThrows
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class GetObjectTest {
+
+ @Test
+ fun getObject() {
+ Relax("com.emergetools.relaxexamples") {
+ pressHome()
+ launch()
+ val obj = getObject("NEXT")
+
+ assertTrue(obj.exists())
+ }
+ }
+
+ @Test
+ fun getObjectDoesntExist() {
+ Relax("com.emergetools.relaxexamples") {
+ pressHome()
+ launch()
+
+ assertThrows(UiObjectNotFoundException::class.java) {
+ getObject("DOESN'T EXIST")
+ }
+ }
+ }
+
+ @Test
+ fun optionalGetObject() {
+ Relax("com.emergetools.relaxexamples") {
+ pressHome()
+ launch()
+
+ optional {
+ getObject("DOESN'T EXIST")
+ }
+ }
+ }
+}