Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/main' into docs/upd…
Browse files Browse the repository at this point in the history
…ate-readme
  • Loading branch information
tercierp committed Dec 19, 2024
2 parents 78b327a + 34396ec commit 4e74830
Show file tree
Hide file tree
Showing 35 changed files with 1,508 additions and 526 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,19 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.GrantPermissionRule
import com.android.streetworkapp.StreetWorkAppMain
import com.android.streetworkapp.model.park.Park
import com.android.streetworkapp.model.park.ParkRepository
import com.android.streetworkapp.model.park.ParkViewModel
import com.android.streetworkapp.model.parklocation.OverpassParkLocationRepository
import com.android.streetworkapp.model.parklocation.ParkLocation
import com.android.streetworkapp.model.parklocation.ParkLocationRepository
import com.android.streetworkapp.model.parklocation.ParkLocationViewModel
import com.android.streetworkapp.model.preferences.PreferencesRepositoryDataStore
import com.android.streetworkapp.model.preferences.PreferencesViewModel
import com.android.streetworkapp.model.user.UserRepository
import com.android.streetworkapp.model.user.UserViewModel
import com.android.streetworkapp.ui.navigation.NavigationActions
import com.android.streetworkapp.ui.navigation.Route
import com.android.streetworkapp.ui.navigation.Screen
import io.mockk.mockk
import okhttp3.OkHttpClient
import org.junit.Before
import org.junit.Rule
Expand Down Expand Up @@ -103,40 +97,17 @@ class MapUiTest {
composeTestRule.onNodeWithTag("eventIcon").assertIsDisplayed()

composeTestRule.onNodeWithTag("eventsPlanned").assertIsDisplayed()

composeTestRule.onNodeWithTag("enterParkIcon").assertIsDisplayed()
}

@Test
fun mapSearchBarComponentIsDisplayed() {

val logicValue = mutableStateOf(false)

composeTestRule.setContent { MapSearchBar(mutableStateOf("")) { logicValue.value = true } }

composeTestRule.waitForIdle()

composeTestRule.onNodeWithTag("searchBar").assertIsDisplayed()

composeTestRule.onNodeWithTag("cancelSearchButton").assertIsDisplayed().performClick()

assert(logicValue.value)
}

@Test
fun mapSearchBarHasCorrectBehavior() {
composeTestRule.setContent {
StreetWorkAppMain(
PreferencesViewModel(mockk<PreferencesRepositoryDataStore>(relaxed = true)),
{ navigateTo(Route.MAP) })
}
composeTestRule.setContent { MapSearchBar(mutableStateOf("")) }

composeTestRule.waitForIdle()

composeTestRule.onNodeWithTag("searchButton").assertIsDisplayed().performClick()

composeTestRule.onNodeWithTag("searchBar").assertIsDisplayed()

composeTestRule.onNodeWithTag("cancelSearchButton").assertIsDisplayed().performClick()

composeTestRule.onNodeWithTag("topAppBar").assertIsDisplayed()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,21 +155,14 @@ class TopAppBarActionTest {
}

@Test
fun isSearchActionWorking() {
val searchAction = TopAppBarManager.TopAppBarAction.SEARCH
fun isSearchBarDisplayed() {

val topAppBarManager = TopAppBarManager("any title", actions = listOf(searchAction))

val logicValue = mutableStateOf(false)

topAppBarManager.setActionCallback(searchAction) { logicValue.value = true }
val topAppBarManager = TopAppBarManager("any title", hasSearchBar = true)

composeTestRule.setContent { TopAppBarWrapper(NavigationActions(mockk()), topAppBarManager) }

// Verify that clicking the action triggers the callback
assert(!logicValue.value)
composeTestRule.onNodeWithTag(searchAction.testTag).performClick()
composeTestRule.waitForIdle()
assert(logicValue.value)

composeTestRule.onNodeWithTag("searchBar").assertIsDisplayed()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,80 @@ package com.android.streetworkapp.ui.train

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import com.android.streetworkapp.model.user.User
import com.android.streetworkapp.model.user.UserRepository
import com.android.streetworkapp.model.user.UserViewModel
import com.android.streetworkapp.model.workout.WorkoutRepository
import com.android.streetworkapp.model.workout.WorkoutViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

class TrainCoachScreenTest {

@get:Rule val composeTestRule = createComposeRule()

private val mockWorkoutRepository = mock<WorkoutRepository>()
private val workoutViewModel = WorkoutViewModel(mockWorkoutRepository)
private lateinit var workoutViewModel: WorkoutViewModel

@Test
fun trainCoachScreen_displaysCorrectInformation() {
val testActivity = "Push-ups"
val testIsTimeDependent = true
@Test fun trainCoachScreen_displaysCorrectInformation() {}

private val mockUserRepository = mock<UserRepository>()
private lateinit var userViewModel: UserViewModel

@Before
fun setUp() = runBlocking {
val testUser = User("testUser", "Test User", "email@mail.com", 2, emptyList(), "picture")
whenever(mockUserRepository.getUserByUid("testUser")).thenReturn(testUser)
// Mock the flow for testUser
whenever(mockWorkoutRepository.observePairingRequests("testUser"))
.thenReturn(MutableStateFlow(emptyList()))

// Initialize the VMs
workoutViewModel = WorkoutViewModel(mockWorkoutRepository)
userViewModel = UserViewModel(mockUserRepository)

// Set the current user in userViewModel if needed
userViewModel.setCurrentUser(testUser)
}

@Test
fun trainCoachScreen_displaysRoleDialog() {
composeTestRule.setContent {
TrainCoachScreen(
activity = testActivity,
isTimeDependent = testIsTimeDependent,
activity = "Push-ups",
isTimeDependent = true,
reps = 10,
time = 60,
workoutViewModel = workoutViewModel,
time = 0,
sets = 0,
reps = 0)
userViewModel = userViewModel)
}

// Verify the static title
composeTestRule.onNodeWithText("Train Coach").assertExists().assertIsDisplayed()
// Verify Role Dialog elements
composeTestRule.onNodeWithTag("DialogTitle").assertIsDisplayed()
composeTestRule.onNodeWithTag("RoleSwitch").performClick()
composeTestRule.onNodeWithTag("ConfirmButton").performClick()
}

// Verify the activity text
composeTestRule.onNodeWithText("Activity: $testActivity").assertExists().assertIsDisplayed()
@Test
fun trainCoachScreen_displaysCoachView() {
composeTestRule.setContent {
CoachView(
isTimeDependent = false,
reps = 20,
workoutViewModel = workoutViewModel,
userViewModel = userViewModel)
}

// Verify the time-dependent text
composeTestRule
.onNodeWithText("Time Dependent: $testIsTimeDependent")
.assertExists()
.assertIsDisplayed()
// Verify Coach View elements
composeTestRule.onNodeWithTag("IncrementButton").performClick()
composeTestRule.onNodeWithTag("DecrementButton").performClick()
composeTestRule.onNodeWithTag("EndSessionButton").performClick()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.android.streetworkapp.ui.train

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import org.junit.Rule
import org.junit.Test

class TrainHelperTest {
@get:Rule val composeTestRule = createComposeRule()

@Test
fun trainCoachDialog_rendersAndInteracts() {
composeTestRule.setContent { TrainCoachDialog(onRoleSelected = {}, onDismiss = {}) }

composeTestRule.onNodeWithTag("DialogTitle").assertIsDisplayed()
composeTestRule.onNodeWithTag("RoleText").assertIsDisplayed()
composeTestRule.onNodeWithTag("RoleSwitch").performClick()
composeTestRule.onNodeWithTag("ConfirmButton").performClick()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,11 @@ class TrainHubScreenTest {
composeTestRule.onNodeWithTag("ActivitySelectionTitle").assertExists()

// Verify RoleSelectionGrid
composeTestRule.onNodeWithTag("Role_Grid").assertExists()
listOf("Solo", "Coach", "Challenge").forEach { role ->
listOf("Solo", "Coach").forEach { role ->
composeTestRule.onNodeWithTag("Role_$role").assertExists()
}

// Verify ActivitySelectionGrid
composeTestRule.onNodeWithTag("Activity_Grid").assertExists()
listOf(
"Push-ups",
"Dips",
Expand All @@ -71,10 +69,8 @@ class TrainHubScreenTest {
"Muscle-up")
.forEach { activity -> composeTestRule.onNodeWithTag("Activity_$activity").assertExists() }

// Verify Divider
composeTestRule.onNodeWithTag("Divider").assertExists()

// Verify ConfirmButton
composeTestRule.onNodeWithTag("ConfirmButton").assertExists()
// composeTestRule.onNodeWithTag("ConfirmButton").assertExists()
// TODO check this in the E2E training debug branch
}
}
43 changes: 20 additions & 23 deletions app/src/main/java/com/android/streetworkapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import com.android.streetworkapp.ui.authentication.SignInScreen
import com.android.streetworkapp.ui.event.AddEventScreen
import com.android.streetworkapp.ui.event.EventOverviewScreen
import com.android.streetworkapp.ui.map.MapScreen
import com.android.streetworkapp.ui.map.MapSearchBar
import com.android.streetworkapp.ui.miscellaneous.SplashScreen
import com.android.streetworkapp.ui.navigation.BottomNavigationMenu
import com.android.streetworkapp.ui.navigation.BottomNavigationMenuType
Expand Down Expand Up @@ -218,7 +217,6 @@ fun StreetWorkAppMain(
}
}

@SuppressLint("UnrememberedMutableState")
@Composable
fun StreetWorkApp(
parkLocationViewModel: ParkLocationViewModel,
Expand Down Expand Up @@ -257,34 +255,28 @@ fun StreetWorkApp(
// Instantiate info manager and its components :
val showInfoDialog = remember { mutableStateOf(false) }
val showSearchBar = remember { mutableStateOf(false) }
val showFilterSettings = remember { mutableStateOf(false) }

// query for the search bar
val searchQuery = remember { mutableStateOf("") }

Log.d("InfoDialog", "Main - Instantiating the InfoDialogManager")
Log.d("MainActivity", "Main - Instantiating the InfoDialogManager")
val infoManager =
InfoDialogManager(
showInfoDialog, currentScreenName, topAppBarManager = screenParams?.topAppBarManager)

Scaffold(
containerColor = ColorPalette.PRINCIPLE_BACKGROUND_COLOR,
topBar = {
if (showSearchBar.value && screenParams?.hasSearchBar == true) {
MapSearchBar(searchQuery) {
searchQuery.value = ""
showSearchBar.value = false
}
} else {
screenParams
?.isTopBarVisible
?.takeIf { it }
?.let {
TopAppBarWrapper(navigationActions, screenParams?.topAppBarManager)
// setup the InfoDialogManager in topBar, because it relies on the topAppBarManager.
Log.d("InfoDialog", "Main - Setting up the InfoDialogManager")
infoManager.setUp()
}
}
screenParams
?.isTopBarVisible
?.takeIf { it }
?.let {
TopAppBarWrapper(navigationActions, screenParams?.topAppBarManager, searchQuery)
// setup the InfoDialogManager in topBar, because it relies on the topAppBarManager.
Log.d("MainActivity", "Main - Setting up the InfoDialogManager")
infoManager.setUp()
}
},
snackbarHost = {
SnackbarHost(
Expand Down Expand Up @@ -339,8 +331,6 @@ fun StreetWorkApp(
route = Route.MAP,
) {
composable(Screen.MAP) {
val showFilterSettings = mutableStateOf(false)

infoManager.Display(LocalContext.current)
MapScreen(
parkLocationViewModel,
Expand Down Expand Up @@ -459,6 +449,7 @@ fun StreetWorkApp(
route = Route.TRAIN_HUB,
) {
composable(Screen.TRAIN_HUB) {
infoManager.Display(LocalContext.current)
TrainHubScreen(navigationActions, workoutViewModel, userViewModel, innerPadding)
}
trainComposable(
Expand All @@ -477,9 +468,15 @@ fun StreetWorkApp(

trainComposable(
route = Screen.TRAIN_COACH,
content = { activity, isTimeDependent, time, sets, reps ->
content = { activity, isTimeDependent, time, _, reps ->
TrainCoachScreen(
activity, isTimeDependent, time, sets, reps, workoutViewModel, innerPadding)
activity,
isTimeDependent,
reps,
time,
workoutViewModel,
userViewModel,
innerPadding)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ package com.android.streetworkapp.model.workout
* @param duration Optional duration for the exercise
*/
data class Exercise(
val name: String,
val name: String = "",
val reps: Int? = null,
val sets: Int? = null,
val weight: Float? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,26 @@ package com.android.streetworkapp.model.workout
* @param timestamp The time when the request was created, in epoch milliseconds.
*/
data class PairingRequest(
val requestId: String = "", // Unique ID for the request
val fromUid: String = "", // User who sent the request
val toUid: String = "", // User who received the request
val status: RequestStatus = RequestStatus.PENDING, // Current status of the request
val timestamp: Long = System.currentTimeMillis() // Time of creation
val requestId: String = "",
val fromUid: String = "",
val toUid: String = "",
val sessionId: String? = null,
val counter: Int? = 0,
val timerStatus: TimerStatus = TimerStatus.STOPPED,
val status: RequestStatus = RequestStatus.PENDING,
val timestamp: Long = System.currentTimeMillis()
)

/** An enum class representing the status of a pairing request. */
enum class RequestStatus {
PENDING, // Waiting for the recipient's response
ACCEPTED, // The request has been accepted
REJECTED // The request has been rejected
REJECTED, // The request has been rejected
OLD // The request is no longer valid
}

/** An enum class representing the status of a timer. */
enum class TimerStatus {
RUNNING, // Running timer
STOPPED // Timer has been stopped
}
Loading

0 comments on commit 4e74830

Please sign in to comment.