Skip to content
This repository was archived by the owner on Jul 15, 2023. It is now read-only.

Commit adf4c75

Browse files
Merge branch 'feature/ui_tests_snackbar_analytics' into 'develop'
Feature/ui tests snackbar analytics See merge request 19111/androidodoo!14
2 parents bbb745c + b3e9c61 commit adf4c75

File tree

19 files changed

+431
-78
lines changed

19 files changed

+431
-78
lines changed

build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ plugins {
66
id("io.gitlab.arturbosch.detekt") version Dependencies.Plugins.DETEKT_VERSION
77
}
88

9+
buildscript {
10+
dependencies {
11+
Dependencies.Firebase.ALL_GRADLE_PLUGINS.forEach {
12+
classpath(it)
13+
}
14+
}
15+
}
16+
917
tasks {
1018
val detektAll by registering(io.gitlab.arturbosch.detekt.Detekt::class) {
1119
parallel = true

buildSrc/src/main/kotlin/consts/Dependencies.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ object Dependencies {
8686
val ALL_RXJAVA_DEPS = listOf(RX_JAVA)
8787
}
8888

89+
object UiTest {
90+
91+
// add to build.gradle with androidTestImplementation()
92+
const val UI_TEST = "androidx.compose.ui:ui-test-junit4:$COMPOSE_VERSION"
93+
94+
// add to build.gradle with debugImplementation
95+
const val UI_TEST_DEBUG = "androidx.compose.ui:ui-test-manifest:$COMPOSE_VERSION"
96+
}
97+
8998
val ALL_DEPS =
9099
Core.ALL_CORE_DEPS + Lifecycle.ALL_LIFECYCLE_DEPS + Foundation.ALL_FOUNDATION_DEPS +
91100
RxJava.ALL_RXJAVA_DEPS + Navigation.ALL_NAVIGATION_DEPS
@@ -148,6 +157,24 @@ object Dependencies {
148157
val ALL_DEPS = listOf(CONSTRAINT_LAYOUT, CORE)
149158
}
150159

160+
object Firebase {
161+
private const val GOOGLE_SERVICES_VERSION = "4.3.14"
162+
private const val BOM_VERSION = "31.1.0"
163+
private const val CRASHLYTICS_GRADLE_VERSION = "2.9.2"
164+
165+
const val GOOGLE_SERVICES_GRADLE_PLUGIN = "com.google.gms:google-services:$GOOGLE_SERVICES_VERSION"
166+
const val FIREBASE_CRASHLYTICS_GRADLE_PLUGIN =
167+
"com.google.firebase:firebase-crashlytics-gradle:$CRASHLYTICS_GRADLE_VERSION"
168+
169+
const val FIREBASE_BOM = "com.google.firebase:firebase-bom:$BOM_VERSION"
170+
const val FIREBASE_ANALYTICS = "com.google.firebase:firebase-analytics-ktx"
171+
const val FIREBASE_CRASHLYTICS = "com.google.firebase:firebase-crashlytics-ktx"
172+
173+
val ALL_GRADLE_PLUGINS = listOf(GOOGLE_SERVICES_GRADLE_PLUGIN, FIREBASE_CRASHLYTICS_GRADLE_PLUGIN)
174+
175+
val ALL_DEPS = listOf(FIREBASE_ANALYTICS, FIREBASE_CRASHLYTICS)
176+
}
177+
151178
object Plugins {
152179
const val DETEKT_VERSION = "1.22.0-RC1"
153180

buildSrc/src/main/kotlin/conventions/module/conventions.module-app.gradle.kts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import org.gradle.kotlin.dsl.dependencies
22
import org.gradle.kotlin.dsl.kotlin
33

44
/**
5-
* Конвеция для app модулей, которая содержит [conventions.base-api] и
5+
* Конвеция для app модулей, которая содержит [conventions.base-app] и
66
* добавляет необходимые зависимости
77
*
88
* @author Ворожцов Михаил
@@ -23,6 +23,10 @@ dependencies {
2323
implementation(Dependencies.Dagger.ANDROID)
2424
Dependencies.Dagger.KAPT_DEPS.forEach { kapt(it) }
2525

26+
// Firebase
27+
Dependencies.Firebase.ALL_DEPS.forEach { implementation(it) }
28+
implementation(platform(Dependencies.Firebase.FIREBASE_BOM))
29+
2630
// Logger
2731
implementation(Dependencies.Logger.TIMBER)
2832

buildSrc/src/main/kotlin/conventions/module_advanced/app/conventions.module-compose-app.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies {
2323
// Android Core
2424
Dependencies.AndroidCore.ALL_DEPS.forEach { implementation(it) }
2525

26-
// // Compose
26+
// Compose
2727
Dependencies.Compose.ALL_DEPS.forEach { implementation(it) }
2828
Dependencies.Compose.Core.ALL_CORE_DEBUG_DEPS.forEach { debugImplementation(it) }
2929

buildSrc/src/main/kotlin/conventions/module_advanced/impl/conventions.module-compose-impl.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ android {
1313
compose = true
1414
}
1515

16+
defaultConfig {
17+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18+
}
19+
1620
composeOptions {
1721
kotlinCompilerExtensionVersion = CompileVersions.COMPOSE_COMPILE_VERSION
1822
}
@@ -27,6 +31,10 @@ dependencies {
2731
Dependencies.Compose.ALL_DEPS.forEach { implementation(it) }
2832
Dependencies.Compose.Core.ALL_CORE_DEBUG_DEPS.forEach { debugImplementation(it) }
2933

34+
// Tests
35+
androidTestImplementation(Dependencies.Compose.UiTest.UI_TEST)
36+
debugImplementation(Dependencies.Compose.UiTest.UI_TEST_DEBUG)
37+
3038
// UI
3139
Dependencies.UI.ALL_DEPS.forEach { implementation(it) }
3240

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package odoo.miem.android.common.uiKitComponents
2+
3+
import androidx.compose.runtime.getValue
4+
import androidx.compose.runtime.mutableStateOf
5+
import androidx.compose.runtime.saveable.rememberSaveable
6+
import androidx.compose.runtime.setValue
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.res.stringResource
9+
import androidx.compose.ui.semantics.contentDescription
10+
import androidx.compose.ui.semantics.semantics
11+
import androidx.compose.ui.test.assert
12+
import androidx.compose.ui.test.hasText
13+
import androidx.compose.ui.test.junit4.createComposeRule
14+
import androidx.compose.ui.test.onNodeWithContentDescription
15+
import androidx.compose.ui.test.onNodeWithText
16+
import androidx.compose.ui.test.performClick
17+
import androidx.compose.ui.test.performTextInput
18+
import androidx.compose.ui.text.input.TextFieldValue
19+
import androidx.test.platform.app.InstrumentationRegistry
20+
import odoo.miem.android.common.uiKitComponents.textfields.LoginTextField
21+
import odoo.miem.android.core.uiKitTheme.OdooMiemAndroidTheme
22+
import org.junit.Rule
23+
import org.junit.Test
24+
25+
/**
26+
* [UiKitComponentsTest] - UI tests for UI components from odoo.miem.android.common.uiKitComponents package
27+
*
28+
* Contains:
29+
* [] - test for [LoginTextField]
30+
*
31+
* @author Egor Danilov
32+
*/
33+
class UiKitComponentsTest {
34+
private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
35+
36+
@get:Rule
37+
val composeTestRule = createComposeRule()
38+
39+
@Test
40+
fun testInputAndClearLoginTextField() {
41+
val textFieldLabel = context.getString(R.string.test_text_field_desc)
42+
val trailingIconDesc = context.getString(R.string.text_field_trailing_icon_desc)
43+
val testInput = context.getString(R.string.test_input)
44+
45+
// Preparation
46+
composeTestRule.setContent {
47+
var textFieldInput by rememberSaveable(stateSaver = TextFieldValue.Saver) {
48+
mutableStateOf(TextFieldValue())
49+
}
50+
51+
OdooMiemAndroidTheme {
52+
LoginTextField(
53+
value = textFieldInput,
54+
labelResource = R.string.test_text_field_desc,
55+
onValueChange = { textFieldInput = it },
56+
)
57+
}
58+
}
59+
val textFieldNode = composeTestRule.onNodeWithText(textFieldLabel)
60+
val trailingIconNode = composeTestRule.onNodeWithContentDescription(trailingIconDesc)
61+
62+
// Asserting
63+
64+
// Checking if all ui elements are displayed
65+
textFieldNode.assertExists()
66+
trailingIconNode.assertDoesNotExist()
67+
textFieldNode.assert(hasText(""))
68+
69+
textFieldNode.performTextInput(testInput)
70+
textFieldNode.assert(hasText(testInput))
71+
72+
// Cleaning
73+
trailingIconNode.assertExists()
74+
trailingIconNode.performClick()
75+
trailingIconNode.assertDoesNotExist()
76+
textFieldNode.assert(hasText(""))
77+
}
78+
}

common/uiKitComponents/src/main/kotlin/odoo/miem/android/common/uiKitComponents/buttons/TextButton.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ fun TextButton(
4141
colors = colors,
4242
modifier = modifier
4343
) {
44-
// I know, its stupid but I found some kind of bug
45-
// If set end padding to Image and remove start padding from Text, icon become very small
4644
iconResource?.let {
4745
Icon(
4846
painter = painterResource(iconResource),
49-
contentDescription = null,
47+
contentDescription = stringResource(
48+
odoo.miem.android.common.uiKitComponents.R.string.button_icon_desc
49+
),
5050
modifier = Modifier.size(buttonIconSize)
5151
)
5252
}

common/uiKitComponents/src/main/kotlin/odoo/miem/android/common/uiKitComponents/textfields/LoginTextField.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import androidx.compose.material3.OutlinedTextField
1818
import androidx.compose.material3.Text
1919
import androidx.compose.material3.TextFieldDefaults
2020
import androidx.compose.runtime.Composable
21+
import androidx.compose.runtime.getValue
22+
import androidx.compose.runtime.setValue
2123
import androidx.compose.ui.Modifier
2224
import androidx.compose.ui.platform.LocalFocusManager
2325
import androidx.compose.ui.res.painterResource
@@ -40,11 +42,12 @@ import odoo.miem.android.core.uiKitTheme.odooPrimaryGray
4042
@Composable
4143
fun LoginTextField(
4244
value: TextFieldValue,
45+
onValueChange: (TextFieldValue) -> Unit = {},
4346
@StringRes labelResource: Int,
44-
onValueChange: (TextFieldValue) -> Unit,
4547
visualTransformation: VisualTransformation = VisualTransformation.None,
4648
keyboardType: KeyboardType = KeyboardType.Text,
47-
isError: Boolean = false,
49+
imeAction: ImeAction = ImeAction.Done,
50+
isError: Boolean = false
4851
) {
4952
val focusManager = LocalFocusManager.current
5053
val textStyle = MaterialTheme.typography.bodyMedium
@@ -58,7 +61,7 @@ fun LoginTextField(
5861
IconButton(onClick = { onValueChange(TextFieldValue()) }) {
5962
Icon(
6063
painter = painterResource(R.drawable.ic_trailing_icon),
61-
contentDescription = null,
64+
contentDescription = stringResource(R.string.text_field_trailing_icon_desc),
6265
modifier = Modifier.size(20.dp),
6366
tint = odooPrimaryGray
6467
)
@@ -73,7 +76,7 @@ fun LoginTextField(
7376
singleLine = true,
7477
label = { Text(text = stringResource(labelResource), style = textStyle) },
7578
visualTransformation = visualTransformation,
76-
keyboardOptions = KeyboardOptions(keyboardType = keyboardType, imeAction = ImeAction.Done),
79+
keyboardOptions = KeyboardOptions(keyboardType = keyboardType, imeAction = imeAction),
7780
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
7881
isError = isError,
7982
shape = MaterialTheme.shapes.small,
@@ -94,6 +97,6 @@ fun LoginTextField(
9497
modifier = Modifier
9598
.fillMaxWidth()
9699
.padding(horizontal = mainHorizontalPadding)
97-
.padding(top = 30.dp),
100+
.padding(top = 20.dp),
98101
)
99102
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="text_field_trailing_icon_desc">textFieldTrailingIcon</string>
4+
<string name="button_icon_desc">buttonIcon</string>
5+
6+
<!-- for ui tests -->
7+
<string name="test_text_field_desc">testTextField</string>
8+
<string name="test_input">Test input</string>
9+
</resources>

core/uiKitTheme/src/main/kotlin/odoo/miem/android/core/uiKitTheme/OdooMiemAndroidTheme.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ private val DarkColorPalette = darkColorScheme(
1515
onPrimaryContainer = Color.White,
1616
onSecondaryContainer = Color.White,
1717
surfaceVariant = odooPrimary.copy(alpha = 0.1f),
18+
inverseSurface = Color.White,
19+
inverseOnSurface = Color.Black,
1820
background = odooDarkBackground,
1921
surface = odooDarkBackground
2022
)
@@ -27,6 +29,8 @@ private val LightColorPalette = lightColorScheme(
2729
onPrimaryContainer = odooPrimaryGray,
2830
onSecondaryContainer = Color.Black,
2931
surfaceVariant = odooPrimary.copy(alpha = 0.1f),
32+
inverseSurface = Color.White,
33+
inverseOnSurface = Color.Black,
3034
background = odooLightGrayBackground,
3135
surface = odooLightGrayBackground
3236
)

0 commit comments

Comments
 (0)