Разрешить пользовательской оболочке TextInput поддерживать тестирование пользовательского интерфейса «performTextInput»

У меня есть эта оболочка MyInput над встроенным TextField Compose, которая выполняет ряд операций пользовательского интерфейса и глобально объявляет стиль для всех моих входных данных в приложении.

Я помещаю все свои компоненты в модуль ui и затем использую их с разных экранов.

Проблема в том, что я пытаюсь провести тестирование пользовательского интерфейса и выполнить performTextInput("[email protected]") вот так:

composeTestRule.onNodeWithTag("enter_email_field")
                .assertIsDisplayed()
                .performTextInput("[email protected]")

и я получаю следующий результат:

java.lang.AssertionError: Failed to perform text input.
Failed to assert the following: (SetText is defined)
Semantics of the node:
Node #20 at (l=84.0, t=1500.0, r=1356.0, b=1699.0)px, Tag: 'enter_email_field'
Has 1 child, 10 siblings
Selector used: (TestTag = 'enter_email_field')

Возможно ли, чтобы мой заказ MyInput поддерживал эту семантику? Я пытался прочитать исходный код TextField, но не увидел, где это объявлено?

если я сам объявлю семантику для setText, меня спросят requestFocus, а затем insertTextAtCursor? Я бы хотел просто наследовать их от внутреннего BasicTextField.

3
0
112
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если ваша пользовательская оболочка TextInput имеет TextField в качестве дочернего элемента какого-либо другого составного объекта, вам следует сначала получить дочерний TextField, а затем выполнить ввод текста в него.

composeTestRule.onNodeWithTag("enter_email_field")
            .onChildren()
            .filterToOne(hasSetTextAction())
            .performTextInput("[email protected]")

Вы можете создать вспомогательную функцию, чтобы избежать повторения.

fun SemanticsNodeInteraction.editTextNode() = onChildren().filterToOne(hasSetTextAction())

Предыдущий ответ

Если вы хотите, чтобы ваше настраиваемое текстовое поле поддерживало performTextInput; убедитесь, что вы указали тестовый тег во внутреннем модификаторе TextField.

Это сработает

@Composable
fun MyTextField(
    modifier: Modifier,
    testTag: String,
) {
    var text by remember { mutableStateOf("Initial") }
    Box(modifier) {
        TextField(text, { text = it }, Modifier.testTag(testTag))
    }
}

Это не будет

@Composable
fun MyTextField(
    modifier: Modifier,
    testTag: String,
) {
    var text by remember { mutableStateOf("Initial") }
    Box(modifier.testTag(testTag)) {
        TextField(text, { text = it }, Modifier)
    }
}

Вероятно, это сработало бы, но теперь testTag стал более явным и загрязняет код даже больше, чем модификатор, разве нет более чистого способа?

M Rajoy 15.06.2024 20:04
testTag использовался в качестве параметра только для примера. Вы можете добавить второй параметр inputModifier (хотя это может выглядеть некрасиво). Можете ли вы предоставить код вашего пользовательского компонента TextInput для большей ясности?
Shreyash.K 16.06.2024 09:05

Я обновил ответ, который требует изменения тестов вместо исходного кода.

Shreyash.K 16.06.2024 10:11

Мне нравится ваш второй подход. Спасибо!

M Rajoy 16.06.2024 13:08

Другие вопросы по теме