import "dart:io"; import "package:flutter/services.dart"; import "package:flutter_test/flutter_test.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:material_ui/material_ui.dart"; // Renders the README screenshots into assets/screenshots. // Regenerate them with `flutter test --update-goldens`. const mobile = Size(400, 720); const desktop = Size(900, 600); Future loadFonts() async { final fonts = "${Platform.environment["FLUTTER_ROOT"]}/bin/cache/artifacts/material_fonts"; Future load(String family, List files) async { final loader = FontLoader(family); for (final file in files) { loader.addFont( File("$fonts/$file") .readAsBytes() .then((bytes) => ByteData.sublistView(bytes)), ); } await loader.load(); } await load("Roboto", [ "Roboto-Regular.ttf", "Roboto-Medium.ttf", "Roboto-Bold.ttf", ]); await load("MaterialIcons", ["MaterialIcons-Regular.otf"]); } class const Demo({super.key}) extends StatelessWidget { @override Widget build(BuildContext context) => Scaffold( appBar: AppBar( title: const Text("Inbox"), actions: [ Builder( builder: (context) => IconButton( key: const Key("popover"), icon: const Icon(Icons.info_outline), tooltip: "Details", onPressed: () => context.showAdaptivePopover( (context) => const Padding( padding: .all(16), child: Column( mainAxisSize: .min, crossAxisAlignment: .start, spacing: 8, children: [ Text( "Inbox", style: TextStyle(fontSize: 18, fontWeight: .w500), ), Text("3 conversations, 1 unread"), Text("Last synced just now"), ], ), ), ), ), ), AdaptiveMenuButton( key: const Key("menu"), icon: const Icon(Icons.more_vert), tooltip: "More", itemBuilder: (context) => const [ PopupMenuItem( value: "read", child: ListTile( leading: Icon(Icons.done_all), title: Text("Mark all as read"), ), ), PopupMenuItem( value: "archive", child: ListTile( leading: Icon(Icons.archive_outlined), title: Text("Archive"), ), ), PopupMenuItem( value: "settings", child: ListTile( leading: Icon(Icons.settings_outlined), title: Text("Settings"), ), ), ], ), ], ), body: ListView( children: [ for (final (name, message) in const [ ("Alice", "Are we still on for tomorrow?"), ("Bob", "Sent you the photos from the trip"), ("Carol", "Thanks for the help!"), ]) ListTile( leading: CircleAvatar(child: Text(name[0])), title: Text(name), subtitle: Text(message), ), ], ), floatingActionButton: Builder( builder: (context) => FloatingActionButton( key: const Key("sheet"), tooltip: "Delete", child: const Icon(Icons.delete_outline), onPressed: () => context.showAdaptiveSheet( (context) => SheetLayout( title: const Text("Delete conversations?"), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text("Cancel"), ), FilledButton( onPressed: () => Navigator.of(context).pop(), child: const Text("Delete"), ), ], children: const [ Text( "All 3 conversations in your inbox will be deleted. This can't be undone.", ), ], ), ), ), ), ); } void main() { setUpAll(loadFonts); for (final (name, size) in const [("mobile", mobile), ("desktop", desktop)]) { for (final surface in const ["sheet", "menu", "popover"]) { testWidgets("$surface on $name", (tester) async { tester.view ..physicalSize = size * 2 ..devicePixelRatio = 2; addTearDown(tester.view.reset); // Draw real shadows instead of the outlines used by default in tests debugDisableShadows = false; await tester.pumpWidget( MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData(colorSchemeSeed: Colors.indigo), home: const Demo(), ), ); await tester.tap(find.byKey(Key(surface))); await tester.pumpAndSettle(); await expectLater( find.byType(MaterialApp), matchesGoldenFile("../assets/screenshots/${surface}_$name.png"), ); debugDisableShadows = true; }); } } }