test(compose): Robolectric JVM tests for account setup screens (#378) #398

Merged
JMR-dev merged 1 commits from test-378-robolectric-account-setup into main 2026-07-07 01:54:48 +00:00
JMR-dev commented 2026-07-07 01:34:47 +00:00 (Migrated from github.com)

Batch 3/9 of the Robolectric JVM Compose umbrella (#373). Converts the
account-setup screens to Robolectric JVM Compose tests and drops them from
jacocoNonJvmTestableSurface so their render/interaction code counts toward the
JVM-testable coverage surface.

Files covered (removed from jacocoNonJvmTestableSurface)

Screen New JVM test Line coverage
AccountPickerScreen AccountPickerScreenJvmTest (9 tests) 98.9%
AppPasswordSetupScreen AppPasswordSetupScreenJvmTest (12 tests) 98.7%
ManualSetupScreen ManualSetupScreenJvmTest (9 tests) 98.5%

Approach

Follows the batch-1/#375 PoC and batch-2 (#377) patterns: each test drives the
real screen via the v2 androidx.compose.ui.test.junit4.v2.createComposeRule()
under @RunWith(RobolectricTestRunner) + @GraphicsMode(NATIVE) +
@Config(sdk = [36]), in the test (JVM) source set — no emulator. Per
screen:

  • the ViewModel is mocked (its own logic stays covered by the existing
    *ViewModelTests), exposing the StateFlow form/state so every branch —
    render, per-provider chrome, unknown-provider fallback, credential/submit
    wiring, and the enabled/busy/error/done states — is driven deterministically;
  • a RESUMED LifecycleOwner is provided for collectAsStateWithLifecycle;
  • AccountPickerScreen gets a no-op ActivityResultRegistry so the Outlook
    launcher never surfaces a real activity/browser;
  • AppPasswordSetupScreen gets a recording UriHandler so the app-password /
    two-factor help links are asserted without opening a browser.

The instrumented androidTest E2Es (AccountPickerScreenTest,
AppPasswordSetupScreenTest, ManualSetupScreenTest) stay as the on-device
coverage, including the Espresso-Intents Outlook/help-link launches.

Coverage / gate

  • Do NOT raise the floor — jacocoLineCoverageFloor stays 0.79 (the
    re-ratchet is the final #373 step). The isIncludeNoLocationClasses fix from
    #394 is already in main and untouched here.
  • Overall line coverage holds/improves at 83.15% (the three ~99%-covered
    screens join the counted surface).
  • Full fast gate green locally: assembleDebug + testDebugUnitTest +
    jacocoTestCoverageVerification + compileDebugAndroidTestKotlin +
    lintDebug + ktlintCheck + detekt.

🤖 Generated with Claude Code

Batch 3/9 of the Robolectric JVM Compose umbrella (#373). Converts the account-setup screens to Robolectric JVM Compose tests and drops them from `jacocoNonJvmTestableSurface` so their render/interaction code counts toward the JVM-testable coverage surface. ## Files covered (removed from `jacocoNonJvmTestableSurface`) | Screen | New JVM test | Line coverage | | --- | --- | --- | | `AccountPickerScreen` | `AccountPickerScreenJvmTest` (9 tests) | 98.9% | | `AppPasswordSetupScreen` | `AppPasswordSetupScreenJvmTest` (12 tests) | 98.7% | | `ManualSetupScreen` | `ManualSetupScreenJvmTest` (9 tests) | 98.5% | ## Approach Follows the batch-1/#375 PoC and batch-2 (#377) patterns: each test drives the real screen via the v2 `androidx.compose.ui.test.junit4.v2.createComposeRule()` under `@RunWith(RobolectricTestRunner)` + `@GraphicsMode(NATIVE)` + `@Config(sdk = [36])`, in the **`test`** (JVM) source set — no emulator. Per screen: - the `ViewModel` is mocked (its own logic stays covered by the existing `*ViewModelTest`s), exposing the `StateFlow` form/state so every branch — render, per-provider chrome, unknown-provider fallback, credential/submit wiring, and the enabled/busy/error/done states — is driven deterministically; - a RESUMED `LifecycleOwner` is provided for `collectAsStateWithLifecycle`; - `AccountPickerScreen` gets a no-op `ActivityResultRegistry` so the Outlook launcher never surfaces a real activity/browser; - `AppPasswordSetupScreen` gets a recording `UriHandler` so the app-password / two-factor help links are asserted without opening a browser. The instrumented `androidTest` E2Es (`AccountPickerScreenTest`, `AppPasswordSetupScreenTest`, `ManualSetupScreenTest`) stay as the on-device coverage, including the Espresso-Intents Outlook/help-link launches. ## Coverage / gate - **Do NOT raise the floor** — `jacocoLineCoverageFloor` stays `0.79` (the re-ratchet is the final #373 step). The `isIncludeNoLocationClasses` fix from #394 is already in main and untouched here. - Overall line coverage holds/improves at **83.15%** (the three ~99%-covered screens join the counted surface). - Full fast gate green locally: `assembleDebug` + `testDebugUnitTest` + `jacocoTestCoverageVerification` + `compileDebugAndroidTestKotlin` + `lintDebug` + `ktlintCheck` + `detekt`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.