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.
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)
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 3/9 of the Robolectric JVM Compose umbrella (#373). Converts the
account-setup screens to Robolectric JVM Compose tests and drops them from
jacocoNonJvmTestableSurfaceso their render/interaction code counts toward theJVM-testable coverage surface.
Files covered (removed from
jacocoNonJvmTestableSurface)AccountPickerScreenAccountPickerScreenJvmTest(9 tests)AppPasswordSetupScreenAppPasswordSetupScreenJvmTest(12 tests)ManualSetupScreenManualSetupScreenJvmTest(9 tests)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 thetest(JVM) source set — no emulator. Perscreen:
ViewModelis mocked (its own logic stays covered by the existing*ViewModelTests), exposing theStateFlowform/state so every branch —render, per-provider chrome, unknown-provider fallback, credential/submit
wiring, and the enabled/busy/error/done states — is driven deterministically;
LifecycleOwneris provided forcollectAsStateWithLifecycle;AccountPickerScreengets a no-opActivityResultRegistryso the Outlooklauncher never surfaces a real activity/browser;
AppPasswordSetupScreengets a recordingUriHandlerso the app-password /two-factor help links are asserted without opening a browser.
The instrumented
androidTestE2Es (AccountPickerScreenTest,AppPasswordSetupScreenTest,ManualSetupScreenTest) stay as the on-devicecoverage, including the Espresso-Intents Outlook/help-link launches.
Coverage / gate
jacocoLineCoverageFloorstays0.79(there-ratchet is the final #373 step). The
isIncludeNoLocationClassesfix from#394 is already in main and untouched here.
screens join the counted surface).
assembleDebug+testDebugUnitTest+jacocoTestCoverageVerification+compileDebugAndroidTestKotlin+lintDebug+ktlintCheck+detekt.🤖 Generated with Claude Code