import 'dart:io' show File; import 'package:actors/actors.dart'; import 'package:drift/native.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mews/application/actors/fetch_actor.dart'; import 'package:mews/application/controllers/browser_controller.dart' show BrokenPage, LoadFailed; import 'package:mews/application/controllers/reader_settings_controller.dart' show ReaderSettingsController; import 'package:mews/database/database.dart'; import 'package:mews/l10n/strings.dart'; import 'package:mews/mews/document.dart'; import 'package:mews/mews/parser.dart'; import 'package:mews/presentation/app.dart'; import 'package:mews/presentation/reader/address_bar.dart'; import 'package:mews/presentation/reader/fob.dart'; import 'package:mews/presentation/reader/reader_screen.dart'; import 'package:mews/presentation/reader/settings_sheet.dart'; import 'package:mews/presentation/reader/swipe_navigator.dart'; const pageSource = '''
Notes on old phones.
'''; /// Serves pages from an in-memory map without network or isolates, so /// navigation tests are deterministic. Cached pages parse back from their /// cached source, like the real actor does for revalidation. class _FakeFetch implements ActorHalf a page & more'); await tester.pumpAndSettle(); expect(find.textContaining('markup error'), findsOneWidget); await tester.tap(find.textContaining('Show page text')); await tester.pumpAndSettle(); expect(find.textContaining('Half a page & more'), findsOneWidget); }); testWidgets('shows the load-failed error page', (tester) async { await pumpApp(tester); deps.browser.error.value = const LoadFailed(); await tester.pumpAndSettle(); expect(find.textContaining('could not be loaded'), findsOneWidget); expect(find.textContaining('Try again'), findsOneWidget); }); testWidgets('settings sheet changes presentation and toggles library', (tester) async { await pumpApp(tester); final page = parseSource(pageSource, 'https://example.com/index.html'); deps.browser.currentPage.value = page; await tester.pumpAndSettle(); showReaderSettingsSheet(tester.element(find.byType(ReaderScreen))); await tester.pumpAndSettle(); // Typeface, size, theme, colors; the lower sections need scrolling. final sheet = find.byType(Scrollable).last; await tester.tap(find.text('Atkinson Hyperlegible')); await tester.pumpAndSettle(); await tester.tap(find.byIcon(Icons.add)); await tester.pumpAndSettle(); await tester.scrollUntilVisible(find.text('Dark'), 200, scrollable: sheet); await tester.tap(find.text('Dark')); await tester.pumpAndSettle(); await tester.scrollUntilVisible(find.text('Warm'), 200, scrollable: sheet); await tester.tap(find.text('Warm')); await tester.pumpAndSettle(); expect(deps.settings.fontScale.value, 1.125); expect(deps.settings.themeMode.value, 'dark'); expect(deps.settings.variant.value, 'warm'); // Bookmark and subscribe the current page; both tiles sit at the bottom // of the sheet, so scroll the sheet down to the end first. await tester.drag(sheet, const Offset(0, -1000)); await tester.pumpAndSettle(); await tester.tap(find.text('Add bookmark')); await tester.pumpAndSettle(); expect(deps.library.isBookmarked('https://example.com/index.html'), isTrue); await tester.tap(find.text('Subscribe to this site')); await tester.pumpAndSettle(); expect(deps.library.isSubscribed('https://example.com/index.html'), isTrue); // Settings survive a reload of the controller. final reloaded = ReaderSettingsController(db); await reloaded.load(); expect(reloaded.themeMode.value, 'dark'); }); testWidgets('the FOB hides on scroll down and returns on scroll up', (tester) async { await pumpApp(tester); // A page long enough to scroll. final tall = pageSource.replaceFirst( '