Releases: open-tool/ultron
2.3.3
Compose List & RecyclerView Item Child improvements in #60
- ComposeListItem child
old syntax:
class CustomListItem : UltronComposeListItem() {
val status by lazy { getChild(hasTestTag(contactStatusTestTag)) }
}
new:
class CustomListItem : UltronComposeListItem() {
val name by child { hasTestTag(contactNameTestTag) }
}
You can use both ways at the same time:
class CustomListItem : UltronComposeListItem() {
val name by child { hasTestTag(contactNameTestTag) }
val status by lazy { getChild(hasTestTag(contactStatusTestTag)) }
}
- RecyclerViewItem child
Old syntax:
class CustomRecyclerItem : UltronRecyclerViewItem() {
val name by lazy { getChild(withId(R.id.tv_name)) }
}
New:
class CustomRecyclerItem : UltronRecyclerViewItem() {
val name by child { withId(R.id.tv_name) }
}
You can use both ways at the same time:
class CustomRecyclerItem : UltronRecyclerViewItem() {
val name by child { withId(R.id.tv_name) }
val status by lazy { getChild(withId(R.id.tv_status)) }
}
Full Changelog: 2.3.2...2.3.3
2.3.2
What's Changed
Compose LazyList improvements in #59
Add
- new methods to interact with LazyList item by position:
firstItem()
item(position: Int)
getItem(position: Int): T
getFirstItem(): T
to use these methods you have to configure positionPropertyKey
in application code and specify it in composeList
declaration.
composeList(marcher =..., positionPropertyKey = ListItemPositionPropertyKey)
Read new wiki page for details - Efficient Strategies for Locating Items in Compose LazyList
- new method for
UltronComposeList
fun assertItemDoesNotExist(itemMatcher: SemanticsMatcher)
Removed
method UltronComposeListItem().assertDoesNotExist()
Full Changelog: 2.3.1...2.3.2
2.3.1
What's Changed
- #49 Custom name for matcher object for Espresso, UiAutomator, Compose by @alex-tiurin in #57
- #50 meta info by @alex-tiurin in #57
There are 2 new general methods:
withName(name: String)
withMetaInfo(meta: Any)
By default name
is used in exceptions messages.
These data also could be used in listeners and result analyzers:
class MetaListener: UltronLifecycleListener(){
override fun afterFailure(operationResult: OperationResult<Operation>) {
val name = operationResult.operation.elementInfo.name
val metaInfo = operationResult.operation.elementInfo.meta
}
}
Full Changelog: 2.3.0...2.3.1
2.3.0
What's Changed
- Ultron extension by @alex-tiurin in #55
Enhanced framework extension for Espresso and Compose.
Here is a new wiki page
New features
Add new Compose methods to getNode and getNodeConfigProperty:
val semanticsNode = hasTestTag("Button").getNode()
val testTag = hasText("Some text").getNodeConfigProperty(SemanticsProperties.TestTag)
Simplified Compose extension
Introducing new perform
and execute
methods.
Use perform if you wish to evaluate an operation and return an updated UltronComposeSemanticsNodeInteraction
object.
fun UltronComposeSemanticsNodeInteraction.hasAnyChildren() = perform {
Assert.assertTrue(it.fetchSemanticsNode().children.isNotEmpty())
}
fun SemanticsMatcher.hasAnyChildren() = UltronComposeSemanticsNodeInteraction(this).hasAnyChildren()
Use execute
to evaluate operation and return the result.
fun UltronComposeSemanticsNodeInteraction.getWidth(): Int = execute {
it.fetchSemanticsNode().size.width
}
fun SemanticsMatcher.getWidth(): Int = UltronComposeSemanticsNodeInteraction(this).getWidth()
Simplified Espresso operations extenstion
Use perform
if you intend to evaluate an operation and return an updated UltronEspressoInteraction
fun <T> UltronEspressoInteraction<T>.appendText(value: String) = perform { _, view ->
val textView = (view as TextView)
textView.text = "${textView.text}$value"
}
Use execute
to evaluate operation and return the result.
fun <T> UltronEspressoInteraction<T>.getText(): String = execute { _, view ->
(view as TextView).text.toString()
}
Customize your action using UltronEspressoActionParams
for both pefrorm
and execute
methods.
fun <T> UltronEspressoInteraction<T>.getDrawable(): Drawable? = execute(
UltronEspressoActionParams(
operationName = "GetDrawable from TextView with '${getInteractionMatcher()}'",
operationDescription = "description...",
operationType = CustomEspressoActionType.GET_DRAWABLE,
viewActionConstraints = isAssignableFrom(ImageView::class.java),
viewActionDescription = "getting Drawable from ImageView"
)
){ _, view ->
(view as ImageView).drawable
}
Use new assertMatches
method to extend framework with new assertion.
fun <T> UltronEspressoInteraction<T>.assertChecked(expectedState: Boolean) = assertMatches { view ->
(view as CheckBox).isChecked == expectedState
}
Breaking changes:
The signature of UltronComposeSemanticsNodeInteraction
old perform
method has been modified.
If you are using the old perform
method to obtain the result of an operation, you should replace it with execute
.
For instance, in the following cases, replace pefrorm
to execute
// in extension function
fun UltronComposeSemanticsNodeInteraction.getWidth(): Int = pefrorm {
it.fetchSemanticsNode().size.width
}
// direct usage
val width: Int = hasTestTag("button").pefrorm {
it.fetchSemanticsNode().size.width
}
Deprecated
Matcher<View>.performOnView()
- Use new Matcher<View>.perform { view -> }
instead.
Full Changelog: 2.2.6...2.3.0
2.2.6
What's Changed
- fix parametrized test name handling by @flotnik in #51
- Add modern design by @Alexandr-Stb in #53
- dumpHierarchy for Allure report by @alex-tiurin in #54
Note: To add window hierarchy for Compose you have to call
UltronComposeConfig.addListener(WindowHierarchyAttachListener())
See updated Allure doc
New Contributors
- @flotnik in #51
- @Alexandr-Stb made first contribution in #53
Full Changelog: 2.2.4...2.2.6
2.2.4
2.2.3
Fix:
getViewForcibly()
performOnViewForcibly()
2.2.2
Inhencments
- New extension methods for
Matcher<View>, ViewInteraction, DataInteraction
:
doesNotExistInAnyVisibleRoot()
getView(): View
getViewForcibly(): View //bypass Espresso idling state mechanism
performOnView(action: View.() -> Unit)
performOnViewForcibly(action: View.() -> Unit) //bypass Espresso idling state mechanism
- Add method to perform action on view on Ui Thread.
View.performOnView(action: View.() -> Unit)
- Improved
ResourceDrawableMatcher
, affected methods:
hasDrawable(@DrawableRes resourceId: Int)
hasAnyDrawable()
Thanks @itsergpot
ultron-allure
Allure report artifacts generation is supported.
There is a new dependency com.atiurin:ultron-allure:<latest_version>
.
Ultron provides all required allure libs. You don't need to add them.
Please read Allure wiki carefully.
Recommended configs
Ultron has recommendations about it's configuration. Basically you just need to add few lines of code to receive full power of framework:
@BeforeClass @JvmStatic
fun configuration() {
UltronConfig.applyRecommended()
UltronAllureConfig.applyRecommended()
UltronComposeConfig.applyRecommended()
UltronComposeConfig.addListener(ScreenshotAttachListener())
UltronComposeConfig.addListener(DetailedOperationAllureListener())
}
Breaking changes
UltronComposeConfig
import changed from import com.atiurin.ultron.core.compose.UltronComposeConfig
to
import com.atiurin.ultron.core.compose.config.UltronComposeConfig
ultron-compose
Compose part is separated into another library ultron-compose
From 2.1.0 you need to add 2 dependencies.
dependencies {
androidTestImplementation 'com.atiurin:ultron:<latest_version>'
androidTestImplementation 'com.atiurin:ultron-compose:<latest_version>'
}
com.atiurin:ultron:2.1.0
provides required libs, so you don't need to add them to dependencies.
The list of provided libs:
"androidx.test.espresso:espresso-core:3.4.0"
"androidx.test.espresso:espresso-contrib:3.4.0"
"androidx.test.espresso:espresso-web:3.4.0"
"androidx.test.uiautomator:uiautomator:2.2.0"
"com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:4.0.0"
"org.hamcrest:hamcrest-core:2.2"
You can exclude them from androidTestImplementation
section
com.atiurin:ultron-compose:2.1.0
provides "androidx.compose.ui:ui-test-junit4:1.1.1"
Breaking changes
UltronConfig.Compose
moved to UltronComposeConfig
Internal changes
Move from gradle to kts