Merge pull request #6765 from thundernest/add-textfields-to-design-system
Add textfields to design system
This commit is contained in:
commit
3f8a3ff0c9
15 changed files with 653 additions and 2 deletions
|
@ -15,6 +15,7 @@ import app.k9mail.ui.catalog.items.buttonItems
|
|||
import app.k9mail.ui.catalog.items.colorItems
|
||||
import app.k9mail.ui.catalog.items.imageItems
|
||||
import app.k9mail.ui.catalog.items.selectionControlItems
|
||||
import app.k9mail.ui.catalog.items.textFieldItems
|
||||
import app.k9mail.ui.catalog.items.themeHeaderItem
|
||||
import app.k9mail.ui.catalog.items.themeSelectorItems
|
||||
import app.k9mail.ui.catalog.items.typographyItems
|
||||
|
@ -48,6 +49,7 @@ fun CatalogContent(
|
|||
colorItems()
|
||||
buttonItems()
|
||||
selectionControlItems()
|
||||
textFieldItems()
|
||||
imageItems()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package app.k9mail.ui.catalog.items
|
||||
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.textfield.PasswordTextFieldOutlined
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.textfield.TextFieldOutlined
|
||||
|
||||
fun LazyGridScope.textFieldItems() {
|
||||
sectionHeaderItem(text = "Text fields")
|
||||
textFieldOutlinedItems()
|
||||
passwordTextFieldOutlinedItems()
|
||||
}
|
||||
|
||||
private fun LazyGridScope.textFieldOutlinedItems() {
|
||||
sectionSubtitleItem(text = "Outlined")
|
||||
item {
|
||||
WithRememberedInput(text = "Initial text") { input ->
|
||||
TextFieldOutlined(
|
||||
value = input.value,
|
||||
label = "Label",
|
||||
onValueChange = { input.value = it },
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedInput(text = "Input text with error") { input ->
|
||||
TextFieldOutlined(
|
||||
value = input.value,
|
||||
label = "Label",
|
||||
onValueChange = { input.value = it },
|
||||
isError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedInput(text = "Input text disabled") { input ->
|
||||
TextFieldOutlined(
|
||||
value = input.value,
|
||||
label = "Label",
|
||||
onValueChange = { input.value = it },
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyGridScope.passwordTextFieldOutlinedItems() {
|
||||
sectionSubtitleItem(text = "Password outlined")
|
||||
item {
|
||||
WithRememberedInput(text = "Input text") { input ->
|
||||
PasswordTextFieldOutlined(
|
||||
value = input.value,
|
||||
label = "Label",
|
||||
onValueChange = { input.value = it },
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedInput(text = "Input text with error") { input ->
|
||||
PasswordTextFieldOutlined(
|
||||
value = input.value,
|
||||
label = "Label",
|
||||
onValueChange = { input.value = it },
|
||||
isError = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
WithRememberedInput(text = "Input text disabled") { input ->
|
||||
PasswordTextFieldOutlined(
|
||||
value = input.value,
|
||||
label = "Label",
|
||||
onValueChange = { input.value = it },
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WithRememberedInput(
|
||||
text: String,
|
||||
content: @Composable (text: MutableState<String>) -> Unit,
|
||||
) {
|
||||
val inputText = remember { mutableStateOf(text) }
|
||||
content(inputText)
|
||||
}
|
|
@ -6,6 +6,13 @@ android {
|
|||
configureSharedComposeConfig(libs)
|
||||
}
|
||||
|
||||
androidComponents {
|
||||
beforeVariants(selector().withBuildType("release")) { variantBuilder ->
|
||||
variantBuilder.enableUnitTest = false
|
||||
variantBuilder.enableAndroidTest = false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
configureSharedComposeDependencies(libs)
|
||||
}
|
||||
|
|
|
@ -4,10 +4,13 @@ plugins {
|
|||
|
||||
android {
|
||||
namespace = "app.k9mail.core.ui.compose.designsystem"
|
||||
resourcePrefix = "core_ui_designsystem_"
|
||||
resourcePrefix = "designsystem_"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.core.ui.compose.theme)
|
||||
implementation(libs.androidx.compose.material)
|
||||
implementation(libs.androidx.compose.material.icons.extended)
|
||||
|
||||
testImplementation(projects.core.ui.compose.testing)
|
||||
}
|
||||
|
|
|
@ -31,3 +31,15 @@ internal fun CheckboxPreview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun CheckboxDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
Checkbox(
|
||||
checked = true,
|
||||
onCheckedChange = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material.icons.filled.VisibilityOff
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.R
|
||||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
import androidx.compose.material.OutlinedTextField as MaterialOutlinedTextField
|
||||
|
||||
@Composable
|
||||
fun PasswordTextFieldOutlined(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isError: Boolean = false,
|
||||
) {
|
||||
var passwordVisibilityState by rememberSaveable { mutableStateOf(false) }
|
||||
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = selectLabel(label),
|
||||
trailingIcon = selectTrailingIcon(
|
||||
isEnabled = enabled,
|
||||
isPasswordVisible = passwordVisibilityState,
|
||||
onClick = { passwordVisibilityState = !passwordVisibilityState },
|
||||
),
|
||||
isError = isError,
|
||||
visualTransformation = selectVisualTransformation(
|
||||
isEnabled = enabled,
|
||||
isPasswordVisible = passwordVisibilityState,
|
||||
),
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
|
||||
private fun selectLabel(label: String?): @Composable (() -> Unit)? {
|
||||
return if (label != null) {
|
||||
{
|
||||
Text(text = label)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectTrailingIcon(
|
||||
isEnabled: Boolean,
|
||||
isPasswordVisible: Boolean,
|
||||
onClick: () -> Unit,
|
||||
hasTrailingIcon: Boolean = true,
|
||||
): @Composable (() -> Unit)? {
|
||||
return if (hasTrailingIcon) {
|
||||
{
|
||||
val image = if (isShowPasswordAllowed(isEnabled, isPasswordVisible)) {
|
||||
Icons.Filled.Visibility
|
||||
} else {
|
||||
Icons.Filled.VisibilityOff
|
||||
}
|
||||
|
||||
val description = if (isShowPasswordAllowed(isEnabled, isPasswordVisible)) {
|
||||
stringResource(id = R.string.designsystem_atom_password_textfield_hide_password)
|
||||
} else {
|
||||
stringResource(id = R.string.designsystem_atom_password_textfield_show_password)
|
||||
}
|
||||
|
||||
IconButton(onClick = onClick) {
|
||||
Icon(imageVector = image, contentDescription = description)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectVisualTransformation(
|
||||
isEnabled: Boolean,
|
||||
isPasswordVisible: Boolean,
|
||||
): VisualTransformation {
|
||||
return if (isShowPasswordAllowed(isEnabled, isPasswordVisible)) {
|
||||
VisualTransformation.None
|
||||
} else {
|
||||
PasswordVisualTransformation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isShowPasswordAllowed(isEnabled: Boolean, isPasswordVisible: Boolean) = isEnabled && isPasswordVisible
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun PasswordTextFieldOutlinedPreview() {
|
||||
PreviewWithThemes {
|
||||
PasswordTextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun PasswordTextFieldOutlinedWithLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
PasswordTextFieldOutlined(
|
||||
value = "Input text",
|
||||
label = "Label",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun PasswordTextFieldOutlinedDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
PasswordTextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun PasswordTextFieldOutlinedErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
PasswordTextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isError = true,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
import androidx.compose.material.OutlinedTextField as MaterialOutlinedTextField
|
||||
|
||||
@Composable
|
||||
fun TextFieldOutlined(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
label: String? = null,
|
||||
isError: Boolean = false,
|
||||
) {
|
||||
MaterialOutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = selectLabel(label),
|
||||
isError = isError,
|
||||
)
|
||||
}
|
||||
|
||||
private fun selectLabel(label: String?): @Composable (() -> Unit)? {
|
||||
return if (label != null) {
|
||||
{
|
||||
Text(text = label)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun TextFieldOutlinedPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun TextFieldOutlinedWithLabelPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
label = "Label",
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun TextFieldOutlinedDisabledPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
internal fun TextFieldOutlinedErrorPreview() {
|
||||
PreviewWithThemes {
|
||||
TextFieldOutlined(
|
||||
value = "Input text",
|
||||
onValueChange = {},
|
||||
isError = true,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="designsystem_atom_password_textfield_hide_password">Hide password</string>
|
||||
<string name="designsystem_atom_password_textfield_show_password">Show password</string>
|
||||
</resources>
|
|
@ -0,0 +1,98 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteraction
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import app.k9mail.core.ui.compose.designsystem.R
|
||||
import app.k9mail.core.ui.compose.testing.ComposeTest
|
||||
import org.junit.Test
|
||||
|
||||
private const val PASSWORD = "Password input"
|
||||
|
||||
class PasswordTextFieldOutlinedKtTest : ComposeTest() {
|
||||
|
||||
@Test
|
||||
fun `should not display password by default`() = runComposeTest {
|
||||
setContent {
|
||||
PasswordTextFieldOutlined(
|
||||
value = PASSWORD,
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithText(PASSWORD).assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should display password when show password is clicked`() = runComposeTest {
|
||||
setContent {
|
||||
PasswordTextFieldOutlined(
|
||||
value = PASSWORD,
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
|
||||
onShowPasswordNode().performClick()
|
||||
|
||||
onNodeWithText(PASSWORD).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not display password when hide password is clicked`() = runComposeTest {
|
||||
setContent {
|
||||
PasswordTextFieldOutlined(
|
||||
value = PASSWORD,
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
onShowPasswordNode().performClick()
|
||||
|
||||
onHidePasswordNode().performClick()
|
||||
|
||||
onNodeWithText(PASSWORD).assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should display hide password icon when show password is clicked`() = runComposeTest {
|
||||
setContent {
|
||||
PasswordTextFieldOutlined(
|
||||
value = PASSWORD,
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
|
||||
onShowPasswordNode().performClick()
|
||||
|
||||
onHidePasswordNode().assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should display show password icon when hide password icon is clicked`() = runComposeTest {
|
||||
setContent {
|
||||
PasswordTextFieldOutlined(
|
||||
value = PASSWORD,
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
onShowPasswordNode().performClick()
|
||||
|
||||
onHidePasswordNode().performClick()
|
||||
|
||||
onShowPasswordNode().assertIsDisplayed()
|
||||
}
|
||||
|
||||
private fun SemanticsNodeInteractionsProvider.onShowPasswordNode(): SemanticsNodeInteraction {
|
||||
return onNodeWithContentDescription(
|
||||
getString(R.string.designsystem_atom_password_textfield_show_password),
|
||||
)
|
||||
}
|
||||
|
||||
private fun SemanticsNodeInteractionsProvider.onHidePasswordNode(): SemanticsNodeInteraction {
|
||||
return onNodeWithContentDescription(
|
||||
getString(R.string.designsystem_atom_password_textfield_hide_password),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.atom.textfield
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
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.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(
|
||||
val name: String,
|
||||
val content: @Composable (
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier,
|
||||
enabled: Boolean?,
|
||||
label: String?,
|
||||
) -> Unit,
|
||||
)
|
||||
|
||||
@RunWith(ParameterizedRobolectricTestRunner::class)
|
||||
class TextFieldKtTest(
|
||||
data: TextFieldTestData,
|
||||
) : ComposeTest() {
|
||||
|
||||
private val testSubjectName = data.name
|
||||
private val testSubject = data.content
|
||||
|
||||
@Test
|
||||
fun `should call onValueChange when value changes`() = runComposeTest {
|
||||
var value = VALUE
|
||||
setContent {
|
||||
testSubject(
|
||||
value = value,
|
||||
onValueChange = { value = it },
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = null,
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(testSubjectName).performClick()
|
||||
onNodeWithTag(testSubjectName).performTextInput(" + added text")
|
||||
|
||||
assertThat(value).isEqualTo("$VALUE + added text")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should be enabled by default`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = null,
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(testSubjectName).assertIsEnabled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should be disabled when enabled is false`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = false,
|
||||
label = null,
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithTag(testSubjectName).assertIsNotEnabled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should show label when label is not null`() = runComposeTest {
|
||||
setContent {
|
||||
testSubject(
|
||||
value = VALUE,
|
||||
onValueChange = {},
|
||||
modifier = Modifier.testTag(testSubjectName),
|
||||
enabled = null,
|
||||
label = LABEL,
|
||||
)
|
||||
}
|
||||
|
||||
onNodeWithText(LABEL).assertIsDisplayed()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@ParameterizedRobolectricTestRunner.Parameters(name = "{0}")
|
||||
fun data(): List<TextFieldTestData> = listOf(
|
||||
TextFieldTestData(
|
||||
name = "TextFieldOutlined",
|
||||
content = { value, onValueChange, modifier, enabled, label ->
|
||||
if (enabled != null) {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
)
|
||||
} else {
|
||||
TextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
TextFieldTestData(
|
||||
name = "PasswordTextFieldOutlined",
|
||||
content = { value, onValueChange, modifier, enabled, label ->
|
||||
if (enabled != null) {
|
||||
PasswordTextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
)
|
||||
} else {
|
||||
PasswordTextFieldOutlined(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
label = label,
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
3
core/ui/compose/testing/README.md
Normal file
3
core/ui/compose/testing/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
## Core - UI - Compose - Testing
|
||||
|
||||
Uses [`:core:ui:compose:theme`](../theme/README.md)
|
14
core/ui/compose/testing/build.gradle.kts
Normal file
14
core/ui/compose/testing/build.gradle.kts
Normal file
|
@ -0,0 +1,14 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.androidCompose)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.k9mail.core.ui.compose.testing"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.ui.compose.theme)
|
||||
implementation(libs.androidx.compose.material)
|
||||
|
||||
implementation(libs.bundles.shared.jvm.test.compose)
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package app.k9mail.core.ui.compose.testing
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import org.junit.Rule
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
open class ComposeTest {
|
||||
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
fun getString(@StringRes resourceId: Int): String = RuntimeEnvironment.getApplication().getString(resourceId)
|
||||
|
||||
fun runComposeTest(testContent: ComposeContentTestRule.() -> Unit): Unit = with(composeTestRule) {
|
||||
testContent()
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ androidxDrawerLayout = "1.1.1"
|
|||
androidxTransition = "1.4.1"
|
||||
androidxComposeCompiler = "1.4.1"
|
||||
androidxComposeBom = "2023.01.00"
|
||||
androidxComposeMaterial = "1.3.1"
|
||||
fastAdapter = "5.7.0"
|
||||
preferencesFix = "1.1.0"
|
||||
timber = "5.0.1"
|
||||
|
@ -80,7 +81,8 @@ androidx-compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-mani
|
|||
androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
|
||||
androidx-compose-activity = "androidx.activity:activity-compose:1.6.1"
|
||||
androidx-compose-lifecycle-viewmodel = "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
|
||||
androidx-compose-material = "androidx.compose.material:material:1.3.1"
|
||||
androidx-compose-material = { module = "androidx.compose.material:material", version.ref = "androidxComposeMaterial" }
|
||||
androidx-compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "androidxComposeMaterial" }
|
||||
androidx-test-core = "androidx.test:core:1.5.0"
|
||||
androidx-test-ext-junit-ktx = "androidx.test.ext:junit-ktx:1.1.5"
|
||||
androidx-test-espresso-core = "androidx.test.espresso:espresso-core:3.5.1"
|
||||
|
|
|
@ -49,6 +49,7 @@ include(
|
|||
":core:ui:compose:common",
|
||||
":core:ui:compose:designsystem",
|
||||
":core:ui:compose:theme",
|
||||
":core:ui:compose:testing",
|
||||
)
|
||||
|
||||
include(
|
||||
|
|
Loading…
Reference in a new issue