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
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
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);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user