Batch 9/9 (final) of the Robolectric Compose JVM-test epic (#373). Closes#384.
What
AppLockGateHostJvmTest — drives the app-lock gate host on the JVM (v2 createComposeRule under Robolectric, no emulator), covering the Unlocked / Checking / Locked render branches, the "content stays composed after re-lock" latch (hasEverUnlocked), and the no-FragmentActivity auth-error path. AppLockViewModel is mocked. → drops **/AppLockGateHost* from jacocoNonJvmTestableSurface.
LibreMailAppJvmTest — covers the JVM-tractable parts of LibreMailApp.kt: LibreMailBottomBar, StartupCrashPrompt (+ its dialog buttons: review / not-now / discard), and LibreMailApp's cold-start "hold until known" guards.
LibreMailApp stays excluded (the acceptable exception)
Per #384's notes, LibreMailApp itself is a real NavHost whose non-onboarding start destinations call hiltViewModel(), and standing the graph up needs ViewModelStoreOwner / SavedStateRegistryOwner / OnBackPressedDispatcherOwner that a plain JVM compose rule doesn't surface. Graph-level navigation therefore stays covered by the instrumented OnboardingFlowTest; the **/LibreMailApp* glob is kept (documented inline in the jacoco list), while its tractable render/callback logic is still exercised by LibreMailAppJvmTest.
The instrumented LibreMailBottomBarTest / StartupCrashPromptTest stay as the on-device E2E.
Gate
assembleDebug + testDebugUnitTest (14 new tests, all green) + jacocoTestCoverageVerification + compileDebugAndroidTestKotlin + lintDebug + ktlintCheck + detekt — all pass. JaCoCo floor unchanged (0.79); scoped line coverage 0.8426.
Batch **9/9 (final)** of the Robolectric Compose JVM-test epic (#373). Closes #384.
## What
- **`AppLockGateHostJvmTest`** — drives the app-lock gate host on the JVM (v2 `createComposeRule` under Robolectric, no emulator), covering the `Unlocked` / `Checking` / `Locked` render branches, the "content stays composed after re-lock" latch (`hasEverUnlocked`), and the no-`FragmentActivity` auth-error path. `AppLockViewModel` is mocked. → drops `**/AppLockGateHost*` from `jacocoNonJvmTestableSurface`.
- **`LibreMailAppJvmTest`** — covers the JVM-tractable parts of `LibreMailApp.kt`: `LibreMailBottomBar`, `StartupCrashPrompt` (+ its dialog buttons: review / not-now / discard), and `LibreMailApp`'s cold-start "hold until known" guards.
## `LibreMailApp` stays excluded (the acceptable exception)
Per #384's notes, `LibreMailApp` itself is a real `NavHost` whose non-onboarding start destinations call `hiltViewModel()`, and standing the graph up needs `ViewModelStoreOwner` / `SavedStateRegistryOwner` / `OnBackPressedDispatcherOwner` that a plain JVM compose rule doesn't surface. Graph-level navigation therefore stays covered by the instrumented `OnboardingFlowTest`; the `**/LibreMailApp*` glob is **kept** (documented inline in the jacoco list), while its tractable render/callback logic is still exercised by `LibreMailAppJvmTest`.
The instrumented `LibreMailBottomBarTest` / `StartupCrashPromptTest` stay as the on-device E2E.
## Gate
`assembleDebug` + `testDebugUnitTest` (14 new tests, all green) + `jacocoTestCoverageVerification` + `compileDebugAndroidTestKotlin` + `lintDebug` + `ktlintCheck` + `detekt` — all pass. JaCoCo floor **unchanged (0.79)**; scoped line coverage **0.8426**.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Tick the box to add this pull request to the merge queue (same as @mergifyio queue).
Queue this pull request
Tick the box to add this pull request to the merge queue (same as `@mergifyio queue`).
- [ ] Queue this pull request <!-- mergify:queue-control:queue -->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Batch 9/9 (final) of the Robolectric Compose JVM-test epic (#373). Closes #384.
What
AppLockGateHostJvmTest— drives the app-lock gate host on the JVM (v2createComposeRuleunder Robolectric, no emulator), covering theUnlocked/Checking/Lockedrender branches, the "content stays composed after re-lock" latch (hasEverUnlocked), and the no-FragmentActivityauth-error path.AppLockViewModelis mocked. → drops**/AppLockGateHost*fromjacocoNonJvmTestableSurface.LibreMailAppJvmTest— covers the JVM-tractable parts ofLibreMailApp.kt:LibreMailBottomBar,StartupCrashPrompt(+ its dialog buttons: review / not-now / discard), andLibreMailApp's cold-start "hold until known" guards.LibreMailAppstays excluded (the acceptable exception)Per #384's notes,
LibreMailAppitself is a realNavHostwhose non-onboarding start destinations callhiltViewModel(), and standing the graph up needsViewModelStoreOwner/SavedStateRegistryOwner/OnBackPressedDispatcherOwnerthat a plain JVM compose rule doesn't surface. Graph-level navigation therefore stays covered by the instrumentedOnboardingFlowTest; the**/LibreMailApp*glob is kept (documented inline in the jacoco list), while its tractable render/callback logic is still exercised byLibreMailAppJvmTest.The instrumented
LibreMailBottomBarTest/StartupCrashPromptTeststay as the on-device E2E.Gate
assembleDebug+testDebugUnitTest(14 new tests, all green) +jacocoTestCoverageVerification+compileDebugAndroidTestKotlin+lintDebug+ktlintCheck+detekt— all pass. JaCoCo floor unchanged (0.79); scoped line coverage 0.8426.🤖 Generated with Claude Code
Tick the box to add this pull request to the merge queue (same as
@mergifyio queue).