Files
minstrel/android
bvandeusen 0ea0fbf8be feat(android): LibraryViewModel + UiState + MainDispatcherExtension (M8 phase 5.3)
First Hilt-injected ViewModel + sealed UiState pattern.

LibraryUiState (sealed interface): Loading / Empty / Success / Error.
The cases are exhaustive so Compose `when` blocks the compiler checks.

LibraryViewModel:
  - combine(observeArtists, observeAlbums) → Success/Empty decision
  - .catch translates upstream Flow exceptions to UiState.Error
  - .stateIn(viewModelScope, WhileSubscribed(5_000), Loading) — the
    standard Compose-friendly pattern; subscriptions tear down 5s after
    the last collector to ride out config changes without hanging the
    DAO Flow forever.

MainDispatcherExtension — JUnit 5 equivalent of the JUnit 4
MainDispatcherRule pattern (audit-deferred item; trigger met). Swaps
Dispatchers.Main for UnconfinedTestDispatcher in beforeEach +
resetMain in afterEach. Apply with `@ExtendWith`.

LibraryViewModelTest covers all four UiState cases — initial Loading,
empty cache (Empty), populated cache (Success), and an upstream Flow
exception (Error). MockK for the repo, Turbine for the Flow assertions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 22:38:59 -04:00
..