chore(studio): RadioGroup migration + second integration test

Two clean-ups:

- `fai_system_ai_editor.dart` uses the new `RadioGroup<T>`
  ancestor pattern Material 3 introduced after Flutter 3.32.
  Same UX (three radios for off/redacted/full), no
  deprecation warnings, `flutter analyze` is now zero-issue
  for the whole project.
- New `install_install_planned_test.dart` asserts that
  installing a `planned` seed entry surfaces a clear,
  human-readable error class (no panic, no silent success).
  Locks in the failed-precondition path Studio's
  friendly-error mapper depends on.

Integration test suite is now 3 scenarios:
  - capabilities_test.dart: system.approval+kind tag
  - install_install_planned_test.dart: planned-install error

All run against a fresh `fai serve` subprocess via
HubFixture, ~2 s total.

Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-25 14:05:43 +02:00
parent 69b54629d3
commit 21c2a0f411
2 changed files with 94 additions and 45 deletions

View file

@ -0,0 +1,42 @@
// Integration test: install_module against a `planned` seed
// entry must fail with a clear, human-readable error class
// not a panic, not a silent success.
//
// Why this matters: planned modules are listed in the Store
// but have no wasm_url. The old behaviour was a server-side
// panic on resolve_install_source(); the new contract emits a
// FAILED_PRECONDITION with "no installable version" so
// Studio's friendly-error mapper can show a usable message.
import 'package:flutter_test/flutter_test.dart';
import 'hub_fixture.dart';
void main() {
test('install_module on a planned entry surfaces a clear error',
() async {
final fixture = await HubFixture.start();
if (fixture == null) return;
try {
// web.scrape is `planned` in the seed and has no
// wasm_url. The hub resolves the name through the store
// index, finds the entry, then fails at the
// "no installable version" check.
try {
await fixture.client.installModule(source: 'web.scrape');
fail('install_module should not succeed for a planned entry');
} catch (e) {
final msg = e.toString();
expect(
msg.contains('no installable version') ||
msg.contains('not yet published'),
isTrue,
reason:
'Expected a clear planned-status error, got: $msg',
);
}
} finally {
await fixture.dispose();
}
});
}