Closes the cleanly JVM-testable coverage gaps from the Phase-2 JaCoCo audit. All changes are test-only (7 existing suites extended, 2 net-new); no production code touched. Each targeted class reached 100% line coverage (source-file aggregate), comfortably clearing the ~95% bar.
Class
Before
After
data/settings/AccountSettingsRepository
38.5%
100%
data/settings/SignatureRepository
63.2%
100%
data/security/CredentialStore (new)
0%
100%
data/security/EncryptedCacheGuard (new)
0%
100%
data/attachment/AttachmentUriGrants
5.3%
100%
data/sync/SyncScheduler
90.2%
100%
ui/lock/AppLockViewModel
92.8%
100%
mail/SmtpSender
91.8%
100%
ui/reporting/StartupReportViewModel
93.3%
100%
What each test adds
AccountSettingsRepository — observe Flow (Turbine) + the sibling setters (setSignatureEnabled/setNotificationsEnabled/setRetentionCount/setRetentionMonths, including the negative-clamp and null-inherit cases).
SignatureRepository — observeForAccount/get/getDefault/update (+ the no-op-for-unknown-id branch) and the toDomain mapping.
CredentialStore (new) — encrypt-on-save / decrypt-on-load / null-on-missing / delete, with KeystoreCrypto mocked as identity (the AES-GCM round-trip is device-bound).
EncryptedCacheGuard (new) — the full isCacheLocked() truth table over appLock/encryptCache/isUnlocked.
AttachmentUriGrants — releaseUnreferenced/referencedUris wiring: empty-set short-circuit, still-referenced guard (drafts + outbox), and the swallowed SecurityException when releasing a grant never held.
AppLockViewModel — distinct lock nonce, the onBackground cover branch, the unwrapSealedPassphrase cancellation rethrow, and the awaitSyncEnqueue execution-failure and interrupt branches.
SmtpSender — the send error paths (required-STARTTLS-unavailable and implicit-TLS-fails) plus the cc-recipient and inline-image-with-a-regular-attachment (bodyPart related-in-mixed) body branches.
StartupReportViewModel — the @Inject real-clock constructor.
Validation (no emulator — pure JVM)
:app:testDebugUnitTest + :app:jacocoTestReport + :app:ktlintCheck + :app:detekt all green.
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 #288
Closes the cleanly JVM-testable coverage gaps from the Phase-2 JaCoCo audit. All changes are test-only (7 existing suites extended, 2 net-new); no production code touched. Each targeted class reached 100% line coverage (source-file aggregate), comfortably clearing the ~95% bar.
data/settings/AccountSettingsRepositorydata/settings/SignatureRepositorydata/security/CredentialStore(new)data/security/EncryptedCacheGuard(new)data/attachment/AttachmentUriGrantsdata/sync/SyncSchedulerui/lock/AppLockViewModelmail/SmtpSenderui/reporting/StartupReportViewModelWhat each test adds
observeFlow (Turbine) + the sibling setters (setSignatureEnabled/setNotificationsEnabled/setRetentionCount/setRetentionMonths, including the negative-clamp and null-inherit cases).observeForAccount/get/getDefault/update(+ the no-op-for-unknown-id branch) and thetoDomainmapping.KeystoreCryptomocked as identity (the AES-GCM round-trip is device-bound).isCacheLocked()truth table overappLock/encryptCache/isUnlocked.releaseUnreferenced/referencedUriswiring: empty-set short-circuit, still-referenced guard (drafts + outbox), and the swallowedSecurityExceptionwhen releasing a grant never held.schedulePeriodicReportPurge(UPDATE policy + unique name).onBackgroundcover branch, theunwrapSealedPassphrasecancellation rethrow, and theawaitSyncEnqueueexecution-failure and interrupt branches.senderror paths (required-STARTTLS-unavailable and implicit-TLS-fails) plus the cc-recipient and inline-image-with-a-regular-attachment (bodyPartrelated-in-mixed) body branches.@Injectreal-clock constructor.Validation (no emulator — pure JVM)
:app:testDebugUnitTest+:app:jacocoTestReport+:app:ktlintCheck+:app:detektall green.🤖 Generated with Claude Code