2026-10-13 11:47:01 +03:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
|
import 'package:muzzle_velocity/note_editor.dart';
|
2026-10-13 12:13:29 +03:00
|
|
|
import 'note_list_harness.dart';
|
2026-10-13 11:47:01 +03:00
|
|
|
|
|
|
|
|
Future<void> _press(WidgetTester tester, LogicalKeyboardKey key) async {
|
|
|
|
|
await tester.sendKeyEvent(key);
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main() {
|
2026-10-13 12:13:29 +03:00
|
|
|
setUp(() => setUpNotes({
|
|
|
|
|
for (final name in ['alpha', 'beta', 'gamma']) '$name.md': '# $name\n',
|
|
|
|
|
}));
|
2026-10-13 11:47:01 +03:00
|
|
|
|
|
|
|
|
bool searchHasFocus(WidgetTester tester) =>
|
|
|
|
|
tester.widget<TextField>(find.byType(TextField)).focusNode!.hasFocus;
|
|
|
|
|
|
|
|
|
|
List<String> highlighted(WidgetTester tester) => [
|
|
|
|
|
for (final tile in tester.widgetList<ListTile>(find.byType(ListTile)))
|
|
|
|
|
if (tile.selected) (tile.title as Text).data!,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
testWidgets('Down enters the list, Up and Left return to the search field',
|
|
|
|
|
(tester) async {
|
|
|
|
|
await pumpList(tester);
|
|
|
|
|
expect(searchHasFocus(tester), isTrue);
|
|
|
|
|
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowDown);
|
|
|
|
|
expect(searchHasFocus(tester), isFalse);
|
|
|
|
|
expect(highlighted(tester), hasLength(1));
|
|
|
|
|
final first = highlighted(tester).single;
|
|
|
|
|
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowDown);
|
|
|
|
|
expect(highlighted(tester).single, isNot(first));
|
|
|
|
|
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowUp);
|
|
|
|
|
expect(highlighted(tester).single, first);
|
|
|
|
|
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowUp);
|
|
|
|
|
expect(searchHasFocus(tester), isTrue);
|
|
|
|
|
expect(highlighted(tester), isEmpty);
|
|
|
|
|
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowDown);
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowLeft);
|
|
|
|
|
expect(searchHasFocus(tester), isTrue);
|
|
|
|
|
expect(highlighted(tester), isEmpty);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWidgets('Right clears the search text, then opens the menu',
|
|
|
|
|
(tester) async {
|
|
|
|
|
await pumpList(tester);
|
|
|
|
|
await tester.enterText(find.byType(TextField), 'alp');
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowRight);
|
|
|
|
|
expect(find.text('alp'), findsNothing);
|
|
|
|
|
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowRight);
|
|
|
|
|
expect(find.text('About'), findsOneWidget);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWidgets('Right in the list opens the menu with D-pad navigation',
|
|
|
|
|
(tester) async {
|
|
|
|
|
await pumpList(tester);
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowDown);
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowRight);
|
|
|
|
|
expect(find.text('About'), findsOneWidget);
|
|
|
|
|
|
|
|
|
|
// The first item has focus, so moving down and selecting picks the second.
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowDown);
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.select);
|
|
|
|
|
expect(find.text('About'), findsNothing);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWidgets('center opens the highlighted note', (tester) async {
|
|
|
|
|
await pumpList(tester);
|
|
|
|
|
await _press(tester, LogicalKeyboardKey.arrowDown);
|
|
|
|
|
// The note reads its file with real I/O, so let it finish between frames.
|
|
|
|
|
await tester.runAsync(() async {
|
|
|
|
|
await tester.sendKeyEvent(LogicalKeyboardKey.select);
|
|
|
|
|
for (var i = 0; i < 10; i++) {
|
|
|
|
|
await tester.pump(const Duration(milliseconds: 50));
|
|
|
|
|
await Future<void>.delayed(const Duration(milliseconds: 20));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
expect(find.byType(NoteEditorScreen), findsOneWidget);
|
|
|
|
|
final editor = tester.widget<TextField>(find.descendant(
|
|
|
|
|
of: find.byType(NoteEditorScreen), matching: find.byType(TextField)));
|
|
|
|
|
expect(editor.controller!.text, matches(r'^# (alpha|beta|gamma)\n$'));
|
|
|
|
|
});
|
|
|
|
|
}
|