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
112 lines
3.3 KiB
Dart
112 lines
3.3 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";
|
|
|
|
// A property section is a docked surface, so its fields are always secondary -
|
|
// an outline field in there draws its own border and background against a
|
|
// panel that already has both, and reads as floating. That made `variant:` a
|
|
// parameter whose every value but one was a bug, so PropertyRow now publishes
|
|
// PropertySlotScope and the controls resolve against it.
|
|
//
|
|
// Explicit does NOT win here, unlike the label scope one widget up. These
|
|
// check exactly that.
|
|
|
|
// the fill a control actually painted, which is the thing the variant decides.
|
|
Color? _fill(WidgetTester tester, Key key) {
|
|
final box = find
|
|
.descendant(of: find.byKey(key), matching: find.byType(DecoratedBox))
|
|
.evaluate()
|
|
.map((e) => e.widget as DecoratedBox)
|
|
.map((d) => d.decoration)
|
|
.whereType<BoxDecoration>()
|
|
.firstWhere((d) => d.color != null);
|
|
return box.color;
|
|
}
|
|
|
|
Widget _host(Widget child) => Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: GarageTheme(
|
|
data: ThemeData(colorScheme: testScheme, density: const Density()),
|
|
child: Center(child: SizedBox(width: 400, child: child)),
|
|
),
|
|
);
|
|
|
|
void main() {
|
|
testWidgets("a field in a property row is secondary however its asked", (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
_host(
|
|
Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
PropertyRow(
|
|
label: "In a row",
|
|
scheme: testScheme,
|
|
// asking for outline, explicitly, and losing
|
|
child: const TextField(
|
|
key: Key("row"),
|
|
variant: TextFieldVariant.outline,
|
|
),
|
|
),
|
|
const TextField(
|
|
key: Key("bare"),
|
|
variant: TextFieldVariant.outline,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(_fill(tester, const Key("row")), testScheme.secondary);
|
|
expect(_fill(tester, const Key("bare")), isNot(testScheme.secondary));
|
|
});
|
|
|
|
testWidgets("a labelless row still counts as a slot", (tester) async {
|
|
await tester.pumpWidget(
|
|
_host(
|
|
PropertyRow(
|
|
label: "Hidden",
|
|
scheme: testScheme,
|
|
labelless: true,
|
|
child: const TextField(
|
|
key: Key("row"),
|
|
variant: TextFieldVariant.outline,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(_fill(tester, const Key("row")), testScheme.secondary);
|
|
});
|
|
|
|
testWidgets("a select in a property row is secondary too", (tester) async {
|
|
await tester.pumpWidget(
|
|
_host(
|
|
PropertyRow(
|
|
label: "Role",
|
|
scheme: testScheme,
|
|
child: Select<String>(
|
|
key: const Key("row"),
|
|
value: "Owner",
|
|
variant: SelectVariant.outline,
|
|
itemBuilder: (ctx, item) => Text(item),
|
|
onChanged: (_) {},
|
|
popup: const SelectPopup(
|
|
items: SelectItemList(
|
|
children: [
|
|
SelectItemButton<String>(value: "Owner", child: Text("Owner")),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(_fill(tester, const Key("row")), testScheme.secondary);
|
|
});
|
|
}
|