test(compose): Robolectric JVM tests for onboarding & lock screens (#377) #396

Merged
JMR-dev merged 2 commits from test-377-robolectric-onboarding-lock into main 2026-07-07 02:25:50 +00:00
JMR-dev commented 2026-07-07 01:18:06 +00:00 (Migrated from github.com)

Batch 2/9 of the Robolectric JVM Compose test epic (#373). Converts the stateless onboarding + lock screens to Robolectric JVM Compose tests (v2 createComposeRule() under RobolectricTestRunner, test source set — no emulator) and drops each from jacocoNonJvmTestableSurface so its render/interaction code now counts as JVM-testable surface.

Screens covered (21 tests across 5 new files)

  • LockScreen — locked title/body, optional error text, unlock callback.
  • WelcomeContent + OnboardingWelcomeScreen — render + add-account. The wrapper's NotificationPermissionEffect launcher is wired to a no-op ActivityResultRegistry so no system permission dialog is surfaced on the JVM (WelcomeContent is also driven directly, as its instrumented test does).
  • LicenseScreen — the real bundled GPL-3.0 text (res/raw/license.txt) renders, Agree gated on scroll-to-end, Decline.
  • ContactsAccessContent + ContactsAccessScreen — the stateless content's skip / grant (done) / request / re-ask-rationale paths, plus the VM wrapper (allow → mark-requested → launch, skip/continue, ON_RESUME re-read) driven by a mocked OnboardingViewModel.
  • BatteryOptimizationScreen (whole file is the VM wrapper) — offered vs. "already unrestricted" done states; Take me there marks the prompt handled and resolves the settings intent; Not now finishes. Mocked OnboardingViewModel.

Notes

  • Removed from jacocoNonJvmTestableSurface: **/LockScreen*, **/OnboardingWelcomeScreen*, **/LicenseScreen*, **/ContactsAccessScreen*, **/BatteryOptimizationScreen*.
  • JaCoCo floor unchanged at 0.79 (the re-ratchet is the final epic step, #386). Scoped line coverage now 0.8288 (5557/6705), up from the 0.8021 baseline.
  • Contacts/Battery use a tall @Config display qualifier so their centered, non-scrolling columns fit without the lower controls clipping under Robolectric's small default viewport.
  • The instrumented androidTest tests are kept. They remain the coverage for LicenseScreen's system back press, which the v2 Robolectric compose rule does not surface a reliable dispatch hook for; the BackHandler registration line is still covered by rendering and onDecline by the Decline-button test.

Fast gate green: assembleDebug + testDebugUnitTest + jacocoTestCoverageVerification + compileDebugAndroidTestKotlin + lintDebug + ktlintCheck + detekt.

Closes #377.

🤖 Generated with Claude Code

Batch 2/9 of the Robolectric JVM Compose test epic (#373). Converts the stateless onboarding + lock screens to Robolectric JVM Compose tests (v2 `createComposeRule()` under `RobolectricTestRunner`, `test` source set — no emulator) and drops each from `jacocoNonJvmTestableSurface` so its render/interaction code now counts as JVM-testable surface. ### Screens covered (21 tests across 5 new files) - **`LockScreen`** — locked title/body, optional error text, unlock callback. - **`WelcomeContent` + `OnboardingWelcomeScreen`** — render + add-account. The wrapper's `NotificationPermissionEffect` launcher is wired to a no-op `ActivityResultRegistry` so no system permission dialog is surfaced on the JVM (`WelcomeContent` is also driven directly, as its instrumented test does). - **`LicenseScreen`** — the real bundled GPL-3.0 text (`res/raw/license.txt`) renders, Agree gated on scroll-to-end, Decline. - **`ContactsAccessContent` + `ContactsAccessScreen`** — the stateless content's skip / grant (done) / request / re-ask-rationale paths, plus the VM wrapper (allow → mark-requested → launch, skip/continue, ON_RESUME re-read) driven by a mocked `OnboardingViewModel`. - **`BatteryOptimizationScreen`** (whole file is the VM wrapper) — offered vs. "already unrestricted" done states; Take me there marks the prompt handled and resolves the settings intent; Not now finishes. Mocked `OnboardingViewModel`. ### Notes - Removed from `jacocoNonJvmTestableSurface`: `**/LockScreen*`, `**/OnboardingWelcomeScreen*`, `**/LicenseScreen*`, `**/ContactsAccessScreen*`, `**/BatteryOptimizationScreen*`. - **JaCoCo floor unchanged at 0.79** (the re-ratchet is the final epic step, #386). Scoped line coverage now **0.8288** (5557/6705), up from the 0.8021 baseline. - Contacts/Battery use a tall `@Config` display qualifier so their centered, non-scrolling columns fit without the lower controls clipping under Robolectric's small default viewport. - The instrumented `androidTest` tests are kept. They remain the coverage for `LicenseScreen`'s system back press, which the v2 Robolectric compose rule does not surface a reliable dispatch hook for; the `BackHandler` registration line is still covered by rendering and `onDecline` by the Decline-button test. Fast gate green: `assembleDebug` + `testDebugUnitTest` + `jacocoTestCoverageVerification` + `compileDebugAndroidTestKotlin` + `lintDebug` + `ktlintCheck` + `detekt`. Closes #377. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.