From 82889e6ab7f397d1f777c73aa7f6dcdbbc0ec1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=BC=D0=B5=D0=BB=D1=8C=D1=8F=D0=BD=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Sat, 2 May 2026 20:39:57 +0500 Subject: [PATCH 1/4] refactor: tests --- test/.gitignore | 2 +- test/arb_worker_golden2_test.dart | 93 ------------- test/arb_worker_test.dart | 44 ------ test/{golden => arb_worker_test}/app_en.arb | 0 test/{golden2 => arb_worker_test}/app_ru.arb | 0 test/arb_worker_test/arb_worker_test.dart | 131 ++++++++++++++++++ .../golden}/l10n.dart | 0 .../golden}/l10n_ru.dart | 0 test/generator_test.dart | 48 ------- test/generator_test/generator_test.dart | 127 +++++++++++++++++ test/{ => generator_test}/golden/l10n.dart | 0 test/{ => generator_test}/golden/l10n_en.dart | 0 test/{golden => generator_test}/l10n.yaml | 4 +- test/golden/_generator_result_test.dart_ | 82 ----------- test/lib/check_generated_dir.dart | 20 ++- test/lib/fake_arb_worker.dart | 18 +++ 16 files changed, 295 insertions(+), 274 deletions(-) delete mode 100644 test/arb_worker_golden2_test.dart delete mode 100644 test/arb_worker_test.dart rename test/{golden => arb_worker_test}/app_en.arb (100%) rename test/{golden2 => arb_worker_test}/app_ru.arb (100%) create mode 100644 test/arb_worker_test/arb_worker_test.dart rename test/{golden2 => arb_worker_test/golden}/l10n.dart (100%) rename test/{golden2 => arb_worker_test/golden}/l10n_ru.dart (100%) delete mode 100644 test/generator_test.dart create mode 100644 test/generator_test/generator_test.dart rename test/{ => generator_test}/golden/l10n.dart (100%) rename test/{ => generator_test}/golden/l10n_en.dart (100%) rename test/{golden => generator_test}/l10n.yaml (79%) delete mode 100644 test/golden/_generator_result_test.dart_ create mode 100644 test/lib/fake_arb_worker.dart diff --git a/test/.gitignore b/test/.gitignore index fd59010..2067bac 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1 +1 @@ -/generated/** +**/generated/ diff --git a/test/arb_worker_golden2_test.dart b/test/arb_worker_golden2_test.dart deleted file mode 100644 index a772e74..0000000 --- a/test/arb_worker_golden2_test.dart +++ /dev/null @@ -1,93 +0,0 @@ -// Created by alex@justprodev.com on 13.02.2025. - -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter_localizations_ota/src/arb_worker/arb_parser.dart'; -import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; -import 'package:test/test.dart'; - -import 'lib/check_generated_dir.dart'; - -const generatedFileName = 'l10n_test.g.dart'; - -void main() { - // generating test file, writing tests and running them via `flutter test` - test('Compare ARB translator nodes with L10n', () async { - final nodes = parseArbContent(File('test/golden2/app_ru.arb').readAsStringSync()); - ArbWorker arbWorker = ArbWorker(nodes, 'ru'); - - File input = File('test/golden2/l10n_ru.dart'); - checkGeneratedDir(); - IOSink output = File('test/generated/$generatedFileName').openWrite(); - - output.writeln(''' -import '../golden2/l10n_ru.dart'; -import 'package:test/test.dart'; - -void main() { - L10nRu l10n = L10nRu(); - - test('Test generated l10n', () { - '''); - - final lines = input.readAsLinesSync(); - - var testedCallsCount = 0; - - // enumerate methods and call it - for (int i = 0; i < lines.length; i++) { - if (lines[i].trimLeft().startsWith("@override")) { - i++; - if (lines[i].trimLeft().startsWith('String get')) { - final key = lines[i].split('get')[1].split('=>')[0].trim(); - output.writeln("\t\texpect(l10n.$key, '''${arbWorker.get(key)}''');"); - testedCallsCount++; - } else { - final key = lines[i].trimLeft().split(' ')[1].split('(').first; - final params = lines[i].split('(').last.split(')')[0].split(','); - - for(int i = 0; i < 5; i++) { - final args = {}; - final values = []; - for (var param in params) { - final pair = param.trim().split(' '); - - if(pair[0] == 'String') { - args[pair[1]] = 'string$i'; - values.add('\'${args[pair[1]]}\''); - } else { - args[pair[1]] = i; - values.add(i); - } - } - output.writeln( - "\t\texpect(l10n.$key(${values.join(',')}), '''${arbWorker.get(key, args)}''');", - ); - } - testedCallsCount++; - } - } - } - - output.writeln(''' - }); -} - '''); - - await output.close(); - - final result = Process.runSync( - Platform.isWindows ? 'flutter.bat' : 'flutter', - ['test', 'test/generated/$generatedFileName'], - stdoutEncoding: Encoding.getByName('UTF-8'), - stderrEncoding: Encoding.getByName('UTF-8'), - ); - - print(result.stdout); - print(result.stderr); - - expect(result.exitCode, 0); - expect(testedCallsCount, nodes.keys.length); - }); -} diff --git a/test/arb_worker_test.dart b/test/arb_worker_test.dart deleted file mode 100644 index df0a086..0000000 --- a/test/arb_worker_test.dart +++ /dev/null @@ -1,44 +0,0 @@ -// Created by alex@justprodev.com on 13.02.2025. - -import 'dart:io'; - -import 'package:flutter_localizations_ota/src/arb_worker/arb_parser.dart'; -import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; -import 'package:test/test.dart'; - -main() { - group('english straightforward working well', () { - final testArb = File('test/golden/app_en.arb').readAsStringSync(); - var worker = ArbWorker(parseArbContent(testArb), 'en'); - - test('retrieves the single key', () { - expect(worker.get('fl_ota_version'), equals('1')); - expect(worker.get('new_test_key'), equals('A new test key')); - }); - test('retrieves the correct translation with plurals', () { - expect(worker.get('nMails', {'count': 0, 'name': 'Nico'}), equals('You have no mails, Nico')); - expect(worker.get('nMails', {'count': 1, 'name': 'Nico'}), equals('Nico! You have one mail!')); - expect(worker.get('nMails', {'count': 2, 'name': 'Nico'}), equals('You have two mails, Nico')); - expect(worker.get('nMails', {'count': 4, 'name': 'Nico'}), equals('You have like 4 mails, Nico')); - expect(worker.get('nMails', {'count': 13, 'name': 'Nico'}), equals('You have like 13 mails, Nico')); - expect(worker.get('nMails', {'count': 3456, 'name': 'Nico'}), equals('You have like 3456 mails, Nico')); - }); - test('retrieves the correct translation with genders', () { - expect(worker.get('pageHomeBirthday', {'sex': 'male'}), equals('His birthday')); - expect(worker.get('pageHomeBirthday', {'sex': 'female'}), equals('Her birthday')); - expect(worker.get('pageHomeBirthday', {'sex': 'anything'}), equals('The birthday of them')); - expect(worker.get('pageHomeBirthday', {'sex': 'anything else'}), equals('The birthday of them')); - expect(worker.get('pageHomeBirthday', {'sex': 'other'}), equals('The birthday of them')); - }); - test('retrieves the correct translation with select', () { - expect(worker.get('trafficLight', {'light': 'red'}), equals('stop')); - expect(worker.get('trafficLight', {'light': 'yellow'}), equals('ready to go')); - expect(worker.get('trafficLight', {'light': 'green'}), equals('go')); - expect(worker.get('trafficLight', {'light': 'ngangong'}), equals('-')); - }); - - test('order', () { - expect(worker.get('nMails', {'name': 'Nico', 'count': 2}), equals('You have two mails, Nico')); - }); - }); -} diff --git a/test/golden/app_en.arb b/test/arb_worker_test/app_en.arb similarity index 100% rename from test/golden/app_en.arb rename to test/arb_worker_test/app_en.arb diff --git a/test/golden2/app_ru.arb b/test/arb_worker_test/app_ru.arb similarity index 100% rename from test/golden2/app_ru.arb rename to test/arb_worker_test/app_ru.arb diff --git a/test/arb_worker_test/arb_worker_test.dart b/test/arb_worker_test/arb_worker_test.dart new file mode 100644 index 0000000..e85afd4 --- /dev/null +++ b/test/arb_worker_test/arb_worker_test.dart @@ -0,0 +1,131 @@ +// Created by alex@justprodev.com on 13.02.2025. + +import 'dart:convert'; +import 'dart:io'; + +// ignore_for_file: avoid_print, avoid_relative_lib_imports + +import 'package:flutter_localizations_ota/src/arb_worker/arb_parser.dart'; +import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; +import 'package:test/test.dart'; + +import '../lib/check_generated_dir.dart'; + +const testDir = 'test/arb_worker_test'; + +main() { + group('english straightforward working well', () { + final testArb = File('$testDir/app_en.arb').readAsStringSync(); + var worker = ArbWorker(parseArbContent(testArb), 'en'); + + test('retrieves the single key', () { + expect(worker.get('fl_ota_version'), equals('1')); + expect(worker.get('new_test_key'), equals('A new test key')); + }); + test('retrieves the correct translation with plurals', () { + expect(worker.get('nMails', {'count': 0, 'name': 'Nico'}), equals('You have no mails, Nico')); + expect(worker.get('nMails', {'count': 1, 'name': 'Nico'}), equals('Nico! You have one mail!')); + expect(worker.get('nMails', {'count': 2, 'name': 'Nico'}), equals('You have two mails, Nico')); + expect(worker.get('nMails', {'count': 4, 'name': 'Nico'}), equals('You have like 4 mails, Nico')); + expect(worker.get('nMails', {'count': 13, 'name': 'Nico'}), equals('You have like 13 mails, Nico')); + expect(worker.get('nMails', {'count': 3456, 'name': 'Nico'}), equals('You have like 3456 mails, Nico')); + }); + test('retrieves the correct translation with genders', () { + expect(worker.get('pageHomeBirthday', {'sex': 'male'}), equals('His birthday')); + expect(worker.get('pageHomeBirthday', {'sex': 'female'}), equals('Her birthday')); + expect(worker.get('pageHomeBirthday', {'sex': 'anything'}), equals('The birthday of them')); + expect(worker.get('pageHomeBirthday', {'sex': 'anything else'}), equals('The birthday of them')); + expect(worker.get('pageHomeBirthday', {'sex': 'other'}), equals('The birthday of them')); + }); + test('retrieves the correct translation with select', () { + expect(worker.get('trafficLight', {'light': 'red'}), equals('stop')); + expect(worker.get('trafficLight', {'light': 'yellow'}), equals('ready to go')); + expect(worker.get('trafficLight', {'light': 'green'}), equals('go')); + expect(worker.get('trafficLight', {'light': 'ngangong'}), equals('-')); + }); + + test('order', () { + expect(worker.get('nMails', {'name': 'Nico', 'count': 2}), equals('You have two mails, Nico')); + }); + }); + + // generating test file, writing tests and running them via `flutter test` + test('Compare ARB translator nodes with L10n', () async { + const generatedFileName = 'l10n_test.g.dart'; + final nodes = parseArbContent(File('$testDir/app_ru.arb').readAsStringSync()); + ArbWorker arbWorker = ArbWorker(nodes, 'ru'); + + prepareGeneratedDir(testDir); + File input = File('$testDir/golden/l10n_ru.dart'); + IOSink output = File('$testDir/generated/$generatedFileName').openWrite(); + + output.writeln(''' +import 'l10n_ru.dart'; +import 'package:test/test.dart'; + +void main() { + L10nRu l10n = L10nRu(); + + test('Test generated l10n', () { + '''); + + final lines = input.readAsLinesSync(); + + var testedCallsCount = 0; + + // enumerate methods and call it + for (int i = 0; i < lines.length; i++) { + if (lines[i].trimLeft().startsWith("@override")) { + i++; + if (lines[i].trimLeft().startsWith('String get')) { + final key = lines[i].split('get')[1].split('=>')[0].trim(); + output.writeln("\t\texpect(l10n.$key, '''${arbWorker.get(key)}''');"); + testedCallsCount++; + } else { + final key = lines[i].trimLeft().split(' ')[1].split('(').first; + final params = lines[i].split('(').last.split(')')[0].split(','); + + for(int i = 0; i < 5; i++) { + final args = {}; + final values = []; + for (var param in params) { + final pair = param.trim().split(' '); + + if(pair[0] == 'String') { + args[pair[1]] = 'string$i'; + values.add('\'${args[pair[1]]}\''); + } else { + args[pair[1]] = i; + values.add(i); + } + } + output.writeln( + "\t\texpect(l10n.$key(${values.join(',')}), '''${arbWorker.get(key, args)}''');", + ); + } + testedCallsCount++; + } + } + } + + output.writeln(''' + }); +} + '''); + + await output.close(); + + final result = Process.runSync( + Platform.isWindows ? 'flutter.bat' : 'flutter', + ['test', '$testDir/generated/$generatedFileName'], + stdoutEncoding: Encoding.getByName('UTF-8'), + stderrEncoding: Encoding.getByName('UTF-8'), + ); + + print(result.stdout); + print(result.stderr); + + expect(result.exitCode, 0); + expect(testedCallsCount, nodes.keys.length); + }); +} diff --git a/test/golden2/l10n.dart b/test/arb_worker_test/golden/l10n.dart similarity index 100% rename from test/golden2/l10n.dart rename to test/arb_worker_test/golden/l10n.dart diff --git a/test/golden2/l10n_ru.dart b/test/arb_worker_test/golden/l10n_ru.dart similarity index 100% rename from test/golden2/l10n_ru.dart rename to test/arb_worker_test/golden/l10n_ru.dart diff --git a/test/generator_test.dart b/test/generator_test.dart deleted file mode 100644 index 784e114..0000000 --- a/test/generator_test.dart +++ /dev/null @@ -1,48 +0,0 @@ -// Created by alex@justprodev.com on 17.02.2025. - -import 'dart:convert'; -import 'dart:io'; - -// ignore_for_file: avoid_print - -import 'package:flutter_localizations_ota/src/generator/generator.dart'; -import 'package:test/test.dart'; - -import 'lib/check_generated_dir.dart'; - -const generatorResultFileName = '_generator_result_test.dart_'; - -void main() { - test('test generator itself', () async { - checkGeneratedDir(); - for(var f in Directory('test/golden').listSync()) { - if(f is File) { - f.copySync(f.path.replaceAll('golden', 'generated')); - } - } - await generate('test/golden/l10n.yaml'); - - final result = Process.runSync( - Platform.isWindows ? 'flutter.bat' : 'flutter', - ['test', 'test/generated/$generatorResultFileName'], - stdoutEncoding: Encoding.getByName('UTF-8'), - stderrEncoding: Encoding.getByName('UTF-8'), - ); - - print(result.stdout); - print(result.stderr); - - expect(result.exitCode, 0); - }); - - test('invoking "dart run flutter_localizations_ota:generate"', () async { - final result = Process.runSync( - 'dart', - ['run', 'flutter_localizations_ota:generate'], - stdoutEncoding: Encoding.getByName('UTF-8'), - stderrEncoding: Encoding.getByName('UTF-8'), - ); - - expect(result.stderr.toString(), contains('PathNotFoundException')); - }); -} diff --git a/test/generator_test/generator_test.dart b/test/generator_test/generator_test.dart new file mode 100644 index 0000000..b3ffee4 --- /dev/null +++ b/test/generator_test/generator_test.dart @@ -0,0 +1,127 @@ +// Created by alex@justprodev.com on 17.02.2025. + +import 'dart:convert'; +import 'dart:io'; + +// ignore_for_file: avoid_print, avoid_relative_lib_imports + +import 'package:flutter_localizations_ota/src/generator/generator.dart'; +import 'package:test/test.dart'; + +import '../lib/check_generated_dir.dart'; + +const generatorResultFileName = 'test_generator_result.dart'; + +const testDir = 'test/generator_test'; + +void main() { + + test('test generator itself', () async { + prepareGeneratedDir(testDir); + + await generate('$testDir/l10n.yaml'); + + await _generateTestFile(); + + final result = Process.runSync( + Platform.isWindows ? 'flutter.bat' : 'flutter', + ['test', '$testDir/generated/$generatorResultFileName'], + stdoutEncoding: Encoding.getByName('UTF-8'), + stderrEncoding: Encoding.getByName('UTF-8'), + ); + + print(result.stdout); + print(result.stderr); + + expect(result.exitCode, 0); + }); + + test('invoking "dart run flutter_localizations_ota:generate"', () async { + // just checking that `dart run flutter_localizations_ota:generate` calls the generator + final result = Process.runSync( + 'dart', + ['run', 'flutter_localizations_ota:generate'], + stdoutEncoding: Encoding.getByName('UTF-8'), + stderrEncoding: Encoding.getByName('UTF-8'), + ); + + // the error from generator is expected, because there is no l10n.yaml in the root of the project + expect(result.stderr.toString(), contains('PathNotFoundException')); + }); +} + +Future _generateTestFile() { + final output = File('$testDir/generated/$generatorResultFileName').openWrite(); + + output.writeln(''' +// file is used to test the generated l10n_remote.dart file +// The file will be invoked by the generator_test.dart + +import 'l10n.dart'; +import 'l10n_en.dart'; +import 'l10n_remote.dart'; +import '../../lib/fake_arb_worker.dart'; +import 'package:test/test.dart'; + +void main() { + final L10n l10n = L10nEn(); + final arbWorker = FakeArbWorker({}, 'en'); + final L10n l10nRemote = L10nRemote(l10n, arbWorker); + + test('Test generated l10n', () { + expect(l10n.fl_ota_version, l10nRemote.fl_ota_version); + expect(arbWorker.lastRequestedKey, 'fl_ota_version'); + expect(arbWorker.lastRequestedArgs, null); + + expect(l10n.nMails(0, 'name'), l10nRemote.nMails(0, 'name')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 0, 'name': 'name'}); + + expect(l10n.nMails(1, 'name1'), l10nRemote.nMails(1, 'name1')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 1, 'name': 'name1'}); + + expect(l10n.nMails(2, 'name2'), l10nRemote.nMails(2, 'name2')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 2, 'name': 'name2'}); + + expect(l10n.nMails(3, 'name3'), l10nRemote.nMails(3, 'name3')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 3, 'name': 'name3'}); + + expect(l10n.nMails(4, 'name4'), l10nRemote.nMails(4, 'name4')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 4, 'name': 'name4'}); + + expect(l10n.nMails(5, 'name5'), l10nRemote.nMails(5, 'name5')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 5, 'name': 'name5'}); + + expect(l10n.new_test_key, l10nRemote.new_test_key); + expect(arbWorker.lastRequestedKey, 'new_test_key'); + expect(arbWorker.lastRequestedArgs, null); + + expect(l10n.pageHomeBirthday('name'), l10nRemote.pageHomeBirthday('name')); + expect(arbWorker.lastRequestedKey, 'pageHomeBirthday'); + expect(arbWorker.lastRequestedArgs, {'sex': 'name'}); + + expect(l10n.trafficLight('red'), l10nRemote.trafficLight('red')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'red'}); + + expect(l10n.trafficLight('yellow'), l10nRemote.trafficLight('yellow')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'yellow'}); + + expect(l10n.trafficLight('green'), l10nRemote.trafficLight('green')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'green'}); + + expect(l10n.trafficLight('abc'), l10nRemote.trafficLight('abc')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'abc'}); + }); +} +'''); + return output.close(); +} \ No newline at end of file diff --git a/test/golden/l10n.dart b/test/generator_test/golden/l10n.dart similarity index 100% rename from test/golden/l10n.dart rename to test/generator_test/golden/l10n.dart diff --git a/test/golden/l10n_en.dart b/test/generator_test/golden/l10n_en.dart similarity index 100% rename from test/golden/l10n_en.dart rename to test/generator_test/golden/l10n_en.dart diff --git a/test/golden/l10n.yaml b/test/generator_test/l10n.yaml similarity index 79% rename from test/golden/l10n.yaml rename to test/generator_test/l10n.yaml index c0cf720..f22fecd 100644 --- a/test/golden/l10n.yaml +++ b/test/generator_test/l10n.yaml @@ -1,11 +1,11 @@ # https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization # https://flutter.dev/go/i18n-user-guide -arb-dir: test/assets/ +arb-dir: not_used_in_tests template-arb-file: app_en.arb output-localization-file: l10n.dart output-class: L10n synthetic-package: false -output-dir: test/generated +output-dir: test/generator_test/generated no-nullable-getter: true \ No newline at end of file diff --git a/test/golden/_generator_result_test.dart_ b/test/golden/_generator_result_test.dart_ deleted file mode 100644 index 74f815f..0000000 --- a/test/golden/_generator_result_test.dart_ +++ /dev/null @@ -1,82 +0,0 @@ -// file is used to test the generated l10n_remote.dart file -// The file will be invoked by the generator_test.dart - -import 'l10n_en.dart'; -import 'l10n_remote.dart'; -import 'package:test/test.dart'; -import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; - -void main() { - final L10nEn l10n = L10nEn(); - final testArbWorker = TestArbWorker({}, 'en'); - final L10nRemote l10nRemote = L10nRemote(l10n, testArbWorker); - - test('Test generated l10n', () { - expect(l10n.fl_ota_version, l10nRemote.fl_ota_version); - expect(testArbWorker.lastRequestedKey, 'fl_ota_version'); - expect(testArbWorker.lastRequestedArgs, null); - - expect(l10n.nMails(0, 'name'), l10nRemote.nMails(0, 'name')); - expect(testArbWorker.lastRequestedKey, 'nMails'); - expect(testArbWorker.lastRequestedArgs, {'count': 0, 'name': 'name'}); - - expect(l10n.nMails(1, 'name1'), l10nRemote.nMails(1, 'name1')); - expect(testArbWorker.lastRequestedKey, 'nMails'); - expect(testArbWorker.lastRequestedArgs, {'count': 1, 'name': 'name1'}); - - expect(l10n.nMails(2, 'name2'), l10nRemote.nMails(2, 'name2')); - expect(testArbWorker.lastRequestedKey, 'nMails'); - expect(testArbWorker.lastRequestedArgs, {'count': 2, 'name': 'name2'}); - - expect(l10n.nMails(3, 'name3'), l10nRemote.nMails(3, 'name3')); - expect(testArbWorker.lastRequestedKey, 'nMails'); - expect(testArbWorker.lastRequestedArgs, {'count': 3, 'name': 'name3'}); - - expect(l10n.nMails(4, 'name4'), l10nRemote.nMails(4, 'name4')); - expect(testArbWorker.lastRequestedKey, 'nMails'); - expect(testArbWorker.lastRequestedArgs, {'count': 4, 'name': 'name4'}); - - expect(l10n.nMails(5, 'name5'), l10nRemote.nMails(5, 'name5')); - expect(testArbWorker.lastRequestedKey, 'nMails'); - expect(testArbWorker.lastRequestedArgs, {'count': 5, 'name': 'name5'}); - - expect(l10n.new_test_key, l10nRemote.new_test_key); - expect(testArbWorker.lastRequestedKey, 'new_test_key'); - expect(testArbWorker.lastRequestedArgs, null); - - expect(l10n.pageHomeBirthday('name'), l10nRemote.pageHomeBirthday('name')); - expect(testArbWorker.lastRequestedKey, 'pageHomeBirthday'); - expect(testArbWorker.lastRequestedArgs, {'sex': 'name'}); - - expect(l10n.trafficLight('red'), l10nRemote.trafficLight('red')); - expect(testArbWorker.lastRequestedKey, 'trafficLight'); - expect(testArbWorker.lastRequestedArgs, {'light': 'red'}); - - expect(l10n.trafficLight('yellow'), l10nRemote.trafficLight('yellow')); - expect(testArbWorker.lastRequestedKey, 'trafficLight'); - expect(testArbWorker.lastRequestedArgs, {'light': 'yellow'}); - - expect(l10n.trafficLight('green'), l10nRemote.trafficLight('green')); - expect(testArbWorker.lastRequestedKey, 'trafficLight'); - expect(testArbWorker.lastRequestedArgs, {'light': 'green'}); - - expect(l10n.trafficLight('abc'), l10nRemote.trafficLight('abc')); - expect(testArbWorker.lastRequestedKey, 'trafficLight'); - expect(testArbWorker.lastRequestedArgs, {'light': 'abc'}); - }); -} - -class TestArbWorker extends ArbWorker { - TestArbWorker(super.arbNodes, super.locale); - - String? lastRequestedKey; - Map? lastRequestedArgs; - - @override - String? get(String key, [Map? args]) { - lastRequestedKey = key; - lastRequestedArgs = args; - return null; - } -} - \ No newline at end of file diff --git a/test/lib/check_generated_dir.dart b/test/lib/check_generated_dir.dart index 0af5753..09beda1 100644 --- a/test/lib/check_generated_dir.dart +++ b/test/lib/check_generated_dir.dart @@ -2,9 +2,21 @@ import 'dart:io'; -void checkGeneratedDir() { - final generatedDir = Directory('test/generated'); - if (!generatedDir.existsSync()) { - generatedDir.createSync(); +void prepareGeneratedDir([String testDir = 'test']) { + final generatedDir = Directory('$testDir/generated'); + + if (generatedDir.existsSync()) { + generatedDir.deleteSync(recursive: true); + } + generatedDir.createSync(); + + Directory goldenDir = Directory('$testDir/golden'); + + if (goldenDir.existsSync()) { + for(var f in goldenDir.listSync()) { + if(f is File) { + f.copySync(f.path.replaceAll('golden', 'generated')); + } + } } } \ No newline at end of file diff --git a/test/lib/fake_arb_worker.dart b/test/lib/fake_arb_worker.dart new file mode 100644 index 0000000..b8ec2d0 --- /dev/null +++ b/test/lib/fake_arb_worker.dart @@ -0,0 +1,18 @@ +// Created by alex@justprodev.com on 02.05.2026. + +import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; + +/// A test implementation of the ARB worker that records the last requested key and arguments. +class FakeArbWorker extends ArbWorker { + FakeArbWorker(super.arbNodes, super.locale); + + String? lastRequestedKey; + Map? lastRequestedArgs; + + @override + String? get(String key, [Map? args]) { + lastRequestedKey = key; + lastRequestedArgs = args; + return null; + } +} \ No newline at end of file From 627b3b889af24411531a6b95725aef575b5388b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=BC=D0=B5=D0=BB=D1=8C=D1=8F=D0=BD=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Sat, 2 May 2026 22:24:25 +0500 Subject: [PATCH 2/4] test: simplify --- test/.gitignore | 1 - test/arb_worker_test/{ => arb}/app_en.arb | 0 test/arb_worker_test/{ => arb}/app_ru.arb | 0 test/arb_worker_test/arb_worker_test.dart | 9 +-- .../{golden => generated}/l10n.dart | 0 .../{golden => generated}/l10n_ru.dart | 0 test/generator_test/generated/.gitignore | 1 + .../{golden => generated}/l10n.dart | 0 .../{golden => generated}/l10n_en.dart | 0 test/generator_test/generator_test.dart | 68 ++-------------- .../lib/compare_local_vs_remote.dart | 77 +++++++++++++++++++ test/lib/check_generated_dir.dart | 22 ------ test/lib/fake_arb_worker.dart | 18 ----- 13 files changed, 88 insertions(+), 108 deletions(-) delete mode 100644 test/.gitignore rename test/arb_worker_test/{ => arb}/app_en.arb (100%) rename test/arb_worker_test/{ => arb}/app_ru.arb (100%) rename test/arb_worker_test/{golden => generated}/l10n.dart (100%) rename test/arb_worker_test/{golden => generated}/l10n_ru.dart (100%) create mode 100644 test/generator_test/generated/.gitignore rename test/generator_test/{golden => generated}/l10n.dart (100%) rename test/generator_test/{golden => generated}/l10n_en.dart (100%) create mode 100644 test/generator_test/lib/compare_local_vs_remote.dart delete mode 100644 test/lib/check_generated_dir.dart delete mode 100644 test/lib/fake_arb_worker.dart diff --git a/test/.gitignore b/test/.gitignore deleted file mode 100644 index 2067bac..0000000 --- a/test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -**/generated/ diff --git a/test/arb_worker_test/app_en.arb b/test/arb_worker_test/arb/app_en.arb similarity index 100% rename from test/arb_worker_test/app_en.arb rename to test/arb_worker_test/arb/app_en.arb diff --git a/test/arb_worker_test/app_ru.arb b/test/arb_worker_test/arb/app_ru.arb similarity index 100% rename from test/arb_worker_test/app_ru.arb rename to test/arb_worker_test/arb/app_ru.arb diff --git a/test/arb_worker_test/arb_worker_test.dart b/test/arb_worker_test/arb_worker_test.dart index e85afd4..ba19293 100644 --- a/test/arb_worker_test/arb_worker_test.dart +++ b/test/arb_worker_test/arb_worker_test.dart @@ -9,13 +9,11 @@ import 'package:flutter_localizations_ota/src/arb_worker/arb_parser.dart'; import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; import 'package:test/test.dart'; -import '../lib/check_generated_dir.dart'; - const testDir = 'test/arb_worker_test'; main() { group('english straightforward working well', () { - final testArb = File('$testDir/app_en.arb').readAsStringSync(); + final testArb = File('$testDir/arb/app_en.arb').readAsStringSync(); var worker = ArbWorker(parseArbContent(testArb), 'en'); test('retrieves the single key', () { @@ -52,11 +50,10 @@ main() { // generating test file, writing tests and running them via `flutter test` test('Compare ARB translator nodes with L10n', () async { const generatedFileName = 'l10n_test.g.dart'; - final nodes = parseArbContent(File('$testDir/app_ru.arb').readAsStringSync()); + final nodes = parseArbContent(File('$testDir/arb/app_ru.arb').readAsStringSync()); ArbWorker arbWorker = ArbWorker(nodes, 'ru'); - prepareGeneratedDir(testDir); - File input = File('$testDir/golden/l10n_ru.dart'); + File input = File('$testDir/generated/l10n_ru.dart'); IOSink output = File('$testDir/generated/$generatedFileName').openWrite(); output.writeln(''' diff --git a/test/arb_worker_test/golden/l10n.dart b/test/arb_worker_test/generated/l10n.dart similarity index 100% rename from test/arb_worker_test/golden/l10n.dart rename to test/arb_worker_test/generated/l10n.dart diff --git a/test/arb_worker_test/golden/l10n_ru.dart b/test/arb_worker_test/generated/l10n_ru.dart similarity index 100% rename from test/arb_worker_test/golden/l10n_ru.dart rename to test/arb_worker_test/generated/l10n_ru.dart diff --git a/test/generator_test/generated/.gitignore b/test/generator_test/generated/.gitignore new file mode 100644 index 0000000..a58b124 --- /dev/null +++ b/test/generator_test/generated/.gitignore @@ -0,0 +1 @@ +l10n_remote.dart \ No newline at end of file diff --git a/test/generator_test/golden/l10n.dart b/test/generator_test/generated/l10n.dart similarity index 100% rename from test/generator_test/golden/l10n.dart rename to test/generator_test/generated/l10n.dart diff --git a/test/generator_test/golden/l10n_en.dart b/test/generator_test/generated/l10n_en.dart similarity index 100% rename from test/generator_test/golden/l10n_en.dart rename to test/generator_test/generated/l10n_en.dart diff --git a/test/generator_test/generator_test.dart b/test/generator_test/generator_test.dart index b3ffee4..da43f79 100644 --- a/test/generator_test/generator_test.dart +++ b/test/generator_test/generator_test.dart @@ -8,17 +8,13 @@ import 'dart:io'; import 'package:flutter_localizations_ota/src/generator/generator.dart'; import 'package:test/test.dart'; -import '../lib/check_generated_dir.dart'; - -const generatorResultFileName = 'test_generator_result.dart'; +const generatorResultFileName = 'check_generator_result.g.dart'; const testDir = 'test/generator_test'; void main() { test('test generator itself', () async { - prepareGeneratedDir(testDir); - await generate('$testDir/l10n.yaml'); await _generateTestFile(); @@ -60,66 +56,16 @@ Future _generateTestFile() { import 'l10n.dart'; import 'l10n_en.dart'; import 'l10n_remote.dart'; -import '../../lib/fake_arb_worker.dart'; +import '../lib/compare_local_vs_remote.dart'; import 'package:test/test.dart'; void main() { - final L10n l10n = L10nEn(); - final arbWorker = FakeArbWorker({}, 'en'); - final L10n l10nRemote = L10nRemote(l10n, arbWorker); - test('Test generated l10n', () { - expect(l10n.fl_ota_version, l10nRemote.fl_ota_version); - expect(arbWorker.lastRequestedKey, 'fl_ota_version'); - expect(arbWorker.lastRequestedArgs, null); - - expect(l10n.nMails(0, 'name'), l10nRemote.nMails(0, 'name')); - expect(arbWorker.lastRequestedKey, 'nMails'); - expect(arbWorker.lastRequestedArgs, {'count': 0, 'name': 'name'}); - - expect(l10n.nMails(1, 'name1'), l10nRemote.nMails(1, 'name1')); - expect(arbWorker.lastRequestedKey, 'nMails'); - expect(arbWorker.lastRequestedArgs, {'count': 1, 'name': 'name1'}); - - expect(l10n.nMails(2, 'name2'), l10nRemote.nMails(2, 'name2')); - expect(arbWorker.lastRequestedKey, 'nMails'); - expect(arbWorker.lastRequestedArgs, {'count': 2, 'name': 'name2'}); - - expect(l10n.nMails(3, 'name3'), l10nRemote.nMails(3, 'name3')); - expect(arbWorker.lastRequestedKey, 'nMails'); - expect(arbWorker.lastRequestedArgs, {'count': 3, 'name': 'name3'}); - - expect(l10n.nMails(4, 'name4'), l10nRemote.nMails(4, 'name4')); - expect(arbWorker.lastRequestedKey, 'nMails'); - expect(arbWorker.lastRequestedArgs, {'count': 4, 'name': 'name4'}); - - expect(l10n.nMails(5, 'name5'), l10nRemote.nMails(5, 'name5')); - expect(arbWorker.lastRequestedKey, 'nMails'); - expect(arbWorker.lastRequestedArgs, {'count': 5, 'name': 'name5'}); - - expect(l10n.new_test_key, l10nRemote.new_test_key); - expect(arbWorker.lastRequestedKey, 'new_test_key'); - expect(arbWorker.lastRequestedArgs, null); - - expect(l10n.pageHomeBirthday('name'), l10nRemote.pageHomeBirthday('name')); - expect(arbWorker.lastRequestedKey, 'pageHomeBirthday'); - expect(arbWorker.lastRequestedArgs, {'sex': 'name'}); - - expect(l10n.trafficLight('red'), l10nRemote.trafficLight('red')); - expect(arbWorker.lastRequestedKey, 'trafficLight'); - expect(arbWorker.lastRequestedArgs, {'light': 'red'}); - - expect(l10n.trafficLight('yellow'), l10nRemote.trafficLight('yellow')); - expect(arbWorker.lastRequestedKey, 'trafficLight'); - expect(arbWorker.lastRequestedArgs, {'light': 'yellow'}); - - expect(l10n.trafficLight('green'), l10nRemote.trafficLight('green')); - expect(arbWorker.lastRequestedKey, 'trafficLight'); - expect(arbWorker.lastRequestedArgs, {'light': 'green'}); - - expect(l10n.trafficLight('abc'), l10nRemote.trafficLight('abc')); - expect(arbWorker.lastRequestedKey, 'trafficLight'); - expect(arbWorker.lastRequestedArgs, {'light': 'abc'}); + final l10n = L10nEn(); + final arbWorker = FakeArbWorker(); + final l10nRemote = L10nRemote(l10n, arbWorker); + + compareLocalVsRemote(l10n, l10nRemote, arbWorker); }); } '''); diff --git a/test/generator_test/lib/compare_local_vs_remote.dart b/test/generator_test/lib/compare_local_vs_remote.dart new file mode 100644 index 0000000..7381094 --- /dev/null +++ b/test/generator_test/lib/compare_local_vs_remote.dart @@ -0,0 +1,77 @@ +// Created by alex@justprodev.com on 02.05.2026. + +// ignore_for_file: avoid_relative_lib_imports + +import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; + +import '../generated/l10n.dart'; +import 'package:test/test.dart'; + +void compareLocalVsRemote(L10n l10n, L10n l10nRemote, FakeArbWorker arbWorker) { + expect(l10n.fl_ota_version, l10nRemote.fl_ota_version); + expect(arbWorker.lastRequestedKey, 'fl_ota_version'); + expect(arbWorker.lastRequestedArgs, null); + + expect(l10n.nMails(0, 'name'), l10nRemote.nMails(0, 'name')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 0, 'name': 'name'}); + + expect(l10n.nMails(1, 'name1'), l10nRemote.nMails(1, 'name1')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 1, 'name': 'name1'}); + + expect(l10n.nMails(2, 'name2'), l10nRemote.nMails(2, 'name2')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 2, 'name': 'name2'}); + + expect(l10n.nMails(3, 'name3'), l10nRemote.nMails(3, 'name3')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 3, 'name': 'name3'}); + + expect(l10n.nMails(4, 'name4'), l10nRemote.nMails(4, 'name4')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 4, 'name': 'name4'}); + + expect(l10n.nMails(5, 'name5'), l10nRemote.nMails(5, 'name5')); + expect(arbWorker.lastRequestedKey, 'nMails'); + expect(arbWorker.lastRequestedArgs, {'count': 5, 'name': 'name5'}); + + expect(l10n.new_test_key, l10nRemote.new_test_key); + expect(arbWorker.lastRequestedKey, 'new_test_key'); + expect(arbWorker.lastRequestedArgs, null); + + expect(l10n.pageHomeBirthday('name'), l10nRemote.pageHomeBirthday('name')); + expect(arbWorker.lastRequestedKey, 'pageHomeBirthday'); + expect(arbWorker.lastRequestedArgs, {'sex': 'name'}); + + expect(l10n.trafficLight('red'), l10nRemote.trafficLight('red')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'red'}); + + expect(l10n.trafficLight('yellow'), l10nRemote.trafficLight('yellow')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'yellow'}); + + expect(l10n.trafficLight('green'), l10nRemote.trafficLight('green')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'green'}); + + expect(l10n.trafficLight('abc'), l10nRemote.trafficLight('abc')); + expect(arbWorker.lastRequestedKey, 'trafficLight'); + expect(arbWorker.lastRequestedArgs, {'light': 'abc'}); +} + +/// A test implementation of the ARB worker that records the last requested key and arguments. +class FakeArbWorker extends ArbWorker { + FakeArbWorker() : super({}, 'en'); + + String? lastRequestedKey; + Map? lastRequestedArgs; + + @override + String? get(String key, [Map? args]) { + lastRequestedKey = key; + lastRequestedArgs = args; + return null; + } +} diff --git a/test/lib/check_generated_dir.dart b/test/lib/check_generated_dir.dart deleted file mode 100644 index 09beda1..0000000 --- a/test/lib/check_generated_dir.dart +++ /dev/null @@ -1,22 +0,0 @@ -// Created by alex@justprodev.com on 18.02.2025. - -import 'dart:io'; - -void prepareGeneratedDir([String testDir = 'test']) { - final generatedDir = Directory('$testDir/generated'); - - if (generatedDir.existsSync()) { - generatedDir.deleteSync(recursive: true); - } - generatedDir.createSync(); - - Directory goldenDir = Directory('$testDir/golden'); - - if (goldenDir.existsSync()) { - for(var f in goldenDir.listSync()) { - if(f is File) { - f.copySync(f.path.replaceAll('golden', 'generated')); - } - } - } -} \ No newline at end of file diff --git a/test/lib/fake_arb_worker.dart b/test/lib/fake_arb_worker.dart deleted file mode 100644 index b8ec2d0..0000000 --- a/test/lib/fake_arb_worker.dart +++ /dev/null @@ -1,18 +0,0 @@ -// Created by alex@justprodev.com on 02.05.2026. - -import 'package:flutter_localizations_ota/src/arb_worker/arb_worker.dart'; - -/// A test implementation of the ARB worker that records the last requested key and arguments. -class FakeArbWorker extends ArbWorker { - FakeArbWorker(super.arbNodes, super.locale); - - String? lastRequestedKey; - Map? lastRequestedArgs; - - @override - String? get(String key, [Map? args]) { - lastRequestedKey = key; - lastRequestedArgs = args; - return null; - } -} \ No newline at end of file From 0e821e134474533076c977a98999ea6dc1d65a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=BC=D0=B5=D0=BB=D1=8C=D1=8F=D0=BD=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Sat, 2 May 2026 22:43:28 +0500 Subject: [PATCH 3/4] fix: key extraction logic for handling 'get' keyword in keys (https://github.com/justprodev/flutter_localizations_ota/pull/7) --- lib/src/generator/generator.dart | 2 +- test/generator_test/generated/l10n.dart | 4 ++++ test/generator_test/generated/l10n_en.dart | 6 ++++++ test/generator_test/lib/compare_local_vs_remote.dart | 8 ++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/src/generator/generator.dart b/lib/src/generator/generator.dart index 89b884b..909edf4 100644 --- a/lib/src/generator/generator.dart +++ b/lib/src/generator/generator.dart @@ -31,7 +31,7 @@ Future generate([String path = 'l10n.yaml']) async { } if (line.startsWith('String get')) { - final key = line.split('get')[1].split(';')[0].trim(); + final key = line.split('get ')[1].split(';')[0].trim(); output.writeln(_generateField(key)); } else { final key = line.split(' ')[1].split('(').first; diff --git a/test/generator_test/generated/l10n.dart b/test/generator_test/generated/l10n.dart index 1fcbcf0..daa70c5 100644 --- a/test/generator_test/generated/l10n.dart +++ b/test/generator_test/generated/l10n.dart @@ -122,6 +122,10 @@ abstract class L10n { /// In en, this message translates to: /// **'{light, select, red{stop} yellow{ready to go} green{go} other{-}}'** String trafficLight(String light); + + String get widgetTitle; + + String get getSomeText; } class _L10nDelegate extends LocalizationsDelegate { diff --git a/test/generator_test/generated/l10n_en.dart b/test/generator_test/generated/l10n_en.dart index a6944c4..1bfee20 100644 --- a/test/generator_test/generated/l10n_en.dart +++ b/test/generator_test/generated/l10n_en.dart @@ -55,4 +55,10 @@ class L10nEn extends L10n { ); return '$_temp0'; } + + @override + String get widgetTitle => 'Widget title'; + + @override + String get getSomeText => 'Get some text'; } diff --git a/test/generator_test/lib/compare_local_vs_remote.dart b/test/generator_test/lib/compare_local_vs_remote.dart index 7381094..5eb55f4 100644 --- a/test/generator_test/lib/compare_local_vs_remote.dart +++ b/test/generator_test/lib/compare_local_vs_remote.dart @@ -59,6 +59,14 @@ void compareLocalVsRemote(L10n l10n, L10n l10nRemote, FakeArbWorker arbWorker) { expect(l10n.trafficLight('abc'), l10nRemote.trafficLight('abc')); expect(arbWorker.lastRequestedKey, 'trafficLight'); expect(arbWorker.lastRequestedArgs, {'light': 'abc'}); + + expect(l10n.widgetTitle, l10nRemote.widgetTitle); + expect(arbWorker.lastRequestedKey, 'widgetTitle'); + expect(arbWorker.lastRequestedArgs, null); + + expect(l10n.getSomeText, l10nRemote.getSomeText); + expect(arbWorker.lastRequestedKey, 'getSomeText'); + expect(arbWorker.lastRequestedArgs, null); } /// A test implementation of the ARB worker that records the last requested key and arguments. From 22643640cf56b5c337ec503586fbcf2e6bdada18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=BC=D0=B5=D0=BB=D1=8C=D1=8F=D0=BD=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= Date: Sat, 2 May 2026 22:48:28 +0500 Subject: [PATCH 4/4] bump version to 0.8.2 --- CHANGELOG.md | 6 +++++- pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93a3372..60beb4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -### 0.8.1 (2025-02-18) +### 0.8.2 (2025-05-02) + +- [Fix generator issues ('get' keyword in keys)](https://github.com/justprodev/flutter_localizations_ota/pull/7) + +### 0.8.1 (2026-04-18) - [Fix generator issues](https://github.com/justprodev/flutter_localizations_ota/pull/5) diff --git a/pubspec.yaml b/pubspec.yaml index c24b633..b80fc7d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_localizations_ota description: Over-The-Air updates for Flutter Framework localizations. -version: 0.8.1 +version: 0.8.2 repository: https://github.com/justprodev/flutter_localizations_ota topics: