Android Compose UI testing: how get the Text from a node - android

I want in my test get the Text from a node.
**var nodes=onAllNodes(myNode).fetchSemanticsNodes()**
println("Test_printlog ########### start ${nodes.size}")
// give a corret number
for (node in nodes) {
println("TestNODE ${node.config}")
I have:
TestNODE SemanticsConfiguration#972964b{ mergeDescendants=true,TestTag : myTestTag, Text : my text,
If I want to get the Text property I tried to use node.config.get
but wat is the parameter to pass to the get to get the text?
in the documentation said:
androidx.compose.ui.semantics.SemanticsConfiguration public final
operator fun get(
key: SemanticsPropertyKey ): T Retrieves the value for the given property if one has been set. If a value has not been set,
throws IllegalStateException
I try several time... but I have always error
like for example if I use node.config.get("Text")
Type mismatch. Required: SemanticsPropertyKey<TypeVariable(T)> Found:
String
What is the correct syntax to get the Text property from node.config.get?

I found.....
add:
import androidx.compose.ui.semantics.SemanticsProperties.Text
and use
node.config.getOrNull(Text)}
in this way you can also find all the other semantic properties:
import androidx.compose.ui.semantics.SemanticsProperties.TestTag
node.config.getOrNull(TestTag)}

Related

Set property type from specific class as parameter type

I have this sample data class:
data class Car ( var id: String )
Now I can create a fun as this:
fun doWhatever(id: String){}
My problem is that if my customer then tells me that Id is an int, I have to change it in both places.
So what I want is to set Car.id type as refence in fun doWhatever, something like this:
fun doWhatever(id: propertyTypeOfCarId){}
So I if the customer changes type, I only have to change it in the class.
I read all kind of posts, but I wasnt able to find the answer. Any idea how to achieve it?
If this isn't something you expect to be doing regularly, consider just using the refactoring tools the IDE provides. You code to handle a specific set of data, and if the structure of that data changes, you have to adapt the code to fit it. Baking in a bunch of "what if" functionality can add complexity, compared to just saying a String is a String and changing it if it ever needs changing, using the tools provided to make that as quick and easy as possible.
But sometimes you need to do this kind of thing, and Kotlin has some nice language features it can be worth using, like type aliases:
typealias CarId = String
data class Car(var id: CarId)
fun doWhatever(id: CarId){}
Two benefits here: the actual type is only defined in one place, so you can change that String to an Int without needing to change anything else - except stuff that relied on the ID being a String specifically of course
The other benefit is you're actually adding some semantic information by using that very specific type. That function isn't supposed to just take any old String - it's specifically meant to handle CarIds. It tells you what it's for, and that can make your code a lot easier to understand
(The function will accept Strings, because CarId is just an alias - an alternative name for a String - so it's not a way to enforce structure on your code, just a way to make it nicer to read and write. You can't define a new type that is a String in Kotlin unfortunately)
If the number of id types you support is limited, you can simply use method overloading:
fun doWhatever(id: String){}
fun doWhatever(id: Int){}
// etc.
Alternatively, you can use a reified generic parameter in your method to support any number of types:
inline fun <reified T> doWhatever(id: T) {
when (T::class) {
Int::class -> {}
String::class -> {}
}
}

What are the rules for using out keyword in generics type without getting a compilation error

In Kotlin i am learning about covariant(a subtype can be used in place of a super type).
They wrote there something like a rule. but it seems wrong for me. It is written:
You can’t, however, use out if the class has function parameters or var
properties of that generic type.
But i think that the word or should be replaced with the word and, because in situation when a class has a function that "gets" the type as a parameter, if the property of the generic type is a val and not var, and damage can't be done, because any assignment isn't possible to val property.
Am i right or what is written in the book is correct and i'm missing something?
Edit:
I just realized (according to some post i saw in this forum) that the only situation that a parameter can be a problem although property is declared as val, is in case we have a container of type T, let's say List then it may be a problem if we try to add to the List, but if we don't have a container i can't see situation when getting a parameter type can make trouble while property is val. Am i right?
The out keyword is for covariance, not contravariance.
Here's a basic example of the trouble caused in an imaginary class where covariance is allowed for the var property type:
class Container<out T>(var item: T)
val intContainer = Container<Int>(1)
val numberContainer: Container<Number> = intContainer // cast is allowed for covariant type
numberContainer.item = 5f // allowed if item is a var
val intValue = intContainer.item // Float value is cast to an Int!
This isn't possible with a val so the above class could be covariant at the declaration site if item were a val.

setText returning error when attempting to input a string on an editText Kotlin

I am attempting to perform a simple mathematical operation on one editText field which changes the value of another editText field (a unit conversion calculator).
inchesEditText.setText(String) = (metersVal.toString().toDouble() * metersToInchesVal).toString()
The following error was returned when setting the text of the editText field:
Error:(24, 28) None of the following functions can be called with the
arguments supplied: public final fun setText(p0: CharSequence!): Unit
defined in android.widget.EditText public final fun setText(p0: Int):
Unit defined in android.widget.EditText
Any help would be much appreciated. Thanks
you need to do something like below. If you want to set value in EditText then you have to set value inside yourEditText.setText('yourvalue') and yourvalue must be in String format. check below,
inchesEditText.setText( (metersVal.toString().toDouble() * metersToInchesVal).toString() )
In kotlin you can write in below way :
mBinding.txtHandlerTimer.text = (metersVal.toString().toDouble() * metersToInchesVal).toString()
Thanks

Why does Kotlin data class objects have backticks?

This is my data class created using a Kotlin data class creator Plugin.
data class ResponseHealthInisghts(
val `data`: List<Data>,
val message: String,
val statusCode: Int
)
This code gets work even if I remove the backticks, I wonder if it's for Java interoperability. But this variable is not a keyword but also it has backticks. why?
Based on Why does this Kotlin method have enclosing backticks?
this question is is a keyword for both Java and Kotlin but data is not.
You can use backticks simply to enclose class, method or variable name
For example it's useful if there are spaces:
class `Final Frontier` {
fun `out of space`() {
val `first second`: String?
}
}
Or as you mention if using Kotlin keyword
If a Java library uses a Kotlin keyword for a method
foo.`is`(bar)
data is a Modifier Keyword
data instructs the compiler to generate canonical members for a class
The following tokens act as keywords in modifier lists of declarations and can be used as identifiers in other contexts
And not a Hard Keyword that can't be used as identifier
The following tokens are always interpreted as keywords and cannot be used as identifier
It allows you to use reserved keywords and operators as names of your variables. The list of those words: https://kotlinlang.org/docs/reference/keyword-reference.html
Based on this question's answerWhy does this Kotlin method have enclosing backticks?
and the comments from #forpas and #marstran I was able to understand my problem.
The is keyword is a hard keyword
Hard Keywords
are always interpreted as keywords and cannot be used as identifiers:
so fore interoperability we need to use backticks because Java and Kotlin both have is keyword.
Where data keyword is only available in Kotlin and also belong to the category
Soft Keywords
act as keywords in the context when they are applicable and can be used as identifiers in other contexts.
So we can use it with or without backticks.
Also as an additional note you can use bacticks to customize your identifier
var `data is simple` : List<String>
If it shows lint error use
"File | Settings | Editor | Inspections | Illegal Android Identifier" and disable this inspection.

Split space from string not working in Kotlin

Anyone wonder this ? Splitting SPACE (" ") in kotlin is not working, i tried with different regex codes but is not working at all.
Tried with this :
value.split("\\s")[0];
value.split("\\s+")[0];
value.split("\\s++")[0];
Then i came up with solution -> Create java constant class which contains this function and returns string array to your kotlin class.
Is there any other solution for this problem where we can directly achieve this thing?
Solution : As #Edson Menegatti said :
KOTLIN Specific : WORKING
values.split("\\s".toRegex())[0]
Many people suggested this solution : NOT WORKING
values.split(" ")[0]
But in my case it's not working.
Here's an issue between the Java and Kotlin implementation of String.split.
While the Java implementation does accept a regex string, the Kotlin one does not. For it to work, you need to provide an actual Regex object.
To do so, you would update your code as follows:
value.split("\\s".toRegex())[0]
Also, as #Thomas suggested, you can just use the regular space character to split your string with:
value.split(" ")[0]
Final point, if you're only using the first element of the split list, you might want to consider using first() instead of [0] - for better readability - and setting the limit parameter to 2 - for better performance.
You need to use :
.toRegex()
fun main(args: Array<String>) {
val str = "Kotlin com"
val separate1 = str.split("\\s".toRegex())[0]
println(separate1) // ------------------> Kotlin
}
OR
You can also use .split(" ")[0] to achieve result. Like
fun main(args: Array<String>) {
val str = "Kotlin com"
val separate1 = str.split(" ")[0]
println(separate1) // ----------> Kotlin
}
String#split (actually CharSequence#split) can take either a regular expression, or just a string which is interpreted literally. So:
value.split(" ")[0]
does what you want.
If you're only using the first element, it's more efficient to also pass limit = 2. Or, even better, use substringBefore.
Kotlin tries to resolve some issues that Java's String library has. For instance, Kotlin tries to be more explicit.
As a result, the split method takes a normal String and does not use it as a regex internally:
"hello world".split("\\s")[0] //no match
"hello world".split(" ")[0] // => "hello"
To explicitly use the overloaded split function that actually takes a regex, the toRegex() extension can be used (inline fun String.toRegex(): Regex (source)):
"hello world".split("\\s".toRegex())[0]// => "hello"
The following shows another example of Kotlin resolving the confusing String::replaceAll method:
Taken from a KotlinConf presentation of Svetlana Isakova, co-author of “Kotlin in Action”
Single delimiter
val splittedStringList = "123.345-80A".split(".")
println(splittedStringList[0])
Several delimiters
println("123.345-80A".split(".", "-"))
Using regex
println("123.345-80A".split("\\.|-".toRegex()))
Try Kotlin Online
Simply use value.split("\s".toRegex())
1.Splits and iterates all items
value.split("\\s".toRegex()).forEach { item ->
//use item
}
2.Spits and use first item
value.split("\\s".toRegex()).first()
3.Spits and use last item
value.split("\\s".toRegex()).last()

Categories

Resources