lock in slash typeahead hyphen + Tab-accept behaviour (T-278)

Both T-278 issues — typing '-' breaking the list, and flaky Tab-to-complete —
were resolved by the D-88 ClideTypeahead migration (T-286): the popover now
narrows live as you type (ValueNotifier-bridged suggestions) and the field keeps
focus (captureFocus:false), so '-' filters normally and Tab reliably accepts the
highlight. Add regression coverage: hyphenated queries in slash_commands_test and
a composer widget test that types through a hyphen then Tab-completes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 17:03:16 +02:00
co-authored by Claude Opus 4.8
parent b10ff321a3
commit d8b9a4137e
4 changed files with 46 additions and 0 deletions
@@ -191,6 +191,28 @@ void main() {
expect(tester.widget<EditableText>(find.byType(EditableText)).controller.text, '/clear ');
});
testWidgets('a hyphenated command keeps filtering through the dash and Tab completes it (T-278)', (tester) async {
await pumpWithCommands(tester, ['add-dir', 'add-context', 'model']);
await tester.enterText(find.byType(EditableText), '/add-');
await tester.pump();
await tester.pump(); // ClideTypeahead inserts the popover post-frame
expect(find.text('/add-dir'), findsOneWidget);
expect(find.text('/add-context'), findsOneWidget);
expect(find.text('/model'), findsNothing);
// Typing further through the hyphen narrows the list (it does not empty it).
await tester.enterText(find.byType(EditableText), '/add-d');
await tester.pump();
await tester.pump();
expect(find.text('/add-dir'), findsOneWidget);
expect(find.text('/add-context'), findsNothing);
// Tab reliably accepts the highlighted suggestion.
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
await tester.pump();
expect(tester.widget<EditableText>(find.byType(EditableText)).controller.text, '/add-dir ');
});
testWidgets('Escape dismisses the typeahead', (tester) async {
await pumpWithCommands(tester, ['model']);
await tester.enterText(find.byType(EditableText), '/mo');
@@ -69,6 +69,12 @@ void main() {
// Cursor sits right after "/mo" inside "/model".
expect(activeSlashQuery('/model', 3), const SlashQuery(start: 0, query: 'mo'));
});
test('hyphens are part of the command token, not a boundary (T-278)', () {
expect(activeSlashQuery('/add-dir', 8), const SlashQuery(start: 0, query: 'add-dir'));
expect(activeSlashQuery('/add-', 5), const SlashQuery(start: 0, query: 'add-'));
expect(activeSlashQuery('go /output-st', 13), const SlashQuery(start: 3, query: 'output-st'));
});
});
group('filterSlashCommands', () {
@@ -86,6 +92,14 @@ void main() {
test('de-duplicates', () {
expect(filterSlashCommands('p', ['pql', 'pql', 'plan']), ['plan', 'pql']);
});
test('keeps filtering through a hyphen in the query (T-278)', () {
const hyphenated = ['add-dir', 'add-context', 'agents', 'output-style'];
// Typing the '-' narrows rather than emptying the list.
expect(filterSlashCommands('add', hyphenated), ['add-context', 'add-dir']);
expect(filterSlashCommands('add-', hyphenated), ['add-context', 'add-dir']);
expect(filterSlashCommands('add-d', hyphenated), ['add-dir']);
});
});
group('completeSlash', () {