Skip to content

Commit

Permalink
ANDROID-15138 Search Input in compose (#380)
Browse files Browse the repository at this point in the history
* ANDROID-15138 Search Input in compose

* ANDROID-15138 Clear search input button

* ANDROID-15138 Reorder composable params

* ANDROID-15138 screenhot tests

* ANDROID-15138 add disabled state catalog sample and test

* ANDROID-15138 fix compilation

* ANDROID-15138 (test) try with hardcoded colors because test doesn't have xml theme

* Updated screenshots baseline

* ANDROID-15138 Fix click on clear input test

* ANDROID-15138 Add helper text

* Updated screenshots baseline

---------

Co-authored-by: yamal-alm <[email protected]>
  • Loading branch information
yamal-alm and yamal-alm authored Sep 10, 2024
1 parent 7ff87d7 commit 6ec1d54
Show file tree
Hide file tree
Showing 15 changed files with 204 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import com.telefonica.mistica.compose.input.LimitCharacters
import com.telefonica.mistica.compose.input.NumberInput
import com.telefonica.mistica.compose.input.PasswordInput
import com.telefonica.mistica.compose.input.PhoneInput
import com.telefonica.mistica.compose.input.SearchInput
import com.telefonica.mistica.compose.input.TextAreaInput
import com.telefonica.mistica.compose.input.TextInput
import com.telefonica.mistica.compose.input.TextLink
Expand Down Expand Up @@ -81,6 +82,9 @@ fun Inputs() {
DropDownSample()
Title("Disable Dropdown")
DropDownSample(enabled = false)
Title("Search Input")
SearchInputSample(enabled = true)
SearchInputSample(enabled = false)
Title("Inverse inputs")
Column(
modifier = Modifier
Expand Down Expand Up @@ -444,4 +448,25 @@ private fun DropDownSample(enabled: Boolean = true) {
},
enabled = enabled
)
}

@Composable
private fun SearchInputSample(enabled: Boolean) {
var text by remember {
mutableStateOf("")
}

SearchInput(
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp, start = 16.dp, end = 16.dp)
,
value = text,
onValueChange = {
text = it
},
label = "Search Something",
helperText = "Some helper text",
enabled = enabled,
)
}
Binary file added library/screenshots/disabled_SearchInput.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added library/screenshots/empty_SearchInput.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added library/screenshots/non_empty_SearchInput.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.telefonica.mistica.compose.input

import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.VisualTransformation
import com.telefonica.mistica.R
import com.telefonica.mistica.compose.theme.MisticaTheme

@Composable
fun SearchInput(
value: String,
onValueChange: (String) -> Unit,
label: String?,
modifier: Modifier = Modifier,
helperText: String? = null,
isError: Boolean = false,
errorText: String? = null,
isInverse: Boolean = false,
enabled: Boolean = true,
readOnly: Boolean = false,
onClick: (() -> Unit)? = null,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
) {
TextInputImpl(
modifier = modifier,
value = value,
onValueChange = onValueChange,
label = label,
helperText = helperText,
isError = isError,
errorText = errorText,
isInverse = isInverse,
enabled = enabled,
readOnly = readOnly,
onClick = onClick,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions.toFoundationKeyboardOptions(
keyboardType = KeyboardType.Text
),
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_search_regular),
tint = MisticaTheme.colors.neutralHigh,
contentDescription = null
)
},
trailingIcon = {
IconButton(
modifier = Modifier.testTag(TextInputTestTags.CLEAR_SEARCH_BUTTON),
onClick = {
onValueChange("")
}
) {
Icon(
painter = painterResource(id = R.drawable.ic_close_regular),
tint = MisticaTheme.colors.neutralHigh,
contentDescription = stringResource(id = R.string.clear_search_content_description),
)
}
}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ internal fun TextInputImpl(
visualTransformation: VisualTransformation,
keyboardOptions: FoundationKeyboardOptions,
underlineEnd: @Composable (() -> Unit)? = null,
leadingIcon: @Composable (() -> Unit)? = null,
) {
Column(
modifier = modifier
Expand All @@ -52,6 +53,7 @@ internal fun TextInputImpl(
onValueChange = onValueChange,
label = label,
isError = isError,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
enabled = enabled,
readOnly = readOnly,
Expand Down Expand Up @@ -84,6 +86,7 @@ private fun TextBox(
onValueChange: (String) -> Unit,
label: String?,
isError: Boolean,
leadingIcon: @Composable (() -> Unit)?,
trailingIcon: @Composable (() -> Unit)?,
enabled: Boolean,
readOnly: Boolean,
Expand Down Expand Up @@ -129,6 +132,7 @@ private fun TextBox(
interactionSource = interactionSource,
keyboardOptions = keyboardOptions,
isError = isError,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
shape = RoundedCornerShape(MisticaTheme.radius.inputBorderRadius),
colors = TextFieldDefaults.textFieldColors(
Expand Down Expand Up @@ -188,6 +192,7 @@ fun PreviewTextInput() {
helperText = "helperText",
isError = false,
errorText = "",
leadingIcon = { },
trailingIcon = { },
isInverse = false,
enabled = true,
Expand All @@ -208,6 +213,7 @@ fun PreviewEmptyTextInput() {
helperText = "helperText",
isError = false,
errorText = "",
leadingIcon = { },
trailingIcon = { },
isInverse = false,
enabled = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package com.telefonica.mistica.compose.input
object TextInputTestTags {
const val TEXT_INPUT = "text_input"
const val PASSWORD_VISIBILITY_TOGGLE = "password_visibility_toggle"
const val CLEAR_SEARCH_BUTTON = "clear_search_button"
}
9 changes: 9 additions & 0 deletions library/src/main/res/drawable/ic_close_regular.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16.841,17.853a0.722,0.722 0,0 0,0.948 -1.086L13.022,12l4.766,-4.767 0.065,-0.074a0.722,0.722 0,0 0,-1.086 -0.947L12,10.978 7.233,6.211l-0.074,-0.064a0.722,0.722 0,0 0,-0.947 1.086L10.979,12 6.21,16.767l-0.064,0.074a0.722,0.722 0,0 0,1.086 0.947L12,13.022l4.767,4.767z"
android:fillColor="#000000"/>
</vector>
9 changes: 9 additions & 0 deletions library/src/main/res/drawable/ic_search_regular.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M10.018,17.83C5.684,17.83 2.172,14.318 2.172,9.984C2.172,7.903 2.998,5.909 4.469,4.435C7.584,1.421 12.55,1.502 15.564,4.615C18.379,7.521 18.505,12.06 15.941,15.112L21.645,20.816C21.864,21.035 21.864,21.39 21.645,21.609C21.536,21.715 21.396,21.774 21.247,21.774C21.099,21.774 20.956,21.715 20.853,21.609L15.156,15.912C13.737,17.149 11.912,17.835 10.018,17.83ZM10.018,3.259C6.304,3.259 3.292,6.27 3.292,9.984C3.292,11.769 4.001,13.477 5.262,14.741C7.897,17.357 12.158,17.34 14.774,14.704C17.376,12.082 17.376,7.853 14.774,5.231C13.514,3.962 11.802,3.253 10.018,3.259Z"
android:fillColor="#000000"/>
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<string name="close_button_content_description" comment="Content description for image views that act as buttons for dismissing views" tools:ignore="Typos">Fenster schließen</string>
<string name="badge_notification_description" comment="Content description for non numeric badge">Neue Inhalte</string>
<string name="toggle_action_click" comment="Toggle announcement information about perform action over the toggle">Wechseln</string>
<string name="clear_search_content_description">Suche löschen</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<string name="close_button_content_description" comment="Content description for image views that act as buttons for dismissing views">Close window</string>
<string name="badge_notification_description" comment="Content description for non numeric badge">New content</string>
<string name="toggle_action_click" comment="Toggle announcement information about perform action over the toggle">toggle</string>
<string name="clear_search_content_description">Clear search</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<string name="close_button_content_description" comment="Content description for image views that act as buttons for dismissing views">Cerrar ventana</string>
<string name="badge_notification_description" comment="Content description for non numeric badge">Contenido nuevo</string>
<string name="toggle_action_click" comment="Toggle announcement information about perform action over the toggle">alternar</string>
<string name="clear_search_content_description">Borrar búsqueda</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<string name="close_button_content_description" comment="Content description for image views that act as buttons for dismissing views">Fechar janela</string>
<string name="badge_notification_description" comment="Content description for non numeric badge">Novos conteúdos</string>
<string name="toggle_action_click" comment="Toggle announcement information about perform action over the toggle">alternar</string>
<string name="clear_search_content_description">Apagar pesquisa</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<string name="close_button_content_description" comment="Content description for image views that act as buttons for dismissing views">Cerrar ventana</string>
<string name="badge_notification_description" comment="Content description for non numeric badge">Contenido nuevo</string>
<string name="toggle_action_click" comment="Toggle announcement information about perform action over the toggle">alternar</string>
<string name="clear_search_content_description">Borrar búsqueda</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.telefonica.mistica.compose.input

import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import com.telefonica.mistica.compose.theme.MisticaTheme
import com.telefonica.mistica.compose.theme.brand.MovistarBrand
import com.telefonica.mistica.testutils.ScreenshotsTest
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class SearchInputTest : ScreenshotsTest() {

private val onValueChangeMock: (String) -> Unit = mock()

@get:Rule
val composeTestRule = createComposeRule()

@Test
fun `empty SearchInput`() {
givenSomeSearchInput(value = "")

thenScreenshotIsOk()
}

@Test
fun `non empty SearchInput`() {
givenSomeSearchInput(value = "Something")

thenScreenshotIsOk()
}

@Test
fun `disabled SearchInput`() {
givenSomeSearchInput(value = "", enabled = false)

thenScreenshotIsOk()
}

@Test
fun `SearchInput is cleared when clicking on clear search button`() {
givenSomeSearchInput(value = "Something")

whenClickingOnClearSearch()

thenValueIsNowEmptyString()
}

private fun givenSomeSearchInput(value: String, enabled: Boolean = true) {
composeTestRule.setContent {
MisticaTheme(brand = MovistarBrand) {
SearchInput(
value = value,
onValueChange = onValueChangeMock,
label = "Search something",
helperText = "Helper text",
enabled = enabled
)
}
}
}

private fun whenClickingOnClearSearch() {
composeTestRule.onNodeWithTag(TextInputTestTags.CLEAR_SEARCH_BUTTON).performClick()
}

private fun thenScreenshotIsOk() {
compareScreenshot(composeTestRule.onRoot())
}

private fun thenValueIsNowEmptyString() {
verify(onValueChangeMock).invoke("")
}
}

0 comments on commit 6ec1d54

Please sign in to comment.