У меня есть эта оболочка 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.
Если ваша пользовательская оболочка 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 использовался в качестве параметра только для примера. Вы можете добавить второй параметр inputModifier (хотя это может выглядеть некрасиво). Можете ли вы предоставить код вашего пользовательского компонента TextInput для большей ясности?
Я обновил ответ, который требует изменения тестов вместо исходного кода.
Мне нравится ваш второй подход. Спасибо!
Вероятно, это сработало бы, но теперь testTag стал более явным и загрязняет код даже больше, чем модификатор, разве нет более чистого способа?