Skip to content

Commit a6d7124

Browse files
authored
Update BottomSheet test for M3 + fix an issue in elevation resolution (flutter#136071)
This PR updates unit tests from bottom sheet tests for M3 migration. More info in flutter#127064 It also contains in bottom_sheet.dart where a default value took precedence over a theme attribute.
1 parent e27dc0a commit a6d7124

File tree

3 files changed

+205
-48
lines changed

3 files changed

+205
-48
lines changed

packages/flutter/lib/src/material/bottom_sheet.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,7 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
10711071
return _ModalBottomSheet<T>(
10721072
route: this,
10731073
backgroundColor: backgroundColor ?? sheetTheme.modalBackgroundColor ?? sheetTheme.backgroundColor ?? defaults.backgroundColor,
1074-
elevation: elevation ?? sheetTheme.modalElevation ?? defaults.modalElevation ?? sheetTheme.elevation,
1074+
elevation: elevation ?? sheetTheme.modalElevation ?? sheetTheme.elevation ?? defaults.modalElevation,
10751075
shape: shape,
10761076
clipBehavior: clipBehavior,
10771077
constraints: constraints,

packages/flutter/test/material/bottom_sheet_test.dart

Lines changed: 148 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ void main() {
911911
expect(modalBarrier.color, barrierColor);
912912
});
913913

914-
testWidgetsWithLeakTracking('BottomSheet uses fallback values in material3',
914+
testWidgetsWithLeakTracking('Material3 - BottomSheet uses fallback values',
915915
(WidgetTester tester) async {
916916
const Color surfaceColor = Colors.pink;
917917
const Color surfaceTintColor = Colors.blue;
@@ -951,7 +951,7 @@ void main() {
951951
expect(tester.getSize(finder).width, 640);
952952
});
953953

954-
testWidgetsWithLeakTracking('BottomSheet has transparent shadow in material3', (WidgetTester tester) async {
954+
testWidgetsWithLeakTracking('Material3 - BottomSheet has transparent shadow', (WidgetTester tester) async {
955955
await tester.pumpWidget(MaterialApp(
956956
theme: ThemeData(
957957
useMaterial3: true,
@@ -975,7 +975,7 @@ void main() {
975975
expect(material.shadowColor, Colors.transparent);
976976
});
977977

978-
testWidgetsWithLeakTracking('modal BottomSheet with scrollController has semantics', (WidgetTester tester) async {
978+
testWidgetsWithLeakTracking('Material2 - Modal BottomSheet with ScrollController has semantics', (WidgetTester tester) async {
979979
final SemanticsTester semantics = SemanticsTester(tester);
980980
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
981981

@@ -1048,12 +1048,89 @@ void main() {
10481048
semantics.dispose();
10491049
});
10501050

1051-
testWidgetsWithLeakTracking('modal BottomSheet with drag handle has semantics', (WidgetTester tester) async {
1051+
testWidgetsWithLeakTracking('Material3 - Modal BottomSheet with ScrollController has semantics', (WidgetTester tester) async {
10521052
final SemanticsTester semantics = SemanticsTester(tester);
10531053
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
10541054

10551055
await tester.pumpWidget(MaterialApp(
1056-
theme: ThemeData.light(useMaterial3: true),
1056+
theme: ThemeData(useMaterial3: true),
1057+
home: Scaffold(
1058+
key: scaffoldKey,
1059+
body: const Center(child: Text('body')),
1060+
),
1061+
));
1062+
1063+
showModalBottomSheet<void>(
1064+
context: scaffoldKey.currentContext!,
1065+
builder: (BuildContext context) {
1066+
return DraggableScrollableSheet(
1067+
expand: false,
1068+
builder: (_, ScrollController controller) {
1069+
return SingleChildScrollView(
1070+
controller: controller,
1071+
child: const Text('BottomSheet'),
1072+
);
1073+
},
1074+
);
1075+
},
1076+
);
1077+
1078+
await tester.pump(); // bottom sheet show animation starts
1079+
await tester.pump(const Duration(seconds: 1)); // animation done
1080+
1081+
expect(semantics, hasSemantics(TestSemantics.root(
1082+
children: <TestSemantics>[
1083+
TestSemantics.rootChild(
1084+
children: <TestSemantics>[
1085+
TestSemantics(
1086+
children: <TestSemantics>[
1087+
TestSemantics(
1088+
label: 'Dialog',
1089+
textDirection: TextDirection.ltr,
1090+
flags: <SemanticsFlag>[
1091+
SemanticsFlag.scopesRoute,
1092+
SemanticsFlag.namesRoute,
1093+
],
1094+
children: <TestSemantics>[
1095+
TestSemantics(
1096+
children: <TestSemantics>[
1097+
TestSemantics(
1098+
flags: <SemanticsFlag>[SemanticsFlag.hasImplicitScrolling],
1099+
children: <TestSemantics>[
1100+
TestSemantics(
1101+
label: 'BottomSheet',
1102+
textDirection: TextDirection.ltr,
1103+
),
1104+
],
1105+
),
1106+
],
1107+
),
1108+
],
1109+
),
1110+
],
1111+
),
1112+
TestSemantics(
1113+
children: <TestSemantics>[
1114+
TestSemantics(
1115+
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.dismiss],
1116+
label: 'Scrim',
1117+
textDirection: TextDirection.ltr,
1118+
),
1119+
],
1120+
),
1121+
],
1122+
),
1123+
],
1124+
), ignoreTransform: true, ignoreRect: true, ignoreId: true));
1125+
semantics.dispose();
1126+
});
1127+
1128+
testWidgetsWithLeakTracking('Material3 - Modal BottomSheet with drag handle has semantics', (WidgetTester tester) async {
1129+
final SemanticsTester semantics = SemanticsTester(tester);
1130+
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
1131+
1132+
await tester.pumpWidget(MaterialApp(
1133+
theme: ThemeData(useMaterial3: true),
10571134
home: Scaffold(
10581135
key: scaffoldKey,
10591136
body: const Center(child: Text('body')),
@@ -1123,7 +1200,7 @@ void main() {
11231200
const Color hoveringColor=Colors.green;
11241201

11251202
await tester.pumpWidget(MaterialApp(
1126-
theme: ThemeData.light(useMaterial3: true).copyWith(
1203+
theme: ThemeData.light().copyWith(
11271204
bottomSheetTheme: BottomSheetThemeData(
11281205
dragHandleColor: MaterialStateColor.resolveWith((Set<MaterialState> states) {
11291206
if (states.contains(MaterialState.hovered)) {
@@ -1139,7 +1216,6 @@ void main() {
11391216
),
11401217
));
11411218

1142-
11431219
showModalBottomSheet<void>(
11441220
context: scaffoldKey.currentContext!,
11451221
showDragHandle: true,
@@ -1182,7 +1258,6 @@ void main() {
11821258

11831259
testWidgetsWithLeakTracking('showModalBottomSheet does not use root Navigator by default', (WidgetTester tester) async {
11841260
await tester.pumpWidget(MaterialApp(
1185-
theme: ThemeData(useMaterial3: false),
11861261
home: Scaffold(
11871262
body: Navigator(onGenerateRoute: (RouteSettings settings) => MaterialPageRoute<void>(builder: (_) {
11881263
return const _TestPage();
@@ -1207,7 +1282,8 @@ void main() {
12071282

12081283
// Bottom sheet is displayed in correct position within the inner navigator
12091284
// and above the BottomNavigationBar.
1210-
expect(tester.getBottomLeft(find.byType(BottomSheet)).dy, 544.0);
1285+
final double tabBarHeight = tester.getSize(find.byType(BottomNavigationBar)).height;
1286+
expect(tester.getBottomLeft(find.byType(BottomSheet)).dy, 600 - tabBarHeight);
12111287
});
12121288

12131289
testWidgetsWithLeakTracking('showModalBottomSheet uses root Navigator when specified', (WidgetTester tester) async {
@@ -1790,10 +1866,10 @@ void main() {
17901866
});
17911867

17921868
group('constraints', () {
1793-
testWidgetsWithLeakTracking('default constraints are max width 640 in material 3', (WidgetTester tester) async {
1869+
testWidgetsWithLeakTracking('Material3 - Default constraints are max width 640', (WidgetTester tester) async {
17941870
await tester.pumpWidget(
17951871
MaterialApp(
1796-
theme: ThemeData.light(useMaterial3: true),
1872+
theme: ThemeData(useMaterial3: true),
17971873
home: const MediaQuery(
17981874
data: MediaQueryData(size: Size(1000, 1000)),
17991875
child: Scaffold(
@@ -1806,8 +1882,9 @@ void main() {
18061882
expect(tester.getSize(find.byType(Placeholder)).width, 640);
18071883
});
18081884

1809-
testWidgetsWithLeakTracking('No constraints by default for bottomSheet property', (WidgetTester tester) async {
1885+
testWidgetsWithLeakTracking('Material2 - No constraints by default for bottomSheet property', (WidgetTester tester) async {
18101886
await tester.pumpWidget(MaterialApp(
1887+
// This test is specific to Material2 because Material3 sets constraints by default for BottomSheet.
18111888
theme: ThemeData(useMaterial3: false),
18121889
home: const Scaffold(
18131890
body: Center(child: Text('body')),
@@ -1823,6 +1900,7 @@ void main() {
18231900

18241901
testWidgetsWithLeakTracking('No constraints by default for showBottomSheet', (WidgetTester tester) async {
18251902
await tester.pumpWidget(MaterialApp(
1903+
// This test is specific to Material2 because Material3 sets constraints by default for BottomSheet.
18261904
theme: ThemeData(useMaterial3: false),
18271905
home: Scaffold(
18281906
body: Builder(builder: (BuildContext context) {
@@ -1851,6 +1929,7 @@ void main() {
18511929

18521930
testWidgetsWithLeakTracking('No constraints by default for showModalBottomSheet', (WidgetTester tester) async {
18531931
await tester.pumpWidget(MaterialApp(
1932+
// This test is specific to Material2 because Material3 sets constraints by default for BottomSheet.
18541933
theme: ThemeData(useMaterial3: false),
18551934
home: Scaffold(
18561935
body: Builder(builder: (BuildContext context) {
@@ -1878,7 +1957,35 @@ void main() {
18781957
);
18791958
});
18801959

1881-
testWidgetsWithLeakTracking('Theme constraints used for bottomSheet property', (WidgetTester tester) async {
1960+
testWidgetsWithLeakTracking('Material3 - Theme constraints used for bottomSheet property', (WidgetTester tester) async {
1961+
const double sheetMaxWidth = 80.0;
1962+
await tester.pumpWidget(MaterialApp(
1963+
theme: ThemeData(
1964+
useMaterial3: true,
1965+
bottomSheetTheme: const BottomSheetThemeData(
1966+
constraints: BoxConstraints(maxWidth: sheetMaxWidth),
1967+
),
1968+
),
1969+
home: Scaffold(
1970+
body: const Center(child: Text('body')),
1971+
bottomSheet: const Text('BottomSheet'),
1972+
floatingActionButton: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)),
1973+
),
1974+
));
1975+
expect(find.text('BottomSheet'), findsOneWidget);
1976+
1977+
// Should be centered and only 80dp wide.
1978+
final Rect bottomSheetRect = tester.getRect(find.text('BottomSheet'));
1979+
expect(bottomSheetRect.left, 800 / 2 - sheetMaxWidth / 2);
1980+
expect(bottomSheetRect.width, sheetMaxWidth);
1981+
1982+
// Ensure the FAB is overlapping the top of the sheet.
1983+
expect(find.byIcon(Icons.add), findsOneWidget);
1984+
final Rect iconRect = tester.getRect(find.byIcon(Icons.add));
1985+
expect(iconRect.top, bottomSheetRect.top - iconRect.height / 2);
1986+
});
1987+
1988+
testWidgetsWithLeakTracking('Material2 - Theme constraints used for bottomSheet property', (WidgetTester tester) async {
18821989
await tester.pumpWidget(MaterialApp(
18831990
theme: ThemeData(
18841991
useMaterial3: false,
@@ -1907,11 +2014,11 @@ void main() {
19072014
});
19082015

19092016
testWidgetsWithLeakTracking('Theme constraints used for showBottomSheet', (WidgetTester tester) async {
2017+
const double sheetMaxWidth = 80.0;
19102018
await tester.pumpWidget(MaterialApp(
19112019
theme: ThemeData(
1912-
useMaterial3: false,
19132020
bottomSheetTheme: const BottomSheetThemeData(
1914-
constraints: BoxConstraints(maxWidth: 80),
2021+
constraints: BoxConstraints(maxWidth: sheetMaxWidth),
19152022
),
19162023
),
19172024
home: Scaffold(
@@ -1933,19 +2040,19 @@ void main() {
19332040
await tester.tap(find.text('Press me'));
19342041
await tester.pumpAndSettle();
19352042
expect(find.text('BottomSheet'), findsOneWidget);
1936-
// Should be centered and only 80dp wide
1937-
expect(
1938-
tester.getRect(find.text('BottomSheet')),
1939-
const Rect.fromLTRB(360, 558, 440, 600),
1940-
);
2043+
2044+
// Should be centered and only 80dp wide.
2045+
final Rect bottomSheetRect = tester.getRect(find.text('BottomSheet'));
2046+
expect(bottomSheetRect.left, 800 / 2 - sheetMaxWidth / 2);
2047+
expect(bottomSheetRect.width, sheetMaxWidth);
19412048
});
19422049

19432050
testWidgetsWithLeakTracking('Theme constraints used for showModalBottomSheet', (WidgetTester tester) async {
2051+
const double sheetMaxWidth = 80.0;
19442052
await tester.pumpWidget(MaterialApp(
19452053
theme: ThemeData(
1946-
useMaterial3: false,
19472054
bottomSheetTheme: const BottomSheetThemeData(
1948-
constraints: BoxConstraints(maxWidth: 80),
2055+
constraints: BoxConstraints(maxWidth: sheetMaxWidth),
19492056
),
19502057
),
19512058
home: Scaffold(
@@ -1968,17 +2075,17 @@ void main() {
19682075
await tester.tap(find.text('Press me'));
19692076
await tester.pumpAndSettle();
19702077
expect(find.text('BottomSheet'), findsOneWidget);
1971-
// Should be centered and only 80dp wide
1972-
expect(
1973-
tester.getRect(find.text('BottomSheet')),
1974-
const Rect.fromLTRB(360, 558, 440, 600),
1975-
);
2078+
2079+
// Should be centered and only 80dp wide.
2080+
final Rect bottomSheetRect = tester.getRect(find.text('BottomSheet'));
2081+
expect(bottomSheetRect.left, 800 / 2 - sheetMaxWidth / 2);
2082+
expect(bottomSheetRect.width, sheetMaxWidth);
19762083
});
19772084

19782085
testWidgetsWithLeakTracking('constraints param overrides theme for showBottomSheet', (WidgetTester tester) async {
2086+
const double sheetMaxWidth = 100.0;
19792087
await tester.pumpWidget(MaterialApp(
19802088
theme: ThemeData(
1981-
useMaterial3: false,
19822089
bottomSheetTheme: const BottomSheetThemeData(
19832090
constraints: BoxConstraints(maxWidth: 80),
19842091
),
@@ -1991,7 +2098,7 @@ void main() {
19912098
onPressed: () {
19922099
Scaffold.of(context).showBottomSheet<void>(
19932100
(BuildContext context) => const Text('BottomSheet'),
1994-
constraints: const BoxConstraints(maxWidth: 100),
2101+
constraints: const BoxConstraints(maxWidth: sheetMaxWidth),
19952102
);
19962103
},
19972104
),
@@ -2003,17 +2110,17 @@ void main() {
20032110
await tester.tap(find.text('Press me'));
20042111
await tester.pumpAndSettle();
20052112
expect(find.text('BottomSheet'), findsOneWidget);
2006-
// Should be centered and only 100dp wide instead of 80dp wide
2007-
expect(
2008-
tester.getRect(find.text('BottomSheet')),
2009-
const Rect.fromLTRB(350, 572, 450, 600),
2010-
);
2113+
2114+
// Should be centered and only 80dp wide.
2115+
final Rect bottomSheetRect = tester.getRect(find.text('BottomSheet'));
2116+
expect(bottomSheetRect.left, 800 / 2 - sheetMaxWidth / 2);
2117+
expect(bottomSheetRect.width, sheetMaxWidth);
20112118
});
20122119

20132120
testWidgetsWithLeakTracking('constraints param overrides theme for showModalBottomSheet', (WidgetTester tester) async {
2121+
const double sheetMaxWidth = 100.0;
20142122
await tester.pumpWidget(MaterialApp(
20152123
theme: ThemeData(
2016-
useMaterial3: false,
20172124
bottomSheetTheme: const BottomSheetThemeData(
20182125
constraints: BoxConstraints(maxWidth: 80),
20192126
),
@@ -2027,7 +2134,7 @@ void main() {
20272134
showModalBottomSheet<void>(
20282135
context: context,
20292136
builder: (BuildContext context) => const Text('BottomSheet'),
2030-
constraints: const BoxConstraints(maxWidth: 100),
2137+
constraints: const BoxConstraints(maxWidth: sheetMaxWidth),
20312138
);
20322139
},
20332140
),
@@ -2039,11 +2146,11 @@ void main() {
20392146
await tester.tap(find.text('Press me'));
20402147
await tester.pumpAndSettle();
20412148
expect(find.text('BottomSheet'), findsOneWidget);
2042-
// Should be centered and only 100dp instead of 80dp wide
2043-
expect(
2044-
tester.getRect(find.text('BottomSheet')),
2045-
const Rect.fromLTRB(350, 572, 450, 600),
2046-
);
2149+
2150+
// Should be centered and only 80dp wide.
2151+
final Rect bottomSheetRect = tester.getRect(find.text('BottomSheet'));
2152+
expect(bottomSheetRect.left, 800 / 2 - sheetMaxWidth / 2);
2153+
expect(bottomSheetRect.width, sheetMaxWidth);
20472154
});
20482155

20492156
group('scrollControlDisabledMaxHeightRatio', () {

0 commit comments

Comments
 (0)