chain-studio/integration_test/dialog_shots_test.dart
flemming-it 87afa4dc05
Some checks failed
Security / Security check (push) Failing after 2s
feat(docs): in-place help pattern — explain a surface where it happens
New ChainInlineHelp (intro strip: what this is + what will happen, with
an optional 'Learn more' into the doc sheet) and ChainFieldHelp /
ChainFieldLabel (a '?' affordance per field). First applied to the
add-satellite dialog, which asked for a bare 'name' with no hint of
what a satellite is or does (usertest): it now leads with a plain
explanation + a federation 'Learn more', and the name field carries a
'?'. Both widgets are quiet by design.

Verified: field_help_test covers the widgets + that the dialog explains
itself; dialog_shots_test.dart (a reusable headed dialog-capture
harness) proved the layout in light + dark. Studio 0.76.0.

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

79 lines
2.9 KiB
Dart

// 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/<name>-<theme>.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<void> _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);
});
}
}