Add read-only to TextFieldOutlined atom

This commit is contained in:
Wolf-Martell Montwé 2023-05-23 17:14:10 +02:00
parent c5fb3211ca
commit 7f2f5e21f1
No known key found for this signature in database
GPG key ID: 6D45B21512ACBF72
7 changed files with 151 additions and 86 deletions

View file

@ -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,
)
}
}

View file

@ -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,
)
}
}

View file

@ -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,
)
}
}

View file

@ -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,
)
}
}

View file

@ -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(

View file

@ -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(

View file

@ -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,
)
}
},