chain-studio/test/integration/README.md
flemming-it 69b54629d3 chore(studio): flutter_markdown_plus migration + integration-test scaffold
Two follow-ups to the May-2026 trust pass.

flutter_markdown_plus migration:

- pubspec swaps `flutter_markdown ^0.7.7` (discontinued
  upstream) for `flutter_markdown_plus ^1.0.3`, the
  actively-maintained fork. API surface
  (MarkdownStyleSheet, Markdown, MarkdownBody) is
  unchanged — the four import sites in welcome, store,
  flow_output, and theme.dart get an updated package
  string and that's it.
- All Studio analyzer + unit-test suites stay green.

Integration test scaffold:

- New `test/integration/hub_fixture.dart` boots a real
  `fai serve` subprocess on a free port against a temp
  FAI_DATA_DIR, polls until Healthy, exposes a ready
  HubClient. Idempotent teardown wipes the temp dir.
- Resolves the `fai` binary from PATH first, then from
  `../fai_platform/target/release/fai`. When neither
  exists, the fixture calls `markTestSkipped` with a
  clear message — fresh checkouts don't fail.
- One canonical test in `capabilities_test.dart` asserts
  on the bug class the May trust pass surfaced: that
  `system.approval` appears in `list_capabilities` with
  `kind=builtin` so Studio's missing-deps check never
  tries to install it. Plus a contract-shape test that
  every cap's `kind` is one of the three known wire
  values.
- README documents the cold-start gotcha (first
  `fai serve` per machine takes ~30s to build the
  curated-model DB) plus the manual warmup recipe.

Not in CI yet — wiring needs the platform build job to
publish `fai` as a CI artifact for downstream consumption.
Deferred until enough integration tests exist to justify
the CI minutes.

Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-05-25 13:22:04 +02:00

2.3 KiB

Integration tests

These tests spin up a real fai serve subprocess against a fresh temp dir and exercise Studio's Hub-facing data layer against it. They cover the "kind of regression that survives unit tests because the system-shape only manifests across the gRPC boundary".

Status

Scaffold. One canonical test (capabilities). The harness is production-quality (proper teardown, idempotent, port-clean) so new tests slot in by importing hub_fixture.dart and calling HubFixture.start() / dispose() in setUp / tearDown.

What's NOT here yet:

  • A full "install dep → run echo → assert title" scenario. The harness can do it (install_module is a real RPC), but building the fixture for module-bundle downloads against a hermetic local registry is its own scaffold. Tracked as follow-up to S-21.
  • Studio-side widget testing against the live hub. The flutter integration_test package supports it (testWidgets + IntegrationTestWidgetsFlutterBinding), but pumping a full StudioApp against a real gRPC channel needs binding.enableSurfaceBindingHack() ceremony we haven't designed yet.

Running

cd fai_studio
flutter test test/integration/

Prereq: a fai binary on PATH or at ../fai_platform/target/release/fai. The harness skips with a clear message when neither exists, so this command does not fail on a fresh checkout — it just reports skipped tests.

To get the binary:

cd ../fai_platform
cargo build --release --bin fai

First-time-start gotcha

A cold fai serve spends its first ~30s building the curated-model database and initialising SQLite migrations. HubFixture.start() waits up to 60s by default; if your local hub takes longer the first time, run fai serve once by hand against any temp FAI_DATA_DIR to warm the per-user cargo / SBOM caches:

FAI_DATA_DIR=/tmp/fai_warmup fai serve --bind 127.0.0.1:0
# wait for "hub started", Ctrl-C

Subsequent integration-test runs are quick.

Not yet wired into CI

.forgejo/workflows/ci.yml doesn't run these yet. Adding them needs an artifact-passing pattern: the platform build job publishes target/release/fai as a CI artifact; the studio test job consumes it. Pattern is straightforward once we want it; it's deferred because we don't yet have enough integration tests to justify the CI runtime.