Mohammad Derakhshan
Mohammad Derakhshan

Reputation: 1562

how to assert that text not contains specific characters in android jetpack compose testing?

I'm trying to write some test cases for my compose functions. I have an outlined Text field with a maximum value of 16 characters. So I want to test this feature. Here is the test:

    @Test
    fun checkMaxTaxCodeLength_16Character() {
        val taxCode = composeRule.onNodeWithTag(testTag = AUTHENTICATION_SCREEN_TAX_CODE_EDIT_TEXT)
        for (i in 'A'..'Z')
            taxCode.performTextInput(i.toString())
        taxCode.assertTextEquals("ABCDEFGHIJKLMNOP")
    }

But although I can see the input is correct, the test fails, and it seems assertTextEquals doesn't work correctly. So:

here is the code of text field:

                OutlinedTextField(
                    value = state.taxCode,
                    maxLines = 1,
                    onValueChange = { string ->
                        viewModel.onEvent(
                            AuthenticationEvent.TaxCodeChanged(string)
                        )
                    },
                    label = {
                        Text(text = stringResource(id = R.string.tax_code))
                    },
                    modifier = Modifier
                        .fillMaxWidth()
                        .testTag(TestingConstant.AUTHENTICATION_SCREEN_TAX_CODE_EDIT_TEXT)
                )

The maximum length is handled in the view model. If the user adds more characters than 16, the view model won't update the state and keep the old value.

Upvotes: 4

Views: 3888

Answers (2)

OtienoSamwel
OtienoSamwel

Reputation: 426

first of all, what am I doing wrong?

assertTextEquals() takes the value of Text and EditableText in your semantics node combines them and then does a check against the values you pass in. The order does not matter, just make sure to pass in the value of the Text as one of the arguments.

     val mNode = composeTestRule.onNodeWithText("Email")) 
     mNode.performTextInput("[email protected]")
     mNode.assertTextEquals("Email", "[email protected]")

Please note the text Email is the label for the textfield composable.

To get the semantic information about your nodes you can have

    @Test
    fun print_semantics_tree() {
        composeTestRule.onRoot(useUnmergedTree = true).printToLog(TAG)
    }

For the TAG you can use any string. After running the above test you can search the logcat with the specified TAG. You should see something like

    |-Node #3 at (l=155.0, t=105.0, r=925.0, b=259.0)px
                                                                                                        
    | Focused = 'false'
                                                                                                        
    | ImeAction = 'Default'
                                                                                                        
    | EditableText = '[email protected]'
                                                                                                        
    | TextSelectionRange = 'TextRange(0, 0)'
                                                                                                        
    | Text = '[Email]'
                                                                                                        
    | Actions = [RequestFocus, GetTextLayoutResult, SetText, SetSelection, 
                 OnClick, OnLongClick, PasteText]

Please note you can also obtain the semantics node object with an index operation rather than iterating through all the values.

   val value = fetchSemanticsNode().config[EditableText]

   assertEquals("[email protected]", value.toString())

Upvotes: 6

Mohammad Derakhshan
Mohammad Derakhshan

Reputation: 1562

Ok, still, the problem is open, but I achieved what I wanted another way. I used semantic nodes to get what is in edit text and compared it with what it should be:

    @Test
    fun checkMaxTaxCodeLength_16Character() {
        val taxCode = composeRule.onNodeWithTag(testTag = AUTHENTICATION_SCREEN_TAX_CODE_EDIT_TEXT)
        for (i in 'A'..'Z')
            taxCode.performTextInput(i.toString())
        for ((key,value) in taxCode.fetchSemanticsNode().config)
            if (key.name =="EditableText")
                assertEquals("ABCDEFGHIJKLMNOP",value.toString())
    }

Upvotes: 2

Related Questions