Search code examples
androidkotlinandroid-layoutandroid-espressokakao

Kaspresso. How check element is displayed without exception


I want check authauthorization screen is displayed with kaspresso But isDisplyed() dont return boolean, and i have error.

How check element is displayed without exception

Now my solution:

fun isNeedAuth(): Boolean {
        return try {
            authButton.isEnabled()
            true
        } catch (e: NullPointerException) {
            false
        }
    }

Solution

  • I'm personally using:

    fun safeAssertion(assert: () -> Unit) =
        try {
            assert()
            true
        } catch (_: Throwable) {
            false
        }
    

    In tests it looks like:

    if (safeAssertion { authButton.isEnabled() }) { doSomething() }
    

    Also, you can make an extension for KViews:

    fun <K : BaseAssertions> K.safeAssert(assert: K.() -> Unit) = safeAssertion { assert() }
    

    And use it like:

    if (authButton.safeAssert { isDisplayed() }) { doSomething() }
    

    More advanced solution with waiting for desired state:

    fun waitUntilConditionMet(
        description: String = "",
        maxWaitTime: Duration = 10.seconds,
        retryInterval: Duration = 250.milliseconds,
        onFail: () -> Unit = { throw MyCustomWaitingFailedException(maxWaitTime, description) },
        conditionToMeet: () -> Boolean
    ) {
        try {
            runBlocking {
                withTimeout(maxWaitTime) {
                    while (!conditionToMeet()) {
                        delay(retryInterval)
                    }
                }
            }
        } catch (e: Throwable) {
            Log.e("My Custom Waiter", e.message ?: "Failed to meet condition in ${maxWaitTime.inWholeSeconds} seconds")
            onFail()
        }
    }
    

    Usage example (will throw exception if condition is not met in 10 seconds):

    waitUntilConditionMet("Some screen appeared") {
        safeAssertion {
            someButton.isDisplayed()
            anotherView.isEnabled()
        }
    }
    

    Or without throwing exception:

    waitUntilConditionMet(
        description = "Some screen appeared",
        onFail = { doSomethingIfConditionIsNotMet() }
    ) {
        safeAssertion {
            someButton.isDisplayed()
            anotherView.isEnabled()
        }
    }