@@ -113,8 +119,9 @@ void main() {
expect(tester.takeException(), isNull);
});
- testWidgets('renders a table with empty | cells (fill-in-the-blank)',
- (tester) async {
+ testWidgets('renders a table with empty | cells (fill-in-the-blank)', (
+ tester,
+ ) async {
// Real Time_with_God table shape: lots of empty cells for users to fill in.
await pump(tester, '''
@@ -144,8 +151,9 @@ void main() {
expect(tester.takeException(), isNull);
});
- testWidgets('renders a nested inside a (Time_with_God shape)',
- (tester) async {
+ testWidgets('renders a nested inside a (Time_with_God shape)', (
+ tester,
+ ) async {
// This is the exact shape from Time_with_God line 70: a table inside a
// list item inside a ul. It uses a before the nested table.
await pump(tester, '''
@@ -175,8 +183,9 @@ void main() {
expect(tester.takeException(), isNull);
});
- testWidgets('renders the real Time_with_God fixture end-to-end',
- (tester) async {
+ testWidgets('renders the real Time_with_God fixture end-to-end', (
+ tester,
+ ) async {
// Pumping the exact page content that was crashing in production.
// Critically:
// 1. enable semantics — on a real device the semantics pass walks the
@@ -190,8 +199,10 @@ void main() {
final semantics = tester.ensureSemantics();
try {
await tester.binding.setSurfaceSize(const Size(390, 844));
- final html = File('test/assets-en/html-en-main/Time_with_God.html')
- .readAsStringSync();
+ final html =
+ File(
+ 'test/assets-en/html-en-main/Time_with_God.html',
+ ).readAsStringSync();
await pump(tester, html);
expect(tester.takeException(), isNull);
} finally {
@@ -200,8 +211,9 @@ void main() {
}
});
- testWidgets('renders a table wrapped in the standard page chrome',
- (tester) async {
+ testWidgets('renders a table wrapped in the standard page chrome', (
+ tester,
+ ) async {
// Mimics the structure of a real Time With God page: headings,
// paragraphs, and a table together.
await pump(tester, '''
diff --git a/test/language_downloader_test.dart b/test/language_downloader_test.dart
index 331cb32..bbf9515 100644
--- a/test/language_downloader_test.dart
+++ b/test/language_downloader_test.dart
@@ -24,14 +24,15 @@ Uint8List createTestZip(Map files) {
/// Helper to set up a mock Dio response for a URL returning zip bytes.
void mockDioGet(MockDio dio, String url, Uint8List zipBytes) {
- when(() => dio.get>(
- url,
- options: any(named: 'options'),
- )).thenAnswer((_) async => Response(
- data: zipBytes.toList(),
- statusCode: 200,
- requestOptions: RequestOptions(path: url),
- ));
+ when(
+ () => dio.get>(url, options: any(named: 'options')),
+ ).thenAnswer(
+ (_) async => Response(
+ data: zipBytes.toList(),
+ statusCode: 200,
+ requestOptions: RequestOptions(path: url),
+ ),
+ );
}
void main() {
@@ -68,41 +69,53 @@ void main() {
expect(await downloader.isDownloaded('de'), true);
final contentsJson = fs.file(
- '/app-docs/assets-de/${Globals.getResourcesDir('de')}/structure/contents.json');
+ '/app-docs/assets-de/${Globals.getResourcesDir('de')}/structure/contents.json',
+ );
expect(await contentsJson.exists(), true);
expect(await contentsJson.readAsString(), '{"worksheets":[]}');
final indexHtml = fs.file(
- '/app-docs/assets-de/${Globals.getResourcesDir('de')}/index.html');
+ '/app-docs/assets-de/${Globals.getResourcesDir('de')}/index.html',
+ );
expect(await indexHtml.exists(), true);
final pdfFile = fs.file(
- '/app-docs/assets-de/${Globals.getPdfDir('de')}/test.pdf');
+ '/app-docs/assets-de/${Globals.getPdfDir('de')}/test.pdf',
+ );
expect(await pdfFile.exists(), true);
// No staging dir left behind
expect(await fs.directory('/app-docs/assets-de.staging').exists(), false);
});
- test('Network failure: nothing remains at pathFor and no staging leftover',
- () async {
- // HTML download succeeds but PDF download throws
- final htmlZip = createTestZip({
- '${Globals.getResourcesDir('fr')}/index.html': 'Bonjour',
- });
- mockDioGet(dio, Globals.getRemoteUrlHtml('fr'), htmlZip);
- when(() => dio.get>(
+ test(
+ 'Network failure: nothing remains at pathFor and no staging leftover',
+ () async {
+ // HTML download succeeds but PDF download throws
+ final htmlZip = createTestZip({
+ '${Globals.getResourcesDir('fr')}/index.html': 'Bonjour',
+ });
+ mockDioGet(dio, Globals.getRemoteUrlHtml('fr'), htmlZip);
+ when(
+ () => dio.get>(
Globals.getRemoteUrlPdf('fr'),
options: any(named: 'options'),
- )).thenThrow(DioException(
- requestOptions: RequestOptions(path: Globals.getRemoteUrlPdf('fr')),
- ));
+ ),
+ ).thenThrow(
+ DioException(
+ requestOptions: RequestOptions(path: Globals.getRemoteUrlPdf('fr')),
+ ),
+ );
- await expectLater(downloader.download('fr'), throwsA(isA()));
+ await expectLater(
+ downloader.download('fr'),
+ throwsA(isA()),
+ );
- expect(await downloader.isDownloaded('fr'), false);
- expect(await fs.directory('/app-docs/assets-fr.staging').exists(), false);
- });
+ expect(await downloader.isDownloaded('fr'), false);
+ expect(await fs.directory('/app-docs/assets-fr.staging').exists(), false);
+ },
+ );
test('Corrupted zip: cleanup same as network failure', () async {
// A zip header (PK\x03\x04) followed by garbage triggers a real decode error
@@ -132,20 +145,25 @@ void main() {
'${Globals.getResourcesDir('it')}/file.html': 'ciao',
});
mockDioGet(dio, Globals.getRemoteUrlHtml('it'), htmlZip);
- when(() => dio.get>(
- Globals.getRemoteUrlPdf('it'),
- options: any(named: 'options'),
- )).thenThrow(DioException(
- requestOptions: RequestOptions(path: Globals.getRemoteUrlPdf('it')),
- ));
+ when(
+ () => dio.get>(
+ Globals.getRemoteUrlPdf('it'),
+ options: any(named: 'options'),
+ ),
+ ).thenThrow(
+ DioException(
+ requestOptions: RequestOptions(path: Globals.getRemoteUrlPdf('it')),
+ ),
+ );
await expectLater(downloader.download('it'), throwsA(isA()));
// Prior data is intact
expect(await downloader.isDownloaded('it'), true);
expect(
- await fs.file('/app-docs/assets-it/existing.txt').readAsString(),
- 'precious');
+ await fs.file('/app-docs/assets-it/existing.txt').readAsString(),
+ 'precious',
+ );
});
test('Different languages download in parallel', () async {
@@ -167,10 +185,12 @@ void main() {
'${Globals.getPdfDir('fr')}/file.pdf': 'fr-pdf',
});
- when(() => dio.get>(
- Globals.getRemoteUrlHtml('de'),
- options: any(named: 'options'),
- )).thenAnswer((_) async {
+ when(
+ () => dio.get>(
+ Globals.getRemoteUrlHtml('de'),
+ options: any(named: 'options'),
+ ),
+ ).thenAnswer((_) async {
deHtmlInFlight = true;
await deHtmlGate.future;
return Response(
@@ -179,18 +199,24 @@ void main() {
requestOptions: RequestOptions(),
);
});
- when(() => dio.get>(
- Globals.getRemoteUrlPdf('de'),
- options: any(named: 'options'),
- )).thenAnswer((_) async => Response(
- data: pdfZip1.toList(),
- statusCode: 200,
- requestOptions: RequestOptions(),
- ));
- when(() => dio.get>(
- Globals.getRemoteUrlHtml('fr'),
- options: any(named: 'options'),
- )).thenAnswer((_) async {
+ when(
+ () => dio.get>(
+ Globals.getRemoteUrlPdf('de'),
+ options: any(named: 'options'),
+ ),
+ ).thenAnswer(
+ (_) async => Response(
+ data: pdfZip1.toList(),
+ statusCode: 200,
+ requestOptions: RequestOptions(),
+ ),
+ );
+ when(
+ () => dio.get>(
+ Globals.getRemoteUrlHtml('fr'),
+ options: any(named: 'options'),
+ ),
+ ).thenAnswer((_) async {
frHtmlInFlight = true;
await frHtmlGate.future;
return Response(
@@ -199,14 +225,18 @@ void main() {
requestOptions: RequestOptions(),
);
});
- when(() => dio.get>(
- Globals.getRemoteUrlPdf('fr'),
- options: any(named: 'options'),
- )).thenAnswer((_) async => Response(
- data: pdfZip2.toList(),
- statusCode: 200,
- requestOptions: RequestOptions(),
- ));
+ when(
+ () => dio.get>(
+ Globals.getRemoteUrlPdf('fr'),
+ options: any(named: 'options'),
+ ),
+ ).thenAnswer(
+ (_) async => Response(
+ data: pdfZip2.toList(),
+ statusCode: 200,
+ requestOptions: RequestOptions(),
+ ),
+ );
final f1 = downloader.download('de');
await Future.delayed(Duration.zero);
@@ -232,10 +262,12 @@ void main() {
'${Globals.getPdfDir('de')}/file.pdf': 'de-pdf',
});
- when(() => dio.get>(
- Globals.getRemoteUrlHtml('de'),
- options: any(named: 'options'),
- )).thenAnswer((_) async {
+ when(
+ () => dio.get>(
+ Globals.getRemoteUrlHtml('de'),
+ options: any(named: 'options'),
+ ),
+ ).thenAnswer((_) async {
htmlCallCount++;
await gate.future;
return Response(
@@ -244,14 +276,18 @@ void main() {
requestOptions: RequestOptions(),
);
});
- when(() => dio.get>(
- Globals.getRemoteUrlPdf('de'),
- options: any(named: 'options'),
- )).thenAnswer((_) async => Response(
- data: pdfZip.toList(),
- statusCode: 200,
- requestOptions: RequestOptions(),
- ));
+ when(
+ () => dio.get>(
+ Globals.getRemoteUrlPdf('de'),
+ options: any(named: 'options'),
+ ),
+ ).thenAnswer(
+ (_) async => Response(
+ data: pdfZip.toList(),
+ statusCode: 200,
+ requestOptions: RequestOptions(),
+ ),
+ );
final f1 = downloader.download('de');
await Future.delayed(Duration.zero);
@@ -264,88 +300,108 @@ void main() {
expect(htmlCallCount, 2);
});
- test('Only kMaxParallelZipDecodes archives are decoded at the same time',
- () async {
- // Every decode blocks on a gate so we can watch how many run at once
- var inFlight = 0;
- var maxInFlight = 0;
- final gates = >[];
- Future> gatedDecoder(Uint8List zipBytes) async {
- inFlight++;
- maxInFlight = max(maxInFlight, inFlight);
- final gate = Completer();
- gates.add(gate);
- await gate.future;
- inFlight--;
- return decodeZipEntries(zipBytes);
- }
-
- downloader = LanguageDownloaderImpl(
- root: root, dio: dio, fileSystem: fs, zipDecoder: gatedDecoder);
-
- const langCodes = ['de', 'fr', 'es'];
- for (final langCode in langCodes) {
- mockDioGet(dio, Globals.getRemoteUrlHtml(langCode),
- createTestZip({'${Globals.getResourcesDir('de')}/f.html': 'x'}));
- mockDioGet(dio, Globals.getRemoteUrlPdf(langCode),
- createTestZip({'${Globals.getPdfDir('de')}/f.pdf': 'x'}));
- }
-
- final downloads = [for (final code in langCodes) downloader.download(code)];
- var finished = false;
- unawaited(Future.wait(downloads).then((_) => finished = true));
-
- // Let all three downloads reach their first decode
- for (var i = 0; i < 5; i++) {
- await Future.delayed(Duration.zero);
- }
- expect(inFlight, kMaxParallelZipDecodes);
- expect(gates.length, kMaxParallelZipDecodes);
-
- // Now let them through one by one - a queued decode may only start
- // once a running one has finished
- for (var i = 0; !finished && i < 100; i++) {
- if (gates.isNotEmpty) gates.removeAt(0).complete();
- await Future.delayed(Duration.zero);
- }
- expect(finished, isTrue);
- expect(maxInFlight, kMaxParallelZipDecodes);
- for (final langCode in langCodes) {
- expect(await downloader.isDownloaded(langCode), true);
- }
- });
-
- test('Crash recovery: pre-seeded staging dir is wiped by next download',
- () async {
- // Simulate crashed prior run leaving a staging dir
- await fs
- .directory('/app-docs/assets-de.staging/leftover')
- .create(recursive: true);
- await fs
- .file('/app-docs/assets-de.staging/leftover/junk.txt')
- .writeAsString('crash-leftover');
-
- final htmlZip = createTestZip({
- '${Globals.getResourcesDir('de')}/fresh.html': 'Fresh',
- });
- final pdfZip = createTestZip({
- '${Globals.getPdfDir('de')}/fresh.pdf': 'fresh-pdf',
- });
-
- mockDioGet(dio, Globals.getRemoteUrlHtml('de'), htmlZip);
- mockDioGet(dio, Globals.getRemoteUrlPdf('de'), pdfZip);
-
- await downloader.download('de');
+ test(
+ 'Only kMaxParallelZipDecodes archives are decoded at the same time',
+ () async {
+ // Every decode blocks on a gate so we can watch how many run at once
+ var inFlight = 0;
+ var maxInFlight = 0;
+ final gates = >[];
+ Future> gatedDecoder(Uint8List zipBytes) async {
+ inFlight++;
+ maxInFlight = max(maxInFlight, inFlight);
+ final gate = Completer();
+ gates.add(gate);
+ await gate.future;
+ inFlight--;
+ return decodeZipEntries(zipBytes);
+ }
+
+ downloader = LanguageDownloaderImpl(
+ root: root,
+ dio: dio,
+ fileSystem: fs,
+ zipDecoder: gatedDecoder,
+ );
- // Old staging leftover is gone
- expect(
- await fs.file('/app-docs/assets-de/leftover/junk.txt').exists(), false);
- // Fresh content is there
- expect(
+ const langCodes = ['de', 'fr', 'es'];
+ for (final langCode in langCodes) {
+ mockDioGet(
+ dio,
+ Globals.getRemoteUrlHtml(langCode),
+ createTestZip({'${Globals.getResourcesDir('de')}/f.html': 'x'}),
+ );
+ mockDioGet(
+ dio,
+ Globals.getRemoteUrlPdf(langCode),
+ createTestZip({'${Globals.getPdfDir('de')}/f.pdf': 'x'}),
+ );
+ }
+
+ final downloads = [
+ for (final code in langCodes) downloader.download(code),
+ ];
+ var finished = false;
+ unawaited(Future.wait(downloads).then((_) => finished = true));
+
+ // Let all three downloads reach their first decode
+ for (var i = 0; i < 5; i++) {
+ await Future.delayed(Duration.zero);
+ }
+ expect(inFlight, kMaxParallelZipDecodes);
+ expect(gates.length, kMaxParallelZipDecodes);
+
+ // Now let them through one by one - a queued decode may only start
+ // once a running one has finished
+ for (var i = 0; !finished && i < 100; i++) {
+ if (gates.isNotEmpty) gates.removeAt(0).complete();
+ await Future.delayed(Duration.zero);
+ }
+ expect(finished, isTrue);
+ expect(maxInFlight, kMaxParallelZipDecodes);
+ for (final langCode in langCodes) {
+ expect(await downloader.isDownloaded(langCode), true);
+ }
+ },
+ );
+
+ test(
+ 'Crash recovery: pre-seeded staging dir is wiped by next download',
+ () async {
+ // Simulate crashed prior run leaving a staging dir
+ await fs
+ .directory('/app-docs/assets-de.staging/leftover')
+ .create(recursive: true);
+ await fs
+ .file('/app-docs/assets-de.staging/leftover/junk.txt')
+ .writeAsString('crash-leftover');
+
+ final htmlZip = createTestZip({
+ '${Globals.getResourcesDir('de')}/fresh.html': 'Fresh',
+ });
+ final pdfZip = createTestZip({
+ '${Globals.getPdfDir('de')}/fresh.pdf': 'fresh-pdf',
+ });
+
+ mockDioGet(dio, Globals.getRemoteUrlHtml('de'), htmlZip);
+ mockDioGet(dio, Globals.getRemoteUrlPdf('de'), pdfZip);
+
+ await downloader.download('de');
+
+ // Old staging leftover is gone
+ expect(
+ await fs.file('/app-docs/assets-de/leftover/junk.txt').exists(),
+ false,
+ );
+ // Fresh content is there
+ expect(
await fs
.file(
- '/app-docs/assets-de/${Globals.getResourcesDir('de')}/fresh.html')
+ '/app-docs/assets-de/${Globals.getResourcesDir('de')}/fresh.html',
+ )
.exists(),
- true);
- });
+ true,
+ );
+ },
+ );
}
diff --git a/test/language_selection_button_test.dart b/test/language_selection_button_test.dart
index cbc45d8..13701a7 100644
--- a/test/language_selection_button_test.dart
+++ b/test/language_selection_button_test.dart
@@ -20,24 +20,36 @@ class TestLanguagesButton extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
- locale: ref.watch(appLanguageProvider).locale,
- localizationsDelegates: AppLocalizations.localizationsDelegates,
- supportedLocales: AppLocalizations.supportedLocales,
- // we need ViewPage here because LanguagesButton uses
- // context.findAncestorWidgetOfExactType() to get current page
- home: const ViewPage('Healing', 'de'));
+ locale: ref.watch(appLanguageProvider).locale,
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
+ supportedLocales: AppLocalizations.supportedLocales,
+ // we need ViewPage here because LanguagesButton uses
+ // context.findAncestorWidgetOfExactType() to get current page
+ home: const ViewPage('Healing', 'de'),
+ );
}
}
void main() {
- testWidgets('Test with only German downloaded, English as appLanguage',
- (WidgetTester tester) async {
- await tester.pumpWidget(ProviderScope(overrides: [
- appLanguageProvider.overrideWith(() => TestAppLanguage('en')),
- languageProvider.overrideWith2((languageCode) => TestLanguageController(
- downloadedLanguages: ['de'],
- pages: {'Healing': const Page('test', 'test', 'test', '1.0', null)}))
- ], child: const TestLanguagesButton()));
+ testWidgets('Test with only German downloaded, English as appLanguage', (
+ WidgetTester tester,
+ ) async {
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ appLanguageProvider.overrideWith(() => TestAppLanguage('en')),
+ languageProvider.overrideWith2(
+ (languageCode) => TestLanguageController(
+ downloadedLanguages: ['de'],
+ pages: {
+ 'Healing': const Page('test', 'test', 'test', '1.0', null),
+ },
+ ),
+ ),
+ ],
+ child: const TestLanguagesButton(),
+ ),
+ );
expect(find.byIcon(Icons.translate), findsOneWidget);
expect(find.text('German (de)'), findsNothing);
@@ -53,14 +65,25 @@ void main() {
expect(find.text('Manage languages'), findsOneWidget);
});
- testWidgets('Test with 5 languages downloaded, German as appLanguage',
- (WidgetTester tester) async {
- await tester.pumpWidget(ProviderScope(overrides: [
- appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
- languageProvider.overrideWith2((languageCode) => TestLanguageController(
- downloadedLanguages: ['de', 'en', 'fr', 'es', 'ar'],
- pages: {'Healing': const Page('test', 'test', 'test', '1.0', null)}))
- ], child: const TestLanguagesButton()));
+ testWidgets('Test with 5 languages downloaded, German as appLanguage', (
+ WidgetTester tester,
+ ) async {
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
+ languageProvider.overrideWith2(
+ (languageCode) => TestLanguageController(
+ downloadedLanguages: ['de', 'en', 'fr', 'es', 'ar'],
+ pages: {
+ 'Healing': const Page('test', 'test', 'test', '1.0', null),
+ },
+ ),
+ ),
+ ],
+ child: const TestLanguagesButton(),
+ ),
+ );
expect(find.byIcon(Icons.translate), findsOneWidget);
expect(find.text('Deutsch (de)'), findsNothing);
@@ -79,7 +102,7 @@ void main() {
'Deutsch (de)',
'Englisch (en)',
'Französisch (fr)',
- 'Spanisch (es)'
+ 'Spanisch (es)',
];
List offsets = [];
@@ -96,16 +119,25 @@ void main() {
final container = ProviderContainer();
final availableLanguages = container.read(availableLanguagesProvider);
- await tester.pumpWidget(UncontrolledProviderScope(
+ await tester.pumpWidget(
+ UncontrolledProviderScope(
container: container,
- child: ProviderScope(overrides: [
- appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
- languageProvider.overrideWith2((languageCode) => TestLanguageController(
- downloadedLanguages: availableLanguages,
- pages: {
- 'Healing': const Page('test', 'test', 'test', '1.0', null)
- }))
- ], child: const TestLanguagesButton())));
+ child: ProviderScope(
+ overrides: [
+ appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
+ languageProvider.overrideWith2(
+ (languageCode) => TestLanguageController(
+ downloadedLanguages: availableLanguages,
+ pages: {
+ 'Healing': const Page('test', 'test', 'test', '1.0', null),
+ },
+ ),
+ ),
+ ],
+ child: const TestLanguagesButton(),
+ ),
+ ),
+ );
expect(find.byIcon(Icons.translate), findsOneWidget);
expect(find.text('Deutsch (de)'), findsNothing);
diff --git a/test/languages_test.dart b/test/languages_test.dart
index 100a6d9..6f1ebd4 100644
--- a/test/languages_test.dart
+++ b/test/languages_test.dart
@@ -23,13 +23,13 @@ class TestLanguageController extends LanguageController {
final List? _downloadedLanguages;
final Map _pages; // map of pages that are available
final bool _initReturns;
- TestLanguageController(
- {List? downloadedLanguages,
- Map pages = const {},
- initReturns = false})
- : _downloadedLanguages = downloadedLanguages,
- _pages = pages,
- _initReturns = initReturns;
+ TestLanguageController({
+ List? downloadedLanguages,
+ Map pages = const {},
+ initReturns = false,
+ }) : _downloadedLanguages = downloadedLanguages,
+ _pages = pages,
+ _initReturns = initReturns;
@override
Language build() {
@@ -41,14 +41,26 @@ class TestLanguageController extends LanguageController {
if (_downloadedLanguages != null) {
downloaded = _downloadedLanguages.contains(languageCode);
}
- return Language(downloaded ? languageCode : '', _pages, const [], const {},
- '', DateTime.utc(2023));
+ return Language(
+ downloaded ? languageCode : '',
+ _pages,
+ const [],
+ const {},
+ '',
+ DateTime.utc(2023),
+ );
}
@override
Future download() async {
- state = Language(languageCode, _pages, const [], const {}, '',
- DateTime.now().toUtc());
+ state = Language(
+ languageCode,
+ _pages,
+ const [],
+ const {},
+ '',
+ DateTime.now().toUtc(),
+ );
return true;
}
@@ -75,7 +87,8 @@ class TestLanguageController extends LanguageController {
/// Only structure/contents.json is existing (with dummy contents)
/// But that's enough for Languages.lazyInit()
Future createBasicFileSystem(
- List downloadedLangs) async {
+ List downloadedLangs,
+) async {
var fileSystem = MemoryFileSystem();
for (final lang in downloadedLangs) {
await fileSystem
@@ -92,10 +105,12 @@ void main() {
test('Test init() when no files are there', () async {
final fileSystem = MemoryFileSystem();
final fakeDownloader = FakeLanguageDownloader(fileSystem: fileSystem);
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(fakeDownloader),
- ]);
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(fakeDownloader),
+ ],
+ );
final frTest = ref.read(languageProvider('fr').notifier);
expect(await frTest.init(), false);
expect(frTest.state.downloaded, false);
@@ -106,10 +121,12 @@ void main() {
test('Test lazyInit() when no files are there', () async {
final fileSystem = MemoryFileSystem();
final fakeDownloader = FakeLanguageDownloader(fileSystem: fileSystem);
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(fakeDownloader),
- ]);
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(fakeDownloader),
+ ],
+ );
final frTest = ref.read(languageProvider('fr').notifier);
expect(await frTest.lazyInit(), false);
expect(frTest.state.downloaded, false);
@@ -118,10 +135,12 @@ void main() {
test('Test that download() starts the download', () async {
final fileSystem = MemoryFileSystem();
final fakeDownloader = FakeLanguageDownloader(fileSystem: fileSystem);
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(fakeDownloader),
- ]);
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(fakeDownloader),
+ ],
+ );
final frTest = ref.read(languageProvider('fr').notifier);
// as we're faking, the language won't be available after download
@@ -133,12 +152,16 @@ void main() {
test('Test failing download', () async {
final fileSystem = MemoryFileSystem();
- final fakeDownloader =
- FakeLanguageDownloader(fileSystem: fileSystem, throwOnDownload: true);
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(fakeDownloader),
- ]);
+ final fakeDownloader = FakeLanguageDownloader(
+ fileSystem: fileSystem,
+ throwOnDownload: true,
+ );
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(fakeDownloader),
+ ],
+ );
final frTest = ref.read(languageProvider('fr').notifier);
expect(await frTest.download(), false);
@@ -150,11 +173,14 @@ void main() {
group('Test error handling of incorrect files / structure', () {
test('Test error handling when no files can be found at all', () async {
final fileSystem = MemoryFileSystem();
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(
- FakeLanguageDownloader(fileSystem: fileSystem)),
- ]);
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ );
final deTest = ref.read(languageProvider('de').notifier);
expect(await deTest.init(), false);
@@ -166,15 +192,19 @@ void main() {
await fileSystem
.directory('assets-de/html-de-main/structure')
.create(recursive: true);
- var contentsJson =
- fileSystem.file('assets-de/html-de-main/structure/contents.json');
+ var contentsJson = fileSystem.file(
+ 'assets-de/html-de-main/structure/contents.json',
+ );
await contentsJson.writeAsString('invalid');
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(
- FakeLanguageDownloader(fileSystem: fileSystem)),
- ]);
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ );
final deTest = ref.read(languageProvider('de').notifier);
expect(await deTest.init(), false);
expect(deTest.state.downloaded, false);
@@ -188,59 +218,81 @@ void main() {
.directory('assets-de/html-de-main/structure')
.create(recursive: true);
var readFileSystem = ChrootFileSystem(
- const LocalFileSystem(), path.canonicalize('test/'));
+ const LocalFileSystem(),
+ path.canonicalize('test/'),
+ );
String jsonPath = 'assets-de/html-de-main/structure/contents.json';
var contentsJson = fileSystem.file(jsonPath);
- await contentsJson
- .writeAsString(await readFileSystem.file(jsonPath).readAsString());
-
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(
- FakeLanguageDownloader(fileSystem: fileSystem)),
- ]);
+ await contentsJson.writeAsString(
+ await readFileSystem.file(jsonPath).readAsString(),
+ );
+
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ );
// init() should work (even if expected HTML files are missing)
final deTest = ref.read(languageProvider('de').notifier);
expect(await deTest.init(), true);
expect(deTest.state.downloaded, true);
- expect(deTest.state.downloadTimestamp.compareTo(DateTime(2023)),
- greaterThan(0));
+ expect(
+ deTest.state.downloadTimestamp.compareTo(DateTime(2023)),
+ greaterThan(0),
+ );
});
});
test('Test lazyInit() when language is available', () async {
// We construct a file system in memory with structure/contents.json
final fileSystem = await createBasicFileSystem(['de']);
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider.overrideWithValue(
- FakeLanguageDownloader(fileSystem: fileSystem)),
- ]);
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ );
expect(await ref.read(languageProvider('de').notifier).lazyInit(), true);
final deStatus = ref.read(languageProvider('de'));
expect(deStatus.downloaded, true);
expect(deStatus.path, equals('assets-de/html-de-main'));
expect(
- deStatus.downloadTimestamp.compareTo(DateTime(2023)), greaterThan(0));
+ deStatus.downloadTimestamp.compareTo(DateTime(2023)),
+ greaterThan(0),
+ );
});
test('Test everything with real content from test/assets-de/', () async {
final fileSystem = ChrootFileSystem(
- const LocalFileSystem(), path.canonicalize('test/'));
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider
- .overrideWithValue(FakeLanguageDownloader(fileSystem: fileSystem)),
- ]);
+ const LocalFileSystem(),
+ path.canonicalize('test/'),
+ );
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ );
final deTest = ref.read(languageProvider('de').notifier);
expect(await deTest.init(), true);
// Loads Gottes_Geschichte_(fünf_Finger).html
- String content = await ref.read(pageContentProvider(
- (name: "God's_Story_(five_fingers)", langCode: 'de')).future);
+ String content = await ref.read(
+ pageContentProvider((
+ name: "God's_Story_(five_fingers)",
+ langCode: 'de',
+ )).future,
+ );
expect(content, startsWith('Gottes Geschichte'));
// The link of this image should have been replaced with image content
@@ -249,19 +301,22 @@ void main() {
// This should still be there as the image file is missing
expect(content, contains('src="files/Hand_5.png"'));
// PDF should be available
- expect(deTest.state.pages['Forgiving_Step_by_Step']?.pdfPath,
- equals('assets-de/pdf-de-main/Schritte_der_Vergebung.pdf'));
+ expect(
+ deTest.state.pages['Forgiving_Step_by_Step']?.pdfPath,
+ equals('assets-de/pdf-de-main/Schritte_der_Vergebung.pdf'),
+ );
// This PDF is missing
expect(deTest.state.pages['MissingTest']?.pdfPath, isNull);
// Test Languages.getPageTitles()
expect(
- deTest.state.getPageTitles().values,
- orderedEquals(const [
- 'Gottes Geschichte (fünf Finger)',
- 'Schritte der Vergebung',
- 'MissingTest'
- ]));
+ deTest.state.getPageTitles().values,
+ orderedEquals(const [
+ 'Gottes Geschichte (fünf Finger)',
+ 'Schritte der Vergebung',
+ 'MissingTest',
+ ]),
+ );
expect(deTest.state.path, equals('assets-de/html-de-main'));
// Test some error handling
@@ -270,18 +325,22 @@ void main() {
ref.read(pageContentProvider((name: 'Invalid', langCode: 'de')));
await Future.delayed(const Duration(milliseconds: 500));
- final missingResult =
- ref.read(pageContentProvider((name: 'MissingTest', langCode: 'de')));
+ final missingResult = ref.read(
+ pageContentProvider((name: 'MissingTest', langCode: 'de')),
+ );
expect(missingResult.hasError, true);
// In Riverpod v3, errors are wrapped in ProviderException
var error = missingResult.error;
if (error is ProviderException) error = error.exception;
expect(error, isA());
- expect((error as LanguageCorruptedException).exception,
- isA());
+ expect(
+ (error as LanguageCorruptedException).exception,
+ isA(),
+ );
- final invalidResult =
- ref.read(pageContentProvider((name: 'Invalid', langCode: 'de')));
+ final invalidResult = ref.read(
+ pageContentProvider((name: 'Invalid', langCode: 'de')),
+ );
expect(invalidResult.hasError, true);
error = invalidResult.error;
if (error is ProviderException) error = error.exception;
@@ -290,13 +349,18 @@ void main() {
});
test('Test languageSizeProvider and diskUsageProvider', () async {
- final fileSystem =
- ChrootFileSystem(const LocalFileSystem(), path.canonicalize('test/'));
- final ref = ProviderContainer(overrides: [
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider
- .overrideWithValue(FakeLanguageDownloader(fileSystem: fileSystem)),
- ]);
+ final fileSystem = ChrootFileSystem(
+ const LocalFileSystem(),
+ path.canonicalize('test/'),
+ );
+ final ref = ProviderContainer(
+ overrides: [
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ );
// Sizes are only calculated for languages that are actually loaded
expect(await ref.read(languageSizeProvider('de').future), 0);
@@ -313,10 +377,14 @@ void main() {
});
test('Test countDownloadedLanguagesProvider', () {
- final ref = ProviderContainer(overrides: [
- languageProvider.overrideWith2((langCode) =>
- TestLanguageController(downloadedLanguages: ['de', 'fr', 'en'])),
- ]);
+ final ref = ProviderContainer(
+ overrides: [
+ languageProvider.overrideWith2(
+ (langCode) =>
+ TestLanguageController(downloadedLanguages: ['de', 'fr', 'en']),
+ ),
+ ],
+ );
expect(ref.read(countDownloadedLanguagesProvider), 3);
});
}
diff --git a/test/main_drawer_test.dart b/test/main_drawer_test.dart
index f9ce8f9..f32bfc8 100644
--- a/test/main_drawer_test.dart
+++ b/test/main_drawer_test.dart
@@ -12,9 +12,12 @@ import 'package:shared_preferences/shared_preferences.dart';
// ignore: implementation_imports, invalid_use_of_internal_member
import 'package:riverpod/src/framework.dart' show $RefArg;
+import 'package:app4training/data/updates.dart';
+
import 'app_language_test.dart';
import 'languages_test.dart';
import 'routes_test.dart';
+import 'updates_test.dart';
// Simulate that five pages are downloaded in most languages.
// French only has "Prayer" available.
@@ -288,6 +291,8 @@ void main() {
testWidgets('Test error message when appLanguage is not downloaded', (
WidgetTester tester,
) async {
+ SharedPreferences.setMockInitialValues({});
+ final prefs = await SharedPreferences.getInstance();
await tester.pumpWidget(
ProviderScope(
overrides: [
@@ -295,6 +300,7 @@ void main() {
languageProvider.overrideWith2(
(languageCode) => TestLanguageController(downloadedLanguages: []),
),
+ sharedPrefsProvider.overrideWithValue(prefs),
],
child: const TestApp(),
),
@@ -311,6 +317,63 @@ void main() {
expect(find.textContaining('lade Deutsch (de) herunter'), findsOneWidget);
});
+ testWidgets('Settings entry shows an indicator dot under requireConfirmation '
+ 'when updates are available', (WidgetTester tester) async {
+ SharedPreferences.setMockInitialValues({
+ 'automaticUpdates': 'requireConfirmation',
+ });
+ final prefs = await SharedPreferences.getInstance();
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
+ languageProvider.overrideWith2(
+ (lang) => CustomTestLanguageController(),
+ ),
+ sharedPrefsProvider.overrideWithValue(prefs),
+ languageStatusProvider.overrideWith2(
+ (lang) => TestLanguageStatus(langWithUpdates: ['de']),
+ ),
+ ],
+ child: const TestApp(),
+ ),
+ );
+ final ScaffoldState state = tester.firstState(find.byType(Scaffold));
+ state.openDrawer();
+ await tester.pumpAndSettle();
+
+ expect(find.text('Einstellungen'), findsOneWidget);
+ expect(find.byIcon(Icons.circle), findsOneWidget);
+ });
+
+ testWidgets('No indicator dot under yesAlways even with updates', (
+ WidgetTester tester,
+ ) async {
+ SharedPreferences.setMockInitialValues({'automaticUpdates': 'yesAlways'});
+ final prefs = await SharedPreferences.getInstance();
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
+ languageProvider.overrideWith2(
+ (lang) => CustomTestLanguageController(),
+ ),
+ sharedPrefsProvider.overrideWithValue(prefs),
+ languageStatusProvider.overrideWith2(
+ (lang) => TestLanguageStatus(langWithUpdates: ['de']),
+ ),
+ ],
+ child: const TestApp(),
+ ),
+ );
+ final ScaffoldState state = tester.firstState(find.byType(Scaffold));
+ state.openDrawer();
+ await tester.pumpAndSettle();
+
+ expect(find.text('Einstellungen'), findsOneWidget);
+ expect(find.byIcon(Icons.circle), findsNothing);
+ });
+
// TODO: test that currently opened page is highlighted in menu
// TODO: test the two dialogs when clicking on an icon / greyed-out icon
}
diff --git a/test/routes_test.dart b/test/routes_test.dart
index 5ae0a73..218218c 100644
--- a/test/routes_test.dart
+++ b/test/routes_test.dart
@@ -6,6 +6,7 @@ import 'package:app4training/l10n/generated/app_localizations.dart';
import 'package:app4training/routes/error_page.dart';
import 'package:app4training/routes/home_page.dart';
import 'package:app4training/routes/onboarding/download_languages_page.dart';
+import 'package:app4training/routes/onboarding/set_update_prefs_page.dart';
import 'package:app4training/routes/onboarding/welcome_page.dart';
import 'package:file/memory.dart';
import 'package:flutter/material.dart';
@@ -57,9 +58,12 @@ void main() {
final prefs = await SharedPreferences.getInstance();
final TestObserver observer = TestObserver();
- await tester.pumpWidget(ProviderScope(
+ await tester.pumpWidget(
+ ProviderScope(
overrides: [sharedPrefsProvider.overrideWithValue(prefs)],
- child: TestApp(observer)));
+ child: TestApp(observer),
+ ),
+ );
// Test that onboarding process get's started on first app usage
expect(find.byType(TestApp), findsOneWidget);
@@ -68,34 +72,42 @@ void main() {
expect(find.byType(WelcomePage), findsOneWidget);
// Test second onboarding step
- unawaited(Navigator.of(tester.element(find.byType(WelcomePage)))
- .pushReplacementNamed('/onboarding/2'));
+ unawaited(
+ Navigator.of(
+ tester.element(find.byType(WelcomePage)),
+ ).pushReplacementNamed('/onboarding/2'),
+ );
await tester.pumpAndSettle();
expect(find.byType(DownloadLanguagesPage), findsOneWidget);
// Go back again
- unawaited(Navigator.of(tester.element(find.byType(DownloadLanguagesPage)))
- .pushReplacementNamed('/onboarding/1'));
+ unawaited(
+ Navigator.of(
+ tester.element(find.byType(DownloadLanguagesPage)),
+ ).pushReplacementNamed('/onboarding/1'),
+ );
await tester.pumpAndSettle();
expect(find.byType(WelcomePage), findsOneWidget);
-/* TODO for version 0.9
// Test third onboarding step
- unawaited(Navigator.of(tester.element(find.byType(WelcomePage)))
- .pushReplacementNamed('/onboarding/3'));
+ unawaited(
+ Navigator.of(
+ tester.element(find.byType(WelcomePage)),
+ ).pushReplacementNamed('/onboarding/3'),
+ );
await tester.pumpAndSettle();
expect(find.byType(SetUpdatePrefsPage), findsOneWidget);
-*/
// Test that routes are handled
expect(
- observer.replacedRoutes,
- orderedEquals([
- '/onboarding/1',
- '/onboarding/2',
- '/onboarding/1',
-// '/onboarding/3'
- ]));
+ observer.replacedRoutes,
+ orderedEquals([
+ '/onboarding/1',
+ '/onboarding/2',
+ '/onboarding/1',
+ '/onboarding/3',
+ ]),
+ );
});
testWidgets('Test normal startup', (WidgetTester tester) async {
@@ -103,32 +115,45 @@ void main() {
final prefs = await SharedPreferences.getInstance();
final TestObserver observer = TestObserver();
- await tester.pumpWidget(ProviderScope(overrides: [
- languageProvider
- .overrideWith2((langCode) => TestLanguageController(initReturns: true)),
- sharedPrefsProvider.overrideWithValue(prefs)
- ], child: TestApp(observer)));
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ languageProvider.overrideWith2(
+ (langCode) => TestLanguageController(initReturns: true),
+ ),
+ sharedPrefsProvider.overrideWithValue(prefs),
+ ],
+ child: TestApp(observer),
+ ),
+ );
// Test initial route /
expect(find.byType(TestApp), findsOneWidget);
expect(find.byType(StartupPage), findsOneWidget);
// Test home page
- unawaited(Navigator.of(tester.element(find.byType(StartupPage)))
- .pushNamed('/home'));
+ unawaited(
+ Navigator.of(tester.element(find.byType(StartupPage))).pushNamed('/home'),
+ );
await tester.pumpAndSettle();
expect(find.byType(HomePage), findsOneWidget);
// Test settings page
- unawaited(Navigator.of(tester.element(find.byType(HomePage)))
- .pushNamed('/settings'));
+ unawaited(
+ Navigator.of(
+ tester.element(find.byType(HomePage)),
+ ).pushNamed('/settings'),
+ );
await tester.pumpAndSettle();
expect(find.byType(SettingsPage), findsOneWidget);
// Test viewing the forgiveness page in English
const String viewRoute = '/view/Forgiving_Step_by_Step/en';
- unawaited(Navigator.of(tester.element(find.byType(SettingsPage)))
- .pushNamed(viewRoute));
+ unawaited(
+ Navigator.of(
+ tester.element(find.byType(SettingsPage)),
+ ).pushNamed(viewRoute),
+ );
await tester.pumpAndSettle();
expect(find.byType(ViewPage), findsOneWidget);
ViewPage viewPage =
@@ -138,7 +163,9 @@ void main() {
// Test that routes are handled
expect(
- observer.routes, orderedEquals(['/', '/home', '/settings', viewRoute]));
+ observer.routes,
+ orderedEquals(['/', '/home', '/settings', viewRoute]),
+ );
});
testWidgets('Test some edge cases', (WidgetTester tester) async {
@@ -146,26 +173,37 @@ void main() {
final prefs = await SharedPreferences.getInstance();
final fileSystem = MemoryFileSystem();
- await tester.pumpWidget(ProviderScope(overrides: [
- sharedPrefsProvider.overrideWithValue(prefs),
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider
- .overrideWithValue(FakeLanguageDownloader(fileSystem: fileSystem)),
- ], child: TestApp(TestObserver())));
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ sharedPrefsProvider.overrideWithValue(prefs),
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ child: TestApp(TestObserver()),
+ ),
+ );
// All of the following errorneous routes should result in showing /home
- unawaited(Navigator.of(tester.element(find.byType(StartupPage)))
- .pushNamed('/view'));
+ unawaited(
+ Navigator.of(tester.element(find.byType(StartupPage))).pushNamed('/view'),
+ );
await tester.pumpAndSettle();
expect(find.byType(HomePage), findsOneWidget);
- unawaited(Navigator.of(tester.element(find.byType(HomePage)))
- .pushNamed('/view//'));
+ unawaited(
+ Navigator.of(tester.element(find.byType(HomePage))).pushNamed('/view//'),
+ );
await tester.pumpAndSettle();
expect(find.byType(HomePage), findsOneWidget);
- unawaited(Navigator.of(tester.element(find.byType(HomePage)))
- .pushNamed('/view/Forgiving_Step_by_Step/'));
+ unawaited(
+ Navigator.of(
+ tester.element(find.byType(HomePage)),
+ ).pushNamed('/view/Forgiving_Step_by_Step/'),
+ );
await tester.pumpAndSettle();
expect(find.byType(HomePage), findsOneWidget);
});
@@ -174,15 +212,24 @@ void main() {
SharedPreferences.setMockInitialValues({'appLanguage': 'system'});
final prefs = await SharedPreferences.getInstance();
final fileSystem = MemoryFileSystem();
- await tester.pumpWidget(ProviderScope(overrides: [
- sharedPrefsProvider.overrideWithValue(prefs),
- fileSystemProvider.overrideWith((ref) => fileSystem),
- languageDownloaderProvider
- .overrideWithValue(FakeLanguageDownloader(fileSystem: fileSystem)),
- ], child: TestApp(TestObserver())));
-
- unawaited(Navigator.of(tester.element(find.byType(StartupPage)))
- .pushNamed('/unknown'));
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ sharedPrefsProvider.overrideWithValue(prefs),
+ fileSystemProvider.overrideWith((ref) => fileSystem),
+ languageDownloaderProvider.overrideWithValue(
+ FakeLanguageDownloader(fileSystem: fileSystem),
+ ),
+ ],
+ child: TestApp(TestObserver()),
+ ),
+ );
+
+ unawaited(
+ Navigator.of(
+ tester.element(find.byType(StartupPage)),
+ ).pushNamed('/unknown'),
+ );
await tester.pumpAndSettle();
expect(find.byType(ErrorPage), findsOneWidget);
expect(find.textContaining('Unknown route /unknown'), findsOneWidget);
diff --git a/test/set_update_prefs_page_test.dart b/test/set_update_prefs_page_test.dart
index ae9cad0..23b8590 100644
--- a/test/set_update_prefs_page_test.dart
+++ b/test/set_update_prefs_page_test.dart
@@ -25,12 +25,13 @@ class TestSetUpdatePrefsPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
- locale: ref.watch(appLanguageProvider).locale,
- localizationsDelegates: AppLocalizations.localizationsDelegates,
- supportedLocales: AppLocalizations.supportedLocales,
- onGenerateRoute: (settings) => generateRoutes(settings),
- navigatorObservers: [navigatorObserver],
- home: const SetUpdatePrefsPage());
+ locale: ref.watch(appLanguageProvider).locale,
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
+ supportedLocales: AppLocalizations.supportedLocales,
+ onGenerateRoute: (settings) => generateRoutes(settings),
+ navigatorObservers: [navigatorObserver],
+ home: const SetUpdatePrefsPage(),
+ );
}
}
@@ -40,13 +41,21 @@ void main() {
final prefs = await SharedPreferences.getInstance();
final testObserver = TestObserver();
- final ref = ProviderContainer(overrides: [
- appLanguageProvider.overrideWith(() => TestAppLanguage('en')),
- backgroundSchedulerProvider.overrideWith(() => TestBackgroundScheduler()),
- sharedPrefsProvider.overrideWithValue(prefs)
- ]);
- await tester.pumpWidget(UncontrolledProviderScope(
- container: ref, child: TestSetUpdatePrefsPage(testObserver)));
+ final ref = ProviderContainer(
+ overrides: [
+ appLanguageProvider.overrideWith(() => TestAppLanguage('en')),
+ backgroundSchedulerProvider.overrideWith(
+ () => TestBackgroundScheduler(),
+ ),
+ sharedPrefsProvider.overrideWithValue(prefs),
+ ],
+ );
+ await tester.pumpWidget(
+ UncontrolledProviderScope(
+ container: ref,
+ child: TestSetUpdatePrefsPage(testObserver),
+ ),
+ );
expect(ref.read(backgroundSchedulerProvider), false);
expect(find.text(AppLocalizationsEn().updatesExplanation), findsOneWidget);
@@ -57,8 +66,9 @@ void main() {
// Press the "Let's go!" button
expect(testObserver.replacedRoutes, isEmpty);
- await tester
- .tap(find.widgetWithText(ElevatedButton, AppLocalizationsEn().letsGo));
+ await tester.tap(
+ find.widgetWithText(ElevatedButton, AppLocalizationsEn().letsGo),
+ );
await tester.pump();
expect(listEquals(testObserver.replacedRoutes, ['/home']), isTrue);
// Even if user didn't change any setting, after clicking "Continue"
@@ -68,16 +78,22 @@ void main() {
expect(ref.read(backgroundSchedulerProvider), true);
});
- testWidgets('Test SetUpdatePrefsPage back button in German',
- (WidgetTester tester) async {
+ testWidgets('Test SetUpdatePrefsPage back button in German', (
+ WidgetTester tester,
+ ) async {
SharedPreferences.setMockInitialValues({});
final prefs = await SharedPreferences.getInstance();
final testObserver = TestObserver();
- await tester.pumpWidget(ProviderScope(overrides: [
- appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
- sharedPrefsProvider.overrideWithValue(prefs)
- ], child: TestSetUpdatePrefsPage(testObserver)));
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ appLanguageProvider.overrideWith(() => TestAppLanguage('de')),
+ sharedPrefsProvider.overrideWithValue(prefs),
+ ],
+ child: TestSetUpdatePrefsPage(testObserver),
+ ),
+ );
// Check that the page is in German
expect(find.text(AppLocalizationsDe().updatesExplanation), findsOneWidget);
@@ -85,8 +101,9 @@ void main() {
// Click the back button
expect(testObserver.replacedRoutes, isEmpty);
- await tester
- .tap(find.widgetWithText(ElevatedButton, AppLocalizationsDe().back));
+ await tester.tap(
+ find.widgetWithText(ElevatedButton, AppLocalizationsDe().back),
+ );
await tester.pump();
expect(listEquals(testObserver.replacedRoutes, ['/onboarding/2']), isTrue);
});
diff --git a/test/startup_page_test.dart b/test/startup_page_test.dart
index e0a8be0..d38b713 100644
--- a/test/startup_page_test.dart
+++ b/test/startup_page_test.dart
@@ -18,9 +18,12 @@ import 'languages_test.dart';
/// Records which languages a full init() was requested for and lets the
/// test decide when each of them finishes loading
class GatedLanguageController extends TestLanguageController {
- GatedLanguageController(this.initCalls, this.gates,
- {super.downloadedLanguages, this.lazyInitGate})
- : super(initReturns: true);
+ GatedLanguageController(
+ this.initCalls,
+ this.gates, {
+ super.downloadedLanguages,
+ this.lazyInitGate,
+ }) : super(initReturns: true);
final List initCalls;
final Map> gates;
@@ -128,27 +131,36 @@ void main() {
expect(ref.read(backgroundSchedulerProvider), false);
});
- /* TODO for version 0.9
- testWidgets('Test continuing to third onboarding step',
- (WidgetTester tester) async {
+ testWidgets('Test continuing to third onboarding step', (
+ WidgetTester tester,
+ ) async {
SharedPreferences.setMockInitialValues({'appLanguage': 'de'});
final prefs = await SharedPreferences.getInstance();
route = null;
- final ref = ProviderContainer(overrides: [
- languageProvider.overrideWith2(
- (languageCode) => TestLanguageController(initReturns: true),
- ),
- sharedPrefsProvider.overrideWith((ref) => prefs)
- ]);
- await tester.pumpWidget(UncontrolledProviderScope(
+ final ref = ProviderContainer(
+ overrides: [
+ languageProvider.overrideWith2(
+ (languageCode) => TestLanguageController(initReturns: true),
+ ),
+ sharedPrefsProvider.overrideWith((ref) => prefs),
+ ],
+ );
+ await tester.pumpWidget(
+ UncontrolledProviderScope(
container: ref,
child: MaterialApp(
- home: const StartupPage(), onGenerateRoute: generateRoutes)));
+ locale: const Locale('de'),
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
+ supportedLocales: AppLocalizations.supportedLocales,
+ home: const StartupPage(),
+ onGenerateRoute: generateRoutes,
+ ),
+ ),
+ );
await tester.pump();
expect(route, equals('/onboarding/3'));
expect(ref.read(backgroundSchedulerProvider), false);
});
-*/
testWidgets('Only the languages of the first screen delay the navigation', (
WidgetTester tester,
@@ -164,7 +176,7 @@ void main() {
final initCalls = [];
final gates = {
for (final languageCode in ['en', 'de', 'fr'])
- languageCode: Completer()
+ languageCode: Completer(),
};
final ref = ProviderContainer(
overrides: [
@@ -229,8 +241,7 @@ void main() {
final initCalls = |