Files
youtube-sync-docker/tests/test_settings.py
ComputerGuru ef903c86d1 fix: wire settings.json to actually drive runtime behavior
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.
2026-05-31 19:21:43 -07:00

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"