Skip to content

Commit

Permalink
Remove reference to MaterialApp and showCupertinoModalPopup from …
Browse files Browse the repository at this point in the history
…`CupertinoAlertDialog` (flutter#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`.
  • Loading branch information
dkwingsmt authored Jun 25, 2024
1 parent a6a8caa commit 98fb56f
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down
232 changes: 137 additions & 95 deletions packages/flutter/test/cupertino/dialog_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -181,16 +244,16 @@ 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>[
CupertinoDialogAction(child: Text('Cancel')),
CupertinoDialogAction(child: Text('OK')),
],
),
)));
));

expect(
semantics,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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)),
Expand All @@ -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)),
Expand All @@ -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);

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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'),
);
}),
),
);
}
Expand All @@ -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,
),
),
);
Expand Down Expand Up @@ -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'),
),
),
),
),
);
}
}

0 comments on commit 98fb56f

Please sign in to comment.