Skip to content

Commit

Permalink
fix Espresso softAssertions (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-tiurin authored Feb 2, 2025
1 parent f3beb72 commit 065e975
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,28 @@ import com.atiurin.sampleapp.framework.utils.AssertUtils
import com.atiurin.sampleapp.framework.utils.TestDataUtils.getResourceString
import com.atiurin.sampleapp.pages.UiElementsPage
import com.atiurin.sampleapp.tests.UiElementsTest
import com.atiurin.ultron.core.common.assertion.softAssertion
import com.atiurin.ultron.core.common.assertion.verifySoftAssertions
import com.atiurin.ultron.core.config.UltronCommonConfig
import com.atiurin.ultron.core.config.UltronConfig
import com.atiurin.ultron.core.espresso.UltronEspresso
import com.atiurin.ultron.custom.espresso.action.getContentDescription
import com.atiurin.ultron.custom.espresso.action.getDrawable
import com.atiurin.ultron.custom.espresso.action.getText
import com.atiurin.ultron.custom.espresso.assertion.hasAnyDrawable
import com.atiurin.ultron.custom.espresso.assertion.hasDrawable
import com.atiurin.ultron.extensions.*
import com.atiurin.ultron.extensions.clearText
import com.atiurin.ultron.extensions.click
import com.atiurin.ultron.extensions.closeSoftKeyboard
import com.atiurin.ultron.extensions.doubleClick
import com.atiurin.ultron.extensions.isDisplayed
import com.atiurin.ultron.extensions.isSameAs
import com.atiurin.ultron.extensions.isSuccess
import com.atiurin.ultron.extensions.longClick
import com.atiurin.ultron.extensions.perform
import com.atiurin.ultron.extensions.replaceText
import com.atiurin.ultron.extensions.textContains
import com.atiurin.ultron.extensions.withTimeout
import com.atiurin.ultron.utils.getTargetString
import org.junit.Assert
import org.junit.Test
Expand Down Expand Up @@ -258,4 +272,29 @@ class ViewInteractionActionsTest : UiElementsTest() {
)
}

@Test
fun verifySoftAssertionsTest() {
UltronCommonConfig.testContext.softAnalyzer.clear()
softAssertion(false) {
withText("NotExistText").withTimeout(100).click()
withText("NotExistTestTag").withTimeout(100).click()
}
runCatching {
verifySoftAssertions()
}.onFailure { exception ->
val message = exception.message ?: throw RuntimeException("Empty exception message: $exception")
Assert.assertTrue(message.contains("NotExistText"))
Assert.assertTrue(message.contains("NotExistTestTag"))
}
}

@Test
fun softAssertionTest() {
UltronCommonConfig.testContext.softAnalyzer.clear()
AssertUtils.assertException {
softAssertion {
withText("NotExistText").withTimeout(100).click()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,47 @@
package com.atiurin.sampleapp.tests.espresso

import androidx.test.espresso.matcher.ViewMatchers.*
import com.atiurin.ultron.custom.espresso.matcher.hasAnyDrawable
import com.atiurin.ultron.custom.espresso.matcher.withDrawable
import com.atiurin.ultron.extensions.*
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isEnabled
import androidx.test.espresso.matcher.ViewMatchers.withText
import com.atiurin.sampleapp.R
import com.atiurin.sampleapp.framework.ultronext.assertChecked
import com.atiurin.sampleapp.framework.utils.AssertUtils
import com.atiurin.sampleapp.framework.utils.TestDataUtils.getResourceString
import com.atiurin.sampleapp.pages.UiElementsPage
import com.atiurin.sampleapp.tests.UiElementsTest
import com.atiurin.ultron.core.common.assertion.softAssertion
import com.atiurin.ultron.core.common.assertion.verifySoftAssertions
import com.atiurin.ultron.core.config.UltronCommonConfig
import com.atiurin.ultron.custom.espresso.assertion.doesNotExistInAnyVisibleRoot
import com.atiurin.ultron.custom.espresso.assertion.hasCurrentHintTextColor
import com.atiurin.ultron.custom.espresso.assertion.hasCurrentTextColor
import com.atiurin.ultron.custom.espresso.assertion.hasHighlightColor
import com.atiurin.ultron.custom.espresso.assertion.hasShadowColor
import com.atiurin.ultron.custom.espresso.matcher.hasAnyDrawable
import com.atiurin.ultron.custom.espresso.matcher.withDrawable
import com.atiurin.ultron.extensions.assertMatches
import com.atiurin.ultron.extensions.click
import com.atiurin.ultron.extensions.doesNotExist
import com.atiurin.ultron.extensions.exists
import com.atiurin.ultron.extensions.hasContentDescription
import com.atiurin.ultron.extensions.hasFocus
import com.atiurin.ultron.extensions.hasText
import com.atiurin.ultron.extensions.isChecked
import com.atiurin.ultron.extensions.isClickable
import com.atiurin.ultron.extensions.isDisplayed
import com.atiurin.ultron.extensions.isEnabled
import com.atiurin.ultron.extensions.isFocusable
import com.atiurin.ultron.extensions.isJavascriptEnabled
import com.atiurin.ultron.extensions.isNotChecked
import com.atiurin.ultron.extensions.isNotClickable
import com.atiurin.ultron.extensions.isNotDisplayed
import com.atiurin.ultron.extensions.isNotEnabled
import com.atiurin.ultron.extensions.isNotFocusable
import com.atiurin.ultron.extensions.isNotSelected
import com.atiurin.ultron.extensions.isSelected
import com.atiurin.ultron.extensions.isSuccess
import com.atiurin.ultron.extensions.textContains
import com.atiurin.ultron.extensions.withTimeout
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.containsString
import org.junit.Assert
Expand Down Expand Up @@ -480,4 +507,30 @@ class ViewInteractionAssertionsTest : UiElementsTest() {
fun notExist_customAssertion(){
AssertUtils.assertException { withText("not exist").withTimeout(100).assertChecked(true) }
}

@Test
fun verifySoftAssertionsTest() {
UltronCommonConfig.testContext.softAnalyzer.clear()
softAssertion(false) {
withText("NotExistText").withTimeout(100).isDisplayed()
withText("NotExistTestTag").withTimeout(100).isDisplayed()
}
runCatching {
verifySoftAssertions()
}.onFailure { exception ->
val message = exception.message ?: throw RuntimeException("Empty exception message: $exception")
Assert.assertTrue(message.contains("NotExistText"))
Assert.assertTrue(message.contains("NotExistTestTag"))
}
}

@Test
fun softAssertionTest() {
UltronCommonConfig.testContext.softAnalyzer.clear()
AssertUtils.assertException {
softAssertion {
withText("NotExistText").withTimeout(100).isDisplayed()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import com.atiurin.sampleapp.framework.DummyMetaObject
import com.atiurin.sampleapp.framework.ultronext.appendText
import com.atiurin.sampleapp.framework.utils.AssertUtils
import com.atiurin.sampleapp.pages.WebViewPage
import com.atiurin.ultron.core.common.assertion.softAssertion
import com.atiurin.ultron.core.common.assertion.verifySoftAssertions
import com.atiurin.ultron.core.config.UltronCommonConfig
import com.atiurin.ultron.core.espressoweb.webelement.UltronWebElement.Companion.className
import com.atiurin.ultron.core.espressoweb.webelement.UltronWebElement.Companion.id
import com.atiurin.ultron.core.espressoweb.webelement.UltronWebElement.Companion.xpath
import com.atiurin.ultron.extensions.withName
import com.atiurin.ultron.extensions.withTimeout
import org.hamcrest.Matchers.`is`
import org.junit.Assert
import org.junit.Test
Expand Down Expand Up @@ -261,4 +262,30 @@ class UltronWebElementTest : BaseWebViewTest() {
Assert.assertEquals(meta, result.operation.elementInfo.meta)
}.exists()
}

@Test
fun verifySoftAssertionsTest() {
UltronCommonConfig.testContext.softAnalyzer.clear()
softAssertion(false) {
id("NotExistText").withTimeout(100).webClick()
id("NotExistTestTag").withTimeout(100).webClick()
}
runCatching {
verifySoftAssertions()
}.onFailure { exception ->
val message = exception.message ?: throw RuntimeException("Empty exception message: $exception")
Assert.assertTrue(message.contains("NotExistText"))
Assert.assertTrue(message.contains("NotExistTestTag"))
}
}

@Test
fun softAssertionTest() {
UltronCommonConfig.testContext.softAnalyzer.clear()
AssertUtils.assertException {
softAssertion {
page.notExistedElement.withTimeout(100).webClick()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.atiurin.ultron.core.common.Operation
import com.atiurin.ultron.core.common.OperationResult
import com.atiurin.ultron.core.common.resultanalyzer.OperationResultAnalyzer
import com.atiurin.ultron.core.common.resultanalyzer.UltronDefaultOperationResultAnalyzer
import com.atiurin.ultron.core.config.UltronConfig.Espresso.Companion
import com.atiurin.ultron.core.espresso.EspressoOperationResult
import com.atiurin.ultron.core.espresso.UltronEspressoOperation
import com.atiurin.ultron.core.espresso.assertion.EspressoAssertionType
Expand Down Expand Up @@ -149,6 +150,7 @@ object UltronConfig {

var resultAnalyzer: OperationResultAnalyzer = UltronCommonConfig.resultAnalyzer


inline fun setResultAnalyzer(crossinline block: (OperationResult<Operation>) -> Boolean) {
resultAnalyzer = object : OperationResultAnalyzer {
override fun <Op : Operation, OpRes : OperationResult<Op>> analyze(
Expand All @@ -173,8 +175,9 @@ object UltronConfig {
AmbiguousViewMatcherException::class.java,
UltronOperationException::class.java
)

val resultHandler: (EspressoOperationResult<UltronEspressoOperation>) -> Unit = {
resultAnalyzer.analyze(it)
UltronCommonConfig.testContext.wrapAnalyzerIfSoftAssertion(resultAnalyzer).analyze(it)
}
}
}
Expand All @@ -192,7 +195,7 @@ object UltronConfig {
AmbiguousViewMatcherException::class.java
)
val resultHandler: (EspressoOperationResult<UltronEspressoOperation>) -> Unit = {
resultAnalyzer.analyze(it)
UltronCommonConfig.testContext.wrapAnalyzerIfSoftAssertion(resultAnalyzer).analyze(it)
}
}
}
Expand All @@ -208,7 +211,7 @@ object UltronConfig {
RuntimeException::class.java
)
val resultHandler: (WebOperationResult<WebInteractionOperation<*>>) -> Unit = {
resultAnalyzer.analyze(it)
UltronCommonConfig.testContext.wrapAnalyzerIfSoftAssertion(resultAnalyzer).analyze(it)
}
}
}
Expand Down Expand Up @@ -257,7 +260,7 @@ object UltronConfig {
NullPointerException::class.java,
)
val resultHandler: (UiAutomatorOperationResult<UiAutomatorUiSelectorOperation>) -> Unit = {
resultAnalyzer.analyze(it)
UltronCommonConfig.testContext.wrapAnalyzerIfSoftAssertion(Espresso.resultAnalyzer).analyze(it)
}
}
}
Expand All @@ -274,7 +277,7 @@ object UltronConfig {
NullPointerException::class.java,
)
val resultHandler: (UiAutomatorOperationResult<UiAutomatorOperation>) -> Unit = {
resultAnalyzer.analyze(it)
UltronCommonConfig.testContext.wrapAnalyzerIfSoftAssertion(Espresso.resultAnalyzer).analyze(it)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import androidx.test.espresso.web.webdriver.DriverAtoms
import androidx.test.espresso.web.webdriver.DriverAtoms.findElement
import androidx.test.espresso.web.webdriver.Locator
import com.atiurin.ultron.core.common.CommonOperationType
import com.atiurin.ultron.core.common.ElementInfo
import com.atiurin.ultron.core.common.DefaultElementInfo
import com.atiurin.ultron.core.common.ElementInfo
import com.atiurin.ultron.core.common.UltronOperationType
import com.atiurin.ultron.core.common.assertion.DefaultOperationAssertion
import com.atiurin.ultron.core.common.assertion.EmptyOperationAssertion
Expand All @@ -25,7 +25,6 @@ import com.atiurin.ultron.core.espressoweb.operation.WebInteractionOperation
import com.atiurin.ultron.core.espressoweb.operation.WebInteractionOperationExecutor
import com.atiurin.ultron.core.espressoweb.operation.WebInteractionOperationIterationResult
import com.atiurin.ultron.core.espressoweb.operation.WebOperationResult
import com.atiurin.ultron.exceptions.UltronException
import com.atiurin.ultron.listeners.setListenersState
import com.atiurin.ultron.log.UltronLog
import org.hamcrest.Matcher
Expand Down Expand Up @@ -136,7 +135,7 @@ open class UltronWebElement internal constructor(
type = EspressoWebOperationType.WEB_GET_TEXT,
description = "GetText of '${elementInfo.name}' during $timeoutMs ms"
)
)
) ?: ""
}

/** Simulates the javascript events to click on a particular element. */
Expand Down Expand Up @@ -184,16 +183,15 @@ open class UltronWebElement internal constructor(
}

/** Returns {@code true} if the desired element is in view after scrolling. */
fun webScrollIntoViewBoolean(
): Boolean {
fun webScrollIntoViewBoolean(): Boolean {
return executeOperation(
getUltronWebActionOperation(
webInteractionBlock = { webInteractionBlock().perform(DriverAtoms.webScrollIntoView()) },
name = "${elementInfo.name} WebScrollIntoView",
type = EspressoWebOperationType.WEB_SCROLL_INTO_VIEW,
description = "'${elementInfo.name}' WebScrollIntoView during $timeoutMs ms"
)
)
) ?: false
}

/** Executes scroll to view. */
Expand Down Expand Up @@ -301,13 +299,12 @@ open class UltronWebElement internal constructor(

fun <R> executeOperation(
webInteractionOperation: WebInteractionOperation<R>
): R {
): R? {
val result = UltronWebLifecycle.execute(
executor = WebInteractionOperationExecutor(webInteractionOperation),
resultHandler = resultHandler as (WebOperationResult<WebInteractionOperation<R>>) -> Unit
)
return (result.operationIterationResult as WebInteractionOperationIterationResult<R>).webInteraction?.get()
?: throw UltronException("Couldn't get result of ${webInteractionOperation.name}.")
}

fun <R> executeOperationVoid(
Expand Down

0 comments on commit 065e975

Please sign in to comment.