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>
This commit is contained in:
parent
c11461b0f9
commit
69b54629d3
9 changed files with 349 additions and 9 deletions
73
test/integration/capabilities_test.dart
Normal file
73
test/integration/capabilities_test.dart
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// First integration test against a real `fai serve` subprocess.
|
||||
//
|
||||
// What this test covers (the regression bait):
|
||||
//
|
||||
// When the operator opens a flow that references `system.approval`
|
||||
// or any other built-in / federated capability, the missing-deps
|
||||
// check in Studio's Flows page must consider those caps already
|
||||
// available — otherwise the Run button stays disabled forever
|
||||
// and the operator's only recourse is to install a module that
|
||||
// doesn't exist.
|
||||
//
|
||||
// Why this test as the canonical first scaffold:
|
||||
//
|
||||
// It's the exact bug class that survived three commits of the
|
||||
// May-2026 trust pass before someone noticed. A real-Hub test
|
||||
// for it makes regressions impossible to ship.
|
||||
//
|
||||
// Cost: ~2 seconds (Hub start) + ~0.1 seconds (gRPC). Acceptable.
|
||||
//
|
||||
// Run manually with:
|
||||
//
|
||||
// flutter test test/integration/
|
||||
//
|
||||
// CI does not yet run these by default — they need a built `fai`
|
||||
// binary in PATH or in ../fai_platform/target/release/. Wire that
|
||||
// in via .forgejo/workflows/ci.yml once the platform CI publishes
|
||||
// a Linux binary as an artifact for downstream jobs to consume.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'hub_fixture.dart';
|
||||
|
||||
void main() {
|
||||
group('Hub capability listing', () {
|
||||
late HubFixture? fixture;
|
||||
|
||||
setUp(() async {
|
||||
fixture = await HubFixture.start();
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await fixture?.dispose();
|
||||
});
|
||||
|
||||
test('system.approval shows up as a builtin capability', () async {
|
||||
final f = fixture;
|
||||
if (f == null) return; // skipped — no binary
|
||||
final caps = await f.client.listCapabilities();
|
||||
final approval = caps.where(
|
||||
(c) => c.capability == 'system.approval',
|
||||
).toList();
|
||||
expect(approval, isNotEmpty,
|
||||
reason: 'system.approval must appear in list_capabilities '
|
||||
'so Studio does not try to install it through the store');
|
||||
expect(approval.first.kind, 'builtin',
|
||||
reason: 'kind=builtin lets Studio gate the Install button correctly');
|
||||
});
|
||||
|
||||
test('every capability carries a kind tag', () async {
|
||||
final f = fixture;
|
||||
if (f == null) return;
|
||||
final caps = await f.client.listCapabilities();
|
||||
expect(caps, isNotEmpty,
|
||||
reason: 'a fresh hub has at least the system.approval builtin');
|
||||
for (final c in caps) {
|
||||
expect(['wasm', 'builtin', 'federated'], contains(c.kind),
|
||||
reason: 'cap ${c.capability} has unrecognised kind="${c.kind}" — '
|
||||
'Studio gates the Install button on this string, so the wire '
|
||||
'value must stay in the known set');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue