test: update frontend tests for server-side display settings
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -328,15 +328,25 @@ def test_settings_open_state_variable_exists() -> None:
|
|||||||
assert "_settingsOpen" in _JS, "_settingsOpen must be declared in app.js"
|
assert "_settingsOpen" in _JS, "_settingsOpen must be declared in app.js"
|
||||||
|
|
||||||
|
|
||||||
def test_display_settings_key_constant_exists() -> None:
|
def test_get_display_settings_function_exists_via_constant_section() -> None:
|
||||||
"""DISPLAY_SETTINGS_KEY constant must be declared."""
|
"""getDisplaySettings function must exist (display settings are now server-side)."""
|
||||||
assert "DISPLAY_SETTINGS_KEY" in _JS, "DISPLAY_SETTINGS_KEY must be in app.js"
|
assert "function getDisplaySettings" in _JS, (
|
||||||
|
"getDisplaySettings must be defined in app.js"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_display_settings_key_value() -> None:
|
def test_get_display_settings_reads_server_settings() -> None:
|
||||||
"""DISPLAY_SETTINGS_KEY must be 'muxplex.display'."""
|
"""getDisplaySettings must read from _serverSettings (not localStorage)."""
|
||||||
assert "'muxplex.display'" in _JS or '"muxplex.display"' in _JS, (
|
match = re.search(
|
||||||
"DISPLAY_SETTINGS_KEY must be 'muxplex.display'"
|
r"function getDisplaySettings\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// |\n/\*)",
|
||||||
|
_JS,
|
||||||
|
re.DOTALL,
|
||||||
|
)
|
||||||
|
assert match, "getDisplaySettings function not found"
|
||||||
|
body = match.group(1)
|
||||||
|
assert "_serverSettings" in body, "getDisplaySettings must read from _serverSettings"
|
||||||
|
assert "localStorage" not in body, (
|
||||||
|
"getDisplaySettings must not use localStorage — display settings are server-side"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -376,17 +386,17 @@ def test_display_defaults_has_notification_permission() -> None:
|
|||||||
# ── Settings functions must exist ─────────────────────────────────────────────
|
# ── Settings functions must exist ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def test_load_display_settings_function_exists() -> None:
|
def test_get_display_settings_function_exists() -> None:
|
||||||
"""loadDisplaySettings function must exist."""
|
"""getDisplaySettings function must exist."""
|
||||||
assert "function loadDisplaySettings" in _JS, (
|
assert "function getDisplaySettings" in _JS, (
|
||||||
"loadDisplaySettings must be defined in app.js"
|
"getDisplaySettings must be defined in app.js"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_save_display_settings_function_exists() -> None:
|
def test_save_display_settings_function_absent() -> None:
|
||||||
"""saveDisplaySettings function must exist."""
|
"""saveDisplaySettings must not exist — display writes go via patchServerSetting."""
|
||||||
assert "function saveDisplaySettings" in _JS, (
|
assert "function saveDisplaySettings" not in _JS, (
|
||||||
"saveDisplaySettings must be defined in app.js"
|
"saveDisplaySettings must not be defined in app.js — use patchServerSetting instead"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -410,76 +420,80 @@ def test_switch_settings_tab_function_exists() -> None:
|
|||||||
# ── loadDisplaySettings implementation ───────────────────────────────────────
|
# ── loadDisplaySettings implementation ───────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def test_load_display_settings_reads_from_localstorage() -> None:
|
def test_get_display_settings_reads_from_server_settings() -> None:
|
||||||
"""loadDisplaySettings must read from localStorage using DISPLAY_SETTINGS_KEY."""
|
"""getDisplaySettings must read from _serverSettings, not localStorage."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"function loadDisplaySettings\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// )",
|
r"function getDisplaySettings\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// |\n/\*)",
|
||||||
_JS,
|
_JS,
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
assert match, "loadDisplaySettings function not found"
|
assert match, "getDisplaySettings function not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "localStorage" in body, "loadDisplaySettings must read from localStorage"
|
assert "_serverSettings" in body, "getDisplaySettings must read from _serverSettings"
|
||||||
assert "DISPLAY_SETTINGS_KEY" in body or "muxplex.display" in body, (
|
assert "localStorage" not in body, (
|
||||||
"loadDisplaySettings must use DISPLAY_SETTINGS_KEY"
|
"getDisplaySettings must not use localStorage — display settings are server-side"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_load_display_settings_uses_object_assign() -> None:
|
def test_get_display_settings_uses_object_assign() -> None:
|
||||||
"""loadDisplaySettings must merge with DISPLAY_DEFAULTS via Object.assign."""
|
"""getDisplaySettings must merge with DISPLAY_DEFAULTS via Object.assign."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"function loadDisplaySettings\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// )",
|
r"function getDisplaySettings\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// |\n/\*)",
|
||||||
_JS,
|
_JS,
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
assert match, "loadDisplaySettings function not found"
|
assert match, "getDisplaySettings function not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "Object.assign" in body, (
|
assert "Object.assign" in body, (
|
||||||
"loadDisplaySettings must use Object.assign to merge with defaults"
|
"getDisplaySettings must use Object.assign to merge with defaults"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_load_display_settings_returns_defaults_on_error() -> None:
|
def test_get_display_settings_uses_display_defaults() -> None:
|
||||||
"""loadDisplaySettings must catch errors and return defaults."""
|
"""getDisplaySettings must use DISPLAY_DEFAULTS as fallback for missing keys."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"function loadDisplaySettings\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// )",
|
r"function getDisplaySettings\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// |\n/\*)",
|
||||||
_JS,
|
_JS,
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
assert match, "loadDisplaySettings function not found"
|
assert match, "getDisplaySettings function not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "catch" in body or "try" in body, (
|
assert "DISPLAY_DEFAULTS" in body, (
|
||||||
"loadDisplaySettings must have error handling (try/catch)"
|
"getDisplaySettings must use DISPLAY_DEFAULTS as fallback"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# ── saveDisplaySettings implementation ───────────────────────────────────────
|
# ── saveDisplaySettings implementation ───────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def test_save_display_settings_writes_to_localstorage() -> None:
|
def test_on_display_setting_change_uses_api_patch() -> None:
|
||||||
"""saveDisplaySettings must write to localStorage."""
|
"""onDisplaySettingChange must write display settings via API PATCH, not localStorage."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"function saveDisplaySettings\s*\(.*?\)\s*\{(.*?)(?=\nfunction |\n// )",
|
r"function onDisplaySettingChange\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// |\n/\*)",
|
||||||
_JS,
|
_JS,
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
assert match, "saveDisplaySettings function not found"
|
assert match, "onDisplaySettingChange function not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "localStorage" in body, "saveDisplaySettings must write to localStorage"
|
assert "api('PATCH'" in body or 'api("PATCH"' in body, (
|
||||||
assert "setItem" in body, "saveDisplaySettings must call localStorage.setItem"
|
"onDisplaySettingChange must write display settings via api('PATCH', '/api/settings', patch)"
|
||||||
|
)
|
||||||
|
assert "localStorage" not in body, (
|
||||||
|
"onDisplaySettingChange must not use localStorage for display settings"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_save_display_settings_catches_errors() -> None:
|
def test_on_display_setting_change_catches_errors() -> None:
|
||||||
"""saveDisplaySettings must catch errors."""
|
"""onDisplaySettingChange must handle API errors gracefully via .catch()."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"function saveDisplaySettings\s*\(.*?\)\s*\{(.*?)(?=\nfunction |\n// )",
|
r"function onDisplaySettingChange\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// |\n/\*)",
|
||||||
_JS,
|
_JS,
|
||||||
re.DOTALL,
|
re.DOTALL,
|
||||||
)
|
)
|
||||||
assert match, "saveDisplaySettings function not found"
|
assert match, "onDisplaySettingChange function not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "catch" in body or "try" in body, (
|
assert ".catch" in body, (
|
||||||
"saveDisplaySettings must have error handling (try/catch)"
|
"onDisplaySettingChange must handle errors via .catch()"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -783,8 +797,8 @@ def test_bind_static_event_listeners_binds_settings_tabs() -> None:
|
|||||||
# ── module.exports for new settings functions ────────────────────────────────
|
# ── module.exports for new settings functions ────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def test_exports_load_display_settings() -> None:
|
def test_exports_get_display_settings() -> None:
|
||||||
"""module.exports must export loadDisplaySettings."""
|
"""module.exports must export getDisplaySettings."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"module\.exports\s*=\s*\{(.*?)\};",
|
r"module\.exports\s*=\s*\{(.*?)\};",
|
||||||
_JS,
|
_JS,
|
||||||
@@ -792,13 +806,13 @@ def test_exports_load_display_settings() -> None:
|
|||||||
)
|
)
|
||||||
assert match, "module.exports block not found"
|
assert match, "module.exports block not found"
|
||||||
exports = match.group(1)
|
exports = match.group(1)
|
||||||
assert "loadDisplaySettings" in exports, (
|
assert "getDisplaySettings" in exports, (
|
||||||
"module.exports must export loadDisplaySettings"
|
"module.exports must export getDisplaySettings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_exports_save_display_settings() -> None:
|
def test_exports_no_save_display_settings() -> None:
|
||||||
"""module.exports must export saveDisplaySettings."""
|
"""module.exports must NOT export saveDisplaySettings (removed in server-settings migration)."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"module\.exports\s*=\s*\{(.*?)\};",
|
r"module\.exports\s*=\s*\{(.*?)\};",
|
||||||
_JS,
|
_JS,
|
||||||
@@ -806,8 +820,8 @@ def test_exports_save_display_settings() -> None:
|
|||||||
)
|
)
|
||||||
assert match, "module.exports block not found"
|
assert match, "module.exports block not found"
|
||||||
exports = match.group(1)
|
exports = match.group(1)
|
||||||
assert "saveDisplaySettings" in exports, (
|
assert "saveDisplaySettings" not in exports, (
|
||||||
"module.exports must export saveDisplaySettings"
|
"module.exports must not export saveDisplaySettings — use patchServerSetting instead"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -955,7 +969,7 @@ def test_on_display_setting_change_reads_grid_columns() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_on_display_setting_change_calls_save_display_settings() -> None:
|
def test_on_display_setting_change_calls_save_display_settings() -> None:
|
||||||
"""onDisplaySettingChange must call saveDisplaySettings."""
|
"""onDisplaySettingChange must save display settings via api('PATCH', '/api/settings', ...)."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"function onDisplaySettingChange\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// )",
|
r"function onDisplaySettingChange\s*\(\s*\)\s*\{(.*?)(?=\nfunction |\n// )",
|
||||||
_JS,
|
_JS,
|
||||||
@@ -963,8 +977,8 @@ def test_on_display_setting_change_calls_save_display_settings() -> None:
|
|||||||
)
|
)
|
||||||
assert match, "onDisplaySettingChange function not found"
|
assert match, "onDisplaySettingChange function not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "saveDisplaySettings" in body, (
|
assert "api('PATCH'" in body or 'api("PATCH"' in body, (
|
||||||
"onDisplaySettingChange must call saveDisplaySettings"
|
"onDisplaySettingChange must save display settings via api('PATCH', '/api/settings', patch)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1000,7 +1014,7 @@ def test_hover_preview_no_hardcoded_1500() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_hover_preview_reads_delay_from_settings() -> None:
|
def test_hover_preview_reads_delay_from_settings() -> None:
|
||||||
"""Hover preview must read delay from loadDisplaySettings().hoverPreviewDelay."""
|
"""Hover preview must read delay from getDisplaySettings().hoverPreviewDelay."""
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"function bindStaticEventListeners\s*\(\s*\)\s*\{(.*?)\n\}",
|
r"function bindStaticEventListeners\s*\(\s*\)\s*\{(.*?)\n\}",
|
||||||
_JS,
|
_JS,
|
||||||
@@ -1008,8 +1022,8 @@ def test_hover_preview_reads_delay_from_settings() -> None:
|
|||||||
)
|
)
|
||||||
assert match, "bindStaticEventListeners function not found"
|
assert match, "bindStaticEventListeners function not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "loadDisplaySettings" in body and "hoverPreviewDelay" in body, (
|
assert "getDisplaySettings" in body and "hoverPreviewDelay" in body, (
|
||||||
"bindStaticEventListeners hover preview must read delay from loadDisplaySettings().hoverPreviewDelay"
|
"bindStaticEventListeners hover preview must read delay from getDisplaySettings().hoverPreviewDelay"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1074,7 +1088,7 @@ def test_bind_static_event_listeners_binds_grid_columns_change() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_dom_content_loaded_calls_apply_display_settings() -> None:
|
def test_dom_content_loaded_calls_apply_display_settings() -> None:
|
||||||
"""DOMContentLoaded handler must call applyDisplaySettings(loadDisplaySettings())."""
|
"""DOMContentLoaded handler must call applyDisplaySettings(getDisplaySettings())."""
|
||||||
# Find the DOMContentLoaded handler block
|
# Find the DOMContentLoaded handler block
|
||||||
match = re.search(
|
match = re.search(
|
||||||
r"DOMContentLoaded.*?\{(.*?)(?=\}\);?\s*\n// |\}\);\s*$)",
|
r"DOMContentLoaded.*?\{(.*?)(?=\}\);?\s*\n// |\}\);\s*$)",
|
||||||
@@ -1084,10 +1098,10 @@ def test_dom_content_loaded_calls_apply_display_settings() -> None:
|
|||||||
assert match, "DOMContentLoaded handler not found"
|
assert match, "DOMContentLoaded handler not found"
|
||||||
body = match.group(1)
|
body = match.group(1)
|
||||||
assert "applyDisplaySettings" in body, (
|
assert "applyDisplaySettings" in body, (
|
||||||
"DOMContentLoaded handler must call applyDisplaySettings(loadDisplaySettings())"
|
"DOMContentLoaded handler must call applyDisplaySettings(getDisplaySettings())"
|
||||||
)
|
)
|
||||||
assert "loadDisplaySettings" in body, (
|
assert "getDisplaySettings" in body, (
|
||||||
"DOMContentLoaded handler must call applyDisplaySettings(loadDisplaySettings())"
|
"DOMContentLoaded handler must call applyDisplaySettings(getDisplaySettings())"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user