{
);
}
- /// Puts the focus on the first control of an error page as it appears, so a
- /// D-pad has somewhere to start. A reader typing in the address field keeps
- /// the focus there.
- void _focusErrorPage(Object? error) {
- if (identical(error, _focusedError)) return;
- _focusedError = error;
- if (error == null) return;
- WidgetsBinding.instance.addPostFrameCallback((_) {
- if (!mounted || _focusInPageField()) return;
- _errorFocus.traversalDescendants.firstOrNull?.requestFocus();
- });
- }
-
/// Records the posts of a subscribed page once per page load, so what is new
/// shows up on the subscriptions and posts pages (spec 6.1). The controller
/// no-ops for a page the reader is not subscribed to.
diff --git a/app/test/app_widget_test.dart b/app/test/app_widget_test.dart
index e77c4c3..bbc5272 100644
--- a/app/test/app_widget_test.dart
+++ b/app/test/app_widget_test.dart
@@ -927,184 +927,6 @@ void main() {
debugDefaultTargetPlatformOverride = null;
});
- group('a D-pad drives the reader on a touch host', () {
- late AppDependencies stubDeps;
-
- setUp(() {
- stubDeps = AppDependencies(
- database: MewsDatabase.test(NativeDatabase.memory()),
- fetch: FakeFetch({
- 'https://example.com/a.html': _page(
- 'Page A',
- 'Page A
To page B
'
- 'To page C
'
- ''
- '${'Padding paragraph to make the page scroll.
' * 60}'
- 'Far down to page C
'),
- 'https://example.com/b.html':
- _page('Page B', 'Page B
The second pages content.
'),
- 'https://example.com/c.html':
- _page('Page C', 'Page C
The third pages content.
'),
- }),
- strings: strings,
- );
- });
-
- tearDown(() => stubDeps.db.close());
-
- Future openA(WidgetTester tester) async {
- debugDefaultTargetPlatformOverride = TargetPlatform.android;
- await tester.pumpWidget(MewsApp(deps: stubDeps, strings: strings));
- await tester.pumpAndSettle();
- await stubDeps.browser.open('https://example.com/a.html');
- await tester.pumpAndSettle();
- }
-
- Future press(WidgetTester tester, LogicalKeyboardKey key) async {
- await tester.sendKeyDownEvent(key);
- await tester.sendKeyUpEvent(key);
- await tester.pumpAndSettle();
- }
-
- Future hold(WidgetTester tester, LogicalKeyboardKey key) async {
- await tester.sendKeyDownEvent(key);
- await tester.sendKeyRepeatEvent(key);
- await tester.sendKeyRepeatEvent(key);
- await tester.sendKeyUpEvent(key);
- await tester.pumpAndSettle();
- }
-
- String? current() => stubDeps.browser.currentPage.value?.url;
-
- ScrollPosition pageScroll(WidgetTester tester) => tester
- .state(find
- .descendant(of: find.byType(ListView), matching: find.byType(Scrollable))
- .first)
- .position;
-
- testWidgets('Left and Right walk the links, the center opens one',
- (tester) async {
- await openA(tester);
-
- await press(tester, LogicalKeyboardKey.arrowRight);
- await press(tester, LogicalKeyboardKey.arrowRight);
- await press(tester, LogicalKeyboardKey.arrowLeft);
- await press(tester, LogicalKeyboardKey.select);
- expect(current(), 'https://example.com/b.html');
-
- debugDefaultTargetPlatformOverride = null;
- });
-
- testWidgets('holding Left, Right and the center navigates', (tester) async {
- await openA(tester);
- await stubDeps.browser.open('https://example.com/b.html');
- await tester.pumpAndSettle();
-
- await hold(tester, LogicalKeyboardKey.arrowLeft);
- expect(current(), 'https://example.com/a.html');
- await hold(tester, LogicalKeyboardKey.arrowRight);
- expect(current(), 'https://example.com/b.html');
- await hold(tester, LogicalKeyboardKey.select);
- expect(current(), MewsUrls.hub);
-
- debugDefaultTargetPlatformOverride = null;
- });
-
- testWidgets('Up and Down scroll, and the walk starts from the screen',
- (tester) async {
- await openA(tester);
- final scroll = pageScroll(tester);
-
- await press(tester, LogicalKeyboardKey.arrowDown);
- expect(scroll.pixels, greaterThan(0));
- await press(tester, LogicalKeyboardKey.arrowUp);
- expect(scroll.pixels, 0);
-
- // Scrolled to the end, Right takes the first link on screen rather
- // than the first of the page.
- scroll.jumpTo(scroll.maxScrollExtent);
- await tester.pumpAndSettle();
- await press(tester, LogicalKeyboardKey.arrowRight);
- await press(tester, LogicalKeyboardKey.enter);
- expect(current(), 'https://example.com/c.html');
-
- debugDefaultTargetPlatformOverride = null;
- });
-
- testWidgets('the walk passes through form controls', (tester) async {
- await openA(tester);
- FocusNode? focused() => FocusManager.instance.primaryFocus;
-
- await press(tester, LogicalKeyboardKey.arrowRight);
- await press(tester, LogicalKeyboardKey.arrowRight);
- await press(tester, LogicalKeyboardKey.arrowRight);
- final field = tester.widget(find.descendant(
- of: find.byType(TextFormField), matching: find.byType(EditableText)));
- expect(focused(), field.focusNode);
-
- // Typed text keeps Left for its cursor until the cursor is at the start.
- await tester.enterText(find.byType(TextFormField), 'Al');
- await press(tester, LogicalKeyboardKey.arrowRight);
- expect(focused()?.context?.findAncestorWidgetOfExactType(),
- isNotNull);
- await press(tester, LogicalKeyboardKey.arrowLeft);
- expect(focused(), field.focusNode);
- await press(tester, LogicalKeyboardKey.arrowLeft);
- await press(tester, LogicalKeyboardKey.arrowLeft);
- expect(focused(), field.focusNode);
- await press(tester, LogicalKeyboardKey.arrowLeft);
- expect(field.focusNode.hasFocus, isFalse);
- await press(tester, LogicalKeyboardKey.select);
- expect(current(), 'https://example.com/c.html');
-
- debugDefaultTargetPlatformOverride = null;
- });
-
- testWidgets('the arrows reach the buttons of an error page', (tester) async {
- await openA(tester);
- await stubDeps.browser.open('https://example.com/missing.html');
- await tester.pumpAndSettle();
- expect(find.text('Try again'), findsOneWidget);
-
- // The first button takes the focus, and the arrows move between them.
- BuildContext? focused() => FocusManager.instance.primaryFocus?.context;
- expect(focused()?.findAncestorWidgetOfExactType(), isNotNull);
- await press(tester, LogicalKeyboardKey.arrowDown);
- expect(focused()?.findAncestorWidgetOfExactType(), isNotNull);
-
- debugDefaultTargetPlatformOverride = null;
- });
-
- testWidgets('Menu shows the chrome and Down returns to the page',
- (tester) async {
- await openA(tester);
- final scroll = pageScroll(tester);
- await press(tester, LogicalKeyboardKey.arrowDown);
- expect(find.byType(AddressBar), findsNothing);
-
- await press(tester, LogicalKeyboardKey.contextMenu);
- final address = tester.widget(find.byType(TextField).first);
- expect(address.focusNode!.hasFocus, isTrue);
-
- // Right moves past the text to the bar's buttons.
- await press(tester, LogicalKeyboardKey.arrowRight);
- await press(tester, LogicalKeyboardKey.arrowRight);
- expect(address.focusNode!.hasFocus, isFalse);
- await press(tester, LogicalKeyboardKey.arrowLeft);
- expect(address.focusNode!.hasFocus, isTrue);
-
- final before = scroll.pixels;
- await press(tester, LogicalKeyboardKey.arrowDown);
- expect(address.focusNode!.hasFocus, isFalse);
- await press(tester, LogicalKeyboardKey.arrowDown);
- expect(scroll.pixels, greaterThan(before));
-
- debugDefaultTargetPlatformOverride = null;
- });
- });
-
testWidgets('bookmarks can be searched and removed from their own page',
(tester) async {
await pumpApp(tester);