feat: add persistent interface settings
This commit is contained in:
+111
@@ -0,0 +1,111 @@
|
||||
package com.flagship.abox.manager.ui.preferences
|
||||
|
||||
import com.flagship.abox.manager.R
|
||||
import com.flagship.abox.manager.preferences.AppThemeMode
|
||||
import com.flagship.abox.manager.preferences.DesignRenderer
|
||||
import com.flagship.abox.manager.ui.common.UiText.StringResource
|
||||
import com.flagship.abox.manager.preferences.NavigationPresentation
|
||||
import com.flagship.abox.manager.preferences.UiPreferences
|
||||
import com.flagship.abox.manager.preferences.UiPreferencesRepository
|
||||
import com.flagship.abox.manager.preferences.UiPreferencesWriteResult
|
||||
import com.flagship.abox.manager.testing.MainDispatcherRule
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class SettingsViewModelTest {
|
||||
@get:Rule
|
||||
val mainDispatcherRule = MainDispatcherRule()
|
||||
|
||||
@Test
|
||||
fun rendererUpdatePersistsWithoutCallingSessionCoordinator() = runTest {
|
||||
val repository = RecordingUiPreferencesRepository()
|
||||
val viewModel = SettingsViewModel(repository)
|
||||
advanceUntilIdle()
|
||||
|
||||
viewModel.onAction(SettingsUiAction.SetRenderer(DesignRenderer.MIUIX))
|
||||
advanceUntilIdle()
|
||||
|
||||
assertEquals(1, repository.updateCalls.size)
|
||||
assertEquals(DesignRenderer.MIUIX, repository.value.renderer)
|
||||
assertEquals(DesignRenderer.MIUIX, viewModel.uiState.value.preferences.renderer)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeFailureLeavesLastValueAndShowsLocalizedError() = runTest {
|
||||
val repository = RecordingUiPreferencesRepository(
|
||||
initial = UiPreferences(renderer = DesignRenderer.MATERIAL3),
|
||||
writeResult = UiPreferencesWriteResult.Failure,
|
||||
)
|
||||
val viewModel = SettingsViewModel(repository)
|
||||
advanceUntilIdle()
|
||||
|
||||
viewModel.onAction(SettingsUiAction.SetRenderer(DesignRenderer.MIUIX))
|
||||
advanceUntilIdle()
|
||||
|
||||
assertEquals(1, repository.updateCalls.size)
|
||||
assertEquals(DesignRenderer.MATERIAL3, viewModel.uiState.value.preferences.renderer)
|
||||
assertTrue(viewModel.uiState.value.error is StringResource)
|
||||
assertEquals(
|
||||
R.string.settings_error_save,
|
||||
(viewModel.uiState.value.error as StringResource).resId,
|
||||
)
|
||||
assertTrue(viewModel.uiState.value.saving.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun collectsRepositoryChanges() = runTest {
|
||||
val repository = RecordingUiPreferencesRepository()
|
||||
val viewModel = SettingsViewModel(repository)
|
||||
advanceUntilIdle()
|
||||
|
||||
repository.emit(
|
||||
UiPreferences(
|
||||
renderer = DesignRenderer.MIUIX,
|
||||
themeMode = AppThemeMode.DARK,
|
||||
dynamicColorEnabled = false,
|
||||
blurEnabled = true,
|
||||
navigationPresentation = NavigationPresentation.FLOATING,
|
||||
hapticsEnabled = false,
|
||||
),
|
||||
)
|
||||
advanceUntilIdle()
|
||||
|
||||
assertTrue(viewModel.uiState.value.loaded)
|
||||
assertEquals(repository.value, viewModel.uiState.value.preferences)
|
||||
}
|
||||
|
||||
|
||||
private class RecordingUiPreferencesRepository(
|
||||
initial: UiPreferences = UiPreferences(),
|
||||
private val writeResult: UiPreferencesWriteResult = UiPreferencesWriteResult.Success,
|
||||
) : UiPreferencesRepository {
|
||||
private val state = MutableStateFlow(initial)
|
||||
val updateCalls = mutableListOf<(UiPreferences) -> UiPreferences>()
|
||||
val value: UiPreferences get() = state.value
|
||||
|
||||
override fun observe(): Flow<UiPreferences> = state.asStateFlow()
|
||||
|
||||
override suspend fun update(
|
||||
transform: (UiPreferences) -> UiPreferences,
|
||||
): UiPreferencesWriteResult {
|
||||
updateCalls += transform
|
||||
if (writeResult is UiPreferencesWriteResult.Success) {
|
||||
state.value = transform(state.value)
|
||||
}
|
||||
return writeResult
|
||||
}
|
||||
|
||||
fun emit(value: UiPreferences) {
|
||||
state.value = value
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user