fix(settings): widen busy-input settings search coverage (#5148)

This commit is contained in:
Rod Boev committed 2026-06-28 18:47:42 -04:00
1 parent 4e71be2268
commit ec00e037f3
4 files changed
+68 -6

No files matched your search

+1 -1
View File
@@ -1293,7 +1293,7 @@
</select>
<div style="font-size:11px;color:var(--muted);margin-top:4px" data-i18n="settings_desc_auto_title_refresh">Automatically re-generates the session title based on the latest exchange, keeping it relevant as the conversation evolves. Requires an LLM title generation model to be configured.</div>
</div>
<div class="settings-field">
<div class="settings-field" data-settings-search="message default while running queue interrupt steer">
<label for="settingsBusyInputMode" data-i18n="settings_label_busy_input_mode">Busy input mode</label>
<select id="settingsBusyInputMode" style="width:100%;padding:8px;background:var(--code-bg);color:var(--text);border:1px solid var(--border2);border-radius:6px">
<option value="queue" data-i18n="settings_busy_input_mode_queue">Queue follow-up</option>
+9 -2
View File
@@ -6953,7 +6953,14 @@ async function _buildSettingsIndex() {
if (!labelEl) return;
const i18nKey = labelEl.dataset ? labelEl.dataset.i18n : undefined;
const label = (i18nKey && t(i18nKey)) || labelEl.textContent.trim();
if (label) index.push({ label, sectionKey, i18nKey, el: field });
if (label) {
const searchBlob = [label, field.textContent, field.dataset ? field.dataset.settingsSearch : '']
.filter(Boolean)
.join(' ')
.replace(/\s+/g, ' ')
.trim();
index.push({ label, searchBlob, sectionKey, i18nKey, el: field });
}
});
if (sectionKey === 'providers') {
pane.querySelectorAll('.provider-card').forEach(card => {
@@ -7001,7 +7008,7 @@ async function filterSettings(query) {
help: t('settings_tab_help') || 'Help',
};
const matches = (_settingsIndex || []).filter(entry =>
entry.label.toLowerCase().includes(q)
(entry.searchBlob || entry.label).toLowerCase().includes(q)
);
if (!matches.length) {
resultsEl.innerHTML = `<div class="settings-search-empty">${esc(t('settings_search_no_results') || 'No settings found.')}</div>`;
+11 -3
View File
@@ -42,17 +42,25 @@ class TestSettingsSearch:
assert "function _buildSettingsIndex()" in PANELS_JS, (
"panels.js must contain _buildSettingsIndex() function"
)
assert "settingsPaneConversation" in PANELS_JS[PANELS_JS.find("function _buildSettingsIndex()"):], (
body = PANELS_JS[PANELS_JS.find("function _buildSettingsIndex()"):]
assert "settingsPaneConversation" in body, (
"_buildSettingsIndex must reference settingsPaneConversation pane"
)
assert "searchBlob" in body, (
"_buildSettingsIndex must store a searchBlob for settings fields"
)
def test_panels_js_has_filter_settings_function(self):
"""panels.js must contain filterSettings function."""
assert "function filterSettings(query)" in PANELS_JS, (
"panels.js must contain filterSettings(query) function"
)
assert "toLowerCase().includes(q)" in PANELS_JS, (
"filterSettings must do case-insensitive substring matching"
body = PANELS_JS[PANELS_JS.find("function filterSettings(query)"):]
assert "(entry.searchBlob || entry.label).toLowerCase().includes(q)" in body, (
"filterSettings must do case-insensitive substring matching over the search blob"
)
assert "esc(m.label)" in body, (
"filterSettings must keep rendering the visible label text"
)
def test_panels_js_has_navigate_to_field_function(self):
@@ -0,0 +1,47 @@
"""Regression coverage for busy-input settings search terms."""
from pathlib import Path
INDEX_HTML = (Path(__file__).parent.parent / "static" / "index.html").read_text(encoding="utf-8")
PANELS_JS = (Path(__file__).parent.parent / "static" / "panels.js").read_text(encoding="utf-8")
class TestBusyInputSettingsSearchTerms:
"""Busy-input settings search must cover option, descriptor, and supplemental text."""
def test_busy_input_field_has_supplemental_search_terms(self):
"""The busy-input field must expose the supplemental terms from HTML."""
assert 'data-settings-search="message default while running queue interrupt steer"' in INDEX_HTML, (
"busy-input field must expose supplemental search terms in data-settings-search"
)
assert "Busy input mode" in INDEX_HTML, (
"busy-input field label must still be present in the HTML"
)
def test_settings_index_uses_field_text_for_busy_input(self):
"""The index builder must include option and descriptor text in searchBlob."""
idx = PANELS_JS.find("function _buildSettingsIndex()")
assert idx >= 0, "_buildSettingsIndex not found"
body = PANELS_JS[idx:idx + 3200]
assert "searchBlob" in body, "_buildSettingsIndex must build a searchBlob"
assert "field.textContent" in body, "_buildSettingsIndex must include field text in searchBlob"
assert "field.dataset ? field.dataset.settingsSearch : ''" in body, (
"_buildSettingsIndex must include supplemental search terms in searchBlob"
)
def test_filter_settings_uses_search_blob_and_keeps_label_rendering(self):
"""filterSettings must match searchBlob, render labels, and keep the cap."""
idx = PANELS_JS.find("function filterSettings(query)")
assert idx >= 0, "filterSettings not found"
body = PANELS_JS[idx:]
assert "(entry.searchBlob || entry.label).toLowerCase().includes(q)" in body, (
"filterSettings must search the richer blob instead of label-only text"
)
assert "esc(m.label)" in body, (
"filterSettings must keep rendering the visible label"
)
assert ".slice(0, 12)" in body, (
"filterSettings must keep the existing 12-result cap"
)
assert ".sort(" not in body, (
"filterSettings must not introduce ranking or reordering"
)