import "package:flutter/widgets.dart"; import "package:flutter_test/flutter_test.dart"; import "package:garage_ui/garage_ui.dart"; import "support/test_scheme.dart"; // The actions band. Before this existed a Save button had to go in `rows`, // where it read as one more property that happened to be a button - no // separator, no tone, and lined up against the property split like a value. Widget _host(Widget child, {Density density = const Density()}) => Directionality( textDirection: TextDirection.ltr, child: GarageTheme( data: ThemeData(colorScheme: testScheme, density: density), child: Center(child: SizedBox(width: 420, child: child)), ), ); Widget _section({List actions = const [], bool collapsed = false}) => PropertiesSection( title: "Profile", scheme: testScheme, collapsed: collapsed, onToggle: () {}, actions: actions, rows: [ PropertyRow( label: "Username", scheme: testScheme, child: const SizedBox(), ), ], ); Color? _bandColour(WidgetTester tester) { final containers = find .ancestor( of: find.text("Save"), matching: find.byType(Container), ) .evaluate() .map((e) => e.widget as Container) .where((c) => c.color != null); return containers.isEmpty ? null : containers.first.color; } void main() { testWidgets("no actions means no band and no separator", (tester) async { await tester.pumpWidget(_host(_section())); expect(find.byType(Divider), findsNothing); }); testWidgets("actions get a separator and the muted band", (tester) async { await tester.pumpWidget( _host( _section( actions: [ Button( style: const ButtonStyle.primary(), onPressed: () {}, child: const Text("Save"), ), ], ), ), ); expect(find.byType(Divider), findsOneWidget); // toned OFF the section, not the same fill expect(_bandColour(tester), testScheme.muted); expect(_bandColour(tester), isNot(testScheme.card)); }); testWidgets("the band spans the section, not just its buttons", ( tester, ) async { await tester.pumpWidget( _host( _section( actions: [ Button( style: const ButtonStyle.primary(), onPressed: () {}, child: const Text("Save"), ), ], ), ), ); const density = Density(); final content = tester.getRect( find .ancestor(of: find.text("Save"), matching: find.byType(Row)) .first, ); final divider = tester.getRect(find.byType(Divider)); // the BAND spans the section edge to edge - its content is inset by the // same buttonPaddingX a row uses, so the buttons line up with the controls // above them rather than sitting on the section's edge. expect(content.width, divider.width - density.buttonPaddingX * 2); // and the whole thing sits under the rows expect( content.top, greaterThan(tester.getRect(find.text("Username")).bottom), ); }); testWidgets("actions collapse with the rows", (tester) async { await tester.pumpWidget( _host( _section( collapsed: true, actions: [ Button( style: const ButtonStyle.primary(), onPressed: () {}, child: const Text("Save"), ), ], ), ), ); expect(find.text("Save"), findsNothing); expect(find.byType(Divider), findsNothing); }); }