允许自定义 TextInput 包装器支持 UI 测试 `performTextInput`

问题描述 投票:0回答:1

我在 compose 的内置 TextField 上有这个包装器

MyInput
,它执行一系列 UI 操作,并为应用程序中的所有输入声明全局样式。

我将所有组件放入

ui
模块中,然后从不同的屏幕上使用它。

问题是当我尝试进行 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
的源代码,但我看不到它是在哪里声明的?

android android-jetpack-compose
1个回答
0
投票

为了使自定义 MyInput 可组合项支持 UI 测试所需的语义,您需要确保它正确提供文本输入所需的语义属性。您遇到的问题表明您的自定义组件未正确公开 PerformTextInput 函数工作所需的 SetText 操作。

以下是如何将所需的语义添加到自定义 MyInput 组件中:

1。确保 Modifier.semantics 设置正确: 确保您的自定义可组合项应用适当的语义修饰符。

2。公开 TextField 语义: 由于您的 MyInput 包装了 TextField,因此您需要确保 TextField 的语义不会被其他组件覆盖或阻止。

这是一个基本示例,说明如何构建 MyInput 以确保它公开所需的语义:

@Composable
fun MyInput(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    testTag: String = ""
) {
    Box(
        modifier = modifier
            .testTag(testTag)
            .semantics { // Ensure semantics are correctly set
                contentDescription = testTag
            }
    ) {
        TextField(
            value = value,
            onValueChange = onValueChange,
            modifier = Modifier.fillMaxWidth()
        )
    }
}

在您的测试中,您将使用:

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

关键部分是确保通过自定义 MyInput 组件保留并公开 TextField 的语义。 .semantics {} 块用于定义或扩展语义属性,并使用 Modifier.testTag(testTag) 确保测试框架可以找到该节点。

如果您需要更多自定义语义,或者 TextField 被包装在其他可能会掩盖其语义的组件中,您可能需要根据需要显式传递或设置这些语义。

调试语义

要调试节点上当前可用的语义,您可以在测试期间打印出节点的语义:

composeTestRule.onNodeWithTag("enter_email_field")
    .printToLog("Semantics")

这可以帮助您了解是否正确设置了必要的语义(如 SetText)以及它们是否可访问。

高级语义示例

如果您的组件更复杂并且涉及额外的层,您可能需要确保语义正确转发:

@Composable
fun MyInput(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    testTag: String = ""
) {
    Box(
        modifier = modifier
            .testTag(testTag)
            .semantics {  // Adding semantics directly
                text = AnnotatedString(value)
                setText = { newText ->
                    onValueChange(newText)
                    true
                }
            }
    ) {
        TextField(
            value = value,
            onValueChange = onValueChange,
            modifier = Modifier.fillMaxWidth().semantics(mergeDescendants = true) {}
        )
    }
}

在这个例子中,text和setText语义直接添加到包含TextField的Box中,这保证了TextField仍然可以正确交互。

通过正确管理和公开这些语义,您的自定义 MyInput 可组合项应该支持所需的测试操作。

© www.soinside.com 2019 - 2024. All rights reserved.