"Fossies" - the Fresh Open Source Software Archive 
Member "flutter-3.7.1/packages/flutter/test/material/about_test.dart" (1 Feb 2023, 33643 Bytes) of package /linux/misc/flutter-3.7.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Dart source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the last
Fossies "Diffs" side-by-side code changes report for "about_test.dart":
3.3.10_vs_3.7.0.
1 // Copyright 2014 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 import 'dart:async';
6 import 'dart:ui';
7
8 import 'package:flutter/cupertino.dart';
9 import 'package:flutter/foundation.dart';
10 import 'package:flutter/material.dart';
11 import 'package:flutter_test/flutter_test.dart';
12
13 void main() {
14 tearDown(() {
15 LicenseRegistry.reset();
16 });
17
18 testWidgets('Material3 has sentence case labels', (WidgetTester tester) async {
19 await tester.pumpWidget(MaterialApp(
20 theme: ThemeData(useMaterial3: true),
21 builder: (BuildContext context, Widget? child) {
22 return MediaQuery(
23 // Display has a vertical hinge down the middle
24 data: const MediaQueryData(
25 size: Size(800, 600),
26 displayFeatures: <DisplayFeature>[
27 DisplayFeature(
28 bounds: Rect.fromLTRB(390, 0, 410, 600),
29 type: DisplayFeatureType.hinge,
30 state: DisplayFeatureState.unknown,
31 ),
32 ],
33 ),
34 child: child!,
35 );
36 },
37 home: Builder(
38 builder: (BuildContext context) => ElevatedButton(
39 onPressed: () {
40 showAboutDialog(
41 context: context,
42 useRootNavigator: false,
43 applicationName: 'A',
44 );
45 },
46 child: const Text('Show About Dialog'),
47 ),
48 ),
49 ));
50
51 // Open the dialog.
52 await tester.tap(find.byType(ElevatedButton));
53 await tester.pumpAndSettle();
54 expect(find.text('Close'), findsOneWidget);
55 expect(find.text('View licenses'), findsOneWidget);
56 });
57
58 testWidgets('AboutListTile control test', (WidgetTester tester) async {
59 const FlutterLogo logo = FlutterLogo();
60
61 await tester.pumpWidget(
62 MaterialApp(
63 title: 'Pirate app',
64 home: Scaffold(
65 appBar: AppBar(
66 title: const Text('Home'),
67 ),
68 drawer: Drawer(
69 child: ListView(
70 children: const <Widget>[
71 AboutListTile(
72 applicationVersion: '0.1.2',
73 applicationIcon: logo,
74 applicationLegalese: 'I am the very model of a modern major general.',
75 aboutBoxChildren: <Widget>[
76 Text('About box'),
77 ],
78 ),
79 ],
80 ),
81 ),
82 ),
83 ),
84 );
85
86 expect(find.text('About Pirate app'), findsNothing);
87 expect(find.text('0.1.2'), findsNothing);
88 expect(find.byWidget(logo), findsNothing);
89 expect(
90 find.text('I am the very model of a modern major general.'),
91 findsNothing,
92 );
93 expect(find.text('About box'), findsNothing);
94
95 await tester.tap(find.byType(IconButton));
96 await tester.pumpAndSettle();
97
98 expect(find.text('About Pirate app'), findsOneWidget);
99 expect(find.text('0.1.2'), findsNothing);
100 expect(find.byWidget(logo), findsNothing);
101 expect(
102 find.text('I am the very model of a modern major general.'),
103 findsNothing,
104 );
105 expect(find.text('About box'), findsNothing);
106
107 await tester.tap(find.text('About Pirate app'));
108 await tester.pumpAndSettle();
109
110 expect(find.text('About Pirate app'), findsOneWidget);
111 expect(find.text('0.1.2'), findsOneWidget);
112 expect(find.byWidget(logo), findsOneWidget);
113 expect(
114 find.text('I am the very model of a modern major general.'),
115 findsOneWidget,
116 );
117 expect(find.text('About box'), findsOneWidget);
118
119 LicenseRegistry.addLicense(() {
120 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
121 const LicenseEntryWithLineBreaks(<String>['Pirate package '], 'Pirate license'),
122 ]);
123 });
124
125 await tester.tap(find.text('VIEW LICENSES'));
126 await tester.pumpAndSettle();
127
128 expect(find.text('Pirate app'), findsOneWidget);
129 expect(find.text('0.1.2'), findsOneWidget);
130 expect(find.byWidget(logo), findsOneWidget);
131 expect(
132 find.text('I am the very model of a modern major general.'),
133 findsOneWidget,
134 );
135 await tester.tap(find.text('Pirate package '));
136 await tester.pumpAndSettle();
137 expect(find.text('Pirate license'), findsOneWidget);
138 });
139
140 testWidgets('About box logic defaults to executable name for app name', (WidgetTester tester) async {
141 await tester.pumpWidget(
142 const MaterialApp(
143 title: 'flutter_tester',
144 home: Material(child: AboutListTile()),
145 ),
146 );
147 expect(find.text('About flutter_tester'), findsOneWidget);
148 });
149
150 testWidgets('LicensePage control test', (WidgetTester tester) async {
151 LicenseRegistry.addLicense(() {
152 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
153 const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
154 ]);
155 });
156
157 LicenseRegistry.addLicense(() {
158 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
159 const LicenseEntryWithLineBreaks(
160 <String>['Another package'],
161 'Another license',
162 ),
163 ]);
164 });
165
166 await tester.pumpWidget(
167 const MaterialApp(
168 home: Center(
169 child: LicensePage(),
170 ),
171 ),
172 );
173
174 expect(find.text('AAA'), findsNothing);
175 expect(find.text('BBB'), findsNothing);
176 expect(find.text('Another package'), findsNothing);
177 expect(find.text('Another license'), findsNothing);
178
179 await tester.pumpAndSettle();
180
181 // Check for packages.
182 expect(find.text('AAA'), findsOneWidget);
183 expect(find.text('Another package'), findsOneWidget);
184
185 // Check license is displayed after entering into license page for 'AAA'.
186 await tester.tap(find.text('AAA'));
187 await tester.pumpAndSettle();
188 expect(find.text('BBB'), findsOneWidget);
189
190 /// Go back to list of packages.
191 await tester.pageBack();
192 await tester.pumpAndSettle();
193
194 /// Check license is displayed after entering into license page for
195 /// 'Another package'.
196 await tester.tap(find.text('Another package'));
197 await tester.pumpAndSettle();
198 expect(find.text('Another license'), findsOneWidget);
199 });
200
201 testWidgets('LicensePage control test with all properties', (WidgetTester tester) async {
202 const FlutterLogo logo = FlutterLogo();
203
204 LicenseRegistry.addLicense(() {
205 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
206 const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
207 ]);
208 });
209
210 LicenseRegistry.addLicense(() {
211 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
212 const LicenseEntryWithLineBreaks(
213 <String>['Another package'],
214 'Another license',
215 ),
216 ]);
217 });
218
219 await tester.pumpWidget(
220 const MaterialApp(
221 title: 'Pirate app',
222 home: Center(
223 child: LicensePage(
224 applicationName: 'LicensePage test app',
225 applicationVersion: '0.1.2',
226 applicationIcon: logo,
227 applicationLegalese: 'I am the very model of a modern major general.',
228 ),
229 ),
230 ),
231 );
232
233 expect(find.text('Pirate app'), findsNothing);
234 expect(find.text('LicensePage test app'), findsOneWidget);
235 expect(find.text('0.1.2'), findsOneWidget);
236 expect(find.byWidget(logo), findsOneWidget);
237 expect(
238 find.text('I am the very model of a modern major general.'),
239 findsOneWidget,
240 );
241 expect(find.text('AAA'), findsNothing);
242 expect(find.text('BBB'), findsNothing);
243 expect(find.text('Another package'), findsNothing);
244 expect(find.text('Another license'), findsNothing);
245
246 await tester.pumpAndSettle();
247
248 expect(find.text('Pirate app'), findsNothing);
249 expect(find.text('LicensePage test app'), findsOneWidget);
250 expect(find.text('0.1.2'), findsOneWidget);
251 expect(find.byWidget(logo), findsOneWidget);
252 expect(
253 find.text('I am the very model of a modern major general.'),
254 findsOneWidget,
255 );
256
257 // Check for packages.
258 expect(find.text('AAA'), findsOneWidget);
259 expect(find.text('Another package'), findsOneWidget);
260
261 // Check license is displayed after entering into license page for 'AAA'.
262 await tester.tap(find.text('AAA'));
263 await tester.pumpAndSettle();
264 expect(find.text('BBB'), findsOneWidget);
265
266 /// Go back to list of packages.
267 await tester.pageBack();
268 await tester.pumpAndSettle();
269
270 /// Check license is displayed after entering into license page for
271 /// 'Another package'.
272 await tester.tap(find.text('Another package'));
273 await tester.pumpAndSettle();
274 expect(find.text('Another license'), findsOneWidget);
275 });
276
277 testWidgets('_PackageLicensePage title style without AppBarTheme', (WidgetTester tester) async {
278 LicenseRegistry.addLicense(() {
279 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
280 const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
281 ]);
282 });
283
284 const TextStyle titleTextStyle = TextStyle(
285 fontSize: 20,
286 color: Colors.black,
287 inherit: false,
288 );
289 const TextStyle subtitleTextStyle = TextStyle(
290 fontSize: 15,
291 color: Colors.red,
292 inherit: false,
293 );
294
295 await tester.pumpWidget(
296 MaterialApp(
297 theme: ThemeData(
298 primaryTextTheme: const TextTheme(
299 titleLarge: titleTextStyle,
300 titleSmall: subtitleTextStyle,
301 ),
302 ),
303 home: const Center(
304 child: LicensePage(),
305 ),
306 ),
307 );
308 await tester.pumpAndSettle();
309
310 // Check for packages.
311 expect(find.text('AAA'), findsOneWidget);
312
313 // Check license is displayed after entering into license page for 'AAA'.
314 await tester.tap(find.text('AAA'));
315 await tester.pumpAndSettle();
316
317 // Check for titles style.
318 final Text title = tester.widget(find.text('AAA'));
319 expect(title.style, titleTextStyle);
320 final Text subtitle = tester.widget(find.text('1 license.'));
321 expect(subtitle.style, subtitleTextStyle);
322 });
323
324 testWidgets('_PackageLicensePage title style with AppBarTheme', (WidgetTester tester) async {
325 LicenseRegistry.addLicense(() {
326 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
327 const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
328 ]);
329 });
330
331 const TextStyle titleTextStyle = TextStyle(
332 fontSize: 20,
333 color: Colors.indigo,
334 );
335 const TextStyle subtitleTextStyle = TextStyle(
336 fontSize: 15,
337 color: Colors.indigo,
338 );
339
340 await tester.pumpWidget(
341 MaterialApp(
342 theme: ThemeData(
343 // Not used because appBarTheme is prioritized.
344 primaryTextTheme: const TextTheme(
345 titleLarge: TextStyle(
346 fontSize: 12,
347 color: Colors.grey,
348 ),
349 titleSmall: TextStyle(
350 fontSize: 10,
351 color: Colors.grey,
352 ),
353 ),
354 appBarTheme: const AppBarTheme(
355 textTheme: TextTheme(
356 titleLarge: titleTextStyle,
357 titleSmall: subtitleTextStyle,
358 ),
359 foregroundColor: Colors.indigo,
360 ),
361 ),
362 home: const Center(
363 child: LicensePage(),
364 ),
365 ),
366 );
367 await tester.pumpAndSettle();
368
369 // Check for packages.
370 expect(find.text('AAA'), findsOneWidget);
371
372 // Check license is displayed after entering into license page for 'AAA'.
373 await tester.tap(find.text('AAA'));
374 await tester.pumpAndSettle();
375
376 // Check for titles style.
377 final Text title = tester.widget(find.text('AAA'));
378 expect(title.style, titleTextStyle);
379 final Text subtitle = tester.widget(find.text('1 license.'));
380 expect(subtitle.style, subtitleTextStyle);
381 });
382
383 testWidgets('LicensePage respects the notch', (WidgetTester tester) async {
384 const double safeareaPadding = 27.0;
385
386 LicenseRegistry.addLicense(() {
387 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
388 const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
389 ]);
390 });
391
392 await tester.pumpWidget(
393 const MaterialApp(
394 home: MediaQuery(
395 data: MediaQueryData(
396 padding: EdgeInsets.all(safeareaPadding),
397 ),
398 child: LicensePage(),
399 ),
400 ),
401 );
402
403 await tester.pumpAndSettle();
404
405 // The position of the top left of app bar title should indicate whether
406 // the safe area is sufficiently respected.
407 expect(
408 tester.getTopLeft(find.text('Licenses')),
409 const Offset(16.0 + safeareaPadding, 18.0 + safeareaPadding),
410 );
411 });
412
413 testWidgets('LicensePage returns early if unmounted', (WidgetTester tester) async {
414 final Completer<LicenseEntry> licenseCompleter = Completer<LicenseEntry>();
415 LicenseRegistry.addLicense(() {
416 return Stream<LicenseEntry>.fromFuture(licenseCompleter.future);
417 });
418
419 await tester.pumpWidget(
420 const MaterialApp(
421 home: LicensePage(),
422 ),
423 );
424 await tester.pump();
425
426 await tester.pumpWidget(
427 const MaterialApp(
428 home: Placeholder(),
429 ),
430 );
431
432 await tester.pumpAndSettle();
433 final FakeLicenseEntry licenseEntry = FakeLicenseEntry();
434 licenseCompleter.complete(licenseEntry);
435 expect(licenseEntry.packagesCalled, false);
436 });
437
438 testWidgets('LicensePage returns late if unmounted', (WidgetTester tester) async {
439 final Completer<LicenseEntry> licenseCompleter = Completer<LicenseEntry>();
440 LicenseRegistry.addLicense(() {
441 return Stream<LicenseEntry>.fromFuture(licenseCompleter.future);
442 });
443
444 await tester.pumpWidget(
445 const MaterialApp(
446 home: LicensePage(),
447 ),
448 );
449 await tester.pump();
450 final FakeLicenseEntry licenseEntry = FakeLicenseEntry();
451 licenseCompleter.complete(licenseEntry);
452
453 await tester.pumpWidget(
454 const MaterialApp(
455 home: Placeholder(),
456 ),
457 );
458
459 await tester.pumpAndSettle();
460 expect(licenseEntry.packagesCalled, true);
461 });
462
463 testWidgets('LicensePage logic defaults to executable name for app name', (WidgetTester tester) async {
464 await tester.pumpWidget(
465 const MaterialApp(
466 title: 'flutter_tester',
467 home: Material(child: LicensePage()),
468 ),
469 );
470 expect(find.text('flutter_tester'), findsOneWidget);
471 });
472
473 testWidgets('AboutListTile dense property is applied', (WidgetTester tester) async {
474 await tester.pumpWidget(const MaterialApp(
475 home: Material(child: Center(child: AboutListTile())),
476 ));
477 Rect tileRect = tester.getRect(find.byType(AboutListTile));
478 expect(tileRect.height, 56.0);
479
480 await tester.pumpWidget(const MaterialApp(
481 home: Material(child: Center(child: AboutListTile(dense: false))),
482 ));
483 tileRect = tester.getRect(find.byType(AboutListTile));
484 expect(tileRect.height, 56.0);
485
486 await tester.pumpWidget(const MaterialApp(
487 home: Material(child: Center(child: AboutListTile(dense: true))),
488 ));
489 tileRect = tester.getRect(find.byType(AboutListTile));
490 expect(tileRect.height, 48.0);
491 });
492
493 testWidgets('showLicensePage uses nested navigator by default', (WidgetTester tester) async {
494 final LicensePageObserver rootObserver = LicensePageObserver();
495 final LicensePageObserver nestedObserver = LicensePageObserver();
496
497 await tester.pumpWidget(MaterialApp(
498 navigatorObservers: <NavigatorObserver>[rootObserver],
499 initialRoute: '/',
500 onGenerateRoute: (_) {
501 return PageRouteBuilder<dynamic>(
502 pageBuilder: (_, __, ___) => Navigator(
503 observers: <NavigatorObserver>[nestedObserver],
504 onGenerateRoute: (RouteSettings settings) {
505 return PageRouteBuilder<dynamic>(
506 pageBuilder: (BuildContext context, _, __) {
507 return ElevatedButton(
508 onPressed: () {
509 showLicensePage(
510 context: context,
511 applicationName: 'A',
512 );
513 },
514 child: const Text('Show License Page'),
515 );
516 },
517 );
518 },
519 ),
520 );
521 },
522 ));
523
524 // Open the dialog.
525 await tester.tap(find.byType(ElevatedButton));
526
527 expect(rootObserver.licensePageCount, 0);
528 expect(nestedObserver.licensePageCount, 1);
529 });
530
531 testWidgets('showLicensePage uses root navigator if useRootNavigator is true', (WidgetTester tester) async {
532 final LicensePageObserver rootObserver = LicensePageObserver();
533 final LicensePageObserver nestedObserver = LicensePageObserver();
534
535 await tester.pumpWidget(MaterialApp(
536 navigatorObservers: <NavigatorObserver>[rootObserver],
537 initialRoute: '/',
538 onGenerateRoute: (_) {
539 return PageRouteBuilder<dynamic>(
540 pageBuilder: (_, __, ___) => Navigator(
541 observers: <NavigatorObserver>[nestedObserver],
542 onGenerateRoute: (RouteSettings settings) {
543 return PageRouteBuilder<dynamic>(
544 pageBuilder: (BuildContext context, _, __) {
545 return ElevatedButton(
546 onPressed: () {
547 showLicensePage(
548 context: context,
549 useRootNavigator: true,
550 applicationName: 'A',
551 );
552 },
553 child: const Text('Show License Page'),
554 );
555 },
556 );
557 },
558 ),
559 );
560 },
561 ));
562
563 // Open the dialog.
564 await tester.tap(find.byType(ElevatedButton));
565
566 expect(rootObserver.licensePageCount, 1);
567 expect(nestedObserver.licensePageCount, 0);
568 });
569
570 testWidgets('showAboutDialog uses root navigator by default', (WidgetTester tester) async {
571 final AboutDialogObserver rootObserver = AboutDialogObserver();
572 final AboutDialogObserver nestedObserver = AboutDialogObserver();
573
574 await tester.pumpWidget(MaterialApp(
575 navigatorObservers: <NavigatorObserver>[rootObserver],
576 home: Navigator(
577 observers: <NavigatorObserver>[nestedObserver],
578 onGenerateRoute: (RouteSettings settings) {
579 return MaterialPageRoute<dynamic>(
580 builder: (BuildContext context) {
581 return ElevatedButton(
582 onPressed: () {
583 showAboutDialog(
584 context: context,
585 applicationName: 'A',
586 );
587 },
588 child: const Text('Show About Dialog'),
589 );
590 },
591 );
592 },
593 ),
594 ));
595
596 // Open the dialog.
597 await tester.tap(find.byType(ElevatedButton));
598
599 expect(rootObserver.dialogCount, 1);
600 expect(nestedObserver.dialogCount, 0);
601 });
602
603 testWidgets('showAboutDialog uses nested navigator if useRootNavigator is false', (WidgetTester tester) async {
604 final AboutDialogObserver rootObserver = AboutDialogObserver();
605 final AboutDialogObserver nestedObserver = AboutDialogObserver();
606
607 await tester.pumpWidget(MaterialApp(
608 navigatorObservers: <NavigatorObserver>[rootObserver],
609 home: Navigator(
610 observers: <NavigatorObserver>[nestedObserver],
611 onGenerateRoute: (RouteSettings settings) {
612 return MaterialPageRoute<dynamic>(
613 builder: (BuildContext context) {
614 return ElevatedButton(
615 onPressed: () {
616 showAboutDialog(
617 context: context,
618 useRootNavigator: false,
619 applicationName: 'A',
620 );
621 },
622 child: const Text('Show About Dialog'),
623 );
624 },
625 );
626 },
627 ),
628 ));
629
630 // Open the dialog.
631 await tester.tap(find.byType(ElevatedButton));
632
633 expect(rootObserver.dialogCount, 0);
634 expect(nestedObserver.dialogCount, 1);
635 });
636
637 group('showAboutDialog avoids overlapping display features', () {
638 testWidgets('default positioning', (WidgetTester tester) async {
639 await tester.pumpWidget(MaterialApp(
640 builder: (BuildContext context, Widget? child) {
641 return MediaQuery(
642 // Display has a vertical hinge down the middle
643 data: const MediaQueryData(
644 size: Size(800, 600),
645 displayFeatures: <DisplayFeature>[
646 DisplayFeature(
647 bounds: Rect.fromLTRB(390, 0, 410, 600),
648 type: DisplayFeatureType.hinge,
649 state: DisplayFeatureState.unknown,
650 ),
651 ],
652 ),
653 child: child!,
654 );
655 },
656 home: Builder(
657 builder: (BuildContext context) => ElevatedButton(
658 onPressed: () {
659 showAboutDialog(
660 context: context,
661 useRootNavigator: false,
662 applicationName: 'A',
663 );
664 },
665 child: const Text('Show About Dialog'),
666 ),
667 ),
668 ));
669
670 // Open the dialog.
671 await tester.tap(find.byType(ElevatedButton));
672 await tester.pumpAndSettle();
673
674 // By default it should place the dialog on the left screen
675 expect(tester.getTopLeft(find.byType(AboutDialog)), Offset.zero);
676 expect(tester.getBottomRight(find.byType(AboutDialog)), const Offset(390.0, 600.0));
677 });
678
679 testWidgets('positioning using anchorPoint', (WidgetTester tester) async {
680 await tester.pumpWidget(MaterialApp(
681 builder: (BuildContext context, Widget? child) {
682 return MediaQuery(
683 // Display has a vertical hinge down the middle
684 data: const MediaQueryData(
685 size: Size(800, 600),
686 displayFeatures: <DisplayFeature>[
687 DisplayFeature(
688 bounds: Rect.fromLTRB(390, 0, 410, 600),
689 type: DisplayFeatureType.hinge,
690 state: DisplayFeatureState.unknown,
691 ),
692 ],
693 ),
694 child: child!,
695 );
696 },
697 home: Builder(
698 builder: (BuildContext context) => ElevatedButton(
699 onPressed: () {
700 showAboutDialog(
701 context: context,
702 useRootNavigator: false,
703 applicationName: 'A',
704 anchorPoint: const Offset(1000, 0),
705 );
706 },
707 child: const Text('Show About Dialog'),
708 ),
709 ),
710 ));
711
712 // Open the dialog.
713 await tester.tap(find.byType(ElevatedButton));
714 await tester.pumpAndSettle();
715
716 // The anchorPoint hits the right side of the display
717 expect(tester.getTopLeft(find.byType(AboutDialog)), const Offset(410.0, 0.0));
718 expect(tester.getBottomRight(find.byType(AboutDialog)), const Offset(800.0, 600.0));
719 });
720
721 testWidgets('positioning using Directionality', (WidgetTester tester) async {
722 await tester.pumpWidget(MaterialApp(
723 builder: (BuildContext context, Widget? child) {
724 return MediaQuery(
725 // Display has a vertical hinge down the middle
726 data: const MediaQueryData(
727 size: Size(800, 600),
728 displayFeatures: <DisplayFeature>[
729 DisplayFeature(
730 bounds: Rect.fromLTRB(390, 0, 410, 600),
731 type: DisplayFeatureType.hinge,
732 state: DisplayFeatureState.unknown,
733 ),
734 ],
735 ),
736 child: Directionality(
737 textDirection: TextDirection.rtl,
738 child: child!,
739 ),
740 );
741 },
742 home: Builder(
743 builder: (BuildContext context) => ElevatedButton(
744 onPressed: () {
745 showAboutDialog(
746 context: context,
747 useRootNavigator: false,
748 applicationName: 'A',
749 );
750 },
751 child: const Text('Show About Dialog'),
752 ),
753 ),
754 ));
755
756 // Open the dialog.
757 await tester.tap(find.byType(ElevatedButton));
758 await tester.pumpAndSettle();
759
760 // Since this is rtl, the first screen is the on the right
761 expect(tester.getTopLeft(find.byType(AboutDialog)), const Offset(410.0, 0.0));
762 expect(tester.getBottomRight(find.byType(AboutDialog)), const Offset(800.0, 600.0));
763 });
764 });
765
766 testWidgets("AboutListTile's child should not be offset when the icon is not specified.", (WidgetTester tester) async {
767 await tester.pumpWidget(
768 const MaterialApp(
769 home: Scaffold(
770 body: AboutListTile(
771 child: Text('About'),
772 ),
773 ),
774 ),
775 );
776
777 expect(
778 find.descendant(
779 of: find.byType(AboutListTile),
780 matching: find.byType(Icon),
781 ),
782 findsNothing,
783 );
784 });
785
786 testWidgets("AboutDialog's contents are scrollable", (WidgetTester tester) async {
787 final Key contentKey = UniqueKey();
788 await tester.pumpWidget(MaterialApp(
789 home: Navigator(
790 onGenerateRoute: (RouteSettings settings) {
791 return MaterialPageRoute<dynamic>(
792 builder: (BuildContext context) {
793 return ElevatedButton(
794 onPressed: () {
795 showAboutDialog(
796 context: context,
797 useRootNavigator: false,
798 applicationName: 'A',
799 children: <Widget>[
800 Container(
801 key: contentKey,
802 color: Colors.orange,
803 height: 500,
804 ),
805 ],
806 );
807 },
808 child: const Text('Show About Dialog'),
809 );
810 },
811 );
812 },
813 ),
814 ));
815
816 await tester.tap(find.text('Show About Dialog'));
817 await tester.pumpAndSettle();
818
819 // Try dragging by the [AboutDialog]'s title.
820 RenderBox box = tester.renderObject(find.text('A'));
821 Offset originalOffset = box.localToGlobal(Offset.zero);
822 await tester.drag(find.byKey(contentKey), const Offset(0.0, -20.0));
823
824 expect(box.localToGlobal(Offset.zero), equals(originalOffset.translate(0.0, -20.0)));
825
826 // Try dragging by the additional children in contents.
827 box = tester.renderObject(find.byKey(contentKey));
828 originalOffset = box.localToGlobal(Offset.zero);
829 await tester.drag(find.byKey(contentKey), const Offset(0.0, -20.0));
830
831 expect(box.localToGlobal(Offset.zero), equals(originalOffset.translate(0.0, -20.0)));
832 });
833
834 testWidgets("LicensePage's color must be same whether loading or done", (WidgetTester tester) async {
835 const Color scaffoldColor = Color(0xFF123456);
836 const Color cardColor = Color(0xFF654321);
837
838 await tester.pumpWidget(MaterialApp(
839 theme: ThemeData.light().copyWith(
840 scaffoldBackgroundColor: scaffoldColor,
841 cardColor: cardColor,
842 ),
843 home: Scaffold(
844 body: Center(
845 child: Builder(
846 builder: (BuildContext context) => GestureDetector(
847 child: const Text('Show licenses'),
848 onTap: () {
849 showLicensePage(
850 context: context,
851 applicationName: 'MyApp',
852 applicationVersion: '1.0.0',
853 );
854 },
855 ),
856 ),
857 ),
858 ),
859 ));
860
861 await tester.tap(find.text('Show licenses'));
862 await tester.pump();
863 await tester.pump();
864
865 // Check color when loading.
866 final List<Material> materialLoadings = tester.widgetList<Material>(find.byType(Material)).toList();
867 expect(materialLoadings.length, equals(4));
868 expect(materialLoadings[1].color, scaffoldColor);
869 expect(materialLoadings[2].color, cardColor);
870
871 await tester.pumpAndSettle();
872
873 // Check color when done.
874 expect(find.byKey(const ValueKey<ConnectionState>(ConnectionState.done)), findsOneWidget);
875 final List<Material> materialDones = tester.widgetList<Material>(find.byType(Material)).toList();
876 expect(materialDones.length, equals(3));
877 expect(materialDones[0].color, scaffoldColor);
878 expect(materialDones[1].color, cardColor);
879 });
880
881 testWidgets('Conflicting scrollbars are not applied by ScrollBehavior to _PackageLicensePage', (WidgetTester tester) async {
882 // Regression test for https://github.com/flutter/flutter/issues/83819
883 LicenseRegistry.addLicense(() {
884 return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
885 const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
886 ]);
887 });
888
889 await tester.pumpWidget(
890 const MaterialApp(
891 home: Center(
892 child: LicensePage(),
893 ),
894 ),
895 );
896 await tester.pumpAndSettle();
897
898 // Check for packages.
899 expect(find.text('AAA'), findsOneWidget);
900 // Check license is displayed after entering into license page for 'AAA'.
901 await tester.tap(find.text('AAA'));
902 await tester.pumpAndSettle();
903
904 // The inherited ScrollBehavior should not apply Scrollbars since they are
905 // already built in to the widget.
906 switch (debugDefaultTargetPlatformOverride) {
907 case TargetPlatform.android:
908 case TargetPlatform.fuchsia:
909 case TargetPlatform.linux:
910 case TargetPlatform.macOS:
911 case TargetPlatform.windows:
912 expect(find.byType(CupertinoScrollbar), findsNothing);
913 break;
914 case TargetPlatform.iOS:
915 expect(find.byType(CupertinoScrollbar), findsOneWidget);
916 break;
917 case null:
918 break;
919 }
920 expect(find.byType(Scrollbar), findsOneWidget);
921 expect(find.byType(RawScrollbar), findsNothing);
922
923 }, variant: TargetPlatformVariant.all());
924
925 testWidgets('LicensePage padding', (WidgetTester tester) async {
926 const FlutterLogo logo = FlutterLogo();
927
928 await tester.pumpWidget(
929 const MaterialApp(
930 title: 'Pirate app',
931 home: Center(
932 child: LicensePage(
933 applicationName: 'LicensePage test app',
934 applicationIcon: logo,
935 applicationVersion: '0.1.2',
936 applicationLegalese: 'I am the very model of a modern major general.',
937 ),
938 ),
939 ),
940 );
941
942 final Finder appName = find.text('LicensePage test app');
943 final Finder appIcon = find.byType(FlutterLogo);
944 final Finder appVersion = find.text('0.1.2');
945 final Finder appLegalese = find.text('I am the very model of a modern major general.');
946 final Finder appPowered = find.text('Powered by Flutter');
947
948 expect(appName, findsOneWidget);
949 expect(appIcon, findsOneWidget);
950 expect(appVersion, findsOneWidget);
951 expect(appLegalese, findsOneWidget);
952 expect(appPowered, findsOneWidget);
953
954 // Bottom padding is applied to the app version and app legalese text.
955 final double appNameBottomPadding = tester.getTopLeft(appIcon).dy - tester.getBottomLeft(appName).dy;
956 expect(appNameBottomPadding, 0.0);
957
958 final double appIconBottomPadding = tester.getTopLeft(appVersion).dy - tester.getBottomLeft(appIcon).dy;
959 expect(appIconBottomPadding, 0.0);
960
961 final double appVersionBottomPadding = tester.getTopLeft(appLegalese).dy - tester.getBottomLeft(appVersion).dy;
962 expect(appVersionBottomPadding, 18.0);
963
964 final double appLegaleseBottomPadding = tester.getTopLeft(appPowered).dy - tester.getBottomLeft(appLegalese).dy;
965 expect(appLegaleseBottomPadding, 18.0);
966 });
967
968 testWidgets('LicensePage has no extra padding between app icon and app powered text', (WidgetTester tester) async {
969 // This is a regression test for https://github.com/flutter/flutter/issues/99559
970
971 const FlutterLogo logo = FlutterLogo();
972
973 await tester.pumpWidget(
974 const MaterialApp(
975 title: 'Pirate app',
976 home: Center(
977 child: LicensePage(
978 applicationIcon: logo,
979 ),
980 ),
981 ),
982 );
983
984 final Finder appName = find.text('LicensePage test app');
985 final Finder appIcon = find.byType(FlutterLogo);
986 final Finder appVersion = find.text('0.1.2');
987 final Finder appLegalese = find.text('I am the very model of a modern major general.');
988 final Finder appPowered = find.text('Powered by Flutter');
989
990 expect(appName, findsNothing);
991 expect(appIcon, findsOneWidget);
992 expect(appVersion, findsNothing);
993 expect(appLegalese, findsNothing);
994 expect(appPowered, findsOneWidget);
995
996 // Padding between app icon and app powered text.
997 final double appIconBottomPadding = tester.getTopLeft(appPowered).dy - tester.getBottomLeft(appIcon).dy;
998 expect(appIconBottomPadding, 18.0);
999 });
1000 }
1001
1002 class FakeLicenseEntry extends LicenseEntry {
1003 FakeLicenseEntry();
1004
1005 bool get packagesCalled => _packagesCalled;
1006 bool _packagesCalled = false;
1007
1008 @override
1009 Iterable<LicenseParagraph> paragraphs = <LicenseParagraph>[];
1010
1011 @override
1012 Iterable<String> get packages {
1013 _packagesCalled = true;
1014 return <String>[];
1015 }
1016 }
1017
1018 class LicensePageObserver extends NavigatorObserver {
1019 int licensePageCount = 0;
1020
1021 @override
1022 void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
1023 if (route is MaterialPageRoute<dynamic>) {
1024 licensePageCount++;
1025 }
1026 super.didPush(route, previousRoute);
1027 }
1028 }
1029
1030 class AboutDialogObserver extends NavigatorObserver {
1031 int dialogCount = 0;
1032
1033 @override
1034 void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
1035 if (route is DialogRoute) {
1036 dialogCount++;
1037 }
1038 super.didPush(route, previousRoute);
1039 }
1040 }