Follow-up to lane 5 (#250 / PR #274): adds instrumented Compose UI tests for the screens that still lacked one, so lane 6's ui-package coverage ratchet (#251, >=95%) can pass. Each follows the lane-5 pattern — createAndroidComposeRule<ComponentActivity> + real ViewModel over a fake/in-memory repo.
Covered (6/6 targets — all 23 tests green locally on an API 36 emulator)
ColorSwatchRow (compose/format) — none entry + swatch rendering, select-argb / select-null callbacks, and selected-state semantics (driven in isolation like ParagraphAlignmentControlTest).
LockScreen — locked title/body always shown, optional error text only when non-null, unlock callback.
AddAnotherAccountScreen — confirmation + both onboarding choices route to their callbacks. (Listed in #275 as "launcher-heavy", but it is actually purely presentational — no intent stubbing needed.)
SignatureEditScreen — real SignatureEditViewModel over an in-memory Room-backed SignatureRepository: new-vs-edit title, create round-trip (first signature becomes default), existing-name prefill, and edit-update round-trip.
ReportReviewScreen — real ReportReviewViewModel over a file-backed ReportStore (submitter stubbed disabled, WorkManager upload out of scope): disclaimer/fields render, Submit gated on min comment length + email validity, discard deletes the report and leaves the screen.
AppPasswordSetupScreen — real AppPasswordViewModel over FakeAccountRepository: provider chrome + credential entry persists and reports the new account id; the "create an app password" help link is asserted via Espresso-Intents (Intents.init/intending/intended, mirroring AccountPickerScreenTest's Outlook test) so no real browser opens.
Skipped
None — no target required a live permission grant.
Local validation
compileDebugAndroidTestKotlin + ktlintCheck + detekt green; the 6 new classes (23 tests) ran green on a Pixel API 36 emulator (0 failed, 0 skipped).
Closes #275
Follow-up to lane 5 (#250 / PR #274): adds instrumented Compose UI tests for the screens that still lacked one, so lane 6's ui-package coverage ratchet (#251, >=95%) can pass. Each follows the lane-5 pattern — `createAndroidComposeRule<ComponentActivity>` + real ViewModel over a fake/in-memory repo.
### Covered (6/6 targets — all 23 tests green locally on an API 36 emulator)
- **`ColorSwatchRow`** (`compose/format`) — none entry + swatch rendering, select-argb / select-null callbacks, and selected-state semantics (driven in isolation like `ParagraphAlignmentControlTest`).
- **`LockScreen`** — locked title/body always shown, optional error text only when non-null, unlock callback.
- **`AddAnotherAccountScreen`** — confirmation + both onboarding choices route to their callbacks. (Listed in #275 as "launcher-heavy", but it is actually purely presentational — no intent stubbing needed.)
- **`SignatureEditScreen`** — real `SignatureEditViewModel` over an in-memory Room-backed `SignatureRepository`: new-vs-edit title, create round-trip (first signature becomes default), existing-name prefill, and edit-update round-trip.
- **`ReportReviewScreen`** — real `ReportReviewViewModel` over a file-backed `ReportStore` (submitter stubbed disabled, WorkManager upload out of scope): disclaimer/fields render, Submit gated on min comment length + email validity, discard deletes the report and leaves the screen.
- **`AppPasswordSetupScreen`** — real `AppPasswordViewModel` over `FakeAccountRepository`: provider chrome + credential entry persists and reports the new account id; the "create an app password" help link is asserted via **Espresso-Intents** (`Intents.init`/`intending`/`intended`, mirroring `AccountPickerScreenTest`'s Outlook test) so no real browser opens.
### Skipped
None — no target required a live permission grant.
### Local validation
`compileDebugAndroidTestKotlin` + `ktlintCheck` + `detekt` green; the 6 new classes (23 tests) ran green on a Pixel API 36 emulator (0 failed, 0 skipped).
🤖 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.
Closes #275
Follow-up to lane 5 (#250 / PR #274): adds instrumented Compose UI tests for the screens that still lacked one, so lane 6's ui-package coverage ratchet (#251, >=95%) can pass. Each follows the lane-5 pattern —
createAndroidComposeRule<ComponentActivity>+ real ViewModel over a fake/in-memory repo.Covered (6/6 targets — all 23 tests green locally on an API 36 emulator)
ColorSwatchRow(compose/format) — none entry + swatch rendering, select-argb / select-null callbacks, and selected-state semantics (driven in isolation likeParagraphAlignmentControlTest).LockScreen— locked title/body always shown, optional error text only when non-null, unlock callback.AddAnotherAccountScreen— confirmation + both onboarding choices route to their callbacks. (Listed in #275 as "launcher-heavy", but it is actually purely presentational — no intent stubbing needed.)SignatureEditScreen— realSignatureEditViewModelover an in-memory Room-backedSignatureRepository: new-vs-edit title, create round-trip (first signature becomes default), existing-name prefill, and edit-update round-trip.ReportReviewScreen— realReportReviewViewModelover a file-backedReportStore(submitter stubbed disabled, WorkManager upload out of scope): disclaimer/fields render, Submit gated on min comment length + email validity, discard deletes the report and leaves the screen.AppPasswordSetupScreen— realAppPasswordViewModeloverFakeAccountRepository: provider chrome + credential entry persists and reports the new account id; the "create an app password" help link is asserted via Espresso-Intents (Intents.init/intending/intended, mirroringAccountPickerScreenTest's Outlook test) so no real browser opens.Skipped
None — no target required a live permission grant.
Local validation
compileDebugAndroidTestKotlin+ktlintCheck+detektgreen; the 6 new classes (23 tests) ran green on a Pixel API 36 emulator (0 failed, 0 skipped).🤖 Generated with Claude Code