From 042b50116c07fd69d0c07e4892bccfeca609c3fd Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Mon, 6 Jul 2026 14:19:22 -0500 Subject: [PATCH] build(jacoco): scope the fail-closed encryption UI out of the JVM coverage surface (#359) CacheEncryptionGate.kt (the gate composable, blank cover, error screen, and ephemeral report-review screen added for #359) is pure Compose render code, structurally unreachable from a JVM unit test the same way every other Screen file in jacocoNonJvmTestableSurface is. Left in scope, it dragged the whole-app line ratio to 0.78, just under the 0.79 no-regression floor. Excluded it via "**/CacheEncryptionGateKt*" rather than the usual bare "**/CacheEncryptionGate*" pattern this list otherwise uses, because CacheEncryptionGateViewModel is named with "CacheEncryptionGate" as a literal prefix - the bare wildcard would also have swallowed the already JVM-tested, 94%-covered ViewModel and its sealed CacheEncryptionGateState. CacheEncryptionGateViewModel and CacheEncryptionUnavailableException stay in scope unchanged. Verified locally: testDebugUnitTest + jacocoTestCoverageVerification now pass, with the line ratio recovered to about 0.807 (5,044 covered / 6,249 total lines) - the same 5,044 covered lines as before, just a smaller, honestly-JVM-testable denominator. Co-Authored-By: Claude Opus 4.8 --- app/build.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ef0c692..946b482 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -311,6 +311,15 @@ val jacocoNonJvmTestableSurface = listOf( "**/SettingsComponents*", "**/SignatureEditScreen*", "**/SignaturesScreen*", + // CacheEncryptionGate.kt (issue #359/#367 fail-closed encryption gate) is pure render: the gate + // composable, its blank cover, the error screen, and the ephemeral report-review screen — no plain + // top-level logic. Spelled out to "...GateKt*" (the file's compiled facade class), NOT the bare + // "**/CacheEncryptionGate*" this list otherwise uses, because unlike every Screen/ViewModel pair + // above, CacheEncryptionGateViewModel's name literally starts with "CacheEncryptionGate" — a bare + // wildcard would also swallow the (94%-covered, dedicated-tested) ViewModel and its sealed + // CacheEncryptionGateState. CacheEncryptionGateViewModel and CacheEncryptionUnavailableException + // stay in scope (both have JVM tests: CacheEncryptionGateViewModelTest, DatabaseProvisionerTest). + "**/CacheEncryptionGateKt*", // --- Android framework entry points (OS-instantiated). NB: Workers are intentionally NOT here // --- (they are unit-tested — see the KEPT IN SCOPE note above). "**/*Activity*",