Skip to content

Commit 9f3ecf0

Browse files
committed
Add tests, update android.yml, and make corrections to the implementation
1 parent 7478b23 commit 9f3ecf0

File tree

16 files changed

+671
-38
lines changed

16 files changed

+671
-38
lines changed

.github/workflows/android.yml

+2
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@ jobs:
2222

2323
- name: Grant execute permission for gradlew
2424
run: chmod +x gradlew
25+
- name: Run unit tests
26+
run: ./gradlew test
2527
- name: Build with Gradle
2628
run: ./gradlew build

app/build.gradle

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ plugins {
55

66
android {
77
compileSdk 32
8-
98
defaultConfig {
109
applicationId "com.aemerse.dialogs_android"
1110
minSdk 21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.aemerse.dialogs_android
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.ui.test.junit4.createComposeRule
5+
import androidx.compose.ui.test.performClick
6+
import androidx.test.ext.junit.runners.AndroidJUnit4
7+
import com.aemerse.dialogs.MaterialDialogButtons
8+
import com.aemerse.dialogs_android.utils.DialogWithContent
9+
import com.aemerse.dialogs_android.utils.extensions.assertDialogDoesNotExist
10+
import com.aemerse.dialogs_android.utils.extensions.assertDialogExists
11+
import com.aemerse.dialogs_android.utils.extensions.onNegativeButton
12+
import com.aemerse.dialogs_android.utils.extensions.onPositiveButton
13+
import org.junit.Rule
14+
import org.junit.Test
15+
import org.junit.runner.RunWith
16+
17+
@RunWith(AndroidJUnit4::class)
18+
class DialogButtonsTest {
19+
@get:Rule
20+
val composeTestRule = createComposeRule()
21+
22+
@Composable
23+
private fun MaterialDialogButtons.defaultButtons() {
24+
negativeButton("Disagree")
25+
positiveButton("Agree")
26+
}
27+
28+
@Test
29+
fun dialogDismissedOnPositiveButton() {
30+
composeTestRule.setContent { DialogWithContent(buttons = { defaultButtons() }) }
31+
composeTestRule.onPositiveButton().performClick()
32+
composeTestRule.assertDialogDoesNotExist()
33+
}
34+
35+
@Test
36+
fun dialogDismissedOnNegativeButton() {
37+
composeTestRule.setContent { DialogWithContent(buttons = { defaultButtons() }) }
38+
composeTestRule.onNegativeButton().performClick()
39+
composeTestRule.assertDialogDoesNotExist()
40+
}
41+
42+
@Test
43+
fun dialogNotDismissedOnPositiveButton() {
44+
composeTestRule.setContent { DialogWithContent(false, buttons = { defaultButtons() }) }
45+
composeTestRule.onPositiveButton().performClick()
46+
composeTestRule.assertDialogExists()
47+
}
48+
49+
@Test
50+
fun dialogNotDismissedOnNegativeButton() {
51+
composeTestRule.setContent { DialogWithContent(false, buttons = { defaultButtons() }) }
52+
composeTestRule.onNegativeButton().performClick()
53+
composeTestRule.assertDialogExists()
54+
}
55+
}

app/src/androidTest/java/com/aemerse/dialogs_android/ExampleInstrumentedTest.kt

-24
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package com.aemerse.dialogs_android
2+
3+
import android.util.Patterns
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.mutableStateOf
6+
import androidx.compose.ui.test.*
7+
import androidx.compose.ui.test.junit4.createComposeRule
8+
import androidx.test.ext.junit.runners.AndroidJUnit4
9+
import com.aemerse.dialogs.MaterialDialogScope
10+
import com.aemerse.dialogs.input
11+
import com.aemerse.dialogs.rememberMaterialDialogState
12+
import com.aemerse.dialogs.title
13+
import com.aemerse.dialogs_android.utils.DialogWithContent
14+
import com.aemerse.dialogs_android.utils.defaultButtons
15+
import com.aemerse.dialogs_android.utils.extensions.onDialogInput
16+
import com.aemerse.dialogs_android.utils.extensions.onDialogInputError
17+
import com.aemerse.dialogs_android.utils.extensions.onPositiveButton
18+
import org.junit.Assert.assertEquals
19+
import org.junit.Rule
20+
import org.junit.Test
21+
import org.junit.runner.RunWith
22+
23+
@RunWith(AndroidJUnit4::class)
24+
class InputDialogTest {
25+
@get:Rule
26+
val composeTestRule = createComposeRule()
27+
28+
private val testInput = "random text input from the user"
29+
private val testHint = "random hint"
30+
private val testLabel = "random text input label"
31+
private val testInputError = "random error"
32+
33+
@Test
34+
fun checkTextShownOnInput() {
35+
setupBasicInputDialog()
36+
composeTestRule.onDialogInput().performTextInput(testInput)
37+
composeTestRule.onNodeWithText(testInput).assertExists()
38+
}
39+
40+
@Test
41+
fun checkPrefillTextIsShown() {
42+
setupBasicInputDialog { input(label = testLabel, prefill = testInput) }
43+
composeTestRule.onNodeWithText(testInput).assertExists()
44+
}
45+
46+
@Test
47+
fun checkHintTextIsShown() {
48+
setupBasicInputDialog { input(label = testLabel, placeholder = testHint) }
49+
composeTestRule.onNodeWithText(testHint, true).assertExists()
50+
}
51+
52+
@Test
53+
fun checkCorrectLabelTextIsShown() {
54+
setupBasicInputDialog { input(label = testLabel) }
55+
composeTestRule.onNodeWithText(testLabel, true).assertExists()
56+
}
57+
58+
// @Test
59+
// fun checkVisualTransformationIsApplied() {
60+
// setupBasicInputDialog {
61+
// input(
62+
// label = testLabel,
63+
// visualTransformation = PasswordVisualTransformation()
64+
// )
65+
// }
66+
//
67+
// composeTestRule.onDialogInput().performTextInput(testInput)
68+
// composeTestRule.onNodeWithText(testInput).assertDoesNotExist()
69+
// }
70+
71+
@Test
72+
fun checkErrorTextIsShown() {
73+
setupBasicInputDialog {
74+
input(
75+
label = testLabel,
76+
errorMessage = testInputError,
77+
isTextValid = { false }
78+
)
79+
}
80+
composeTestRule.onNodeWithText(testLabel, true).assertExists()
81+
}
82+
83+
@Test
84+
fun checkWaitForPositiveButtonEnabled() {
85+
val input = mutableStateOf<String?>(null)
86+
setupBasicInputDialog {
87+
input(
88+
label = testLabel,
89+
waitForPositiveButton = true,
90+
onInput = { input.value = it }
91+
)
92+
}
93+
94+
composeTestRule.onDialogInput().performTextInput(testInput)
95+
assertEquals(null, input.value)
96+
composeTestRule.onPositiveButton().performClick()
97+
assertEquals(testInput, input.value)
98+
}
99+
100+
@Test
101+
fun checkWaitForPositiveButtonDisabled() {
102+
val input = mutableStateOf<String?>(null)
103+
setupBasicInputDialog {
104+
input(
105+
label = testLabel,
106+
waitForPositiveButton = false,
107+
onInput = { input.value = it }
108+
)
109+
}
110+
111+
composeTestRule.onDialogInput().performTextInput(testInput)
112+
assertEquals(testInput, input.value)
113+
input.value = null
114+
composeTestRule.onPositiveButton().performClick()
115+
assertEquals(null, input.value)
116+
}
117+
118+
@Test
119+
fun checkErrorShownWithInputValidation() {
120+
setupBasicInputDialog {
121+
input(
122+
label = testLabel,
123+
waitForPositiveButton = false,
124+
isTextValid = { Patterns.EMAIL_ADDRESS.matcher(it).matches() }
125+
)
126+
}
127+
128+
listOf("hello", "hello@gmail", "hello.com", "hello@.com").forEach {
129+
composeTestRule.onDialogInput().performTextInput(it)
130+
composeTestRule.onDialogInputError().assertExists()
131+
composeTestRule.onDialogInput().performTextClearance()
132+
}
133+
134+
listOf("hello@gmail.com", "test@test.co.uk", "test@hello.is").forEach {
135+
composeTestRule.onDialogInput().performTextInput(it)
136+
composeTestRule.onDialogInputError().assertDoesNotExist()
137+
composeTestRule.onDialogInput().performTextClearance()
138+
}
139+
}
140+
141+
@Test
142+
fun checkErrorDisappearsOnValidInput() {
143+
setupBasicInputDialog {
144+
input(
145+
label = testLabel,
146+
waitForPositiveButton = false,
147+
isTextValid = { Patterns.EMAIL_ADDRESS.matcher(it).matches() }
148+
)
149+
}
150+
151+
composeTestRule.onDialogInput().performTextInput("hello@hello")
152+
composeTestRule.onDialogInputError().assertExists()
153+
composeTestRule.onDialogInput().performTextInput(".com")
154+
composeTestRule.onDialogInputError().assertDoesNotExist()
155+
}
156+
157+
@Test
158+
fun checkPositiveButtonDisabledOnInvalidInput() {
159+
setupBasicInputDialog {
160+
input(
161+
label = testLabel,
162+
waitForPositiveButton = false,
163+
isTextValid = { Patterns.EMAIL_ADDRESS.matcher(it).matches() }
164+
)
165+
}
166+
167+
composeTestRule.onDialogInput().performTextInput("hello@hello")
168+
composeTestRule.onPositiveButton().assertIsNotEnabled()
169+
composeTestRule.onDialogInput().performTextInput(".com")
170+
composeTestRule.onPositiveButton().assertIsEnabled()
171+
}
172+
173+
private fun setupBasicInputDialog(
174+
testInputDialog: @Composable MaterialDialogScope.() -> Unit = { input(label = "Test") }
175+
) {
176+
composeTestRule.setContent {
177+
val dialogState = rememberMaterialDialogState(true)
178+
179+
DialogWithContent(dialogState = dialogState, buttons = { defaultButtons() }) {
180+
title(res = R.string.input_dialog_title)
181+
testInputDialog()
182+
}
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)