Unverified Commit 9c3bfde5 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Updated flutter_localizations tests for Material3; (#128521)

Updated the localization tests so that they'll DTRT when useMaterial3:true becomes the default for ThemeData. In a few cases there are M2 and M3 tests now, to check features that are significantly different in Material3, notably the double ring for the 24  hour input dial. 

| Material 2 | Material 3|
|---------|---------|
|   <img width="250" alt="Screenshot 2023-06-08 at 10 47 37 AM" src="https://github.com/flutter/flutter/assets/1377460/6ca95e22-b3f1-4f6b-9e39-79c888ba58f1"> | <img width="257" alt="Screenshot 2023-06-08 at 10 47 13 AM" src="https://github.com/flutter/flutter/assets/1377460/19b685bf-c812-4c87-baed-70fa56efaad8"> | 

In M3, most aspects of the ideographic text styles are the same as for alphabetic styles, so there are some tweaks here to account for that.
parent 63f41746
...@@ -9,6 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -9,6 +9,7 @@ import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
testWidgets('Nested Localizations', (WidgetTester tester) async { testWidgets('Nested Localizations', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( // Creates the outer Localizations widget. await tester.pumpWidget(MaterialApp( // Creates the outer Localizations widget.
theme: ThemeData(useMaterial3: true),
home: ListView( home: ListView(
children: <Widget>[ children: <Widget>[
const LocalizationTracker(key: ValueKey<String>('outer')), const LocalizationTracker(key: ValueKey<String>('outer')),
...@@ -20,11 +21,12 @@ void main() { ...@@ -20,11 +21,12 @@ void main() {
], ],
), ),
)); ));
// Most localized aspects of the TextTheme text styles are the same for the default US local and
// for Chinese for Material3. The baselines for all text styles differ.
final LocalizationTrackerState outerTracker = tester.state(find.byKey(const ValueKey<String>('outer'), skipOffstage: false)); final LocalizationTrackerState outerTracker = tester.state(find.byKey(const ValueKey<String>('outer'), skipOffstage: false));
expect(outerTracker.bodySmallFontSize, 12.0); expect(outerTracker.textBaseline, TextBaseline.alphabetic);
final LocalizationTrackerState innerTracker = tester.state(find.byKey(const ValueKey<String>('inner'), skipOffstage: false)); final LocalizationTrackerState innerTracker = tester.state(find.byKey(const ValueKey<String>('inner'), skipOffstage: false));
expect(innerTracker.bodySmallFontSize, 13.0); expect(innerTracker.textBaseline, TextBaseline.ideographic);
}); });
testWidgets('Localizations is compatible with ChangeNotifier.dispose() called during didChangeDependencies', (WidgetTester tester) async { testWidgets('Localizations is compatible with ChangeNotifier.dispose() called during didChangeDependencies', (WidgetTester tester) async {
...@@ -92,11 +94,11 @@ class LocalizationTracker extends StatefulWidget { ...@@ -92,11 +94,11 @@ class LocalizationTracker extends StatefulWidget {
} }
class LocalizationTrackerState extends State<LocalizationTracker> { class LocalizationTrackerState extends State<LocalizationTracker> {
late double bodySmallFontSize; late TextBaseline textBaseline;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bodySmallFontSize = Theme.of(context).textTheme.bodySmall!.fontSize!; textBaseline = Theme.of(context).textTheme.bodySmall!.textBaseline!;
return Container(); return Container();
} }
} }
...@@ -93,79 +93,123 @@ void main() { ...@@ -93,79 +93,123 @@ void main() {
}); });
testWidgets('locale parameter overrides ambient locale', (WidgetTester tester) async { testWidgets('locale parameter overrides ambient locale', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( Widget buildFrame(bool useMaterial3) {
locale: const Locale('en', 'US'), return MaterialApp(
supportedLocales: const <Locale>[ theme: ThemeData(useMaterial3: useMaterial3),
Locale('en', 'US'), locale: const Locale('en', 'US'),
Locale('fr', 'CA'), supportedLocales: const <Locale>[
], Locale('en', 'US'),
localizationsDelegates: GlobalMaterialLocalizations.delegates, Locale('fr', 'CA'),
home: Material( ],
child: Builder( localizationsDelegates: GlobalMaterialLocalizations.delegates,
builder: (BuildContext context) { home: Material(
return TextButton( child: Builder(
onPressed: () async { builder: (BuildContext context) {
await showDatePicker( return TextButton(
context: context, onPressed: () async {
initialDate: initialDate, await showDatePicker(
firstDate: firstDate, context: context,
lastDate: lastDate, initialDate: initialDate,
locale: const Locale('fr', 'CA'), firstDate: firstDate,
); lastDate: lastDate,
}, locale: const Locale('fr', 'CA'),
child: const Text('X'), );
); },
}, child: const Text('X'),
);
},
),
), ),
), );
)); }
Element getPicker() => tester.element(find.byType(CalendarDatePicker));
await tester.pumpWidget(buildFrame(true));
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle();
final Element picker = tester.element(find.byType(CalendarDatePicker));
expect( expect(
Localizations.localeOf(picker), Localizations.localeOf(getPicker()),
const Locale('fr', 'CA'), const Locale('fr', 'CA'),
); );
expect(
Directionality.of(getPicker()),
TextDirection.ltr,
);
await tester.tap(find.text('Annuler'));
// The tests below are only relevant for Material 2. Once Material 2
// support is deprecated and the APIs are removed, these tests
// can be deleted.
await tester.pumpWidget(buildFrame(false));
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
expect(
Localizations.localeOf(getPicker()),
const Locale('fr', 'CA'),
);
expect( expect(
Directionality.of(picker), Directionality.of(getPicker()),
TextDirection.ltr, TextDirection.ltr,
); );
await tester.tap(find.text('ANNULER')); await tester.tap(find.text('ANNULER'));
}); });
testWidgets('textDirection parameter overrides ambient textDirection', (WidgetTester tester) async { testWidgets('textDirection parameter overrides ambient textDirection', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( Widget buildFrame(bool useMaterial3) {
locale: const Locale('en', 'US'), return MaterialApp(
home: Material( theme: ThemeData(useMaterial3: useMaterial3),
child: Builder( locale: const Locale('en', 'US'),
builder: (BuildContext context) { home: Material(
return TextButton( child: Builder(
onPressed: () async { builder: (BuildContext context) {
await showDatePicker( return TextButton(
context: context, onPressed: () async {
initialDate: initialDate, await showDatePicker(
firstDate: firstDate, context: context,
lastDate: lastDate, initialDate: initialDate,
textDirection: TextDirection.rtl, firstDate: firstDate,
); lastDate: lastDate,
}, textDirection: TextDirection.rtl,
child: const Text('X'), );
); },
}, child: const Text('X'),
);
},
),
), ),
), );
)); }
Element getPicker() => tester.element(find.byType(CalendarDatePicker));
await tester.pumpWidget(buildFrame(true));
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle();
final Element picker = tester.element(find.byType(CalendarDatePicker));
expect( expect(
Directionality.of(picker), Directionality.of(getPicker()),
TextDirection.rtl,
);
await tester.tap(find.text('Cancel'));
// The tests below are only relevant for Material 2. Once Material 2
// support is deprecated and the APIs are removed, these tests
// can be deleted.
await tester.pumpWidget(buildFrame(false));
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
expect(
Directionality.of(getPicker()),
TextDirection.rtl, TextDirection.rtl,
); );
...@@ -173,45 +217,70 @@ void main() { ...@@ -173,45 +217,70 @@ void main() {
}); });
testWidgets('textDirection parameter takes precedence over locale parameter', (WidgetTester tester) async { testWidgets('textDirection parameter takes precedence over locale parameter', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( Widget buildFrame(bool useMaterial3) {
locale: const Locale('en', 'US'), return MaterialApp(
supportedLocales: const <Locale>[ theme: ThemeData(useMaterial3: useMaterial3),
Locale('en', 'US'), locale: const Locale('en', 'US'),
Locale('fr', 'CA'), supportedLocales: const <Locale>[
], Locale('en', 'US'),
localizationsDelegates: GlobalMaterialLocalizations.delegates, Locale('fr', 'CA'),
home: Material( ],
child: Builder( localizationsDelegates: GlobalMaterialLocalizations.delegates,
builder: (BuildContext context) { home: Material(
return TextButton( child: Builder(
onPressed: () async { builder: (BuildContext context) {
await showDatePicker( return TextButton(
context: context, onPressed: () async {
initialDate: initialDate, await showDatePicker(
firstDate: firstDate, context: context,
lastDate: lastDate, initialDate: initialDate,
locale: const Locale('fr', 'CA'), firstDate: firstDate,
textDirection: TextDirection.rtl, lastDate: lastDate,
); locale: const Locale('fr', 'CA'),
}, textDirection: TextDirection.rtl,
child: const Text('X'), );
); },
}, child: const Text('X'),
);
},
),
), ),
), );
)); }
Element getPicker() => tester.element(find.byType(CalendarDatePicker));
await tester.pumpWidget(buildFrame(true));
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle(const Duration(seconds: 1));
final Element picker = tester.element(find.byType(CalendarDatePicker));
expect( expect(
Localizations.localeOf(picker), Localizations.localeOf(getPicker()),
const Locale('fr', 'CA'),
);
expect(
Directionality.of(getPicker()),
TextDirection.rtl,
);
await tester.tap(find.text('Annuler'));
// The tests below are only relevant for Material 2. Once Material 2
// support is deprecated and the APIs are removed, these tests
// can be deleted.
await tester.pumpWidget(buildFrame(false));
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
expect(
Localizations.localeOf(getPicker()),
const Locale('fr', 'CA'), const Locale('fr', 'CA'),
); );
expect( expect(
Directionality.of(picker), Directionality.of(getPicker()),
TextDirection.rtl, TextDirection.rtl,
); );
......
...@@ -220,7 +220,7 @@ void main() { ...@@ -220,7 +220,7 @@ void main() {
} }
}); });
testWidgets('uses single-ring 24-hour dial for all formats', (WidgetTester tester) async { testWidgets('Material2 uses single-ring 24-hour dial for all locales', (WidgetTester tester) async {
const List<Locale> locales = <Locale>[ const List<Locale> locales = <Locale>[
Locale('en', 'US'), // h Locale('en', 'US'), // h
Locale('en', 'GB'), // HH Locale('en', 'GB'), // HH
...@@ -228,11 +228,11 @@ void main() { ...@@ -228,11 +228,11 @@ void main() {
]; ];
for (final Locale locale in locales) { for (final Locale locale in locales) {
// Tap along the segment stretching from the center to the edge at // Tap along the segment stretching from the center to the edge at
// 12:00 AM position. Because there's only one ring, no matter where you // 12:00 AM position. Because there's only one ring, in the M2
// tap the time will be the same. // DatePicker no matter where you tap the time will be the same.
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
TimeOfDay? result; TimeOfDay? result;
final Offset center = await startPicker(tester, (TimeOfDay? time) { result = time; }, locale: locale); final Offset center = await startPicker(tester, (TimeOfDay? time) { result = time; }, locale: locale, useMaterial3: false);
final Size size = tester.getSize(find.byKey(const Key('time-picker-dial'))); final Size size = tester.getSize(find.byKey(const Key('time-picker-dial')));
final double dy = (size.height / 2.0 / 10) * i; final double dy = (size.height / 2.0 / 10) * i;
await tester.tapAt(Offset(center.dx, center.dy - dy)); await tester.tapAt(Offset(center.dx, center.dy - dy));
...@@ -242,34 +242,57 @@ void main() { ...@@ -242,34 +242,57 @@ void main() {
} }
}); });
testWidgets('Material3 uses a double-ring 24-hour dial for 24 hour locales', (WidgetTester tester) async {
Future<void> testLocale(Locale locale, int startFactor, int endFactor, TimeOfDay expectedTime) async {
// For locales that display 24 hour time, factors 1-5 put the tap on the
// inner ring's "12" (the inner ring goes from 12-23). Otherwise the offset
// should land on the outer ring's "00".
for (int factor = startFactor; factor < endFactor; factor += 1) {
TimeOfDay? result;
final Offset center = await startPicker(tester, (TimeOfDay? time) { result = time; }, locale: locale, useMaterial3: true);
final Size size = tester.getSize(find.byKey(const Key('time-picker-dial')));
final double dy = (size.height / 2.0 / 10) * factor;
await tester.tapAt(Offset(center.dx, center.dy - dy));
await finishPicker(tester);
expect(result, equals(expectedTime), reason: 'Failed for locale=$locale with factor=$factor');
}
}
await testLocale(const Locale('en', 'US'), 1, 10, const TimeOfDay(hour: 0, minute: 0)); // 12 hour
await testLocale(const Locale('en', 'ES'), 1, 10, const TimeOfDay(hour: 0, minute: 0)); // 12 hour
await testLocale(const Locale('en', 'GB'), 1, 5, const TimeOfDay(hour: 12, minute: 0)); // 24 hour, inner ring
await testLocale(const Locale('en', 'GB'), 6, 10, const TimeOfDay(hour: 0, minute: 0)); // 24 hour, outer ring
});
const List<String> labels12To11 = <String>['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']; const List<String> labels12To11 = <String>['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'];
const List<String> labels00To22TwoDigit = <String>['00', '02', '04', '06', '08', '10', '12', '14', '16', '18', '20', '22']; const List<String> labels00To22TwoDigit = <String>['00', '02', '04', '06', '08', '10', '12', '14', '16', '18', '20', '22']; // Material 2
const List<String> labels00To23TwoDigit = <String>[ // Material 3
'00', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
Future<void> mediaQueryBoilerplate(WidgetTester tester, bool alwaysUse24HourFormat) async { Future<void> mediaQueryBoilerplate(WidgetTester tester, {required bool alwaysUse24HourFormat, bool? useMaterial3}) async {
await tester.pumpWidget( await tester.pumpWidget(
Localizations( MaterialApp(
locale: const Locale('en', 'US'), theme: ThemeData(useMaterial3: useMaterial3),
delegates: const <LocalizationsDelegate<dynamic>>[ builder: (BuildContext context, Widget? child) {
GlobalMaterialLocalizations.delegate, return MediaQuery(
DefaultWidgetsLocalizations.delegate, data: MediaQueryData(alwaysUse24HourFormat: alwaysUse24HourFormat),
], child: child!,
child: MediaQuery( );
data: MediaQueryData(alwaysUse24HourFormat: alwaysUse24HourFormat), },
child: Material( home: Material(
child: Directionality( child: Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Navigator( child: Navigator(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<void>(builder: (BuildContext context) { return MaterialPageRoute<void>(builder: (BuildContext context) {
return TextButton( return TextButton(
onPressed: () { onPressed: () {
showTimePicker(context: context, initialTime: const TimeOfDay(hour: 7, minute: 0)); showTimePicker(context: context, initialTime: const TimeOfDay(hour: 7, minute: 0));
}, },
child: const Text('X'), child: const Text('X'),
); );
}); });
}, },
),
), ),
), ),
), ),
...@@ -281,7 +304,7 @@ void main() { ...@@ -281,7 +304,7 @@ void main() {
} }
testWidgets('respects MediaQueryData.alwaysUse24HourFormat == false', (WidgetTester tester) async { testWidgets('respects MediaQueryData.alwaysUse24HourFormat == false', (WidgetTester tester) async {
await mediaQueryBoilerplate(tester, false); await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: false);
final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial'))); final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial')));
final dynamic dialPainter = dialPaint.painter; final dynamic dialPainter = dialPaint.painter;
...@@ -302,8 +325,30 @@ void main() { ...@@ -302,8 +325,30 @@ void main() {
); );
}); });
testWidgets('respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async { testWidgets('Material3 respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
await mediaQueryBoilerplate(tester, true); await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, useMaterial3: true);
final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial')));
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
primaryLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels00To23TwoDigit,
);
// ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
selectedLabels.map<String>((dynamic tp) => ((tp.painter as TextPainter).text! as TextSpan).text!),
labels00To23TwoDigit,
);
});
testWidgets('Material2 respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, useMaterial3: false);
final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial'))); final CustomPaint dialPaint = tester.widget(find.byKey(const ValueKey<String>('time-picker-dial')));
final dynamic dialPainter = dialPaint.painter; final dynamic dialPainter = dialPaint.painter;
...@@ -330,15 +375,18 @@ class _TimePickerLauncher extends StatelessWidget { ...@@ -330,15 +375,18 @@ class _TimePickerLauncher extends StatelessWidget {
this.onChanged, this.onChanged,
required this.locale, required this.locale,
this.entryMode = TimePickerEntryMode.dial, this.entryMode = TimePickerEntryMode.dial,
this.useMaterial3,
}); });
final ValueChanged<TimeOfDay?>? onChanged; final ValueChanged<TimeOfDay?>? onChanged;
final Locale locale; final Locale locale;
final TimePickerEntryMode entryMode; final TimePickerEntryMode entryMode;
final bool? useMaterial3;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
theme: ThemeData(useMaterial3: useMaterial3),
locale: locale, locale: locale,
supportedLocales: <Locale>[locale], supportedLocales: <Locale>[locale],
localizationsDelegates: GlobalMaterialLocalizations.delegates, localizationsDelegates: GlobalMaterialLocalizations.delegates,
...@@ -368,11 +416,13 @@ Future<Offset> startPicker( ...@@ -368,11 +416,13 @@ Future<Offset> startPicker(
WidgetTester tester, WidgetTester tester,
ValueChanged<TimeOfDay?> onChanged, { ValueChanged<TimeOfDay?> onChanged, {
Locale locale = const Locale('en', 'US'), Locale locale = const Locale('en', 'US'),
bool? useMaterial3,
}) async { }) async {
await tester.pumpWidget( await tester.pumpWidget(
_TimePickerLauncher( _TimePickerLauncher(
onChanged: onChanged, onChanged: onChanged,
locale: locale, locale: locale,
useMaterial3: useMaterial3,
), ),
); );
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
......
...@@ -17,6 +17,7 @@ void main() { ...@@ -17,6 +17,7 @@ void main() {
final Key targetKey = UniqueKey(); final Key targetKey = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
theme: ThemeData(useMaterial3: true),
routes: <String, WidgetBuilder>{ routes: <String, WidgetBuilder>{
'/next': (BuildContext context) { '/next': (BuildContext context) {
return const Text('Next'); return const Text('Next');
...@@ -75,20 +76,20 @@ void main() { ...@@ -75,20 +76,20 @@ void main() {
Offset bottomLeft = tester.getBottomLeft(find.text('hello, world')); Offset bottomLeft = tester.getBottomLeft(find.text('hello, world'));
Offset bottomRight = tester.getBottomRight(find.text('hello, world')); Offset bottomRight = tester.getBottomRight(find.text('hello, world'));
expect(topLeft, const Offset(392.0, 299.5)); expect(topLeft, const Offset(392.0, 298.0));
expect(topRight, const Offset(596.0, 299.5)); expect(topRight, const Offset(562.0, 298.0));
expect(bottomLeft, const Offset(392.0, 316.5)); expect(bottomLeft, const Offset(392.0, 318.0));
expect(bottomRight, const Offset(596.0, 316.5)); expect(bottomRight, const Offset(562.0, 318.0));
topLeft = tester.getTopLeft(find.text('你好,世界')); topLeft = tester.getTopLeft(find.text('你好,世界'));
topRight = tester.getTopRight(find.text('你好,世界')); topRight = tester.getTopRight(find.text('你好,世界'));
bottomLeft = tester.getBottomLeft(find.text('你好,世界')); bottomLeft = tester.getBottomLeft(find.text('你好,世界'));
bottomRight = tester.getBottomRight(find.text('你好,世界')); bottomRight = tester.getBottomRight(find.text('你好,世界'));
expect(topLeft, const Offset(392.0, 347.5)); expect(topLeft, const Offset(392.0, 346.0));
expect(topRight, const Offset(477.0, 347.5)); expect(topRight, const Offset(463.0, 346.0));
expect(bottomLeft, const Offset(392.0, 364.5)); expect(bottomLeft, const Offset(392.0, 366.0));
expect(bottomRight, const Offset(477.0, 364.5)); expect(bottomRight, const Offset(463.0, 366.0));
}); });
testWidgets('Text baseline with EN locale', (WidgetTester tester) async { testWidgets('Text baseline with EN locale', (WidgetTester tester) async {
...@@ -101,6 +102,7 @@ void main() { ...@@ -101,6 +102,7 @@ void main() {
final Key targetKey = UniqueKey(); final Key targetKey = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
theme: ThemeData(useMaterial3: true),
routes: <String, WidgetBuilder>{ routes: <String, WidgetBuilder>{
'/next': (BuildContext context) { '/next': (BuildContext context) {
return const Text('Next'); return const Text('Next');
...@@ -159,19 +161,19 @@ void main() { ...@@ -159,19 +161,19 @@ void main() {
Offset bottomLeft = tester.getBottomLeft(find.text('hello, world')); Offset bottomLeft = tester.getBottomLeft(find.text('hello, world'));
Offset bottomRight = tester.getBottomRight(find.text('hello, world')); Offset bottomRight = tester.getBottomRight(find.text('hello, world'));
expect(topLeft, const Offset(392.0, 300.0)); expect(topLeft, const Offset(392.0, 298.0));
expect(topRight, const Offset(584.0, 300.0)); expect(topRight, const Offset(562.0, 298.0));
expect(bottomLeft, const Offset(392.0, 316)); expect(bottomLeft, const Offset(392.0, 318.0));
expect(bottomRight, const Offset(584.0, 316)); expect(bottomRight, const Offset(562.0, 318.0));
topLeft = tester.getTopLeft(find.text('你好,世界')); topLeft = tester.getTopLeft(find.text('你好,世界'));
topRight = tester.getTopRight(find.text('你好,世界')); topRight = tester.getTopRight(find.text('你好,世界'));
bottomLeft = tester.getBottomLeft(find.text('你好,世界')); bottomLeft = tester.getBottomLeft(find.text('你好,世界'));
bottomRight = tester.getBottomRight(find.text('你好,世界')); bottomRight = tester.getBottomRight(find.text('你好,世界'));
expect(topLeft, const Offset(392.0, 348.0)); expect(topLeft, const Offset(392.0, 346.0));
expect(topRight, const Offset(472.0, 348.0)); expect(topRight, const Offset(463.0, 346.0));
expect(bottomLeft, const Offset(392.0, 364.0)); expect(bottomLeft, const Offset(392.0, 366.0));
expect(bottomRight, const Offset(472.0, 364.0)); expect(bottomRight, const Offset(463.0, 366.0));
}); });
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment