test(dashboard): add autocomplete trigger/filter tests
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { html, useState, useRef, useCallback, useMemo, useEffect } from '../lib/preact.js';
|
||||
import { getStatusMeta } from '../utils/status.js';
|
||||
import { getTriggerInfo as _getTriggerInfo, filteredSkills as _filteredSkills } from '../utils/autocomplete.js';
|
||||
|
||||
export function SimpleInput({ sessionId, status, onRespond, autocompleteConfig = null }) {
|
||||
const [text, setText] = useState('');
|
||||
@@ -13,48 +14,12 @@ export function SimpleInput({ sessionId, status, onRespond, autocompleteConfig =
|
||||
const autocompleteRef = useRef(null);
|
||||
const meta = getStatusMeta(status);
|
||||
|
||||
// Detect if cursor is at a trigger position for autocomplete
|
||||
const getTriggerInfo = useCallback((value, cursorPos) => {
|
||||
// No config means no autocomplete
|
||||
if (!autocompleteConfig) return null;
|
||||
|
||||
const { trigger } = autocompleteConfig;
|
||||
|
||||
// Find the start of the current "word" (after last whitespace before cursor)
|
||||
let wordStart = cursorPos;
|
||||
while (wordStart > 0 && !/\s/.test(value[wordStart - 1])) {
|
||||
wordStart--;
|
||||
}
|
||||
|
||||
// Check if word starts with this agent's trigger character
|
||||
if (value[wordStart] === trigger) {
|
||||
return {
|
||||
trigger,
|
||||
filterText: value.slice(wordStart + 1, cursorPos).toLowerCase(),
|
||||
replaceStart: wordStart,
|
||||
replaceEnd: cursorPos,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
return _getTriggerInfo(value, cursorPos, autocompleteConfig);
|
||||
}, [autocompleteConfig]);
|
||||
|
||||
// Filter skills based on user input after trigger
|
||||
const filteredSkills = useMemo(() => {
|
||||
if (!autocompleteConfig || !triggerInfo) return [];
|
||||
|
||||
const { skills } = autocompleteConfig;
|
||||
const { filterText } = triggerInfo;
|
||||
|
||||
let filtered = skills;
|
||||
if (filterText) {
|
||||
filtered = skills.filter(s =>
|
||||
s.name.toLowerCase().includes(filterText)
|
||||
);
|
||||
}
|
||||
|
||||
// Server pre-sorts, but re-sort after filtering for stability
|
||||
return filtered.sort((a, b) => a.name.localeCompare(b.name));
|
||||
return _filteredSkills(autocompleteConfig, triggerInfo);
|
||||
}, [autocompleteConfig, triggerInfo]);
|
||||
|
||||
// Show/hide autocomplete based on trigger detection
|
||||
@@ -229,7 +194,7 @@ export function SimpleInput({ sessionId, status, onRespond, autocompleteConfig =
|
||||
<div class="px-3 py-2 text-sm text-dim">No matching skills</div>
|
||||
` : filteredSkills.map((skill, i) => html`
|
||||
<div
|
||||
key=${i}
|
||||
key=${skill.name}
|
||||
class="px-3 py-2 cursor-pointer text-sm transition-colors ${
|
||||
i === selectedIndex
|
||||
? 'bg-selection/50 text-bright'
|
||||
|
||||
Reference in New Issue
Block a user