Files
clide/test/kernel/src/commands/palette_test.dart
T
jpmschweitzerandClaude Opus 4.8 6d0ebab721 chore: adopt Dart 3.9 toolchain — honest floor + tall-style reformat (T-353)
Raise the declared minimums in pubspec.yaml to what our deps already
require: Flutter >=3.35.0 / Dart >=3.9.0 (was 3.19.0 / 3.5.0). alchemist
0.12 needs Flutter 3.32; Dart 3.9 first ships in Flutter 3.35, so 3.35 is
the binding floor. Pin the exact build toolchain in .fvmrc (Flutter
3.44.1).

Moving to the Dart 3.9 language level switches `dart format` to the new
"tall" style and enables two new lints. This commit is the resulting
mechanical churn, isolated from any behaviour change:
  - whole-tree `dart format` reformat (tall style)
  - `dart fix` for unnecessary_underscores + use_null_aware_elements

No runtime behaviour change; `make test` green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 12:11:53 +02:00

84 lines
3.0 KiB
Dart

import 'package:clide/clide.dart';
import 'package:clide/extension/extension.dart';
import 'package:clide/kernel/kernel.dart';
import 'package:flutter_test/flutter_test.dart';
CommandContribution _cmd(String id, {String? title}) => CommandContribution(
id: id,
command: id,
title: title,
run: (_) async => IpcResponse.ok(id: '', data: const {}),
);
void main() {
group('PaletteController', () {
late CommandRegistry registry;
late PaletteController palette;
setUp(() {
registry = CommandRegistry();
registry.register(_cmd('git.commit', title: 'Git: Commit'));
registry.register(_cmd('git.push', title: 'Git: Push'));
registry.register(_cmd('theme.pick', title: 'Theme: Pick…'));
palette = PaletteController(registry);
});
test('open/close toggles isOpen and clears filter', () {
palette.open();
palette.setFilter('git');
expect(palette.isOpen, true);
expect(palette.filter, 'git');
palette.close();
expect(palette.isOpen, false);
expect(palette.filter, '');
});
test('filtered empty filter returns all commands', () {
expect(palette.filtered().length, 3);
});
test('filter is case-insensitive against title or command', () {
palette.setFilter('git');
expect(palette.filtered().map((c) => c.command).toSet(), {'git.commit', 'git.push'});
palette.setFilter('PICK');
expect(palette.filtered().map((c) => c.command).toSet(), {'theme.pick'});
});
test('invoke closes the palette + runs the command', () async {
palette.open();
palette.setFilter('git');
await palette.invoke('git.commit');
expect(palette.isOpen, false);
expect(palette.filter, '');
});
test('fuzzy subsequence match — non-contiguous chars (not substring)', () {
// "gc" / "gp" aren't substrings of the titles, but are subsequences.
palette.setFilter('gc');
expect(palette.filtered().map((c) => c.command), contains('git.commit'));
palette.setFilter('gp');
expect(palette.filtered().map((c) => c.command), contains('git.push'));
// Garbage that isn't a subsequence matches nothing.
palette.setFilter('zzz');
expect(palette.filtered(), isEmpty);
});
test('recency floats invoked commands to the top on an empty filter', () async {
expect(palette.filtered().first.command, 'git.commit'); // registry order
await palette.invoke('theme.pick');
expect(palette.filtered().first.command, 'theme.pick');
await palette.invoke('git.push');
expect(palette.filtered().map((c) => c.command).take(2).toList(), ['git.push', 'theme.pick']);
});
test('recency breaks fuzzy-score ties', () async {
// "git" matches both git.* titles with an equal score; invoking push
// floats it above commit among the equal matches.
await palette.invoke('git.push');
palette.setFilter('git');
final order = palette.filtered().map((c) => c.command).toList();
expect(order.indexOf('git.push'), lessThan(order.indexOf('git.commit')));
});
});
}