android: add logout flow with full local session cleanup
Some checks are pending
CI / test (push) Has started running

This commit is contained in:
Codex
2026-03-09 15:09:10 +03:00
parent 33514265e3
commit d7dfda1d31
15 changed files with 230 additions and 5 deletions

View File

@@ -49,6 +49,18 @@ class DataStoreNotificationSettingsRepositoryTest {
assertTrue(mode == ChatNotificationOverride.DEFAULT)
}
@Test
fun clearChatOverrides_removesAllPerChatModes() = runTest {
val repository = DataStoreNotificationSettingsRepository(createTestDataStore())
repository.setChatOverride(chatId = 1L, mode = ChatNotificationOverride.MUTED)
repository.setChatOverride(chatId = 2L, mode = ChatNotificationOverride.ENABLED)
repository.clearChatOverrides()
assertEquals(ChatNotificationOverride.DEFAULT, repository.getChatOverride(chatId = 1L))
assertEquals(ChatNotificationOverride.DEFAULT, repository.getChatOverride(chatId = 2L))
}
private fun createTestDataStore(): DataStore<Preferences> {
return InMemoryPreferencesDataStore()
}

View File

@@ -0,0 +1,99 @@
package ru.daemonlord.messenger.domain.auth.usecase
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Test
import ru.daemonlord.messenger.core.notifications.ActiveChatTracker
import ru.daemonlord.messenger.domain.auth.repository.AuthRepository
import ru.daemonlord.messenger.domain.auth.repository.SessionCleanupRepository
import ru.daemonlord.messenger.domain.common.AppResult
import ru.daemonlord.messenger.domain.realtime.RealtimeManager
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import ru.daemonlord.messenger.domain.auth.model.AuthSession
import ru.daemonlord.messenger.domain.auth.model.AuthUser
import ru.daemonlord.messenger.domain.realtime.model.RealtimeEvent
@OptIn(ExperimentalCoroutinesApi::class)
class LogoutUseCaseTest {
@Test
fun invoke_disconnectsRealtime_clearsSessionAndAuth() = runTest {
val authRepository = FakeAuthRepository()
val cleanupRepository = FakeSessionCleanupRepository()
val realtimeManager = FakeRealtimeManager()
val activeChatTracker = ActiveChatTracker().apply { setActiveChat(42L) }
val useCase = LogoutUseCase(
authRepository = authRepository,
sessionCleanupRepository = cleanupRepository,
realtimeManager = realtimeManager,
activeChatTracker = activeChatTracker,
)
useCase()
assertEquals(true, realtimeManager.disconnected)
assertEquals(true, authRepository.loggedOut)
assertEquals(true, cleanupRepository.cleaned)
assertEquals(null, activeChatTracker.activeChatId.value)
}
private class FakeAuthRepository : AuthRepository {
var loggedOut: Boolean = false
override suspend fun login(email: String, password: String): AppResult<AuthUser> {
return AppResult.Error(ru.daemonlord.messenger.domain.common.AppError.Unknown(null))
}
override suspend fun refreshTokens(): AppResult<Unit> {
return AppResult.Success(Unit)
}
override suspend fun getMe(): AppResult<AuthUser> {
return AppResult.Error(ru.daemonlord.messenger.domain.common.AppError.Unknown(null))
}
override suspend fun restoreSession(): AppResult<AuthUser> {
return AppResult.Error(ru.daemonlord.messenger.domain.common.AppError.Unauthorized)
}
override suspend fun listSessions(): AppResult<List<AuthSession>> {
return AppResult.Success(emptyList())
}
override suspend fun revokeSession(jti: String): AppResult<Unit> {
return AppResult.Success(Unit)
}
override suspend fun revokeAllSessions(): AppResult<Unit> {
return AppResult.Success(Unit)
}
override suspend fun logout() {
loggedOut = true
}
}
private class FakeSessionCleanupRepository : SessionCleanupRepository {
var cleaned: Boolean = false
override suspend fun clearLocalSessionData() {
cleaned = true
}
}
private class FakeRealtimeManager : RealtimeManager {
var disconnected: Boolean = false
private val eventsFlow = MutableStateFlow<RealtimeEvent>(RealtimeEvent.Ignored)
override val events: Flow<RealtimeEvent> = eventsFlow
override fun connect() = Unit
override fun disconnect() {
disconnected = true
}
}
}

View File

@@ -87,6 +87,9 @@ class ShouldShowMessageNotificationUseCaseTest {
override suspend fun clearChatOverride(chatId: Long) {
chatOverrides.remove(chatId)
}
override suspend fun clearChatOverrides() {
chatOverrides.clear()
}
}
}