Skip to content

Releases: open-tool/ultron

2.5.0-alpha09

04 Jul 22:10
3916eef
Compare
Choose a tag to compare

What's Changed

Full Changelog: 2.3.5...2.5.0-alpha09

2.3.5

18 Mar 17:21
a108073
Compare
Choose a tag to compare

What's Changed

  • Custom Allure directory in #61

By default Allure results are saved in /data/data/<package_name>/files/allure-results.
It's possible to set a custom directory. Make sure application has WRITE permission to the directory.

UltronAllureConfig.setAllureResultsDirectory(File("directory_path"))
UltronAllureConfig.setAllureResultsDirectory(Environment.DIRECTORY_DOCUMENTS)
UltronAllureConfig.setAllureResultsDirectory() // set Environment.DIRECTORY_DOWNLOADS as target directory

If custom directory is specified allure results artifacts are copied to the desired directory at the end of test run.

If no parameters are provided to UltronAllureConfig.setAllureResultsDirectory() then you can pull artifacts from /sdcard/Download/allure-results.

  • Fix RecyclerView item search in #62

Full Changelog: 2.3.3...2.3.5

2.3.3

07 Mar 07:54
Compare
Choose a tag to compare

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

25 Feb 11:47
dd15bc8
Compare
Choose a tag to compare

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

02 Dec 08:13
Compare
Choose a tag to compare

What's Changed

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

20 Aug 12:01
1c81014
Compare
Choose a tag to compare

What's Changed

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

31 Jul 20:36
Compare
Choose a tag to compare

What's Changed

Note: To add window hierarchy for Compose you have to call

UltronComposeConfig.addListener(WindowHierarchyAttachListener())

See updated Allure doc

New Contributors

Full Changelog: 2.2.4...2.2.6

2.2.4

17 Jun 15:45
Compare
Choose a tag to compare

#45 - Fix method name for parametrized tests

2.2.3

13 Jun 20:01
Compare
Choose a tag to compare

Fix:

  • getViewForcibly()
  • performOnViewForcibly()

2.2.2

31 May 20:29
Compare
Choose a tag to compare

Inhencments

  1. 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
  1. Add method to perform action on view on Ui Thread.
View.performOnView(action: View.() -> Unit)
  1. Improved ResourceDrawableMatcher, affected methods:
hasDrawable(@DrawableRes resourceId: Int)
hasAnyDrawable()

Thanks @itsergpot