import 'dart:io' show File; import 'package:actors/actors.dart'; import 'package:flutter/foundation.dart' show TargetPlatform, debugDefaultTargetPlatformOverride; import 'package:drift/native.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart' show RenderParagraph; 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/database/database.dart'; import 'package:mews/l10n/strings.dart'; import 'package:mews/mews/document.dart'; import 'package:mews/mews/parser.dart'; import 'package:mews/application/pages/mews_urls.dart'; import 'package:mews/presentation/app.dart'; import 'package:mews/presentation/reader/address_bar.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('the hub opens the settings page, which applies a choice in place',
(tester) async {
await pumpApp(tester);
// The hub opens from the left address bar icon.
await tester.tap(find.byIcon(Icons.menu));
await tester.pumpAndSettle();
expect(deps.browser.currentPage.value?.url, MewsUrls.hub);
expect(find.text('Mews'), findsOneWidget);
expect(find.textContaining('No bookmarks yet'), findsOneWidget);
// Its menu reaches settings, which carries the strip of our own pages.
await tapRun(tester, 'Settings');
expect(deps.browser.currentPage.value?.url, MewsUrls.settings);
expect(find.text('Settings'), findsOneWidget);
expect(find.text('Typeface'), findsOneWidget);
expect(find.text('Theme'), findsOneWidget);
expect(find.text('Colors'), findsOneWidget);
// The buried Library section is gone; the strip replaced it.
expect(find.text('Library'), findsNothing);
Future No entries here.Evil
'),
}),
strings: strings,
);
await tester.pumpWidget(MewsApp(deps: stubDeps, strings: strings));
await tester.pumpAndSettle();
await stubDeps.browser.open('https://example.com/evil.html');
await tester.pumpAndSettle();
expect(stubDeps.settings.themeMode.value, 'system');
// Following the link from a fetched page changes nothing and goes nowhere
// (spec 8.1: page content must not act for the reader).
await tapRun(tester, 'Go');
expect(stubDeps.settings.themeMode.value, 'system');
expect(stubDeps.browser.currentPage.value?.url,
'https://example.com/evil.html');
// The same link works from one of our own pages.
await stubDeps.browser.open(MewsUrls.settings);
await stubDeps.browser.open('mews:do/set-theme?value=dark');
expect(stubDeps.settings.themeMode.value, 'dark');
expect(stubDeps.browser.currentPage.value?.url, MewsUrls.settings);
});
testWidgets('a form on one of our pages navigates instead of fetching',
(tester) async {
await pumpApp(tester);
// The fetch client cannot speak the mews scheme, so a form on an internal
// page must be routed before it ever reaches the actor.
await deps.browser.open(MewsUrls.bookmarks);
await deps.browser.submitForm(MewsUrls.bookmarks, 'get', {'q': 'retro'});
await tester.pumpAndSettle();
expect(deps.browser.currentPage.value?.url, 'mews:bookmarks?q=retro');
expect(deps.browser.error.value, isNull);
// A form whose action is an action link applies it in place.
await deps.browser.open(MewsUrls.settings);
await deps.browser.submitForm('mews:do/set-theme', 'get', {'value': 'dark'});
await tester.pumpAndSettle();
expect(deps.settings.themeMode.value, 'dark');
expect(deps.browser.currentPage.value?.url, MewsUrls.settings);
expect(deps.browser.error.value, isNull);
});
testWidgets('bare mews: and an unknown name resolve predictably',
(tester) async {
await pumpApp(tester);
await deps.browser.open('mews:');
await tester.pumpAndSettle();
expect(deps.browser.currentPage.value?.url, MewsUrls.hub);
await deps.browser.open('mews:nonsense');
await tester.pumpAndSettle();
expect(deps.browser.currentPage.value, isNull);
expect(deps.browser.error.value, isAPlain