Settings page saved to /config/settings.json but nothing downstream read that file. Schedule changes were silently ignored; max_quality and sleep_interval changes were silently ignored. The "Settings saved successfully" flash was a lie. Fix: - sync.sh reads max_quality + sleep_interval from settings.json on each run (jq -er ... // empty, falling back to env vars on missing/malformed file) - entrypoint.sh reads sync_schedule from settings.json before setting up cron, and writes the crond PID to /var/run/crond.pid so Flask can SIGHUP it - app.py adds apply_schedule(): rewrites /etc/crontabs/root, signals crond via the recorded PID, restarts crond if the PID is stale, drops the crontab when schedule is set to "manual". save_settings_route invokes it only when the schedule actually changed; any failure flashes a warning so the save still succeeds with the user informed - bare `except: pass` in get_settings replaced with explicit exception types + stderr warning so debugging malformed settings is possible - sync.sh: one bad channel no longer aborts the whole loop under set -e - Dockerfile adds jq for the JSON reads in sync.sh / entrypoint.sh - README: two stale github.com URLs fixed to Gitea; new Running Tests section under Building From Source - tests/test_settings.py: 3 pytest cases covering get_settings()'s three branches (missing file, valid file, malformed JSON) Settings hierarchy unchanged: env-var defaults seed the UI; settings.json wins when present and parseable. Timezone (TZ) is not applied live - tzdata is locked in at process start. Same behavior as before; not in scope for this commit.
71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
"""
|
|
Tests for the settings hierarchy in app.get_settings().
|
|
|
|
Hierarchy under test: env-var defaults are returned when settings.json is
|
|
missing or malformed; the file wins when it exists and parses cleanly.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
|
|
import pytest
|
|
|
|
# Make the app module importable without installing it.
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
import app as app_module # noqa: E402
|
|
|
|
|
|
@pytest.fixture
|
|
def tmp_settings_path(monkeypatch, tmp_path):
|
|
"""Point app.SETTINGS_FILE at a temp path for the duration of the test."""
|
|
path = tmp_path / "settings.json"
|
|
monkeypatch.setattr(app_module, "SETTINGS_FILE", str(path))
|
|
return path
|
|
|
|
|
|
def test_get_settings_returns_defaults_when_file_missing(tmp_settings_path, monkeypatch):
|
|
monkeypatch.setenv("SYNC_SCHEDULE", "5 5 * * *")
|
|
monkeypatch.setenv("MAX_QUALITY", "720")
|
|
monkeypatch.setenv("SLEEP_INTERVAL", "7")
|
|
monkeypatch.setenv("TZ", "UTC")
|
|
assert not tmp_settings_path.exists()
|
|
|
|
result = app_module.get_settings()
|
|
|
|
assert result == {
|
|
"sync_schedule": "5 5 * * *",
|
|
"max_quality": "720",
|
|
"sleep_interval": "7",
|
|
"timezone": "UTC",
|
|
}
|
|
|
|
|
|
def test_get_settings_returns_file_contents_when_present(tmp_settings_path):
|
|
payload = {
|
|
"sync_schedule": "0 4 * * *",
|
|
"max_quality": "1440",
|
|
"sleep_interval": "3",
|
|
"timezone": "America/Phoenix",
|
|
}
|
|
tmp_settings_path.write_text(json.dumps(payload))
|
|
|
|
assert app_module.get_settings() == payload
|
|
|
|
|
|
def test_get_settings_falls_back_on_malformed_json(tmp_settings_path, monkeypatch):
|
|
monkeypatch.setenv("SYNC_SCHEDULE", "0 2 * * *")
|
|
monkeypatch.setenv("MAX_QUALITY", "1080")
|
|
monkeypatch.setenv("SLEEP_INTERVAL", "2")
|
|
monkeypatch.setenv("TZ", "America/Phoenix")
|
|
tmp_settings_path.write_text("{ this is not valid json ")
|
|
|
|
result = app_module.get_settings()
|
|
|
|
assert result["sync_schedule"] == "0 2 * * *"
|
|
assert result["max_quality"] == "1080"
|
|
assert result["sleep_interval"] == "2"
|
|
assert result["timezone"] == "America/Phoenix"
|