Some checks failed
Security / Security check (push) Failing after 2s
The Studio design system, widgets and helpers carried a Fai* / fai_ prefix (FaiSpace, FaiColors, FaiTheme, FaiLog, 17 fai_*.dart files, the faiBinary* l10n keys). Studio is the Ch∆In product, so rename them to Chain* / chain_ — carefully preserving English fail/failure/failed. Also fix stale references: the 'fai' binary in l10n strings -> 'chain', FAI_* env vars (FAI_BIN/DATA_DIR/MODULES_DIR/TODAY/BOOTSTRAP_TOKEN) -> CHAIN_*, fai_platform -> fai_chain, fai_hub -> chain_hub. Vendor security-hook tooling (FAI_BANNED_TERMS_FILE) + the .fai bundle ext left. flutter analyze + test: clean (20 passed). Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
73 lines
2.6 KiB
Dart
73 lines
2.6 KiB
Dart
// 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 ../chain_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');
|
|
}
|
|
});
|
|
});
|
|
}
|