Unverified Commit e29f2b98 authored by Bruno Leroux's avatar Bruno Leroux Committed by GitHub

Update SnackBar tests for M2/M3 (#130717)

This PR updates unit tests for `SnackBar` to have M2 and M3 versions.

More info in https://github.com/flutter/flutter/issues/127064
parent edcaa335
......@@ -10,6 +10,7 @@ library;
import 'dart:async';
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -302,7 +303,7 @@ void main() {
expect(tapCount, equals(1));
});
testWidgets('Light theme SnackBar has dark background', (WidgetTester tester) async {
testWidgets('Material2 - Light theme SnackBar has dark background', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData.light(useMaterial3: false);
await tester.pumpWidget(
MaterialApp(
......@@ -344,6 +345,45 @@ void main() {
expect(renderModel.color, equals(const Color(0xFF333333)));
});
testWidgets('Material3 - Light theme SnackBar has dark background', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData.light(useMaterial3: true);
await tester.pumpWidget(
MaterialApp(
theme: lightTheme,
home: Scaffold(
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('I am a snack bar.'),
duration: const Duration(seconds: 2),
action: SnackBarAction(
label: 'ACTION',
onPressed: () { },
),
),
);
},
child: const Text('X'),
);
},
),
),
),
);
await tester.tap(find.text('X'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750));
final Finder material = find.widgetWithText(Material, 'I am a snack bar.').first;
final RenderPhysicalModel renderModel = tester.renderObject(material);
expect(renderModel.color, equals(lightTheme.colorScheme.inverseSurface));
});
testWidgets('Dark theme SnackBar has light background', (WidgetTester tester) async {
final ThemeData darkTheme = ThemeData.dark();
await tester.pumpWidget(
......@@ -383,7 +423,7 @@ void main() {
expect(renderModel.color, equals(darkTheme.colorScheme.onSurface));
});
testWidgets('Dark theme SnackBar has primary text buttons', (WidgetTester tester) async {
testWidgets('Material2 - Dark theme SnackBar has primary text buttons', (WidgetTester tester) async {
final ThemeData darkTheme = ThemeData.dark(useMaterial3: false);
await tester.pumpWidget(
MaterialApp(
......@@ -422,6 +462,45 @@ void main() {
expect(buttonTextStyle.color, equals(darkTheme.colorScheme.primary));
});
testWidgets('Material3 - Dark theme SnackBar has primary text buttons', (WidgetTester tester) async {
final ThemeData darkTheme = ThemeData.dark(useMaterial3: true);
await tester.pumpWidget(
MaterialApp(
theme: darkTheme,
home: Scaffold(
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('I am a snack bar.'),
duration: const Duration(seconds: 2),
action: SnackBarAction(
label: 'ACTION',
onPressed: () { },
),
),
);
},
child: const Text('X'),
);
},
),
),
),
);
await tester.tap(find.text('X'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750));
final TextStyle buttonTextStyle = tester.widget<RichText>(
find.descendant(of: find.text('ACTION'), matching: find.byType(RichText))
).text.style!;
expect(buttonTextStyle.color, equals(darkTheme.colorScheme.inversePrimary));
});
testWidgets('SnackBar should inherit theme data from its ancestor.', (WidgetTester tester) async {
final SliderThemeData sliderTheme = SliderThemeData.fromPrimaryColors(
primaryColor: Colors.black,
......@@ -767,9 +846,7 @@ void main() {
expect(snackBarBottomRight.dx, (800 + width) / 2); // Device width is 800.
});
testWidgets(
'Snackbar width customization takes preference of widget over theme',
(WidgetTester tester) async {
testWidgets('Snackbar width customization takes preference of widget over theme', (WidgetTester tester) async {
const double themeWidth = 200.0;
const double widgetWidth = 400.0;
await tester.pumpWidget(
......@@ -812,9 +889,10 @@ void main() {
expect(snackBarBottomRight.dx, (800 + widgetWidth) / 2); // Device width is 800.
});
testWidgets('Snackbar labels can be colored as MaterialColor (Material 2)', (WidgetTester tester) async {
testWidgets('Material2 - Snackbar labels can be colored as MaterialColor', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: false),
home: Scaffold(
body: Builder(
builder: (BuildContext context) {
......@@ -856,8 +934,7 @@ void main() {
}
});
testWidgets('Snackbar labels can be colored as MaterialColor (Material 3)',
(WidgetTester tester) async {
testWidgets('Material3 - Snackbar labels can be colored as MaterialColor', (WidgetTester tester) async {
const MaterialColor usedColor = Colors.teal;
await tester.pumpWidget(
......@@ -960,7 +1037,7 @@ void main() {
}
});
testWidgets('SnackBar button text alignment', (WidgetTester tester) async {
testWidgets('Material2 - SnackBar button text alignment', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: MediaQuery(
......@@ -1008,8 +1085,56 @@ void main() {
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 17.0 + 40.0); // margin + bottom padding
});
testWidgets('Material3 - SnackBar button text alignment', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(
left: 10.0,
top: 20.0,
right: 30.0,
bottom: 40.0,
),
),
child: Scaffold(
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('I am a snack bar.'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () { }),
));
},
child: const Text('X'),
);
},
),
),
),
));
await tester.tap(find.text('X'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750)); // Animation last frame.
final Offset textBottomLeft = tester.getBottomLeft(find.text('I am a snack bar.'));
final Offset textBottomRight = tester.getBottomRight(find.text('I am a snack bar.'));
final Offset actionTextBottomLeft = tester.getBottomLeft(find.text('ACTION'));
final Offset actionTextBottomRight = tester.getBottomRight(find.text('ACTION'));
final Offset snackBarBottomLeft = tester.getBottomLeft(find.byType(SnackBar));
final Offset snackBarBottomRight = tester.getBottomRight(find.byType(SnackBar));
expect(textBottomLeft.dx - snackBarBottomLeft.dx, 24.0 + 10.0); // margin + left padding
expect(snackBarBottomLeft.dy - textBottomLeft.dy, 14.0 + 40.0); // margin + bottom padding
expect(actionTextBottomLeft.dx - textBottomRight.dx, 24.0 + 12.0); // action padding + margin
expect(snackBarBottomRight.dx - actionTextBottomRight.dx, 24.0 + 12.0 + 30.0); // action (padding + margin) + right padding
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 14.0 + 40.0); // margin + bottom padding
});
testWidgets(
'Custom padding between SnackBar and its contents when set to SnackBarBehavior.fixed',
'Material2 - Custom padding between SnackBar and its contents when set to SnackBarBehavior.fixed',
(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
......@@ -1065,6 +1190,63 @@ void main() {
},
);
testWidgets(
'Material3 - Custom padding between SnackBar and its contents when set to SnackBarBehavior.fixed',
(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(
left: 10.0,
top: 20.0,
right: 30.0,
bottom: 40.0,
),
),
child: Scaffold(
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.favorite), label: 'Animutation'),
BottomNavigationBarItem(icon: Icon(Icons.block), label: 'Zombo.com'),
],
),
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('I am a snack bar.'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
));
},
child: const Text('X'),
);
},
),
),
),
));
await tester.tap(find.text('X'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750)); // Animation last frame.
final Offset textBottomLeft = tester.getBottomLeft(find.text('I am a snack bar.'));
final Offset textBottomRight = tester.getBottomRight(find.text('I am a snack bar.'));
final Offset actionTextBottomLeft = tester.getBottomLeft(find.text('ACTION'));
final Offset actionTextBottomRight = tester.getBottomRight(find.text('ACTION'));
final Offset snackBarBottomLeft = tester.getBottomLeft(find.byType(SnackBar));
final Offset snackBarBottomRight = tester.getBottomRight(find.byType(SnackBar));
expect(textBottomLeft.dx - snackBarBottomLeft.dx, 24.0 + 10.0); // margin + left padding
expect(snackBarBottomLeft.dy - textBottomLeft.dy, 14.0); // margin (with no bottom padding)
expect(actionTextBottomLeft.dx - textBottomRight.dx, 24.0 + 12.0); // action padding + margin
expect(snackBarBottomRight.dx - actionTextBottomRight.dx, 24.0 + 12.0 + 30.0); // action (padding + margin) + right padding
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 14.0); // margin (with no bottom padding)
},
);
testWidgets('SnackBar should push FloatingActionButton above', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: MediaQuery(
......@@ -1120,7 +1302,7 @@ void main() {
expect(fabRect.bottomRight.dy, snackBarTopRight.dy - defaultFabPadding);
});
testWidgets('Floating SnackBar button text alignment', (WidgetTester tester) async {
testWidgets('Material2 - Floating SnackBar button text alignment', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
useMaterial3: false,
......@@ -1171,8 +1353,59 @@ void main() {
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 27.0); // margin (with no bottom padding)
});
testWidgets('Material3 - Floating SnackBar button text alignment', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
useMaterial3: true,
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating),
),
home: MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(
left: 10.0,
top: 20.0,
right: 30.0,
bottom: 40.0,
),
),
child: Scaffold(
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('I am a snack bar.'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
));
},
child: const Text('X'),
);
},
),
),
),
));
await tester.tap(find.text('X'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750)); // Animation last frame.
final Offset textBottomLeft = tester.getBottomLeft(find.text('I am a snack bar.'));
final Offset textBottomRight = tester.getBottomRight(find.text('I am a snack bar.'));
final Offset actionTextBottomLeft = tester.getBottomLeft(find.text('ACTION'));
final Offset actionTextBottomRight = tester.getBottomRight(find.text('ACTION'));
final Offset snackBarBottomLeft = tester.getBottomLeft(find.byType(SnackBar));
final Offset snackBarBottomRight = tester.getBottomRight(find.byType(SnackBar));
expect(textBottomLeft.dx - snackBarBottomLeft.dx, 31.0 + 10.0); // margin + left padding
expect(snackBarBottomLeft.dy - textBottomLeft.dy, 24.0); // margin (with no bottom padding)
expect(actionTextBottomLeft.dx - textBottomRight.dx, 16.0 + 8.0); // action padding + margin
expect(snackBarBottomRight.dx - actionTextBottomRight.dx, 31.0 + 30.0 + 8.0); // margin + right (padding + margin)
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 24.0); // margin (with no bottom padding)
});
testWidgets(
'Custom padding between SnackBar and its contents when set to SnackBarBehavior.floating',
'Material2 - Custom padding between SnackBar and its contents when set to SnackBarBehavior.floating',
(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
......@@ -1224,10 +1457,70 @@ void main() {
final Offset snackBarBottomRight = tester.getBottomRight(find.byType(SnackBar));
expect(textBottomLeft.dx - snackBarBottomLeft.dx, 31.0 + 10.0); // margin + left padding
expect(snackBarBottomLeft.dy - textBottomLeft.dy, 27.0); // margin (with no bottom padding)
expect(snackBarBottomLeft.dy - textBottomLeft.dy, 27.0); // margin (with no bottom padding)
expect(actionTextBottomLeft.dx - textBottomRight.dx, 16.0 + 8.0); // action (margin + padding)
expect(snackBarBottomRight.dx - actionTextBottomRight.dx, 31.0 + 30.0 + 8.0); // margin + right (padding + margin)
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 27.0); // margin (with no bottom padding)
},
);
testWidgets(
'Material3 - Custom padding between SnackBar and its contents when set to SnackBarBehavior.floating',
(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
useMaterial3: true,
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating),
),
home: MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(
left: 10.0,
top: 20.0,
right: 30.0,
bottom: 40.0,
),
),
child: Scaffold(
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.favorite), label: 'Animutation'),
BottomNavigationBarItem(icon: Icon(Icons.block), label: 'Zombo.com'),
],
),
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('I am a snack bar.'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
));
},
child: const Text('X'),
);
},
),
),
),
));
await tester.tap(find.text('X'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750)); // Animation last frame.
final Offset textBottomLeft = tester.getBottomLeft(find.text('I am a snack bar.'));
final Offset textBottomRight = tester.getBottomRight(find.text('I am a snack bar.'));
final Offset actionTextBottomLeft = tester.getBottomLeft(find.text('ACTION'));
final Offset actionTextBottomRight = tester.getBottomRight(find.text('ACTION'));
final Offset snackBarBottomLeft = tester.getBottomLeft(find.byType(SnackBar));
final Offset snackBarBottomRight = tester.getBottomRight(find.byType(SnackBar));
expect(textBottomLeft.dx - snackBarBottomLeft.dx, 31.0 + 10.0); // margin + left padding
expect(snackBarBottomLeft.dy - textBottomLeft.dy, 24.0); // margin (with no bottom padding)
expect(actionTextBottomLeft.dx - textBottomRight.dx, 16.0 + 8.0); // action (margin + padding)
expect(snackBarBottomRight.dx - actionTextBottomRight.dx, 31.0 + 30.0 + 8.0); // margin + right (padding + margin)
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 27.0); // margin (with no bottom padding)
expect(snackBarBottomRight.dy - actionTextBottomRight.dy, 24.0); // margin (with no bottom padding)
},
);
......@@ -1858,16 +2151,12 @@ void main() {
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
}
void expectSnackBarNotVisibleError(WidgetTester tester) {
final AssertionError exception = tester.takeException() as AssertionError;
const String message = 'Floating SnackBar presented off screen.\n'
const String offScreenMessage = 'Floating SnackBar presented off screen.\n'
'A SnackBar with behavior property set to SnackBarBehavior.floating is fully '
'or partially off screen because some or all the widgets provided to '
'Scaffold.floatingActionButton, Scaffold.persistentFooterButtons and '
'Scaffold.bottomNavigationBar take up too much vertical space.\n'
'Consider constraining the size of these widgets to allow room for the SnackBar to be visible.';
expect(exception.message, message);
}
testWidgets('Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.floatingActionButton', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/84263
......@@ -1891,12 +2180,14 @@ void main() {
// Run with the Snackbar fully off screen.
await boilerplate(fabHeight: spaceAboveSnackBar + mediumFabHeight * 2);
await openFloatingSnackBar(tester);
expectSnackBarNotVisibleError(tester);
AssertionError exception = tester.takeException() as AssertionError;
expect(exception.message, offScreenMessage);
// Run with the Snackbar partially off screen.
await boilerplate(fabHeight: spaceAboveSnackBar + mediumFabHeight + 10);
await openFloatingSnackBar(tester);
expectSnackBarNotVisibleError(tester);
exception = tester.takeException() as AssertionError;
expect(exception.message, offScreenMessage);
// Run with the Snackbar fully visible right on the top of the screen.
await boilerplate(fabHeight: spaceAboveSnackBar + mediumFabHeight);
......@@ -1904,7 +2195,7 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.persistentFooterButtons', (WidgetTester tester) async {
testWidgets('Material2 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.persistentFooterButtons', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/84263
await tester.pumpWidget(
MaterialApp(
......@@ -1917,10 +2208,36 @@ void main() {
await openFloatingSnackBar(tester);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
expectSnackBarNotVisibleError(tester);
final AssertionError exception = tester.takeException() as AssertionError;
expect(exception.message, offScreenMessage);
});
testWidgets('Material3 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.persistentFooterButtons', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/84263
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
persistentFooterButtons: <Widget>[SizedBox(height: 1000)],
),
),
);
final FlutterExceptionHandler? handler = FlutterError.onError;
final List<String> errorMessages = <String>[];
FlutterError.onError = (FlutterErrorDetails details) {
errorMessages.add(details.exceptionAsString());
};
addTearDown(() => FlutterError.onError = handler);
await openFloatingSnackBar(tester);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
expect(errorMessages.contains(offScreenMessage), isTrue);
});
testWidgets('Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.bottomNavigationBar', (WidgetTester tester) async {
testWidgets('Material2 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.bottomNavigationBar', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/84263
await tester.pumpWidget(
MaterialApp(
......@@ -1933,7 +2250,32 @@ void main() {
await openFloatingSnackBar(tester);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
expectSnackBarNotVisibleError(tester);
final AssertionError exception = tester.takeException() as AssertionError;
expect(exception.message, offScreenMessage);
});
testWidgets('Material3 - Snackbar with SnackBarBehavior.floating will assert when offset too high by a large Scaffold.bottomNavigationBar', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/84263
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
bottomNavigationBar: SizedBox(height: 1000),
),
),
);
final FlutterExceptionHandler? handler = FlutterError.onError;
final List<String> errorMessages = <String>[];
FlutterError.onError = (FlutterErrorDetails details) {
errorMessages.add(details.exceptionAsString());
};
addTearDown(() => FlutterError.onError = handler);
await openFloatingSnackBar(tester);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
expect(errorMessages.contains(offScreenMessage), isTrue);
});
testWidgets(
......@@ -2155,7 +2497,7 @@ void main() {
expect(find.text(snackBarText), findsOneWidget);
});
testWidgets('SnackBars should be shown above the bottomSheet', (WidgetTester tester) async {
testWidgets('Material2 - SnackBars should be shown above the bottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const Scaffold(
......@@ -2178,7 +2520,33 @@ void main() {
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.workWithBottomSheet.png'));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.workWithBottomSheet.png'));
});
testWidgets('Material3 - SnackBars should be shown above the bottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(SnackBar(
content: const Text('I love Flutter!'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
behavior: SnackBarBehavior.floating,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.workWithBottomSheet.png'));
});
testWidgets('ScaffoldMessenger does not duplicate a SnackBar when presenting a MaterialBanner.', (WidgetTester tester) async {
......@@ -2238,7 +2606,7 @@ void main() {
expect(find.text(materialBannerText), findsOneWidget);
});
testWidgets('ScaffoldMessenger presents SnackBars to only the root Scaffold when Scaffolds are nested.', (WidgetTester tester) async {
testWidgets('Material2 - ScaffoldMessenger presents SnackBars to only the root Scaffold when Scaffolds are nested.', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: Scaffold(
......@@ -2265,12 +2633,48 @@ void main() {
// overlapping the FAB.
await expectLater(
find.byType(MaterialApp),
matchesGoldenFile('snack_bar.scaffold.nested.png'),
matchesGoldenFile('m2_snack_bar.scaffold.nested.png'),
);
final Offset snackBarTopRight = tester.getTopRight(find.byType(SnackBar));
expect(snackBarTopRight.dy, 465.0);
});
testWidgets('Material3 - ScaffoldMessenger presents SnackBars to only the root Scaffold when Scaffolds are nested.', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Scaffold(
body: const Scaffold(),
floatingActionButton: FloatingActionButton(onPressed: () {}),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state<ScaffoldMessengerState>(
find.byType(ScaffoldMessenger),
);
scaffoldMessengerState.showSnackBar(SnackBar(
content: const Text('ScaffoldMessenger'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
behavior: SnackBarBehavior.floating,
));
await tester.pumpAndSettle();
expect(find.byType(SnackBar), findsOneWidget);
// The FloatingActionButton helps us identify which Scaffold has the
// SnackBar here. Since the outer Scaffold contains a FAB, the SnackBar
// should be above it. If the inner Scaffold had the SnackBar, it would be
// overlapping the FAB.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.scaffold.nested.png'));
final Offset snackBarTopRight = tester.getTopRight(find.byType(SnackBar));
// TODO(bleroux): https://github.com/flutter/flutter/issues/99933
// A bug in the HTML renderer and/or Chrome 96+ causes a
// discrepancy in the paragraph height.
const bool hasIssue99933 = kIsWeb && !bool.fromEnvironment('FLUTTER_WEB_USE_SKIA');
expect(snackBarTopRight.dy, hasIssue99933 ? 464.0 : 465.0);
});
testWidgets('ScaffoldMessengerState clearSnackBars works as expected', (WidgetTester tester) async {
final List<String> snackBars = <String>['Hello Snackbar', 'Hi Snackbar', 'Bye Snackbar'];
int snackBarCounter = 0;
......@@ -2438,8 +2842,7 @@ void main() {
});
}
testWidgets('Snackbar by default clips BackdropFilter', (WidgetTester tester) async {
testWidgets('Material2 - Snackbar by default clips BackdropFilter', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/98205
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
......@@ -2469,7 +2872,40 @@ void main() {
await tester.tap(find.text('I am a snack bar.'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.backdropFilter.png'));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.backdropFilter.png'));
});
testWidgets('Material3 - Snackbar by default clips BackdropFilter', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/98205
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Scaffold(
body: const Scaffold(),
floatingActionButton: FloatingActionButton(onPressed: () {}),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state<ScaffoldMessengerState>(
find.byType(ScaffoldMessenger),
);
scaffoldMessengerState.showSnackBar(SnackBar(
backgroundColor: Colors.transparent,
content: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 20.0,
sigmaY: 20.0,
),
child: const Text('I am a snack bar.'),
),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
behavior: SnackBarBehavior.fixed,
));
await tester.pumpAndSettle();
await tester.tap(find.text('I am a snack bar.'));
await tester.pump(); // start animation
await tester.pump(const Duration(milliseconds: 750));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.backdropFilter.png'));
});
testWidgets('Floating snackbar can display optional icon', (WidgetTester tester) async {
......@@ -2504,7 +2940,7 @@ void main() {
'snack_bar.goldenTest.floatingWithActionWithIcon.png'));
});
testWidgets('Fixed width snackbar can display optional icon', (WidgetTester tester) async {
testWidgets('Material2 - Fixed width snackbar can display optional icon', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const Scaffold(
......@@ -2528,10 +2964,37 @@ void main() {
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.fixedWithActionWithIcon.png'));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.fixedWithActionWithIcon.png'));
});
testWidgets('Material3 - Fixed width snackbar can display optional icon', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(SnackBar(
content: const Text('Go get a snack'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
showCloseIcon: true,
behavior: SnackBarBehavior.fixed,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.fixedWithActionWithIcon.png'));
});
testWidgets('Fixed snackbar can display optional icon without action', (WidgetTester tester) async {
testWidgets('Material2 - Fixed snackbar can display optional icon without action', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const Scaffold(
......@@ -2556,11 +3019,38 @@ void main() {
);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.fixedWithIcon.png'));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.fixedWithIcon.png'));
});
testWidgets(
'Floating width snackbar can display optional icon without action', (WidgetTester tester) async {
testWidgets('Material3 - Fixed snackbar can display optional icon without action', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(
const SnackBar(
content: Text('I wonder if there are snacks nearby?'),
duration: Duration(seconds: 2),
behavior: SnackBarBehavior.fixed,
showCloseIcon: true,
),
);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.fixedWithIcon.png'));
});
testWidgets('Material2 - Floating width snackbar can display optional icon without action', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const Scaffold(
......@@ -2583,11 +3073,36 @@ void main() {
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp),
matchesGoldenFile('snack_bar.goldenTest.floatingWithIcon.png'));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.floatingWithIcon.png'));
});
testWidgets('Material3 - Floating width snackbar can display optional icon without action', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(const SnackBar(
content: Text('Must go get a snack!'),
duration: Duration(seconds: 2),
showCloseIcon: true,
behavior: SnackBarBehavior.floating,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.floatingWithIcon.png'));
});
testWidgets('Floating multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async {
testWidgets('Material2 - Floating multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const Scaffold(
......@@ -2611,11 +3126,37 @@ void main() {
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp),
matchesGoldenFile('snack_bar.goldenTest.multiLineWithIcon.png'));
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m2_snack_bar.goldenTest.multiLineWithIcon.png'));
});
testWidgets('Material3 - Floating multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(const SnackBar(
content: Text(
'This is a really long snackbar message. So long, it spans across more than one line!'),
duration: Duration(seconds: 2),
showCloseIcon: true,
behavior: SnackBarBehavior.floating,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('m3_snack_bar.goldenTest.multiLineWithIcon.png'));
});
testWidgets('Floating multi-line snackbar with icon and actionOverflowThreshold=1 is aligned correctly', (WidgetTester tester) async {
testWidgets('Material2 - Floating multi-line snackbar with icon and actionOverflowThreshold=1 is aligned correctly', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const Scaffold(
......@@ -2639,8 +3180,40 @@ void main() {
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate in.
await expectLater(find.byType(MaterialApp),
matchesGoldenFile('snack_bar.goldenTest.multiLineWithIconWithZeroActionOverflowThreshold.png'));
await expectLater(
find.byType(MaterialApp),
matchesGoldenFile('m2_snack_bar.goldenTest.multiLineWithIconWithZeroActionOverflowThreshold.png'),
);
});
testWidgets('Material3 - Floating multi-line snackbar with icon and actionOverflowThreshold=1 is aligned correctly', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(const SnackBar(
content: Text('This is a really long snackbar message. So long, it spans across more than one line!'),
duration: Duration(seconds: 2),
showCloseIcon: true,
behavior: SnackBarBehavior.floating,
actionOverflowThreshold: 1,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate in.
await expectLater(
find.byType(MaterialApp),
matchesGoldenFile('m3_snack_bar.goldenTest.multiLineWithIconWithZeroActionOverflowThreshold.png'),
);
});
testWidgets(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment