Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/Logout #204

Merged
merged 33 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
004f717
feat(main): instantiate Google Auth Service in main
SaturneV Dec 8, 2024
d83a4ea
feat(main): add Google Auth Service in SignIn
SaturneV Dec 8, 2024
1c82cdc
feat(main): add Google Auth Service in settings
SaturneV Dec 8, 2024
9c1e755
feat(setting): add a logout function
SaturneV Dec 8, 2024
7f475b8
feat(setting): add a preferences viewmodel parameter
SaturneV Dec 8, 2024
b76f8c9
feat(setting): make the button call logout
SaturneV Dec 8, 2024
c18c1ce
feat(user): add a user setter function
SaturneV Dec 8, 2024
4dc8a2a
feat(user): update the user with a null value when logout
SaturneV Dec 8, 2024
7ed9d5d
feat(user): navigate to login screen when logged out
SaturneV Dec 8, 2024
92be501
feat(strings): add logout string resources
SaturneV Dec 8, 2024
6ea99b8
feat(setting): adapt logout texts with string resources
SaturneV Dec 8, 2024
770c669
chore: add comments
SaturneV Dec 8, 2024
a38daec
feat(test): implement a `setUser` test
SaturneV Dec 8, 2024
3b60a48
fix(test): add Google Auth service mock to tests
SaturneV Dec 8, 2024
15b8562
feat(test): add a logout button click test
SaturneV Dec 8, 2024
5f1b8f3
Merge branch 'main' into feat/logout
SaturneV Dec 8, 2024
b6f3de6
Merge branch 'main' into feat/logout
SaturneV Dec 9, 2024
220c79f
fix(test): add Google Auth Service mock to E2E test
SaturneV Dec 9, 2024
d37c31e
feat(auth): add context parameter to google auth service class
SaturneV Dec 10, 2024
aaca593
feat(auth): init `GoogleSignInClient`globally in class
SaturneV Dec 10, 2024
f5066ab
fix(auth): update parameters in `AuthService` interface
SaturneV Dec 10, 2024
4c1be7c
fix(auth): update `launchSignIn` function and parameters
SaturneV Dec 10, 2024
036d5da
fix(auth): update button sign in launcher parameters
SaturneV Dec 10, 2024
8c475b2
feat(main): add context to auth service parameters
SaturneV Dec 10, 2024
24529f0
fix(test): update test with new auth service parameters
SaturneV Dec 10, 2024
a95a60a
feat(auth): add google auth service sign out in sign out function
SaturneV Dec 10, 2024
3633bca
chore(auth): add documentation
SaturneV Dec 10, 2024
6a01ad3
Merge branch 'main' into feat/logout
SaturneV Dec 10, 2024
b658727
fix(auth): remove unused parameter
SaturneV Dec 10, 2024
3195075
fix(signin): remove Google Auth button context parameter
SaturneV Dec 10, 2024
64f99d9
feat(auth): add access revocation to auth service interface
SaturneV Dec 10, 2024
c76b233
feat(auth): implement a Google Auth revocation function
SaturneV Dec 10, 2024
588366f
feat(settings): revoke access when logging out in settings
SaturneV Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.android.streetworkapp.end2end
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertTextContains
import androidx.compose.ui.test.click
Expand Down Expand Up @@ -38,14 +39,17 @@ import com.android.streetworkapp.model.user.UserRepository
import com.android.streetworkapp.model.user.UserViewModel
import com.android.streetworkapp.model.workout.WorkoutViewModel
import com.android.streetworkapp.ui.navigation.Screen
import com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.Timestamp
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import okhttp3.OkHttpClient
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.RETURNS_DEFAULTS
import org.mockito.Mockito.mock

@RunWith(AndroidJUnit4::class)
Expand Down Expand Up @@ -139,6 +143,10 @@ class End2EndCreateEvent {
mock(TextModerationViewModel::class.java),
mock(ImageViewModel::class.java),
mock(PreferencesViewModel::class.java),
GoogleAuthService(
"abc",
mock(FirebaseAuth::class.java, RETURNS_DEFAULTS),
context = LocalContext.current),
true)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.android.streetworkapp.end2end

import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertCountEquals
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertTextEquals
Expand Down Expand Up @@ -32,11 +33,14 @@ import com.android.streetworkapp.model.user.UserViewModel
import com.android.streetworkapp.model.workout.WorkoutRepository
import com.android.streetworkapp.model.workout.WorkoutViewModel
import com.android.streetworkapp.ui.navigation.Route
import com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.auth.FirebaseAuth
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito.RETURNS_DEFAULTS
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.wheneverBlocking
Expand Down Expand Up @@ -124,7 +128,9 @@ class End2EndGeneral {
WorkoutViewModel(mock(WorkoutRepository::class.java)),
TextModerationViewModel(mock(TextModerationRepository::class.java)),
ImageViewModel(mock(ImageRepository::class.java)),
PreferencesViewModel(mock(PreferencesRepository::class.java)))
PreferencesViewModel(mock(PreferencesRepository::class.java)),
GoogleAuthService(
"abc", mock(FirebaseAuth::class.java, RETURNS_DEFAULTS), LocalContext.current))
}

composeTestRule.waitForIdle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.click
Expand Down Expand Up @@ -42,6 +43,8 @@ import com.android.streetworkapp.model.progression.ProgressionViewModel
import com.android.streetworkapp.model.user.UserViewModel
import com.android.streetworkapp.model.workout.WorkoutViewModel
import com.android.streetworkapp.ui.navigation.Route
import com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.auth.FirebaseAuth
import io.mockk.every
import io.mockk.mockk
import org.junit.After
Expand All @@ -51,6 +54,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.RETURNS_DEFAULTS
import org.mockito.Mockito.mock

@RunWith(AndroidJUnit4::class)
Expand Down Expand Up @@ -118,7 +122,9 @@ class End2EndParks {
WorkoutViewModel(mockk()),
TextModerationViewModel(mockk()),
ImageViewModel(mockk()),
PreferencesViewModel(mock(PreferencesRepository::class.java)))
PreferencesViewModel(mock(PreferencesRepository::class.java)),
GoogleAuthService(
"abc", mock(FirebaseAuth::class.java, RETURNS_DEFAULTS), LocalContext.current))
// setup so as we're already on the MAP route
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.android.streetworkapp.end2end

import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertTextEquals
Expand Down Expand Up @@ -36,6 +37,8 @@ import com.android.streetworkapp.model.workout.WorkoutSession
import com.android.streetworkapp.model.workout.WorkoutViewModel
import com.android.streetworkapp.ui.navigation.NavigationActions
import com.android.streetworkapp.ui.navigation.Route
import com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.auth.FirebaseAuth
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
Expand Down Expand Up @@ -122,7 +125,8 @@ class End2EndWorkoutTraining {
workoutViewModel,
TextModerationViewModel(mock(TextModerationRepository::class.java)),
mock(ImageViewModel::class.java),
PreferencesViewModel(mock(PreferencesRepository::class.java)))
PreferencesViewModel(mock(PreferencesRepository::class.java)),
GoogleAuthService("abc", mock(FirebaseAuth::class.java), LocalContext.current))
}
NavigationActions(testNavController).apply {
composeTestRule.waitForIdle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertCountEquals
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
Expand Down Expand Up @@ -34,6 +35,8 @@ 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 com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.auth.FirebaseAuth
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
Expand Down Expand Up @@ -128,6 +131,8 @@ class BottomNavigationTest {
TextModerationViewModel(mock(TextModerationRepository::class.java, RETURNS_DEFAULTS)),
ImageViewModel(mock(ImageRepository::class.java)),
PreferencesViewModel(mock(PreferencesRepository::class.java)),
GoogleAuthService(
"abc", mock(FirebaseAuth::class.java, RETURNS_DEFAULTS), LocalContext.current),
true)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.android.streetworkapp.ui.navigation

import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertTextEquals
Expand All @@ -25,6 +26,8 @@ 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 com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.auth.FirebaseAuth
import io.mockk.mockk
import org.junit.Rule
import org.junit.Test
Expand Down Expand Up @@ -65,6 +68,8 @@ class TopAppBarTest {
TextModerationViewModel(mock(TextModerationRepository::class.java)),
ImageViewModel(mock(ImageRepository::class.java)),
PreferencesViewModel(mock(PreferencesRepository::class.java)),
GoogleAuthService(
"abc", mock(FirebaseAuth::class.java, RETURNS_DEFAULTS), LocalContext.current),
true)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,31 @@ import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.sample.R
import com.android.streetworkapp.model.preferences.PreferencesRepository
import com.android.streetworkapp.model.preferences.PreferencesViewModel
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.ui.navigation.NavigationActions
import com.android.streetworkapp.ui.navigation.Route
import com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.auth.FirebaseAuth
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mockito.RETURNS_DEFAULTS
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify

@RunWith(AndroidJUnit4::class)
class SettingsTest {

@get:Rule val composeTestRule = createComposeRule()

private val navigationActions = Mockito.mock(NavigationActions::class.java)
private val userRepository = Mockito.mock(UserRepository::class.java)
private val navigationActions = mock(NavigationActions::class.java)
private val userRepository = mock(UserRepository::class.java)
private val userViewModel = UserViewModel(userRepository)
private val preferencesViewModel = PreferencesViewModel(mock(PreferencesRepository::class.java))

@Test
fun isSettingsContentDisplayedForNullUser() {
Expand All @@ -37,7 +45,11 @@ class SettingsTest {
var context: Context? = null

composeTestRule.setContent {
SettingsContent(navigationActions, userViewModel, showSettingDialog)
val authService =
GoogleAuthService(
"abc", mock(FirebaseAuth::class.java, RETURNS_DEFAULTS), LocalContext.current)
SettingsContent(
navigationActions, userViewModel, preferencesViewModel, authService, showSettingDialog)
context = LocalContext.current
}

Expand Down Expand Up @@ -70,7 +82,11 @@ class SettingsTest {
userViewModel.setCurrentUser(alice)

composeTestRule.setContent {
SettingsContent(navigationActions, userViewModel, showSettingDialog)
val authService =
GoogleAuthService(
"abc", mock(FirebaseAuth::class.java, RETURNS_DEFAULTS), LocalContext.current)
SettingsContent(
navigationActions, userViewModel, preferencesViewModel, authService, showSettingDialog)
context = LocalContext.current
}

Expand All @@ -89,4 +105,28 @@ class SettingsTest {

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

@Test
fun testLogoutButtonNavigatesToAuthScreen() {
val showSettingDialog = mutableStateOf(false)
var context: Context? = null
val alice = User("uid-alice", "Alice", "alice@gmail.com", 42, emptyList(), "")
userViewModel.setCurrentUser(alice)

composeTestRule.setContent {
val authService =
GoogleAuthService(
"abc", mock(FirebaseAuth::class.java, RETURNS_DEFAULTS), LocalContext.current)
SettingsContent(
navigationActions, userViewModel, preferencesViewModel, authService, showSettingDialog)
context = LocalContext.current
}

// Click the logout button
composeTestRule.onNodeWithTag("LogOutButton").performClick()
composeTestRule.waitForIdle()

// Verify that the navigation action to the AUTH screen was called
verify(navigationActions).navigateTo(Route.AUTH)
}
}
21 changes: 18 additions & 3 deletions app/src/main/java/com/android/streetworkapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import androidx.navigation.navigation
import com.android.sample.R
import com.android.streetworkapp.device.network.isInternetAvailable
import com.android.streetworkapp.model.event.EventRepositoryFirestore
import com.android.streetworkapp.model.event.EventViewModel
Expand Down Expand Up @@ -80,8 +82,10 @@ import com.android.streetworkapp.ui.tutorial.TutorialEvent
import com.android.streetworkapp.ui.utils.CustomDialog
import com.android.streetworkapp.ui.utils.DialogType
import com.android.streetworkapp.ui.utils.trainComposable
import com.android.streetworkapp.utils.GoogleAuthService
import com.google.firebase.auth.ktx.auth
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.serialization.json.JsonNull.content
import com.google.firebase.ktx.Firebase
import okhttp3.OkHttpClient

class MainActivity : ComponentActivity() {
Expand Down Expand Up @@ -146,6 +150,10 @@ fun StreetWorkAppMain(
val imageRepository = ImageRepositoryFirestore(firestoreDB, parkRepository, userRepository)
val imageViewModel = ImageViewModel(imageRepository)

// Instantiate Google Auth Service
val token = stringResource(R.string.default_web_client_id)
val authService = GoogleAuthService(token, Firebase.auth, LocalContext.current)

// Get the preferences cached parameters
val loginState by preferencesViewModel.loginState.collectAsState()
val uid by preferencesViewModel.uid.collectAsState()
Expand Down Expand Up @@ -199,6 +207,7 @@ fun StreetWorkAppMain(
textModerationViewModel,
imageViewModel,
preferencesViewModel,
authService,
startDestination = resolvedStartDestination!!)
}
}
Expand All @@ -218,6 +227,7 @@ fun StreetWorkApp(
textModerationViewModel: TextModerationViewModel,
imageViewModel: ImageViewModel,
preferencesViewModel: PreferencesViewModel,
authService: GoogleAuthService,
navTestInvokationOnEachRecompose: Boolean = false,
e2eEventTesting: Boolean = false,
startDestination: String = Route.AUTH
Expand Down Expand Up @@ -305,7 +315,7 @@ fun StreetWorkApp(
route = Route.AUTH,
) {
composable(Screen.AUTH) {
SignInScreen(navigationActions, userViewModel, preferencesViewModel)
SignInScreen(navigationActions, userViewModel, preferencesViewModel, authService)
}
}
navigation(startDestination = Screen.PROGRESSION, route = Route.PROGRESSION) {
Expand Down Expand Up @@ -389,7 +399,12 @@ fun StreetWorkApp(
tag = "Settings",
title = "Settings",
Content = {
SettingsContent(navigationActions, userViewModel, showSettingsDialog)
SettingsContent(
navigationActions,
userViewModel,
preferencesViewModel,
authService,
showSettingsDialog)
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ open class UserViewModel(private val repository: UserRepository) : ViewModel() {
val userList: StateFlow<List<User?>>
get() = _userList

/**
* Sets the user to the provided User object.
*
* @param user The User object to set as the user.
*/
fun setUser(user: User?) {
_user.value = user
}

/**
* Sets the current user to the provided User object.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,13 @@ import com.android.streetworkapp.utils.GoogleAuthService
@Composable
fun GoogleAuthButton(
authService: GoogleAuthService,
context: android.content.Context,
launcher: ManagedActivityResultLauncher<Intent, ActivityResult>
) {

Button(
onClick = {
Log.d("SignInScreen", "Start sign-in")
authService.launchSignIn(context, launcher)
authService.launchSignIn(launcher)
},
modifier =
Modifier.width(250.dp)
Expand Down
Loading
Loading