Rebase PR #5162 (rename busy_input_mode -> default_message_mode; flip the default from 'queue' to 'steer') onto current origin/master WITHOUT dropping the shipped #5170 localStorage persistence mirror. Rename the mirror machinery to the new setting name for consistency: _BUSY_INPUT_MODES -> _DEFAULT_MESSAGE_MODES (values unchanged) _normalizeBusyInputMode -> _normalizeDefaultMessageMode (fallback now 'steer') _persistBusyInputMode -> _persistDefaultMessageMode _readPersistedBusyInputMode -> _readPersistedDefaultMessageMode window._busyInputMode -> window._defaultMessageMode (+ renamed exports) localStorage: write the new 'hermes-default-message-mode' key; read it with a fallback to the legacy 'hermes-busy-input-mode' key so an existing user's persisted preference survives the rename. Preserve #5170 behavior at every mirror site under the new names: - boot success -> window._defaultMessageMode=_persistDefaultMessageMode(...) - boot FAILURE -> window._defaultMessageMode=_readPersistedDefaultMessageMode() (NOT a hardcoded 'steer' — a saved 'interrupt'/'queue' must still apply when the server is unreachable; do not regress #5167/#5132) - preferences autosave, settings-panel load, and _applySavedSettingsUi all persist through _persistDefaultMessageMode(...) Tests updated for the rename while keeping the persistence-behavior assertions (test_1062, test_5145, test_5167); test_5167 gains explicit guards that the load-failure path reads the persisted pref and never hardcodes a literal mode, plus autosave/panel-load mirror-write coverage. Co-authored-by: Rod Boev <rod.boev@gmail.com>
130 lines
6.0 KiB
Python
130 lines
6.0 KiB
Python
"""Focused regression coverage for #5145 busy-input defaults."""
|
||
|
||
import re
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).parent.parent
|
||
CONFIG_PY = (ROOT / "api" / "config.py").read_text(encoding="utf-8")
|
||
BOOT_JS = (ROOT / "static" / "boot.js").read_text(encoding="utf-8")
|
||
PANELS_JS = (ROOT / "static" / "panels.js").read_text(encoding="utf-8")
|
||
INDEX_HTML = (ROOT / "static" / "index.html").read_text(encoding="utf-8")
|
||
I18N_JS = (ROOT / "static" / "i18n.js").read_text(encoding="utf-8")
|
||
LOCALE_KEYS = (
|
||
"en",
|
||
"it",
|
||
"ja",
|
||
"ru",
|
||
"es",
|
||
"de",
|
||
"zh",
|
||
"'zh-Hant'",
|
||
"pt",
|
||
"ko",
|
||
"fr",
|
||
"tr",
|
||
"pl",
|
||
"vi",
|
||
)
|
||
|
||
|
||
def _locale_block(locale_key):
|
||
escaped_keys = [re.escape(key) for key in LOCALE_KEYS]
|
||
next_keys = "|".join(key for key in escaped_keys if key != re.escape(locale_key))
|
||
pattern = rf"^ {re.escape(locale_key)}: \{{(?P<body>.*?)(?=^ (?:{next_keys}): \{{|\n\}};)"
|
||
match = re.search(pattern, I18N_JS, re.MULTILINE | re.DOTALL)
|
||
assert match, f"missing {locale_key} locale block"
|
||
return match.group("body")
|
||
|
||
|
||
def _default_message_mode_label(locale_key):
|
||
block = _locale_block(locale_key)
|
||
match = re.search(r"settings_label_default_message_mode: '([^']+)'", block)
|
||
assert match, f"missing default message mode label for {locale_key}"
|
||
return match.group(1)
|
||
|
||
def _default_message_mode_steer_option(locale_key):
|
||
block = _locale_block(locale_key)
|
||
match = re.search(r"settings_default_message_mode_steer: '([^']+)'", block)
|
||
assert match, f"missing default message mode steer option for {locale_key}"
|
||
return match.group(1)
|
||
|
||
def _default_message_mode_description(locale_key):
|
||
block = _locale_block(locale_key)
|
||
match = re.search(r"settings_desc_default_message_mode: ([\"'])((?:\\.|(?!\1).)*)\1", block)
|
||
assert match, f"missing default message mode description for {locale_key}"
|
||
return match.group(2)
|
||
|
||
|
||
def test_backend_default_resolves_to_steer():
|
||
assert '"default_message_mode": "steer"' in CONFIG_PY
|
||
|
||
|
||
def test_boot_defaults_resolve_to_steer():
|
||
# Success path routes through the #5170 persistence mirror; the resolved
|
||
# value still defaults to 'steer' because _normalizeDefaultMessageMode()
|
||
# returns 'steer' for a missing/invalid value.
|
||
assert "window._defaultMessageMode=_persistDefaultMessageMode(s.default_message_mode||s.busy_input_mode)" in BOOT_JS
|
||
assert "return _DEFAULT_MESSAGE_MODES.includes(mode)?mode:'steer';" in BOOT_JS
|
||
# Load-FAILURE path re-reads the persisted mirror (never a hardcoded literal),
|
||
# so a saved preference survives an unreachable server (#5167/#5170). With no
|
||
# persisted value the normalize fallback still yields 'steer'.
|
||
assert "window._defaultMessageMode=_readPersistedDefaultMessageMode()" in BOOT_JS
|
||
assert "window._defaultMessageMode='steer'" not in BOOT_JS
|
||
|
||
|
||
def test_settings_panel_fallbacks_resolve_to_steer():
|
||
assert "String(settings.default_message_mode||settings.busy_input_mode||'steer')" in PANELS_JS
|
||
assert "['queue','interrupt','steer'].includes(val)?val:'steer'" in PANELS_JS
|
||
# _applySavedSettingsUi routes through the #5170 mirror; the ||'steer' tail
|
||
# keeps steer as the resolved default when the helper is unavailable.
|
||
assert "_persistDefaultMessageMode(body.default_message_mode||body.busy_input_mode)" in PANELS_JS
|
||
assert "body.default_message_mode||body.busy_input_mode||'steer'" in PANELS_JS
|
||
assert "const defaultMessageMode=($('settingsDefaultMessageMode')||{}).value||'steer'" in PANELS_JS
|
||
|
||
|
||
def test_busy_input_label_changes_without_key_or_id_drift():
|
||
assert 'id="settingsDefaultMessageMode"' in INDEX_HTML
|
||
assert 'data-i18n="settings_label_default_message_mode">Default message mode' in INDEX_HTML
|
||
assert _default_message_mode_label("en") == "Default message mode"
|
||
assert I18N_JS.count("settings_label_default_message_mode: 'Default message mode'") == 1
|
||
|
||
|
||
def test_busy_input_labels_stay_in_their_locale_blocks():
|
||
assert _default_message_mode_label("it") == "Modalità messaggio predefinita"
|
||
assert _default_message_mode_label("ja") == "既定のメッセージモード"
|
||
assert _default_message_mode_label("ru") == "Режим сообщений по умолчанию"
|
||
assert _default_message_mode_label("es") == "Modo de mensaje predeterminado"
|
||
assert _default_message_mode_label("de") == "Standard-Nachrichtenmodus"
|
||
assert _default_message_mode_label("zh") == "默认消息模式"
|
||
assert _default_message_mode_label("'zh-Hant'") == "預設訊息模式"
|
||
assert _default_message_mode_label("pt") == "Modo de mensagem padrão"
|
||
assert _default_message_mode_label("ko") == "기본 메시지 모드"
|
||
assert _default_message_mode_label("fr") == "Mode de message par défaut"
|
||
assert _default_message_mode_label("tr") == "Varsayılan mesaj modu"
|
||
assert _default_message_mode_label("pl") == "Domyślny tryb wiadomości"
|
||
assert _default_message_mode_label("vi") == "Chế độ tin nhắn mặc định"
|
||
|
||
def test_russian_steer_option_keeps_mid_turn_meaning():
|
||
assert _default_message_mode_steer_option("ru") == "Steer (коррекция в середине хода)"
|
||
|
||
def test_localized_descriptions_keep_draft_restore_meaning():
|
||
expected_restore_phrases = {
|
||
"it": "bozza viene ripristinata",
|
||
"ja": "下書きが復元",
|
||
"ru": "черновик восстанавливается",
|
||
"es": "borrador se restaura",
|
||
"de": "Entwurf wiederhergestellt",
|
||
"zh": "恢复草稿",
|
||
"'zh-Hant'": "恢復草稿",
|
||
"pt": "rascunho é restaurado",
|
||
"ko": "초안이 복원",
|
||
"fr": "brouillon est restauré",
|
||
"tr": "taslak geri yüklenir",
|
||
"pl": "szkic zostaje przywrócony",
|
||
"vi": "bản nháp sẽ được khôi phục",
|
||
}
|
||
for locale_key, restore_phrase in expected_restore_phrases.items():
|
||
assert restore_phrase in _default_message_mode_description(locale_key), (
|
||
f"{locale_key} description must describe restoring the draft when Steer is unavailable"
|
||
)
|