flutter/packages/flutter_localizations/test/widgets_test.dart
Ian Hickson 449f4a6673
License update (#45373)
* Update project.pbxproj files to say Flutter rather than Chromium

Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright.

* Update the copyright notice checker to require a standard notice on all files

* Update copyrights on Dart files. (This was a mechanical commit.)

* Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine.

Some were already marked "The Flutter Authors", not clear why. Their
dates have been normalized. Some were missing the blank line after the
license. Some were randomly different in trivial ways for no apparent
reason (e.g. missing the trailing period).

* Clean up the copyrights in non-Dart files. (Manual edits.)

Also, make sure templates don't have copyrights.

* Fix some more ORGANIZATIONNAMEs
2019-11-27 15:04:02 -08:00

1455 lines
50 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:ui' as ui;
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
class TestLocalizations {
TestLocalizations(this.locale, this.prefix);
final Locale locale;
final String prefix;
static Future<TestLocalizations> loadSync(Locale locale, String prefix) {
return SynchronousFuture<TestLocalizations>(TestLocalizations(locale, prefix));
}
static Future<TestLocalizations> loadAsync(Locale locale, String prefix) {
return Future<TestLocalizations>.delayed(const Duration(milliseconds: 100))
.then((_) => TestLocalizations(locale, prefix));
}
static TestLocalizations of(BuildContext context) {
return Localizations.of<TestLocalizations>(context, TestLocalizations);
}
String get message => '${prefix ?? ""}$locale';
}
class SyncTestLocalizationsDelegate extends LocalizationsDelegate<TestLocalizations> {
SyncTestLocalizationsDelegate([this.prefix]);
final String prefix; // Changing this value triggers a rebuild
final List<bool> shouldReloadValues = <bool>[];
@override
bool isSupported(Locale locale) => true;
@override
Future<TestLocalizations> load(Locale locale) => TestLocalizations.loadSync(locale, prefix);
@override
bool shouldReload(SyncTestLocalizationsDelegate old) {
shouldReloadValues.add(prefix != old.prefix);
return prefix != old.prefix;
}
@override
String toString() => '$runtimeType($prefix)';
}
class AsyncTestLocalizationsDelegate extends LocalizationsDelegate<TestLocalizations> {
AsyncTestLocalizationsDelegate([this.prefix]);
final String prefix; // Changing this value triggers a rebuild
final List<bool> shouldReloadValues = <bool>[];
@override
bool isSupported(Locale locale) => true;
@override
Future<TestLocalizations> load(Locale locale) => TestLocalizations.loadAsync(locale, prefix);
@override
bool shouldReload(AsyncTestLocalizationsDelegate old) {
shouldReloadValues.add(prefix != old.prefix);
return prefix != old.prefix;
}
@override
String toString() => '$runtimeType($prefix)';
}
class MoreLocalizations {
MoreLocalizations(this.locale);
final Locale locale;
static Future<MoreLocalizations> loadSync(Locale locale) {
return SynchronousFuture<MoreLocalizations>(MoreLocalizations(locale));
}
static Future<MoreLocalizations> loadAsync(Locale locale) {
return Future<MoreLocalizations>.delayed(const Duration(milliseconds: 100))
.then((_) => MoreLocalizations(locale));
}
static MoreLocalizations of(BuildContext context) {
return Localizations.of<MoreLocalizations>(context, MoreLocalizations);
}
String get message => '$locale';
}
class SyncMoreLocalizationsDelegate extends LocalizationsDelegate<MoreLocalizations> {
@override
Future<MoreLocalizations> load(Locale locale) => MoreLocalizations.loadSync(locale);
@override
bool isSupported(Locale locale) => true;
@override
bool shouldReload(SyncMoreLocalizationsDelegate old) => false;
}
class AsyncMoreLocalizationsDelegate extends LocalizationsDelegate<MoreLocalizations> {
@override
Future<MoreLocalizations> load(Locale locale) => MoreLocalizations.loadAsync(locale);
@override
bool isSupported(Locale locale) => true;
@override
bool shouldReload(AsyncMoreLocalizationsDelegate old) => false;
}
class OnlyRTLDefaultWidgetsLocalizations extends DefaultWidgetsLocalizations {
@override
TextDirection get textDirection => TextDirection.rtl;
}
class OnlyRTLDefaultWidgetsLocalizationsDelegate extends LocalizationsDelegate<WidgetsLocalizations> {
const OnlyRTLDefaultWidgetsLocalizationsDelegate();
@override
bool isSupported(Locale locale) => true;
@override
Future<WidgetsLocalizations> load(Locale locale) {
return SynchronousFuture<WidgetsLocalizations>(OnlyRTLDefaultWidgetsLocalizations());
}
@override
bool shouldReload(OnlyRTLDefaultWidgetsLocalizationsDelegate old) => false;
}
Widget buildFrame({
Locale locale,
Iterable<LocalizationsDelegate<dynamic>> delegates,
WidgetBuilder buildContent,
LocaleResolutionCallback localeResolutionCallback,
List<Locale> supportedLocales = const <Locale>[
Locale('en', 'US'),
Locale('en', 'GB'),
],
}) {
return WidgetsApp(
color: const Color(0xFFFFFFFF),
locale: locale,
localizationsDelegates: delegates,
localeResolutionCallback: localeResolutionCallback,
supportedLocales: supportedLocales,
onGenerateRoute: (RouteSettings settings) {
return PageRouteBuilder<void>(
pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
return buildContent(context);
}
);
},
);
}
class SyncLoadTest extends StatefulWidget {
const SyncLoadTest();
@override
SyncLoadTestState createState() => SyncLoadTestState();
}
class SyncLoadTestState extends State<SyncLoadTest> {
@override
Widget build(BuildContext context) {
return Text(
TestLocalizations.of(context).message,
textDirection: TextDirection.rtl,
);
}
}
void main() {
testWidgets('Localizations.localeFor in a WidgetsApp with system locale', (WidgetTester tester) async {
BuildContext pageContext;
await tester.pumpWidget(
buildFrame(
buildContent: (BuildContext context) {
pageContext = context;
return const Text('Hello World', textDirection: TextDirection.ltr);
}
)
);
await tester.binding.setLocale('en', 'GB');
await tester.pump();
expect(Localizations.localeOf(pageContext), const Locale('en', 'GB'));
await tester.binding.setLocale('en', 'US');
await tester.pump();
expect(Localizations.localeOf(pageContext), const Locale('en', 'US'));
});
testWidgets('Localizations.localeFor in a WidgetsApp with an explicit locale', (WidgetTester tester) async {
const Locale locale = Locale('en', 'US');
BuildContext pageContext;
await tester.pumpWidget(
buildFrame(
locale: locale,
buildContent: (BuildContext context) {
pageContext = context;
return const Text('Hello World');
},
)
);
expect(Localizations.localeOf(pageContext), locale);
await tester.binding.setLocale('en', 'GB');
await tester.pump();
// The WidgetApp's explicit locale overrides the system's locale.
expect(Localizations.localeOf(pageContext), locale);
});
testWidgets('Synchronously loaded localizations in a WidgetsApp', (WidgetTester tester) async {
final List<LocalizationsDelegate<dynamic>> delegates = <LocalizationsDelegate<dynamic>>[
SyncTestLocalizationsDelegate(),
DefaultWidgetsLocalizations.delegate,
];
Future<void> pumpTest(Locale locale) async {
await tester.pumpWidget(Localizations(
locale: locale,
delegates: delegates,
child: const SyncLoadTest(),
));
}
await pumpTest(const Locale('en', 'US'));
expect(find.text('en_US'), findsOneWidget);
await pumpTest(const Locale('en', 'GB'));
await tester.pump();
expect(find.text('en_GB'), findsOneWidget);
await pumpTest(const Locale('en', 'US'));
await tester.pump();
expect(find.text('en_US'), findsOneWidget);
});
testWidgets('Asynchronously loaded localizations in a WidgetsApp', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
AsyncTestLocalizationsDelegate(),
],
buildContent: (BuildContext context) {
return Text(TestLocalizations.of(context).message);
},
)
);
await tester.pump(const Duration(milliseconds: 50)); // TestLocalizations.loadAsync() takes 100ms
expect(find.text('en_US'), findsNothing); // TestLocalizations hasn't been loaded yet
await tester.pump(const Duration(milliseconds: 50)); // TestLocalizations.loadAsync() completes
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget); // default test locale is US english
await tester.binding.setLocale('en', 'GB');
await tester.pump(const Duration(milliseconds: 100));
await tester.pumpAndSettle();
expect(find.text('en_GB'), findsOneWidget);
await tester.binding.setLocale('en', 'US');
await tester.pump(const Duration(milliseconds: 50));
// TestLocalizations.loadAsync() hasn't completed yet so the old text
// localization is still displayed
expect(find.text('en_GB'), findsOneWidget);
await tester.pump(const Duration(milliseconds: 50)); // finish the async load
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
});
testWidgets('Localizations with multiple sync delegates', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
SyncTestLocalizationsDelegate(),
SyncMoreLocalizationsDelegate(),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Column(
children: <Widget>[
Text('A: ${TestLocalizations.of(context).message}'),
Text('B: ${MoreLocalizations.of(context).message}'),
],
);
},
)
);
// All localizations were loaded synchronously
expect(find.text('A: en_US'), findsOneWidget);
expect(find.text('B: en_US'), findsOneWidget);
});
testWidgets('Localizations with multiple delegates', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
SyncTestLocalizationsDelegate(),
AsyncMoreLocalizationsDelegate(), // No resources until this completes
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Column(
children: <Widget>[
Text('A: ${TestLocalizations.of(context).message}'),
Text('B: ${MoreLocalizations.of(context).message}'),
],
);
},
)
);
await tester.pump(const Duration(milliseconds: 50));
expect(find.text('A: en_US'), findsNothing); // MoreLocalizations.load() hasn't completed yet
expect(find.text('B: en_US'), findsNothing);
await tester.pump(const Duration(milliseconds: 50));
await tester.pumpAndSettle();
expect(find.text('A: en_US'), findsOneWidget);
expect(find.text('B: en_US'), findsOneWidget);
});
testWidgets('Multiple Localizations', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
SyncTestLocalizationsDelegate(),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Column(
children: <Widget>[
Text('A: ${TestLocalizations.of(context).message}'),
Localizations(
locale: const Locale('en', 'GB'),
delegates: <LocalizationsDelegate<dynamic>>[
SyncTestLocalizationsDelegate(),
DefaultWidgetsLocalizations.delegate,
],
// Create a new context within the en_GB Localization
child: Builder(
builder: (BuildContext context) {
return Text('B: ${TestLocalizations.of(context).message}');
},
),
),
],
);
},
)
);
expect(find.text('A: en_US'), findsOneWidget);
expect(find.text('B: en_GB'), findsOneWidget);
});
// If both the locale and the length and type of a Localizations delegate list
// stays the same BUT one of its delegate.shouldReload() methods returns true,
// then the dependent widgets should rebuild.
testWidgets('Localizations sync delegate shouldReload returns true', (WidgetTester tester) async {
final SyncTestLocalizationsDelegate originalDelegate = SyncTestLocalizationsDelegate();
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
originalDelegate,
SyncMoreLocalizationsDelegate(),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Column(
children: <Widget>[
Text('A: ${TestLocalizations.of(context).message}'),
Text('B: ${MoreLocalizations.of(context).message}'),
],
);
},
)
);
await tester.pumpAndSettle();
expect(find.text('A: en_US'), findsOneWidget);
expect(find.text('B: en_US'), findsOneWidget);
expect(originalDelegate.shouldReloadValues, <bool>[]);
final SyncTestLocalizationsDelegate modifiedDelegate = SyncTestLocalizationsDelegate('---');
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
modifiedDelegate,
SyncMoreLocalizationsDelegate(),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Column(
children: <Widget>[
Text('A: ${TestLocalizations.of(context).message}'),
Text('B: ${MoreLocalizations.of(context).message}'),
],
);
},
)
);
await tester.pumpAndSettle();
expect(find.text('A: ---en_US'), findsOneWidget);
expect(find.text('B: en_US'), findsOneWidget);
expect(modifiedDelegate.shouldReloadValues, <bool>[true]);
expect(originalDelegate.shouldReloadValues, <bool>[]);
});
testWidgets('Localizations async delegate shouldReload returns true', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
AsyncTestLocalizationsDelegate(),
AsyncMoreLocalizationsDelegate(),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Column(
children: <Widget>[
Text('A: ${TestLocalizations.of(context).message}'),
Text('B: ${MoreLocalizations.of(context).message}'),
],
);
},
)
);
await tester.pumpAndSettle();
expect(find.text('A: en_US'), findsOneWidget);
expect(find.text('B: en_US'), findsOneWidget);
final AsyncTestLocalizationsDelegate modifiedDelegate = AsyncTestLocalizationsDelegate('---');
await tester.pumpWidget(
buildFrame(
delegates: <LocalizationsDelegate<dynamic>>[
modifiedDelegate,
AsyncMoreLocalizationsDelegate(),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Column(
children: <Widget>[
Text('A: ${TestLocalizations.of(context).message}'),
Text('B: ${MoreLocalizations.of(context).message}'),
],
);
},
)
);
await tester.pumpAndSettle();
expect(find.text('A: ---en_US'), findsOneWidget);
expect(find.text('B: en_US'), findsOneWidget);
expect(modifiedDelegate.shouldReloadValues, <bool>[true]);
});
testWidgets('Directionality tracks system locale', (WidgetTester tester) async {
BuildContext pageContext;
await tester.pumpWidget(
buildFrame(
delegates: const <LocalizationsDelegate<dynamic>>[
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: const <Locale>[
Locale('en', 'GB'),
Locale('ar', 'EG'),
],
buildContent: (BuildContext context) {
pageContext = context;
return const Text('Hello World');
},
)
);
await tester.binding.setLocale('en', 'GB');
await tester.pump();
expect(Directionality.of(pageContext), TextDirection.ltr);
await tester.binding.setLocale('ar', 'EG');
await tester.pump();
expect(Directionality.of(pageContext), TextDirection.rtl);
});
testWidgets('localeResolutionCallback override', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
localeResolutionCallback: (Locale newLocale, Iterable<Locale> supportedLocales) {
return const Locale('foo', 'BAR');
},
buildContent: (BuildContext context) {
return Text(Localizations.localeOf(context).toString());
},
)
);
await tester.pumpAndSettle();
expect(find.text('foo_BAR'), findsOneWidget);
await tester.binding.setLocale('en', 'GB');
await tester.pumpAndSettle();
expect(find.text('foo_BAR'), findsOneWidget);
});
testWidgets('supportedLocales and defaultLocaleChangeHandler', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('zh', 'CN'),
Locale('en', 'GB'),
Locale('en', 'CA'),
],
buildContent: (BuildContext context) {
return Text(Localizations.localeOf(context).toString());
},
)
);
await tester.pumpAndSettle();
expect(find.text('en_GB'), findsOneWidget);
// defaultLocaleChangedHandler prefers exact supported locale match
await tester.binding.setLocale('en', 'CA');
await tester.pumpAndSettle();
expect(find.text('en_CA'), findsOneWidget);
// defaultLocaleChangedHandler chooses 1st matching supported locale.languageCode
await tester.binding.setLocale('en', 'US');
await tester.pumpAndSettle();
expect(find.text('en_GB'), findsOneWidget);
// defaultLocaleChangedHandler: no matching supported locale, so use the 1st one
await tester.binding.setLocale('da', 'DA');
await tester.pumpAndSettle();
expect(find.text('zh_CN'), findsOneWidget);
});
testWidgets('Localizations.override widget tracks parent\'s locale and delegates', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
delegates: const <LocalizationsDelegate<dynamic>>[
GlobalWidgetsLocalizations.delegate,
],
buildContent: (BuildContext context) {
return Localizations.override(
context: context,
child: Builder(
builder: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final TextDirection direction = WidgetsLocalizations.of(context).textDirection;
return Text('$locale $direction');
},
),
);
},
)
);
// Initial WidgetTester locale is `en_US`.
await tester.pumpAndSettle();
expect(find.text('en_US TextDirection.ltr'), findsOneWidget);
await tester.binding.setLocale('en', 'CA');
await tester.pumpAndSettle();
expect(find.text('en_CA TextDirection.ltr'), findsOneWidget);
await tester.binding.setLocale('ar', 'EG');
await tester.pumpAndSettle();
expect(find.text('ar_EG TextDirection.rtl'), findsOneWidget);
await tester.binding.setLocale('da', 'DA');
await tester.pumpAndSettle();
expect(find.text('da_DA TextDirection.ltr'), findsOneWidget);
});
testWidgets('Localizations.override widget overrides parent\'s DefaultWidgetLocalizations', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
buildContent: (BuildContext context) {
return Localizations.override(
context: context,
delegates: const <OnlyRTLDefaultWidgetsLocalizationsDelegate>[
// Override: no matter what the locale, textDirection is always RTL.
OnlyRTLDefaultWidgetsLocalizationsDelegate(),
],
child: Builder(
builder: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final TextDirection direction = WidgetsLocalizations.of(context).textDirection;
return Text('$locale $direction');
},
),
);
},
)
);
// Initial WidgetTester locale is `en_US`.
await tester.pumpAndSettle();
expect(find.text('en_US TextDirection.rtl'), findsOneWidget);
await tester.binding.setLocale('en', 'CA');
await tester.pumpAndSettle();
expect(find.text('en_CA TextDirection.rtl'), findsOneWidget);
await tester.binding.setLocale('ar', 'EG');
await tester.pumpAndSettle();
expect(find.text('ar_EG TextDirection.rtl'), findsOneWidget);
await tester.binding.setLocale('da', 'DA');
await tester.pumpAndSettle();
expect(find.text('da_DA TextDirection.rtl'), findsOneWidget);
});
testWidgets('WidgetsApp overrides DefaultWidgetLocalizations', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
delegates: <OnlyRTLDefaultWidgetsLocalizationsDelegate>[
const OnlyRTLDefaultWidgetsLocalizationsDelegate(),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
final TextDirection direction = WidgetsLocalizations.of(context).textDirection;
return Text('$locale $direction');
},
)
);
// Initial WidgetTester locale is `en_US`.
await tester.pumpAndSettle();
expect(find.text('en_US TextDirection.rtl'), findsOneWidget);
await tester.binding.setLocale('en', 'CA');
await tester.pumpAndSettle();
expect(find.text('en_CA TextDirection.rtl'), findsOneWidget);
await tester.binding.setLocale('ar', 'EG');
await tester.pumpAndSettle();
expect(find.text('ar_EG TextDirection.rtl'), findsOneWidget);
await tester.binding.setLocale('da', 'DA');
await tester.pumpAndSettle();
expect(find.text('da_DA TextDirection.rtl'), findsOneWidget);
});
// We provide <Locale>[Locale('en', 'US'), Locale('zh', 'CN')] as ui.window.locales
// for flutter tester so that the behavior of tests match that of production
// environments. Here, we test the default locales.
testWidgets('WidgetsApp DefaultWidgetLocalizations', (WidgetTester tester) async {
await tester.pumpAndSettle();
await tester.pumpWidget(
buildFrame(
// Accept whatever locale we're given
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) => locale,
delegates: <OnlyRTLDefaultWidgetsLocalizationsDelegate>[
const OnlyRTLDefaultWidgetsLocalizationsDelegate(),
],
buildContent: (BuildContext context) {
final Locale locale1 = ui.window.locales.first;
final Locale locale2 = ui.window.locales[1];
return Text('$locale1 $locale2');
},
)
);
// Initial WidgetTester default locales is `en_US` and `zh_CN`.
await tester.pumpAndSettle();
expect(find.text('en_US zh_CN'), findsOneWidget);
});
testWidgets('WidgetsApp.locale is resolved against supportedLocales', (WidgetTester tester) async {
// app locale matches a supportedLocale
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('zh', 'CN'),
Locale('en', 'US'),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Text(Localizations.localeOf(context).toString());
},
)
);
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
// app locale matches a supportedLocale's language
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('zh', 'CN'),
Locale('en', 'GB'),
],
locale: const Locale('en', 'US'),
buildContent: (BuildContext context) {
return Text(Localizations.localeOf(context).toString());
},
)
);
await tester.pumpAndSettle();
expect(find.text('en_GB'), findsOneWidget);
// app locale matches no supportedLocale
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('zh', 'CN'),
Locale('en', 'US'),
],
locale: const Locale('ab', 'CD'),
buildContent: (BuildContext context) {
return Text(Localizations.localeOf(context).toString());
},
)
);
await tester.pumpAndSettle();
expect(find.text('zh_CN'), findsOneWidget);
});
// Example from http://unicode.org/reports/tr35/#LanguageMatching
testWidgets('WidgetsApp Unicode tr35 1', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('de'),
Locale('fr'),
Locale('ja'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'de', countryCode: 'AT'),
Locale.fromSubtags(languageCode: 'fr'),]
);
await tester.pumpAndSettle();
expect(find.text('de'), findsOneWidget);
});
// Examples from http://unicode.org/reports/tr35/#LanguageMatching
testWidgets('WidgetsApp Unicode tr35 2', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('ja', 'JP'),
Locale('de'),
Locale('zh', 'TW'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'de'),
Locale.fromSubtags(languageCode: 'fr'),
Locale.fromSubtags(languageCode: 'de', countryCode: 'SW'),
Locale.fromSubtags(languageCode: 'it'),]
);
await tester.pumpAndSettle();
expect(find.text('de'), findsOneWidget);
});
testWidgets('WidgetsApp EdgeCase Chinese', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale.fromSubtags(languageCode: 'zh'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'HK'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'de'),
Locale.fromSubtags(languageCode: 'fr'),
Locale.fromSubtags(languageCode: 'de', countryCode: 'SW'),
Locale.fromSubtags(languageCode: 'zh'),]
);
await tester.pumpAndSettle();
expect(find.text('zh'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'HK'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'HK'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('zh'), findsOneWidget);
// This behavior is up to the implementer to decide if a perfect scriptCode match
// is better than a countryCode match.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'CN'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),
Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
// languageCode only match is not enough to prevent resolving a perfect match
// further down the preferredLocales list.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'JP'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
// When no language match, we try for country only, since it is likely users are
// at least familiar with their country's language. This is a possible case only
// on iOS, where countryCode can be selected independently from language and script.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', scriptCode: 'Hans', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'HK'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
});
// Same as 'WidgetsApp EdgeCase Chinese' test except the supportedLocales order is
// reversed.
testWidgets('WidgetsApp EdgeCase ReverseChinese', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'HK'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),
Locale.fromSubtags(languageCode: 'zh'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'de'),
Locale.fromSubtags(languageCode: 'fr'),
Locale.fromSubtags(languageCode: 'de', countryCode: 'SW'),
Locale.fromSubtags(languageCode: 'zh'),]
);
await tester.pumpAndSettle();
expect(find.text('zh'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'HK'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'HK'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
// This behavior is up to the implementer to decide if a perfect scriptCode match
// is better than a countryCode match.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'CN'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),
Locale.fromSubtags(languageCode: 'zh', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
// languageCode only match is not enough to prevent resolving a perfect match
// further down the preferredLocales list.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'JP'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'zh', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),
Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hans_CN'), findsOneWidget);
// When no language match, we try for country only, since it is likely users are
// at least familiar with their country's language. This is a possible case only
// on iOS, where countryCode can be selected independently from language and script.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', scriptCode: 'Hans', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'TW'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_TW'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'HK'),]
);
await tester.pumpAndSettle();
expect(find.text('zh_Hant_HK'), findsOneWidget);
});
// Examples from https://developer.android.com/guide/topics/resources/multilingual-support
testWidgets('WidgetsApp Android', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('en'),
Locale('de', 'DE'),
Locale('es', 'ES'),
Locale('fr', 'FR'),
Locale('it', 'IT'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'fr', countryCode: 'CH'),]
);
await tester.pumpAndSettle();
expect(find.text('fr_FR'), findsOneWidget);
});
// Examples from https://developer.android.com/guide/topics/resources/multilingual-support
testWidgets('WidgetsApp Android', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('en'),
Locale('de', 'DE'),
Locale('es', 'ES'),
Locale('it', 'IT'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'fr', countryCode: 'CH'),
Locale.fromSubtags(languageCode: 'it', countryCode: 'CH'),]
);
await tester.pumpAndSettle();
expect(find.text('it_IT'), findsOneWidget);
});
testWidgets('WidgetsApp Country-only fallback', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('en', 'US'),
Locale('de', 'DE'),
Locale('de', 'AU'),
Locale('de', 'LU'),
Locale('de', 'CH'),
Locale('es', 'ES'),
Locale('es', 'US'),
Locale('it', 'IT'),
Locale('zh', 'CN'),
Locale('zh', 'TW'),
Locale('fr', 'FR'),
Locale('br', 'FR'),
Locale('pt', 'BR'),
Locale('pt', 'PT'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar', countryCode: 'CH'),]
);
await tester.pumpAndSettle();
expect(find.text('de_CH'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar', countryCode: 'FR'),]
);
await tester.pumpAndSettle();
expect(find.text('fr_FR'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'es', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('es_US'), findsOneWidget);
// Strongly prefer matching first locale even if next one is perfect.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'pt'),
Locale.fromSubtags(languageCode: 'pt', countryCode: 'PT'),]
);
await tester.pumpAndSettle();
expect(find.text('pt_PT'), findsOneWidget);
// Don't country match with any other available match. This behavior is
// up for reconsideration.
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar', countryCode: 'BR'),
Locale.fromSubtags(languageCode: 'pt'),]
);
await tester.pumpAndSettle();
expect(find.text('pt_BR'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar', countryCode: 'BR'),
Locale.fromSubtags(languageCode: 'pt', countryCode: 'PT'),]
);
await tester.pumpAndSettle();
expect(find.text('pt_PT'), findsOneWidget);
});
// Simulates a Chinese-default app that supports english in Canada but not
// French. French-Canadian users should get 'en_CA' instead of Chinese.
testWidgets('WidgetsApp Multilingual country', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('zh', 'CN'),
Locale('en', 'CA'),
Locale('en', 'US'),
Locale('en', 'AU'),
Locale('de', 'DE'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'fr', countryCode: 'CA'),
Locale.fromSubtags(languageCode: 'fr'),]
);
await tester.pumpAndSettle();
expect(find.text('en_CA'), findsOneWidget);
});
testWidgets('WidgetsApp Common cases', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
// Decently well localized app.
supportedLocales: const <Locale>[
Locale('en', 'US'),
Locale('en', 'GB'),
Locale('en', 'AU'),
Locale('en', 'CA'),
Locale('zh', 'CN'),
Locale('zh', 'TW'),
Locale('de', 'DE'),
Locale('de', 'CH'),
Locale('es', 'MX'),
Locale('es', 'ES'),
Locale('es', 'AR'),
Locale('es', 'CO'),
Locale('ru', 'RU'),
Locale('fr', 'FR'),
Locale('fr', 'CA'),
Locale('ar', 'SA'),
Locale('ar', 'EG'),
Locale('ar', 'IQ'),
Locale('ar', 'MA'),
Locale('af'),
Locale('bg'),
Locale('nl', 'NL'),
Locale('pl'),
Locale('cs'),
Locale('fa'),
Locale('el'),
Locale('he'),
Locale('hi'),
Locale('pa'),
Locale('ta'),
Locale('id'),
Locale('it', 'IT'),
Locale('ja'),
Locale('ko'),
Locale('ms'),
Locale('mn'),
Locale('pt', 'BR'),
Locale('pt', 'PT'),
Locale('sv', 'SE'),
Locale('th'),
Locale('tr'),
Locale('vi'),
],
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en'),]
);
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'CA'),]
);
await tester.pumpAndSettle();
expect(find.text('en_CA'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'AU'),]
);
await tester.pumpAndSettle();
expect(find.text('en_AU'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar', countryCode: 'CH'),]
);
await tester.pumpAndSettle();
expect(find.text('ar_SA'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar'),]
);
await tester.pumpAndSettle();
expect(find.text('ar_SA'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ar', countryCode: 'IQ'),]
);
await tester.pumpAndSettle();
expect(find.text('ar_IQ'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'es', countryCode: 'ES'),]
);
await tester.pumpAndSettle();
expect(find.text('es_ES'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'es'),]
);
await tester.pumpAndSettle();
expect(find.text('es_MX'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'pa', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('pa'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'hi', countryCode: 'IN'),]
);
await tester.pumpAndSettle();
expect(find.text('hi'), findsOneWidget);
// Multiple preferred locales:
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'NZ'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'AU'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'GB'),
Locale.fromSubtags(languageCode: 'en'),]
);
await tester.pumpAndSettle();
expect(find.text('en_AU'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'ab'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'NZ'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'AU'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'GB'),
Locale.fromSubtags(languageCode: 'en'),]
);
await tester.pumpAndSettle();
expect(find.text('en_AU'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'NZ'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'PH'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'ZA'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'CB'),]
);
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'CA'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'AU'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'GB'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('en_CA'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'da'),
Locale.fromSubtags(languageCode: 'en'),
Locale.fromSubtags(languageCode: 'en', countryCode: 'CA'),]
);
await tester.pumpAndSettle();
expect(find.text('en_CA'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'da'),
Locale.fromSubtags(languageCode: 'fo'),
Locale.fromSubtags(languageCode: 'hr'),]
);
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'da'),
Locale.fromSubtags(languageCode: 'fo'),
Locale.fromSubtags(languageCode: 'hr', countryCode: 'CA'),]
);
await tester.pumpAndSettle();
expect(find.text('en_CA'), findsOneWidget);
});
testWidgets('WidgetsApp invalid preferredLocales', (WidgetTester tester) async {
await tester.pumpWidget(
buildFrame(
supportedLocales: const <Locale>[
Locale('zh', 'CN'),
Locale('en', 'CA'),
Locale('en', 'US'),
Locale('en', 'AU'),
Locale('de', 'DE'),
],
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) {
if (locale == null)
return const Locale('und', 'US');
return const Locale('en', 'US');
},
buildContent: (BuildContext context) {
final Locale locale = Localizations.localeOf(context);
return Text('$locale');
},
)
);
await tester.binding.setLocales(const <Locale>[
Locale.fromSubtags(languageCode: 'en', countryCode: 'US'),]
);
await tester.pumpAndSettle();
expect(find.text('en_US'), findsOneWidget);
await tester.binding.setLocales(null);
await tester.pumpAndSettle();
expect(find.text('und_US'), findsOneWidget);
await tester.binding.setLocales(const <Locale>[]);
await tester.pumpAndSettle();
expect(find.text('und_US'), findsOneWidget);
});
}