feat(store,doctor): surface the hub's trust + exposure data (0.77.0)
Some checks failed
Security / Security check (push) Failing after 1s
Some checks failed
Security / Security check (push) Failing after 1s
The trust-gate dialog replaces its generic 'no per-entry status yet (alpha)' note with the hub's classified verification statement — pinned store key / trusted publishers (green), installs without signature checking (amber), install would be refused (red), bridge entry (neutral) — via one shared describeInstallVerification mapping. Against a pre-0.23 hub the field is empty and the old honest wording stays (pinned by test). Information architecture: policy-off is a GLOBAL fact, so it appears as ONE ChainInlineHelp notice above the store grid instead of a warning pill on every card (card noise); only 'blocked' — a genuine per-source anomaly — earns a card pill. Doctor's host services show the hub-classified network reach per endpoint (local only / private network / publicly reachable with a protect-it hint / reach unknown). Verified end-to-end against the live dev hub (guide harness): the wire field arrives, the store page shows exactly one policy notice and quiet cards; trust-gate variants captured via the dialog harness. Suite 123 green. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
87afa4dc05
commit
2f076ccf29
15 changed files with 732 additions and 13 deletions
116
test/install_verification_test.dart
Normal file
116
test/install_verification_test.dart
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// 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<AppLocalizations> _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('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,
|
||||
);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue