Remove reference to MaterialApp and showCupertinoModalPopup from CupertinoAlertDialog (#150725)

This PR removes the usage of Material widgets from unit tests of `CupertinoAlertDialog`. Other than it being just wrong, it also introduces bad behavior, such as the scroll view can't be overscrolled so that the overscroll behavior can't be tested.
* Since there are no longer M2 or M3 variants of tests, I straight up rewrote the unit tests for "default look" with similar tests as those of `CupertinoActionSheet` ([here](https://github.com/flutter/flutter/blob/master/packages/flutter/test/cupertino/action_sheet_test.dart#L21))

This PR also replaces `showCupertinoModalPopup` with `showCupertinoDialog` in `CupertinoAlertDialog`'s example code. The former should only be used by `CupertinoActionSheet`, which has a different animation from the correct `showCupertinoDialog`.
This commit is contained in:
Tong Mu 2024-06-25 15:45:05 -07:00 committed by GitHub
parent a6a8caaa73
commit 98fb56fc05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 138 additions and 97 deletions

View File

@ -23,9 +23,8 @@ class AlertDialogApp extends StatelessWidget {
class AlertDialogExample extends StatelessWidget {
const AlertDialogExample({super.key});
// This shows a CupertinoModalPopup which hosts a CupertinoAlertDialog.
void _showAlertDialog(BuildContext context) {
showCupertinoModalPopup<void>(
showCupertinoDialog<void>(
context: context,
builder: (BuildContext context) => CupertinoAlertDialog(
title: const Text('Alert'),

View File

@ -19,6 +19,69 @@ import 'package:flutter_test/flutter_test.dart';
import '../widgets/semantics_tester.dart';
void main() {
testWidgets('Overall appearance is correct for the light theme', (WidgetTester tester) async {
await tester.pumpWidget(
TestScaffoldApp(
theme: const CupertinoThemeData(brightness: Brightness.light),
dialog: CupertinoAlertDialog(
content: const Text('The content'),
actions: <Widget>[
CupertinoDialogAction(child: const Text('One'), onPressed: () {}),
CupertinoDialogAction(child: const Text('Two'), onPressed: () {}),
],
),
),
);
await tester.tap(find.text('Go'));
await tester.pumpAndSettle();
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('One')));
await tester.pumpAndSettle();
// This golden file also verifies the structure of an alert dialog that
// has a content, no title, and no overscroll for any sections (in contrast
// to cupertinoAlertDialog.dark-theme.png).
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoAlertDialog.overall-light-theme.png'),
);
await gesture.up();
});
testWidgets('Overall appearance is correct for the dark theme', (WidgetTester tester) async {
await tester.pumpWidget(
TestScaffoldApp(
theme: const CupertinoThemeData(brightness: Brightness.dark),
dialog: CupertinoAlertDialog(
title: const Text('The title'),
content: const Text('The content'),
actions: List<Widget>.generate(20, (int i) =>
CupertinoDialogAction(
onPressed: () {},
child: Text('Button $i'),
),
),
),
),
);
await tester.tap(find.text('Go'));
await tester.pumpAndSettle();
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Button 0')));
await tester.pumpAndSettle();
// This golden file also verifies the structure of an action sheet that
// has both a message and a title, and an overscrolled action section (in
// contrast to cupertinoAlertDialog.light-theme.png).
await expectLater(
find.byType(CupertinoApp),
matchesGoldenFile('cupertinoAlertDialog.overall-dark-theme.png'),
);
await gesture.up();
});
testWidgets('Alert dialog control test', (WidgetTester tester) async {
bool didDelete = false;
@ -181,8 +244,8 @@ void main() {
testWidgets('Has semantic annotations', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(const MaterialApp(home: Material(
child: CupertinoAlertDialog(
await tester.pumpWidget(const CupertinoApp(
home: CupertinoAlertDialog(
title: Text('The Title'),
content: Text('Content'),
actions: <Widget>[
@ -190,7 +253,7 @@ void main() {
CupertinoDialogAction(child: Text('OK')),
],
),
)));
));
expect(
semantics,
@ -506,7 +569,7 @@ void main() {
// Check that the title/message section is not displayed
expect(actionScrollController.offset, 0.0);
expect(tester.getTopLeft(find.widgetWithText(CupertinoDialogAction, 'One')).dy, equals(277.5));
expect(tester.getTopLeft(find.widgetWithText(CupertinoDialogAction, 'One')).dy, equals(270.75));
// Check that the button's vertical size is the same.
expect(
@ -1160,7 +1223,7 @@ void main() {
testWidgets('Dialog widget insets by MediaQuery viewInsets', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
const CupertinoApp(
home: MediaQuery(
data: MediaQueryData(),
child: CupertinoAlertDialog(content: Placeholder(fallbackHeight: 200.0)),
@ -1171,7 +1234,7 @@ void main() {
final Rect placeholderRectWithoutInsets = tester.getRect(find.byType(Placeholder));
await tester.pumpWidget(
const MaterialApp(
const CupertinoApp(
home: MediaQuery(
data: MediaQueryData(viewInsets: EdgeInsets.fromLTRB(40.0, 30.0, 20.0, 10.0)),
child: CupertinoAlertDialog(content: Placeholder(fallbackHeight: 200.0)),
@ -1188,70 +1251,6 @@ void main() {
expect(tester.getRect(find.byType(Placeholder)), placeholderRectWithoutInsets.translate(10, 10));
});
testWidgets('Material2 - Default cupertino dialog golden', (WidgetTester tester) async {
await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog(
useMaterial3: false,
dialogBuilder: (BuildContext context) {
return MediaQuery.withClampedTextScaling(
minScaleFactor: 3.0,
maxScaleFactor: 3.0,
child: const RepaintBoundary(
child: CupertinoAlertDialog(
title: Text('Title'),
content: Text('text'),
actions: <Widget>[
CupertinoDialogAction(child: Text('No')),
CupertinoDialogAction(child: Text('OK')),
],
),
),
);
},
),
);
await tester.tap(find.text('Go'));
await tester.pumpAndSettle();
await expectLater(
find.byType(CupertinoAlertDialog),
matchesGoldenFile('m2_dialog_test.cupertino.default.png'),
);
});
testWidgets('Material3 - Default cupertino dialog golden', (WidgetTester tester) async {
await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog(
useMaterial3: true,
dialogBuilder: (BuildContext context) {
return MediaQuery.withClampedTextScaling(
minScaleFactor: 3.0,
maxScaleFactor: 3.0,
child: const RepaintBoundary(
child: CupertinoAlertDialog(
title: Text('Title'),
content: Text('text'),
actions: <Widget>[
CupertinoDialogAction(child: Text('No')),
CupertinoDialogAction(child: Text('OK')),
],
),
),
);
},
),
);
await tester.tap(find.text('Go'));
await tester.pumpAndSettle();
await expectLater(
find.byType(CupertinoAlertDialog),
matchesGoldenFile('m3_dialog_test.cupertino.default.png'),
);
});
testWidgets('showCupertinoDialog - custom barrierLabel', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
@ -1363,7 +1362,7 @@ void main() {
testWidgets('CupertinoAlertDialog scrollbars controllers should be different', (WidgetTester tester) async {
// https://github.com/flutter/flutter/pull/81278
await tester.pumpWidget(
const MaterialApp(
const CupertinoApp(
home: MediaQuery(
data: MediaQueryData(),
child: CupertinoAlertDialog(
@ -1565,24 +1564,20 @@ RenderBox findScrollableActionsSectionRenderBox(WidgetTester tester) {
Widget createAppWithButtonThatLaunchesDialog({
required WidgetBuilder dialogBuilder,
bool? useMaterial3,
}) {
return MaterialApp(
theme: ThemeData(useMaterial3: useMaterial3),
home: Material(
child: Center(
child: Builder(builder: (BuildContext context) {
return ElevatedButton(
onPressed: () {
showDialog<void>(
context: context,
builder: dialogBuilder,
);
},
child: const Text('Go'),
);
}),
),
return CupertinoApp(
home: Center(
child: Builder(builder: (BuildContext context) {
return CupertinoButton(
onPressed: () {
showCupertinoDialog<void>(
context: context,
builder: dialogBuilder,
);
},
child: const Text('Go'),
);
}),
),
);
}
@ -1595,13 +1590,11 @@ Widget boilerplate(Widget child) {
}
Widget createAppWithCenteredButton(Widget child) {
return MaterialApp(
home: Material(
child: Center(
child: ElevatedButton(
onPressed: null,
child: child,
),
return CupertinoApp(
home: Center(
child: CupertinoButton(
onPressed: null,
child: child,
),
),
);
@ -1643,3 +1636,52 @@ class _RestorableDialogTestWidget extends StatelessWidget {
);
}
}
// Shows an app that has a button with text "Go", and clicking this button
// displays the `dialog` and hides the button.
//
// The `theme` will be applied to the app and determines the background.
class TestScaffoldApp extends StatefulWidget {
const TestScaffoldApp({super.key, required this.theme, required this.dialog});
final CupertinoThemeData theme;
final Widget dialog;
@override
TestScaffoldAppState createState() => TestScaffoldAppState();
}
class TestScaffoldAppState extends State<TestScaffoldApp> {
bool _pressedButton = false;
@override
Widget build(BuildContext context) {
return CupertinoApp(
// Hide the debug banner. Because this CupertinoApp is captured in golden
// test as a whole. The debug banner contains tilted text, whose
// anti-alias might cause false negative result.
// https://github.com/flutter/flutter/pull/150442
debugShowCheckedModeBanner: false,
theme: widget.theme,
home: Builder(builder: (BuildContext context) =>
CupertinoPageScaffold(
child: Center(
child: _pressedButton ? Container() : CupertinoButton(
onPressed: () {
setState(() {
_pressedButton = true;
});
showCupertinoDialog<void>(
context: context,
builder: (BuildContext context) {
return widget.dialog;
},
);
},
child: const Text('Go'),
),
),
),
),
);
}
}