From 2bd81f428f3d8d384a61da063644cee0139131d8 Mon Sep 17 00:00:00 2001 From: agonzalez-r Date: Thu, 10 Oct 2024 18:58:14 +0200 Subject: [PATCH 1/4] feat: implement UI for AlertScreen with dropdowns and text fields Added UI components for product selection, urgency level, location, and message input Includes a submit button for saving alerts Needs linking to ViewModel for functionality --- .../periodpals/ui/alert/AlertScreenTest.kt | 48 +++++++ .../periodpals/ui/alert/AlertScreen.kt | 134 ++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt create mode 100644 app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt diff --git a/app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt b/app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt new file mode 100644 index 000000000..7b2b4edf0 --- /dev/null +++ b/app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt @@ -0,0 +1,48 @@ +package com.android.periodpals.ui.alert + +import androidx.compose.material3.MaterialTheme +import androidx.compose.ui.test.* +import androidx.compose.ui.test.junit4.createComposeRule +import org.junit.Rule +import org.junit.Test + +class AlertScreenTest { + + @get:Rule val composeTestRule = createComposeRule() + + @Test + fun testAlertScreenUI() { + // Start the composable in the test environment + composeTestRule.setContent { MaterialTheme { AlertScreen() } } + + // Check if the instruction text is displayed + composeTestRule.onNodeWithTag("alertInstruction").assertIsDisplayed() + + // Check if the product dropdown is displayed and clickable + composeTestRule + .onNodeWithTag("alertProduct") + .assertIsDisplayed() + .performClick() // To expand the dropdown menu + + // Check if urgency dropdown is displayed and clickable + composeTestRule.onNodeWithTag("alertUrgency").assertIsDisplayed().performClick() + + // Enter text in the location field + composeTestRule + .onNodeWithTag("alertLocation") + .assertIsDisplayed() + .performTextInput("Rolex Learning Center") + + // Enter text in the message field + composeTestRule + .onNodeWithTag("alertMessage") + .assertIsDisplayed() + .performTextInput("I need help finding a tampon! I'll be at rolex until 2pm") + + // Check if the submit button is displayed and perform a click + composeTestRule + .onNodeWithTag("alertSubmit") + .assertIsDisplayed() + .assertHasClickAction() // Ensure the button is clickable + } +} diff --git a/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt b/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt new file mode 100644 index 000000000..19ff8e33d --- /dev/null +++ b/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt @@ -0,0 +1,134 @@ +package com.android.periodpals.ui.alert + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Button +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@Preview +@Composable +fun AlertScreen() { + var location by remember { mutableStateOf("") } + var message by remember { mutableStateOf("") } + + // TODO("TOP APP BAR and BOTTOM NAVIGATION") + Scaffold( + modifier = Modifier.testTag("alertScreen"), + content = { paddingValues -> + Column( + modifier = Modifier.fillMaxSize().padding(16.dp).padding(paddingValues), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceEvenly) { + // Text Instruction + Text( + "Push a notification that will be received by users around you so that they can help you find the period product that you need", + modifier = Modifier.testTag("alertInstruction"), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleSmall) + + // Product selection + ExposedDropdownMenuSample( + listOf("Tampons", "Pads", "Either"), "Product Needed", "alertProduct") + + // Urgency indicator + ExposedDropdownMenuSample( + listOf("!!! High", "!! Medium", "! Low"), "Urgency level", "alertUrgency") + + // Location + OutlinedTextField( + value = location, + onValueChange = { location = it }, + label = { Text("Location") }, + placeholder = { Text("Enter your location") }, + modifier = Modifier.fillMaxWidth().testTag("alertLocation")) + + // Message Box + OutlinedTextField( + value = message, + onValueChange = { message = it }, + label = { Text("Message") }, + placeholder = { Text("Write a message for the other users") }, + modifier = Modifier.fillMaxWidth().height(150.dp).testTag("alertMessage")) + + // Submit Button + Button( + onClick = { + // TODO("Save alert on supabase + navigation to + // AlertListScreen") + }, + modifier = + Modifier.width(300.dp).height(100.dp).testTag("alertSubmit").padding(16.dp), + // colors + ) { + Text("Ask for help", style = MaterialTheme.typography.headlineMedium) + } + } + }) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ExposedDropdownMenuSample(list: List, m: String, testTag: String) { + var options = list + var expanded by remember { mutableStateOf(false) } + var text by remember { mutableStateOf(m) } + + ExposedDropdownMenuBox( + modifier = Modifier.testTag(testTag), + expanded = expanded, + onExpandedChange = { expanded = it }, + ) { + TextField( + // The `menuAnchor` modifier must be passed to the text field to handle + // expanding/collapsing the menu on click. A read-only text field has + // the anchor type `PrimaryNotEditable`. + modifier = Modifier.menuAnchor(), + value = text, + onValueChange = {}, + readOnly = true, + singleLine = true, + label = { Text("Label") }, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, + colors = ExposedDropdownMenuDefaults.textFieldColors(), + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }, + ) { + options.forEach { option -> + DropdownMenuItem( + text = { Text(option) }, + onClick = { + text = option + expanded = false + }, + contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, + ) + } + } + } +} From 47e1fa05955f3d0ecc9c765dbfe5b5e622edf926 Mon Sep 17 00:00:00 2001 From: agonzalez-r Date: Thu, 10 Oct 2024 19:21:04 +0200 Subject: [PATCH 2/4] test: add UI tests for Alert Screen components fix: change labels for the dropdown menus in AlertScreen --- .../java/com/android/periodpals/ui/alert/AlertScreen.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt b/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt index 19ff8e33d..8c0096e50 100644 --- a/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt +++ b/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt @@ -52,7 +52,7 @@ fun AlertScreen() { // Product selection ExposedDropdownMenuSample( - listOf("Tampons", "Pads", "Either"), "Product Needed", "alertProduct") + listOf("Tampons", "Pads", "No Preference"), "Product Needed", "alertProduct") // Urgency indicator ExposedDropdownMenuSample( @@ -92,10 +92,10 @@ fun AlertScreen() { @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ExposedDropdownMenuSample(list: List, m: String, testTag: String) { +fun ExposedDropdownMenuSample(list: List, label: String, testTag: String) { var options = list var expanded by remember { mutableStateOf(false) } - var text by remember { mutableStateOf(m) } + var text by remember { mutableStateOf("Please choose one option") } ExposedDropdownMenuBox( modifier = Modifier.testTag(testTag), @@ -111,7 +111,7 @@ fun ExposedDropdownMenuSample(list: List, m: String, testTag: String) { onValueChange = {}, readOnly = true, singleLine = true, - label = { Text("Label") }, + label = { Text(label) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.textFieldColors(), ) From 17cf680fe85a01df806563b599576997203ef095 Mon Sep 17 00:00:00 2001 From: agonzalez-r Date: Fri, 11 Oct 2024 09:21:42 +0200 Subject: [PATCH 3/4] fix: delete sample test file causing problems with the CI --- .../periodpals/ExampleInstrumentedTest.kt | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 app/src/androidTest/java/com/android/periodpals/ExampleInstrumentedTest.kt diff --git a/app/src/androidTest/java/com/android/periodpals/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/android/periodpals/ExampleInstrumentedTest.kt deleted file mode 100644 index 03e490f71..000000000 --- a/app/src/androidTest/java/com/android/periodpals/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.android.periodpals - -import androidx.compose.ui.test.junit4.createAndroidComposeRule -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.kaspersky.kaspresso.testcases.api.testcase.TestCase -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class MainActivityTest : TestCase() { - - @get:Rule val composeTestRule = createAndroidComposeRule() - - @Test - fun test() = - run { - // step("Start Main Activity") { - // ComposeScreen.onComposeScreen(composeTestRule) { - // simpleText { - // assertIsDisplayed() - // assertTextEquals("Hello Android!") - // } - // } - // } - } -} From 87ab835be30d549e395c5a130532e5f2bc1647aa Mon Sep 17 00:00:00 2001 From: agonzalez-r Date: Sat, 12 Oct 2024 17:52:19 +0200 Subject: [PATCH 4/4] fix: separate Test functions for maintainability and readability --- .../periodpals/ui/alert/AlertScreenTest.kt | 50 +++++++++---------- .../periodpals/ui/alert/AlertScreen.kt | 8 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt b/app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt index 7b2b4edf0..6da447b41 100644 --- a/app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt +++ b/app/src/androidTest/java/com/android/periodpals/ui/alert/AlertScreenTest.kt @@ -1,8 +1,12 @@ package com.android.periodpals.ui.alert import androidx.compose.material3.MaterialTheme -import androidx.compose.ui.test.* +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertTextEquals import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput import org.junit.Rule import org.junit.Test @@ -11,38 +15,34 @@ class AlertScreenTest { @get:Rule val composeTestRule = createComposeRule() @Test - fun testAlertScreenUI() { - // Start the composable in the test environment + fun displayAllComponents() { composeTestRule.setContent { MaterialTheme { AlertScreen() } } - // Check if the instruction text is displayed composeTestRule.onNodeWithTag("alertInstruction").assertIsDisplayed() - - // Check if the product dropdown is displayed and clickable + composeTestRule.onNodeWithTag("alertProduct").assertIsDisplayed() + composeTestRule.onNodeWithTag("alertUrgency").assertIsDisplayed() + composeTestRule.onNodeWithTag("alertLocation").assertIsDisplayed() + composeTestRule.onNodeWithTag("alertMessage").assertIsDisplayed() composeTestRule - .onNodeWithTag("alertProduct") + .onNodeWithTag("alertSubmit") .assertIsDisplayed() - .performClick() // To expand the dropdown menu + .assertTextEquals("Ask for Help") + } - // Check if urgency dropdown is displayed and clickable - composeTestRule.onNodeWithTag("alertUrgency").assertIsDisplayed().performClick() + @Test + fun interactWithComponents() { + composeTestRule.setContent { MaterialTheme { AlertScreen() } } - // Enter text in the location field - composeTestRule - .onNodeWithTag("alertLocation") - .assertIsDisplayed() - .performTextInput("Rolex Learning Center") + composeTestRule.onNodeWithTag("alertProduct").performClick() + composeTestRule.onNodeWithTag("Pads").performClick() + // composeTestRule.onNodeWithTag("alertProduct").assertTextEquals("Pads") + composeTestRule.onNodeWithTag("alertUrgency").performClick() + composeTestRule.onNodeWithTag("!! Medium").performClick() + // composeTestRule.onNodeWithTag("alertUrgency").assertTextEquals("!! Medium") - // Enter text in the message field - composeTestRule - .onNodeWithTag("alertMessage") - .assertIsDisplayed() - .performTextInput("I need help finding a tampon! I'll be at rolex until 2pm") + composeTestRule.onNodeWithTag("alertLocation").performTextInput("Rolex") + composeTestRule.onNodeWithTag("alertMessage").performTextInput("I need help finding a tampon") - // Check if the submit button is displayed and perform a click - composeTestRule - .onNodeWithTag("alertSubmit") - .assertIsDisplayed() - .assertHasClickAction() // Ensure the button is clickable + composeTestRule.onNodeWithTag("alertSubmit").performClick() } } diff --git a/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt b/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt index 8c0096e50..c0a93cd21 100644 --- a/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt +++ b/app/src/main/java/com/android/periodpals/ui/alert/AlertScreen.kt @@ -40,12 +40,12 @@ fun AlertScreen() { modifier = Modifier.testTag("alertScreen"), content = { paddingValues -> Column( - modifier = Modifier.fillMaxSize().padding(16.dp).padding(paddingValues), + modifier = Modifier.fillMaxSize().padding(30.dp).padding(paddingValues), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceEvenly) { // Text Instruction Text( - "Push a notification that will be received by users around you so that they can help you find the period product that you need", + "Push a notification to users near you! If they are available and have the products you need, they'll be able to help you!", modifier = Modifier.testTag("alertInstruction"), textAlign = TextAlign.Center, style = MaterialTheme.typography.titleSmall) @@ -82,9 +82,8 @@ fun AlertScreen() { }, modifier = Modifier.width(300.dp).height(100.dp).testTag("alertSubmit").padding(16.dp), - // colors ) { - Text("Ask for help", style = MaterialTheme.typography.headlineMedium) + Text("Ask for Help", style = MaterialTheme.typography.headlineMedium) } } }) @@ -121,6 +120,7 @@ fun ExposedDropdownMenuSample(list: List, label: String, testTag: String ) { options.forEach { option -> DropdownMenuItem( + modifier = Modifier.testTag(option), text = { Text(option) }, onClick = { text = option