Unverified Commit bd940073 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate localizations_utils to null safety (#78939)

parent b8041178
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import 'package:yaml/yaml.dart';
......@@ -22,11 +20,11 @@ int sortFilesByPath (File a, File b) {
@immutable
class LocaleInfo implements Comparable<LocaleInfo> {
const LocaleInfo({
this.languageCode,
this.scriptCode,
this.countryCode,
this.length,
this.originalString,
required this.languageCode,
required this.scriptCode,
required this.countryCode,
required this.length,
required this.originalString,
});
/// Simple parser. Expects the locale string to be in the form of 'language_script_COUNTRY'
......@@ -41,8 +39,8 @@ class LocaleInfo implements Comparable<LocaleInfo> {
final List<String> codes = locale.split('_'); // [language, script, country]
assert(codes.isNotEmpty && codes.length < 4);
final String languageCode = codes[0];
String scriptCode;
String countryCode;
String? scriptCode;
String? countryCode;
int length = codes.length;
String originalString = locale;
if (codes.length == 2) {
......@@ -112,8 +110,8 @@ class LocaleInfo implements Comparable<LocaleInfo> {
}
final String languageCode;
final String scriptCode;
final String countryCode;
final String? scriptCode;
final String? countryCode;
final int length; // The number of fields. Ranges from 1-3.
final String originalString; // Original un-parsed locale string.
......@@ -149,7 +147,7 @@ class LocaleInfo implements Comparable<LocaleInfo> {
// See also //master/tools/gen_locale.dart in the engine repo.
Map<String, List<String>> _parseSection(String section) {
final Map<String, List<String>> result = <String, List<String>>{};
List<String> lastHeading;
late List<String> lastHeading;
for (final String line in section.split('\n')) {
if (line == '') {
continue;
......@@ -165,7 +163,7 @@ Map<String, List<String>> _parseSection(String section) {
final String name = line.substring(0, colon);
final String value = line.substring(colon + 2);
lastHeading = result.putIfAbsent(name, () => <String>[]);
result[name].add(value);
result[name]!.add(value);
}
return result;
}
......@@ -184,11 +182,11 @@ void precacheLanguageAndRegionTags() {
languageSubtagRegistry.split('%%').skip(1).map<Map<String, List<String>>>(_parseSection).toList();
for (final Map<String, List<String>> section in sections) {
assert(section.containsKey('Type'), section.toString());
final String type = section['Type'].single;
final String type = section['Type']!.single;
if (type == 'language' || type == 'region' || type == 'script') {
assert(section.containsKey('Subtag') && section.containsKey('Description'), section.toString());
final String subtag = section['Subtag'].single;
String description = section['Description'].join(' ');
final String subtag = section['Subtag']!.single;
String description = section['Description']!.join(' ');
if (description.startsWith('United ')) {
description = 'the $description';
}
......@@ -220,10 +218,10 @@ String describeLocale(String tag) {
final List<String> subtags = tag.split('_');
assert(subtags.isNotEmpty);
assert(_languages.containsKey(subtags[0]));
final String language = _languages[subtags[0]];
final String language = _languages[subtags[0]]!;
String output = language;
String region;
String script;
String? region;
String? script;
if (subtags.length == 2) {
region = _regions[subtags[1]];
script = _scripts[subtags[1]];
......@@ -311,50 +309,50 @@ class LocalizationOptions {
/// The `--arb-dir` argument.
///
/// The directory where all input localization files should reside.
final Uri arbDirectory;
final Uri? arbDirectory;
/// The `--template-arb-file` argument.
///
/// This URI is relative to [arbDirectory].
final Uri templateArbFile;
final Uri? templateArbFile;
/// The `--output-localization-file` argument.
///
/// This URI is relative to [arbDirectory].
final Uri outputLocalizationsFile;
final Uri? outputLocalizationsFile;
/// The `--untranslated-messages-file` argument.
///
/// This URI is relative to [arbDirectory].
final Uri untranslatedMessagesFile;
final Uri? untranslatedMessagesFile;
/// The `--header` argument.
///
/// The header to prepend to the generated Dart localizations.
final String header;
final String? header;
/// The `--output-class` argument.
final String outputClass;
final String? outputClass;
/// The `--output-dir` argument.
///
/// The directory where all output localization files should be generated.
final Uri outputDirectory;
final Uri? outputDirectory;
/// The `--preferred-supported-locales` argument.
final List<String> preferredSupportedLocales;
final List<String>? preferredSupportedLocales;
/// The `--header-file` argument.
///
/// A file containing the header to prepend to the generated
/// Dart localizations.
final Uri headerFile;
final Uri? headerFile;
/// The `--use-deferred-loading` argument.
///
/// Whether to generate the Dart localization file with locales imported
/// as deferred.
final bool deferredLoading;
final bool? deferredLoading;
/// The `--synthetic-package` argument.
///
......@@ -375,8 +373,8 @@ class LocalizationOptions {
/// [LocalizationOptions] with all fields as `null` if the config file exists
/// but is empty.
LocalizationOptions parseLocalizationsOptions({
@required File file,
@required Logger logger,
required File file,
required Logger logger,
}) {
final String contents = file.readAsStringSync();
if (contents.trim().isEmpty) {
......@@ -387,26 +385,25 @@ LocalizationOptions parseLocalizationsOptions({
logger.printError('Expected ${file.path} to contain a map, instead was $yamlNode');
throw Exception();
}
final YamlMap yamlMap = yamlNode as YamlMap;
return LocalizationOptions(
arbDirectory: _tryReadUri(yamlMap, 'arb-dir', logger),
templateArbFile: _tryReadUri(yamlMap, 'template-arb-file', logger),
outputLocalizationsFile: _tryReadUri(yamlMap, 'output-localization-file', logger),
untranslatedMessagesFile: _tryReadUri(yamlMap, 'untranslated-messages-file', logger),
header: _tryReadString(yamlMap, 'header', logger),
outputClass: _tryReadString(yamlMap, 'output-class', logger),
outputDirectory: _tryReadUri(yamlMap, 'output-dir', logger),
preferredSupportedLocales: _tryReadStringList(yamlMap, 'preferred-supported-locales', logger),
headerFile: _tryReadUri(yamlMap, 'header-file', logger),
deferredLoading: _tryReadBool(yamlMap, 'use-deferred-loading', logger),
useSyntheticPackage: _tryReadBool(yamlMap, 'synthetic-package', logger) ?? true,
areResourceAttributesRequired: _tryReadBool(yamlMap, 'required-resource-attributes', logger) ?? false,
arbDirectory: _tryReadUri(yamlNode, 'arb-dir', logger),
templateArbFile: _tryReadUri(yamlNode, 'template-arb-file', logger),
outputLocalizationsFile: _tryReadUri(yamlNode, 'output-localization-file', logger),
untranslatedMessagesFile: _tryReadUri(yamlNode, 'untranslated-messages-file', logger),
header: _tryReadString(yamlNode, 'header', logger),
outputClass: _tryReadString(yamlNode, 'output-class', logger),
outputDirectory: _tryReadUri(yamlNode, 'output-dir', logger),
preferredSupportedLocales: _tryReadStringList(yamlNode, 'preferred-supported-locales', logger),
headerFile: _tryReadUri(yamlNode, 'header-file', logger),
deferredLoading: _tryReadBool(yamlNode, 'use-deferred-loading', logger),
useSyntheticPackage: _tryReadBool(yamlNode, 'synthetic-package', logger) ?? true,
areResourceAttributesRequired: _tryReadBool(yamlNode, 'required-resource-attributes', logger) ?? false,
);
}
// Try to read a `bool` value or null from `yamlMap`, otherwise throw.
bool _tryReadBool(YamlMap yamlMap, String key, Logger logger) {
final Object value = yamlMap[key];
bool? _tryReadBool(YamlMap yamlMap, String key, Logger logger) {
final Object? value = yamlMap[key];
if (value == null) {
return null;
}
......@@ -414,12 +411,12 @@ bool _tryReadBool(YamlMap yamlMap, String key, Logger logger) {
logger.printError('Expected "$key" to have a bool value, instead was "$value"');
throw Exception();
}
return value as bool;
return value;
}
// Try to read a `String` value or null from `yamlMap`, otherwise throw.
String _tryReadString(YamlMap yamlMap, String key, Logger logger) {
final Object value = yamlMap[key];
String? _tryReadString(YamlMap yamlMap, String key, Logger logger) {
final Object? value = yamlMap[key];
if (value == null) {
return null;
}
......@@ -427,11 +424,11 @@ String _tryReadString(YamlMap yamlMap, String key, Logger logger) {
logger.printError('Expected "$key" to have a String value, instead was "$value"');
throw Exception();
}
return value as String;
return value;
}
List<String> _tryReadStringList(YamlMap yamlMap, String key, Logger logger) {
final Object value = yamlMap[key];
List<String>? _tryReadStringList(YamlMap yamlMap, String key, Logger logger) {
final Object? value = yamlMap[key];
if (value == null) {
return null;
}
......@@ -446,12 +443,12 @@ List<String> _tryReadStringList(YamlMap yamlMap, String key, Logger logger) {
}
// Try to read a valid `Uri` or null from `yamlMap`, otherwise throw.
Uri _tryReadUri(YamlMap yamlMap, String key, Logger logger) {
final String value = _tryReadString(yamlMap, key, logger);
Uri? _tryReadUri(YamlMap yamlMap, String key, Logger logger) {
final String? value = _tryReadString(yamlMap, key, logger);
if (value == null) {
return null;
}
final Uri uri = Uri.tryParse(value);
final Uri? uri = Uri.tryParse(value);
if (uri == null) {
logger.printError('"$value" must be a relative file URI');
}
......
......@@ -19,7 +19,7 @@ import '../../../src/context.dart';
void main() {
// Verifies that values are correctly passed through the localizations
// target, but does not validate them beyond the serialized data type.
testUsingContext('generateLocalizations forwards arguments correctly', () async {
testWithoutContext('generateLocalizations forwards arguments correctly', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Logger logger = BufferLogger.test();
final Directory flutterProjectDirectory = fileSystem
......@@ -76,7 +76,7 @@ void main() {
verify(mockLocalizationsGenerator.writeOutputFiles(logger, isFromYaml: true)).called(1);
});
testUsingContext('generateLocalizations throws exception on missing flutter: generate: true flag', () async {
testWithoutContext('generateLocalizations throws exception on missing flutter: generate: true flag', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final BufferLogger logger = BufferLogger.test();
final Directory arbDirectory = fileSystem.directory('arb')
......
......@@ -12,15 +12,13 @@ import 'package:yaml/yaml.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/localizations/gen_l10n.dart';
import 'package:flutter_tools/src/localizations/gen_l10n_types.dart';
import 'package:flutter_tools/src/localizations/localizations_utils.dart';
import 'package:test/test.dart';
final String defaultL10nPathString = globals.fs.path.join('lib', 'l10n');
final String syntheticPackagePath = globals.fs.path.join('.dart_tool', 'flutter_gen');
final String syntheticL10nPackagePath = globals.fs.path.join(syntheticPackagePath, 'gen_l10n');
import '../src/common.dart';
import '../src/context.dart';
const String defaultTemplateArbFileName = 'app_en.arb';
const String defaultOutputFileString = 'output-localization-file.dart';
const String defaultClassNameString = 'AppLocalizations';
......@@ -71,16 +69,23 @@ void _standardFlutterDirectoryL10nSetup(FileSystem fs) {
void main() {
MemoryFileSystem fs;
String defaultL10nPathString;
String syntheticPackagePath;
String syntheticL10nPackagePath;
setUp(() {
fs = MemoryFileSystem(
style: Platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix
);
defaultL10nPathString = fs.path.join('lib', 'l10n');
syntheticPackagePath = fs.path.join('.dart_tool', 'flutter_gen');
syntheticL10nPackagePath = fs.path.join(syntheticPackagePath, 'gen_l10n');
precacheLanguageAndRegionTags();
});
group('Setters', () {
test('setInputDirectory fails if the directory does not exist', () {
testWithoutContext('setInputDirectory fails if the directory does not exist', () {
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
try {
generator.setInputDirectory('lib');
......@@ -95,7 +100,7 @@ void main() {
);
});
test('setInputDirectory fails if input string is null', () {
testWithoutContext('setInputDirectory fails if input string is null', () {
_standardFlutterDirectoryL10nSetup(fs);
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
try {
......@@ -111,7 +116,7 @@ void main() {
);
});
test(
testWithoutContext(
'setOutputDirectory fails if output string is null while not using the '
'synthetic package option',
() {
......@@ -132,7 +137,7 @@ void main() {
},
);
test('setTemplateArbFile fails if inputDirectory is null', () {
testWithoutContext('setTemplateArbFile fails if inputDirectory is null', () {
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
try {
generator.setTemplateArbFile(defaultTemplateArbFileName);
......@@ -147,7 +152,7 @@ void main() {
);
});
test('setTemplateArbFile fails if templateArbFileName is null', () {
testWithoutContext('setTemplateArbFile fails if templateArbFileName is null', () {
_standardFlutterDirectoryL10nSetup(fs);
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
try {
......@@ -163,7 +168,7 @@ void main() {
);
});
test('setTemplateArbFile fails if input string is null', () {
testWithoutContext('setTemplateArbFile fails if input string is null', () {
_standardFlutterDirectoryL10nSetup(fs);
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
try {
......@@ -179,7 +184,7 @@ void main() {
);
});
test('setBaseOutputFile fails if input string is null', () {
testWithoutContext('setBaseOutputFile fails if input string is null', () {
_standardFlutterDirectoryL10nSetup(fs);
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
try {
......@@ -195,7 +200,7 @@ void main() {
);
});
test('setting className fails if input string is null', () {
testWithoutContext('setting className fails if input string is null', () {
_standardFlutterDirectoryL10nSetup(fs);
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
try {
......@@ -211,7 +216,7 @@ void main() {
);
});
test('sets absolute path of the target Flutter project', () {
testUsingContext('sets absolute path of the target Flutter project', () {
// Set up project directory.
final Directory l10nDirectory = fs.currentDirectory
.childDirectory('absolute')
......@@ -269,7 +274,7 @@ void main() {
);
});
test('throws error when directory at absolute path does not exist', () {
testWithoutContext('throws error when directory at absolute path does not exist', () {
// Set up project directory.
final Directory l10nDirectory = fs.currentDirectory
.childDirectory('lib')
......@@ -317,7 +322,7 @@ void main() {
}
});
test('fails on string with spaces', () {
testWithoutContext('fails on string with spaces', () {
try {
generator.className = 'String with spaces';
} on L10nException catch (e) {
......@@ -330,7 +335,7 @@ void main() {
);
});
test('fails on non-alphanumeric symbols', () {
testWithoutContext('fails on non-alphanumeric symbols', () {
try {
generator.className = 'TestClass@123';
} on L10nException catch (e) {
......@@ -343,7 +348,7 @@ void main() {
);
});
test('fails on camel-case', () {
testWithoutContext('fails on camel-case', () {
try {
generator.className = 'camelCaseClassName';
} on L10nException catch (e) {
......@@ -356,7 +361,7 @@ void main() {
);
});
test('fails when starting with a number', () {
testWithoutContext('fails when starting with a number', () {
try {
generator.className = '123ClassName';
} on L10nException catch (e) {
......@@ -371,7 +376,7 @@ void main() {
});
});
test('correctly adds a headerString when it is set', () {
testUsingContext('correctly adds a headerString when it is set', () {
_standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator;
......@@ -392,7 +397,7 @@ void main() {
expect(generator.header, '/// Sample header');
});
test('correctly adds a headerFile when it is set', () {
testUsingContext('correctly adds a headerFile when it is set', () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
......@@ -417,7 +422,7 @@ void main() {
expect(generator.header, '/// Sample header in a text file');
});
test('sets templateArbFileName with more than one underscore correctly', () {
testUsingContext('sets templateArbFileName with more than one underscore correctly', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile('app_localizations_en.arb')
......@@ -446,7 +451,7 @@ void main() {
expect(outputDirectory.childFile('output-localization-file_es.dart').existsSync(), isTrue);
});
test('filenames with invalid locales should not be recognized', () {
testUsingContext('filenames with invalid locales should not be recognized', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile('app_localizations_en.arb')
......@@ -472,7 +477,7 @@ void main() {
fail('Using app_en_CA_foo.arb should fail as it is not a valid locale.');
});
test('correctly creates an untranslated messages file (useSyntheticPackage = true)', () {
testUsingContext('correctly creates an untranslated messages file (useSyntheticPackage = true)', () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString)
......@@ -510,7 +515,7 @@ void main() {
expect(unimplementedOutputString, contains('subtitle'));
});
test('correctly creates an untranslated messages file (useSyntheticPackage = false)', () {
testUsingContext('correctly creates an untranslated messages file (useSyntheticPackage = false)', () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString)
......@@ -549,7 +554,7 @@ void main() {
expect(unimplementedOutputString, contains('subtitle'));
});
test(
testUsingContext(
'untranslated messages suggestion is printed when translation is missing: '
'command line message',
() {
......@@ -588,7 +593,7 @@ void main() {
},
);
test(
testUsingContext(
'untranslated messages suggestion is printed when translation is missing: '
'l10n.yaml message',
() {
......@@ -625,7 +630,7 @@ void main() {
},
);
test(
testUsingContext(
'unimplemented messages suggestion is not printed when all messages '
'are fully translated',
() {
......@@ -656,7 +661,7 @@ void main() {
},
);
test('untranslated messages file included in generated JSON list of outputs', () {
testUsingContext('untranslated messages file included in generated JSON list of outputs', () {
_standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator;
......@@ -689,7 +694,7 @@ void main() {
expect(outputList, contains(contains('unimplemented_message_translations.json')));
});
test(
testUsingContext(
'uses inputPathString as outputPathString when the outputPathString is '
'null while not using the synthetic package option',
() {
......@@ -719,7 +724,7 @@ void main() {
},
);
test(
testUsingContext(
'correctly generates output files in non-default output directory if it '
'already exists while not using the synthetic package option',
() {
......@@ -763,7 +768,7 @@ void main() {
},
);
test(
testUsingContext(
'correctly creates output directory if it does not exist and writes files '
'in it while not using the synthetic package option',
() {
......@@ -795,7 +800,7 @@ void main() {
},
);
test('creates list of inputs and outputs when file path is specified', () {
testUsingContext('creates list of inputs and outputs when file path is specified', () {
_standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator;
......@@ -833,7 +838,7 @@ void main() {
expect(outputList, contains(fs.path.absolute(syntheticL10nPackagePath, 'output-localization-file_es.dart')));
});
test('setting both a headerString and a headerFile should fail', () {
testUsingContext('setting both a headerString and a headerFile should fail', () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
......@@ -860,7 +865,7 @@ void main() {
fail('Setting both headerFile and headerString should fail');
});
test('setting a headerFile that does not exist should fail', () {
testUsingContext('setting a headerFile that does not exist should fail', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
......@@ -889,7 +894,7 @@ void main() {
fail('Setting headerFile that does not exist should fail');
});
test('setting useDefferedLoading to null should fail', () {
testUsingContext('setting useDefferedLoading to null should fail', () {
_standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator;
......@@ -913,7 +918,7 @@ void main() {
});
group('loadResources', () {
test('correctly initializes supportedLocales and supportedLanguageCodes properties', () {
testUsingContext('correctly initializes supportedLocales and supportedLanguageCodes properties', () {
_standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator;
......@@ -935,7 +940,7 @@ void main() {
expect(generator.supportedLocales.contains(LocaleInfo.fromString('es')), true);
});
test('correctly sorts supportedLocales and supportedLanguageCodes alphabetically', () {
testUsingContext('correctly sorts supportedLocales and supportedLanguageCodes alphabetically', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
// Write files in non-alphabetical order so that read performs in that order
......@@ -966,7 +971,7 @@ void main() {
expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('zh'));
});
test('adds preferred locales to the top of supportedLocales and supportedLanguageCodes', () {
testUsingContext('adds preferred locales to the top of supportedLocales and supportedLanguageCodes', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile('app_en.arb')
......@@ -998,7 +1003,7 @@ void main() {
expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('en'));
});
test(
testUsingContext(
'throws an error attempting to add preferred locales '
'when there is no corresponding arb file for that '
'locale',
......@@ -1040,7 +1045,7 @@ void main() {
},
);
test('correctly sorts arbPathString alphabetically', () {
testUsingContext('correctly sorts arbPathString alphabetically', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
// Write files in non-alphabetical order so that read performs in that order
......@@ -1071,7 +1076,7 @@ void main() {
expect(generator.arbPathStrings.elementAt(2), fs.path.join('lib', 'l10n', 'app_zh.arb'));
});
test('correctly parses @@locale property in arb file', () {
testUsingContext('correctly parses @@locale property in arb file', () {
const String arbFileWithEnLocale = '''
{
"@@locale": "en",
......@@ -1116,7 +1121,7 @@ void main() {
expect(generator.supportedLocales.contains(LocaleInfo.fromString('zh')), true);
});
test('correctly requires @@locale property in arb file to match the filename locale suffix', () {
testUsingContext('correctly requires @@locale property in arb file to match the filename locale suffix', () {
const String arbFileWithEnLocale = '''
{
"@@locale": "en",
......@@ -1164,7 +1169,7 @@ void main() {
);
});
test("throws when arb file's locale could not be determined", () {
testUsingContext("throws when arb file's locale could not be determined", () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true)
..childFile('app.arb')
......@@ -1188,7 +1193,7 @@ void main() {
'should fail'
);
});
test('throws when the same locale is detected more than once', () {
testUsingContext('throws when the same locale is detected more than once', () {
const String secondMessageArbFileString = '''
{
"market": "MARKET",
......@@ -1225,7 +1230,7 @@ void main() {
);
});
test('throws when the base locale does not exist', () {
testUsingContext('throws when the base locale does not exist', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile('app_en_US.arb')
......@@ -1254,7 +1259,7 @@ void main() {
});
group('writeOutputFiles', () {
test('message without placeholders - should generate code comment with description and template message translation', () {
testUsingContext('message without placeholders - should generate code comment with description and template message translation', () {
_standardFlutterDirectoryL10nSetup(fs);
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
final BufferLogger testLogger = BufferLogger.test();
......@@ -1286,7 +1291,7 @@ void main() {
/// **'Title'**'''));
});
test('template message translation handles newline characters', () {
testUsingContext('template message translation handles newline characters', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
......@@ -1331,7 +1336,7 @@ void main() {
/// **'Title \n of the application'**'''));
});
test('message with placeholders - should generate code comment with description and template message translation', () {
testUsingContext('message with placeholders - should generate code comment with description and template message translation', () {
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
......@@ -1386,7 +1391,7 @@ void main() {
/// **'The price of this item is: \${price}'**'''));
});
test('should generate a file per language', () {
testUsingContext('should generate a file per language', () {
const String singleEnCaMessageArbFileString = '''
{
"title": "Canadian Title"
......@@ -1420,7 +1425,7 @@ void main() {
expect(englishLocalizationsFile, contains('class AppLocalizationsEn extends AppLocalizations'));
});
test('language imports are sorted when preferredSupportedLocaleString is given', () {
testUsingContext('language imports are sorted when preferredSupportedLocaleString is given', () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
..childFile('app_zh.arb').writeAsStringSync(singleZhMessageArbFileString)
......@@ -1454,7 +1459,7 @@ import 'output-localization-file_zh.dart';
'''));
});
test('imports are deferred and loaded when useDeferredImports are set', () {
testUsingContext('imports are deferred and loaded when useDeferredImports are set', () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString);
......@@ -1484,7 +1489,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
});
group('DateTime tests', () {
test('throws an exception when improperly formatted date is passed in', () {
testUsingContext('throws an exception when improperly formatted date is passed in', () {
const String singleDateMessageArbFileString = '''
{
"@@locale": "en",
......@@ -1524,7 +1529,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
fail('Improper date formatting should throw an exception');
});
test('throws an exception when no format attribute is passed in', () {
testUsingContext('throws an exception when no format attribute is passed in', () {
const String singleDateMessageArbFileString = '''
{
"springBegins": "Spring begins on {springStartDate}",
......@@ -1561,7 +1566,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
fail('Improper date formatting should throw an exception');
});
test('throws an exception when improperly formatted number is passed in', () {
testUsingContext('throws an exception when improperly formatted number is passed in', () {
const String singleDateMessageArbFileString = '''
{
"courseCompletion": "You have completed {progress} of the course.",
......@@ -1603,7 +1608,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
});
group('plural messages', () {
test('should throw attempting to generate a plural message without placeholders', () {
testUsingContext('should throw attempting to generate a plural message without placeholders', () {
const String pluralMessageWithoutPlaceholdersAttribute = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}",
......@@ -1635,7 +1640,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
fail('Generating class methods without placeholders should not succeed');
});
test('should throw attempting to generate a plural message with an empty placeholders map', () {
testUsingContext('should throw attempting to generate a plural message with an empty placeholders map', () {
const String pluralMessageWithEmptyPlaceholdersMap = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}",
......@@ -1668,7 +1673,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
fail('Generating class methods without placeholders should not succeed');
});
test('should throw attempting to generate a plural message with no resource attributes', () {
testUsingContext('should throw attempting to generate a plural message with no resource attributes', () {
const String pluralMessageWithoutResourceAttributes = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}"
......@@ -1697,7 +1702,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
fail('Generating plural class method without resource attributes should not succeed');
});
test('should throw attempting to generate a plural message with incorrect format for placeholders', () {
testUsingContext('should throw attempting to generate a plural message with incorrect format for placeholders', () {
const String pluralMessageWithIncorrectPlaceholderFormat = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}",
......@@ -1731,7 +1736,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
});
});
test('intl package import should be omitted in subclass files when no plurals are included', () {
testUsingContext('intl package import should be omitted in subclass files when no plurals are included', () {
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString);
......@@ -1757,7 +1762,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
expect(localizationsFile, isNot(contains(intlImportDartCode)));
});
test('intl package import should be kept in subclass files when plurals are included', () {
testUsingContext('intl package import should be kept in subclass files when plurals are included', () {
const String pluralMessageArb = '''
{
"helloWorlds": "{count,plural, =0{Hello} =1{Hello World} =2{Hello two worlds} few{Hello {count} worlds} many{Hello all {count} worlds} other{Hello other {count} worlds}}",
......@@ -1801,7 +1806,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
expect(localizationsFile, contains(intlImportDartCode));
});
test('check for string interpolation rules', () {
testUsingContext('check for string interpolation rules', () {
const String enArbCheckList = '''
{
"one": "The number of {one} elapsed is: 44",
......@@ -1941,7 +1946,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
expect(localizationsFile, contains(r'${nine}'));
});
test('check for string interpolation rules - plurals', () {
testUsingContext('check for string interpolation rules - plurals', () {
const String enArbCheckList = '''
{
"first": "{count,plural, =0{test {count} test} =1{哈{count}哈} =2{m{count}m} few{_{count}_} many{{count} test} other{{count}m}",
......@@ -2006,7 +2011,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
expect(localizationsFile, contains(r' $count'));
});
test(
testUsingContext(
'should throw with descriptive error message when failing to parse the '
'arb file',
() {
......@@ -2047,7 +2052,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
},
);
test('should throw when resource is missing resource attribute (isResourceAttributeRequired = true)', () {
testUsingContext('should throw when resource is missing resource attribute (isResourceAttributeRequired = true)', () {
const String arbFileWithMissingResourceAttribute = '''
{
"title": "Stocks"
......@@ -2081,7 +2086,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
});
group('checks for method/getter formatting', () {
test('cannot contain non-alphanumeric symbols', () {
testUsingContext('cannot contain non-alphanumeric symbols', () {
const String nonAlphaNumericArbFile = '''
{
"title!!": "Stocks",
......@@ -2113,7 +2118,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
fail('should fail due to non-alphanumeric character.');
});
test('must start with lowercase character', () {
testUsingContext('must start with lowercase character', () {
const String nonAlphaNumericArbFile = '''
{
"Title": "Stocks",
......@@ -2145,7 +2150,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
fail('should fail since key starts with a non-lowercase.');
});
test('cannot start with a number', () {
testUsingContext('cannot start with a number', () {
const String nonAlphaNumericArbFile = '''
{
"123title": "Stocks",
......@@ -2178,7 +2183,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
});
});
test('should generate a valid pubspec.yaml file when using synthetic package if it does not already exist', () {
testUsingContext('should generate a valid pubspec.yaml file when using synthetic package if it does not already exist', () {
_standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator;
try {
......@@ -2210,7 +2215,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
expect(pubspecDescription, "The Flutter application's synthetic package.");
});
test('should not overwrite existing pubspec.yaml file when using synthetic package', () {
testUsingContext('should not overwrite existing pubspec.yaml file when using synthetic package', () {
_standardFlutterDirectoryL10nSetup(fs);
final File pubspecFile = fs.file(fs.path.join(syntheticPackagePath, 'pubspec.yaml'))
..createSync(recursive: true)
......
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