Add read-only to TextFieldOutlined atom
This commit is contained in:
parent
c5fb3211ca
commit
7f2f5e21f1
7 changed files with 151 additions and 86 deletions
|
@ -30,7 +30,7 @@ private fun LazyGridScope.textFieldOutlinedItems() {
|
|||
value = state.value,
|
||||
label = "Label",
|
||||
onValueChange = { state.value = it },
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ private fun LazyGridScope.textFieldOutlinedItems() {
|
|||
value = state.value,
|
||||
label = "Label",
|
||||
onValueChange = { state.value = it },
|
||||
enabled = false,
|
||||
hasError = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ private fun LazyGridScope.textFieldOutlinedItems() {
|
|||
label = "Label",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ private fun LazyGridScope.passwordTextFieldOutlinedItems() {
|
|||
value = state.value,
|
||||
label = "Password with error",
|
||||
onValueChange = { state.value = it },
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ private fun LazyGridScope.passwordTextFieldOutlinedItems() {
|
|||
value = state.value,
|
||||
label = "Password disabled",
|
||||
onValueChange = { state.value = it },
|
||||
enabled = false,
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ private fun LazyGridScope.passwordTextFieldOutlinedItems() {
|
|||
label = "Password required with error",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ private fun LazyGridScope.emailTextFieldOutlinedItems() {
|
|||
value = state.value,
|
||||
label = "Email address with error",
|
||||
onValueChange = { state.value = it },
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ private fun LazyGridScope.emailTextFieldOutlinedItems() {
|
|||
value = state.value,
|
||||
label = "Email address disabled",
|
||||
onValueChange = { state.value = it },
|
||||
enabled = false,
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ private fun LazyGridScope.emailTextFieldOutlinedItems() {
|
|||
label = "Email address required with error",
|
||||
onValueChange = { state.value = it },
|
||||
isRequired = true,
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,23 +6,26 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
import androidx.compose.material.OutlinedTextField as MaterialOutlinedTextField
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
fun TextFieldOutlined(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isEnabled: Boolean = true,
|
||||
isReadOnly: Boolean = false,
|
||||
isRequired: Boolean = false,
|
||||
isError: Boolean = false,
|
||||
hasError: Boolean = false,
|
||||
) {
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
enabled = isEnabled,
|
||||
label = selectLabel(label, isRequired),
|
||||
isError = isError,
|
||||
readOnly = isReadOnly,
|
||||
isError = hasError,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -56,7 +59,7 @@ internal fun TextFieldOutlinedDisabledPreview() {
|
|||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
enabled = false,
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +71,7 @@ internal fun TextFieldOutlinedErrorPreview() {
|
|||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,23 +8,26 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
import androidx.compose.material.OutlinedTextField as MaterialOutlinedTextField
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
fun TextFieldOutlinedEmailAddress(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isEnabled: Boolean = true,
|
||||
isReadOnly: Boolean = false,
|
||||
isRequired: Boolean = false,
|
||||
isError: Boolean = false,
|
||||
hasError: Boolean = false,
|
||||
) {
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
enabled = isEnabled,
|
||||
label = selectLabel(label, isRequired),
|
||||
isError = isError,
|
||||
readOnly = isReadOnly,
|
||||
isError = hasError,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Email,
|
||||
),
|
||||
|
@ -62,7 +65,7 @@ internal fun TextFieldOutlinedEmailDisabledPreview() {
|
|||
TextFieldOutlinedEmailAddress(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
enabled = false,
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +77,7 @@ internal fun TextFieldOutlinedEmailErrorPreview() {
|
|||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,17 @@ import app.k9mail.core.ui.compose.theme.Icons
|
|||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
import androidx.compose.material.OutlinedTextField as MaterialOutlinedTextField
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
fun TextFieldOutlinedPassword(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isEnabled: Boolean = true,
|
||||
isReadOnly: Boolean = false,
|
||||
isRequired: Boolean = false,
|
||||
isError: Boolean = false,
|
||||
hasError: Boolean = false,
|
||||
) {
|
||||
var passwordVisibilityState by rememberSaveable { mutableStateOf(false) }
|
||||
|
||||
|
@ -35,16 +37,17 @@ fun TextFieldOutlinedPassword(
|
|||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
enabled = isEnabled,
|
||||
label = selectLabel(label, isRequired),
|
||||
trailingIcon = selectTrailingIcon(
|
||||
isEnabled = enabled,
|
||||
isEnabled = isEnabled,
|
||||
isPasswordVisible = passwordVisibilityState,
|
||||
onClick = { passwordVisibilityState = !passwordVisibilityState },
|
||||
),
|
||||
isError = isError,
|
||||
readOnly = isReadOnly,
|
||||
isError = hasError,
|
||||
visualTransformation = selectVisualTransformation(
|
||||
isEnabled = enabled,
|
||||
isEnabled = isEnabled,
|
||||
isPasswordVisible = passwordVisibilityState,
|
||||
),
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
|
||||
|
@ -124,7 +127,7 @@ internal fun TextFieldOutlinedPasswordDisabledPreview() {
|
|||
TextFieldOutlinedPassword(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
enabled = false,
|
||||
isEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +139,7 @@ internal fun TextFieldOutlinedPasswordErrorPreview() {
|
|||
TextFieldOutlinedPassword(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isError = true,
|
||||
hasError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ fun EmailAddressInput(
|
|||
value = emailAddress,
|
||||
onValueChange = onEmailAddressChange,
|
||||
label = stringResource(id = R.string.designsystem_molecule_email_address_input_label),
|
||||
isError = errorMessage != null,
|
||||
hasError = errorMessage != null,
|
||||
)
|
||||
AnimatedVisibility(visible = errorMessage != null) {
|
||||
TextCaption(
|
||||
|
|
|
@ -34,7 +34,7 @@ fun PasswordInput(
|
|||
value = password,
|
||||
onValueChange = onPasswordChange,
|
||||
label = stringResource(id = R.string.designsystem_molecule_password_input_label),
|
||||
isError = errorMessage != null,
|
||||
hasError = errorMessage != null,
|
||||
)
|
||||
AnimatedVisibility(visible = errorMessage != null) {
|
||||
TextCaption(
|
||||
|
|
|
@ -11,65 +11,78 @@ import androidx.compose.ui.test.onNodeWithText
|
|||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import assertk.assertFailure
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.ParameterizedRobolectricTestRunner
|
||||
|
||||
private const val VALUE = "Input text"
|
||||
private const val LABEL = "Label"
|
||||
|
||||
data class TextFieldTestData(
|
||||
data class TextFieldConfig(
|
||||
val label: String?,
|
||||
val isEnabled: Boolean?,
|
||||
val isReadOnly: Boolean,
|
||||
val isRequired: Boolean,
|
||||
)
|
||||
|
||||
data class TextFieldTestData<INPUT, VALUE>(
|
||||
val name: String,
|
||||
val input: INPUT,
|
||||
val content: @Composable (
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
value: VALUE,
|
||||
onValueChange: (VALUE) -> Unit,
|
||||
modifier: Modifier,
|
||||
enabled: Boolean?,
|
||||
label: String?,
|
||||
isRequired: Boolean,
|
||||
textFieldConfig: TextFieldConfig,
|
||||
) -> Unit,
|
||||
)
|
||||
|
||||
@RunWith(ParameterizedRobolectricTestRunner::class)
|
||||
class TextFieldKtTest(
|
||||
data: TextFieldTestData,
|
||||
data: TextFieldTestData<Any, Any>,
|
||||
) : ComposeTest() {
|
||||
|
||||
private val testSubjectName = data.name
|
||||
private val testSubject = data.content
|
||||
private val testInput = data.input
|
||||
|
||||
@Test
|
||||
fun `should call onValueChange when value changes`() = runComposeTest {
|
||||
var value = VALUE
|
||||
var value = testInput
|
||||
setContent {
|
||||
testSubject(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = null,
|
||||
isRequired = false,
|
||||
textFieldConfig = TextFieldConfig(
|
||||
label = null,
|
||||
isEnabled = null,
|
||||
isReadOnly = false,
|
||||
isRequired = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(testSubjectName).performClick()
|
||||
onNodeWithTag(testSubjectName).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("$VALUE + added text")
|
||||
assertThat(value).isEqualTo("$testInput + added text")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should be enabled by default`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
value = testInput,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = null,
|
||||
isRequired = false,
|
||||
textFieldConfig = TextFieldConfig(
|
||||
label = null,
|
||||
isEnabled = null,
|
||||
isReadOnly = false,
|
||||
isRequired = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -80,12 +93,15 @@ class TextFieldKtTest(
|
|||
fun `should be disabled when enabled is false`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
value = testInput,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = false,
|
||||
label = null,
|
||||
isRequired = false,
|
||||
textFieldConfig = TextFieldConfig(
|
||||
label = null,
|
||||
isEnabled = false,
|
||||
isReadOnly = false,
|
||||
isRequired = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -96,12 +112,15 @@ class TextFieldKtTest(
|
|||
fun `should show label when label is not null`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
value = testInput,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = LABEL,
|
||||
isRequired = false,
|
||||
textFieldConfig = TextFieldConfig(
|
||||
label = LABEL,
|
||||
isEnabled = null,
|
||||
isReadOnly = false,
|
||||
isRequired = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -112,12 +131,15 @@ class TextFieldKtTest(
|
|||
fun `should show asterisk when isRequired is true`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
value = testInput,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = LABEL,
|
||||
isRequired = true,
|
||||
textFieldConfig = TextFieldConfig(
|
||||
label = LABEL,
|
||||
isEnabled = null,
|
||||
isReadOnly = false,
|
||||
isRequired = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -128,88 +150,122 @@ class TextFieldKtTest(
|
|||
fun `should not show asterisk when isRequired is false`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
value = testInput,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = LABEL,
|
||||
isRequired = false,
|
||||
textFieldConfig = TextFieldConfig(
|
||||
label = LABEL,
|
||||
isEnabled = null,
|
||||
isReadOnly = false,
|
||||
isRequired = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithText("$LABEL*").assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not allow editing when isReadOnly is true`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = testInput,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
textFieldConfig = TextFieldConfig(
|
||||
label = LABEL,
|
||||
isEnabled = null,
|
||||
isReadOnly = true,
|
||||
isRequired = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(testSubjectName).performClick()
|
||||
assertFailure {
|
||||
onNodeWithText(testSubjectName).performTextInput(" + added text")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@ParameterizedRobolectricTestRunner.Parameters(name = "{0}")
|
||||
@Suppress("LongMethod")
|
||||
fun data(): List<TextFieldTestData> = listOf(
|
||||
fun data(): List<TextFieldTestData<*, *>> = listOf(
|
||||
TextFieldTestData(
|
||||
name = "TextFieldOutlined",
|
||||
content = { value, onValueChange, modifier, enabled, label, isRequired ->
|
||||
if (enabled != null) {
|
||||
input = "value",
|
||||
content = { value, onValueChange: (String) -> Unit, modifier, config ->
|
||||
if (config.isEnabled != null) {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
label = config.label,
|
||||
isEnabled = config.isEnabled,
|
||||
isReadOnly = config.isReadOnly,
|
||||
isRequired = config.isRequired,
|
||||
)
|
||||
} else {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
label = config.label,
|
||||
isRequired = config.isRequired,
|
||||
isReadOnly = config.isReadOnly,
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
TextFieldTestData(
|
||||
name = "TextFieldOutlinedPassword",
|
||||
content = { value, onValueChange, modifier, enabled, label, isRequired ->
|
||||
if (enabled != null) {
|
||||
input = "value",
|
||||
content = { value, onValueChange: (String) -> Unit, modifier, config ->
|
||||
if (config.isEnabled != null) {
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
label = config.label,
|
||||
isEnabled = config.isEnabled,
|
||||
isReadOnly = config.isReadOnly,
|
||||
isRequired = config.isRequired,
|
||||
)
|
||||
} else {
|
||||
TextFieldOutlinedPassword(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
label = config.label,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
isRequired = config.isRequired,
|
||||
isReadOnly = config.isReadOnly,
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
TextFieldTestData(
|
||||
name = "TextFieldOutlinedEmail",
|
||||
content = { value, onValueChange, modifier, enabled, label, isRequired ->
|
||||
if (enabled != null) {
|
||||
input = "value",
|
||||
content = { value, onValueChange: (String) -> Unit, modifier, config ->
|
||||
if (config.isEnabled != null) {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
label = config.label,
|
||||
isEnabled = config.isEnabled,
|
||||
isReadOnly = config.isReadOnly,
|
||||
isRequired = config.isRequired,
|
||||
)
|
||||
} else {
|
||||
TextFieldOutlinedEmailAddress(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
isRequired = isRequired,
|
||||
label = config.label,
|
||||
isRequired = config.isRequired,
|
||||
isReadOnly = config.isReadOnly,
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue