diff --git a/analysis_options.yaml b/analysis_options.yaml index a1beef0bf1a..519b1d8cb8b 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -228,6 +228,7 @@ linter: - use_rethrow_when_possible # - use_setters_to_change_properties # not yet tested # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 + - use_test_throws_matchers # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review - valid_regexps - void_checks diff --git a/packages/flutter/test/animation/tween_test.dart b/packages/flutter/test/animation/tween_test.dart index 57e1cf3503d..a717c1b61e3 100644 --- a/packages/flutter/test/animation/tween_test.dart +++ b/packages/flutter/test/animation/tween_test.dart @@ -14,22 +14,18 @@ void main() { end: Object(), ); - FlutterError? error; - try { - objectTween.transform(0.1); - } on FlutterError catch (err) { - error = err; - } - - if (error == null) { - fail('Expected Tween.transform to throw a FlutterError'); - } - - expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), [ - 'Cannot lerp between "Instance of \'Object\'" and "Instance of \'Object\'".', - 'The type Object might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink', - 'There may be a dedicated "ObjectTween" for this type, or you may need to create one.', - ]); + expect( + () => objectTween.transform(0.1), + throwsA(isA().having( + (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()), + 'diagnostics', + [ + 'Cannot lerp between "Instance of \'Object\'" and "Instance of \'Object\'".', + 'The type Object might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink', + 'There may be a dedicated "ObjectTween" for this type, or you may need to create one.', + ], + )), + ); }); test('throws flutter error when tweening types that do not fully satisfy tween requirements - Color', () { @@ -38,22 +34,18 @@ void main() { end: const Color(0xFFFFFFFF), ); - FlutterError? error; - try { - colorTween.transform(0.1); - } on FlutterError catch (err) { - error = err; - } - - if (error == null) { - fail('Expected Tween.transform to throw a FlutterError'); - } - - expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), [ - 'Cannot lerp between "Color(0xff000000)" and "Color(0xffffffff)".', - 'The type Color might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink', - 'To lerp colors, consider ColorTween instead.', - ]); + expect( + () => colorTween.transform(0.1), + throwsA(isA().having( + (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()), + 'diagnostics', + [ + 'Cannot lerp between "Color(0xff000000)" and "Color(0xffffffff)".', + 'The type Color might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink', + 'To lerp colors, consider ColorTween instead.', + ], + )), + ); }); test('throws flutter error when tweening types that do not fully satisfy tween requirements - Rect', () { @@ -62,22 +54,18 @@ void main() { end: const Rect.fromLTWH(2, 2, 2, 2), ); - FlutterError? error; - try { - rectTween.transform(0.1); - } on FlutterError catch (err) { - error = err; - } - - if (error == null) { - fail('Expected Tween.transform to throw a FlutterError'); - } - - expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), [ - 'Cannot lerp between "Rect.fromLTRB(0.0, 0.0, 10.0, 10.0)" and "Rect.fromLTRB(2.0, 2.0, 4.0, 4.0)".', - 'The type Rect might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink', - 'To lerp rects, consider RectTween instead.', - ]); + expect( + () => rectTween.transform(0.1), + throwsA(isA().having( + (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()), + 'diagnostics', + [ + 'Cannot lerp between "Rect.fromLTRB(0.0, 0.0, 10.0, 10.0)" and "Rect.fromLTRB(2.0, 2.0, 4.0, 4.0)".', + 'The type Rect might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink', + 'To lerp rects, consider RectTween instead.', + ], + )), + ); }); test('throws flutter error when tweening types that do not fully satisfy tween requirements - int', () { @@ -86,22 +74,18 @@ void main() { end: 1, ); - FlutterError? error; - try { - colorTween.transform(0.1); - } on FlutterError catch (err) { - error = err; - } - - if (error == null) { - fail('Expected Tween.transform to throw a FlutterError'); - } - - expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), [ - 'Cannot lerp between "0" and "1".', - 'The type int returned a double after multiplication with a double value. $kApiDocsLink', - 'To lerp int values, consider IntTween or StepTween instead.', - ]); + expect( + () => colorTween.transform(0.1), + throwsA(isA().having( + (FlutterError error) => error.diagnostics.map((DiagnosticsNode node) => node.toString()), + 'diagnostics', + [ + 'Cannot lerp between "0" and "1".', + 'The type int returned a double after multiplication with a double value. $kApiDocsLink', + 'To lerp int values, consider IntTween or StepTween instead.', + ], + )), + ); }); test('Can chain tweens', () { diff --git a/packages/flutter/test/material/expansion_tile_test.dart b/packages/flutter/test/material/expansion_tile_test.dart index e829a4cc32c..db0b8162f0c 100644 --- a/packages/flutter/test/material/expansion_tile_test.dart +++ b/packages/flutter/test/material/expansion_tile_test.dart @@ -371,24 +371,23 @@ void main() { }); testWidgets('CrossAxisAlignment.baseline is not allowed', (WidgetTester tester) async { - try { - MaterialApp( - home: Material( - child: ExpansionTile( - initiallyExpanded: true, - title: const Text('title'), - expandedCrossAxisAlignment: CrossAxisAlignment.baseline, + expect( + () { + MaterialApp( + home: Material( + child: ExpansionTile( + initiallyExpanded: true, + title: const Text('title'), + expandedCrossAxisAlignment: CrossAxisAlignment.baseline, + ), ), - ), - ); - } on AssertionError catch (error) { - expect(error.toString(), contains( + ); + }, + throwsA(isA().having((AssertionError error) => error.toString(), '.toString()', contains( 'CrossAxisAlignment.baseline is not supported since the expanded' ' children are aligned in a column, not a row. Try to use another constant.', - )); - return; - } - fail('AssertionError was not thrown when expandedCrossAxisAlignment is CrossAxisAlignment.baseline.'); + ))), + ); }); testWidgets('expandedCrossAxisAlignment and expandedAlignment default values', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/reorderable_list_test.dart b/packages/flutter/test/material/reorderable_list_test.dart index 45b9ce10246..9dd4ea16e15 100644 --- a/packages/flutter/test/material/reorderable_list_test.dart +++ b/packages/flutter/test/material/reorderable_list_test.dart @@ -485,11 +485,10 @@ void main() { ), ), ); - try { - await tester.pumpWidget(boilerplate); - } catch (e) { - fail('Expected no error, but got $e'); - } + await expectLater( + () => tester.pumpWidget(boilerplate), + returnsNormally, + ); }); group('Accessibility (a11y/Semantics)', () { diff --git a/packages/flutter/test/services/platform_channel_test.dart b/packages/flutter/test/services/platform_channel_test.dart index c70e6d8d32a..a97fa9bb1ff 100644 --- a/packages/flutter/test/services/platform_channel_test.dart +++ b/packages/flutter/test/services/platform_channel_test.dart @@ -128,16 +128,15 @@ void main() { ]); }, ); - try { - await channel.invokeMethod('sayHello', 'hello'); - fail('Exception expected'); - } on PlatformException catch (e) { - expect(e.code, equals('bad')); - expect(e.message, equals('Something happened')); - expect(e.details, equals({'a': 42, 'b': 3.14})); - } catch (e) { - fail('PlatformException expected'); - } + expect( + () => channel.invokeMethod('sayHello', 'hello'), + throwsA( + isA() + .having((PlatformException e) => e.code, 'code', equals('bad')) + .having((PlatformException e) => e.message, 'message', equals('Something happened')) + .having((PlatformException e) => e.details, 'details', equals({'a': 42, 'b': 3.14})), + ), + ); }); test('can invoke unimplemented method', () async { @@ -145,15 +144,16 @@ void main() { 'ch7', (ByteData? message) async => null, ); - try { - await channel.invokeMethod('sayHello', 'hello'); - fail('Exception expected'); - } on MissingPluginException catch (e) { - expect(e.message, contains('sayHello')); - expect(e.message, contains('ch7')); - } catch (e) { - fail('MissingPluginException expected'); - } + expect( + () => channel.invokeMethod('sayHello', 'hello'), + throwsA( + isA() + .having((MissingPluginException e) => e.message, 'message', allOf( + contains('sayHello'), + contains('ch7'), + )), + ), + ); }); test('can invoke unimplemented method (optional)', () async { @@ -218,15 +218,14 @@ void main() { await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); - try { - jsonMethod.decodeEnvelope(envelope!); - fail('Exception expected'); - } on PlatformException catch (e) { - expect(e.code, equals('bad')); - expect(e.message, equals('sayHello failed')); - } catch (e) { - fail('PlatformException expected'); - } + expect( + () => jsonMethod.decodeEnvelope(envelope!), + throwsA( + isA() + .having((PlatformException e) => e.code, 'code', equals('bad')) + .having((PlatformException e) => e.message, 'message', equals('sayHello failed')), + ), + ); }); test('can handle method call with other error result', () async { @@ -238,15 +237,14 @@ void main() { await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage('ch7', call, (ByteData? result) { envelope = result; }); - try { - jsonMethod.decodeEnvelope(envelope!); - fail('Exception expected'); - } on PlatformException catch (e) { - expect(e.code, equals('error')); - expect(e.message, equals('Invalid argument(s): bad')); - } catch (e) { - fail('PlatformException expected'); - } + expect( + () => jsonMethod.decodeEnvelope(envelope!), + throwsA( + isA() + .having((PlatformException e) => e.code, 'code', equals('error')) + .having((PlatformException e) => e.message, 'message', equals('Invalid argument(s): bad')), + ), + ); }); test('can check the mock handler', () async { diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart index 3bbc185b06f..9358d908952 100644 --- a/packages/flutter/test/services/raw_keyboard_test.dart +++ b/packages/flutter/test/services/raw_keyboard_test.dart @@ -686,16 +686,20 @@ void main() { }; } - try { - await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( - SystemChannels.keyEvent.name, - SystemChannels.keyEvent.codec.encodeMessage(keyEventMessage), - (ByteData? data) { }, - ); - fail('Expected an exception, but did not get one.'); - } on AssertionError catch (error) { - expect(error.toString(), contains('Attempted to send a key down event when no keys are in keysPressed')); - } + expect( + () async { + await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage( + SystemChannels.keyEvent.name, + SystemChannels.keyEvent.codec.encodeMessage(keyEventMessage), + (ByteData? data) { }, + ); + }, + throwsA(isA().having( + (AssertionError error) => error.toString(), + '.toString()', + contains('Attempted to send a key down event when no keys are in keysPressed'), + )), + ); }); }); diff --git a/packages/flutter/test/widgets/selectable_text_test.dart b/packages/flutter/test/widgets/selectable_text_test.dart index 82e9f135b44..1315f18b6d6 100644 --- a/packages/flutter/test/widgets/selectable_text_test.dart +++ b/packages/flutter/test/widgets/selectable_text_test.dart @@ -1303,24 +1303,27 @@ void main() { }); testWidgets('minLines cannot be greater than maxLines', (WidgetTester tester) async { - try { - await tester.pumpWidget( - overlay( - child: SizedBox( - width: 300.0, - child: SelectableText( - 'abcd', - minLines: 4, - maxLines: 3, + expect( + () async { + await tester.pumpWidget( + overlay( + child: SizedBox( + width: 300.0, + child: SelectableText( + 'abcd', + minLines: 4, + maxLines: 3, + ), ), ), - ), - ); - } on AssertionError catch (e) { - expect(e.toString(), contains("minLines can't be greater than maxLines")); - return; - } - fail('An assert should be triggered when minLines is greater than maxLines'); + ); + }, + throwsA(isA().having( + (AssertionError error) => error.toString(), + '.toString()', + contains("minLines can't be greater than maxLines"), + )), + ); }); testWidgets('Selectable height with minLine', (WidgetTester tester) async { diff --git a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart index c34e5a51f83..f5d32f752a9 100644 --- a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart +++ b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart @@ -81,31 +81,25 @@ void main() { group('Setters', () { testWithoutContext('setInputDirectory fails if the directory does not exist', () { - try { - LocalizationsGenerator.inputDirectoryFromPath(fs, 'lib', fs.directory('bogus')); - } on L10nException catch (e) { - expect(e.message, contains('Make sure that the correct path was provided')); - return; - } - - fail( - 'LocalizationsGenerator.setInputDirectory should fail if the ' - 'directory does not exist.' + expect( + () => LocalizationsGenerator.inputDirectoryFromPath(fs, 'lib', fs.directory('bogus')), + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Make sure that the correct path was provided'), + )), ); }); testWithoutContext('setting className fails if input string is empty', () { _standardFlutterDirectoryL10nSetup(fs); - try { - LocalizationsGenerator.classNameFromString(''); - } on L10nException catch (e) { - expect(e.message, contains('cannot be empty')); - return; - } - - fail( - 'LocalizationsGenerator.className should fail if the ' - 'input string is null.' + expect( + () => LocalizationsGenerator.classNameFromString(''), + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('cannot be empty'), + )), ); }); @@ -179,8 +173,8 @@ void main() { .writeAsStringSync(singleEsMessageArbFileString); // Project path should be intentionally a directory that does not exist. - try { - LocalizationsGenerator( + expect( + () => LocalizationsGenerator( fileSystem: fs, projectPathString: 'absolute/path/to/flutter_project', inputPathString: defaultL10nPathString, @@ -188,15 +182,12 @@ void main() { templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString, classNameString: defaultClassNameString, - ); - } on L10nException catch (e) { - expect(e.message, contains('Directory does not exist')); - return; - } - - fail( - 'An exception should be thrown when the directory ' - 'specified in projectPathString does not exist.' + ), + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Directory does not exist'), + )), ); }); @@ -206,54 +197,46 @@ void main() { }); testWithoutContext('fails on string with spaces', () { - try { - LocalizationsGenerator.classNameFromString('String with spaces'); - } on L10nException catch (e) { - expect(e.message, contains('is not a valid public Dart class name')); - return; - } - fail( - 'LocalizationsGenerator.className should fail if the ' - 'input string is not a valid Dart class name.' + expect( + () => LocalizationsGenerator.classNameFromString('String with spaces'), + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('is not a valid public Dart class name'), + )), ); }); testWithoutContext('fails on non-alphanumeric symbols', () { - try { - LocalizationsGenerator.classNameFromString('TestClass@123'); - } on L10nException catch (e) { - expect(e.message, contains('is not a valid public Dart class name')); - return; - } - fail( - 'LocalizationsGenerator.className should fail if the ' - 'input string is not a valid public Dart class name.' + expect( + () => LocalizationsGenerator.classNameFromString('TestClass@123'), + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('is not a valid public Dart class name'), + )), ); }); testWithoutContext('fails on camel-case', () { - try { - LocalizationsGenerator.classNameFromString('camelCaseClassName'); - } on L10nException catch (e) { - expect(e.message, contains('is not a valid public Dart class name')); - return; - } - fail( - 'LocalizationsGenerator.className should fail if the ' - 'input string is not a valid public Dart class name.' + expect( + () => LocalizationsGenerator.classNameFromString('camelCaseClassName'), + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('is not a valid public Dart class name'), + )), ); }); testWithoutContext('fails when starting with a number', () { - try { - LocalizationsGenerator.classNameFromString('123ClassName'); - } on L10nException catch (e) { - expect(e.message, contains('is not a valid public Dart class name')); - return; - } - fail( - 'LocalizationsGenerator.className should fail if the ' - 'input string is not a valid public Dart class name.' + expect( + () => LocalizationsGenerator.classNameFromString('123ClassName'), + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('is not a valid public Dart class name'), + )), ); }); }); @@ -339,20 +322,22 @@ void main() { .writeAsStringSync(singleMessageArbFileString); l10nDirectory.childFile('app_localizations_en_CA_foo.arb') .writeAsStringSync(singleMessageArbFileString); - try { - LocalizationsGenerator( - fileSystem: fs, + expect( + () { + LocalizationsGenerator( + fileSystem: fs, inputPathString: defaultL10nPathString, templateArbFileName: 'app_localizations_en.arb', outputFileString: defaultOutputFileString, classNameString: defaultClassNameString, ).loadResources(); - } on L10nException catch (e) { - expect(e.message, contains("The following .arb file's locale could not be determined")); - return; - } - - fail('Using app_en_CA_foo.arb should fail as it is not a valid locale.'); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains("The following .arb file's locale could not be determined"), + )), + ); }); testWithoutContext('correctly creates an untranslated messages file (useSyntheticPackage = true)', () { @@ -775,23 +760,25 @@ void main() { ..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString) ..childFile('header.txt').writeAsStringSync('/// Sample header in a text file'); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - headerString: '/// Sample header for localizations file.', - headerFile: 'header.txt', - ); - } on L10nException catch (e) { - expect(e.message, contains('Cannot accept both header and header file arguments')); - return; - } - - fail('Setting both headerFile and headerString should fail'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + headerString: '/// Sample header for localizations file.', + headerFile: 'header.txt', + ); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Cannot accept both header and header file arguments'), + )), + ); }); testWithoutContext('setting a headerFile that does not exist should fail', () { @@ -804,22 +791,24 @@ void main() { l10nDirectory.childFile('header.txt') .writeAsStringSync('/// Sample header in a text file'); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - headerFile: 'header.tx', // Intentionally spelled incorrectly - ); - } on L10nException catch (e) { - expect(e.message, contains('Failed to read header file')); - return; - } - - fail('Setting headerFile that does not exist should fail'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + headerFile: 'header.tx', // Intentionally spelled incorrectly + ); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Failed to read header file'), + )), + ); }); group('generateLocalizations', () { @@ -1022,27 +1011,23 @@ flutter: .writeAsStringSync(singleZhMessageArbFileString); const List preferredSupportedLocale = ['am', 'es']; - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - preferredSupportedLocales: preferredSupportedLocale, - ).loadResources(); - } on L10nException catch (e) { - expect( - e.message, + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + preferredSupportedLocales: preferredSupportedLocale, + ).loadResources(); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', contains("The preferred supported locale, 'am', cannot be added."), - ); - return; - } - - fail( - 'Should fail since an unsupported locale was added ' - 'to the preferredSupportedLocales list.' + )), ); }, ); @@ -1149,25 +1134,22 @@ flutter: l10nDirectory.childFile('app_am.arb') .writeAsStringSync(arbFileWithZhLocale); - LocalizationsGenerator generator; - try { - generator = LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: 'app_es.arb', - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ); - generator.loadResources(); - } on L10nException catch (e) { - expect(e.message, contains('The locale specified in @@locale and the arb filename do not match.')); - return; - } - - fail( - 'An exception should occur if the @@locale and the filename extensions are ' - 'defined but not matching.' + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: 'app_es.arb', + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ).loadResources(); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('The locale specified in @@locale and the arb filename do not match.'), + )), ); }); @@ -1176,23 +1158,22 @@ flutter: ..createSync(recursive: true) ..childFile('app.arb') .writeAsStringSync(singleMessageArbFileString); - try { - final LocalizationsGenerator generator = LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: 'app.arb', - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ); - generator.loadResources(); - } on L10nException catch (e) { - expect(e.message, contains('locale could not be determined')); - return; - } - fail( - 'Since locale is not specified, setting languages and locales ' - 'should fail' + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: 'app.arb', + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ).loadResources(); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('locale could not be determined'), + )), ); }); testWithoutContext('throws when the same locale is detected more than once', () { @@ -1211,23 +1192,22 @@ flutter: l10nDirectory.childFile('app2_en.arb') .writeAsStringSync(secondMessageArbFileString); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: 'app_en.arb', - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ).loadResources(); - } on L10nException catch (e) { - expect(e.message, contains("Multiple arb files with the same 'en' locale detected")); - return; - } - - fail( - 'Since en locale is specified twice, setting languages and locales ' - 'should fail' + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: 'app_en.arb', + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ).loadResources(); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains("Multiple arb files with the same 'en' locale detected"), + )), ); }); @@ -1237,23 +1217,22 @@ flutter: l10nDirectory.childFile('app_en_US.arb') .writeAsStringSync(singleMessageArbFileString); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: 'app_en_US.arb', - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ).loadResources(); - } on L10nException catch (e) { - expect(e.message, contains('Arb file for a fallback, en, does not exist')); - return; - } - - fail( - 'Since en_US.arb is specified, but en.arb is not, ' - 'the tool should throw an error.' + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: 'app_en_US.arb', + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ).loadResources(); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Arb file for a fallback, en, does not exist'), + )), ); }); }); @@ -1544,24 +1523,28 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(singleDateMessageArbFileString); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('asdf')); - expect(e.message, contains('springStartDate')); - expect(e.message, contains('does not have a corresponding DateFormat')); - return; - } - - fail('Improper date formatting should throw an exception'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + allOf( + contains('asdf'), + contains('springStartDate'), + contains('does not have a corresponding DateFormat'), + ), + )), + ); }); testWithoutContext('throws an exception when no format attribute is passed in', () { @@ -1582,23 +1565,25 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(singleDateMessageArbFileString); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('the "format" attribute needs to be set')); - return; - } - - fail('Improper date formatting should throw an exception'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('the "format" attribute needs to be set'), + )), + ); }); }); @@ -1658,25 +1643,29 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(singleDateMessageArbFileString); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('asdf')); - expect(e.message, contains('progress')); - expect(e.message, contains('does not have a corresponding NumberFormat')); - return; - } - - fail('Improper date formatting should throw an exception'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + allOf( + contains('asdf'), + contains('progress'), + contains('does not have a corresponding NumberFormat'), + ), + )), + ); }); }); @@ -1695,22 +1684,25 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(pluralMessageWithoutPlaceholdersAttribute); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('Check to see if the plural message is in the proper ICU syntax format')); - return; - } - fail('Generating class methods without placeholders should not succeed'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Check to see if the plural message is in the proper ICU syntax format'), + )), + ); }); testWithoutContext('should throw attempting to generate a plural message with an empty placeholders map', () { @@ -1728,22 +1720,25 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(pluralMessageWithEmptyPlaceholdersMap); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('Check to see if the plural message is in the proper ICU syntax format')); - return; - } - fail('Generating class methods without placeholders should not succeed'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Check to see if the plural message is in the proper ICU syntax format'), + )), + ); }); testWithoutContext('should throw attempting to generate a plural message with no resource attributes', () { @@ -1757,22 +1752,25 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(pluralMessageWithoutResourceAttributes); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('Resource attribute "@helloWorlds" was not found')); - return; - } - fail('Generating plural class method without resource attributes should not succeed'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Resource attribute "@helloWorlds" was not found'), + )), + ); }); testWithoutContext('should throw attempting to generate a plural message with incorrect format for placeholders', () { @@ -1789,23 +1787,28 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(pluralMessageWithIncorrectPlaceholderFormat); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('is not properly formatted')); - expect(e.message, contains('Ensure that it is a map with string valued keys')); - return; - } - fail('Generating class methods with incorrect placeholder format should not succeed'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + allOf( + contains('is not properly formatted'), + contains('Ensure that it is a map with string valued keys'), + ), + )), + ); }); }); @@ -2190,27 +2193,28 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(arbFileWithTrailingComma); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('app_en.arb')); - expect(e.message, contains('FormatException')); - expect(e.message, contains('Unexpected character')); - return; - } - - fail( - 'should fail with an L10nException due to a trailing comma in the ' - 'arb file.' + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + allOf( + contains('app_en.arb'), + contains('FormatException'), + contains('Unexpected character'), + ), + )), ); }, ); @@ -2225,26 +2229,25 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(arbFileWithMissingResourceAttribute); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - areResourceAttributesRequired: true, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('Resource attribute "@title" was not found')); - return; - } - - fail( - 'should fail with a FormatException due to a trailing comma in the ' - 'arb file.' + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + areResourceAttributesRequired: true, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Resource attribute "@title" was not found'), + )), ); }); @@ -2262,23 +2265,25 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(nonAlphaNumericArbFile); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('Invalid ARB resource name')); - return; - } - - fail('should fail due to non-alphanumeric character.'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Invalid ARB resource name'), + )), + ); }); testWithoutContext('must start with lowercase character', () { @@ -2294,23 +2299,25 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(nonAlphaNumericArbFile); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - outputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('Invalid ARB resource name')); - return; - } - - fail('should fail since key starts with a non-lowercase.'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Invalid ARB resource name'), + )), + ); }); testWithoutContext('cannot start with a number', () { @@ -2326,22 +2333,24 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e l10nDirectory.childFile(defaultTemplateArbFileName) .writeAsStringSync(nonAlphaNumericArbFile); - try { - LocalizationsGenerator( - fileSystem: fs, - inputPathString: defaultL10nPathString, - templateArbFileName: defaultTemplateArbFileName, - outputFileString: defaultOutputFileString, - classNameString: defaultClassNameString, - ) - ..loadResources() - ..writeOutputFiles(BufferLogger.test()); - } on L10nException catch (e) { - expect(e.message, contains('Invalid ARB resource name')); - return; - } - - fail('should fail since key starts with a number.'); + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + templateArbFileName: defaultTemplateArbFileName, + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('Invalid ARB resource name'), + )), + ); }); }); });