diff --git a/espresso-server/app/build.gradle.kts b/espresso-server/app/build.gradle.kts index 7fbf01ee..2f39e6f4 100644 --- a/espresso-server/app/build.gradle.kts +++ b/espresso-server/app/build.gradle.kts @@ -115,8 +115,8 @@ dependencies { testImplementation("org.jetbrains.kotlin:kotlin-test:${kotlinVersion}") testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion") testImplementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}") - testImplementation("androidx.compose.ui:ui-test:${composeVersion}") - testImplementation("androidx.compose.ui:ui-test-junit4:${composeVersion}") +// testImplementation("androidx.compose.ui:ui-test:${composeVersion}") +// testImplementation("androidx.compose.ui:ui-test-junit4:${composeVersion}") androidTestImplementation("androidx.annotation:annotation:${annotationVersion}") androidTestImplementation("androidx.test.espresso:espresso-contrib:${espressoVersion}") { @@ -137,12 +137,12 @@ dependencies { androidTestImplementation("org.nanohttpd:nanohttpd-webserver:${Version.nanohttpd}") androidTestImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}") androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}") - androidTestImplementation("androidx.compose.ui:ui-test:${composeVersion}") { - because("Android Compose support") - } - androidTestImplementation("androidx.compose.ui:ui-test-junit4:${composeVersion}") { - because("Android Compose support") - } +// androidTestImplementation("androidx.compose.ui:ui-test:${composeVersion}") { +// because("Android Compose support") +// } +// androidTestImplementation("androidx.compose.ui:ui-test-junit4:${composeVersion}") { +// because("Android Compose support") +// } // additionalAndroidTestDependencies placeholder (don't change or delete this line) } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/EspressoServerRunnerTest.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/EspressoServerRunnerTest.kt index 4f5aa5ba..09711e2f 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/EspressoServerRunnerTest.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/EspressoServerRunnerTest.kt @@ -31,7 +31,6 @@ import org.junit.Rule import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement -import androidx.compose.ui.test.junit4.AndroidComposeTestRule /** * Instrumentation test, which will execute on an Android device. @@ -41,24 +40,6 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule @LargeTest class EspressoServerRunnerTest { - @get:Rule - val composeRule = AndroidComposeTestRule( - activityRule = EmptyTestRule(), - activityProvider = { error("Can't provide current activity") } - ).also { - composeTestRule = it - } - - private val syncComposeClock = Thread { - while (!Server.isStopRequestReceived) { - if (context.currentStrategyType == DriverContext.StrategyType.COMPOSE) { - composeTestRule.mainClock.advanceTimeByFrame() - } - // Let Android run measure, draw and in general any other async operations. AndroidComposeTestRule.android.kt:325 - Thread.sleep(ANDROID_ASYNC_WAIT_TIME_MS) - } - } - @Test @Throws(InterruptedException::class, IOException::class, DuplicateRouteException::class) fun startEspressoServer() { @@ -68,13 +49,11 @@ class EspressoServerRunnerTest { } try { Server.start() - syncComposeClock.start() while (!Server.isStopRequestReceived) { Thread.sleep(1000) } } finally { Server.stop() - syncComposeClock.join() } assertEquals(true, true) // Keep Codacy happy @@ -85,7 +64,6 @@ class EspressoServerRunnerTest { } companion object { - lateinit var composeTestRule: AndroidComposeTestRule<*, *> val context = DriverContext() const val ANDROID_ASYNC_WAIT_TIME_MS = 10L } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Clear.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Clear.kt index 645a8b08..446dd513 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Clear.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Clear.kt @@ -16,15 +16,12 @@ package io.appium.espressoserver.lib.handlers -import androidx.compose.ui.test.performTextClearance import androidx.test.espresso.PerformException import io.appium.espressoserver.lib.handlers.exceptions.InvalidElementStateException import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.EspressoElement import androidx.test.espresso.action.ViewActions.clearText -import io.appium.espressoserver.lib.handlers.exceptions.StaleElementException -import io.appium.espressoserver.lib.helpers.getNodeInteractionById class Clear : RequestHandler { @@ -36,14 +33,4 @@ class Clear : RequestHandler { throw InvalidElementStateException("clear", params.elementId!!, e) } } - - override fun handleCompose(params: AppiumParams) { - try { - getNodeInteractionById(params.elementId).performTextClearance() - } catch (e: AssertionError) { - throw StaleElementException(params.elementId!!) - } catch (e: IllegalArgumentException) { - throw InvalidElementStateException("Clear", params.elementId!!, e) - } - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Click.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Click.kt index 77288466..575fdcaa 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Click.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Click.kt @@ -16,15 +16,12 @@ package io.appium.espressoserver.lib.handlers -import androidx.compose.ui.test.performClick import androidx.test.espresso.PerformException import io.appium.espressoserver.lib.handlers.exceptions.InvalidElementStateException import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.EspressoElement import androidx.test.espresso.action.ViewActions.click -import io.appium.espressoserver.lib.handlers.exceptions.StaleElementException -import io.appium.espressoserver.lib.helpers.getNodeInteractionById class Click : RequestHandler { @@ -36,14 +33,4 @@ class Click : RequestHandler { throw InvalidElementStateException("click", params.elementId!!, e) } } - - override fun handleCompose(params: AppiumParams) { - try { - getNodeInteractionById(params.elementId).performClick() - } catch (e: AssertionError) { - throw StaleElementException(params.elementId!!) - } catch (e: IllegalArgumentException) { - throw InvalidElementStateException("Click", params.elementId!!, e) - } - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementScreenshot.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementScreenshot.kt index fa77bde3..da25c57e 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementScreenshot.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementScreenshot.kt @@ -16,8 +16,6 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getNodeInteractionById -import io.appium.espressoserver.lib.helpers.takeComposeNodeScreenshot import io.appium.espressoserver.lib.helpers.takeEspressoViewScreenshot import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.EspressoElement @@ -26,7 +24,4 @@ class ElementScreenshot : RequestHandler { override fun handleEspresso(params: AppiumParams): String = takeEspressoViewScreenshot(EspressoElement.getCachedViewStateById(params.elementId).view) - - override fun handleCompose(params: AppiumParams): String = - takeComposeNodeScreenshot(getNodeInteractionById(params.elementId!!)) } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementValue.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementValue.kt index 97d585ad..6f98644e 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementValue.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/ElementValue.kt @@ -18,8 +18,6 @@ package io.appium.espressoserver.lib.handlers import android.widget.NumberPicker import android.widget.ProgressBar -import androidx.compose.ui.test.performTextClearance -import androidx.compose.ui.test.performTextInput import androidx.test.espresso.PerformException import io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException @@ -30,7 +28,6 @@ import androidx.test.espresso.action.ViewActions.replaceText import androidx.test.espresso.action.ViewActions.typeText import io.appium.espressoserver.lib.handlers.exceptions.InvalidElementStateException import io.appium.espressoserver.lib.helpers.AndroidLogger -import io.appium.espressoserver.lib.helpers.getNodeInteractionById import io.appium.espressoserver.lib.viewaction.ViewTextGetter class ElementValue(private val isReplacing: Boolean) : RequestHandler { @@ -76,18 +73,6 @@ class ElementValue(private val isReplacing: Boolean) : RequestHandler { // If we have a match, return success return EspressoElement(viewState) } - - override fun handleCompose(params: Locator): BaseElement { - val nodeInteractions = toNodeInteractionsCollection(params) - if (nodeInteractions.fetchSemanticsNodes(false).isEmpty()) throw NoSuchElementException( - String.format( - "Could not find a compose element with strategy '%s' and selector '%s'", - params.using, params.value - ) - ) - return ComposeElement(nodeInteractions[0]) - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/FindElements.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/FindElements.kt index 75cbd653..ec79552d 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/FindElements.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/FindElements.kt @@ -20,7 +20,6 @@ import io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException import io.appium.espressoserver.lib.handlers.exceptions.InvalidSelectorException import io.appium.espressoserver.lib.helpers.* import io.appium.espressoserver.lib.model.BaseElement -import io.appium.espressoserver.lib.model.ComposeElement import io.appium.espressoserver.lib.model.EspressoElement import io.appium.espressoserver.lib.model.Locator import io.appium.espressoserver.lib.viewaction.ViewGetter @@ -39,10 +38,4 @@ class FindElements : RequestHandler> { params.value ?: throw InvalidArgumentException() ).map { EspressoElement(it) } } - - override fun handleCompose(params: Locator): List { - val nodeInteractions = toNodeInteractionsCollection(params) - return List(nodeInteractions.fetchSemanticsNodes(false).size) - { index -> ComposeElement(nodeInteractions[index]) } - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetAttribute.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetAttribute.kt index 414e870a..a038654b 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetAttribute.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetAttribute.kt @@ -24,7 +24,6 @@ import io.appium.espressoserver.lib.drivers.DriverContext import io.appium.espressoserver.lib.handlers.exceptions.AppiumException import io.appium.espressoserver.lib.handlers.exceptions.NotYetImplementedException import io.appium.espressoserver.lib.helpers.AndroidLogger -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.* import io.appium.espressoserver.lib.viewaction.ViewTextGetter @@ -39,15 +38,7 @@ class GetAttribute : RequestHandler { throw AppiumException("Attribute name cannot be null or empty") } - return when (EspressoServerRunnerTest.context.currentStrategyType) { - DriverContext.StrategyType.COMPOSE -> getComposeAttribute(params.elementId!!, attributeName) - DriverContext.StrategyType.ESPRESSO -> getEspressoAttribute(params.elementId!!, attributeName) - } - } - - - private fun getComposeAttribute(elementId: String, attributeName: String): String? { - return ComposeNodeElement(getSemanticsNode(elementId)).getAttribute(attributeName) + return getEspressoAttribute(params.elementId!!, attributeName) } private fun getEspressoAttribute(elementId: String, attributeName: String): String? { diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetDisplayed.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetDisplayed.kt index d63181be..ba390480 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetDisplayed.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetDisplayed.kt @@ -16,8 +16,6 @@ package io.appium.espressoserver.lib.handlers -import androidx.compose.ui.test.assertIsDisplayed -import io.appium.espressoserver.lib.helpers.getNodeInteractionById import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.EspressoElement import io.appium.espressoserver.lib.model.ViewElement @@ -26,13 +24,5 @@ class GetDisplayed : RequestHandler { override fun handleEspresso(params: AppiumParams): Boolean = ViewElement(EspressoElement.getCachedViewStateById(params.elementId, false).view).isVisible - - override fun handleCompose(params: AppiumParams): Boolean = - try { - getNodeInteractionById(params.elementId).assertIsDisplayed() - true - } catch (e: AssertionError) { - false - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetEnabled.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetEnabled.kt index 62d35341..653429e5 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetEnabled.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetEnabled.kt @@ -16,17 +16,12 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.ViewElement import io.appium.espressoserver.lib.model.EspressoElement -import io.appium.espressoserver.lib.model.ComposeNodeElement class GetEnabled : RequestHandler { override fun handleEspresso(params: AppiumParams): Boolean = ViewElement(EspressoElement.getCachedViewStateById(params.elementId).view).isEnabled - - override fun handleCompose(params: AppiumParams): Boolean = - ComposeNodeElement(getSemanticsNode(params.elementId!!)).isEnabled } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetLocation.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetLocation.kt index 68104d1d..1b4faab3 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetLocation.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetLocation.kt @@ -16,12 +16,10 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.Location import io.appium.espressoserver.lib.model.ViewElement import io.appium.espressoserver.lib.model.EspressoElement -import io.appium.espressoserver.lib.model.ComposeNodeElement class GetLocation : RequestHandler { @@ -29,9 +27,4 @@ class GetLocation : RequestHandler { val viewElement = ViewElement(EspressoElement.getCachedViewStateById(params.elementId).view) return Location(viewElement.bounds.left, viewElement.bounds.top) } - - override fun handleCompose(params: AppiumParams): Location { - val composeNodeElement = ComposeNodeElement(getSemanticsNode(params.elementId!!)) - return Location(composeNodeElement.bounds.left, composeNodeElement.bounds.top) - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetName.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetName.kt index 6e07011a..52abc52e 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetName.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetName.kt @@ -16,11 +16,9 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.ViewElement import io.appium.espressoserver.lib.model.EspressoElement -import io.appium.espressoserver.lib.model.ComposeNodeElement class GetName : RequestHandler { @@ -28,9 +26,4 @@ class GetName : RequestHandler { val viewState = EspressoElement.getCachedViewStateById(params.elementId) return ViewElement(viewState.view).contentDescription?.toString() } - - override fun handleCompose(params: AppiumParams): String? { - val composeNodeElement = ComposeNodeElement(getSemanticsNode(params.elementId!!)) - return composeNodeElement.contentDescription?.toString() - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetRect.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetRect.kt index a757a503..da8ed12e 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetRect.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetRect.kt @@ -16,9 +16,7 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.AppiumParams -import io.appium.espressoserver.lib.model.ComposeNodeElement import io.appium.espressoserver.lib.model.EspressoElement import io.appium.espressoserver.lib.model.Rect import io.appium.espressoserver.lib.model.ViewElement @@ -27,7 +25,4 @@ class GetRect : RequestHandler { override fun handleEspresso(params: AppiumParams): Rect = ViewElement(EspressoElement.getCachedViewStateById(params.elementId).view).rect - - override fun handleCompose(params: AppiumParams): Rect = - ComposeNodeElement(getSemanticsNode(params.elementId!!)).rect } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSelected.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSelected.kt index bc953d55..13a1ef84 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSelected.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSelected.kt @@ -16,9 +16,7 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.AppiumParams -import io.appium.espressoserver.lib.model.ComposeNodeElement import io.appium.espressoserver.lib.model.EspressoElement import io.appium.espressoserver.lib.model.ViewElement @@ -27,7 +25,4 @@ class GetSelected : RequestHandler { override fun handleEspresso(params: AppiumParams): Boolean = ViewElement(EspressoElement.getCachedViewStateById(params.elementId).view).isSelected - - override fun handleCompose(params: AppiumParams): Boolean = - ComposeNodeElement(getSemanticsNode(params.elementId!!)).isSelected } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSize.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSize.kt index 8fdae918..8b0a89c5 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSize.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/GetSize.kt @@ -16,12 +16,10 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.AppiumParams import io.appium.espressoserver.lib.model.Size import io.appium.espressoserver.lib.model.ViewElement import io.appium.espressoserver.lib.model.EspressoElement -import io.appium.espressoserver.lib.model.ComposeNodeElement class GetSize : RequestHandler { @@ -29,9 +27,4 @@ class GetSize : RequestHandler { val bounds = ViewElement(EspressoElement.getCachedViewStateById(params.elementId).view).bounds return Size(bounds.width(), bounds.height()) } - - override fun handleCompose(params: AppiumParams): Size { - val bounds = ComposeNodeElement(getSemanticsNode(params.elementId!!)).bounds - return Size(bounds.width(), bounds.height()) - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Keys.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Keys.kt index cb67ce4e..15a4e60f 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Keys.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Keys.kt @@ -16,11 +16,7 @@ package io.appium.espressoserver.lib.handlers -import androidx.compose.ui.test.performTextInput import androidx.test.espresso.UiController -import io.appium.espressoserver.lib.handlers.exceptions.InvalidElementStateException -import io.appium.espressoserver.lib.handlers.exceptions.StaleElementException -import io.appium.espressoserver.lib.helpers.getNodeInteractionById import io.appium.espressoserver.lib.helpers.w3c.adapter.espresso.EspressoW3CActionAdapter import io.appium.espressoserver.lib.helpers.w3c.models.Actions.ActionsBuilder import io.appium.espressoserver.lib.helpers.w3c.models.InputSource.Action @@ -79,17 +75,4 @@ class Keys : RequestHandler { UiControllerPerformer(runnable).run() } - - override fun handleCompose(params: TextValueParams) { - try { - val keys = params.value ?: return - keys.forEach { - getNodeInteractionById(params.elementId).performTextInput(it) - } - } catch (e: AssertionError) { - throw StaleElementException(params.elementId!!) - } catch (e: IllegalArgumentException) { - throw InvalidElementStateException("Keys", params.elementId!!, e) - } - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/MobileSwipe.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/MobileSwipe.kt index b6e2e30d..cdd63939 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/MobileSwipe.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/MobileSwipe.kt @@ -16,17 +16,10 @@ package io.appium.espressoserver.lib.handlers -import androidx.compose.ui.test.performGesture -import androidx.compose.ui.test.swipeDown - -import androidx.compose.ui.test.swipeLeft -import androidx.compose.ui.test.swipeRight -import androidx.compose.ui.test.swipeUp import androidx.test.espresso.UiController import androidx.test.espresso.action.GeneralSwipeAction import io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException import io.appium.espressoserver.lib.helpers.AndroidLogger -import io.appium.espressoserver.lib.helpers.getNodeInteractionById import io.appium.espressoserver.lib.model.EspressoElement import io.appium.espressoserver.lib.model.MobileSwipeParams import io.appium.espressoserver.lib.model.MobileSwipeParams.Direction.* @@ -77,22 +70,4 @@ class MobileSwipe : RequestHandler { return null } - - override fun handleCompose(params: MobileSwipeParams): Void? { - val nodeInteractions = getNodeInteractionById(params.elementId) - - AndroidLogger.info("Performing swipe action with direction '${params.direction}'") - when (params.direction) { - UP -> nodeInteractions.performGesture { swipeUp() } - DOWN -> nodeInteractions.performGesture { swipeDown() } - LEFT -> nodeInteractions.performGesture { swipeLeft() } - RIGHT -> nodeInteractions.performGesture { swipeRight() } - else -> throw InvalidArgumentException( - "Unknown swipe direction '${params.direction}'. " + - "Only the following values are supported: " + - values().joinToString(",") { x -> x.name.lowercase() } - ) - } - return null - } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/RequestHandler.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/RequestHandler.kt index d08ad459..8f51c699 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/RequestHandler.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/RequestHandler.kt @@ -29,20 +29,12 @@ interface RequestHandler { fun handleInternal(params: T): R = invokeStrategy(params) @Suppress("UNCHECKED_CAST") - fun invokeStrategy(params: AppiumParams): R = - when (EspressoServerRunnerTest.context.currentStrategyType) { - StrategyType.COMPOSE -> handleCompose(params as T) - StrategyType.ESPRESSO -> handleEspresso(params as T) - } + fun invokeStrategy(params: AppiumParams): R = handleEspresso(params as T) fun handleEspresso(params: T): R { throw NotYetImplementedException() } - fun handleCompose(params: T): R { - throw NotYetImplementedException() - } - @Suppress("UNCHECKED_CAST") @Throws(AppiumException::class) fun handle(params: AppiumParams): R { diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Text.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Text.kt index 9ee1458c..188a964d 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Text.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/handlers/Text.kt @@ -16,9 +16,7 @@ package io.appium.espressoserver.lib.handlers -import io.appium.espressoserver.lib.helpers.getSemanticsNode import io.appium.espressoserver.lib.model.AppiumParams -import io.appium.espressoserver.lib.model.ComposeNodeElement import io.appium.espressoserver.lib.model.EspressoElement import io.appium.espressoserver.lib.viewaction.ViewTextGetter @@ -28,7 +26,4 @@ class Text : RequestHandler { val viewInteraction = EspressoElement.getViewInteractionById(params.elementId) return ViewTextGetter()[viewInteraction].rawText } - - override fun handleCompose(params: AppiumParams): String = - ComposeNodeElement(getSemanticsNode(params.elementId!!)).text.toString() } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ComposeNodeFinder.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ComposeNodeFinder.kt deleted file mode 100644 index 545155de..00000000 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ComposeNodeFinder.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.espressoserver.lib.helpers - -import androidx.compose.ui.semantics.SemanticsNode -import androidx.compose.ui.test.* -import io.appium.espressoserver.EspressoServerRunnerTest -import io.appium.espressoserver.lib.handlers.exceptions.InvalidSelectorException -import io.appium.espressoserver.lib.model.Strategy -import io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException -import io.appium.espressoserver.lib.handlers.exceptions.StaleElementException -import io.appium.espressoserver.lib.model.Locator -import io.appium.espressoserver.lib.model.SourceDocument -import io.appium.espressoserver.lib.model.AttributesEnum -import io.appium.espressoserver.lib.model.compileXpathExpression -import io.appium.espressoserver.lib.viewmatcher.fetchIncludedAttributes - -/** - * Retrieve cached node and return the SemanticsNodeInteraction - */ -fun getNodeInteractionById(elementId: String?): SemanticsNodeInteraction = - elementId?.let { ComposeViewCache.get(it) ?: throw StaleElementException(it) } - ?: throw InvalidArgumentException("Cannot find 'null' element") - -// https://developer.android.com/jetpack/compose/semantics#merged-vs-unmerged -fun toNodeInteractionsCollection(params: Locator): SemanticsNodeInteractionCollection { - val parentNodeInteraction = params.elementId?.let { getNodeInteractionById(it) } - return parentNodeInteraction?.findDescendantNodeInteractions(params) - ?: EspressoServerRunnerTest.composeTestRule.onAllNodes( - useUnmergedTree = true, - matcher = semanticsMatcherForLocator(params) - ) -} - -fun SemanticsNodeInteraction.findDescendantNodeInteractions(locator: Locator): SemanticsNodeInteractionCollection = - this.onChildren().filter(semanticsMatcherForLocator(locator)) - -fun semanticsMatcherForLocator(locator: Locator): SemanticsMatcher = - when (locator.using) { - Strategy.VIEW_TAG -> hasTestTag(locator.value!!) - Strategy.TEXT -> hasText(locator.value!!) - Strategy.LINK_TEXT -> hasText(locator.value!!) - Strategy.ACCESSIBILITY_ID -> hasContentDescription(locator.value!!) - Strategy.XPATH -> hasXpath(locator) - else -> throw InvalidSelectorException( - "Can't use non-Compose selectors. " + - "Only ${Strategy.VIEW_TAG}, ${Strategy.TEXT}, ${Strategy.LINK_TEXT}, ${Strategy.XPATH} and " + - "${Strategy.ACCESSIBILITY_ID} are supported" - ) - } - -private fun hasXpath(locator: Locator): SemanticsMatcher { - val xpath = locator.value!! - val expression = compileXpathExpression(xpath) - val attributes = fetchIncludedAttributes(xpath) - val matchingIds = SourceDocument( - locator.elementId?.let { getSemanticsNode(it) }, attributes - ).findMatchingNodeIds(expression, AttributesEnum.RESOURCE_ID.toString()) - - return SemanticsMatcher("Matches Xpath ${locator.value}") { - matchingIds.contains(it.id) - } -} - -fun getSemanticsNode(elementId: String): SemanticsNode = - try { - getNodeInteractionById(elementId).fetchSemanticsNode() - } catch (e: AssertionError) { - throw StaleElementException(elementId) - } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/EspressoViewsCache.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/EspressoViewsCache.kt index 9e09fda3..339d282a 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/EspressoViewsCache.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/EspressoViewsCache.kt @@ -18,7 +18,6 @@ package io.appium.espressoserver.lib.helpers import android.util.LruCache import android.view.View -import androidx.compose.ui.test.SemanticsNodeInteraction import androidx.test.espresso.Root import org.hamcrest.Matcher @@ -45,19 +44,3 @@ object EspressoViewsCache { cache.evictAll() } } - -/** Compose does not have stable instances, use locator again. */ -object ComposeViewCache { - private val cache = LruCache(MAX_CACHE_SIZE) - - fun put(id: String, composeNode: SemanticsNodeInteraction) { - cache.put(id, composeNode) - } - - fun get(id: String?): SemanticsNodeInteraction? = - cache.get(id) - - fun reset() { - cache.evictAll() - } -} diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ScreenshotHelpers.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ScreenshotHelpers.kt index 30da58f1..5323ca81 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ScreenshotHelpers.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/helpers/ScreenshotHelpers.kt @@ -19,9 +19,6 @@ package io.appium.espressoserver.lib.helpers import android.graphics.Bitmap import android.util.Base64 import android.view.View -import androidx.compose.ui.graphics.asAndroidBitmap -import androidx.compose.ui.test.SemanticsNodeInteraction -import androidx.compose.ui.test.captureToImage import java.io.ByteArrayOutputStream import androidx.test.runner.screenshot.Screenshot @@ -48,12 +45,3 @@ fun takeEspressoViewScreenshot(view: View): String = } catch (e: RuntimeException) { throw ScreenCaptureException("Cannot take a screenshot of a view", e) } - -fun takeComposeNodeScreenshot(nodeInteraction: SemanticsNodeInteraction): String = - try { - encodeBitmap( - nodeInteraction.captureToImage().asAndroidBitmap() - ) { nodeInteraction.fetchSemanticsNode().toString() } - } catch (e: RuntimeException) { - throw ScreenCaptureException("Cannot take a screenshot of a node", e) - } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/ComposeNodeElement.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/ComposeNodeElement.kt deleted file mode 100644 index 9fe239c8..00000000 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/ComposeNodeElement.kt +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.espressoserver.lib.model - -import android.graphics.Rect -import androidx.compose.ui.semantics.SemanticsActions -import androidx.compose.ui.semantics.SemanticsNode -import androidx.compose.ui.semantics.SemanticsProperties -import androidx.compose.ui.semantics.SemanticsPropertyKey -import androidx.compose.ui.semantics.getOrNull -import androidx.compose.ui.state.ToggleableState -import io.appium.espressoserver.lib.handlers.exceptions.NotYetImplementedException -import io.appium.espressoserver.lib.model.Rect.Companion.fromBounds - -const val DEFAULT_TAG_NAME = "ComposeNode" -val composeAttributes by lazy { ComposeAttributes() } - -val POSSIBLE_CLASS_PROPERTIES: List> by lazy { - listOf( - SemanticsProperties.EditableText, - SemanticsProperties.Text, - SemanticsProperties.ProgressBarRangeInfo, - SemanticsProperties.HorizontalScrollAxisRange, - SemanticsProperties.VerticalScrollAxisRange, - SemanticsProperties.SelectableGroup, - SemanticsProperties.PaneTitle, - SemanticsProperties.Password - ) -} - -class ComposeNodeElement(private val node: SemanticsNode) { - - val contentDescription: CharSequence? - get() = node.config.getOrNull(SemanticsProperties.ContentDescription)?.firstOrNull() - - val text: String? - get() = node.config.getOrNull(SemanticsProperties.Text)?.firstOrNull()?.toString() - ?: node.config.getOrNull(SemanticsProperties.EditableText)?.text - ?: node.config.getOrNull(SemanticsProperties.ProgressBarRangeInfo)?.current?.toString() - - val resourceId: String - get() = node.id.toString() - - val viewTag: CharSequence? - get() = node.config.getOrNull(SemanticsProperties.TestTag) - - val isClickable: Boolean - get() = node.config.contains(SemanticsActions.OnClick) - - val isEnabled: Boolean - get() = !node.config.contains(SemanticsProperties.Disabled) - - val isFocused: Boolean - get() = node.config.getOrNull(SemanticsProperties.Focused) == true - - val isScrollable: Boolean - get() = node.config.contains(SemanticsActions.ScrollBy) - - val isSelected: Boolean - get() = node.config.getOrNull(SemanticsProperties.Selected) == true - - val className: String - get() { - // Compose API doesn't have class name info, as a workaround relaying on node SemanticsProperties. - return node.config.getOrNull(SemanticsProperties.Role)?.toString() - ?: POSSIBLE_CLASS_PROPERTIES.firstOrNull { node.config.contains(it) }?.name - ?: DEFAULT_TAG_NAME - } - - val isPassword: Boolean - get() = node.config.contains(SemanticsProperties.Password) - - val isChecked: Boolean - get() = node.config.getOrNull(SemanticsProperties.ToggleableState) == ToggleableState.On - - val index: Int - get() { - node.parent?.let { - it.children.mapIndexed { index, childNode -> if (node.id == childNode.id) return index } - } - return 0 - } - - val bounds: Rect - get() { - val bounds = node.boundsInWindow - return Rect( - bounds.left.toInt(), bounds.top.toInt(), bounds.right.toInt(), - bounds.bottom.toInt() - ) - } - - val rect: io.appium.espressoserver.lib.model.Rect - get() = fromBounds(bounds) - - fun getAttribute(attributeName: String): String? { - when (composeAttributes.valueOf(attributeName)) { - AttributesEnum.CONTENT_DESC -> return contentDescription?.toString() - AttributesEnum.CLASS -> return className - AttributesEnum.CLICKABLE -> return isClickable.toString() - AttributesEnum.ENABLED -> return isEnabled.toString() - AttributesEnum.FOCUSED -> return isFocused.toString() - AttributesEnum.SCROLLABLE -> return isScrollable.toString() - AttributesEnum.PASSWORD -> return isPassword.toString() - AttributesEnum.SELECTED -> return isSelected.toString() - AttributesEnum.BOUNDS -> return bounds.toShortString() - AttributesEnum.RESOURCE_ID -> return resourceId - AttributesEnum.INDEX -> return index.toString() - AttributesEnum.VIEW_TAG -> return viewTag?.toString() - AttributesEnum.TEXT -> return text?.toString() - AttributesEnum.CHECKED -> return isChecked.toString() - else -> throw NotYetImplementedException( - "Compose doesn't support attribute '$attributeName', Attribute name should be one of ${composeAttributes.supportedAttributes()}") - } - } -} diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/Element.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/Element.kt index 108c91fb..f32ba41a 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/Element.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/Element.kt @@ -19,7 +19,6 @@ package io.appium.espressoserver.lib.model import android.view.View import android.view.ViewParent import android.widget.AdapterView -import androidx.compose.ui.test.SemanticsNodeInteraction import androidx.test.espresso.Espresso.onData import androidx.test.espresso.Espresso.onView import androidx.test.espresso.EspressoException @@ -30,7 +29,6 @@ import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import com.google.gson.annotations.SerializedName import io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException import io.appium.espressoserver.lib.handlers.exceptions.StaleElementException -import io.appium.espressoserver.lib.helpers.ComposeViewCache import io.appium.espressoserver.lib.helpers.StringHelpers.charSequenceToNullableString import io.appium.espressoserver.lib.helpers.ViewState import io.appium.espressoserver.lib.helpers.EspressoViewsCache @@ -161,14 +159,3 @@ class EspressoElement(viewState: ViewState) : BaseElement { } } } - -class ComposeElement(node: SemanticsNodeInteraction) : BaseElement { - @Suppress("JoinDeclarationAndAssignment") - @SerializedName(JSONWP_ELEMENT_KEY, alternate = [W3C_ELEMENT_KEY]) - override val element: String - - init { - element = UUID.randomUUID().toString() - ComposeViewCache.put(element, node) - } -} \ No newline at end of file diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/GlobalSession.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/GlobalSession.kt index 59476857..8091cd94 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/GlobalSession.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/GlobalSession.kt @@ -17,7 +17,6 @@ package io.appium.espressoserver.lib.model import io.appium.espressoserver.lib.helpers.AndroidLogger -import io.appium.espressoserver.lib.helpers.ComposeViewCache import io.appium.espressoserver.lib.helpers.EspressoViewsCache import io.appium.espressoserver.lib.helpers.extensions.withPermit import java.util.* @@ -45,7 +44,6 @@ object GlobalSession { AndroidLogger.warn("Got request for new session creation while the one " + "is still in progress. Overriding the old session having the id $_sessionId") EspressoViewsCache.reset() - ComposeViewCache.reset() } _sessionId = UUID.randomUUID().toString() _capabilities = capabilities @@ -58,7 +56,6 @@ object GlobalSession { _sessionId = null _capabilities = null EspressoViewsCache.reset() - ComposeViewCache.reset() } } } diff --git a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/SourceDocument.kt b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/SourceDocument.kt index 416edf45..5038986a 100644 --- a/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/SourceDocument.kt +++ b/espresso-server/app/src/androidTest/java/io/appium/espressoserver/lib/model/SourceDocument.kt @@ -25,13 +25,6 @@ import android.view.View import android.view.ViewGroup import android.widget.AdapterView import androidx.test.core.app.ApplicationProvider.getApplicationContext -import androidx.compose.ui.semantics.SemanticsNode -import androidx.compose.ui.test.SelectionResult -import androidx.compose.ui.test.SemanticsNodeInteraction -import androidx.compose.ui.test.onRoot -import io.appium.espressoserver.EspressoServerRunnerTest -import io.appium.espressoserver.EspressoServerRunnerTest.Companion.context -import io.appium.espressoserver.lib.drivers.DriverContext import io.appium.espressoserver.lib.handlers.exceptions.AppiumException import io.appium.espressoserver.lib.handlers.exceptions.XPathLookupException import io.appium.espressoserver.lib.helpers.AndroidLogger @@ -44,12 +37,9 @@ import org.w3c.dom.NodeList import org.xml.sax.InputSource import org.xmlpull.v1.XmlSerializer import java.io.* -import java.lang.AssertionError import java.util.* import java.util.concurrent.Semaphore import javax.xml.xpath.* -import kotlin.reflect.full.declaredMemberFunctions -import kotlin.reflect.jvm.isAccessible const val NON_XML_CHAR_REPLACEMENT = "?" const val VIEW_INDEX = "viewIndex" @@ -213,49 +203,6 @@ class SourceDocument constructor( serializer?.endTag(NAMESPACE, tagName) } - private fun serializeComposeNode(semanticsNode: SemanticsNode?, depth: Int) { - if (semanticsNode == null) { - return - } - val nodeElement = ComposeNodeElement(semanticsNode) - val className = nodeElement.className - val tagName = toXmlNodeName(className) - serializer?.startTag(NAMESPACE, tagName) - - linkedMapOf( - AttributesEnum.CLASS to { className }, - AttributesEnum.INDEX to { nodeElement.index }, - AttributesEnum.CLICKABLE to { nodeElement.isClickable }, - AttributesEnum.ENABLED to { nodeElement.isEnabled }, - AttributesEnum.FOCUSED to { nodeElement.isFocused }, - AttributesEnum.SCROLLABLE to { nodeElement.isScrollable }, - AttributesEnum.SELECTED to { nodeElement.isSelected }, - AttributesEnum.CHECKED to { nodeElement.isChecked }, - AttributesEnum.VIEW_TAG to { nodeElement.viewTag }, - AttributesEnum.CONTENT_DESC to { nodeElement.contentDescription }, - AttributesEnum.BOUNDS to { nodeElement.bounds.toShortString() }, - AttributesEnum.TEXT to { nodeElement.text }, - AttributesEnum.PASSWORD to { nodeElement.isPassword }, - AttributesEnum.RESOURCE_ID to { nodeElement.resourceId }, - ).forEach { - setAttribute(it.key, it.value()) - } - - if (depth < MAX_TRAVERSAL_DEPTH) { - // Visit the children and build them too - for (index in 0 until semanticsNode.children.count()) { - serializeComposeNode(semanticsNode.children[index], depth + 1) - } - } else { - AndroidLogger.warn( - "Skipping traversal of ${semanticsNode.javaClass.name}'s children, since " + - "the current depth has reached its maximum allowed value of $depth" - ) - } - - serializer?.endTag(NAMESPACE, tagName) - } - private fun toStream(): InputStream { var lastError: Throwable? = null // Try to serialize the xml into the memory first, since it is fast @@ -281,26 +228,8 @@ class SourceDocument constructor( it.startDocument(XML_ENCODING, true) it.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true) val startTime = SystemClock.uptimeMillis() - when (context.currentStrategyType) { - DriverContext.StrategyType.COMPOSE -> { - if (root != null) { - serializeComposeNode(root as SemanticsNode, 0) - } else { - val rootNodes = rootSemanticNodes() - if (rootNodes.size == 1) { - serializeComposeNode(rootNodes.first(), 0) - } else { - serializer?.startTag(NAMESPACE, DEFAULT_TAG_NAME) - rootNodes.forEach { semanticsNode -> serializeComposeNode(semanticsNode, 0) } - serializer?.endTag(NAMESPACE, DEFAULT_TAG_NAME) - } - } - } - DriverContext.StrategyType.ESPRESSO -> { - val rootView = root ?: ViewGetter().rootView - serializeView(rootView as View, 0) - } - } + val rootView = root ?: ViewGetter().rootView + serializeView(rootView as View, 0) it.endDocument() AndroidLogger.info( @@ -330,26 +259,6 @@ class SourceDocument constructor( throw AppiumException(lastError!!) } - private fun rootSemanticNodes(): List = - try { - listOf(EspressoServerRunnerTest.composeTestRule.onRoot(useUnmergedTree = true).fetchSemanticsNode()) - } catch (e: AssertionError) { -// Ideally there should be on `root` node but on some cases e.g:overlays screen, there can be more than 1 root. -// Compose API not respecting such cases instead throws AssertionError, as a work around fetching all root nodes by relaying on internal API. -// e.g: "Reason: Expected exactly '1' node but found '2' nodes that satisfy: (isRoot)" - val result: SelectionResult = SemanticsNodeInteraction::class.declaredMemberFunctions.find { it.name == "fetchSemanticsNodes" }?.let { - it.isAccessible = true -// INFO: Compose API has added the method parameter in compose 1.6.x+ -// https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction.kt;l=59;bpv=1;bpt=0;drc=78d5dc8c9b42c32b0c8518c72181c19620a71c05;dlc=7aed8c7ff9c9355d5dfeb28021f8725d58dc4c6f - if (it.parameters.size == 4) { - it.call(EspressoServerRunnerTest.composeTestRule.onRoot(useUnmergedTree = true), true, null, true) - } else { - it.call(EspressoServerRunnerTest.composeTestRule.onRoot(useUnmergedTree = true), true, null) - } - } as SelectionResult - result.selectedNodes - } - private fun performCleanup() { tmpXmlName?.let { getApplicationContext().deleteFile(it)