Files
odysseus/tests/test_image_research_settings_static.py
T
Léo 8a95ec9299 refactor(settings): extract four panels into settings/ modules
static/js/settings.js was 5,721 lines behind a four-name public surface.
static/js/settings/ already existed with dom, registry, search, sidebar,
navigation and lifecycle, so this continues that package rather than
inventing a layout.

Moved verbatim, 407 lines:

  settings/speech.js        initTtsSettings, initSttSettings
  settings/writingStyle.js  initDocumentWritingStyle
  settings/imageModels.js   initImageSettings
  settings/agent.js         initAgentSettings
  settings/api.js           postSettings, lifted from _postSettings

These five were chosen because their only dependencies outside themselves
were el/byId, _postSettings and sortModelIds. Panels with wider reach stay
put: initEmailAccountsSettings, for instance, pulls a 64-declaration closure
covering most of the file, and splitting that is a design change rather than
a move.

settings.js keeps its public surface exactly: open, close,
refreshAiModelEndpoints and the default export, verified in a browser.

Three test updates the move required:

- tests/helpers/test_settings_shell_coordinator.mjs allowlists the real
  modules the coordinator may import, and rejected the new ones. That guard
  working is the reason to trust the rest of this diff.
- two source-introspection tests read settings.js for behaviour that now
  lives in a panel module. They read the whole settings surface now, so the
  next extraction does not break them again.
2026-09-30 09:04:20 +02:00

37 lines
1.7 KiB
Python

from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_image_settings_only_list_online_served_image_models():
# The image panel moved into static/js/settings/imageModels.js; read the
# whole settings surface so this pins behaviour rather than a filename.
settings = "\n".join(
p.read_text(encoding="utf-8")
for p in [ROOT / "static/js/settings.js", *sorted((ROOT / "static/js/settings").glob("*.js"))]
)
assert "fetch('/api/model-endpoints'" in settings
assert "!endpoint.is_enabled || !endpoint.online" in settings
assert "endpoint.model_type || '').toLowerCase() !== 'image'" in settings
assert "stable-diffusion-3.5-medium', 'stable-diffusion-inpainting" not in settings
assert "(not detected)" not in settings[settings.index("async function initImageSettings"):settings.index("function syncImgDisabled")]
def test_deep_research_fields_are_constrained_to_their_card():
styles = (ROOT / "static/style.css").read_text(encoding="utf-8")
rule = styles[styles.index("/* Deep Research uses long labels"):]
assert ".admin-card:has(#set-researchSearch) .settings-row { min-width: 0; }" in rule
assert "min-width: 0 !important;" in rule
assert "flex: 1 1 0 !important;" in rule
def test_endpoint_probe_is_hidden_during_bulk_selection():
admin = (ROOT / "static/js/admin.js").read_text(encoding="utf-8")
update = admin[admin.index("function _updateEndpointBulkControls()"):admin.index("function _ensureEndpointBulkControls()")]
assert "const probeBtn = el('adm-epProbeAllBtn');" in update
assert "probeBtn.style.display = _endpointSelectMode ? 'none' : 'inline-flex'" in update