1968 lines
65 KiB
Dart
1968 lines
65 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:ui';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
void main() {
|
|
tearDown(() {
|
|
LicenseRegistry.reset();
|
|
});
|
|
|
|
testWidgets('Material3 has sentence case labels', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
builder: (BuildContext context, Widget? child) {
|
|
return MediaQuery(
|
|
// Display has a vertical hinge down the middle
|
|
data: const MediaQueryData(
|
|
size: Size(800, 600),
|
|
displayFeatures: <DisplayFeature>[
|
|
DisplayFeature(
|
|
bounds: Rect.fromLTRB(390, 0, 410, 600),
|
|
type: DisplayFeatureType.hinge,
|
|
state: DisplayFeatureState.unknown,
|
|
),
|
|
],
|
|
),
|
|
child: child!,
|
|
);
|
|
},
|
|
home: Builder(
|
|
builder: (BuildContext context) => ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(context: context, useRootNavigator: false, applicationName: 'A');
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Close'), findsOneWidget);
|
|
expect(find.text('View licenses'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Material2 - AboutListTile control test', (WidgetTester tester) async {
|
|
const logo = FlutterLogo();
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(useMaterial3: false),
|
|
title: 'Pirate app',
|
|
home: Scaffold(
|
|
appBar: AppBar(title: const Text('Home')),
|
|
drawer: Drawer(
|
|
child: ListView(
|
|
children: const <Widget>[
|
|
AboutListTile(
|
|
applicationVersion: '0.1.2',
|
|
applicationIcon: logo,
|
|
applicationLegalese: 'I am the very model of a modern major general.',
|
|
aboutBoxChildren: <Widget>[Text('About box')],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.text('About Pirate app'), findsNothing);
|
|
expect(find.text('0.1.2'), findsNothing);
|
|
expect(find.byWidget(logo), findsNothing);
|
|
expect(find.text('I am the very model of a modern major general.'), findsNothing);
|
|
expect(find.text('About box'), findsNothing);
|
|
|
|
await tester.tap(find.byType(IconButton));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('About Pirate app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsNothing);
|
|
expect(find.byWidget(logo), findsNothing);
|
|
expect(find.text('I am the very model of a modern major general.'), findsNothing);
|
|
expect(find.text('About box'), findsNothing);
|
|
|
|
await tester.tap(find.text('About Pirate app'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('About Pirate app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsOneWidget);
|
|
expect(find.byWidget(logo), findsOneWidget);
|
|
expect(find.text('I am the very model of a modern major general.'), findsOneWidget);
|
|
expect(find.text('About box'), findsOneWidget);
|
|
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['Pirate package '], 'Pirate license'),
|
|
]);
|
|
});
|
|
|
|
await tester.tap(find.text('VIEW LICENSES'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Pirate app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsOneWidget);
|
|
expect(find.byWidget(logo), findsOneWidget);
|
|
expect(find.text('I am the very model of a modern major general.'), findsOneWidget);
|
|
await tester.tap(find.text('Pirate package '));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Pirate license'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Material3 - AboutListTile control test', (WidgetTester tester) async {
|
|
const logo = FlutterLogo();
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
title: 'Pirate app',
|
|
home: Scaffold(
|
|
appBar: AppBar(title: const Text('Home')),
|
|
drawer: Drawer(
|
|
child: ListView(
|
|
children: const <Widget>[
|
|
AboutListTile(
|
|
applicationVersion: '0.1.2',
|
|
applicationIcon: logo,
|
|
applicationLegalese: 'I am the very model of a modern major general.',
|
|
aboutBoxChildren: <Widget>[Text('About box')],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.text('About Pirate app'), findsNothing);
|
|
expect(find.text('0.1.2'), findsNothing);
|
|
expect(find.byWidget(logo), findsNothing);
|
|
expect(find.text('I am the very model of a modern major general.'), findsNothing);
|
|
expect(find.text('About box'), findsNothing);
|
|
|
|
await tester.tap(find.byType(IconButton));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('About Pirate app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsNothing);
|
|
expect(find.byWidget(logo), findsNothing);
|
|
expect(find.text('I am the very model of a modern major general.'), findsNothing);
|
|
expect(find.text('About box'), findsNothing);
|
|
|
|
await tester.tap(find.text('About Pirate app'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('About Pirate app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsOneWidget);
|
|
expect(find.byWidget(logo), findsOneWidget);
|
|
expect(find.text('I am the very model of a modern major general.'), findsOneWidget);
|
|
expect(find.text('About box'), findsOneWidget);
|
|
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['Pirate package '], 'Pirate license'),
|
|
]);
|
|
});
|
|
|
|
await tester.tap(find.text('View licenses'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Pirate app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsOneWidget);
|
|
expect(find.byWidget(logo), findsOneWidget);
|
|
expect(find.text('I am the very model of a modern major general.'), findsOneWidget);
|
|
await tester.tap(find.text('Pirate package '));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Pirate license'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('About box logic defaults to executable name for app name', (
|
|
WidgetTester tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: 'flutter_tester',
|
|
home: Material(child: AboutListTile()),
|
|
),
|
|
);
|
|
expect(find.text('About flutter_tester'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('LicensePage control test', (WidgetTester tester) async {
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
|
|
]);
|
|
});
|
|
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['Another package'], 'Another license'),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: Center(child: LicensePage())));
|
|
|
|
expect(find.text('AAA'), findsNothing);
|
|
expect(find.text('BBB'), findsNothing);
|
|
expect(find.text('Another package'), findsNothing);
|
|
expect(find.text('Another license'), findsNothing);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for packages.
|
|
expect(find.text('AAA'), findsOneWidget);
|
|
expect(find.text('Another package'), findsOneWidget);
|
|
|
|
// Check license is displayed after entering into license page for 'AAA'.
|
|
await tester.tap(find.text('AAA'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('BBB'), findsOneWidget);
|
|
|
|
/// Go back to list of packages.
|
|
await tester.pageBack();
|
|
await tester.pumpAndSettle();
|
|
|
|
/// Check license is displayed after entering into license page for
|
|
/// 'Another package'.
|
|
await tester.tap(find.text('Another package'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Another license'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('LicensePage control test with all properties', (WidgetTester tester) async {
|
|
const logo = FlutterLogo();
|
|
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
|
|
]);
|
|
});
|
|
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['Another package'], 'Another license'),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: 'Pirate app',
|
|
home: Center(
|
|
child: LicensePage(
|
|
applicationName: 'LicensePage test app',
|
|
applicationVersion: '0.1.2',
|
|
applicationIcon: logo,
|
|
applicationLegalese: 'I am the very model of a modern major general.',
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.text('Pirate app'), findsNothing);
|
|
expect(find.text('LicensePage test app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsOneWidget);
|
|
expect(find.byWidget(logo), findsOneWidget);
|
|
expect(find.text('I am the very model of a modern major general.'), findsOneWidget);
|
|
expect(find.text('AAA'), findsNothing);
|
|
expect(find.text('BBB'), findsNothing);
|
|
expect(find.text('Another package'), findsNothing);
|
|
expect(find.text('Another license'), findsNothing);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Pirate app'), findsNothing);
|
|
expect(find.text('LicensePage test app'), findsOneWidget);
|
|
expect(find.text('0.1.2'), findsOneWidget);
|
|
expect(find.byWidget(logo), findsOneWidget);
|
|
expect(find.text('I am the very model of a modern major general.'), findsOneWidget);
|
|
|
|
// Check for packages.
|
|
expect(find.text('AAA'), findsOneWidget);
|
|
expect(find.text('Another package'), findsOneWidget);
|
|
|
|
// Check license is displayed after entering into license page for 'AAA'.
|
|
await tester.tap(find.text('AAA'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('BBB'), findsOneWidget);
|
|
|
|
/// Go back to list of packages.
|
|
await tester.pageBack();
|
|
await tester.pumpAndSettle();
|
|
|
|
/// Check license is displayed after entering into license page for
|
|
/// 'Another package'.
|
|
await tester.tap(find.text('Another package'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('Another license'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Material2 - _PackageLicensePage title style without AppBarTheme', (
|
|
WidgetTester tester,
|
|
) async {
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
|
|
]);
|
|
});
|
|
|
|
const titleTextStyle = TextStyle(fontSize: 20, color: Colors.black, inherit: false);
|
|
const subtitleTextStyle = TextStyle(fontSize: 15, color: Colors.red, inherit: false);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(
|
|
useMaterial3: false,
|
|
primaryTextTheme: const TextTheme(
|
|
titleLarge: titleTextStyle,
|
|
titleSmall: subtitleTextStyle,
|
|
),
|
|
),
|
|
home: const Center(child: LicensePage()),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for packages.
|
|
expect(find.text('AAA'), findsOneWidget);
|
|
|
|
// Check license is displayed after entering into license page for 'AAA'.
|
|
await tester.tap(find.text('AAA'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for titles style.
|
|
final Text title = tester.widget(find.text('AAA'));
|
|
expect(title.style, titleTextStyle);
|
|
final Text subtitle = tester.widget(find.text('1 license.'));
|
|
expect(subtitle.style, subtitleTextStyle);
|
|
});
|
|
|
|
testWidgets('Material3 - _PackageLicensePage title style without AppBarTheme', (
|
|
WidgetTester tester,
|
|
) async {
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
|
|
]);
|
|
});
|
|
|
|
const titleTextStyle = TextStyle(fontSize: 20, color: Colors.black, inherit: false);
|
|
const subtitleTextStyle = TextStyle(fontSize: 15, color: Colors.red, inherit: false);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(
|
|
textTheme: const TextTheme(titleLarge: titleTextStyle, titleSmall: subtitleTextStyle),
|
|
),
|
|
home: const Center(child: LicensePage()),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for packages.
|
|
expect(find.text('AAA'), findsOneWidget);
|
|
|
|
// Check license is displayed after entering into license page for 'AAA'.
|
|
await tester.tap(find.text('AAA'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for titles style.
|
|
final Text title = tester.widget(find.text('AAA'));
|
|
expect(title.style, titleTextStyle);
|
|
final Text subtitle = tester.widget(find.text('1 license.'));
|
|
expect(subtitle.style, subtitleTextStyle);
|
|
});
|
|
|
|
testWidgets('_PackageLicensePage title style with AppBarTheme', (WidgetTester tester) async {
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
|
|
]);
|
|
});
|
|
|
|
const titleTextStyle = TextStyle(fontSize: 20, color: Colors.indigo);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(
|
|
// Not used because appBarTheme is prioritized.
|
|
primaryTextTheme: const TextTheme(
|
|
titleLarge: TextStyle(fontSize: 12, color: Colors.grey),
|
|
titleSmall: TextStyle(fontSize: 10, color: Colors.grey),
|
|
),
|
|
appBarTheme: const AppBarTheme(
|
|
titleTextStyle: titleTextStyle,
|
|
foregroundColor: Colors.indigo,
|
|
),
|
|
),
|
|
home: const Center(child: LicensePage()),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for packages.
|
|
expect(find.text('AAA'), findsOneWidget);
|
|
|
|
// Check license is displayed after entering into license page for 'AAA'.
|
|
await tester.tap(find.text('AAA'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for titles style.
|
|
final Text title = tester.widget(find.text('AAA'));
|
|
expect(title.style, titleTextStyle);
|
|
});
|
|
|
|
testWidgets('Material2 - LicensePage respects the notch', (WidgetTester tester) async {
|
|
const safeareaPadding = 27.0;
|
|
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(useMaterial3: false),
|
|
home: const MediaQuery(
|
|
data: MediaQueryData(padding: EdgeInsets.all(safeareaPadding)),
|
|
child: LicensePage(),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
// The position of the top left of app bar title should indicate whether
|
|
// the safe area is sufficiently respected.
|
|
expect(
|
|
tester.getTopLeft(find.text('Licenses')),
|
|
const Offset(16.0 + safeareaPadding, 18.0 + safeareaPadding),
|
|
);
|
|
});
|
|
|
|
testWidgets('Material3 - LicensePage respects the notch', (WidgetTester tester) async {
|
|
const safeareaPadding = 27.0;
|
|
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: MediaQuery(
|
|
data: MediaQueryData(padding: EdgeInsets.all(safeareaPadding)),
|
|
child: LicensePage(),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
// The position of the top left of app bar title should indicate whether
|
|
// the safe area is sufficiently respected.
|
|
expect(
|
|
tester.getTopLeft(find.text('Licenses')),
|
|
const Offset(16.0 + safeareaPadding, 14.0 + safeareaPadding),
|
|
);
|
|
});
|
|
|
|
testWidgets('LicensePage returns early if unmounted', (WidgetTester tester) async {
|
|
final licenseCompleter = Completer<LicenseEntry>();
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromFuture(licenseCompleter.future);
|
|
});
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: LicensePage()));
|
|
await tester.pump();
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: Placeholder()));
|
|
|
|
await tester.pumpAndSettle();
|
|
final licenseEntry = FakeLicenseEntry();
|
|
licenseCompleter.complete(licenseEntry);
|
|
expect(licenseEntry.packagesCalled, false);
|
|
});
|
|
|
|
testWidgets('LicensePage returns late if unmounted', (WidgetTester tester) async {
|
|
final licenseCompleter = Completer<LicenseEntry>();
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromFuture(licenseCompleter.future);
|
|
});
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: LicensePage()));
|
|
await tester.pump();
|
|
final licenseEntry = FakeLicenseEntry();
|
|
licenseCompleter.complete(licenseEntry);
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: Placeholder()));
|
|
|
|
await tester.pumpAndSettle();
|
|
expect(licenseEntry.packagesCalled, true);
|
|
});
|
|
|
|
testWidgets('LicensePage logic defaults to executable name for app name', (
|
|
WidgetTester tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: 'flutter_tester',
|
|
home: Material(child: LicensePage()),
|
|
),
|
|
);
|
|
expect(find.text('flutter_tester'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('AboutListTile dense property is applied', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: Material(child: Center(child: AboutListTile())),
|
|
),
|
|
);
|
|
Rect tileRect = tester.getRect(find.byType(AboutListTile));
|
|
expect(tileRect.height, 56.0);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: Material(child: Center(child: AboutListTile(dense: false))),
|
|
),
|
|
);
|
|
tileRect = tester.getRect(find.byType(AboutListTile));
|
|
expect(tileRect.height, 56.0);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: Material(child: Center(child: AboutListTile(dense: true))),
|
|
),
|
|
);
|
|
tileRect = tester.getRect(find.byType(AboutListTile));
|
|
expect(tileRect.height, 48.0);
|
|
});
|
|
|
|
testWidgets('showLicensePage uses nested navigator by default', (WidgetTester tester) async {
|
|
final rootObserver = LicensePageObserver();
|
|
final nestedObserver = LicensePageObserver();
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorObservers: <NavigatorObserver>[rootObserver],
|
|
initialRoute: '/',
|
|
onGenerateRoute: (_) {
|
|
return PageRouteBuilder<dynamic>(
|
|
pageBuilder: (_, _, _) => Navigator(
|
|
observers: <NavigatorObserver>[nestedObserver],
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return PageRouteBuilder<dynamic>(
|
|
pageBuilder: (BuildContext context, _, _) {
|
|
return ElevatedButton(
|
|
onPressed: () {
|
|
showLicensePage(context: context, applicationName: 'A');
|
|
},
|
|
child: const Text('Show License Page'),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
|
|
expect(rootObserver.licensePageCount, 0);
|
|
expect(nestedObserver.licensePageCount, 1);
|
|
});
|
|
|
|
testWidgets('showLicensePage uses root navigator if useRootNavigator is true', (
|
|
WidgetTester tester,
|
|
) async {
|
|
final rootObserver = LicensePageObserver();
|
|
final nestedObserver = LicensePageObserver();
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorObservers: <NavigatorObserver>[rootObserver],
|
|
initialRoute: '/',
|
|
onGenerateRoute: (_) {
|
|
return PageRouteBuilder<dynamic>(
|
|
pageBuilder: (_, _, _) => Navigator(
|
|
observers: <NavigatorObserver>[nestedObserver],
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return PageRouteBuilder<dynamic>(
|
|
pageBuilder: (BuildContext context, _, _) {
|
|
return ElevatedButton(
|
|
onPressed: () {
|
|
showLicensePage(
|
|
context: context,
|
|
useRootNavigator: true,
|
|
applicationName: 'A',
|
|
);
|
|
},
|
|
child: const Text('Show License Page'),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
|
|
expect(rootObserver.licensePageCount, 1);
|
|
expect(nestedObserver.licensePageCount, 0);
|
|
});
|
|
|
|
group('Barrier dismissible', () {
|
|
late AboutDialogObserver rootObserver;
|
|
|
|
setUp(() {
|
|
rootObserver = AboutDialogObserver();
|
|
});
|
|
|
|
testWidgets('Barrier is dismissible with default parameter', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorObservers: <NavigatorObserver>[rootObserver],
|
|
home: Material(
|
|
child: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
child: const Text('X'),
|
|
onPressed: () => showAboutDialog(context: context),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
expect(rootObserver.dialogCount, 1);
|
|
|
|
// Tap on the barrier.
|
|
await tester.tapAt(const Offset(10.0, 10.0));
|
|
await tester.pumpAndSettle();
|
|
expect(rootObserver.dialogCount, 0);
|
|
});
|
|
|
|
testWidgets('Barrier is not dismissible with barrierDismissible is false', (
|
|
WidgetTester tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorObservers: <NavigatorObserver>[rootObserver],
|
|
home: Material(
|
|
child: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
child: const Text('X'),
|
|
onPressed: () => showAboutDialog(context: context, barrierDismissible: false),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
expect(rootObserver.dialogCount, 1);
|
|
|
|
// Tap on the barrier, which shouldn't do anything this time.
|
|
await tester.tapAt(const Offset(10.0, 10.0));
|
|
await tester.pumpAndSettle();
|
|
expect(rootObserver.dialogCount, 1);
|
|
});
|
|
});
|
|
|
|
testWidgets('Barrier color', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Material(
|
|
child: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
child: const Text('X'),
|
|
onPressed: () => showAboutDialog(context: context),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
expect(tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color, Colors.black54);
|
|
|
|
// Dismiss the dialog.
|
|
await tester.tapAt(const Offset(10.0, 10.0));
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Material(
|
|
child: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
child: const Text('X'),
|
|
onPressed: () => showAboutDialog(context: context, barrierColor: Colors.pink),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
expect(tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color, Colors.pink);
|
|
});
|
|
|
|
testWidgets('Barrier Label', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Material(
|
|
child: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
child: const Text('X'),
|
|
onPressed: () => showAboutDialog(context: context, barrierLabel: 'Custom Label'),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
expect(
|
|
tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).semanticsLabel,
|
|
'Custom Label',
|
|
);
|
|
});
|
|
|
|
testWidgets('showAboutDialog uses root navigator by default', (WidgetTester tester) async {
|
|
final rootObserver = AboutDialogObserver();
|
|
final nestedObserver = AboutDialogObserver();
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorObservers: <NavigatorObserver>[rootObserver],
|
|
home: Navigator(
|
|
observers: <NavigatorObserver>[nestedObserver],
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return MaterialPageRoute<dynamic>(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(context: context, applicationName: 'A');
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
|
|
expect(rootObserver.dialogCount, 1);
|
|
expect(nestedObserver.dialogCount, 0);
|
|
});
|
|
|
|
testWidgets('showAboutDialog uses nested navigator if useRootNavigator is false', (
|
|
WidgetTester tester,
|
|
) async {
|
|
final rootObserver = AboutDialogObserver();
|
|
final nestedObserver = AboutDialogObserver();
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorObservers: <NavigatorObserver>[rootObserver],
|
|
home: Navigator(
|
|
observers: <NavigatorObserver>[nestedObserver],
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return MaterialPageRoute<dynamic>(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(
|
|
context: context,
|
|
useRootNavigator: false,
|
|
applicationName: 'A',
|
|
);
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
|
|
expect(rootObserver.dialogCount, 0);
|
|
expect(nestedObserver.dialogCount, 1);
|
|
});
|
|
|
|
group('showAboutDialog avoids overlapping display features', () {
|
|
testWidgets('default positioning', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
builder: (BuildContext context, Widget? child) {
|
|
return MediaQuery(
|
|
// Display has a vertical hinge down the middle
|
|
data: const MediaQueryData(
|
|
size: Size(800, 600),
|
|
displayFeatures: <DisplayFeature>[
|
|
DisplayFeature(
|
|
bounds: Rect.fromLTRB(390, 0, 410, 600),
|
|
type: DisplayFeatureType.hinge,
|
|
state: DisplayFeatureState.unknown,
|
|
),
|
|
],
|
|
),
|
|
child: child!,
|
|
);
|
|
},
|
|
home: Builder(
|
|
builder: (BuildContext context) => ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(context: context, useRootNavigator: false, applicationName: 'A');
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
|
|
// By default it should place the dialog on the left screen
|
|
expect(tester.getTopLeft(find.byType(AboutDialog)), Offset.zero);
|
|
expect(tester.getBottomRight(find.byType(AboutDialog)), const Offset(390.0, 600.0));
|
|
});
|
|
|
|
testWidgets('positioning using anchorPoint', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
builder: (BuildContext context, Widget? child) {
|
|
return MediaQuery(
|
|
// Display has a vertical hinge down the middle
|
|
data: const MediaQueryData(
|
|
size: Size(800, 600),
|
|
displayFeatures: <DisplayFeature>[
|
|
DisplayFeature(
|
|
bounds: Rect.fromLTRB(390, 0, 410, 600),
|
|
type: DisplayFeatureType.hinge,
|
|
state: DisplayFeatureState.unknown,
|
|
),
|
|
],
|
|
),
|
|
child: child!,
|
|
);
|
|
},
|
|
home: Builder(
|
|
builder: (BuildContext context) => ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(
|
|
context: context,
|
|
useRootNavigator: false,
|
|
applicationName: 'A',
|
|
anchorPoint: const Offset(1000, 0),
|
|
);
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
|
|
// The anchorPoint hits the right side of the display
|
|
expect(tester.getTopLeft(find.byType(AboutDialog)), const Offset(410.0, 0.0));
|
|
expect(tester.getBottomRight(find.byType(AboutDialog)), const Offset(800.0, 600.0));
|
|
});
|
|
|
|
testWidgets('positioning using Directionality', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
builder: (BuildContext context, Widget? child) {
|
|
return MediaQuery(
|
|
// Display has a vertical hinge down the middle
|
|
data: const MediaQueryData(
|
|
size: Size(800, 600),
|
|
displayFeatures: <DisplayFeature>[
|
|
DisplayFeature(
|
|
bounds: Rect.fromLTRB(390, 0, 410, 600),
|
|
type: DisplayFeatureType.hinge,
|
|
state: DisplayFeatureState.unknown,
|
|
),
|
|
],
|
|
),
|
|
child: Directionality(textDirection: TextDirection.rtl, child: child!),
|
|
);
|
|
},
|
|
home: Builder(
|
|
builder: (BuildContext context) => ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(context: context, useRootNavigator: false, applicationName: 'A');
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Since this is rtl, the first screen is the on the right
|
|
expect(tester.getTopLeft(find.byType(AboutDialog)), const Offset(410.0, 0.0));
|
|
expect(tester.getBottomRight(find.byType(AboutDialog)), const Offset(800.0, 600.0));
|
|
});
|
|
});
|
|
|
|
testWidgets("AboutListTile's child should not be offset when the icon is not specified.", (
|
|
WidgetTester tester,
|
|
) async {
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: Scaffold(body: AboutListTile(child: Text('About'))),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
find.descendant(of: find.byType(AboutListTile), matching: find.byType(Icon)),
|
|
findsNothing,
|
|
);
|
|
});
|
|
|
|
testWidgets("AboutDialog's contents are scrollable", (WidgetTester tester) async {
|
|
final Key contentKey = UniqueKey();
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Navigator(
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return MaterialPageRoute<dynamic>(
|
|
builder: (BuildContext context) {
|
|
return ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(
|
|
context: context,
|
|
useRootNavigator: false,
|
|
applicationName: 'A',
|
|
children: <Widget>[
|
|
Container(key: contentKey, color: Colors.orange, height: 500),
|
|
],
|
|
);
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('Show About Dialog'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Try dragging by the [AboutDialog]'s title.
|
|
RenderBox box = tester.renderObject(find.text('A'));
|
|
Offset originalOffset = box.localToGlobal(Offset.zero);
|
|
await tester.drag(find.byKey(contentKey), const Offset(0.0, -20.0));
|
|
|
|
expect(box.localToGlobal(Offset.zero), equals(originalOffset.translate(0.0, -20.0)));
|
|
|
|
// Try dragging by the additional children in contents.
|
|
box = tester.renderObject(find.byKey(contentKey));
|
|
originalOffset = box.localToGlobal(Offset.zero);
|
|
await tester.drag(find.byKey(contentKey), const Offset(0.0, -20.0));
|
|
|
|
expect(box.localToGlobal(Offset.zero), equals(originalOffset.translate(0.0, -20.0)));
|
|
});
|
|
|
|
testWidgets("Material2 - LicensePage's color must be same whether loading or done", (
|
|
WidgetTester tester,
|
|
) async {
|
|
const scaffoldColor = Color(0xFF123456);
|
|
const cardColor = Color(0xFF654321);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData.light(
|
|
useMaterial3: false,
|
|
).copyWith(scaffoldBackgroundColor: scaffoldColor, cardColor: cardColor),
|
|
home: Scaffold(
|
|
body: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) => GestureDetector(
|
|
child: const Text('Show licenses'),
|
|
onTap: () {
|
|
showLicensePage(
|
|
context: context,
|
|
applicationName: 'MyApp',
|
|
applicationVersion: '1.0.0',
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('Show licenses'));
|
|
await tester.pump();
|
|
await tester.pump();
|
|
|
|
// Check color when loading.
|
|
final List<Material> materialLoadings = tester
|
|
.widgetList<Material>(find.byType(Material))
|
|
.toList();
|
|
expect(materialLoadings.length, equals(4));
|
|
expect(materialLoadings[1].color, scaffoldColor);
|
|
expect(materialLoadings[2].color, cardColor);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check color when done.
|
|
expect(find.byKey(const ValueKey<ConnectionState>(ConnectionState.done)), findsOneWidget);
|
|
final List<Material> materialDones = tester
|
|
.widgetList<Material>(find.byType(Material))
|
|
.toList();
|
|
expect(materialDones.length, equals(3));
|
|
expect(materialDones[0].color, scaffoldColor);
|
|
expect(materialDones[1].color, cardColor);
|
|
});
|
|
|
|
testWidgets("Material3 - LicensePage's color must be same whether loading or done", (
|
|
WidgetTester tester,
|
|
) async {
|
|
const scaffoldColor = Color(0xFF123456);
|
|
const cardColor = Color(0xFF654321);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(scaffoldBackgroundColor: scaffoldColor, cardColor: cardColor),
|
|
home: Scaffold(
|
|
body: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) => GestureDetector(
|
|
child: const Text('Show licenses'),
|
|
onTap: () {
|
|
showLicensePage(
|
|
context: context,
|
|
applicationName: 'MyApp',
|
|
applicationVersion: '1.0.0',
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.tap(find.text('Show licenses'));
|
|
await tester.pump();
|
|
await tester.pump();
|
|
|
|
// Check color when loading.
|
|
final List<Material> materialLoadings = tester
|
|
.widgetList<Material>(find.byType(Material))
|
|
.toList();
|
|
expect(materialLoadings.length, equals(5));
|
|
expect(materialLoadings[1].color, scaffoldColor);
|
|
expect(materialLoadings[2].color, cardColor);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check color when done.
|
|
expect(find.byKey(const ValueKey<ConnectionState>(ConnectionState.done)), findsOneWidget);
|
|
final List<Material> materialDones = tester
|
|
.widgetList<Material>(find.byType(Material))
|
|
.toList();
|
|
expect(materialDones.length, equals(4));
|
|
expect(materialDones[0].color, scaffoldColor);
|
|
expect(materialDones[1].color, cardColor);
|
|
});
|
|
|
|
testWidgets(
|
|
'Conflicting scrollbars are not applied by ScrollBehavior to _PackageLicensePage',
|
|
(WidgetTester tester) async {
|
|
// Regression test for https://github.com/flutter/flutter/issues/83819
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['AAA'], 'BBB'),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: Center(child: LicensePage())));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for packages.
|
|
expect(find.text('AAA'), findsOneWidget);
|
|
// Check license is displayed after entering into license page for 'AAA'.
|
|
await tester.tap(find.text('AAA'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// The inherited ScrollBehavior should not apply Scrollbars since they are
|
|
// already built in to the widget.
|
|
switch (debugDefaultTargetPlatformOverride) {
|
|
case TargetPlatform.android:
|
|
case TargetPlatform.fuchsia:
|
|
case TargetPlatform.linux:
|
|
case TargetPlatform.macOS:
|
|
case TargetPlatform.windows:
|
|
expect(find.byType(CupertinoScrollbar), findsNothing);
|
|
case TargetPlatform.iOS:
|
|
expect(find.byType(CupertinoScrollbar), findsOneWidget);
|
|
case null:
|
|
break;
|
|
}
|
|
expect(find.byType(Scrollbar), findsOneWidget);
|
|
expect(find.byType(RawScrollbar), findsNothing);
|
|
},
|
|
variant: TargetPlatformVariant.all(),
|
|
);
|
|
|
|
testWidgets('ListView of license entries is primary', (WidgetTester tester) async {
|
|
// Regression test for https://github.com/flutter/flutter/issues/120710
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
LicenseEntryWithLineBreaks(
|
|
<String>['AAA'],
|
|
// Add enough content to scroll
|
|
List<String>.generate(500, (int index) => 'BBBB').join('\n'),
|
|
),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
title: 'Flutter Code Sample',
|
|
home: Scaffold(
|
|
body: Builder(
|
|
builder: (BuildContext context) => TextButton(
|
|
child: const Text('Show License Page'),
|
|
onPressed: () {
|
|
showLicensePage(context: context);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Show License Page'), findsOneWidget);
|
|
await tester.tap(find.text('Show License Page'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Check for packages.
|
|
expect(find.text('AAA'), findsOneWidget);
|
|
// Check license is displayed after entering into license page for 'AAA'.
|
|
await tester.tap(find.text('AAA'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// The inherited ScrollBehavior should not apply Scrollbars since they are
|
|
// already built in to the widget.
|
|
switch (debugDefaultTargetPlatformOverride) {
|
|
case TargetPlatform.android:
|
|
case TargetPlatform.fuchsia:
|
|
case TargetPlatform.linux:
|
|
case TargetPlatform.macOS:
|
|
case TargetPlatform.windows:
|
|
expect(find.byType(CupertinoScrollbar), findsNothing);
|
|
case TargetPlatform.iOS:
|
|
expect(find.byType(CupertinoScrollbar), findsOneWidget);
|
|
case null:
|
|
break;
|
|
}
|
|
expect(find.byType(Scrollbar), findsOneWidget);
|
|
expect(find.byType(RawScrollbar), findsNothing);
|
|
await tester.drag(find.byType(ListView), const Offset(0.0, 20.0));
|
|
await tester.pumpAndSettle(); // No exception triggered.
|
|
}, variant: TargetPlatformVariant.all());
|
|
|
|
testWidgets('LicensePage padding', (WidgetTester tester) async {
|
|
const logo = FlutterLogo();
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: 'Pirate app',
|
|
home: Center(
|
|
child: LicensePage(
|
|
applicationName: 'LicensePage test app',
|
|
applicationIcon: logo,
|
|
applicationVersion: '0.1.2',
|
|
applicationLegalese: 'I am the very model of a modern major general.',
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
final Finder appName = find.text('LicensePage test app');
|
|
final Finder appIcon = find.byType(FlutterLogo);
|
|
final Finder appVersion = find.text('0.1.2');
|
|
final Finder appLegalese = find.text('I am the very model of a modern major general.');
|
|
final Finder appPowered = find.text('Powered by Flutter');
|
|
|
|
expect(appName, findsOneWidget);
|
|
expect(appIcon, findsOneWidget);
|
|
expect(appVersion, findsOneWidget);
|
|
expect(appLegalese, findsOneWidget);
|
|
expect(appPowered, findsOneWidget);
|
|
|
|
// Bottom padding is applied to the app version and app legalese text.
|
|
final double appNameBottomPadding =
|
|
tester.getTopLeft(appIcon).dy - tester.getBottomLeft(appName).dy;
|
|
expect(appNameBottomPadding, 0.0);
|
|
|
|
final double appIconBottomPadding =
|
|
tester.getTopLeft(appVersion).dy - tester.getBottomLeft(appIcon).dy;
|
|
expect(appIconBottomPadding, 0.0);
|
|
|
|
final double appVersionBottomPadding =
|
|
tester.getTopLeft(appLegalese).dy - tester.getBottomLeft(appVersion).dy;
|
|
expect(appVersionBottomPadding, 18.0);
|
|
|
|
final double appLegaleseBottomPadding =
|
|
tester.getTopLeft(appPowered).dy - tester.getBottomLeft(appLegalese).dy;
|
|
expect(appLegaleseBottomPadding, 18.0);
|
|
});
|
|
|
|
testWidgets('LicensePage has no extra padding between app icon and app powered text', (
|
|
WidgetTester tester,
|
|
) async {
|
|
// This is a regression test for https://github.com/flutter/flutter/issues/99559
|
|
|
|
const logo = FlutterLogo();
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: 'Pirate app',
|
|
home: Center(child: LicensePage(applicationIcon: logo)),
|
|
),
|
|
);
|
|
|
|
final Finder appName = find.text('LicensePage test app');
|
|
final Finder appIcon = find.byType(FlutterLogo);
|
|
final Finder appVersion = find.text('0.1.2');
|
|
final Finder appLegalese = find.text('I am the very model of a modern major general.');
|
|
final Finder appPowered = find.text('Powered by Flutter');
|
|
|
|
expect(appName, findsNothing);
|
|
expect(appIcon, findsOneWidget);
|
|
expect(appVersion, findsNothing);
|
|
expect(appLegalese, findsNothing);
|
|
expect(appPowered, findsOneWidget);
|
|
|
|
// Padding between app icon and app powered text.
|
|
final double appIconBottomPadding =
|
|
tester.getTopLeft(appPowered).dy - tester.getBottomLeft(appIcon).dy;
|
|
expect(appIconBottomPadding, 18.0);
|
|
});
|
|
|
|
testWidgets('Material2 - Error handling test', (WidgetTester tester) async {
|
|
LicenseRegistry.addLicense(() => Stream<LicenseEntry>.error(Exception('Injected failure')));
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(useMaterial3: false),
|
|
home: const Material(child: AboutListTile()),
|
|
),
|
|
);
|
|
await tester.tap(find.byType(ListTile));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.tap(find.text('VIEW LICENSES'));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(seconds: 2));
|
|
final Finder finder = find.byWidgetPredicate(
|
|
(Widget widget) => widget.runtimeType.toString() == '_PackagesView',
|
|
);
|
|
// force the stream to complete (has to be done in a runAsync block since it's areal async process)
|
|
await tester.runAsync(() => (tester.firstState(finder) as dynamic).licenses as Future<dynamic>);
|
|
expect(tester.takeException().toString(), 'Exception: Injected failure');
|
|
await tester.pumpAndSettle();
|
|
expect(tester.takeException().toString(), 'Exception: Injected failure');
|
|
expect(find.text('Exception: Injected failure'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Material3 - Error handling test', (WidgetTester tester) async {
|
|
LicenseRegistry.addLicense(() => Stream<LicenseEntry>.error(Exception('Injected failure')));
|
|
await tester.pumpWidget(const MaterialApp(home: Material(child: AboutListTile())));
|
|
await tester.tap(find.byType(ListTile));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(seconds: 2));
|
|
await tester.tap(find.text('View licenses'));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(seconds: 2));
|
|
final Finder finder = find.byWidgetPredicate(
|
|
(Widget widget) => widget.runtimeType.toString() == '_PackagesView',
|
|
);
|
|
// force the stream to complete (has to be done in a runAsync block since it's areal async process)
|
|
await tester.runAsync(() => (tester.firstState(finder) as dynamic).licenses as Future<dynamic>);
|
|
expect(tester.takeException().toString(), 'Exception: Injected failure');
|
|
await tester.pumpAndSettle();
|
|
expect(tester.takeException().toString(), 'Exception: Injected failure');
|
|
expect(find.text('Exception: Injected failure'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Material2 - LicensePage master view layout position - ltr', (
|
|
WidgetTester tester,
|
|
) async {
|
|
const TextDirection textDirection = TextDirection.ltr;
|
|
const defaultSize = Size(800.0, 600.0);
|
|
const wideSize = Size(1200.0, 600.0);
|
|
const title = 'License ABC';
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
addTearDown(() async {
|
|
await tester.binding.setSurfaceSize(null);
|
|
});
|
|
|
|
// Configure to show the default layout.
|
|
await tester.binding.setSurfaceSize(defaultSize);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(useMaterial3: false),
|
|
title: title,
|
|
home: const Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is less than 840.0 pixels, nested layout is
|
|
// used which positions license page title at the top center.
|
|
Offset titleOffset = tester.getCenter(find.text(title));
|
|
expect(titleOffset, Offset(defaultSize.width / 2, 92.0));
|
|
expect(tester.getCenter(find.byType(ListView)), Offset(defaultSize.width / 2, 328.0));
|
|
|
|
// Configure a wide window to show the lateral UI.
|
|
await tester.binding.setSurfaceSize(wideSize);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: title,
|
|
home: Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is greater than 840.0 pixels, lateral UI layout
|
|
// is used which positions license page title and packageList
|
|
// at the top left.
|
|
titleOffset = tester.getTopRight(find.text(title));
|
|
expect(titleOffset, const Offset(292.0, 136.0));
|
|
expect(titleOffset.dx, lessThan(wideSize.width - 320)); // Default master view width is 320.0.
|
|
expect(tester.getCenter(find.byType(ListView)), const Offset(160, 356));
|
|
});
|
|
|
|
testWidgets('Material3 - LicensePage master view layout position - ltr', (
|
|
WidgetTester tester,
|
|
) async {
|
|
const TextDirection textDirection = TextDirection.ltr;
|
|
const defaultSize = Size(800.0, 600.0);
|
|
const wideSize = Size(1200.0, 600.0);
|
|
const title = 'License ABC';
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
addTearDown(() async {
|
|
await tester.binding.setSurfaceSize(null);
|
|
});
|
|
|
|
// Configure to show the default layout.
|
|
await tester.binding.setSurfaceSize(defaultSize);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: title,
|
|
home: Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is less than 840.0 pixels, nested layout is
|
|
// used which positions license page title at the top center.
|
|
Offset titleOffset = tester.getCenter(find.text(title));
|
|
expect(titleOffset, Offset(defaultSize.width / 2, 96.0));
|
|
expect(tester.getCenter(find.byType(ListView)), Offset(defaultSize.width / 2, 328.0));
|
|
|
|
// Configure a wide window to show the lateral UI.
|
|
await tester.binding.setSurfaceSize(wideSize);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: title,
|
|
home: Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is greater than 840.0 pixels, lateral UI layout
|
|
// is used which positions license page title and packageList
|
|
// at the top left.
|
|
titleOffset = tester.getTopRight(find.text(title));
|
|
expect(titleOffset, const Offset(292.0, 136.0));
|
|
expect(titleOffset.dx, lessThan(wideSize.width - 320)); // Default master view width is 320.0.
|
|
expect(tester.getCenter(find.byType(ListView)), const Offset(160, 356));
|
|
});
|
|
|
|
testWidgets('Material2 - LicensePage master view layout position - rtl', (
|
|
WidgetTester tester,
|
|
) async {
|
|
const TextDirection textDirection = TextDirection.rtl;
|
|
const defaultSize = Size(800.0, 600.0);
|
|
const wideSize = Size(1200.0, 600.0);
|
|
const title = 'License ABC';
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
addTearDown(() async {
|
|
await tester.binding.setSurfaceSize(null);
|
|
});
|
|
|
|
// Configure to show the default layout.
|
|
await tester.binding.setSurfaceSize(defaultSize);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(useMaterial3: false),
|
|
title: title,
|
|
home: const Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is less than 840.0 pixels, nested layout is
|
|
// used which positions license page title at the top center.
|
|
Offset titleOffset = tester.getCenter(find.text(title));
|
|
expect(titleOffset, Offset(defaultSize.width / 2, 92.0));
|
|
expect(tester.getCenter(find.byType(ListView)), Offset(defaultSize.width / 2, 328.0));
|
|
|
|
// Configure a wide window to show the lateral UI.
|
|
await tester.binding.setSurfaceSize(wideSize);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: title,
|
|
home: Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is greater than 840.0 pixels, lateral UI layout
|
|
// is used which positions license page title and packageList
|
|
// at the top right.
|
|
titleOffset = tester.getTopLeft(find.text(title));
|
|
expect(titleOffset, const Offset(908.0, 136.0));
|
|
expect(
|
|
titleOffset.dx,
|
|
greaterThan(wideSize.width - 320),
|
|
); // Default master view width is 320.0.
|
|
expect(tester.getCenter(find.byType(ListView)), const Offset(1040.0, 356.0));
|
|
});
|
|
|
|
testWidgets('Material3 - LicensePage master view layout position - rtl', (
|
|
WidgetTester tester,
|
|
) async {
|
|
const TextDirection textDirection = TextDirection.rtl;
|
|
const defaultSize = Size(800.0, 600.0);
|
|
const wideSize = Size(1200.0, 600.0);
|
|
const title = 'License ABC';
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
addTearDown(() async {
|
|
await tester.binding.setSurfaceSize(null);
|
|
});
|
|
|
|
// Configure to show the default layout.
|
|
await tester.binding.setSurfaceSize(defaultSize);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: title,
|
|
home: Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is less than 840.0 pixels, nested layout is
|
|
// used which positions license page title at the top center.
|
|
Offset titleOffset = tester.getCenter(find.text(title));
|
|
expect(titleOffset, Offset(defaultSize.width / 2, 96.0));
|
|
expect(tester.getCenter(find.byType(ListView)), Offset(defaultSize.width / 2, 328.0));
|
|
|
|
// Configure a wide window to show the lateral UI.
|
|
await tester.binding.setSurfaceSize(wideSize);
|
|
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
title: title,
|
|
home: Scaffold(
|
|
body: Directionality(textDirection: textDirection, child: LicensePage()),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// If the layout width is greater than 840.0 pixels, lateral UI layout
|
|
// is used which positions license page title and packageList
|
|
// at the top right.
|
|
titleOffset = tester.getTopLeft(find.text(title));
|
|
expect(titleOffset, const Offset(908.0, 136.0));
|
|
expect(
|
|
titleOffset.dx,
|
|
greaterThan(wideSize.width - 320),
|
|
); // Default master view width is 320.0.
|
|
expect(tester.getCenter(find.byType(ListView)), const Offset(1040.0, 356.0));
|
|
});
|
|
|
|
testWidgets('License page title in lateral UI does not use AppBarTheme.foregroundColor', (
|
|
WidgetTester tester,
|
|
) async {
|
|
// This is a regression test for https://github.com/flutter/flutter/issues/108991
|
|
final theme = ThemeData(appBarTheme: const AppBarTheme(foregroundColor: Color(0xFFFFFFFF)));
|
|
const title = 'License ABC';
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
addTearDown(() async {
|
|
await tester.binding.setSurfaceSize(null);
|
|
});
|
|
|
|
// Configure a wide window to show the lateral UI.
|
|
await tester.binding.setSurfaceSize(const Size(1200.0, 600.0));
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
title: title,
|
|
theme: theme,
|
|
home: const Scaffold(body: LicensePage()),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
final renderParagraph = tester.renderObject(find.text('ABC').last) as RenderParagraph;
|
|
|
|
// License page title should not use AppBarTheme's foregroundColor.
|
|
expect(renderParagraph.text.style!.color, isNot(theme.appBarTheme.foregroundColor));
|
|
|
|
// License page title in the lateral UI uses default text style color.
|
|
expect(renderParagraph.text.style!.color, theme.textTheme.titleLarge!.color);
|
|
});
|
|
|
|
testWidgets('License page default title text color in the nested UI', (
|
|
WidgetTester tester,
|
|
) async {
|
|
// This is a regression test for https://github.com/flutter/flutter/issues/108991
|
|
final theme = ThemeData();
|
|
const title = 'License ABC';
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
title: title,
|
|
theme: theme,
|
|
home: const Scaffold(body: LicensePage()),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// Currently in the master view.
|
|
expect(find.text('License ABC'), findsOneWidget);
|
|
|
|
// Navigate to the license page.
|
|
await tester.tap(find.text('ABC'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Master view is no longer visible.
|
|
expect(find.text('License ABC'), findsNothing);
|
|
|
|
final renderParagraph = tester.renderObject(find.text('ABC').first) as RenderParagraph;
|
|
expect(renderParagraph.text.style!.color, theme.textTheme.titleLarge!.color);
|
|
});
|
|
|
|
group('Material 2', () {
|
|
// These tests are only relevant for Material 2. Once Material 2
|
|
// support is deprecated and the APIs are removed, these tests
|
|
// can be deleted.
|
|
|
|
testWidgets('License page default title text color in the nested UI', (
|
|
WidgetTester tester,
|
|
) async {
|
|
// This is a regression test for https://github.com/flutter/flutter/issues/108991
|
|
final theme = ThemeData(useMaterial3: false);
|
|
const title = 'License ABC';
|
|
LicenseRegistry.addLicense(() {
|
|
return Stream<LicenseEntry>.fromIterable(<LicenseEntry>[
|
|
const LicenseEntryWithLineBreaks(<String>['ABC'], 'DEF'),
|
|
]);
|
|
});
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
title: title,
|
|
theme: theme,
|
|
home: const Scaffold(body: LicensePage()),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle(); // Finish rendering the page.
|
|
|
|
// Currently in the master view.
|
|
expect(find.text('License ABC'), findsOneWidget);
|
|
|
|
// Navigate to the license page.
|
|
await tester.tap(find.text('ABC'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Master view is no longer visible.
|
|
expect(find.text('License ABC'), findsNothing);
|
|
|
|
final renderParagraph = tester.renderObject(find.text('ABC').first) as RenderParagraph;
|
|
expect(renderParagraph.text.style!.color, theme.primaryTextTheme.titleLarge!.color);
|
|
});
|
|
});
|
|
|
|
testWidgets('Adaptive AboutDialog shows correct widget on each platform', (
|
|
WidgetTester tester,
|
|
) async {
|
|
for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(platform: platform),
|
|
home: const Material(
|
|
child: Center(child: ElevatedButton(onPressed: null, child: Text('Go'))),
|
|
),
|
|
),
|
|
);
|
|
|
|
final BuildContext context = tester.element(find.text('Go'));
|
|
|
|
showAdaptiveAboutDialog(
|
|
context: context,
|
|
applicationIcon: const Icon(Icons.abc),
|
|
applicationName: 'Test',
|
|
applicationVersion: '1.0.0',
|
|
applicationLegalese: 'Application Legalese',
|
|
children: <Widget>[const Text('Test1')],
|
|
);
|
|
|
|
await tester.pumpAndSettle(const Duration(seconds: 1));
|
|
expect(find.byType(CupertinoDialogAction), findsWidgets);
|
|
}
|
|
|
|
for (final platform in <TargetPlatform>[
|
|
TargetPlatform.android,
|
|
TargetPlatform.fuchsia,
|
|
TargetPlatform.linux,
|
|
TargetPlatform.windows,
|
|
]) {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(platform: platform),
|
|
home: const Material(
|
|
child: Center(child: ElevatedButton(onPressed: null, child: Text('Go'))),
|
|
),
|
|
),
|
|
);
|
|
|
|
final BuildContext context = tester.element(find.text('Go'));
|
|
|
|
showAboutDialog(
|
|
context: context,
|
|
applicationIcon: const Icon(Icons.abc),
|
|
applicationName: 'Test',
|
|
applicationVersion: '1.0.0',
|
|
);
|
|
|
|
await tester.pumpAndSettle(const Duration(seconds: 1));
|
|
expect(find.byType(CupertinoDialogAction), findsNothing);
|
|
}
|
|
});
|
|
|
|
testWidgets('Adaptive AboutDialog closes correctly on each platform', (
|
|
WidgetTester tester,
|
|
) async {
|
|
for (final platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(platform: platform),
|
|
home: const Material(
|
|
child: Center(child: ElevatedButton(onPressed: null, child: Text('Go'))),
|
|
),
|
|
),
|
|
);
|
|
|
|
final BuildContext context = tester.element(find.text('Go'));
|
|
|
|
showAdaptiveAboutDialog(
|
|
context: context,
|
|
applicationName: 'Test',
|
|
applicationVersion: '1.0.0',
|
|
);
|
|
|
|
await tester.pumpAndSettle(const Duration(seconds: 1));
|
|
expect(find.byType(CupertinoDialogAction), findsWidgets);
|
|
|
|
await tester.tap(find.text('Close'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.byType(CupertinoAlertDialog), findsNothing);
|
|
}
|
|
|
|
for (final platform in <TargetPlatform>[
|
|
TargetPlatform.android,
|
|
TargetPlatform.fuchsia,
|
|
TargetPlatform.linux,
|
|
TargetPlatform.windows,
|
|
]) {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData(platform: platform),
|
|
home: const Material(
|
|
child: Center(child: ElevatedButton(onPressed: null, child: Text('Go'))),
|
|
),
|
|
),
|
|
);
|
|
|
|
final BuildContext context = tester.element(find.text('Go'));
|
|
|
|
showAdaptiveAboutDialog(
|
|
context: context,
|
|
applicationName: 'Test',
|
|
applicationVersion: '1.0.0',
|
|
);
|
|
|
|
await tester.pumpAndSettle(const Duration(seconds: 1));
|
|
expect(find.byType(TextButton), findsWidgets);
|
|
|
|
await tester.tap(find.text('Close'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.byType(AlertDialog), findsNothing);
|
|
}
|
|
});
|
|
|
|
testWidgets('showLicensePage inherits ambient Theme', (WidgetTester tester) async {
|
|
final theme = ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: const Color(0XFFFF0000)));
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Theme(
|
|
data: theme,
|
|
child: Builder(
|
|
builder: (BuildContext context) => ElevatedButton(
|
|
onPressed: () {
|
|
showAboutDialog(
|
|
context: context,
|
|
applicationName: 'Sample Test',
|
|
applicationVersion: 'v1.0.0', // Version of the app
|
|
);
|
|
},
|
|
child: const Text('Show About Dialog'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
// Open the dialog.
|
|
await tester.tap(find.byType(ElevatedButton));
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.tap(find.text('View licenses'));
|
|
await tester.pumpAndSettle();
|
|
|
|
final ThemeData licensePageTheme = Theme.of(tester.element(find.text('Powered by Flutter')));
|
|
expect(theme.colorScheme.primary, licensePageTheme.colorScheme.primary);
|
|
});
|
|
|
|
testWidgets('AboutDialog renders at zero area', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: Center(
|
|
child: SizedBox.shrink(
|
|
child: Scaffold(body: AboutDialog(children: <Widget>[Text('X')])),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
final Finder xText = find.text('X');
|
|
expect(tester.getSize(xText).isEmpty, isTrue);
|
|
});
|
|
|
|
testWidgets('AboutListTile renders at zero area', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: Center(
|
|
child: SizedBox.shrink(
|
|
child: Scaffold(body: AboutListTile(child: Text('X'))),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
final Finder xText = find.text('X');
|
|
expect(tester.getSize(xText).isEmpty, isTrue);
|
|
});
|
|
|
|
testWidgets('LicensePage renders at zero area', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const MaterialApp(
|
|
home: Center(
|
|
child: SizedBox.shrink(
|
|
child: Scaffold(body: LicensePage(applicationName: 'X')),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
final Finder xText = find.text('X');
|
|
expect(tester.getSize(xText).isEmpty, isTrue);
|
|
});
|
|
}
|
|
|
|
class FakeLicenseEntry extends LicenseEntry {
|
|
FakeLicenseEntry();
|
|
|
|
bool get packagesCalled => _packagesCalled;
|
|
bool _packagesCalled = false;
|
|
|
|
@override
|
|
Iterable<LicenseParagraph> paragraphs = <LicenseParagraph>[];
|
|
|
|
@override
|
|
Iterable<String> get packages {
|
|
_packagesCalled = true;
|
|
return <String>[];
|
|
}
|
|
}
|
|
|
|
class LicensePageObserver extends NavigatorObserver {
|
|
int licensePageCount = 0;
|
|
|
|
@override
|
|
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
|
if (route is MaterialPageRoute<dynamic>) {
|
|
licensePageCount++;
|
|
}
|
|
super.didPush(route, previousRoute);
|
|
}
|
|
}
|
|
|
|
class AboutDialogObserver extends NavigatorObserver {
|
|
int dialogCount = 0;
|
|
|
|
@override
|
|
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
|
if (route is DialogRoute) {
|
|
dialogCount++;
|
|
}
|
|
super.didPush(route, previousRoute);
|
|
}
|
|
|
|
@override
|
|
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
|
if (route is DialogRoute) {
|
|
dialogCount--;
|
|
}
|
|
super.didPop(route, previousRoute);
|
|
}
|
|
}
|