test(worldclock): make the seconds tests mean what they say
The no-re-emission check now waits for the write to be readable before asserting, and the seconds switch has its own settings test instead of riding in the clock-defaults one. WorldClockSource.state takes its refresh signal without a default, and ARCHITECTURE.md's slice count and alignedTicks guarantee match the code.
This commit is contained in:
1 parent
78da94d775
commit
d70d0c78da
4 files changed
+25
-8
No files matched your search
@@ -15,7 +15,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
@@ -64,7 +63,7 @@ internal class WorldClockSource @Inject constructor(
|
||||
* state and `distinctUntilChanged` only drops the odd early wake (D18).
|
||||
*/
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun state(refreshes: Flow<Unit> = emptyFlow()): Flow<WorldClockUiState.Loaded> =
|
||||
fun state(refreshes: Flow<Unit>): Flow<WorldClockUiState.Loaded> =
|
||||
combine(
|
||||
worldClocks.worldClocks(),
|
||||
storedHomeZoneId,
|
||||
|
||||
@@ -90,6 +90,9 @@ class ClockPrefsTest {
|
||||
assertThat(awaitItem()).isEqualTo(ClockDefaults())
|
||||
|
||||
prefs.setWorldClockSeconds(true)
|
||||
// Wait until the write is visible to a reader, so a re-emission of
|
||||
// the defaults would have had its chance to arrive.
|
||||
prefs.worldClockSeconds.first { it }
|
||||
|
||||
expectNoEvents()
|
||||
cancel()
|
||||
|
||||
@@ -119,7 +119,6 @@ class SettingsViewModelTest {
|
||||
viewModel.onSnoozeLimitChanged(2)
|
||||
viewModel.onVolumeRampChanged(30)
|
||||
viewModel.onDismissChallengeChanged(DismissChallenge.MATH)
|
||||
viewModel.onWorldClockSecondsChanged(true)
|
||||
advanceUntilIdle()
|
||||
|
||||
val defaults = (viewModel.state.value as SettingsUiState.Loaded).defaults
|
||||
@@ -128,9 +127,23 @@ class SettingsViewModelTest {
|
||||
assertThat(defaults.snoozeLimit).isEqualTo(2)
|
||||
assertThat(defaults.volumeRampSeconds).isEqualTo(30)
|
||||
assertThat(defaults.dismissChallenge).isEqualTo(DismissChallenge.MATH)
|
||||
assertThat((viewModel.state.value as SettingsUiState.Loaded).worldClockSeconds).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `the world clock's seconds switch writes through, apart from the defaults`(@TempDir tempDir: Path) =
|
||||
runTest(main.dispatcher) {
|
||||
val viewModel = collecting(newViewModel(tempDir))
|
||||
advanceUntilIdle()
|
||||
val defaultsBefore = (viewModel.state.value as SettingsUiState.Loaded).defaults
|
||||
|
||||
viewModel.onWorldClockSecondsChanged(true)
|
||||
advanceUntilIdle()
|
||||
|
||||
val loaded = viewModel.state.value as SettingsUiState.Loaded
|
||||
assertThat(loaded.worldClockSeconds).isTrue()
|
||||
assertThat(loaded.defaults).isEqualTo(defaultsBefore)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `choosing a default alarm ringtone writes through and closes the picker`(@TempDir tempDir: Path) =
|
||||
runTest(main.dispatcher) {
|
||||
|
||||
@@ -592,7 +592,7 @@ one anywhere under `domain/` or `ui/`.
|
||||
## 6. Preferences
|
||||
|
||||
One DataStore file, `clockula_prefs`, behind floret-kit's typed `PrefStore`.
|
||||
Four slices:
|
||||
Six slices:
|
||||
|
||||
| Slice | Keys | Owner |
|
||||
|---|---|---|
|
||||
@@ -1429,9 +1429,11 @@ nothing but `delay`, which makes it testable under `runTest`'s virtual clock.
|
||||
`alignedTicks(unit)` is the same seam for a readout of whole wall-clock units:
|
||||
after the immediate emission it waits `WallBoundaries.untilNext(now, unit)`,
|
||||
re-measured against `WallClock` after every wake, so it fires on the second or
|
||||
minute boundary itself and a long `delay` or a set clock does not accumulate.
|
||||
The world clock is its one caller (§16, "The cadence"), and it merges in
|
||||
`ClockChanges`, the system's own word that the clock or zone moved, so a long
|
||||
minute boundary itself and a `delay` that ran long does not accumulate. A
|
||||
clock set mid-wait is only caught up once that wait ends, so a caller on a
|
||||
long cadence restarts the flow on `ClockChanges`, the system's own word that
|
||||
the clock or zone moved. The world clock is its one caller (§16, "The
|
||||
cadence"), and does exactly that, so a long
|
||||
cadence never means a long wait for those.
|
||||
|
||||
### The dismiss challenge, and why it cannot strand anyone
|
||||
|
||||
Reference in new issue
Block a user