chain-studio/test/setup_gate_test.dart
flemming-it 065939be74
Some checks are pending
Security / Security check (push) Waiting to run
feat(setup): first-run gate, hub-first preview, honest wording — setup before the app
Stefan's live findings, all four addressed at the root:

- 'In 3 Fragen loslegen' read like ad copy → the entry is now plainly
  'Einrichtung starten' / 'Start setup'.
- The setup button sat permanently on the Welcome page of a running
  app ('setup after the app runs is backwards' — reported twice). A
  fresh install now starts INSIDE the setup: SetupGateScreen hosts
  the wizard embedded as the page (new embedded/onFinished modes on
  GuidedSetupDialog), with an explicit 'Später einrichten' skip.
  Welcome loses the setup button entirely and stays a calm intro.
- Re-running the setup later lives in Settings → General ('Run setup
  again…'), the single post-first-run home.
- 'You must grant access first and only then see what will be done':
  the preview used to spawn the chain CLI, whose first run could pop
  the macOS permission prompt BEFORE the plan was ever shown. The
  preview now calls the new PlanSetup RPC over the live hub
  connection (no subprocess, nothing granted); the CLI remains only
  a fallback when no hub is reachable — and applying stays the
  explicit, separate step.

Widget tests: gate hosts the wizard + skip/cancel leave it; CLI-path
tests drive the fallback through the new hub-preview test seam.
Suite 76 green, analyze clean.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-07-17 00:59:22 +02:00

55 lines
2 KiB
Dart

// First-run gate: on a fresh install the app opens INTO the setup
// (embedded wizard as the page), with an explicit skip. Setup
// before the app — not a dialog over a shell that isn't set up.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:chain_studio/l10n/app_localizations.dart';
import 'package:chain_studio/pages/setup_gate.dart';
void main() {
testWidgets('gate hosts the embedded wizard + a skip action', (
tester,
) async {
var done = false;
await tester.pumpWidget(
MaterialApp(
locale: const Locale('de'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: SetupGateScreen(onDone: () => done = true),
),
);
await tester.pumpAndSettle();
// The wizard renders as PAGE content (step 1 visible, no dialog).
expect(find.text('Worum geht es?'), findsOneWidget);
expect(find.text('Erst mal ausprobieren'), findsOneWidget);
expect(find.byType(AlertDialog), findsNothing);
// Honest framing + a way past the gate.
expect(find.textContaining('Nichts wird ohne Ihre'), findsOneWidget);
await tester.ensureVisible(find.text('Später einrichten'));
await tester.tap(find.text('Später einrichten'));
await tester.pumpAndSettle();
expect(done, isTrue, reason: 'skip must hand control to the app');
});
testWidgets('cancel on step 1 also leaves the gate', (tester) async {
var done = false;
await tester.pumpWidget(
MaterialApp(
locale: const Locale('de'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: SetupGateScreen(onDone: () => done = true),
),
);
await tester.pumpAndSettle();
await tester.ensureVisible(find.text('Abbrechen'));
await tester.tap(find.text('Abbrechen'));
await tester.pumpAndSettle();
expect(done, isTrue);
});
}