Files
kadence/backend/tests/test_settings_service.py
2026-10-19 11:54:15 +03:00

97 lines
3.7 KiB
Python

"""Settings: deep merge, secret masking, and the environment seed."""
from __future__ import annotations
from app.services import pomodoro, settings_service
from app.settings_schema import SECRET_MASK
def test_a_preset_change_resizes_the_running_interval(session, settings):
row = pomodoro.start(session, settings, kind="work")
assert row.planned_seconds == settings.pomodoro.work_minutes * 60
updated = settings_service.apply_patch(
session, {"pomodoro": {"work_minutes": 85, "short_break_minutes": 10}}
)
current = pomodoro.current_session(session)
assert current.id == row.id
assert current.planned_seconds == 85 * 60
# Elapsed time is wall-clock, not stored — resizing never has to touch it.
assert pomodoro.elapsed_seconds(current) >= 0
assert updated.pomodoro.work_minutes == 85
def test_a_patch_unrelated_to_durations_leaves_the_running_interval_alone(session, settings):
row = pomodoro.start(session, settings, kind="work")
settings_service.apply_patch(session, {"pomodoro": {"daily_goal_pomodoros": 12}})
current = pomodoro.current_session(session)
assert current.id == row.id
assert current.planned_seconds == row.planned_seconds
def test_patch_merges_without_clobbering_siblings(session):
settings_service.apply_patch(session, {"pomodoro": {"work_minutes": 50}})
updated = settings_service.apply_patch(
session, {"pomodoro": {"daily_goal_pomodoros": 12}}
)
assert updated.pomodoro.work_minutes == 50
assert updated.pomodoro.daily_goal_pomodoros == 12
assert updated.pomodoro.short_break_minutes == 5 # untouched default
def test_secrets_are_masked_on_the_way_out(session):
settings_service.apply_patch(
session,
{"sources": {"todoist": {"enabled": True, "api_token": "super-secret"}}},
)
masked = settings_service.mask_secrets(
settings_service.load_settings(session).model_dump(mode="json")
)
assert masked["sources"]["todoist"]["api_token"] == SECRET_MASK
def test_sending_the_mask_back_keeps_the_stored_secret(session):
settings_service.apply_patch(
session, {"sources": {"todoist": {"api_token": "super-secret"}}}
)
settings_service.apply_patch(
session,
{"sources": {"todoist": {"api_token": SECRET_MASK, "enabled": True}}},
)
settings = settings_service.load_settings(session)
assert settings.sources.todoist.api_token == "super-secret"
assert settings.sources.todoist.enabled is True
def test_a_real_new_secret_replaces_the_old_one(session):
settings_service.apply_patch(session, {"sources": {"todoist": {"api_token": "old"}}})
settings_service.apply_patch(session, {"sources": {"todoist": {"api_token": "new"}}})
assert settings_service.load_settings(session).sources.todoist.api_token == "new"
def test_environment_seeds_the_sources(monkeypatch):
monkeypatch.setenv("JIRA_BASE_URL", "https://example.atlassian.net/")
monkeypatch.setenv("JIRA_EMAIL", "me@example.com")
monkeypatch.setenv("JIRA_API_TOKEN", "token")
monkeypatch.setenv("TODOIST_API_TOKEN", "todoist-token")
monkeypatch.setenv("TODOIST_PROJECTS", "Inbox, Учёба")
from app.config import env_settings
env_settings.cache_clear()
try:
settings = settings_service.settings_from_env()
finally:
env_settings.cache_clear()
assert settings.sources.jira.enabled
assert settings.sources.jira.base_url == "https://example.atlassian.net"
assert settings.sources.todoist.projects == ["Inbox", "Учёба"]
def test_listeners_fire_on_save(session):
seen = []
settings_service.on_change(lambda new: seen.append(new.pomodoro.work_minutes))
settings_service.apply_patch(session, {"pomodoro": {"work_minutes": 33}})
assert 33 in seen