Files
Garage-SDKs/garage_ui/test/properties_section_actions_test.dart
ImBenjiandClaude Opus 5.5 b269201919 The Garage SDKs, in the open
garage_auth, garage_entitlements, garage_iap and garage_ui, moved out of
Garage-Services and Metro-Map-Maker into one public repo. MIT, one readme,
docs under docs/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013F4NWNvYcdeSgqbWMT1VQ7
2026-09-23 18:49:21 +01:00

132 lines
3.6 KiB
Dart

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<Widget> 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);
});
}