// Presentation of the hub's per-entry install-verification // statement. The mapping is the single source for the trust-gate // dialog, the store card pill and the detail sheet — these tests // pin the wire contract and the honest-fallback rule (unknown or // empty => null => callers keep their generic wording). import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:chain_studio/data/hub.dart'; import 'package:chain_studio/data/install_verification.dart'; import 'package:chain_studio/l10n/app_localizations.dart'; import 'package:chain_studio/widgets/chain_install_confirm.dart'; StoreItem _item({String verification = ''}) => StoreItem( name: 'text.extract', taglineEn: '', taglineDe: '', descriptionEn: '', descriptionDe: '', category: 'text', tags: const [], requiresCapabilities: const [], requiresServices: const [], license: 'Apache-2.0', repository: '', bestVersion: '0.1.0', status: 'alpha', installed: false, featured: false, iconUrl: '', screenshotUrls: const [], docsUrl: '', kind: 'native', provider: '', source: 'bundled', installVerification: verification, ); Widget _host(Widget child) => MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, locale: const Locale('de'), home: Scaffold(body: child), ); Future _l10n(WidgetTester tester) async { late AppLocalizations l; await tester.pumpWidget( _host( Builder( builder: (context) { l = AppLocalizations.of(context)!; return const SizedBox(); }, ), ), ); return l; } void main() { testWidgets('wire values map to tones; unknown maps to null', ( tester, ) async { final l = await _l10n(tester); expect( describeInstallVerification('pinned-key', l)!.tone, VerificationTone.good, ); expect( describeInstallVerification('trusted-publishers', l)!.tone, VerificationTone.good, ); expect( describeInstallVerification('unverified', l)!.tone, VerificationTone.warning, ); expect( describeInstallVerification('blocked', l)!.tone, VerificationTone.danger, ); expect( describeInstallVerification('federated', l)!.tone, VerificationTone.neutral, ); // Pre-0.23 hub / future value: no guessing. expect(describeInstallVerification('', l), isNull); expect(describeInstallVerification('something-new', l), isNull); }); testWidgets('trust gate states the classified verification', (tester) async { await tester.pumpWidget( _host(ChainInstallConfirmDialog(item: _item(verification: 'unverified'))), ); await tester.pumpAndSettle(); expect( find.text('Wird ohne Signaturprüfung installiert'), findsOneWidget, ); // The generic alpha note must be gone when the hub reports. expect( find.textContaining('zeigt der Store-Index derzeit noch nicht'), findsNothing, ); }); testWidgets('blocked disables the install button', (tester) async { await tester.pumpWidget( _host(ChainInstallConfirmDialog(item: _item(verification: 'blocked'))), ); await tester.pumpAndSettle(); // The statement says the hub would refuse — the button must // not contradict it. expect(find.text('Installation würde abgelehnt'), findsOneWidget); final button = tester.widget(find.byType(FilledButton)); expect(button.onPressed, isNull); }); testWidgets('trust gate keeps the generic note for old hubs', (tester) async { await tester.pumpWidget(_host(ChainInstallConfirmDialog(item: _item()))); await tester.pumpAndSettle(); expect( find.textContaining('zeigt der Store-Index derzeit noch nicht'), findsOneWidget, ); }); }