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
150 lines
4.5 KiB
Dart
150 lines
4.5 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 group inside a group. The inner one used to install its own scope over the
|
|
// outer one's, so the outer's say was simply lost: the bottom row's field kept
|
|
// the top corners the vertical group had flattened, and painted a top edge the
|
|
// row above had already drawn.
|
|
//
|
|
// Corners are 0-or-1 keep factors, so composing is a product - a corner stays
|
|
// round only where BOTH groups leave it alone.
|
|
|
|
void main() {
|
|
ButtonGroupCorners cornersOf(WidgetTester tester, Type type) {
|
|
final ctx = tester.element(find.byType(type));
|
|
return ButtonGroupScope.maybeOf(ctx)!.corners;
|
|
}
|
|
|
|
ButtonGroupScope scopeOf(WidgetTester tester, Key key) {
|
|
return ButtonGroupScope.maybeOf(tester.element(find.byKey(key)))!;
|
|
}
|
|
|
|
testWidgets("a horizontal group nested in a vertical one composes", (
|
|
tester,
|
|
) async {
|
|
const top = Key("top");
|
|
const bottomStart = Key("bottom-start");
|
|
const bottomEnd = Key("bottom-end");
|
|
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: GarageTheme(
|
|
data: ThemeData(colorScheme: testScheme, density: const Density()),
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 300,
|
|
child: ButtonGroup.vertical(
|
|
expands: true,
|
|
children: [
|
|
const SizedBox(key: top, height: 20),
|
|
// no expands on the inner group - it keeps the
|
|
// IntrinsicHeight that bounds it inside the vertical one.
|
|
ButtonGroup.horizontal(
|
|
children: const [
|
|
Expanded(child: SizedBox(key: bottomStart, height: 20)),
|
|
SizedBox(key: bottomEnd, height: 20, width: 20),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// top row: vertical index 0 - both top corners live, bottom flattened
|
|
// against the row below.
|
|
final t = scopeOf(tester, top);
|
|
expect(
|
|
[t.corners.topStart, t.corners.topEnd],
|
|
[1, 1],
|
|
reason: "the top row keeps its top corners",
|
|
);
|
|
expect(
|
|
[t.corners.bottomStart, t.corners.bottomEnd],
|
|
[0, 0],
|
|
reason: "the top row's bottom is a seam",
|
|
);
|
|
expect(t.hideTop, isFalse);
|
|
expect(t.hideStart, isFalse);
|
|
|
|
// bottom-left: bottom of the vertical group AND start of the horizontal
|
|
// one, so the ONLY surviving corner is bottom-start.
|
|
final bs = scopeOf(tester, bottomStart);
|
|
expect(
|
|
[
|
|
bs.corners.topStart,
|
|
bs.corners.topEnd,
|
|
bs.corners.bottomStart,
|
|
bs.corners.bottomEnd,
|
|
],
|
|
[0, 0, 1, 0],
|
|
reason: "only the outer bottom-start corner survives both groups",
|
|
);
|
|
expect(
|
|
bs.hideTop,
|
|
isTrue,
|
|
reason: "the row above already painted this edge",
|
|
);
|
|
expect(bs.hideStart, isFalse, reason: "its the first in its own row");
|
|
|
|
// bottom-right: bottom of the vertical AND end of the horizontal, so only
|
|
// bottom-end survives - and it gives up BOTH its top and its start edge,
|
|
// which is the pair a single axis+index could never express.
|
|
final be = scopeOf(tester, bottomEnd);
|
|
expect(
|
|
[
|
|
be.corners.topStart,
|
|
be.corners.topEnd,
|
|
be.corners.bottomStart,
|
|
be.corners.bottomEnd,
|
|
],
|
|
[0, 0, 0, 1],
|
|
);
|
|
expect(be.hideTop, isTrue, reason: "the row above painted the top edge");
|
|
expect(
|
|
be.hideStart,
|
|
isTrue,
|
|
reason: "the field beside it painted the start edge",
|
|
);
|
|
});
|
|
|
|
testWidgets("an unnested group is unchanged", (tester) async {
|
|
const a = Key("a");
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: GarageTheme(
|
|
data: ThemeData(colorScheme: testScheme, density: const Density()),
|
|
child: Center(
|
|
child: ButtonGroup.horizontal(
|
|
children: const [
|
|
SizedBox(key: a, height: 20, width: 20),
|
|
SizedBox(height: 20, width: 20),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final s = scopeOf(tester, a);
|
|
expect(
|
|
[
|
|
s.corners.topStart,
|
|
s.corners.topEnd,
|
|
s.corners.bottomStart,
|
|
s.corners.bottomEnd,
|
|
],
|
|
[1, 0, 1, 0],
|
|
);
|
|
expect(s.hideTop, isFalse);
|
|
expect(s.hideStart, isFalse);
|
|
});
|
|
}
|