android: add datastore notification settings and gating usecase
Some checks failed
CI / test (push) Failing after 2m6s
Some checks failed
CI / test (push) Failing after 2m6s
This commit is contained in:
@@ -2,14 +2,14 @@ package ru.daemonlord.messenger.core.token
|
||||
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
|
||||
import androidx.datastore.preferences.core.emptyPreferences
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import okio.Path.Companion.toPath
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class DataStoreTokenRepositoryTest {
|
||||
@@ -46,10 +46,18 @@ class DataStoreTokenRepositoryTest {
|
||||
}
|
||||
|
||||
private fun createTestDataStore(): DataStore<Preferences> {
|
||||
val file = File.createTempFile("tokens", ".preferences_pb")
|
||||
file.deleteOnExit()
|
||||
return PreferenceDataStoreFactory.createWithPath(
|
||||
produceFile = { file.absolutePath.toPath() }
|
||||
)
|
||||
return InMemoryPreferencesDataStore()
|
||||
}
|
||||
|
||||
private class InMemoryPreferencesDataStore : DataStore<Preferences> {
|
||||
private val state = MutableStateFlow<Preferences>(emptyPreferences())
|
||||
|
||||
override val data: Flow<Preferences> = state
|
||||
|
||||
override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences {
|
||||
val updated = transform(state.value)
|
||||
state.value = updated
|
||||
return updated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package ru.daemonlord.messenger.data.notifications.repository
|
||||
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.emptyPreferences
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import ru.daemonlord.messenger.domain.notifications.model.ChatNotificationOverride
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class DataStoreNotificationSettingsRepositoryTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadGlobalSettings_returnsPersistedValues() = runTest {
|
||||
val repository = DataStoreNotificationSettingsRepository(createTestDataStore())
|
||||
|
||||
repository.setGlobalEnabled(enabled = false)
|
||||
repository.setPreviewEnabled(enabled = false)
|
||||
|
||||
val settings = repository.getSettings()
|
||||
assertFalse(settings.globalEnabled)
|
||||
assertFalse(settings.previewEnabled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAndReadChatOverride_returnsPersistedValue() = runTest {
|
||||
val repository = DataStoreNotificationSettingsRepository(createTestDataStore())
|
||||
|
||||
repository.setChatOverride(chatId = 42L, mode = ChatNotificationOverride.MUTED)
|
||||
|
||||
val mode = repository.getChatOverride(chatId = 42L)
|
||||
assertEquals(ChatNotificationOverride.MUTED, mode)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clearChatOverride_resetsToDefault() = runTest {
|
||||
val repository = DataStoreNotificationSettingsRepository(createTestDataStore())
|
||||
repository.setChatOverride(chatId = 42L, mode = ChatNotificationOverride.ENABLED)
|
||||
|
||||
repository.clearChatOverride(chatId = 42L)
|
||||
|
||||
val mode = repository.getChatOverride(chatId = 42L)
|
||||
assertTrue(mode == ChatNotificationOverride.DEFAULT)
|
||||
}
|
||||
|
||||
private fun createTestDataStore(): DataStore<Preferences> {
|
||||
return InMemoryPreferencesDataStore()
|
||||
}
|
||||
|
||||
private class InMemoryPreferencesDataStore : DataStore<Preferences> {
|
||||
private val state = MutableStateFlow<Preferences>(emptyPreferences())
|
||||
|
||||
override val data: Flow<Preferences> = state
|
||||
|
||||
override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences {
|
||||
val updated = transform(state.value)
|
||||
state.value = updated
|
||||
return updated
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package ru.daemonlord.messenger.domain.notifications.usecase
|
||||
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import ru.daemonlord.messenger.domain.notifications.model.ChatNotificationOverride
|
||||
import ru.daemonlord.messenger.domain.notifications.model.NotificationSettings
|
||||
import ru.daemonlord.messenger.domain.notifications.repository.NotificationSettingsRepository
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class ShouldShowMessageNotificationUseCaseTest {
|
||||
|
||||
@Test
|
||||
fun globalDisabled_blocksNotifications() = runTest {
|
||||
val repository = FakeNotificationSettingsRepository(
|
||||
settings = NotificationSettings(globalEnabled = false, previewEnabled = true),
|
||||
)
|
||||
val useCase = ShouldShowMessageNotificationUseCase(repository)
|
||||
|
||||
val result = useCase(chatId = 1L, isMention = true, serverMuted = false)
|
||||
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mutedChat_allowsMention() = runTest {
|
||||
val repository = FakeNotificationSettingsRepository(
|
||||
settings = NotificationSettings(globalEnabled = true, previewEnabled = true),
|
||||
overrides = mutableMapOf(1L to ChatNotificationOverride.MUTED),
|
||||
)
|
||||
val useCase = ShouldShowMessageNotificationUseCase(repository)
|
||||
|
||||
val result = useCase(chatId = 1L, isMention = true, serverMuted = true)
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun chatOverrideEnabled_unmutesServerMutedChat() = runTest {
|
||||
val repository = FakeNotificationSettingsRepository(
|
||||
settings = NotificationSettings(globalEnabled = true, previewEnabled = true),
|
||||
overrides = mutableMapOf(1L to ChatNotificationOverride.ENABLED),
|
||||
)
|
||||
val useCase = ShouldShowMessageNotificationUseCase(repository)
|
||||
|
||||
val result = useCase(chatId = 1L, isMention = false, serverMuted = true)
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
private class FakeNotificationSettingsRepository(
|
||||
settings: NotificationSettings,
|
||||
overrides: MutableMap<Long, ChatNotificationOverride> = mutableMapOf(),
|
||||
) : NotificationSettingsRepository {
|
||||
private val settingsFlow = MutableStateFlow(settings)
|
||||
private val chatOverrides = overrides
|
||||
|
||||
override fun observeSettings(): Flow<NotificationSettings> = settingsFlow
|
||||
|
||||
override suspend fun getSettings(): NotificationSettings = settingsFlow.value
|
||||
|
||||
override suspend fun setGlobalEnabled(enabled: Boolean) {
|
||||
settingsFlow.value = settingsFlow.value.copy(globalEnabled = enabled)
|
||||
}
|
||||
|
||||
override suspend fun setPreviewEnabled(enabled: Boolean) {
|
||||
settingsFlow.value = settingsFlow.value.copy(previewEnabled = enabled)
|
||||
}
|
||||
|
||||
override fun observeChatOverride(chatId: Long): Flow<ChatNotificationOverride> {
|
||||
return settingsFlow.map { chatOverrides[chatId] ?: ChatNotificationOverride.DEFAULT }
|
||||
}
|
||||
|
||||
override suspend fun getChatOverride(chatId: Long): ChatNotificationOverride {
|
||||
return chatOverrides[chatId] ?: ChatNotificationOverride.DEFAULT
|
||||
}
|
||||
|
||||
override suspend fun setChatOverride(chatId: Long, mode: ChatNotificationOverride) {
|
||||
chatOverrides[chatId] = mode
|
||||
}
|
||||
|
||||
override suspend fun clearChatOverride(chatId: Long) {
|
||||
chatOverrides.remove(chatId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user