Files
transcription/tests/ui/test_runtime_settings_store.py
T
Jim Lancaster 96bb80d91f
Quality Gate / gate (push) Successful in 2m29s
V6.1 backups: once more into the breach.
2026-09-02 10:59:28 -05:00

135 lines
5.1 KiB
Python

"""Tests for safe runtime settings .env editing helpers."""
from __future__ import annotations
from pathlib import Path
import pytest
from transcription.config import Settings
from transcription.errors import AppError
from transcription.ui import runtime_settings_store
from transcription.ui.runtime_settings_store import HIDDEN_SETTINGS_CATEGORIES
from transcription.ui.runtime_settings_store import RUNTIME_SETTINGS_CATALOG
from transcription.ui.runtime_settings_store import SETTINGS_UI_EXCLUDED_FIELDS
from transcription.ui.runtime_settings_store import read_runtime_settings_snapshot
from transcription.ui.runtime_settings_store import save_runtime_settings
from transcription.ui.runtime_settings_store import settings_catalog_field_names
def _settings_for_runtime_editing(tmp_path: Path) -> Settings:
env_path = tmp_path / ".env"
env_path.write_text("OPENROUTER_API_KEY=test-key\n", encoding="utf-8")
return Settings(_env_file=env_path, _cli_parse_args=False)
def test_runtime_settings_catalog_classifies_all_non_secret_settings_fields():
available_fields = set(Settings.model_fields)
expected = available_fields - set(SETTINGS_UI_EXCLUDED_FIELDS)
assert settings_catalog_field_names() == expected
assert "openrouter_api_key" not in settings_catalog_field_names()
def test_hidden_settings_categories_list_secret_and_high_risk_env_keys():
hidden_keys = {key for category in HIDDEN_SETTINGS_CATEGORIES for key in category.env_keys}
assert "OPENROUTER_API_KEY" in hidden_keys
assert "DATABASE__PASSWORD" in hidden_keys
assert "DATABASE__DRIVER" in hidden_keys
assert "DATABASE__HOST" in hidden_keys
assert "POSTGRES_DB" in hidden_keys
assert "POSTGRES_USER" in hidden_keys
assert "POSTGRES_PASSWORD" in hidden_keys
assert "CLOUDFLARE_TUNNEL_TOKEN" in hidden_keys
assert "BACKUP_DIR" in hidden_keys
def test_runtime_settings_snapshot_includes_catalog_fields(tmp_path: Path):
settings = _settings_for_runtime_editing(tmp_path)
snapshot = read_runtime_settings_snapshot(settings=settings, env_file_path=tmp_path / ".env")
assert snapshot.env_file_path == tmp_path / ".env"
assert len(snapshot.fields) == len(RUNTIME_SETTINGS_CATALOG)
assert any(field.field_name == "port" for field in snapshot.fields)
assert any(field.field_name == "provider" for field in snapshot.fields)
def test_save_runtime_settings_writes_allowed_updates(tmp_path: Path):
settings = _settings_for_runtime_editing(tmp_path)
env_path = tmp_path / ".env"
env_path.write_text(
"# sample env\nOPENROUTER_API_KEY=test-key\nPORT=8000\nLOG_LEVEL=info\n",
encoding="utf-8",
)
snapshot = save_runtime_settings(
settings=settings,
updates={
"port": "9001",
"log_level": "debug",
"reload": True,
},
env_file_path=env_path,
)
updated = env_path.read_text(encoding="utf-8")
assert "PORT=9001" in updated
assert "LOG_LEVEL=debug" in updated
assert "RELOAD=true" in updated
assert any(field.field_name == "port" and str(field.value) == "9001" for field in snapshot.fields)
def test_save_runtime_settings_rejects_invalid_values(tmp_path: Path):
settings = _settings_for_runtime_editing(tmp_path)
env_path = tmp_path / ".env"
with pytest.raises(AppError):
save_runtime_settings(
settings=settings,
updates={"port": "not-a-number"},
env_file_path=env_path,
)
def test_runtime_settings_uses_override_env_file(tmp_path: Path, monkeypatch):
settings = _settings_for_runtime_editing(tmp_path)
target = tmp_path / ".env.production"
target.write_text("OPENROUTER_API_KEY=test-key\nPORT=8000\n", encoding="utf-8")
monkeypatch.setenv("RUNTIME_SETTINGS_ENV_FILE", str(target))
snapshot = save_runtime_settings(
settings=settings,
updates={"port": "9001"},
)
assert snapshot.env_file_path == target
assert "PORT=9001" in target.read_text(encoding="utf-8")
def test_save_runtime_settings_surfaces_unreadable_target(tmp_path: Path, monkeypatch):
settings = _settings_for_runtime_editing(tmp_path)
env_path = tmp_path / ".env"
def _raise_read_error(_self, encoding="utf-8"):
_ = encoding
raise OSError("denied")
monkeypatch.setattr(Path, "read_text", _raise_read_error)
with pytest.raises(AppError) as exc:
save_runtime_settings(settings=settings, updates={"port": "9001"}, env_file_path=env_path)
assert exc.value.message == "Runtime settings file is unreadable."
def test_save_runtime_settings_surfaces_unwritable_target(tmp_path: Path, monkeypatch):
settings = _settings_for_runtime_editing(tmp_path)
env_path = tmp_path / ".env"
def _raise_write_error(*args, **kwargs):
_ = args, kwargs
raise OSError("denied")
monkeypatch.setattr(runtime_settings_store, "_write_env_lines_atomic", _raise_write_error)
with pytest.raises(AppError) as exc:
save_runtime_settings(settings=settings, updates={"port": "9001"}, env_file_path=env_path)
assert exc.value.message == "Runtime settings file is not writable."