testsAndMisc/docs/app-split-recipes.md
Krzysztof kuhy Rudnicki 34783a5022
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Add docs/app-split-recipes.md; update the handoff to 78 left
Dart's library-scoped privates (use part/part of), Kotlin's lack of any
equivalent (use an internal fixture object), and the TypeScript seams
that compile clean and fail at runtime - three projects hit that last
one. Also the per-project test baselines, including that gradle prints
UP-TO-DATE rather than a count and needs JDK 21 pinned.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 20:51:38 +02:00

3.6 KiB

App split recipes (Dart, Kotlin, TypeScript)

Settled while clearing focus_owner, kcd2_dice_solver and reverse_survivors. Referenced from refactor_claude_todo_resume.md.

Baselines — measure before editing, re-check after

Project Command Expect
focus_owner (Dart) flutter test 94
focus_owner (Kotlin) see below 40, 0 failures
kcd2_dice_solver npm test -- --run 288
reverse_survivors npm test -- --run 160

Gradle prints UP-TO-DATE rather than a count, so read the JUnit XML, and pin the JDK — the default JDK 26 breaks the AGP jlink transform:

cd focus_owner/android
JAVA_HOME=/usr/lib/jvm/java-21-openjdk ./gradlew testDebugUnitTest --offline
grep -ho 'tests="[0-9]*"' ../build/app/test-results/testDebugUnitTest/*.xml \
  | grep -oP '\d+' | paste -sd+ | bc

Dart: privates are library-scoped, so use part

A separate file is a separate library, so _Card and friends are invisible to it. Splitting main.dart with import + export produced 30 errors of the form "The name _Card isn't a class". part 'x.dart'; + part of 'main.dart'; keeps both files in one library and the analyzer goes straight to zero issues.

The part file carries no imports of its own — it inherits the library's.

A part cannot rescue a State class. status_page_state.dart stayed over the cap: its methods call setState and read seven private fields, and a mixin on State<...> cannot see them without declaring the state twice.

Splitting a widget test off its testWidgets group loses the binding. Four tests failed with "Binding has not yet been initialized" because the group that had been initialising it implicitly moved away. Add TestWidgetsFlutterBinding.ensureInitialized() to both halves.

Kotlin: no part, so use an internal fixture object

Shared private val/private fun test fixtures go into an internal object XFixtures in the same package, and each test class delegates to it. Two compile failures came from missing one (installed) — list every private member of the original class before cutting.

EnforcementRunner.kt is not splittable as it stands: its location block reads the private constructor property context and prefs() eleven times, which no extension function can reach.

TypeScript: tsc does not tell you a split worked

Three separate projects had a seam that compiled clean and failed at runtime:

  • an import cycle leaves a constant undefined at module-init (HEADSTART_POINTS, twice, in kcd2);
  • a moved function is simply not there (survivorStep, 63 failures);
  • a type name that collides with a DOM global resolves to the DOM one — the error talks about anchorNode rather than saying the name is missing.

Always run the suite. Prune the imports the split leaves behind by iterating on tsc's own TS6133/TS6192/TS6196 output rather than guessing, but note it cannot see a helper another file still needs.

Coverage: new files must land inside the include glob

kcd2 and reverse_survivors both gate at 100%. New source modules are picked up automatically; shared test fixtures must go in src/test/, which the coverage exclude names by path. Beside the source they count as production code and break the gate — the same trap recorded for poker-stakes.

A split that empties a file must delete it

App.test.tsx lost its last describe and vitest failed the whole run with "No test suite found in file". Remove the shell.