// Dialog capture harness — visual proof for dialogs the page-level // guide harness doesn't reach. Renders the target dialog against // the scriptable fake hub and writes a PNG per theme via a // RepaintBoundary (driverless, headed macOS `flutter test`). // // flutter test integration_test/dialog_shots_test.dart -d macos // // Output: build/dialog-shots/-.png (or $DIALOG_SHOTS_OUT). import 'dart:io'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:chain_studio/l10n/app_localizations.dart'; import 'package:chain_studio/pages/federation.dart'; import '../test/support/fake_hub.dart'; final GlobalKey _shotKey = GlobalKey(); String get _outDir => Platform.environment['DIALOG_SHOTS_OUT'] ?? 'build/dialog-shots'; Future _shot(WidgetTester tester, String name) async { await tester.pump(const Duration(milliseconds: 150)); await tester.pump(const Duration(milliseconds: 150)); final boundary = _shotKey.currentContext!.findRenderObject() as RenderRepaintBoundary; final image = await boundary.toImage(pixelRatio: 2.0); final bytes = await image.toByteData(format: ui.ImageByteFormat.png); image.dispose(); final file = File('$_outDir/$name.png'); file.parent.createSync(recursive: true); file.writeAsBytesSync(bytes!.buffer.asUint8List()); // ignore: avoid_print print('dialog-shot: ${file.path}'); } void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); for (final (themeName, mode) in [ ('light', ThemeMode.light), ('dark', ThemeMode.dark), ]) { testWidgets('add-satellite dialog — $themeName', (tester) async { SharedPreferences.setMockInitialValues({}); installFakeHub(); await tester.pumpWidget( MaterialApp( debugShowCheckedModeBanner: false, themeMode: mode, theme: ThemeData.light(useMaterial3: true), darkTheme: ThemeData.dark(useMaterial3: true), localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, locale: const Locale('de'), // Wrap the whole navigator (incl. the overlay dialogs // render into) so the capture catches the dialog, not // just the page beneath it. builder: (context, child) => RepaintBoundary(key: _shotKey, child: child), home: const FederationPage(), ), ); await tester.pump(const Duration(milliseconds: 200)); await tester.tap(find.text('Satellit hinzufügen').first); await tester.pumpAndSettle(); await _shot(tester, 'add-satellite-$themeName'); expect(find.textContaining('Ein Satellit ist ein weiterer Hub'), findsOneWidget); }); } }