Open jarinrocks opened 3 years ago
There was a similar issue related to flutter_driver
api for which a solution was to use FlutterDriver.requestData
to translate the strings, but since there doesn't seem to be an equivalent for requestData
from integration_test
package point of view, https://github.com/flutter/flutter/issues/76852, it doesn't seem to be possible.
Labeling it accordingly.
CC @shihaohong
I have the same issue. This is for us a big blocker to start with integration tests 🙁
@nilsreichardt This might help you https://medium.com/codechai/testing-localized-widget-in-flutter-3bfa5492bc84
@jarinrocks Thanks! I found out that it was another issue. Integration tests are now running :)
@nilsreichardt Are you using localization in the code which you are integration testing?
@jarinrocks Yes, we are using localization, but we are testing with Keys
(await tester.tap(find.byKey(const ValueKey('nav-board-button-e2e')));
). I had an issue that tester
could not tap on anything, even with Key
, Type
, etc. I had a similar issue with Flutter Widget Tests, where localization was the problem. So I thought that localization was blocking integration tests, but this wasn't correct.
I still have the same issue. This is a big blocker for us to start with integration tests.
I have modifier the AppLocalizations
class as below and now I can run the test case with localization successfully. This may be work around for now
part of common;
class AppLocalizations {
final Locale locale;
final bool isTest;
late Map<String,String> _localizedString;
AppLocalizations(this.locale,{this.isTest = false});
/// localizations are access using the InheritedWidget `of` syntax
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
/// A list of this localizations delegate along with the default localizations
/// delegates.
///
/// Returns a list of localizations delegates containing this delegate along with
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
/// and GlobalWidgetsLocalizations.delegate.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];
/// For Widget/Golden/Integration Test only
/// `jsonString` is the localization json file
static LocalizationsDelegate<AppLocalizations> delegateTest(String jsonString) => _AppLocalizationsDelegate(isTest: true, jsonString: jsonString);
/// For Widget/Golden/Integration Test only
/// `jsonString` is the localization json file
static List<LocalizationsDelegate<dynamic>> localizationsDelegatesTest(String jsonString) => <LocalizationsDelegate<dynamic>>[
delegateTest(jsonString),
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];
static AppLocalizations get instance => _AppLocalizationsDelegate.instance;
/// For Widget/Golden/Integration Test only
/// Test runs on `FakeAsync` so we cant use a compute to decode string to map
void loadTest(String jsonString) {
_localizedString = _decodeTranslation(jsonString);
}
// load json translation file from assets
Future<void> load() async {
final jsonString = await rootBundle.loadString('packages/common/assets/i18n/${locale.languageCode}.json');
_localizedString = await compute(_decodeTranslation, jsonString);
}
String translate(String key) {
return _localizedString[key] ?? 'No translation found';
}
Map<String, String> _decodeTranslation(String data) =>
Map<String, String>.from(jsonDecode(data) as Map);
}
/// private class for LocalizationsDelegate
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
// bool variable to know if we running a Test
final bool isTest;
// variable to hold the localization josn file when running Test
final String jsonString;
const _AppLocalizationsDelegate({this.isTest = false, this.jsonString = ''});
static late AppLocalizations instance;
@override
Future<AppLocalizations> load(Locale locale) async {
// create new instance of AppLocalizations
final localization = AppLocalizations(locale, isTest: isTest);
// For Widget/Golden/Integration Test only
if (isTest) {
localization.loadTest(jsonString);
}
else {
// load the translation file
await localization.load();
}
instance = localization;
return instance;
}
@override
bool isSupported(Locale locale) {
// include all your supported locals
return <String>['en', 'hi', 'th'].contains(locale.languageCode);
}
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
From Test create a material app wrapper
return ProviderScope(
overrides: overrides,
child: MaterialApp(
debugShowCheckedModeBanner: false,
// jsonString is the localization json file loaded as String
localizationsDelegates: AppLocalizations.localizationsDelegatesTest(jsonString),
supportedLocales: AppLocales.supportedLocales,
locale: Locale(local),
themeMode: themeMode,
home: home,
),
);
// Integration test code
// Test Driver
// Main screen
// Application class
// App Translation
// App Translation Delegate
// Pubspec
// localization_en.json
// flutter doctor -v
// flutter --verbose
// flutter analyze