Batch 1/9 of the Robolectric Compose umbrella (#373). Converts the stateless rich-text format controls to Robolectric JVM Compose tests in the test source set and drops them from jacocoNonJvmTestableSurface.
Each mirrors its existing instrumented androidTest counterpart (which stays as the on-device E2E), following the #375 PoC pattern: @RunWith(RobolectricTestRunner) + @GraphicsMode(NATIVE) + @Config(sdk=[36]), v2 createComposeRule().
New JVM test
Covers
Line coverage
ColorSwatchRowJvmTest
ColorSwatchRow.kt, ColorSwatch.kt
40/46
FontPickerJvmTest
FontPicker.kt
43/43
FontSizePickerJvmTest
FontSizePicker.kt
43/43
ParagraphAlignmentControlJvmTest
ParagraphAlignmentControl.kt
34/34
They assert render, selected/unselected state, dropdown open, and the null-vs-value onSelect branch — genuine coverage, not smoke tests. (The 6 uncovered ColorSwatchRow lines are the Canvas slash-draw lambda for the "no color" swatch, which Robolectric's NATIVE graphics doesn't run in the draw phase; the kept instrumented test exercises real-device rendering.)
Removed from jacocoNonJvmTestableSurface
**/ColorSwatch*, **/FontPicker*, **/FontSizePicker*, **/ParagraphAlignmentControl* (replaced with a breadcrumb comment). FontRegistry.kt stays out of the list — it is plain logic, already JVM-covered by FontRegistryTest.
⚠️ Infra fix folded in (heads-up for siblings 2/9–9/9)
While validating, I found the #375 infra was silently recording zero JaCoCo coverage for every Robolectric-run composable — including the PoC AddAnotherAccountScreen. Cause: the JaCoCo agent skips classes with no code-source location, which is exactly how Robolectric loads the classes-under-test through its sandbox classloader. #375's single 40-line PoC didn't breach the 0.79 floor, so the gap stayed hidden; this 4-file (166-line) batch is the first to expose it (verification failed at 0.78).
Fix: isIncludeNoLocationClasses = true (+ jdk.internal.* exclude) on the Test tasks. With it, Robolectric coverage registers and the scoped bundle rises ~0.80 → 0.8217. This is a one-time fix that unblocks the whole epic (coverage now rises as batches land, as #386's re-ratchet assumes) — siblings should not duplicate it. It lives near the jacoco {} block, away from the exclusion list, so it won't add to the trivial exclusion-list conflicts between batches.
Per the ticket, the floor stays at 0.79 (the re-ratchet is #386).
Batch 1/9 of the Robolectric Compose umbrella (#373). Converts the stateless rich-text format controls to **Robolectric JVM Compose tests** in the `test` source set and drops them from `jacocoNonJvmTestableSurface`.
Closes #376.
## Tests added (`src/test`, JVM — no emulator)
Each mirrors its existing instrumented `androidTest` counterpart (which stays as the on-device E2E), following the #375 PoC pattern: `@RunWith(RobolectricTestRunner)` + `@GraphicsMode(NATIVE)` + `@Config(sdk=[36])`, v2 `createComposeRule()`.
| New JVM test | Covers | Line coverage |
|---|---|---|
| `ColorSwatchRowJvmTest` | `ColorSwatchRow.kt`, `ColorSwatch.kt` | 40/46 |
| `FontPickerJvmTest` | `FontPicker.kt` | 43/43 |
| `FontSizePickerJvmTest` | `FontSizePicker.kt` | 43/43 |
| `ParagraphAlignmentControlJvmTest` | `ParagraphAlignmentControl.kt` | 34/34 |
They assert render, selected/unselected state, dropdown open, and the null-vs-value `onSelect` branch — genuine coverage, not smoke tests. (The 6 uncovered `ColorSwatchRow` lines are the `Canvas` slash-draw lambda for the "no color" swatch, which Robolectric's NATIVE graphics doesn't run in the draw phase; the kept instrumented test exercises real-device rendering.)
## Removed from `jacocoNonJvmTestableSurface`
`**/ColorSwatch*`, `**/FontPicker*`, `**/FontSizePicker*`, `**/ParagraphAlignmentControl*` (replaced with a breadcrumb comment). `FontRegistry.kt` stays out of the list — it is plain logic, already JVM-covered by `FontRegistryTest`.
## ⚠️ Infra fix folded in (heads-up for siblings 2/9–9/9)
While validating, I found the #375 infra was **silently recording zero JaCoCo coverage for every Robolectric-run composable — including the PoC `AddAnotherAccountScreen`**. Cause: the JaCoCo agent skips classes with no code-source location, which is exactly how Robolectric loads the classes-under-test through its sandbox classloader. #375's single 40-line PoC didn't breach the 0.79 floor, so the gap stayed hidden; this 4-file (166-line) batch is the first to expose it (verification failed at **0.78**).
Fix: `isIncludeNoLocationClasses = true` (+ `jdk.internal.*` exclude) on the `Test` tasks. With it, Robolectric coverage registers and the scoped bundle rises **~0.80 → 0.8217**. This is a one-time fix that unblocks the whole epic (coverage now *rises* as batches land, as #386's re-ratchet assumes) — **siblings should not duplicate it.** It lives near the `jacoco {}` block, away from the exclusion list, so it won't add to the trivial exclusion-list conflicts between batches.
Per the ticket, the **floor stays at 0.79** (the re-ratchet is #386).
## Gate (JVM, local)
`assembleDebug` + `testDebugUnitTest` (19 new tests green) + `jacocoTestCoverageVerification` (0.8217 ≥ 0.79) + `compileDebugAndroidTestKotlin` + `lintDebug` + `ktlintCheck` + `detekt` — all green.
🤖 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 1/9 of the Robolectric Compose umbrella (#373). Converts the stateless rich-text format controls to Robolectric JVM Compose tests in the
testsource set and drops them fromjacocoNonJvmTestableSurface.Closes #376.
Tests added (
src/test, JVM — no emulator)Each mirrors its existing instrumented
androidTestcounterpart (which stays as the on-device E2E), following the #375 PoC pattern:@RunWith(RobolectricTestRunner)+@GraphicsMode(NATIVE)+@Config(sdk=[36]), v2createComposeRule().ColorSwatchRowJvmTestColorSwatchRow.kt,ColorSwatch.ktFontPickerJvmTestFontPicker.ktFontSizePickerJvmTestFontSizePicker.ktParagraphAlignmentControlJvmTestParagraphAlignmentControl.ktThey assert render, selected/unselected state, dropdown open, and the null-vs-value
onSelectbranch — genuine coverage, not smoke tests. (The 6 uncoveredColorSwatchRowlines are theCanvasslash-draw lambda for the "no color" swatch, which Robolectric's NATIVE graphics doesn't run in the draw phase; the kept instrumented test exercises real-device rendering.)Removed from
jacocoNonJvmTestableSurface**/ColorSwatch*,**/FontPicker*,**/FontSizePicker*,**/ParagraphAlignmentControl*(replaced with a breadcrumb comment).FontRegistry.ktstays out of the list — it is plain logic, already JVM-covered byFontRegistryTest.⚠️ Infra fix folded in (heads-up for siblings 2/9–9/9)
While validating, I found the #375 infra was silently recording zero JaCoCo coverage for every Robolectric-run composable — including the PoC
AddAnotherAccountScreen. Cause: the JaCoCo agent skips classes with no code-source location, which is exactly how Robolectric loads the classes-under-test through its sandbox classloader. #375's single 40-line PoC didn't breach the 0.79 floor, so the gap stayed hidden; this 4-file (166-line) batch is the first to expose it (verification failed at 0.78).Fix:
isIncludeNoLocationClasses = true(+jdk.internal.*exclude) on theTesttasks. With it, Robolectric coverage registers and the scoped bundle rises ~0.80 → 0.8217. This is a one-time fix that unblocks the whole epic (coverage now rises as batches land, as #386's re-ratchet assumes) — siblings should not duplicate it. It lives near thejacoco {}block, away from the exclusion list, so it won't add to the trivial exclusion-list conflicts between batches.Per the ticket, the floor stays at 0.79 (the re-ratchet is #386).
Gate (JVM, local)
assembleDebug+testDebugUnitTest(19 new tests green) +jacocoTestCoverageVerification(0.8217 ≥ 0.79) +compileDebugAndroidTestKotlin+lintDebug+ktlintCheck+detekt— all green.🤖 Generated with Claude Code